feat: 抽离题型枚举 (#272)
* feat: 抽离题型枚举 * fix: 投放的链接加时间戳去掉ifream缓存 * feat: serve端的node engines
This commit is contained in:
parent
4eda73e669
commit
dc7275aeee
@ -97,5 +97,9 @@
|
||||
"moduleNameMapper": {
|
||||
"^src/(.*)$": "<rootDir>/$1"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.6.0"
|
||||
}
|
||||
}
|
||||
|
50
web/src/common/typeEnum.ts
Normal file
50
web/src/common/typeEnum.ts
Normal file
@ -0,0 +1,50 @@
|
||||
// 题型枚举
|
||||
export enum QUESTION_TYPE {
|
||||
TEXT = 'text',
|
||||
TEXTAREA = 'textarea',
|
||||
RADIO = 'radio',
|
||||
CHECKBOX = 'checkbox',
|
||||
BINARY_CHOICE = 'binary-choice',
|
||||
RADIO_STAR = 'radio-star',
|
||||
RADIO_NPS = 'radio-nps',
|
||||
VOTE = 'vote',
|
||||
}
|
||||
|
||||
// 题目类型标签映射对象
|
||||
export const typeTagLabels: Record<QUESTION_TYPE, string> = {
|
||||
[QUESTION_TYPE.TEXT]: '单行输入框',
|
||||
[QUESTION_TYPE.TEXTAREA]: '多行输入框',
|
||||
[QUESTION_TYPE.RADIO]: '单选',
|
||||
[QUESTION_TYPE.CHECKBOX]: '多选',
|
||||
[QUESTION_TYPE.BINARY_CHOICE]: '判断',
|
||||
[QUESTION_TYPE.RADIO_STAR]: '评分',
|
||||
[QUESTION_TYPE.RADIO_NPS]: 'NPS评分',
|
||||
[QUESTION_TYPE.VOTE]: '投票'
|
||||
}
|
||||
|
||||
// 输入类题型
|
||||
export const INPUT = [
|
||||
QUESTION_TYPE.TEXT,
|
||||
QUESTION_TYPE.TEXTAREA
|
||||
]
|
||||
|
||||
// 选择类题型分类
|
||||
export const NORMAL_CHOICES = [
|
||||
QUESTION_TYPE.RADIO,
|
||||
QUESTION_TYPE.CHECKBOX
|
||||
]
|
||||
|
||||
// 选择类题型分类
|
||||
export const CHOICES = [
|
||||
QUESTION_TYPE.RADIO,
|
||||
QUESTION_TYPE.CHECKBOX,
|
||||
QUESTION_TYPE.BINARY_CHOICE,
|
||||
QUESTION_TYPE.VOTE
|
||||
]
|
||||
|
||||
// 评分题题型分类
|
||||
export const RATES = [
|
||||
QUESTION_TYPE.RADIO_STAR,
|
||||
QUESTION_TYPE.RADIO_NPS
|
||||
]
|
||||
|
@ -65,7 +65,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, ref, type ComputedRef } from 'vue'
|
||||
import { ConditionNode, RuleNode } from '@/common/logicEngine/RuleBuild'
|
||||
import { qAbleList } from '@/management/utils/constant.js'
|
||||
import { CHOICES } from '@/common/typeEnum'
|
||||
import { cleanRichText } from '@/common/xss'
|
||||
const renderData = inject<ComputedRef<Array<any>>>('renderData') || ref([])
|
||||
const props = defineProps({
|
||||
@ -94,7 +94,7 @@ const fieldList = computed(() => {
|
||||
const currentIndex = renderData.value.findIndex((item) => item.field === props.ruleNode.target)
|
||||
return renderData.value
|
||||
.slice(0, currentIndex)
|
||||
.filter((question: any) => qAbleList.includes(question.type))
|
||||
.filter((question: any) => CHOICES.includes(question.type))
|
||||
.map((item: any) => {
|
||||
return {
|
||||
label: `${item.showIndex ? item.indexNumber + '.' : ''} ${cleanRichText(item.title)}`,
|
||||
|
@ -48,7 +48,7 @@ import { getQuestionByType } from '@/management/utils/index'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get, isNumber as _isNumber } from 'lodash-es'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||
const store = useStore()
|
||||
|
||||
const activeNames = ref([0, 1])
|
||||
@ -70,8 +70,8 @@ const getNewQuestion = ({ type }) => {
|
||||
const fields = questionDataList.value.map((item) => item.field)
|
||||
const newQuestion = getQuestionByType(type, fields)
|
||||
newQuestion.title = newQuestion.title = `标题${newQuestionIndex.value + 1}`
|
||||
if (type === 'vote') {
|
||||
newQuestion.innerType = 'radio'
|
||||
if (type === QUESTION_TYPE.VOTE) {
|
||||
newQuestion.innerType = QUESTION_TYPE.RADIO
|
||||
}
|
||||
return newQuestion
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ moment.locale('zh-cn')
|
||||
|
||||
import EmptyIndex from '@/management/components/EmptyIndex.vue'
|
||||
import { CODE_MAP } from '@/management/api/base'
|
||||
import { QOP_MAP } from '@/management/utils/constant'
|
||||
import { QOP_MAP } from '@/management/utils/constant.ts'
|
||||
import { deleteSurvey } from '@/management/api/survey'
|
||||
import ModifyDialog from './ModifyDialog.vue'
|
||||
import TagModule from './TagModule.vue'
|
||||
|
@ -48,7 +48,6 @@ import { useStore } from 'vuex'
|
||||
import { pick as _pick } from 'lodash-es'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { QOP_MAP } from '@/management/utils/constant'
|
||||
import MemberSelect from './MemberSelect.vue'
|
||||
import { type IMember, type IWorkspace, UserRole } from '@/management/utils/types/workSpace'
|
||||
|
@ -51,7 +51,7 @@ const mainChannel = computed(() => {
|
||||
let fullUrl = ''
|
||||
|
||||
if (metaData.value) {
|
||||
fullUrl = `${location.origin}/render/${metaData.value.surveyPath}`
|
||||
fullUrl = `${location.origin}/render/${metaData.value.surveyPath}?t=${Date.now()}`
|
||||
}
|
||||
|
||||
return { fullUrl }
|
||||
|
@ -1,11 +1,10 @@
|
||||
// 问卷操作枚举
|
||||
export const QOP_MAP = {
|
||||
ADD: 'add',
|
||||
COPY: 'copy',
|
||||
EDIT: 'edit'
|
||||
export enum QOP_MAP {
|
||||
ADD = 'add',
|
||||
COPY = 'copy',
|
||||
EDIT = 'edit'
|
||||
}
|
||||
|
||||
export const qAbleList = ['radio', 'checkbox', 'binary-choice', 'vote']
|
||||
export const operatorOptions = [
|
||||
{
|
||||
label: '选择了',
|
@ -1,5 +1,6 @@
|
||||
import { defaultQuestionConfig } from '../config/questionConfig'
|
||||
import { cloneDeep as _cloneDeep, map as _map } from 'lodash-es'
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||
const generateQuestionField = () => {
|
||||
const num = Math.floor(Math.random() * 1000)
|
||||
return `data${num}`
|
||||
@ -24,7 +25,7 @@ const generateHash = (hashList) => {
|
||||
|
||||
function getOptions(type) {
|
||||
const options = [].concat({ ..._cloneDeep(defaultQuestionConfig) }.options)
|
||||
if (type === 'binary-choice') {
|
||||
if (type === QUESTION_TYPE.BINARY_CHOICE) {
|
||||
options[0].text = '对'
|
||||
options[1].text = '错'
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
const config = {
|
||||
mob: '手机号',
|
||||
text: '单行输入框',
|
||||
textarea: '多行输入框',
|
||||
radio: '单选',
|
||||
checkbox: '多选',
|
||||
'radio-star': '评分',
|
||||
'radio-nps': 'NPS评分',
|
||||
city: '城市选择',
|
||||
vote: '投票',
|
||||
'binary-choice': '判断',
|
||||
fillin: '填空'
|
||||
}
|
||||
|
||||
export default config
|
@ -54,6 +54,7 @@ import { ref, computed, inject } from 'vue'
|
||||
import OptionConfig from '../AdvancedConfig/OptionConfig.vue'
|
||||
import RateConfig from '../AdvancedConfig/RateConfig.vue'
|
||||
import ExtraIcon from '../ExtraIcon/index.vue'
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum'
|
||||
|
||||
defineProps({
|
||||
optionList: {
|
||||
@ -101,7 +102,7 @@ const onVisibleChange = (val) => {
|
||||
}
|
||||
|
||||
const isNps = computed(() => {
|
||||
return moduleConfig.value.type === 'radio-nps'
|
||||
return moduleConfig.value.type === QUESTION_TYPE.RADIO_NPS
|
||||
})
|
||||
|
||||
const min = computed(() => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { defineComponent, watch, ref, computed } from 'vue'
|
||||
import { filterXSS } from '@/common/xss'
|
||||
import tagList from '@materials/questions/common/config/tagList'
|
||||
import { typeTagLabels } from '@/common/typeEnum.ts'
|
||||
|
||||
import './style.scss'
|
||||
|
||||
@ -58,7 +58,7 @@ export default defineComponent({
|
||||
let ret = ''
|
||||
types.forEach((t) => {
|
||||
if (ret) return
|
||||
const tv = tagList && tagList[t]
|
||||
const tv = typeTagLabels && typeTagLabels[t]
|
||||
if (tv && typeof tv === 'string') {
|
||||
ret = tv.trim()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { includes } from 'lodash-es'
|
||||
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum'
|
||||
import AnswerProcess from './AnswerProcess/index.vue'
|
||||
import BaseChoice from '../BaseChoice'
|
||||
|
||||
@ -56,7 +56,7 @@ export default defineComponent({
|
||||
}
|
||||
const myOptions = computed(() => {
|
||||
const { options } = props
|
||||
if (props.innerType === 'checkbox') {
|
||||
if (props.innerType === QUESTION_TYPE.CHECKBOX) {
|
||||
return options.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
|
@ -11,7 +11,7 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum'
|
||||
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
||||
|
||||
interface Props {
|
||||
@ -25,7 +25,7 @@ interface Emit {
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
const props = defineProps<Props>()
|
||||
const setterTypes = ['checkbox', 'vote']
|
||||
const setterTypes = [QUESTION_TYPE.CHECKBOX, QUESTION_TYPE.VOTE]
|
||||
const modelValue = ref(props.formConfig.value || 0)
|
||||
const minModelValue = computed(() => {
|
||||
const { min } = props.formConfig
|
||||
|
@ -1,4 +1,5 @@
|
||||
// 定义提交的数据结构:{ field1: '', field2: [], field1_hash1: '', }
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||
export default function ({ dataConf }) {
|
||||
const dataList = dataConf.dataList
|
||||
const formValues = {}
|
||||
@ -17,7 +18,7 @@ export default function ({ dataConf }) {
|
||||
// }
|
||||
|
||||
// 题型是多选,或者子题型是多选(innerType是用于投票)
|
||||
if (/checkbox/.test(type) || innerType === 'checkbox') {
|
||||
if (/checkbox/.test(type) || innerType === QUESTION_TYPE.CHECKBOX) {
|
||||
value = value ? [value] : []
|
||||
}
|
||||
formValues[key] = value
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { get as _get, map as _map } from 'lodash-es'
|
||||
|
||||
import { QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||
// 处理选择题的options
|
||||
function handleOptions(item) {
|
||||
const { type } = item
|
||||
@ -13,7 +13,7 @@ function handleOptions(item) {
|
||||
const cleanOption = {}
|
||||
|
||||
// 投票逻辑处理
|
||||
if (type.indexOf('vote') > -1) {
|
||||
if (type.indexOf(QUESTION_TYPE.VOTE) > -1) {
|
||||
cleanOption.voteCount = 0
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
keys as _keys,
|
||||
set as _set
|
||||
} from 'lodash-es'
|
||||
import { INPUT, RATES, QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||
|
||||
const regexpMap = {
|
||||
nd: /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/,
|
||||
@ -28,13 +29,11 @@ const msgMap = {
|
||||
e: '请输入邮箱',
|
||||
licensePlate: '请输入车牌号'
|
||||
}
|
||||
const inputType = ['text', 'textarea']
|
||||
const checkBoxTip = '至少选择#min#项,少选择了#less#项'
|
||||
const checkBoxTipSame = '请选择#min#项,少选择了#less#项'
|
||||
const textRangeMinTip = '至少输入#min#字'
|
||||
const numberRangeMinTip = '数字最小为#min#'
|
||||
const numberRangeMaxTip = '数字最大为#max#'
|
||||
const radioType = ['radio-star', 'radio-nps']
|
||||
|
||||
// 多选题的选项数目限制
|
||||
export function optionValidator(value, minNum, maxNum) {
|
||||
@ -88,7 +87,7 @@ export function generateValidArr(
|
||||
numberRangeMax
|
||||
) {
|
||||
const validArr = []
|
||||
const isInput = inputType.indexOf(type) !== -1
|
||||
const isInput = INPUT.indexOf(type) !== -1
|
||||
if (isRequired || valid === '*') {
|
||||
// 输入框的必填校验做trim
|
||||
if (!isInput) {
|
||||
@ -199,14 +198,14 @@ const generateOthersKeyMap = (question) => {
|
||||
const { type, field, options, rangeConfig } = question
|
||||
let othersKeyMap = undefined
|
||||
|
||||
if (radioType.includes(type)) {
|
||||
if (RATES.includes(type)) {
|
||||
othersKeyMap = {}
|
||||
for (const key in rangeConfig) {
|
||||
if (rangeConfig[key].isShowInput) {
|
||||
othersKeyMap[`${field}_${key}`] = key
|
||||
}
|
||||
}
|
||||
} else if (type.includes('radio') || type.includes('checkbox')) {
|
||||
} else if (type.includes(QUESTION_TYPE.RADIO) || type.includes(QUESTION_TYPE.CHECKBOX)) {
|
||||
othersKeyMap = {}
|
||||
options
|
||||
.filter((op) => op.others)
|
||||
@ -258,7 +257,7 @@ export default function (questionConfig) {
|
||||
|
||||
// 对于选择题支持填写更多信息的,需要做是否必填的校验
|
||||
if (_keys(othersKeyMap).length) {
|
||||
if (radioType.includes(type)) {
|
||||
if (RATES.includes(type)) {
|
||||
if (rangeConfig) {
|
||||
for (const key in rangeConfig) {
|
||||
if (rangeConfig[key].isShowInput && rangeConfig[key].required) {
|
||||
|
@ -17,7 +17,8 @@ import { useShowInput } from '@/render/hooks/useShowInput'
|
||||
import store from '@/render/store'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { ruleEngine } from '@/render/hooks/useRuleEngine.js'
|
||||
import { QUESTION_TYPE } from '@/render/constant/index'
|
||||
|
||||
import { NORMAL_CHOICES, RATES, QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||
|
||||
const props = defineProps({
|
||||
indexNumber: {
|
||||
@ -48,7 +49,7 @@ const questionConfig = computed(() => {
|
||||
moduleConfig.voteTotal = unref(voteTotal)
|
||||
}
|
||||
if (
|
||||
QUESTION_TYPE.CHOICES.includes(type) &&
|
||||
NORMAL_CHOICES.includes(type) &&
|
||||
options.filter((optionItem) => optionItem.others).length > 0
|
||||
) {
|
||||
let { options, othersValue } = useShowOthers(field)
|
||||
@ -57,7 +58,7 @@ const questionConfig = computed(() => {
|
||||
moduleConfig.othersValue = unref(othersValue)
|
||||
}
|
||||
if (
|
||||
QUESTION_TYPE.RATES.includes(type) &&
|
||||
RATES.includes(type) &&
|
||||
Object.keys(rest.rangeConfig).filter((index) => rest.rangeConfig[index].isShowInput).length > 0
|
||||
) {
|
||||
let { rangeConfig, othersValue } = useShowInput(field)
|
||||
|
@ -1,14 +0,0 @@
|
||||
export const QUESTION_TYPE = {
|
||||
VOTE: 'vote',
|
||||
CHECKBOX: 'checkbox',
|
||||
CHOICES: [
|
||||
// 选择类题型分类
|
||||
'radio',
|
||||
'checkbox'
|
||||
],
|
||||
RATES: [
|
||||
// 评分题题型分类
|
||||
'radio-star',
|
||||
'radio-nps'
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user