Explorar el Código

答题格式修改

dusenyao hace 1 año
padre
commit
14f9e3395c

+ 2 - 2
src/views/exercise_questions/create/components/common/SoundRecord.vue

@@ -132,11 +132,11 @@ export default {
         let reader = new window.FileReader();
         reader.readAsDataURL(wav);
         reader.onloadend = () => {
-          this.$emit('updataWav', this.itemIndex, reader.result, Math.floor(tolTime));
+          this.$emit('updateWav', this.itemIndex, reader.result, Math.floor(tolTime));
         };
       } else {
         this.hasMicro = '';
-        this.$emit('updataWav', this.itemIndex, '', 0);
+        this.$emit('updateWav', this.itemIndex, '', 0);
         // 开始录音
         this.recorder.start();
         this.microphoneStatus = true;

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

@@ -49,7 +49,7 @@
               :record-time="item.audio_wav_time"
               :item-index="i"
               @deleteWav="deleteWav"
-              @updataWav="updataWav"
+              @updateWav="updateWav"
             />
             <SvgIcon icon-class="delete" class="delete pointer" @click="deleteOption(i, item.audio_file_id)" />
           </li>
@@ -192,7 +192,7 @@ export default {
       this.data.option_list[index].audio_wav_time = 0;
     },
     // 更新录音内容和时间
-    updataWav(index, wav, time) {
+    updateWav(index, wav, time) {
       this.data.option_list[index].audio_wav = wav;
       this.data.option_list[index].audio_wav_time = time;
     },

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

@@ -52,9 +52,9 @@
         <div v-if="data.answer.answer_list.length > 0" class="correct-answer">
           <div class="subtitle">正确答案</div>
           <el-input
-            v-for="(item, i) in data.answer.answer_list.filter(({ type }) => type === 'underline')"
+            v-for="(item, i) in data.answer.answer_list.filter(({ type }) => type === 'any_one')"
             :key="item.mark"
-            v-model="item.content"
+            v-model="item.value"
           >
             <span slot="prefix">{{ i + 1 }}.</span>
           </el-input>
@@ -120,16 +120,6 @@
         <el-form-item label-width="45px">
           <el-input v-model="data.property.score" type="number" />
         </el-form-item>
-        <el-form-item label="语音作答">
-          <el-radio
-            v-for="{ value, label } in switchOption"
-            :key="value"
-            v-model="data.property.is_enable_voice_answer"
-            :label="value"
-          >
-            {{ label }}
-          </el-radio>
-        </el-form-item>
       </el-form>
     </template>
   </QuestionBase>
@@ -199,9 +189,9 @@ export default {
           // 设置答案数组
           let isUnderline = /^_{3,}$/.test(content);
           this.data.answer.answer_list.push({
-            content: isUnderline ? '' : content,
+            value: isUnderline ? '' : content,
             mark,
-            type: isUnderline ? 'underline' : 'input',
+            type: isUnderline ? 'any_one' : 'only_one',
           });
           // 将 content 设置为空,为预览准备
           arr[arr.length - 1].content = '';

+ 0 - 1
src/views/exercise_questions/data/fill.js

@@ -15,7 +15,6 @@ export const fillData = {
     question_number: 1, // 题号
     is_enable_listening: switchOption[0].value, // 是否听力
     is_enable_description: switchOption[1].value, // 描述
-    is_enable_voice_answer: switchOption[1].value, // 语音作答
     score: 1, // 分值
     score_type: scoreTypeList[0].value, // 分值类型
   },

+ 93 - 4
src/views/exercise_questions/preview/DialoguePreview.vue

@@ -6,18 +6,87 @@
       <span v-html="sanitizeHTML(data.stem)"></span>
     </div>
     <div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
-    <div class="dialogue">{{ data.dialogue }}</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">{{ item.name }}</span>
+          <div class="content">
+            <template v-if="item.type === 'text'">
+              {{ item.content }}
+            </template>
+            <template v-else>
+              <el-input v-model="item.content" />
+            </template>
+          </div>
+        </li>
+      </ul>
+    </div>
   </div>
 </template>
 
 <script>
+import { getRandomNumber } from '@/utils';
 import PreviewMixin from './components/PreviewMixin';
 
 export default {
   name: 'DialoguePreview',
   mixins: [PreviewMixin],
   data() {
-    return {};
+    return {
+      dialogue: [], // 对话列表
+    };
+  },
+  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,
+                mark: isFill ? getRandomNumber() : '',
+                type: isFill ? 'input' : 'text',
+              };
+            }
+          })
+          .filter((item) => item);
+      },
+      deep: true,
+      immediate: true,
+    },
+    dialogue: {
+      handler() {
+        this.answer.answer_list = this.dialogue
+          .map(({ type, mark, content }) => {
+            if (type === 'text') return;
+            return {
+              content,
+              mark,
+            };
+          })
+          .filter((item) => item);
+      },
+      deep: true,
+      immediate: true,
+    },
   },
   methods: {},
 };
