Procházet zdrojové kódy

添加问答题和评价题页面展示和试题添加

lm před 1 měsícem
rodič
revize
c46d0552ec

+ 120 - 11
src/components/questionConfig/QuestionConfig.vue

@@ -1,6 +1,9 @@
+<!-- 题目配置 -->
+
 <template>
     <div class="test_question_config">
         <Form
+            :v-model:formRef="formRefDom"
             :form-item-list="finalFormItemList"
             :default-form-data="defaultFormData"
             @form-item-change="HandleFormItemChange"
@@ -36,6 +39,33 @@
                     </el-checkbox-group>
                 </div>
             </template>
+
+            <template #scoreReviewType="{formData}">
+                <div class="score_reviewType">
+                    <el-radio-group v-model="defaultFormData.scoreReviewType">
+                        <el-radio v-for="radioItem in scoreReviewTypeList" :key="radioItem.value" :value="radioItem.value">{{ radioItem.label }}</el-radio>
+                    </el-radio-group>
+
+                    <ul class="num_score" v-if="Number(formData.scoreReviewType) === 0 && Number(formData.titleScore)">
+                        <li v-for="value in Number(formData.titleScore)">
+                            {{ value }}分
+                        </li>
+                    </ul>
+                    <div class="star_score" v-else-if="Number(formData.scoreReviewType) === 1 && Number(formData.titleScore)">
+                        非常不满意
+                        <el-rate size="large" 
+                            :model-value="0" 
+                            :disabled="true" 
+                            disabled-void-color="#c6d1de" 
+                            disabled-void-icon="Star" 
+                            :max="Number(formData.titleScore)" 
+                            clearable />
+                        非常满意
+                    </div>
+                </div>
+            </template>
+
+
             <template #options="{ formData }">
                 <div class="options_list_container">
                     <div v-for="(option) in formData.options" :key="option.id" class="option_item">
@@ -98,7 +128,7 @@ import Form from '@/baseComponents/Form.vue'
 
 import { questionFormItemList } from './form'
 import {
-    statisticQuestionType, scoredQuestionType, questionConfig
+    statisticQuestionType, scoredQuestionType
 } from './questionTypeList'
 
 type DisplayMode = 'scored' | 'statistic'
