feat: 整卷增加基础配置:必填、显示类型、显示序号、显示分割线 (#391)

* feat: 增加整卷配置功能

* fix: 限制单题修改配置时只对基础配置进行更新全局基础配置操作

---------

Co-authored-by: jiangchunfu <jiangchunfu@kaike.la>
This commit is contained in:
Jiangchunfu 2024-08-12 21:39:19 +08:00 committed by sudoooooo
parent 28591f00a3
commit 624308bae8
3 changed files with 187 additions and 47 deletions

View File

@ -1,37 +1,51 @@
<template> <template>
<div class="setter-wrapper"> <div class="setter-wrapper">
<div class="no-select-question" v-if="currentEditOne === null"> <div class="no-select-question" v-if="editStore.currentEditOne === null">
<img src="/imgs/icons/unselected.webp" /> <img src="/imgs/icons/unselected.webp" />
<h4 class="tipFont">选中题型可以编辑</h4> <h4 class="tipFont">选中题型可以编辑</h4>
<span class="tip">试试看</span> <span class="tip">试试看</span>
</div> </div>
<template v-else> <el-tabs v-else v-model="confType" type="border-card" stretch>
<div class="setter-title">{{ currentEditMeta?.title || '' }}</div> <el-tab-pane name="baseConf" label="单题设置">
<SetterField <div class="setter-title">{{ currentEditMeta?.title || '' }}</div>
class="question-config-form" <SetterField
:form-config-list="formConfigList" :form-config-list="formConfigList"
:module-config="moduleConfig" :module-config="moduleConfig"
@form-change="handleFormChange" @form-change="handleFormChange"
/> />
</template> </el-tab-pane>
<el-tab-pane name="globalBaseConf" label="整卷设置">
<SetterField
:form-config-list="[basicConfig]"
:module-config="editStore.editGlobalBaseConf.globalBaseConfig"
@form-change="editStore.editGlobalBaseConf.updateGlobalConfOption"
/>
</el-tab-pane>
</el-tabs>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { ref } from 'vue'
import { useEditStore } from '@/management/stores/edit' import { useEditStore } from '@/management/stores/edit'
import basicConfig from '@/materials/questions/common/config/basicConfig'
import SetterField from '@/management/pages/edit/components/SetterField.vue' import SetterField from '@/management/pages/edit/components/SetterField.vue'
const confType = ref('baseConf')
const editStore = useEditStore() const editStore = useEditStore()
const { currentEditOne, currentEditKey, currentEditMeta, formConfigList, moduleConfig } =
storeToRefs(editStore) const { currentEditKey, currentEditMeta, formConfigList, moduleConfig } = storeToRefs(editStore)
const { changeSchema } = editStore const { changeSchema } = editStore
const handleFormChange = (data: any) => { const handleFormChange = (data: any) => {
const { key, value } = data const { key, value } = data
const resultKey = `${currentEditKey.value}.${key}` const resultKey = `${currentEditKey.value}.${key}`
changeSchema({ key: resultKey, value }) changeSchema({ key: resultKey, value })
if (key in editStore.editGlobalBaseConf.globalBaseConfig)
editStore.editGlobalBaseConf.updateCounts('MODIFY', { key, value })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.setter-wrapper { .setter-wrapper {
width: 360px; width: 360px;
@ -39,36 +53,53 @@ const handleFormChange = (data: any) => {
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
background-color: #fff; background-color: #fff;
} .no-select-question {
padding-top: 125px;
display: flex;
flex-direction: column;
align-items: center;
.setter-title { img {
height: 40px; width: 160px;
line-height: 40px; padding: 25px;
font-size: 14px; }
color: $primary-color;
padding-left: 20px;
border-bottom: 1px solid #edeffc;
}
.no-select-question { .tip {
padding-top: 125px; font-size: 14px;
display: flex; color: $normal-color;
flex-direction: column; letter-spacing: 0;
align-items: center; }
img {
width: 160px;
padding: 25px;
} }
.tip { .setter-title {
height: 40px;
line-height: 40px;
font-size: 14px; font-size: 14px;
color: $normal-color; color: $primary-color;
letter-spacing: 0; padding-left: 20px;
border-bottom: 1px solid #edeffc;
} }
}
.question-config-form { :deep(.el-tabs) {
padding: 30px 20px 50px 20px; width: 360px;
height: 100%;
border: none;
display: flex;
flex-direction: column;
.el-tabs__nav {
width: 100%;
}
.el-tabs__content {
flex: 1;
overflow-y: auto;
padding: 0;
.config-form {
padding: 30px 20px 50px 20px;
}
}
}
} }
</style> </style>

View File

@ -0,0 +1,91 @@
import { reactive, type Ref } from 'vue'
export type TypeMethod = 'INIT' | 'MODIFY' | 'REMOVE' | 'ADD'
export default function useEditGlobalBaseConf(
questionDetailList: Ref<any[]>,
updateTime: () => void
) {
// 整卷配置数据
const globalBaseConfig = reactive({
isRequired: true,
showIndex: true,
showType: true,
showSpliter: true
})
// 整卷配置各项选项选中个数统计
const optionCheckedCounts = {
isRequiredCount: 0,
showIndexCount: 0,
showTypeCount: 0,
showSpliterCount: 0
}
// 初始化统计
function initCounts() {
questionDetailList.value.forEach((question: any) => {
calculateCountsForQuestion('INIT', { question })
})
updateGlobalBaseConf()
}
// 更新统计
function updateCounts(type: TypeMethod, data: any) {
if (type === 'MODIFY') {
calculateOptionCounts(type, data)
} else {
calculateCountsForQuestion(type, data)
}
updateGlobalBaseConf()
}
// 计算整卷配置各项选项选中个数
function calculateCountsForQuestion(type: TypeMethod, { question }: any) {
Object.keys(globalBaseConfig).forEach((key) => {
calculateOptionCounts(type, { key, value: question[key] })
})
}
// 计算单个选项选中个数
function calculateOptionCounts(type: TypeMethod, { key, value }: any) {
const _key = `${key}Count` as keyof typeof optionCheckedCounts
if (value) {
if (type === 'REMOVE') optionCheckedCounts[_key]--
else optionCheckedCounts[_key]++
} else {
if (type === 'MODIFY') optionCheckedCounts[_key]--
}
}
// 更新整卷配置状态
function updateGlobalBaseConf() {
const len = questionDetailList.value.length
const { isRequiredCount, showIndexCount, showSpliterCount, showTypeCount } = optionCheckedCounts
Object.assign(globalBaseConfig, {
isRequired: isRequiredCount === len,
showIndex: showIndexCount === len,
showSpliter: showSpliterCount === len,
showType: showTypeCount === len
})
}
// 整卷配置修改
function updateGlobalConfOption({ key, value }: { key: string; value: boolean }) {
const len = questionDetailList.value.length
const _key = `${key}Count` as keyof typeof optionCheckedCounts
if (value) optionCheckedCounts[_key] = len
else optionCheckedCounts[_key] = 0
questionDetailList.value.forEach((question: any) => {
question[key] = value
})
updateTime()
}
return {
globalBaseConfig,
initCounts,
updateCounts,
updateGlobalConfOption
}
}

View File

@ -19,6 +19,7 @@ import questionLoader from '@/materials/questions/questionLoader'
import { SurveyPermissions } from '@/management/utils/types/workSpace' import { SurveyPermissions } from '@/management/utils/types/workSpace'
import { getBannerData } from '@/management/api/skin.js' import { getBannerData } from '@/management/api/skin.js'
import { getCollaboratorPermissions } from '@/management/api/space' import { getCollaboratorPermissions } from '@/management/api/space'
import useEditGlobalBaseConf, { type TypeMethod } from './composables/useEditGlobalBaseConf'
import { CODE_MAP } from '../api/base' import { CODE_MAP } from '../api/base'
const innerMetaConfig = { const innerMetaConfig = {
@ -28,7 +29,7 @@ const innerMetaConfig = {
} }
} }
function useInitializeSchema(surveyId: Ref<string>) { function useInitializeSchema(surveyId: Ref<string>, initializeSchemaCallBack: () => void) {
const schema = reactive({ const schema = reactive({
metaData: null, metaData: null,
bannerConf: { bannerConf: {
@ -130,6 +131,7 @@ function useInitializeSchema(surveyId: Ref<string>) {
logicConf logicConf
} }
}) })
initializeSchemaCallBack()
} else { } else {
throw new Error(res.errmsg || '问卷不存在') throw new Error(res.errmsg || '问卷不存在')
} }
@ -142,11 +144,17 @@ function useInitializeSchema(surveyId: Ref<string>) {
} }
} }
function useQuestionDataListOperations( function useQuestionDataListOperations({
questionDataList: Ref<any[]>, questionDataList,
updateTime: () => void, updateTime,
pageOperations,
updateCounts
}: {
questionDataList: Ref<any[]>
updateTime: () => void
pageOperations: (type: string) => void pageOperations: (type: string) => void
) { updateCounts: (type: TypeMethod, data: any) => void
}) {
function copyQuestion({ index }: { index: number }) { function copyQuestion({ index }: { index: number }) {
const newQuestion = _cloneDeep(questionDataList.value[index]) const newQuestion = _cloneDeep(questionDataList.value[index])
newQuestion.field = getNewField(questionDataList.value.map((item) => item.field)) newQuestion.field = getNewField(questionDataList.value.map((item) => item.field))
@ -157,12 +165,14 @@ function useQuestionDataListOperations(
questionDataList.value.splice(index, 0, question) questionDataList.value.splice(index, 0, question)
pageOperations('add') pageOperations('add')
updateTime() updateTime()
updateCounts('ADD', { question })
} }
function deleteQuestion({ index }: { index: number }) { function deleteQuestion({ index }: { index: number }) {
pageOperations('remove') pageOperations('remove')
questionDataList.value.splice(index, 1) const [question] = questionDataList.value.splice(index, 1)
updateTime() updateTime()
updateCounts('REMOVE', { question })
} }
function moveQuestion({ index, range }: { index: number; range: number }) { function moveQuestion({ index, range }: { index: number; range: number }) {
@ -432,9 +442,13 @@ export const useEditStore = defineStore('edit', () => {
const bannerList: Ref<IBannerList> = ref({}) const bannerList: Ref<IBannerList> = ref({})
const cooperPermissions = ref(Object.values(SurveyPermissions)) const cooperPermissions = ref(Object.values(SurveyPermissions))
const schemaUpdateTime = ref(Date.now()) const schemaUpdateTime = ref(Date.now())
const { schema, initSchema, getSchemaFromRemote } = useInitializeSchema(surveyId) const { schema, initSchema, getSchemaFromRemote } = useInitializeSchema(surveyId, () => {
editGlobalBaseConf.initCounts()
})
const questionDataList = toRef(schema, 'questionDataList') const questionDataList = toRef(schema, 'questionDataList')
const editGlobalBaseConf = useEditGlobalBaseConf(questionDataList, updateTime)
function setQuestionDataList(data: any) { function setQuestionDataList(data: any) {
schema.questionDataList = data schema.questionDataList = data
} }
@ -497,9 +511,12 @@ export const useEditStore = defineStore('edit', () => {
} = usePageEdit({ schema, questionDataList }, updateTime) } = usePageEdit({ schema, questionDataList }, updateTime)
const { copyQuestion, addQuestion, deleteQuestion, moveQuestion } = useQuestionDataListOperations( const { copyQuestion, addQuestion, deleteQuestion, moveQuestion } = useQuestionDataListOperations(
questionDataList, {
updateTime, questionDataList,
pageOperations updateTime,
pageOperations,
updateCounts: editGlobalBaseConf.updateCounts
}
) )
function moveQuestionDataList(data: any) { function moveQuestionDataList(data: any) {
@ -575,6 +592,7 @@ export const useEditStore = defineStore('edit', () => {
} }
return { return {
editGlobalBaseConf,
surveyId, surveyId,
setSurveyId, setSurveyId,
bannerList, bannerList,