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

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