Просмотр исходного кода

选择题和听后选择题选项细分修改

dusenyao 1 год назад
Родитель
Сommit
88e785c4ba

+ 56 - 23
src/views/exercise_questions/create/components/exercises/ListenSelectQuestion.vue

@@ -26,8 +26,11 @@
               {{ computedQuestionNumber(i, data.option_number_show_mode) }}
             </span>
             <div v-if="isEnable(data.property.is_option_subdivision)" class="option-list">
-              <div v-for="li in item" :key="li.mark" class="option-content">
-                <span :class="['checkbox', { active: isAnswer(li.mark, i) }]" @click="selectAnswer(li.mark, i)"></span>
+              <div v-for="li in item.data_list" :key="li.mark" class="option-content">
+                <span
+                  :class="['checkbox', { active: isAnswer(li.mark, item.mark) }]"
+                  @click="selectAnswer(li.mark, item.mark)"
+                ></span>
                 <RichText v-model="li.content" placeholder="输入内容" :inline="true" />
               </div>
             </div>
@@ -121,7 +124,7 @@
             :key="value"
             v-model="data.property.score_type"
             :label="value"
-            :disabled="scoreTypeList[1].value === value && data.property.select_type === selectTypeList[0].value"
+            :disabled="true"
           >
             {{ label }}
           </el-radio>
@@ -143,7 +146,7 @@ import UploadAudio from '../common/UploadAudio.vue';
 import QuestionMixin from '../common/QuestionMixin.js';
 
 import { selectTypeList, scoreTypeList, changeOptionType, isEnable } from '@/views/exercise_questions/data/common';
-import { getListenSelectData, getOption } from '@/views/exercise_questions/data/listenSelect';
+import { getListenSelectData, getOption, getSubdivisionOption } from '@/views/exercise_questions/data/listenSelect';
 
 export default {
   name: 'ListenSelectQuestion',
@@ -158,6 +161,14 @@ export default {
       data: getListenSelectData(),
     };
   },