@@ -114,7 +144,8 @@ interface FormData {
     titleScore?: String  //题目分值
     questionType: String   //题目类型
     extraConfig: String[]    // 是否必答 required, 是否横排 isHorizontal
-    options: Option[]  //单选/多选 的 选项配置
+    options: Option[],  //单选/多选 的 选项配置
+    scoreReviewType?:Number,  // 评价题 评分的展示形式
 }
 
 const props = defineProps({
@@ -130,19 +161,22 @@ const props = defineProps({
 })
 const emit = defineEmits(['confirm', 'cancel', 'form-change'])
 
-// 题目信息 
+const formRefDom = ref()
+
+// 试题题目信息 
 const defaultFormData = ref<FormData>({
     title: '',  
     titleScore: '',   
     questionType: '', 
-    extraConfig: ['required'],  
-    options: []  
+    extraConfig: ['required'],  //默认勾选必答题
+    options: [],
+    scoreReviewType:0  //默认展示 数字式
  })
 
 
 
 /*
-  监听 props.displayMode 展示 不同的 题型配置 和 试卷配置 
+  监听 props.displayMode  展示 不同的 题型配置 和 试卷配置 
 */
 // 题型选项配置 监听 动态切换
 const questionTypeOptions = computed(() => {
@@ -152,19 +186,46 @@ const questionTypeOptions = computed(() => {
         return  [... statisticQuestionType.value]
     }
 })
-// 表单试卷 展示项配置  监听 动态显隐
+// 表单试题 展示项配置  监听 表单元素 动态显隐
 const finalFormItemList = computed(() => {
     return questionFormItemList.value.map(item => {
         const newItem = { ...item }
         // 题目分值仅在 scored 模式显示
         if (item.key === 'titleScore') {
             newItem.hidden = props.displayMode !== 'scored'
+        }else if(item.key == 'options'){
+            // 评价题  和 问答题 不展示 题目子选项配置
+            newItem.hidden = [2,4].includes(Number(defaultFormData.value.questionType))  
+        }else if(item.key == 'scoreReviewType'){
+            // 评价题 展示评分的格式
+            newItem.hidden = Number(defaultFormData.value.questionType) !== 4
         }
         return newItem
     })
 })
 
 
+// 试题额外配置项   // 评价题 和 问答题 展示不同的配置项
+const questionConfig = computed(()=>{
+    // 评价题 和 问答题
+    if([2,4].includes(Number(defaultFormData.value.questionType)) ){
+        return [
+            { label: '必答题', value: 'required' },
+        ]
+    }else{
+        return [
+            { label: '必答题', value: 'required' },
+            { label: '选项横排', value: 'isHorizontal' }
+        ]
+    }
+})
+
+// 评价题 评分形式 列表
+const scoreReviewTypeList = ref([
+    {label:'数字式',value:0},
+    {label:'星星式', value:1},
+])
+
 // 题目类型变化触发的操作
 const HandleQuestionTypeChange = (key,val)=>{
     // 
@@ -217,6 +278,19 @@ watch(()=>defaultFormData.value, (newVal) => {
 }, { deep: true })
 
 
+watch(() =>defaultFormData.value.questionType, (newVal,oldVal) => {
+    if (newVal !== oldVal) {
+        // 清空 除了选项外的表单信息  
+        defaultFormData.value = {
+            title: '',  
+            titleScore: '',   
+            questionType: newVal, 
+            extraConfig: ['required'],  //默认勾选必答题
+            options: [],
+            scoreReviewType:0  //默认展示 数字式
+        }
+    }
+}, { immediate: true })
 
 </script>
 
@@ -237,6 +311,45 @@ watch(()=>defaultFormData.value, (newVal) => {
     }
 }
 
+.score_reviewType{
+    display: flex;
+    flex-direction: column;
+
+    .num_score,
+    .star_score
+    {
+        display: flex;
+        align-items: center;
+        gap:16px;
+        color: #CCCCCC;
+        line-height: 1;
+    }
+    .num_score{
+        flex-wrap: wrap;
+        li{
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            border-radius: 4px ;
+            border: 1px solid #CCCCCC;
+            width: 44px;
+            height: 32px;
+            font-size: 14px;
+            background-color: white;
+        }
+    }
+
+    .star_score{
+        word-break: keep-all;
+        .el-rate{
+            display: flex;
+            flex-wrap: wrap;
+            gap:10px 20px;
+            height: auto;
+        }
+    } 
+}
+
 // 选项列表样式
 .options_list_container {
     width:100% ;
@@ -333,10 +446,6 @@ watch(()=>defaultFormData.value, (newVal) => {
         &.percent_30 {
             width: 35%;
         }
-
-        &.percent_40 {
-            width: 40%;
-        }
     }
 }
 </style>

+ 20 - 2
src/components/questionConfig/form.ts

@@ -50,16 +50,34 @@ export const questionFormItemList = ref([
         ],
         style: {},
         custom:true,
-        // className: 'percent_40'
         className: 'custom_itm'
     },
+
+    {
+        key: 'scoreReviewType',
+        label: '分割',
+        type: 'radio',
+        selectList: [],
+        rules: [
+            {
+                required:true,
+                message:'请填写信息',
+                trigger:'blur'
+            }
+        ],
+        style: {},
+        custom:true,
+        className: 'custom_itm',
+        hidden:true,
+    },
     {
         key: 'options',
         label: '',
         type: 'input',
         rules: [],
         className:'custom_itm',
-        custom: true
+        custom: true,
+        hidden:false
     }
 ])
 

+ 0 - 5
src/components/questionConfig/questionTypeList.ts

@@ -44,11 +44,6 @@ export const scoredQuestionType = ref<QuestionTypeItm[]>([
     },
 ])
 
-export const questionConfig = ref([
-    { label: '必答题', value: 'required' },
-    { label: '选项横排', value: 'isHorizontal' }
-])
-
 export const qustionTypeToName = (type)=>{
     switch(Number(type)){
         case 0:

+ 57 - 7
src/views/surveyManagement/createQuestionnaire/CreateQuestionnaire.vue

@@ -51,6 +51,7 @@
                     ></QuestionnaireBaseForm>
                 </div>
 
+                <!-- 已添加题目展示区 -->
                 <ul class="question_list_area">
                     <li v-for="(question,index) in addedQuestionList" :key="question.id">
                         <div class="question_title" 
@@ -61,7 +62,7 @@
 
                         <!-- 单选  -->
                         <el-radio-group 
-                            v-if="Number(question.questionType) === 0" 
+                            v-if="[0,3].includes(Number(question.questionType))" 
                             :class="{vertical:!question.extraConfig.includes('isHorizontal')}"> 
 
                             <el-radio v-for="radioItem in question.options" :key="radioItem.value" :value="radioItem.value">{{ radioItem.label }}</el-radio>
@@ -82,16 +83,28 @@
 
                         <!-- 问答题 -->
                         <el-input  
-                            v-else-if="Number(question.questionType) === 2 || Number(question.questionType) === 4"
+                            v-else-if="Number(question.questionType) === 2"
                             :autosize="{ minRows:5, maxRows: 5 }" 
                             type="textarea" 
                             :rows="5"  
                             placeholder="不超过2000字"
                         />
 
-                        <!-- 评分题 3 -->
-
-
+                        <!-- 评价(分)题 4 -->
+                        <template v-else-if="Number(question.questionType) === 4 ">
+                            <ul class="num_score" v-if="Number(question.scoreReviewType) === 0 && Number(question.titleScore)">
+                                <li v-for="value in Number(question.titleScore)">
+                                    {{ value }}分
+                                </li>
+                            </ul>
+                            <div class="star_score" v-else-if="Number(question.scoreReviewType) === 1 && Number(question.titleScore)">
+                                非常不满意
+                                <el-rate size="large" 
+                                    :max="Number(question.titleScore)" 
+                                    clearable />
+                                非常满意
+                            </div>
+                        </template>
                     </li>
                 </ul>
 
@@ -160,9 +173,10 @@ interface QuestionItm {
     id:Number
     title: String   //题目名称
     titleScore?: String | Number  //题目分值
-    questionType: String   //题目类型
+    questionType: String | String   //题目类型
     extraConfig: String[]    // 是否必答 required, 是否横排 isHorizontal
-    options: Option[]  //单选/多选 的 选项配置
+    options: Option[],  //单选/多选 的 选项配置
+    scoreReviewType: Number|String
 }
 
 interface QuestionnaireInfo {
@@ -189,6 +203,7 @@ const addedQuestionList = ref<QuestionItm[]>([
         questionType: '2',   //题目类型
         extraConfig:[],    // 是否必答 required, 是否横排 isHorizontal
         options: [] ,
+        scoreReviewType:''
     }
 ])
 // 当前选中的题型
@@ -421,6 +436,41 @@ const HandleQuestionnaireSave = async ()=>{
                     justify-content: flex-start;
                     align-items: flex-start;
                 }
+
+
+                .num_score,
+                .star_score
+                {
+                    display: flex;
+                    align-items: center;
+                    gap:16px;
+                    color: #CCCCCC;
+                    line-height: 1;
+                }
+                .num_score{
+                    flex-wrap: wrap;
+                    li{
+                        display: flex;
+                        justify-content: center;
+                        align-items: center;
+                        border-radius: 4px ;
+                        border: 1px solid #CCCCCC;
+                        width: 44px;
+                        height: 32px;
+                        font-size: 14px;
+                        background-color: white;
+                    }
+                }
+
+                .star_score{
+                    word-break: keep-all;
+                    .el-rate{
+                        display: flex;
+                        flex-wrap: wrap;
+                        gap:10px 20px;
+                        height: auto;
+                    }
+                } 
             }
         }