Pārlūkot izejas kodu

解决一些问题,做了预览容错处理

dusenyao 1 gadu atpakaļ
vecāks
revīzija
2c7c2e6fd4

+ 11 - 4
src/views/exercise_questions/create/components/create.vue

@@ -90,7 +90,7 @@ export default {
   },
   data() {
     return {
-      timer: '',
+      timer: null,
       curSaveDate: '',
       exerciseTypeList,
       exerciseComponents: {
@@ -116,15 +116,22 @@ export default {
     },
   },
   mounted() {
-    this.timer = setInterval(() => {
-      this.saveQuestion();
-    }, 30000);
+    this.resetSaveDate();
   },
   beforeDestroy() {
     this.saveQuestion();
     clearInterval(this.timer);
   },
   methods: {
+    // 重置保存时间
+    resetSaveDate() {
+      if (this.timer) {
+        clearInterval(this.timer);
+      }
+      this.timer = setInterval(() => {
+        this.saveQuestion();
+      }, 30000);
+    },
     /**
      * 选择练习
      * @param {Number} i 练习索引

+ 39 - 0
src/views/exercise_questions/create/components/exercises/DialogueQuestion.vue

@@ -115,6 +115,7 @@
 <script>
 import QuestionMixin from '../common/QuestionMixin.js';
 
+import { getRandomNumber } from '@/utils';
 import { dialogueData } from '@/views/exercise_questions/data/dialogue';
 
 export default {
@@ -125,6 +126,44 @@ export default {
       data: JSON.parse(JSON.stringify(dialogueData)),
     };
   },
+  watch: {
+    'data.dialogue': {
+      handler(val) {
+        if (!val) return;
+
+        let direction = 'row';
+        let preName = '';
+        this.data.option_list = val
+          // 用换行分割 data.dialogue
+          .split('\n')
+          // 过滤掉空行
+          .filter((item) => item.trim() !== '')
+          .map((item) => {
+            // 分割对话中的人物和对话内容
+            const match = item.match(/(\S+)[::](.+)/);
+            if (match) {
+              let name = match[1];
+              if (preName.length === 0 || preName !== name) {
+                direction = preName.length === 0 ? 'row' : direction === 'row' ? 'row-reverse' : 'row';
+              }
+              preName = name;
+              let content = match[2];
+              let isFill = /^_{3,}$/.test(content);
+
+              return {
+                name,
+                content: isFill ? '' : content,
+                direction,
+                audio_file_id: '',
+                mark: isFill ? getRandomNumber() : '',
+                type: isFill ? 'input' : 'text',
+              };
+            }
+          })
+          .filter((item) => item);
+      },
+    },
+  },
   methods: {},
 };
 </script>

+ 2 - 2
src/views/exercise_questions/create/components/exercises/FillQuestion.vue

@@ -181,7 +181,7 @@ export default {
         if (index === -1) break;
         matchNum += 1;
         arr.push({ content: _str.slice(start, index), type: 'text' });
-        if (matchNum % 2 === 0 && arr.length > 1) {
+        if (matchNum % 2 === 0 && arr.length > 0) {
           arr[arr.length - 1].type = 'input';
           let mark = getRandomNumber();
           arr[arr.length - 1].mark = mark;
@@ -198,7 +198,7 @@ export default {
         }
         start = index + 3;
       }
-      let last = _str.slice(start, -1);
+      let last = _str.slice(start);
       if (last) {
         arr.push({ content: last, type: 'text' });
       }

+ 11 - 6
src/views/exercise_questions/create/components/exercises/MatchingQuestion.vue

@@ -126,6 +126,17 @@ export default {
       data: getMatchingDataTemplate(),
     };
   },
+  watch: {
+    'data.option_list': {
+      handler(val) {
+        if (!val) return;
+        this.data.answer.answer_list = val.map((item) => {
+          return item.map(({ mark }) => mark);
+        });
+      },
+      deep: true,
+    },
+  },
   methods: {
     addOption() {
       let newOption = [];
@@ -134,11 +145,6 @@ export default {
       }
       this.data.option_list.push(newOption);
     },
-    setAnswerColumnList() {
-      this.data.answer.column_list = this.data.option_list.map((item) => {
-        return item.map(({ mark }) => mark);
-      });
-    },
     /**
      * 修改列数后,修改选项列表
      * @param {Number} val 列数
@@ -155,7 +161,6 @@ export default {
         }
         return item;
       });
-      this.setAnswerColumnList();
     },
   },
 };

+ 2 - 0
src/views/exercise_questions/create/index.vue

@@ -196,6 +196,7 @@ export default {
           if (question.content) {
             this.$nextTick(() => {
               this.$refs.createMain.$refs.exercise?.[0].setQuestion(question);
+              this.refreshPreviewData();
             });
           }
         })
@@ -228,6 +229,7 @@ export default {
     selectExerciseItem(index, data) {
       if (index < 0 || index > this.index_list.length - 1) return;
       this.curIndex = index;
+      this.$refs.createMain.resetSaveDate();
       this.$refs.createMain.saveQuestion(data);
     },
     // 设置

+ 2 - 1
src/views/exercise_questions/data/dialogue.js

@@ -6,7 +6,8 @@ export const dialogueData = {
   stem: '', // 题干
   reference_answer: '', // 参考答案
   description: '', // 描述
-  dialogue: '', // 对话内容
+  dialogue: '', // 对话内容,用于编辑显示
+  option_list: [], // 选项
   answer: { score: 0, score_type: scoreTypeList[0].value }, // 答案
   // 题型属性
   property: {

+ 3 - 3
src/views/exercise_questions/data/matching.js

@@ -13,13 +13,13 @@ export function getOption(content = '') {
 
 /**
  * 获取连线题数据模板
- * 因为 option_list 和 answer.column_list 中的数据是一一对应的,所以需要函数生成来保持一致
+ * 因为 option_list 和 answer.answer_list 中的数据是一一对应的,所以需要函数生成来保持一致
  */
 export function getMatchingDataTemplate() {
   let option_list = Array.from({ length: 3 }, () =>
     Array.from({ length: columnNumberList[0].value }, () => getOption()),
   );
-  let column_list = option_list.map((item) => item.map(({ mark }) => mark));
+  let answer_list = option_list.map((item) => item.map(({ mark }) => mark));
 
   return {
     type: 'matching', // 题型
@@ -27,7 +27,7 @@ export function getMatchingDataTemplate() {
     option_number_show_mode: optionTypeList[0].value, // 选项类型
     description: '', // 描述
     option_list, // 选项
-    answer: { column_list, score: 0, score_type: scoreTypeList[0].value }, // 答案
+    answer: { answer_list, score: 0, score_type: scoreTypeList[0].value }, // 答案
     // 题型属性
     property: {
       stem_type: stemTypeList[0].value, // 题干类型

+ 16 - 48
src/views/exercise_questions/preview/DialoguePreview.vue

@@ -8,16 +8,23 @@
     <div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
     <div class="dialogue-wrapper">
       <ul>
-        <li v-for="(item, i) in dialogue" :key="i" :style="{ flexDirection: item.dir }" class="dialogue-item">
-          <span class="name" :style="{ backgroundColor: item.dir === 'row' ? '#4F73F4' : '#3ABD38' }">
+        <li
+          v-for="(item, i) in data.option_list"
+          :key="i"
+          :style="{ flexDirection: item.direction }"
+          class="dialogue-item"
+        >
+          <span class="name" :style="{ backgroundColor: item.direction === 'row' ? '#4F73F4' : '#3ABD38' }">
             {{ item.name }}
           </span>
-          <div class="content" :style="{ backgroundColor: item.dir === 'row' ? '#fff' : '#d0f3de' }">
+          <div class="content" :style="{ backgroundColor: item.direction === 'row' ? '#fff' : '#d0f3de' }">
             <template v-if="item.type === 'text'">
               {{ item.content }}
             </template>
             <template v-else>
-              <el-input v-model="item.content" :class="[item.dir === 'row' ? 'is_left' : 'is_right']" /><span>。</span>
+              <el-input v-model="item.content" :class="[item.direction === 'row' ? 'is_left' : 'is_right']" /><span
+                >。</span
+              >
             </template>
           </div>
           <SoundRecordPreview v-if="item.type === 'input'" :wav-blob.sync="item.audio_file_id" type="small" />
@@ -28,8 +35,6 @@
 </template>
 
 <script>
-import { getRandomNumber } from '@/utils';
-
 import PreviewMixin from './components/PreviewMixin';
 import SoundRecordPreview from './components/common/SoundRecordPreview.vue';
 
@@ -40,50 +45,13 @@ export default {
   },
   mixins: [PreviewMixin],
   data() {
-    return {
-      dialogue: [], // 对话列表
-    };
+    return {};
   },
   watch: {
-    'data.dialogue': {
-      handler() {
-        let dir = 'row';
-        let preName = '';
-        this.dialogue = this.data.dialogue
-          // 用换行分割 this.data.dialogue
-          .split('\n')
-          // 过滤掉空行
-          .filter((item) => item.trim() !== '')
-          .map((item) => {
-            // 分割对话中的人物和对话内容
-            const match = item.match(/(\S+)[::](.+)/);
-            if (match) {
-              let name = match[1];
-              if (preName.length === 0 || preName !== name) {
-                dir = preName.length === 0 ? 'row' : dir === 'row' ? 'row-reverse' : 'row';
-              }
-              preName = name;
-              let content = match[2];
-              let isFill = /_{3,}/.test(content);
-
-              return {
-                name,
-                content: isFill ? '' : content,
-                dir,
-                audio_file_id: '',
-                mark: isFill ? getRandomNumber() : '',
-                type: isFill ? 'input' : 'text',
-              };
-            }
-          })
-          .filter((item) => item);
-      },
-      deep: true,
-      immediate: true,
-    },
-    dialogue: {
-      handler() {
-        this.answer.answer_list = this.dialogue
+    'data.option_list': {
+      handler(val) {
+        if (!val) return;
+        this.answer.answer_list = val
           .map(({ type, mark, content, audio_file_id }) => {
             if (type === 'text') return;
             return {

+ 1 - 0
src/views/exercise_questions/preview/FillPreview.vue

@@ -35,6 +35,7 @@ export default {
   watch: {
     'data.model_essay': {
       handler(val) {
+        if (!val) return;
         this.answer.answer_list = val
           .map((item) => {
             return item

+ 2 - 3
src/views/exercise_questions/preview/MatchingPreview.vue

@@ -43,7 +43,6 @@ export default {
     return {
       answerList: [], // 答案列表
       curConnectionPoint: { i: -1, j: -1, position: 'pre', mark: '' }, // 当前连线点
-      connectionList: [], // 连接线列表
       // 拖拽相关
       drag: false,
       mousePointer: { i: -1, j: -1, position: 'pre', mark: '' },
@@ -67,9 +66,9 @@ export default {
   },
   watch: {
     optionList: {
-      handler() {
+      handler(val) {
         this.clearLine();
-
+        if (!val) return;
         let list = this.optionList.map((item) => {
           return item.map(({ mark }) => {
             return { mark, preMark: '', nextMark: '' };