feat: 高级设置组件迁移
This commit is contained in:
parent
9e07e8330a
commit
013f9ac811
@ -14,7 +14,7 @@
|
|||||||
:ref="`questionWrapper-${element.field}`"
|
:ref="`questionWrapper-${element.field}`"
|
||||||
:moduleConfig="element"
|
:moduleConfig="element"
|
||||||
:qIndex="element.qIndex"
|
:qIndex="element.qIndex"
|
||||||
:isFirst="index==0"
|
:isFirst="index == 0"
|
||||||
:indexNumber="element.indexNumber"
|
:indexNumber="element.indexNumber"
|
||||||
:isSelected="currentEditOne === element.qIndex"
|
:isSelected="currentEditOne === element.qIndex"
|
||||||
:isLast="index + 1 === questionDataList.length"
|
:isLast="index + 1 === questionDataList.length"
|
||||||
@ -28,7 +28,11 @@
|
|||||||
:isSelected="currentEditOne === element.qIndex"
|
:isSelected="currentEditOne === element.qIndex"
|
||||||
:readonly="true"
|
:readonly="true"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
></QuestionContainerB>
|
>
|
||||||
|
<template #advancedEdit>
|
||||||
|
<slot name="advancedEdit" :moduleConfig="element"></slot>
|
||||||
|
</template>
|
||||||
|
</QuestionContainerB>
|
||||||
</QuestionWrapper>
|
</QuestionWrapper>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
@ -60,12 +64,12 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['change', 'select', 'changeSeq','change'],
|
emits: ['change', 'select', 'changeSeq', 'change'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const editStore = useEditStore()
|
const editStore = useEditStore()
|
||||||
const renderData = computed({
|
const renderData = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.questionDataList; //filterQuestionPreviewData(props.questionDataList)
|
return props.questionDataList //filterQuestionPreviewData(props.questionDataList)
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
editStore.moveQuestionDataList(value)
|
editStore.moveQuestionDataList(value)
|
||||||
|
@ -20,7 +20,11 @@
|
|||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
@changeSeq="onQuestionOperation"
|
@changeSeq="onQuestionOperation"
|
||||||
ref="materialGroup"
|
ref="materialGroup"
|
||||||
/>
|
>
|
||||||
|
<template #advancedEdit="{ moduleConfig }">
|
||||||
|
<AdvancedComponent :moduleConfig="moduleConfig" @handleChange="handleChange" />
|
||||||
|
</template>
|
||||||
|
</MaterialGroup>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
:submit-conf="submitConf"
|
:submit-conf="submitConf"
|
||||||
:readonly="false"
|
:readonly="false"
|
||||||
@ -36,10 +40,14 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch, toRefs } from 'vue'
|
import { ref, watch, toRefs } from 'vue'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
import communalLoader from '@materials/communals/communalLoader.js'
|
import communalLoader from '@materials/communals/communalLoader.js'
|
||||||
|
|
||||||
import PageWrapper from '@/management/pages/edit/components/Pagination/PaginationWrapper.vue'
|
import PageWrapper from '@/management/pages/edit/components/Pagination/PaginationWrapper.vue'
|
||||||
import MaterialGroup from '@/management/pages/edit/components/MaterialGroup.vue'
|
import MaterialGroup from '@/management/pages/edit/components/MaterialGroup.vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import AdvancedComponent from './components/AdvancedConfig/index.vue'
|
||||||
|
|
||||||
import { useEditStore } from '@/management/stores/edit'
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
|
|
||||||
const MainTitle = communalLoader.loadComponent('MainTitle')
|
const MainTitle = communalLoader.loadComponent('MainTitle')
|
||||||
@ -95,6 +103,7 @@ const onQuestionOperation = (data) => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
skinConf,
|
skinConf,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
|
@ -1,77 +1,74 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<div>
|
||||||
title="选项高级设置"
|
<span class="primary-color" @click="openOptionConfig"> 高级设置 > </span>
|
||||||
class="option-config-wrapper"
|
|
||||||
v-model="configVisible"
|
<el-dialog
|
||||||
:append-to-body="true"
|
title="选项高级设置"
|
||||||
:width="dialogWidth"
|
class="option-config-wrapper"
|
||||||
size="large"
|
v-model="configVisible"
|
||||||
>
|
:append-to-body="true"
|
||||||
<div class="option-handwrite">
|
width="60%"
|
||||||
<div class="option-header">
|
size="large"
|
||||||
<div class="header-item flex-1" v-if="showText">选项内容</div>
|
>
|
||||||
<div class="header-item w285" v-if="showOthers">选项后增添输入框</div>
|
<div class="option-handwrite">
|
||||||
</div>
|
<div class="option-header">
|
||||||
<div>
|
<div class="header-item flex-1">选项内容</div>
|
||||||
<draggable :list="curOptions" handle=".drag-handle" itemKey="hash">
|
<div class="header-item w285">选项后增添输入框</div>
|
||||||
<template #item="{ element, index }">
|
</div>
|
||||||
<div class="option-item">
|
<div>
|
||||||
<span class="drag-handle qicon qicon-tuodong"></span>
|
<draggable :list="curOptions" handle=".drag-handle" itemKey="hash">
|
||||||
<div class="flex-1 oitem" v-if="showText">
|
<template #item="{ element, index }">
|
||||||
<div
|
<div class="option-item">
|
||||||
contenteditable="true"
|
<span class="drag-handle qicon qicon-tuodong"></span>
|
||||||
class="render-html"
|
<div class="flex-1 oitem">
|
||||||
v-html="textOptions[index]"
|
<div
|
||||||
@blur="onBlur($event, index)"
|
contenteditable="true"
|
||||||
></div>
|
class="render-html"
|
||||||
</div>
|
v-html="textOptions[index]"
|
||||||
<div class="oitem moreInfo lh36" v-if="showOthers">
|
@blur="onBlur($event, index)"
|
||||||
<el-switch
|
></div>
|
||||||
:modelValue="element.others"
|
</div>
|
||||||
@change="(val) => changeOptionOthers(val, element)"
|
<div class="oitem moreInfo lh36">
|
||||||
></el-switch>
|
<el-switch
|
||||||
<div class="more-info-content" v-if="element.others">
|
:modelValue="element.others"
|
||||||
<el-input v-model="element.placeholderDesc" placeholder="提示文案"></el-input>
|
@change="(val) => changeOptionOthers(val, element)"
|
||||||
<el-checkbox v-model="element.mustOthers">必填</el-checkbox>
|
></el-switch>
|
||||||
|
<div class="more-info-content" v-if="element.others">
|
||||||
|
<el-input v-model="element.placeholderDesc" placeholder="提示文案"></el-input>
|
||||||
|
<el-checkbox v-model="element.mustOthers">必填</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="operate-area">
|
||||||
|
<i-ep-circlePlus class="area-btn-icon" @click="addOption('选项', false, index)" />
|
||||||
|
<i-ep-remove
|
||||||
|
v-show="curOptions.length"
|
||||||
|
class="area-btn-icon"
|
||||||
|
@click="deleteOption(index)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
<div class="operate-area" v-if="showOperateOption">
|
</draggable>
|
||||||
<i-ep-circlePlus
|
|
||||||
v-if="showOperateOption"
|
|
||||||
class="area-btn-icon"
|
|
||||||
@click="addOption('选项', false, index)"
|
|
||||||
/>
|
|
||||||
<i-ep-remove
|
|
||||||
v-show="curOptions.length"
|
|
||||||
class="area-btn-icon"
|
|
||||||
@click="deleteOption(index)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
|
||||||
<div class="add-btn-row">
|
|
||||||
<div class="add-option" v-if="showOperateOption" @click="addOption()">
|
|
||||||
<span class="add-option-item"> <i-ep-circlePlus class="icon" /> 添加新选项 </span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="add-btn-row">
|
||||||
|
<div class="add-option" @click="addOption()">
|
||||||
|
<span class="add-option-item"> <i-ep-circlePlus class="icon" /> 添加新选项 </span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="showOperateOption && showOthers" class="add-option" @click="addOtherOption">
|
<div class="add-option" @click="addOtherOption">
|
||||||
<span>
|
<span class="add-option-item"> <i-ep-circlePlus class="icon" /> 其他____ </span>
|
||||||
<extra-icon type="add-square"></extra-icon>
|
</div>
|
||||||
其他____
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<template #footer>
|
||||||
<template #footer>
|
<span class="dialog-footer">
|
||||||
<span class="dialog-footer">
|
<el-button @click="configVisible = false">取消</el-button>
|
||||||
<el-button @click="configVisible = false">取消</el-button>
|
<el-button type="primary" @click="optionConfigChange">确认</el-button>
|
||||||
<el-button type="primary" @click="optionConfigChange">确认</el-button>
|
</span>
|
||||||
</span>
|
</template>
|
||||||
</template>
|
</el-dialog>
|
||||||
</el-dialog>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -81,54 +78,26 @@ import { forEach as _forEach, cloneDeep as _cloneDeep } from 'lodash-es'
|
|||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
import { cleanRichText } from '@/common/xss'
|
import { cleanRichText } from '@/common/xss'
|
||||||
import ExtraIcon from '../ExtraIcon/index.vue'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'OptionConfig',
|
name: 'OptionConfig',
|
||||||
inject: ['moduleConfig'],
|
props: {
|
||||||
data() {
|
fieldId: {
|
||||||
return {
|
type: String,
|
||||||
curOptions: _cloneDeep(this.options),
|
default: ''
|
||||||
popoverVisible: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
data() {
|
||||||
options: {
|
return {
|
||||||
type: Array,
|
configVisible: false
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
showOptionDialog: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
dialogWidth: {
|
|
||||||
type: String,
|
|
||||||
default: '60%'
|
|
||||||
},
|
|
||||||
showOperateOption: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
showText: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
showOthers: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
configVisible: {
|
curOptions() {
|
||||||
get() {
|
const editStore = useEditStore()
|
||||||
return this.showOptionDialog
|
return _cloneDeep(editStore.moduleConfig.options)
|
||||||
},
|
|
||||||
set(newVal) {
|
|
||||||
this.$emit('update:modelValue', newVal)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
hashMap() {
|
hashMap() {
|
||||||
const mapData = {}
|
const mapData = {}
|
||||||
@ -144,8 +113,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
draggable,
|
draggable
|
||||||
ExtraIcon
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
options(val) {
|
options(val) {
|
||||||
@ -154,10 +122,12 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addOtherOption() {
|
addOtherOption() {
|
||||||
const { field } = this.moduleConfig
|
this.addOption('其他', true, -1, this.fieldId)
|
||||||
this.addOption('其他', true, -1, field)
|
|
||||||
},
|
},
|
||||||
addOption(text = '选项', others = false, index = -1, field) {
|
openOptionConfig() {
|
||||||
|
this.configVisible = true
|
||||||
|
},
|
||||||
|
addOption(text = '选项', others = false, index = -1, fieldId) {
|
||||||
let addOne
|
let addOne
|
||||||
if (this.curOptions[0]) {
|
if (this.curOptions[0]) {
|
||||||
addOne = _cloneDeep(this.curOptions[0])
|
addOne = _cloneDeep(this.curOptions[0])
|
||||||
@ -176,7 +146,7 @@ export default {
|
|||||||
for (const i in addOne) {
|
for (const i in addOne) {
|
||||||
if (i === 'others') {
|
if (i === 'others') {
|
||||||
addOne[i] = others
|
addOne[i] = others
|
||||||
if (others) addOne.othersKey = `${field}_${addOne.hash}`
|
if (others) addOne.othersKey = `${fieldId}_${addOne.hash}`
|
||||||
} else if (i === 'mustOthers') {
|
} else if (i === 'mustOthers') {
|
||||||
addOne[i] = false
|
addOne[i] = false
|
||||||
} else if (i === 'text') {
|
} else if (i === 'text') {
|
||||||
@ -201,7 +171,6 @@ export default {
|
|||||||
if (typeof newOptions !== 'undefined' && newOptions.length > 0) {
|
if (typeof newOptions !== 'undefined' && newOptions.length > 0) {
|
||||||
this.curOptions = newOptions
|
this.curOptions = newOptions
|
||||||
this.importKey = 'single'
|
this.importKey = 'single'
|
||||||
this.popoverVisible = false
|
|
||||||
} else {
|
} else {
|
||||||
ElMessage.warning('最少保留一项')
|
ElMessage.warning('最少保留一项')
|
||||||
}
|
}
|
||||||
@ -217,10 +186,9 @@ export default {
|
|||||||
return Math.random().toString().slice(-6)
|
return Math.random().toString().slice(-6)
|
||||||
},
|
},
|
||||||
changeOptionOthers(val, option) {
|
changeOptionOthers(val, option) {
|
||||||
const { field } = this.moduleConfig
|
|
||||||
option.others = val
|
option.others = val
|
||||||
if (val) {
|
if (val) {
|
||||||
option.othersKey = `${field}_${option.hash}`
|
option.othersKey = `${this.fieldId}_${option.hash}`
|
||||||
} else {
|
} else {
|
||||||
option.othersKey = ''
|
option.othersKey = ''
|
||||||
}
|
}
|
||||||
@ -238,7 +206,7 @@ export default {
|
|||||||
ElMessage.warning('已存在相同的标签内容,请重新输入')
|
ElMessage.warning('已存在相同的标签内容,请重新输入')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.$emit('optionChange', this.curOptions)
|
this.$emit('handleChange', { key: 'options', value: this.curOptions })
|
||||||
this.configVisible = false
|
this.configVisible = false
|
||||||
},
|
},
|
||||||
onBlur(e, index) {
|
onBlur(e, index) {
|
||||||
@ -250,6 +218,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.primary-color {
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
.option-config-wrapper {
|
.option-config-wrapper {
|
||||||
.option-handwrite {
|
.option-handwrite {
|
||||||
.option-header {
|
.option-header {
|
@ -0,0 +1,172 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<span class="primary-color" @click="openOptionConfig"> 评分高级设置 > </span>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
title="评分高级设置"
|
||||||
|
custom-class="option-config-wrapper"
|
||||||
|
v-model="configVisible"
|
||||||
|
:append-to-body="true"
|
||||||
|
width="800px"
|
||||||
|
>
|
||||||
|
<div class="head">
|
||||||
|
<div class="row">
|
||||||
|
<div class="score">评分数值</div>
|
||||||
|
<div class="explain" v-if="isStar">评分释义</div>
|
||||||
|
<div class="other">评分后增添输入框</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="row" v-for="item in range" :key="item.index">
|
||||||
|
<div class="score">{{ item.index }}</div>
|
||||||
|
<div class="explain" v-if="isStar">
|
||||||
|
<el-input class="text" v-model="item.explain" maxlength="200" placeholder="最多200字" />
|
||||||
|
</div>
|
||||||
|
<div class="other">
|
||||||
|
<el-switch class="is-show" v-model="item.isShowInput"></el-switch>
|
||||||
|
<el-input
|
||||||
|
class="text"
|
||||||
|
v-show="item.isShowInput"
|
||||||
|
v-model="item.text"
|
||||||
|
placeholder="提示文案"
|
||||||
|
/>
|
||||||
|
<el-checkbox class="required" v-show="item.isShowInput" v-model="item.required"
|
||||||
|
>必填</el-checkbox
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="configVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onConfirm">确认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { get as _get } from 'lodash-es'
|
||||||
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
|
import { QUESTION_TYPE } from '@/common/typeEnum'
|
||||||
|
|
||||||
|
const editStore = useEditStore()
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
range: [],
|
||||||
|
configVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initRange()
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isStar() {
|
||||||
|
return editStore.moduleConfig.type === QUESTION_TYPE.RADIO_STAR
|
||||||
|
},
|
||||||
|
isNps() {
|
||||||
|
return editStore.moduleConfig.type === QUESTION_TYPE.RADIO_NPS
|
||||||
|
},
|
||||||
|
min() {
|
||||||
|
const { min = 1, starMin = 1 } = editStore.moduleConfig
|
||||||
|
return this.isNps ? min : starMin
|
||||||
|
},
|
||||||
|
max() {
|
||||||
|
const { max = 5, starMax = 5 } = editStore.moduleConfig
|
||||||
|
return this.isNps ? max : starMax
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
min(newValue, oldValue) {
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
this.initRange()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
max(newValue, oldValue) {
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
this.initRange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openOptionConfig() {
|
||||||
|
this.configVisible = true
|
||||||
|
},
|
||||||
|
initRange() {
|
||||||
|
if (this.min >= this.max) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const res = []
|
||||||
|
const rangeConfig = editStore.moduleConfig.rangeConfig
|
||||||
|
|
||||||
|
console.log(234234, editStore.moduleConfig.rangeConfig)
|
||||||
|
for (let i = this.min; i <= this.max; i++) {
|
||||||
|
res.push({
|
||||||
|
index: i,
|
||||||
|
isShowInput: _get(rangeConfig, `${i}.isShowInput`) || false,
|
||||||
|
text: _get(rangeConfig, `${i}.text`) || '',
|
||||||
|
required: _get(rangeConfig, `${i}.required`) || false,
|
||||||
|
explain: _get(rangeConfig, `${i}.explain`) || ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.range = res
|
||||||
|
},
|
||||||
|
onConfirm() {
|
||||||
|
const res = {}
|
||||||
|
for (const item of this.range) {
|
||||||
|
res[item.index] = {
|
||||||
|
isShowInput: item.isShowInput,
|
||||||
|
text: item.text,
|
||||||
|
required: item.required,
|
||||||
|
explain: item.explain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('handleChange', {
|
||||||
|
key: `rangeConfig`,
|
||||||
|
value: res
|
||||||
|
})
|
||||||
|
this.configVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.primary-color {
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
height: 60px;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
.score {
|
||||||
|
flex-basis: 110px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.other {
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 10px;
|
||||||
|
.is-show {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
width: 240px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.explain {
|
||||||
|
width: 216px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.head .row {
|
||||||
|
border: 1px solid #edeffc;
|
||||||
|
background-color: #f9fafc;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<Component
|
||||||
|
:is="advancedComponent"
|
||||||
|
:fieldId="editStore.moduleConfig.field"
|
||||||
|
@handleChange="handleChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { shallowRef, defineAsyncComponent } from 'vue'
|
||||||
|
import { QUESTION_TYPE } from '@/common/typeEnum'
|
||||||
|
|
||||||
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
|
|
||||||
|
const editStore = useEditStore()
|
||||||
|
|
||||||
|
const emit = defineEmits(['handleChange'])
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
moduleConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const advancedComponent = shallowRef(null)
|
||||||
|
|
||||||
|
const handleChange = (data) => {
|
||||||
|
emit('handleChange', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 题型组件的高级设置
|
||||||
|
switch (props.moduleConfig.type) {
|
||||||
|
case QUESTION_TYPE.RADIO:
|
||||||
|
case QUESTION_TYPE.CHECKBOX:
|
||||||
|
case QUESTION_TYPE.VOTE:
|
||||||
|
advancedComponent.value = defineAsyncComponent(() => import('./OptionConfig.vue'))
|
||||||
|
break
|
||||||
|
case QUESTION_TYPE.RADIO_STAR:
|
||||||
|
case QUESTION_TYPE.RADIO_NPS:
|
||||||
|
advancedComponent.value = defineAsyncComponent(() => import('./RateConfig.vue'))
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
@ -1,4 +1,4 @@
|
|||||||
import { computed, defineComponent, onMounted, shallowRef, ref } from 'vue'
|
import { computed, defineComponent, onMounted, shallowRef, ref, provide } from 'vue'
|
||||||
|
|
||||||
import questionLoader from '@/materials/questions/questionLoader.js'
|
import questionLoader from '@/materials/questions/questionLoader.js'
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['blur', 'focus', 'change', 'select'],
|
emits: ['blur', 'focus', 'change', 'select'],
|
||||||
setup(props, { emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const BlockComponent = shallowRef(null)
|
const BlockComponent = shallowRef(null)
|
||||||
|
|
||||||
const questionMeta = ref({})
|
const questionMeta = ref({})
|
||||||
@ -76,6 +76,11 @@ export default defineComponent({
|
|||||||
emit('change', data)
|
emit('change', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 透传高级组件
|
||||||
|
provide('slots', {
|
||||||
|
advancedEdit: slots.advancedEdit
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props,
|
props,
|
||||||
BlockComponent,
|
BlockComponent,
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
title="评分高级设置"
|
|
||||||
custom-class="option-config-wrapper"
|
|
||||||
v-model="innerVisible"
|
|
||||||
:append-to-body="true"
|
|
||||||
:width="dialogWidth"
|
|
||||||
>
|
|
||||||
<div class="head">
|
|
||||||
<div class="row">
|
|
||||||
<div class="score">评分数值</div>
|
|
||||||
<div class="explain" v-if="explain">评分释义</div>
|
|
||||||
<div class="other">评分后增添输入框</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="body">
|
|
||||||
<div class="row" v-for="item in range" :key="item.index">
|
|
||||||
<div class="score">{{ item.index }}</div>
|
|
||||||
<div class="explain" v-if="explain">
|
|
||||||
<el-input class="text" v-model="item.explain" maxlength="200" placeholder="最多200字" />
|
|
||||||
</div>
|
|
||||||
<div class="other">
|
|
||||||
<el-switch class="is-show" v-model="item.isShowInput"></el-switch>
|
|
||||||
<el-input
|
|
||||||
class="text"
|
|
||||||
v-show="item.isShowInput"
|
|
||||||
v-model="item.text"
|
|
||||||
placeholder="提示文案"
|
|
||||||
/>
|
|
||||||
<el-checkbox class="required" v-show="item.isShowInput" v-model="item.required"
|
|
||||||
>必填</el-checkbox
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="innerVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="onConfirm">确认</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { get as _get } from 'lodash-es'
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
min: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
max: {
|
|
||||||
type: Number,
|
|
||||||
default: 5
|
|
||||||
},
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
dialogWidth: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: '600px'
|
|
||||||
},
|
|
||||||
rangeConfig: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
},
|
|
||||||
explain: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
range: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.initRange()
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
innerVisible: {
|
|
||||||
get() {
|
|
||||||
return this.visible
|
|
||||||
},
|
|
||||||
set(newVal) {
|
|
||||||
this.$emit('update:modelValue', newVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initRange() {
|
|
||||||
if (this.min >= this.max) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const res = []
|
|
||||||
for (let i = this.min; i <= this.max; i++) {
|
|
||||||
res.push({
|
|
||||||
index: i,
|
|
||||||
isShowInput: _get(this.rangeConfig, `${i}.isShowInput`) || false,
|
|
||||||
text: _get(this.rangeConfig, `${i}.text`) || '',
|
|
||||||
required: _get(this.rangeConfig, `${i}.required`) || false,
|
|
||||||
explain: _get(this.rangeConfig, `${i}.explain`) || ''
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.range = res
|
|
||||||
},
|
|
||||||
onConfirm() {
|
|
||||||
const res = {}
|
|
||||||
for (const item of this.range) {
|
|
||||||
res[item.index] = {
|
|
||||||
isShowInput: item.isShowInput,
|
|
||||||
text: item.text,
|
|
||||||
required: item.required,
|
|
||||||
explain: item.explain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const payload = {
|
|
||||||
key: `rangeConfig`,
|
|
||||||
value: res
|
|
||||||
}
|
|
||||||
this.$emit('confirm', payload)
|
|
||||||
this.innerVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
height: 60px;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
.score {
|
|
||||||
flex-basis: 110px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.other {
|
|
||||||
flex: 1;
|
|
||||||
padding-left: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 10px;
|
|
||||||
.is-show {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
.text {
|
|
||||||
width: 240px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.explain {
|
|
||||||
width: 216px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.head .row {
|
|
||||||
border: 1px solid #edeffc;
|
|
||||||
background-color: #f9fafc;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,60 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- const { showOthers, hasAdvancedConfig, hasAdvancedRateConfig, min, max, explain, isNps } = this -->
|
|
||||||
<div class="option-edit-bar-wrap">
|
<div class="option-edit-bar-wrap">
|
||||||
<div class="option-edit-bar">
|
<div class="option-edit-bar">
|
||||||
<div v-if="showOthers" class="add-option primary-color" @click="addOther">
|
<div v-if="showOthers" class="add-option primary-color" @click="addOther">
|
||||||
<extra-icon type="add-square"></extra-icon>
|
<extra-icon type="add-square"></extra-icon>
|
||||||
其他____
|
其他____
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 预留:作为左侧内容的扩展 -->
|
||||||
<span
|
<!-- <span class="extra-config"><component :is="slots.extraEdit" /></span> -->
|
||||||
v-if="hasAdvancedConfig"
|
<span v-if="showAdvancedConfig && !!slots.advancedEdit" class="advanced-config">
|
||||||
class="option-advanced-config primary-color"
|
<component :is="slots.advancedEdit" />
|
||||||
@click="openOptionConfig"
|
|
||||||
>
|
|
||||||
高级设置>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="hasAdvancedRateConfig"
|
|
||||||
class="option-advanced-config primary-color"
|
|
||||||
@click="openRateConfig"
|
|
||||||
>
|
|
||||||
高级评分设置>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OptionConfig
|
|
||||||
:options="optionList"
|
|
||||||
:showOptionDialog="optionConfigVisible"
|
|
||||||
:showOthers="showOthers"
|
|
||||||
:showLimit="false"
|
|
||||||
v-model="optionConfigVisible"
|
|
||||||
@addOther="addOther"
|
|
||||||
@optionChange="handleOptionChange"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RateConfig
|
|
||||||
:class="isNps ? 'nps-rate-config' : ''"
|
|
||||||
dialogWidth="800px"
|
|
||||||
:min="min"
|
|
||||||
:max="max"
|
|
||||||
:rangeConfig="moduleConfig.rangeConfig"
|
|
||||||
v-model="rateConfigVisible"
|
|
||||||
:explain="explain"
|
|
||||||
@confirm="handleChange"
|
|
||||||
@visibleChange="onVisibleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, inject } from 'vue'
|
import { ref, inject } from 'vue'
|
||||||
import OptionConfig from '../AdvancedConfig/OptionConfig.vue'
|
|
||||||
import RateConfig from '../AdvancedConfig/RateConfig.vue'
|
|
||||||
import ExtraIcon from '../ExtraIcon/index.vue'
|
import ExtraIcon from '../ExtraIcon/index.vue'
|
||||||
import { QUESTION_TYPE } from '@/common/typeEnum'
|
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
optionList: {
|
optionList: {
|
||||||
@ -65,18 +27,16 @@ defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
hasAdvancedConfig: {
|
showAdvancedConfig: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
|
||||||
hasAdvancedRateConfig: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['addOther', 'optionChange', 'change'])
|
const emit = defineEmits(['addOther', 'optionChange', 'change'])
|
||||||
|
|
||||||
const moduleConfig = inject('moduleConfig')
|
const moduleConfig = inject('moduleConfig')
|
||||||
|
const slots = inject('slots')
|
||||||
|
|
||||||
const optionConfigVisible = ref(false)
|
const optionConfigVisible = ref(false)
|
||||||
const openOptionConfig = () => {
|
const openOptionConfig = () => {
|
||||||
optionConfigVisible.value = true
|
optionConfigVisible.value = true
|
||||||
@ -85,41 +45,6 @@ const openOptionConfig = () => {
|
|||||||
const addOther = () => {
|
const addOther = () => {
|
||||||
emit('addOther')
|
emit('addOther')
|
||||||
}
|
}
|
||||||
const handleOptionChange = (value) => {
|
|
||||||
emit('optionChange', value)
|
|
||||||
}
|
|
||||||
const handleChange = (data) => {
|
|
||||||
emit('change', data)
|
|
||||||
}
|
|
||||||
|
|
||||||
const rateConfigVisible = ref(false)
|
|
||||||
const openRateConfig = () => {
|
|
||||||
rateConfigVisible.value = true
|
|
||||||
}
|
|
||||||
const onVisibleChange = (val) => {
|
|
||||||
rateConfigVisible.value = val
|
|
||||||
}
|
|
||||||
|
|
||||||
const isNps = computed(() => {
|
|
||||||
return moduleConfig.value.type === QUESTION_TYPE.RADIO_NPS
|
|
||||||
})
|
|
||||||
|
|
||||||
const min = computed(() => {
|
|
||||||
const { min, starMin } = moduleConfig.value
|
|
||||||
return isNps.value ? min : starMin
|
|
||||||
})
|
|
||||||
|
|
||||||
const max = computed(() => {
|
|
||||||
const { max, starMax } = moduleConfig.value
|
|
||||||
return isNps.value ? max : starMax
|
|
||||||
})
|
|
||||||
|
|
||||||
const explain = computed(() => {
|
|
||||||
const { type } = moduleConfig.value
|
|
||||||
if (type == 'radio-start') return true
|
|
||||||
if (isNps.value) return false
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -133,16 +58,14 @@ const explain = computed(() => {
|
|||||||
|
|
||||||
.add-option {
|
.add-option {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 10px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
margin-right: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-advanced-config {
|
.advanced-config {
|
||||||
color: #0f8a82;
|
|
||||||
float: right;
|
float: right;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-color {
|
.primary-color {
|
||||||
|
@ -46,9 +46,8 @@ export default defineComponent({
|
|||||||
emit('change', { key, value })
|
emit('change', { key, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasAdvancedConfig = ref(false)
|
|
||||||
const hasAdvancedRateConfig = ref(false)
|
|
||||||
const showOthers = ref(false)
|
const showOthers = ref(false)
|
||||||
|
const showAdvancedConfig = ref(false)
|
||||||
const showOptionEdit = ref(true)
|
const showOptionEdit = ref(true)
|
||||||
const showOptionEditBar = ref(true)
|
const showOptionEditBar = ref(true)
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -56,17 +55,15 @@ export default defineComponent({
|
|||||||
showOptionEdit.value = optionEdit.show
|
showOptionEdit.value = optionEdit.show
|
||||||
showOptionEditBar.value = optionEditBar.show
|
showOptionEditBar.value = optionEditBar.show
|
||||||
showOthers.value = optionEditBar.configure.showOthers
|
showOthers.value = optionEditBar.configure.showOthers
|
||||||
hasAdvancedConfig.value = Boolean(optionEditBar.configure.showAdvancedConfig)
|
showAdvancedConfig.value = optionEditBar.configure.showAdvancedConfig
|
||||||
hasAdvancedRateConfig.value = Boolean(optionEditBar.configure.showAdvancedRateConfig)
|
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
slots,
|
slots,
|
||||||
getOptions,
|
getOptions,
|
||||||
hasAdvancedConfig,
|
|
||||||
hasAdvancedRateConfig,
|
|
||||||
showOptionEdit,
|
showOptionEdit,
|
||||||
showOptionEditBar,
|
showOptionEditBar,
|
||||||
showOthers,
|
showOthers,
|
||||||
|
showAdvancedConfig,
|
||||||
handleAddOption,
|
handleAddOption,
|
||||||
handleAddOtherOption,
|
handleAddOtherOption,
|
||||||
handleOptionChange,
|
handleOptionChange,
|
||||||
@ -92,8 +89,7 @@ export default defineComponent({
|
|||||||
ref="optionEditBar"
|
ref="optionEditBar"
|
||||||
option-list={this.getOptions}
|
option-list={this.getOptions}
|
||||||
showOthers={this.showOthers}
|
showOthers={this.showOthers}
|
||||||
hasAdvancedConfig={this.hasAdvancedConfig}
|
showAdvancedConfig={this.showAdvancedConfig}
|
||||||
hasAdvancedRateConfig={this.hasAdvancedRateConfig}
|
|
||||||
onAddOption={this.handleAddOption}
|
onAddOption={this.handleAddOption}
|
||||||
onAddOther={this.handleAddOtherOption}
|
onAddOther={this.handleAddOtherOption}
|
||||||
onOptionChange={this.handleOptionChange}
|
onOptionChange={this.handleOptionChange}
|
||||||
|
@ -149,7 +149,7 @@ const meta = {
|
|||||||
show: true,
|
show: true,
|
||||||
configure: {
|
configure: {
|
||||||
showOthers: false,
|
showOthers: false,
|
||||||
showAdvancedRateConfig: true
|
showAdvancedConfig: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ const meta = {
|
|||||||
show: true,
|
show: true,
|
||||||
configure: {
|
configure: {
|
||||||
showOthers: false,
|
showOthers: false,
|
||||||
showAdvancedRateConfig: true
|
showAdvancedConfig: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user