diff --git a/server/src/modules/survey/services/dataStatistic.service.ts b/server/src/modules/survey/services/dataStatistic.service.ts index 16926904..cd958a7f 100644 --- a/server/src/modules/survey/services/dataStatistic.service.ts +++ b/server/src/modules/survey/services/dataStatistic.service.ts @@ -10,6 +10,8 @@ import { ResponseSchema } from 'src/models/responseSchema.entity'; import { getListHeadByDataList } from '../utils'; @Injectable() export class DataStatisticService { + private radioType = ['radio-star', 'radio-nps']; + constructor( @InjectRepository(SurveyResponse) private readonly surveyResponseRepository: MongoRepository, @@ -66,7 +68,7 @@ export class DataStatisticService { } // 处理选项的更多输入框 if ( - itemConfig.type === 'radio-star' && + this.radioType.includes(itemConfig.type) && !data[`${itemConfigKey}_custom`] ) { data[`${itemConfigKey}_custom`] = diff --git a/web/public/imgs/question-type-snapshot/radio-nps.webp b/web/public/imgs/question-type-snapshot/radio-nps.webp new file mode 100644 index 00000000..ab034902 Binary files /dev/null and b/web/public/imgs/question-type-snapshot/radio-nps.webp differ diff --git a/web/src/management/config/questionConfig.js b/web/src/management/config/questionConfig.js index b949b653..9de31599 100644 --- a/web/src/management/config/questionConfig.js +++ b/web/src/management/config/questionConfig.js @@ -29,6 +29,10 @@ export const defaultQuestionConfig = { starStyle: 'star', starMin: 1, starMax: 5, + min: 0, + max: 10, + minMsg: '极不满意', + maxMsg: '十分满意', // 分值对应的开关和输入框配置,因为不是固定从0开始,用对象比较合适 rangeConfig: {}, // 选项 diff --git a/web/src/management/config/questionMenuConfig.js b/web/src/management/config/questionMenuConfig.js index f70c670b..3d279a9f 100644 --- a/web/src/management/config/questionMenuConfig.js +++ b/web/src/management/config/questionMenuConfig.js @@ -41,6 +41,13 @@ const menuItems = { icon: 'tixing-pingfen', title: '评分', }, + 'radio-nps': { + type: 'radio-nps', + path: 'NpsModule', + snapshot: '/imgs/question-type-snapshot/radio-nps.webp', + icon: 'NPSpingfen', + title: 'nps评分', + }, vote: { type: 'vote', path: 'VoteModule', @@ -57,7 +64,14 @@ const menuGroup = [ }, { title: '选择类题型', - questionList: ['radio', 'checkbox', 'binary-choice', 'radio-star', 'vote'], + questionList: [ + 'radio', + 'checkbox', + 'binary-choice', + 'radio-star', + 'radio-nps', + 'vote', + ], }, ]; diff --git a/web/src/management/pages/edit/components/setterField.vue b/web/src/management/pages/edit/components/setterField.vue index 1f622510..a587192d 100644 --- a/web/src/management/pages/edit/components/setterField.vue +++ b/web/src/management/pages/edit/components/setterField.vue @@ -17,6 +17,7 @@ @form-change="onFormChange($event, item)" :inline="true" labelPosition="left" + :class="item.contentClass" > + diff --git a/web/src/materials/questions/widgets/NpsModule/meta.js b/web/src/materials/questions/widgets/NpsModule/meta.js new file mode 100644 index 00000000..df34b950 --- /dev/null +++ b/web/src/materials/questions/widgets/NpsModule/meta.js @@ -0,0 +1,95 @@ +import basicConfig from '../../common/config/basicConfig'; +import { Message } from 'element-ui'; + +const meta = { + title: '评分', + questExtra: ['listenMerge'], + type: 'radio-nps', + componentName: 'NpsModule', + formConfig: [ + basicConfig, + { + name: 'min', + label: 'NPS量表最小值', + labelStyle: { + 'font-weight': 'bold', + }, + contentClass: 'nps-select-config', + key: 'min', + type: 'Select', + options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((v) => ({ + value: v, + label: v, + })), + valueSetter: (val, moduleConfig) => { + if (moduleConfig['max'] && val >= moduleConfig['max']) { + Message({ + type: 'info', + message: '最小值不可大于最大值', + }); + return true; + } + }, + }, + { + name: 'max', + label: 'NPS量表最大值', + labelStyle: { + 'font-weight': 'bold', + }, + key: 'max', + type: 'Select', + contentClass: 'nps-select-config', + options: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((v) => ({ + value: v, + label: v, + })), + valueSetter: (val, moduleConfig) => { + if (moduleConfig['min'] && val <= moduleConfig['min']) { + Message({ + type: 'info', + message: '最大值不可小于最小值', + }); + return true; + } + }, + }, + { + name: 'npsMsg', + label: 'NPS两级文案', + labelStyle: { + 'font-weight': 'bold', + }, + contentClass: 'nps-customed-config', + type: 'Customed', + content: [ + { + label: '最小值文案', + type: 'Input', + key: 'minMsg', + direction: 'horizon', + }, + { + label: '最大值文案', + type: 'Input', + key: 'maxMsg', + direction: 'horizon', + }, + ], + }, + ], + editConfigure: { + optionEdit: { + show: false, + }, + optionEditBar: { + show: true, + configure: { + showOthers: false, + showAdvancedRateConfig: true, + }, + }, + }, +}; + +export default meta; diff --git a/web/src/materials/setters/widgets/Select.vue b/web/src/materials/setters/widgets/Select.vue index eda029a4..0520c6bd 100644 --- a/web/src/materials/setters/widgets/Select.vue +++ b/web/src/materials/setters/widgets/Select.vue @@ -9,6 +9,7 @@ @change="changeData" popper-class="option-list-width" :disabled="formConfig.disabled" + :class="formConfig.contentClass" > { const { type, field, options, rangeConfig } = question; let othersKeyMap = undefined; - if (['radio-star'].includes(type)) { + if (radioType.includes(type)) { othersKeyMap = {}; for (const key in rangeConfig) { if (rangeConfig[key].isShowInput) { @@ -257,7 +258,7 @@ export default function (questionConfig) { // 对于选择题支持填写更多信息的,需要做是否必填的校验 if (_keys(othersKeyMap).length) { - if (['radio-star'].includes(type)) { + if (radioType.includes(type)) { if (rangeConfig) { for (const key in rangeConfig) { if (rangeConfig[key].isShowInput && rangeConfig[key].required) { @@ -275,7 +276,6 @@ export default function (questionConfig) { }); } } - return Object.assign(validMap, pre); }, {}); return { rules };