Prechádzať zdrojové kódy

Merge branch 'master' of http://60.205.254.193:3000/GCLS/GCLS_Page_Exercise

dusenyao 1 rok pred
rodič
commit
45e4b516e6

+ 1 - 1
src/views/exercise_questions/create/components/exercises/ChooseToneQuestion.vue

@@ -238,7 +238,7 @@ export default {
     },
     handleValue(valItem) {
       let numList = [];
-      if (/[A-Za-z]+\d/g.test(valItem)) {
+      if (/[A-Za-zü]+\d/g.test(valItem)) {
         valItem.split('').forEach((item, i) => {
           if (/\d/.test(item)) {
             let numIndex = numList.length === 0 ? 0 : numList[numList.length - 1].index;

+ 5 - 1
src/views/exercise_questions/data/common.js

@@ -181,6 +181,7 @@ export const tone_data = [
   ['ī', 'í', 'ǐ', 'ì', 'i'],
   ['ū', 'ú', 'ǔ', 'ù', 'u'],
   ['ǖ', 'ǘ', 'ǚ', 'ǜ', 'ü'],
+  ['ǖ', 'ǘ', 'ǚ', 'ǜ', 'ü'],
   ['Ā', 'Á', 'Â', 'À', 'A'],
   ['Ō', 'Ó', 'Ô', 'Ò', 'O'],
   ['Ē', 'É', 'Ê', 'È', 'E'],
@@ -195,7 +196,7 @@ export const tone_data = [
  * @returns String
  */
 export function addTone(number, con) {
-  const zmList = ['a', 'o', 'e', 'i', 'u', 'v', 'A', 'O', 'E', 'I', 'U'];
+  const zmList = ['a', 'o', 'e', 'i', 'u', 'v', 'ü', 'A', 'O', 'E', 'I', 'U'];
   let cons = con;
   if (number) {
     for (let i = 0; i < zmList.length; i++) {
@@ -211,6 +212,9 @@ export function addTone(number, con) {
         } else if (/yv|jv|qv|xv/.test(con)) {
           zm2 = tone_data[4][number - 1];
           cons = con.replace('v', zm2);
+        } else if (/yü|jü|qü|xü/.test(con)) {
+          zm2 = tone_data[4][number - 1];
+          cons = con.replace('ü', zm2);
         } else {
           cons = con.replace(zm, zm2);
         }

+ 1 - 1
src/views/exercise_questions/data/essayQuestion.js

@@ -1,6 +1,6 @@
 import { stemTypeList, questionNumberTypeList, scoreTypeList, switchOption } from './common';
 
-// 朗读题数据模板
+// 问答题数据模板
 export const essayQuestionData = {
   type: 'essay_question', // 题型
   stem: '', // 题干

+ 1 - 1
src/views/exercise_questions/preview/AnswerQuestionPreview.vue

@@ -8,7 +8,7 @@
 
     <AudioPlay v-if="data.file_id_list.length > 0" :file-id="data.file_id_list[0]" />
 
-    <SoundRecordPreview :wav-blob.sync="answer.answer_list[0].audio_file_id" />
+    <SoundRecordPreview :wav-blob.sync="answer.answer_list[0].audio_file_id" :disabled="isJudgingRightWrong" />
     <div v-if="isEnable(data.property.is_enable_reference_answer) && isShowRightAnswer" class="reference-box">
       <h5 class="reference-title">参考答案</h5>
       <span class="reference-answer" v-html="sanitizeHTML(data.reference_answer)"></span>

+ 43 - 23
src/views/exercise_questions/preview/ChinesePreview.vue

@@ -1,6 +1,6 @@
 <!-- eslint-disable vue/no-v-html -->
 <template>
-  <div class="chinese-preview">
+  <div class="chinese-preview" v-if="show_preview">
     <div class="stem">
       <span class="question-number">{{ data.property.question_number }}.</span>
       <span v-html="sanitizeHTML(data.stem)"></span>
@@ -9,7 +9,7 @@
 
     <!-- 笔画学习 -->
     <div :class="['words-box', 'words-box-' + data.property.learn_type]">
-      <div v-for="(item, index) in data.option_list" :key="index" :class="['words-item']">
+      <div v-for="(item, index) in option_list" :key="index" :class="['words-item']">
         <template v-if="item.content && item.content.trim() && item.hz_strokes_list[0].strokes">
           <div
             v-if="data.property.learn_type !== 'dictation'"
@@ -55,9 +55,9 @@
             >
               <SvgIcon icon-class="hanzi-writer-bg" class="character-target-bg" />
               <img
-                v-if="!play_status && items && items.strokes_image_url"
+                v-if="!play_status && items && items.strokes_image"
                 class="hanzi-writer-img"
-                :src="items.strokes_image_url"
+                :src="items.strokes_image"
                 alt=""
               />
             </div> -->
@@ -74,13 +74,13 @@
             <div v-for="(items, indexs) in item.imgArr" :key="indexs" class="con-box">
               <div
                 :class="['strockplay-newWord', (indexs + 1) % writer_number_yuan !== 0 ? 'border-left-none' : '']"
-                @click="freeWrite(items, index, indexs, item.mark)"
+                @click="freeWrite(items ? JSON.parse(items) : null, index, indexs, item.mark)"
               >
                 <SvgIcon icon-class="hanzi-writer-bg" class="character-target-bg" />
                 <img
-                  v-if="!play_status && items && items.strokes_image_url"
+                  v-if="!play_status && items && JSON.parse(items).strokes_image"
                   class="hanzi-writer-img"
-                  :src="items.strokes_image_url"
+                  :src="JSON.parse(items).strokes_image"
                   alt=""
                 />
               </div>
@@ -96,12 +96,15 @@
           <div class="words-dic-box">
             <div v-for="(itemc, indexc) in item.imgArr" :key="indexc" class="words-dic-item">
               <span class="pinyin">{{ item.pinyin_arr[indexc].pinyin_item }}</span>
-              <div :class="['strockplay-newWord']" @click="freeWrite(itemc, index, indexc, item.mark)">
+              <div
+                :class="['strockplay-newWord']"
+                @click="freeWrite(itemc ? JSON.parse(itemc) : itemc, index, indexc, item.mark)"
+              >
                 <SvgIcon icon-class="hanzi-writer-bg" class="character-target-bg" />
                 <img
-                  v-if="!play_status && itemc && itemc.strokes_image_url"
+                  v-if="!play_status && itemc && JSON.parse(itemc).strokes_image"
                   class="hanzi-writer-img"
-                  :src="itemc.strokes_image_url"
+                  :src="JSON.parse(itemc).strokes_image"
                   alt=""
                 />
               </div>
@@ -118,6 +121,7 @@
         :curren-hz-data="current_hz_data"
         :row-index="active_index"
         :col-index="active_col_index"
+        :disabled="isJudgingRightWrong"
         @closeIfFreeShow="closeIfFreeShow"
         @changePraShow="changePraShow"
         @changeCurQue="changeCurQue"
@@ -148,7 +152,6 @@ export default {
       hanzi_color: '#404040', // 描红汉字底色
       writer_number_yuan: 19,
       writer_number: null, // 书写个数
-      answer_list: [], // 用户答题数据
       if_free_show: false,
       free_img: [],
       active_index: null,
@@ -196,6 +199,8 @@ export default {
         '素',
       ],
       active_mark: '',
+      option_list: [],
+      show_preview: false,
     };
   },
   watch: {
@@ -206,21 +211,27 @@ export default {
         }
       },
       deep: true,
+      immediate: true,
+    },
+    data: {
+      handler(val, oldVal) {
+        if (!val || this.data.type !== 'chinese') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
     },
   },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   mounted() {},
   methods: {
     // 初始化数据
     handleData() {
-      this.answer_list = [];
-      this.writer_number_yuan = Math.floor(
-        (document.getElementsByClassName('preview-content')[0].clientWidth - 128) / 64,
-      );
       this.writer_number = this.data.property.tian_number ? Number(this.data.property.tian_number) : 8;
-      this.data.option_list.forEach((item, index) => {
+      let option_list = JSON.parse(JSON.stringify(this.data.option_list));
+      option_list.forEach((item) => {
         let arr = [];
         if (this.data.property.learn_type === 'dictation') {
           item.pinyin_arr = [];
@@ -245,14 +256,23 @@ export default {
           mark: item.mark,
           strokes_content_list: arr,
         };
-        this.answer_list.push(obj);
+        if (!this.isJudgingRightWrong) {
+          this.answer.answer_list.push(obj);
+        }
       });
+      this.option_list = option_list;
+      this.show_preview = true;
+      if (document.getElementsByClassName('preview-content').length > 0) {
+        this.writer_number_yuan = Math.floor(
+          (document.getElementsByClassName('preview-content')[0].clientWidth - 128) / 64,
+        );
+      }
     },
     changePraShow() {
       this.if_free_show = false;
     },
     closeIfFreeShow(data, rowIndex, colIndex, mark) {
-      this.data.option_list[rowIndex].imgArr[colIndex] = data;
+      this.option_list[rowIndex].imgArr[colIndex] = JSON.stringify(data);
       this.if_free_show = false;
       this.freeWrite(data, rowIndex, colIndex, mark);
       this.$forceUpdate();
@@ -265,13 +285,13 @@ export default {
       if (this.data.property.learn_type === 'dictation') {
         this.current_hz = this.hz_data[index];
       } else {
-        this.current_hz = this.data.option_list[index].content;
+        this.current_hz = this.option_list[index].content;
       }
       this.current_hz_data = imgUrl;
     },
     // 删除记录
     deleteWriteRecord(rowIndex, colIndex, current_hz) {
-      this.$set(this.data.option_list[rowIndex].imgArr, colIndex, {});
+      this.$set(this.option_list[rowIndex].imgArr, colIndex, JSON.stringify({}));
       this.changeCurQue(null, colIndex, this.active_mark);
       this.current_hz_data = null;
       this.active_mark = '';
@@ -280,12 +300,12 @@ export default {
     changeCurQue(answer, colIndex, mark) {
       if (answer) {
         let write_model = [];
-        this.answer_list.forEach((itema) => {
+        this.answer.answer_list.forEach((itema) => {
           if (itema.mark === mark) {
             write_model = itema.strokes_content_list;
           }
         });
-        write_model[colIndex] = answer;
+        write_model[colIndex] = JSON.stringify(answer);
       }
     },
   },

+ 11 - 1
src/views/exercise_questions/preview/ChooseTonePreview.vue

@@ -108,8 +108,18 @@ export default {
       show_tips: false, // 是否显示答题提示
     };
   },
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'choose_tone') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   methods: {
     chooseTone(item, value, i) {

+ 34 - 13
src/views/exercise_questions/preview/EssayQuestionPreview.vue

@@ -1,6 +1,6 @@
 <!-- eslint-disable vue/no-v-html -->
 <template>
-  <div class="essayquestion-preview">
+  <div class="essayquestion-preview" v-if="show_preview">
     <div class="stem">
       <span class="question-number">{{ data.property.question_number }}.</span>
       <span v-html="sanitizeHTML(data.stem)"></span>
@@ -8,7 +8,7 @@
     <div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
 
     <el-input
-      v-model="answer.answer_list.value"
+      v-model="answer.answer_list[0].text"
       rows="12"
       resize="none"
       type="textarea"
@@ -16,16 +16,18 @@
       :maxlength="1000"
       show-word-limit
       @input="handleInput"
+      :readonly="isJudgingRightWrong"
     />
-    <SoundRecordPreview :wav-blob.sync="answer.answer_list.audio_file_id" />
+    <SoundRecordPreview :disabled="isJudgingRightWrong" :wav-blob.sync="answer.answer_list[0].audio_file_id" />
     <UploadFiles
       :fille-number="999"
       file-type-name="文件"
       :upload-type="'*'"
-      :file-id-list="answer.answer_list.accessory_file_id"
+      :file-id-list="answer.answer_list[0].accessory_file_id_list"
       upload-title="上传附件:"
       @upload="handleUpload"
       @deleteFile="handleDelete"
+      :disabled="isJudgingRightWrong"
     />
     <div v-if="isEnable(data.property.is_enable_reference_answer) && isShowRightAnswer" class="reference-box">
       <h5 class="reference-title">参考答案</h5>
@@ -48,24 +50,43 @@ export default {
   mixins: [PreviewMixin],
   data() {
     return {
-      answer: {
-        answer_list: {
-          audio_file_id: '',
-          value: '',
-          accessory_file_id: [],
-        },
-      },
+      show_preview: false,
     };
   },
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'essay_question') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {},
   methods: {
+    // 初始化数据
+    handleData() {
+      if (!this.isJudgingRightWrong) {
+        let obj = {
+          audio_file_id: '',
+          text: '',
+          accessory_file_id_list: [],
+        };
+        this.answer.answer_list.push(obj);
+      }
+      this.show_preview = true;
+    },
     // 文件上传成功
     handleUpload(fileId) {
-      this.answer.answer_list.accessory_file_id.push(fileId);
+      this.answer.answer_list[0].accessory_file_id_list.push(fileId);
     },
     // 删除文件
     handleDelete(fileId) {
-      this.answer.answer_list.accessory_file_id.splice(this.answer.answer_list.accessory_file_id.indexOf(fileId), 1);
+      this.answer.answer_list[0].accessory_file_id_list.splice(
+        this.answer.answer_list[0].accessory_file_id_list.indexOf(fileId),
+        1,
+      );
     },
     handleInput(value) {
       if (value.length >= 1000) {

+ 22 - 12
src/views/exercise_questions/preview/RepeatPreview.vue

@@ -7,7 +7,7 @@
     </div>
     <div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
     <div class="option-list">
-      <li v-for="(item, i) in answer_list" :key="i" :class="['option-item']">
+      <li v-for="(item, i) in answer.answer_list" :key="i" :class="['option-item']">
         <span>{{ computeOptionMethods[data.option_number_show_mode](i) }} </span>
         <AudioPlay v-if="data.option_list[i].audio_file_id" :file-id="data.option_list[i].audio_file_id" />
         <div
@@ -16,7 +16,7 @@
           v-html="sanitizeHTML(data.option_list[i].content)"
         ></div>
         <div class="sound-box">
-          <SoundRecordPreview :wav-blob.sync="item.audio_file_id" :type="'small'" />
+          <SoundRecordPreview :wav-blob.sync="item.audio_file_id" :disabled="isJudgingRightWrong" :type="'small'" />
         </div>
       </li>
     </div>
@@ -37,23 +37,33 @@ export default {
   data() {
     return {
       computeOptionMethods,
-      answer_list: [],
     };
   },
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'repeat') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   methods: {
     // 初始化数据
     handleData() {
-      this.answer_list = [];
-      this.data.option_list.forEach((item) => {
-        let obj = {
-          mark: item.mark,
-          audio_file_id: '',
-        };
-        this.answer_list.push(obj);
-      });
+      if (!this.isJudgingRightWrong) {
+        this.data.option_list.forEach((item) => {
+          let obj = {
+            mark: item.mark,
+            audio_file_id: '',
+          };
+          this.answer.answer_list.push(obj);
+        });
+      }
     },
   },
 };

+ 27 - 18
src/views/exercise_questions/preview/ReplaceAnswerPreview.vue

@@ -1,6 +1,6 @@
 <!-- eslint-disable vue/no-v-html -->
 <template>
-  <div class="replace-preview">
+  <div class="replace-preview" v-if="show_preview">
     <div class="stem">
       <span class="question-number">{{ data.property.question_number }}.</span>
       <span v-html="sanitizeHTML(data.stem)"></span>
@@ -16,7 +16,7 @@
           <span class="select-item select-active">{{ active_content[i] }}</span>
           <ul :ref="'ui' + i" class="replace-ul" @scroll="handleScroll($event, i)">
             <li
-              :class="[answer.answer_list[0].select_mark[i] === items.mark ? 'active' : '']"
+              :class="[computedAnswerClass(i, items)]"
               v-for="(items, indexs) in item"
               :key="indexs"
               @click="handleClickItem(i, indexs)"
@@ -27,7 +27,7 @@
         </template>
         <span v-else class="select-item">{{ item[0].content }}</span>
       </div>
-      <SoundRecordPreview :wav-blob.sync="answer.answer_list[0].audio_file_id" />
+      <SoundRecordPreview :wav-blob.sync="answer.answer_list[0].audio_file_id" :disabled="isJudgingRightWrong" />
     </div>
   </div>
 </template>
@@ -46,33 +46,39 @@ export default {
   data() {
     return {
       computeOptionMethods,
-      // answer: {
-      //   answer_list: [
-      //     {
-      //       audio_file_id: '',
-      //       mark_list: [],
-      //     },
-      //   ],
-      // },
       option_list: [],
       active_content: [],
+      show_preview: false,
     };
   },
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'replace_answer') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   mounted() {},
   methods: {
     // 初始化数据
     handleData() {
+      this.show_preview = true;
       this.option_list = [];
       this.active_content = [];
-      this.answer.answer_list = [
-        {
-          audio_file_id: '',
-          mark_list: [],
-        },
-      ];
+      if (!this.isJudgingRightWrong) {
+        this.answer.answer_list = [
+          {
+            audio_file_id: '',
+            mark_list: [],
+          },
+        ];
+      }
       let option_lists = [[], [], [], []];
       this.data.option_list.forEach((item) => {
         item.forEach((items, indexs) => {
@@ -103,6 +109,9 @@ export default {
       this.answer.answer_list[0].mark_list[i] = this.option_list[i][indexs].mark;
       this.$forceUpdate();
     },
+    computedAnswerClass(i, item) {
+      return this.answer.answer_list[0].mark_list[i] === item.mark ? 'active' : '';
+    },
   },
 };
 </script>

+ 41 - 6
src/views/exercise_questions/preview/SortPreview.vue

@@ -23,7 +23,7 @@
           :key="indexNode"
           :class="[
             'drag-item',
-            { error: !itemNode.correct && isJudgingRightWrong },
+            { error: itemNode.mark !== data.option_list[indexNode].mark && isJudgingRightWrong },
             click_index_list.indexOf(indexNode) > -1 ? 'drag-item-active' : '',
           ]"
           @click="handleClickItem(indexNode)"
@@ -44,6 +44,32 @@
         </div>
       </transition-group>
     </draggable>
+    <template v-if="isJudgingRightWrong">
+      <h4 class="right-title">正确答案:</h4>
+      <draggable
+        v-model="move_list"
+        animation="300"
+        :options="{
+          group: { name: 'itxst', pull: 'clone' },
+        }"
+        :sort="false"
+        :class="['content-box', 'content-box-' + data.property.layout_type]"
+      >
+        <transition-group>
+          <div
+            v-for="(itemNode, indexNode) in data.option_list"
+            :key="indexNode"
+            :class="[
+              'drag-item',
+              { error: itemNode.mark !== data.option_list[indexNode].mark && isJudgingRightWrong },
+              click_index_list.indexOf(indexNode) > -1 ? 'drag-item-active' : '',
+            ]"
+          >
+            <span class="drag-content" v-html="sanitizeHTML(itemNode.content)"></span>
+          </div>
+        </transition-group>
+      </draggable>
+    </template>
   </div>
 </template>
 
@@ -66,7 +92,7 @@ export default {
   watch: {
     move_list: {
       handler(val) {
-        if (!val) return;
+        if (!val || this.isJudgingRightWrong) return;
         this.answer.answer_list = val.map(({ mark }) => {
           return mark;
         });
@@ -80,7 +106,6 @@ export default {
         this.move_list = this.answer.answer_list.map((item, i) => {
           return {
             ...this.data.option_list.find((items) => items.mark === item),
-            correct: item.mark === this.data.option_list[i].mark,
           };
         });
       },
@@ -89,11 +114,10 @@ export default {
     'data.option_list': {
       handler(val) {
         if (!val) return;
+        this.disrupted = false;
         this.move_list = this.shuffle(val.slice()).map((item, i) => ({
           ...item,
-          correct: item.mark === this.data.option_list[i].mark,
         }));
-        this.disrupted = true;
       },
       deep: true,
       immediate: true,
@@ -114,6 +138,7 @@ export default {
         const j = Math.floor(Math.random() * (i + 1));
         [arr[i], arr[j]] = [arr[j], arr[i]];
       }
+      this.disrupted = true;
       return arr;
     },
     onStart() {
@@ -122,7 +147,7 @@ export default {
     // 拖拽结束事件
     onEnd() {
       this.drag = false;
-      this.changeuserAnswerJudge();
+      // this.changeuserAnswerJudge();
       this.$forceUpdate();
     },
     // 判断对错
@@ -134,6 +159,7 @@ export default {
     // 点击item
     handleClickItem(indexNode) {
       // 查看答案模式下需要禁用
+      if (this.isJudgingRightWrong) return;
       this.click_index_list.push(indexNode);
     },
     // 点击交换
@@ -159,6 +185,7 @@ export default {
       display: flex;
       column-gap: 16px;
       align-items: center;
+      max-width: 800px;
       margin-bottom: 8px;
       cursor: move;
 
@@ -217,5 +244,13 @@ export default {
       }
     }
   }
+
+  .right-title {
+    margin: 24px 0;
+    font-size: 16px;
+    font-weight: 500;
+    line-height: 24px;
+    color: #000;
+  }
 }
 </style>

+ 26 - 12
src/views/exercise_questions/preview/TalkPictruePreview.vue

@@ -17,8 +17,12 @@
         <h3 class="pic-title" v-html="sanitizeHTML(item.picture_title)"></h3>
         <p class="pic-info" v-html="sanitizeHTML(item.picture_info)"></p>
         <!-- 语音作答 -->
-        <div v-if="isEnable(data.property.is_enable_voice_answer)" class="sound-box">
-          <SoundRecordPreview :wav-blob.sync="answer_list[index].audio_file_id" type="small" />
+        <div v-if="isEnable(data.property.is_enable_voice_answer) && answer.answer_list[index]" class="sound-box">
+          <SoundRecordPreview
+            :disabled="isJudgingRightWrong"
+            :wav-blob.sync="answer.answer_list[index].audio_file_id"
+            type="small"
+          />
         </div>
 
         <div v-if="isEnable(data.property.is_enable_reference_answer) && isShowRightAnswer" class="reference-box">
@@ -45,16 +49,24 @@ export default {
     return {
       pic_list: {},
       active_index: 0,
-      answer_list: [],
     };
   },
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'talk_picture') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   methods: {
     // 初始化数据
     handleData() {
-      this.answer_list = [];
       this.pic_list = {};
       this.active_index = 0;
       this.data.file_id_list.forEach((item) => {
@@ -62,13 +74,15 @@ export default {
           this.$set(this.pic_list, file_id, file_url);
         });
       });
-      this.data.option_list.forEach((item) => {
-        let obj = {
-          mark: item.mark,
-          audio_file_id: '',
-        };
-        this.answer_list.push(obj);
-      });
+      if (!this.isJudgingRightWrong) {
+        this.data.option_list.forEach((item) => {
+          let obj = {
+            mark: item.mark,
+            audio_file_id: '',
+          };
+          this.answer.answer_list.push(obj);
+        });
+      }
     },
     changeImg(index) {
       this.active_index = index;

+ 38 - 44
src/views/exercise_questions/preview/WordCardPreview.vue

@@ -10,21 +10,25 @@
     <!-- 笔画学习 -->
     <div :class="['words-box']">
       <el-image
-        v-if="pic_list[data.option_list[active_index].picture_file_id]"
-        :src="pic_list[data.option_list[active_index].picture_file_id]"
+        v-if="
+          option_list[active_index] &&
+          option_list[active_index].picture_file_id &&
+          pic_list[option_list[active_index].picture_file_id]
+        "
+        :src="pic_list[option_list[active_index].picture_file_id]"
         fit="contain"
       />
       <div class="words-right">
         <div :class="['words-item']">
           <label
-            v-for="(item, index) in data.option_list"
+            v-for="(item, index) in option_list"
             :key="index"
             :class="[active_index === index ? 'active' : '']"
             @click="active_index = index"
             >{{ item.content }}</label
           >
         </div>
-        <template v-for="(item, index) in data.option_list">
+        <template v-for="(item, index) in option_list">
           <div class="strock-box" :key="index" v-if="index === active_index">
             <div class="strock-left" v-if="item.hz_strokes_list && item.hz_strokes_list.length > 0">
               <template v-for="(items, indexs) in item.hz_strokes_list">
@@ -49,23 +53,20 @@
           </div>
         </template>
         <el-divider></el-divider>
-        <div class="content-box">
-          <p
-            class="definition"
-            v-for="(itemd, indexd) in data.option_list[active_index].definition_preview"
-            :key="indexd"
-          >
+        <div class="content-box" v-if="option_list[active_index]">
+          <p class="definition" v-for="(itemd, indexd) in option_list[active_index].definition_preview" :key="indexd">
             {{ itemd }}
           </p>
           <span
             class="tips"
             v-if="
-              data.option_list[active_index].example_sentence[0].trim() ||
-              data.option_list[active_index].example_sentence[1].trim()
+              option_list[active_index].example_sentence &&
+              (option_list[active_index].example_sentence[0].trim() ||
+                option_list[active_index].example_sentence[1].trim())
             "
             >例句:</span
           >
-          <template v-for="(iteme, indexe) in data.option_list[active_index].example_sentence">
+          <template v-for="(iteme, indexe) in option_list[active_index].example_sentence">
             <p class="example-sentence" :key="indexe + iteme.trim()" v-if="iteme.trim()">
               <span>{{ computeOptionMethods[data.option_number_show_mode](indexe) }} </span>
               <span>{{ iteme }}</span>
@@ -73,8 +74,12 @@
           </template>
         </div>
         <el-divider></el-divider>
-        <div class="sound-box">
-          <SoundRecordPreview :wav-blob.sync="answer_list[active_index].audio_file_id" :type="'small'" />
+        <div class="sound-box" v-if="answer.answer_list[active_index]">
+          <SoundRecordPreview
+            :wav-blob.sync="answer.answer_list[active_index].audio_file_id"
+            :type="'small'"
+            :disabled="isJudgingRightWrong"
+          />
         </div>
       </div>
     </div>
@@ -97,56 +102,45 @@ export default {
       computeOptionMethods,
       hanzi_color: '#404040', // 描红汉字底色
       pic_list: {},
-      answer_list: [], // 用户答题数据
       active_index: 0,
+      option_list: [],
     };
   },
-  watch: {},
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'word_card') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   mounted() {},
   methods: {
     // 初始化数据
     handleData() {
-      this.answer_list = [];
       this.pic_list = {};
       this.data.file_id_list.forEach((item) => {
         GetFileStoreInfo({ file_id: item }).then(({ file_id, file_url }) => {
           this.$set(this.pic_list, file_id, file_url);
         });
       });
-      this.data.option_list.forEach((item) => {
+      let option_list = JSON.parse(JSON.stringify(this.data.option_list));
+      option_list.forEach((item) => {
         let obj = {
           mark: item.mark,
           audio_file_id: '',
         };
         item.definition_preview = item.definition.split('\n');
-        this.answer_list.push(obj);
-        // let content_arr = item.content.trim().split('');
-        // let content_arrs = [];
-        // let content_arr_strokes = [];
-        // content_arr.forEach((itemc) => {
-        //   if (itemc.trim()) {
-        //     content_arrs.push(itemc.trim());
-        //   }
-        // });
-        // content_arrs.forEach((itemc, indexc) => {
-        //   content_arr_strokes.push(null);
-        //   let MethodName = 'hz_resource_manager-GetHZStrokesContent';
-        //   let data = {
-        //     hz: itemc,
-        //   };
-        //   GetStaticResources(MethodName, data).then((res) => {
-        //     let obj = {
-        //       hz: itemc.trim(),
-        //       strokes: res,
-        //     };
-        //     content_arr_strokes[indexc] = obj;
-        //   });
-        // });
-        // item.content_arr_strokes = content_arr_strokes;
+        if (!this.isJudgingRightWrong) {
+          this.answer.answer_list.push(obj);
+        }
       });
+      this.option_list = option_list;
     },
   },
 };

+ 33 - 19
src/views/exercise_questions/preview/WritePictruePreview.vue

@@ -1,6 +1,6 @@
 <!-- eslint-disable vue/no-v-html -->
 <template>
-  <div class="writepicture-preview">
+  <div class="writepicture-preview" v-if="show_preview">
     <div class="stem">
       <span class="question-number">{{ data.property.question_number }}.</span>
       <span v-html="sanitizeHTML(data.stem)"></span>
@@ -26,9 +26,9 @@
       </div>
     </div>
 
-    <div class="content-right" v-if="answer_list[active_index]">
+    <div class="content-right" v-if="answer.answer_list[active_index]">
       <el-input
-        v-model="answer_list[active_index].value"
+        v-model="answer.answer_list[active_index].value"
         rows="12"
         resize="none"
         type="textarea"
@@ -36,19 +36,21 @@
         :maxlength="data.property.word_num"
         show-word-limit
         @input="handleInput"
+        :readonly="isJudgingRightWrong"
       />
     </div>
     <template v-if="isEnable(data.property.is_enable_upload_accessory)">
       <!-- 上传附件 -->
       <UploadFiles
+        :disabled="isJudgingRightWrong"
         :fille-number="999"
         file-type-name="文件"
         :upload-type="'*'"
-        :file-id-list="answer_list[active_index].accessory_file_id"
+        :file-id-list="answer.answer_list[active_index].accessory_file_id"
         upload-title="上传附件:"
         @upload="handleUpload"
         @deleteFile="handleDelete"
-        v-if="answer_list[active_index]"
+        v-if="answer.answer_list[active_index]"
       />
     </template>
     <template v-if="isEnable(data.property.is_enable_sample_text) && isShowRightAnswer">
@@ -81,16 +83,26 @@ export default {
       show_sample_text: false,
       pic_list: {},
       active_index: 0,
-      answer_list: [],
+      show_preview: false,
     };
   },
+  watch: {
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'write_picture') return;
+        this.handleData();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {
-    this.handleData();
+    // this.handleData();
   },
   methods: {
     // 初始化数据
     handleData() {
-      this.answer_list = [];
+      this.show_preview = true;
       this.pic_list = {};
       this.active_index = 0;
       this.data.file_id_list.forEach((item) => {
@@ -98,26 +110,28 @@ export default {
           this.$set(this.pic_list, file_id, file_url);
         });
       });
-      this.data.option_list.forEach((item) => {
-        let obj = {
-          mark: item.mark,
-          value: '',
-          accessory_file_id: [], // 上传文件列表
-        };
-        this.answer_list.push(obj);
-      });
+      if (!this.isJudgingRightWrong) {
+        this.data.option_list.forEach((item) => {
+          let obj = {
+            mark: item.mark,
+            value: '',
+            accessory_file_id: [], // 上传文件列表
+          };
+          this.answer.answer_list.push(obj);
+        });
+      }
     },
     changeImg(index) {
       this.active_index = index;
     },
     // 文件上传成功
     handleUpload(fileId) {
-      this.answer_list[this.active_index].accessory_file_id.push(fileId);
+      this.answer.answer_list[this.active_index].accessory_file_id.push(fileId);
     },
     // 删除文件
     handleDelete(fileId) {
-      this.answer_list[this.active_index].accessory_file_id.splice(
-        this.answer_list[this.active_index].accessory_file_id.indexOf(fileId),
+      this.answer.answer_list[this.active_index].accessory_file_id.splice(
+        this.answer.answer_list[this.active_index].accessory_file_id.indexOf(fileId),
         1,
       );
     },

+ 29 - 8
src/views/exercise_questions/preview/WritePreview.vue

@@ -12,13 +12,14 @@
       v-html="sanitizeHTML(data.description)"
     ></div>
     <el-input
-      v-model="user_answer.text"
+      v-model="answer.answer_list[0].text"
       rows="3"
       type="textarea"
       placeholder="请输入内容"
       :maxlength="data.property.word_num"
       show-word-limit
       @input="handleInput"
+      :readonly="isJudgingRightWrong"
     />
 
     <template v-if="isEnable(data.property.is_enable_upload_accessory)">
@@ -27,10 +28,11 @@
         :fille-number="999"
         file-type-name="文件"
         :upload-type="'*'"
-        :file-id-list="user_answer.accessory_file_id"
+        :file-id-list="answer.answer_list[0].accessory_file_id_list"
         upload-title="上传附件:"
         @upload="handleUpload"
         @deleteFile="handleDelete"
+        :disabled="isJudgingRightWrong"
       />
     </template>
     <template v-if="isEnable(data.property.is_enable_sample_text) && isShowRightAnswer">
@@ -59,21 +61,40 @@ export default {
   data() {
     return {
       show_sample_text: false,
-      user_answer: {
-        text: '', // 用户文章
-        accessory_file_id: [], // 上传文件列表
-      },
     };
   },
+  watch: {
+    isJudgingRightWrong: {
+      handler(val) {
+        if (!val) {
+          this.answer.answer_list.push({
+            text: '', // 用户文章
+            accessory_file_id_list: [], // 上传文件列表
+          });
+        }
+      },
+      immediate: true,
+    },
+    data: {
+      handler(val) {
+        if (!val || this.data.type !== 'write') return;
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
   created() {},
   methods: {
     // 文件上传成功
     handleUpload(fileId) {
-      this.user_answer.accessory_file_id.push(fileId);
+      this.answer.answer_list[0].accessory_file_id_list.push(fileId);
     },
     // 删除文件
     handleDelete(fileId) {
-      this.user_answer.accessory_file_id.splice(this.user_answer.accessory_file_id.indexOf(fileId), 1);
+      this.answer.answer_list[0].accessory_file_id_list.splice(
+        this.answer.answer_list[0].accessory_file_id_list.indexOf(fileId),
+        1,
+      );
     },
     handleInput(value) {
       if (value.length >= this.data.property.word_num) {

+ 16 - 11
src/views/exercise_questions/preview/components/common/FreewriteLettle.vue

@@ -4,8 +4,8 @@
     <div class="right-content">
       <SvgIcon icon-class="hanzi-writer-bg" class="character-target-bg" />
       <div class="right-strockred">
-        <template v-if="!hasPlay && data && data.strokes_image_url">
-          <img class="img" :src="data.strokes_image_url" alt="" />
+        <template v-if="!hasPlay && data && data.strokes_image">
+          <img class="img" :src="data.strokes_image" alt="" />
         </template>
         <FreeWriteQP
           id="esign"
@@ -18,13 +18,13 @@
           :width="width"
           class="vueEsign"
         />
-        <a class="clean-btn" @click="resetHuahua">
+        <a class="clean-btn" @click="resetHuahua" v-if="!disabled">
           <SvgIcon icon-class="reset" class="reset-btn" />
         </a>
       </div>
       <ul class="nav-list">
         <li :class="currenHzData && currenHzData.history ? '' : 'disabled'" @click="play()">播放</li>
-        <li @click="handleWriteImg">保存</li>
+        <li @click="handleWriteImg" :class="disabled ? 'disabled' : ''">保存</li>
       </ul>
     </div>
   </div>
@@ -48,7 +48,7 @@ export default {
     currenHzData: {
       type: Object,
       default: () => ({
-        strokes_image_url: '',
+        strokes_image: '',
         history: [],
       }),
     },
@@ -60,6 +60,10 @@ export default {
       type: Number,
       default: 0,
     },
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
   },
   data() {
     return {
@@ -89,7 +93,7 @@ export default {
     let color = _this.colorsList[_this.colorIndex];
     _this.hanzicolor = color;
     _this.hanziweight = 6;
-    if (_this.currenHzData && _this.currenHzData.strokes_image_url) {
+    if (_this.currenHzData && _this.currenHzData.strokes_image) {
       _this.imgOrCans = true;
     }
     _this.data = JSON.parse(JSON.stringify(_this.currenHzData));
@@ -155,7 +159,7 @@ export default {
       _this.imgOrCans = false;
       _this.$refs.esign.reset();
       if (_this.data) {
-        _this.data.strokes_image_url = '';
+        _this.data.strokes_image = '';
       }
       _this.$emit('deleteWriteRecord', _this.rowIndex, _this.colIndex, _this.currentHz);
       // this.removeImage();
@@ -176,6 +180,7 @@ export default {
     },
     // 不保存到记录列表
     handleWriteImg() {
+      if (this.disabled) return;
       if (this.$refs.esign.history.length === 0) return;
       this.$refs.esign.generate().then((res) => {
         let Book_img = res.replace('data:image/png;base64,', '');
@@ -184,12 +189,12 @@ export default {
         answer = {
           hz: this.currentHz,
           strokes_content: JSON.stringify(this.$refs.esign.history),
-          strokes_image_url: write_img,
+          strokes_image: write_img,
         };
         this.$emit('changeCurQue', answer, this.colIndex);
         let obj = {
           history: this.$refs.esign.history,
-          strokes_image_url: write_img,
+          strokes_image: write_img,
         };
         this.$emit('closeIfFreeShow', obj, this.rowIndex, this.colIndex);
         // this.$message.warning("请先书写在保存");
@@ -206,7 +211,7 @@ export default {
           answer = {
             hz: this.currentHz,
             strokes_content: JSON.stringify(this.$refs.esign.history),
-            strokes_image_url: write_img,
+            strokes_image: write_img,
           };
           this.$emit('changeCurQue', answer, this.colIndex);
 
@@ -214,7 +219,7 @@ export default {
           let obj = {
             hz_handwritten_record_id: res.hz_handwritten_record_id,
             history: this.$refs.esign.history,
-            strokes_image_url: write_img,
+            strokes_image: write_img,
           };
           this.$emit('closeIfFreeShow', obj, this.rowIndex, this.colIndex);
         })

+ 5 - 0
src/views/exercise_questions/preview/components/common/SoundRecordPreview.vue

@@ -53,6 +53,10 @@ export default {
       type: String,
       default: 'big',
     },
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
   },
   data() {
     return {
@@ -148,6 +152,7 @@ export default {
         this.$refs.audio.pause();
         this.audio.paused = true;
       }
+      if (this.disabled) return;
       if (this.microphoneStatus) {
         this.hasMicro = 'normal';
         this.recorder.stop();

+ 1 - 1
src/views/exercise_questions/preview/components/common/Strockplayredline.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="strockplay-redInner">
+  <div class="strockplay-redInner" v-if="bookText">
     <div v-if="playStorkes" :class="['strock-play-box']" @click="playHanzi">
       <SvgIcon icon-class="hanzi-strock-play" class="strock-play-btn" />
     </div>

+ 5 - 0
src/views/exercise_questions/preview/components/common/UploadFiles.vue

@@ -10,6 +10,7 @@
       :before-upload="beforeUpload"
       :http-request="upload"
       :on-exceed="handleExceed"
+      :disabled="disabled"
     >
       <div class="upload-audio">
         <span>上传{{ fileTypeName }}</span>
@@ -65,6 +66,10 @@ export default {
       type: String,
       default: '',
     },
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
   },
   data() {
     return {