+  watch: {
+    'data.property.is_option_subdivision': {
+      handler(val) {
+        this.data.answer.is_option_subdivision = val;
+      },
+      immediate: true,
+    },
+  },
   methods: {
     /**
      * 智能识别
@@ -177,34 +188,50 @@ export default {
     changeSelectType(val) {
       if (val === selectTypeList[0].value && this.data.answer.answer_list.length > 1) {
         if (isEnable(this.data.property.is_option_subdivision)) {
-          this.data.answer.answer_list = Array.from({ length: this.data.option_list.length }, () => []);
+          this.data.answer.answer_list = [];
         } else {
           this.data.answer.answer_list = [this.data.answer.answer_list[0]];
         }
       }
-      // 当多选题切换到单选题时,分值类型切换为总分
-      if (val === selectTypeList[0].value && this.data.property.score_type === scoreTypeList[1].value) {
-        this.data.property.score_type = scoreTypeList[0].value;
-      }
     },
-    isAnswer(mark, i) {
+    isAnswer(mark, parent_mark) {
       if (isEnable(this.data.property.is_option_subdivision)) {
-        return this.data.answer.answer_list?.[i].includes(mark);
+        return this.data.answer.answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark);
       }
       return this.data.answer.answer_list.includes(mark);
     },
-    selectAnswer(mark, i) {
+    selectAnswer(mark, parent_mark) {
       let is_option_subdivision = isEnable(this.data.property.is_option_subdivision);
-      let answer_list = is_option_subdivision ? this.data.answer.answer_list[i] : this.data.answer.answer_list;
-      let index = answer_list.indexOf(mark);
+      let answer_list = this.data.answer.answer_list;
+      let index = is_option_subdivision
+        ? answer_list.findIndex((item) => item.mark === parent_mark)
+        : answer_list.indexOf(mark);
+
       if (this.data.property.select_type === selectTypeList[0].value) {
         if (is_option_subdivision) {
-          this.$set(this.data.answer.answer_list, i, [mark]);
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            this.$set(this.data.answer.answer_list[index], 'value_list', [mark]);
+          }
         } else {
           this.$set(this.data.answer, 'answer_list', [mark]);
         }
       }
       if (this.data.property.select_type === selectTypeList[1].value) {
+        if (is_option_subdivision) {
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            let mIndex = answer_list[index].value_list.findIndex((item) => item.mark === mark);
+            if (mIndex === -1) {
+              answer_list[index].value_list.push(mark);
+            } else {
+              answer_list[index].value_list.splice(mIndex, 1);
+            }
+          }
+          return;
+        }
         if (index === -1) {
           answer_list.push(mark);
         } else {
@@ -213,18 +240,24 @@ export default {
       }
     },
     addOption() {
-      this.data.option_list.push(getOption());
+      this.data.option_list.push(
+        isEnable(this.data.property.is_option_subdivision)
+          ? getSubdivisionOption(this.data.property.option_number)
+          : getOption(),
+      );
     },
     /**
      * 修改是否选项细分
      * @param {'true'|'false'} val
      */
     changeOptionSubdivision(val) {
+      // 现在,选项细分开启分值类型为细分,关闭为总分
+      this.data.property.score_type = scoreTypeList[isEnable(val) ? 1 : 0].value;
       if (isEnable(val)) {
         // 创建与当前 option_list 相同数量的选项,选项内的细分数量与 property.option_number 数量一样
-        this.data.answer.answer_list = Array.from({ length: this.data.option_list.length }, () => []);
+        this.data.answer.answer_list = [];
         this.data.option_list = Array.from({ length: this.data.option_list.length }, () => {
-          return Array.from({ length: this.data.property.option_number }, getOption);
+          return getSubdivisionOption(this.data.property.option_number);
         });
       } else {
         this.data.answer.answer_list = [];
@@ -236,12 +269,12 @@ export default {
      * @param {Number} val
      */
     changeOptionNumber(val) {
-      this.data.answer.answer_list = Array.from({ length: this.data.option_list.length }, () => []);
-      this.data.option_list = this.data.option_list.map((item) => {
-        if (item.length < val) {
-          return [...item, ...Array.from({ length: val - item.length }, getOption)];
+      this.data.answer.answer_list = [];
+      this.data.option_list = this.data.option_list.map(({ data_list, mark }) => {
+        if (data_list.length < val) {
+          return { mark, data_list: [...data_list, ...Array.from({ length: val - data_list.length }, getOption)] };
         }
-        return item.slice(0, val);
+        return { mark, data_list: data_list.slice(0, val) };
       });
     },
   },

+ 56 - 23
src/views/exercise_questions/create/components/exercises/SelectQuestion.vue

@@ -19,8 +19,11 @@
               {{ computedQuestionNumber(i, data.option_number_show_mode) }}
             </span>
             <div v-if="isEnable(data.property.is_option_subdivision)" class="option-list">
-              <div v-for="li in item" :key="li.mark" class="option-content">
-                <span :class="['checkbox', { active: isAnswer(li.mark, i) }]" @click="selectAnswer(li.mark, i)"></span>
+              <div v-for="li in item.data_list" :key="li.mark" class="option-content">
+                <span
+                  :class="['checkbox', { active: isAnswer(li.mark, item.mark) }]"
+                  @click="selectAnswer(li.mark, item.mark)"
+                ></span>
                 <RichText v-model="li.content" placeholder="输入内容" :inline="true" />
               </div>
             </div>
@@ -104,7 +107,7 @@
             :key="value"
             v-model="data.property.score_type"
             :label="value"
-            :disabled="scoreTypeList[1].value === value && data.property.select_type === selectTypeList[0].value"
+            :disabled="true"
           >
             {{ label }}
           </el-radio>
@@ -125,7 +128,7 @@
 import QuestionMixin from '../common/QuestionMixin.js';
 
 import { selectTypeList, scoreTypeList, changeOptionType, isEnable } from '@/views/exercise_questions/data/common';
-import { getSelectData, getOption } from '@/views/exercise_questions/data/select';
+import { getSelectData, getOption, getSubdivisionOption } from '@/views/exercise_questions/data/select';
 
 export default {
   name: 'SelectQuestion',
@@ -137,6 +140,14 @@ export default {
       data: getSelectData(),
     };
   },
+  watch: {
+    'data.property.is_option_subdivision': {
+      handler(val) {
+        this.data.answer.is_option_subdivision = val;
+      },
+      immediate: true,
+    },
+  },
   methods: {
     /**
      * 智能识别
@@ -156,34 +167,50 @@ export default {
     changeSelectType(val) {
       if (val === selectTypeList[0].value && this.data.answer.answer_list.length > 1) {
         if (isEnable(this.data.property.is_option_subdivision)) {
-          this.data.answer.answer_list = Array.from({ length: this.data.option_list.length }, () => []);
+          this.data.answer.answer_list = [];
         } else {
           this.data.answer.answer_list = [this.data.answer.answer_list[0]];
         }
       }
-      // 当多选题切换到单选题时,分值类型切换为总分
-      if (val === selectTypeList[0].value && this.data.property.score_type === scoreTypeList[1].value) {
-        this.data.property.score_type = scoreTypeList[0].value;
-      }
     },
-    isAnswer(mark, i) {
+    isAnswer(mark, parent_mark) {
       if (isEnable(this.data.property.is_option_subdivision)) {
-        return this.data.answer.answer_list?.[i].includes(mark);
+        return this.data.answer.answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark);
       }
       return this.data.answer.answer_list.includes(mark);
     },
-    selectAnswer(mark, i) {
+    selectAnswer(mark, parent_mark) {
       let is_option_subdivision = isEnable(this.data.property.is_option_subdivision);
-      let answer_list = is_option_subdivision ? this.data.answer.answer_list[i] : this.data.answer.answer_list;
-      let index = answer_list.indexOf(mark);
+      let answer_list = this.data.answer.answer_list;
+      let index = is_option_subdivision
+        ? answer_list.findIndex((item) => item.mark === parent_mark)
+        : answer_list.indexOf(mark);
+
       if (this.data.property.select_type === selectTypeList[0].value) {
         if (is_option_subdivision) {
-          this.$set(this.data.answer.answer_list, i, [mark]);
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            this.$set(this.data.answer.answer_list[index], 'value_list', [mark]);
+          }
         } else {
           this.$set(this.data.answer, 'answer_list', [mark]);
         }
       }
       if (this.data.property.select_type === selectTypeList[1].value) {
+        if (is_option_subdivision) {
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            let mIndex = answer_list[index].value_list.findIndex((item) => item.mark === mark);
+            if (mIndex === -1) {
+              answer_list[index].value_list.push(mark);
+            } else {
+              answer_list[index].value_list.splice(mIndex, 1);
+            }
+          }
+          return;
+        }
         if (index === -1) {
           answer_list.push(mark);
         } else {
@@ -192,18 +219,24 @@ export default {
       }
     },
     addOption() {
-      this.data.option_list.push(getOption());
+      this.data.option_list.push(
+        isEnable(this.data.property.is_option_subdivision)
+          ? getSubdivisionOption(this.data.property.option_number)
+          : getOption(),
+      );
     },
     /**
      * 修改是否选项细分
      * @param {'true'|'false'} val
      */
     changeOptionSubdivision(val) {
+      // 现在,选项细分开启分值类型为细分,关闭为总分
+      this.data.property.score_type = scoreTypeList[isEnable(val) ? 1 : 0].value;
       if (isEnable(val)) {
         // 创建与当前 option_list 相同数量的选项,选项内的细分数量与 property.option_number 数量一样
-        this.data.answer.answer_list = Array.from({ length: this.data.option_list.length }, () => []);
+        this.data.answer.answer_list = [];
         this.data.option_list = Array.from({ length: this.data.option_list.length }, () => {
-          return Array.from({ length: this.data.property.option_number }, getOption);
+          return getSubdivisionOption(this.data.property.option_number);
         });
       } else {
         this.data.answer.answer_list = [];
@@ -215,12 +248,12 @@ export default {
      * @param {Number} val
      */
     changeOptionNumber(val) {
-      this.data.answer.answer_list = Array.from({ length: this.data.option_list.length }, () => []);
-      this.data.option_list = this.data.option_list.map((item) => {
-        if (item.length < val) {
-          return [...item, ...Array.from({ length: val - item.length }, getOption)];
+      this.data.answer.answer_list = [];
+      this.data.option_list = this.data.option_list.map(({ data_list, mark }) => {
+        if (data_list.length < val) {
+          return { mark, data_list: [...data_list, ...Array.from({ length: val - data_list.length }, getOption)] };
         }
-        return item.slice(0, val);
+        return { mark, data_list: data_list.slice(0, val) };
       });
     },
   },

+ 11 - 0
src/views/exercise_questions/data/listenSelect.js

@@ -13,6 +13,17 @@ export function getOption(content = '') {
 }
 
 /**
+ * 获取选项细分数据项
+ * @param {number} number 选项数
+ */
+export function getSubdivisionOption(number = 2) {
+  return {
+    mark: getRandomNumber(),
+    data_list: Array.from({ length: number }, () => getOption()),
+  };
+}
+
+/**
  * 获取听后选择题数据模板(防止 mark 重复)
  */
 export function getListenSelectData() {

+ 11 - 0
src/views/exercise_questions/data/select.js

@@ -13,6 +13,17 @@ export function getOption(content = '') {
 }
 
 /**
+ * 获取选项细分数据项
+ * @param {number} number 选项数
+ */
+export function getSubdivisionOption(number = 2) {
+  return {
+    mark: getRandomNumber(),
+    data_list: Array.from({ length: number }, () => getOption()),
+  };
+}
+
+/**
  * 获取选择题数据模板(防止 mark 重复)
  */
 export function getSelectData() {

+ 37 - 19
src/views/exercise_questions/preview/ListenSelectPreview.vue

@@ -17,14 +17,14 @@
     />
 
     <div v-if="isEnable(data.property.is_option_subdivision)" class="option-subdivision">
-      <ul v-for="(item, i) in data.option_list" :key="i" class="option-subdivision-list">
+      <ul v-for="(item, i) in data.option_list" :key="item.mark" class="option-subdivision-list">
         <span class="serial-number">{{ computeOptionMethods[data.option_number_show_mode](i) }} </span>
         <li
-          v-for="{ content, mark } in item"
+          v-for="{ content, mark } in item.data_list"
           :key="mark"
           :style="{ cursor: disabled ? 'not-allowed' : 'pointer' }"
-          :class="['option-item', { active: isAnswer(mark, i) }, ...computedAnswerClass(mark, i)]"
-          @click="selectAnswer(mark, i)"
+          :class="['option-item', { active: isAnswer(mark, item.mark) }, ...computedAnswerClass(mark, item.mark)]"
+          @click="selectAnswer(mark, item.mark)"
         >
           <span class="selectionbox"></span>
           <span class="content rich-text" v-html="sanitizeHTML(content)"></span>
@@ -72,24 +72,43 @@ export default {
     }
   },
   methods: {
-    isAnswer(mark, i) {
+    isAnswer(mark, parent_mark) {
       if (isEnable(this.data.property.is_option_subdivision)) {
-        return this.answer.answer_list?.[i]?.includes(mark);
+        return this.answer.answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark);
       }
       return this.answer.answer_list.includes(mark);
     },
-    selectAnswer(mark, i) {
+    selectAnswer(mark, parent_mark) {
       if (this.disabled) return;
-      let answer_list = this.isSubdivision ? this.answer.answer_list[i] : this.answer.answer_list;
+      let answer_list = this.answer.answer_list;
+      let index = this.isSubdivision
+        ? answer_list.findIndex((item) => item.mark === parent_mark)
+        : answer_list.indexOf(mark);
       if (this.data.property.select_type === selectTypeList[0].value) {
         if (this.isSubdivision) {
-          this.$set(this.answer.answer_list, i, [mark]);
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            this.$set(this.answer.answer_list[index], 'value_list', [mark]);
+          }
         } else {
           this.$set(this.answer, 'answer_list', [mark]);
         }
       }
       if (this.data.property.select_type === selectTypeList[1].value) {
-        let index = answer_list.indexOf(mark);
+        if (this.isSubdivision) {
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            let mIndex = answer_list[index].value_list.findIndex((item) => item.mark === mark);
+            if (mIndex === -1) {
+              answer_list[index].value_list.push(mark);
+            } else {
+              answer_list[index].value_list.splice(mIndex, 1);
+            }
+          }
+          return;
+        }
         if (index === -1) {
           answer_list.push(mark);
         } else {
@@ -97,24 +116,23 @@ export default {
         }
       }
     },
-    computedAnswerClass(mark, i) {
+    computedAnswerClass(mark, parent_mark) {
       if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
         return [];
       }
+      let answer_list = this.answer.answer_list;
       let isHas = this.isSubdivision
-        ? this.answer.answer_list[i].includes(mark)
-        : this.answer.answer_list.includes(mark); // 是否已选中的选项
+        ? answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark)
+        : answer_list.includes(mark); // 是否已选中的选项
+      let isRight = this.isSubdivision
+        ? this.data.answer.answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark)
+        : this.data.answer.answer_list.includes(mark); // 是否是正确答案
+
       if (!isHas && this.isShowRightAnswer) {
-        let isRight = this.isSubdivision
-          ? this.data.answer.answer_list[i].includes(mark)
-          : this.data.answer.answer_list.includes(mark); // 是否是正确答案
         return isRight ? ['answer-right'] : [];
       }
       // 判断是否是正确答案
       if (this.isJudgingRightWrong) {
-        let isRight = this.isSubdivision
-          ? this.data.answer.answer_list[i].includes(mark)
-          : this.data.answer.answer_list.includes(mark); // 是否是正确答案
         return isRight ? ['right'] : ['wrong'];
       }
       return [];

+ 37 - 19
src/views/exercise_questions/preview/SelectPreview.vue

@@ -12,14 +12,14 @@
     ></div>
 
     <div v-if="isEnable(data.property.is_option_subdivision)" class="option-subdivision">
-      <ul v-for="(item, i) in data.option_list" :key="i" class="option-subdivision-list">
+      <ul v-for="(item, i) in data.option_list" :key="item.mark" class="option-subdivision-list">
         <span class="serial-number">{{ computeOptionMethods[data.option_number_show_mode](i) }} </span>
         <li
-          v-for="{ content, mark } in item"
+          v-for="{ content, mark } in item.data_list"
           :key="mark"
           :style="{ cursor: disabled ? 'not-allowed' : 'pointer' }"
-          :class="['option-item', { active: isAnswer(mark, i) }, ...computedAnswerClass(mark, i)]"
-          @click="selectAnswer(mark, i)"
+          :class="['option-item', { active: isAnswer(mark, item.mark) }, ...computedAnswerClass(mark, item.mark)]"
+          @click="selectAnswer(mark, item.mark)"
         >
           <span class="selectionbox"></span>
           <span class="content rich-text" v-html="sanitizeHTML(content)"></span>
@@ -67,24 +67,43 @@ export default {
     }
   },
   methods: {
-    isAnswer(mark, i) {
+    isAnswer(mark, parent_mark) {
       if (isEnable(this.data.property.is_option_subdivision)) {
-        return this.answer.answer_list?.[i]?.includes(mark);
+        return this.answer.answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark);
       }
       return this.answer.answer_list.includes(mark);
     },
-    selectAnswer(mark, i) {
+    selectAnswer(mark, parent_mark) {
       if (this.disabled) return;
-      let answer_list = this.isSubdivision ? this.answer.answer_list[i] : this.answer.answer_list;
+      let answer_list = this.answer.answer_list;
+      let index = this.isSubdivision
+        ? answer_list.findIndex((item) => item.mark === parent_mark)
+        : answer_list.indexOf(mark);
       if (this.data.property.select_type === selectTypeList[0].value) {
         if (this.isSubdivision) {
-          this.$set(this.answer.answer_list, i, [mark]);
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            this.$set(this.answer.answer_list[index], 'value_list', [mark]);
+          }
         } else {
           this.$set(this.answer, 'answer_list', [mark]);
         }
       }
       if (this.data.property.select_type === selectTypeList[1].value) {
-        let index = answer_list.indexOf(mark);
+        if (this.isSubdivision) {
+          if (index === -1) {
+            answer_list.push({ mark: parent_mark, value_list: [mark] });
+          } else {
+            let mIndex = answer_list[index].value_list.findIndex((item) => item.mark === mark);
+            if (mIndex === -1) {
+              answer_list[index].value_list.push(mark);
+            } else {
+              answer_list[index].value_list.splice(mIndex, 1);
+            }
+          }
+          return;
+        }
         if (index === -1) {
           answer_list.push(mark);
         } else {
@@ -92,24 +111,23 @@ export default {
         }
       }
     },
-    computedAnswerClass(mark, i) {
+    computedAnswerClass(mark, parent_mark) {
       if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
         return [];
       }
+      let answer_list = this.answer.answer_list;
       let isHas = this.isSubdivision
-        ? this.answer.answer_list[i].includes(mark)
-        : this.answer.answer_list.includes(mark); // 是否已选中的选项
+        ? answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark)
+        : answer_list.includes(mark); // 是否已选中的选项
+      let isRight = this.isSubdivision
+        ? this.data.answer.answer_list.find((item) => item.mark === parent_mark)?.value_list?.includes(mark)
+        : this.data.answer.answer_list.includes(mark); // 是否是正确答案
+
       if (!isHas && this.isShowRightAnswer) {
-        let isRight = this.isSubdivision
-          ? this.data.answer.answer_list[i].includes(mark)
-          : this.data.answer.answer_list.includes(mark); // 是否是正确答案
         return isRight ? ['answer-right'] : [];
       }
       // 判断是否是正确答案
       if (this.isJudgingRightWrong) {
-        let isRight = this.isSubdivision
-          ? this.data.answer.answer_list[i].includes(mark)
-          : this.data.answer.answer_list.includes(mark); // 是否是正确答案
         return isRight ? ['right'] : ['wrong'];
       }
       return [];