@@ -29,8 +98,28 @@ export default {
 .dialogue-preview {
   @include preview;
 
-  .dialogue {
-    white-space: pre-line;
+  .dialogue-wrapper {
+    padding: 24px;
+    background-color: #f9f8f9;
+    border-radius: 16px;
+
+    ul {
+      display: flex;
+      flex-direction: column;
+      row-gap: 24px;
+
+      .dialogue-item {
+        display: flex;
+        column-gap: 16px;
+
+        .content {
+          padding: 8px 16px;
+          color: #000;
+          background-color: #fff;
+          border-radius: 8px;
+        }
+      }
+    }
   }
 }
 </style>

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

@@ -41,7 +41,7 @@ export default {
               .map(({ type, content, mark }) => {
                 if (type === 'input') {
                   return {
-                    content,
+                    value: content,
                     mark,
                   };
                 }

+ 33 - 2
src/views/exercise_questions/preview/ReadAloudPreview.vue

@@ -8,19 +8,50 @@
     <div v-if="isEnable(data.property.is_enable_reference_answer)" class="reference-answer">
       {{ data.reference_answer }}
     </div>
+    <SoundRecordPreview
+      :wav-blob="user_answer.voice_file_id"
+      :record-time="user_answer.audio_wav_time"
+      @deleteWav="deleteWav"
+      @updateWav="updateWav"
+    />
   </div>
 </template>
 
 <script>
 import PreviewMixin from './components/PreviewMixin';
+import SoundRecordPreview from './components/common/SoundRecordPreview.vue';
 
 export default {
   name: 'ReadAloudPreview',
+  components: {
+    SoundRecordPreview,
+  },
   mixins: [PreviewMixin],
   data() {
-    return {};
+    return {
+      user_answer: {
+        text: '', // 用户文章
+        voice_file_id: '', // 录音文件id
+        audio_wav_time: 0, // 录音时间
+        accessory_file_id: [], // 上传文件列表
+      },
+    };
+  },
+  watch: {
+    'user_answer.voice_file_id'(val) {
+      this.answer.file_id = val;
+    },
+  },
+  methods: {
+    deleteWav() {
+      this.user_answer.voice_file_id = '';
+      this.user_answer.audio_wav_time = 0;
+    },
+    updateWav(wav, time) {
+      this.user_answer.voice_file_id = wav;
+      this.user_answer.audio_wav_time = time;
+    },
   },
-  methods: {},
 };
 </script>
 

+ 2 - 2
src/views/exercise_questions/preview/WritePreview.vue

@@ -21,7 +21,7 @@
         :wav-blob="user_answer.voice_file_id"
         :record-time="user_answer.audio_wav_time"
         @deleteWav="deleteWav"
-        @updataWav="updataWav"
+        @updateWav="updateWav"
       />
     </template>
     <template v-if="isEnable(data.property.is_enable_upload_accessory)">
@@ -74,7 +74,7 @@ export default {
       this.user_answer.audio_wav_time = 0;
     },
     // 更新录音内容和时间
-    updataWav(wav, time) {
+    updateWav(wav, time) {
       this.user_answer.voice_file_id = wav;
       this.user_answer.audio_wav_time = time;
     },

+ 2 - 3
src/views/exercise_questions/preview/components/common/SoundRecordPreview.vue

@@ -66,7 +66,6 @@ export default {
       return this.audio.paused ? 'play-fill' : 'pause';
     },
   },
-  watch: {},
   mounted() {
     this.$refs.audio.addEventListener('ended', () => {
       this.audio.paused = true;
@@ -138,11 +137,11 @@ export default {
         let reader = new window.FileReader();
         reader.readAsDataURL(wav);
         reader.onloadend = () => {
-          this.$emit('updataWav', reader.result, Math.floor(tolTime));
+          this.$emit('updateWav', reader.result, Math.floor(tolTime));
         };
       } else {
         this.hasMicro = '';
-        this.$emit('updataWav', '', 0);
+        this.$emit('updateWav', '', 0);
         // 开始录音
         this.recorder.start();
         this.microphoneStatus = true;