Quellcode durchsuchen

阅读题和简答题的答题处理

dusenyao vor 1 Jahr
Ursprung
Commit
6cb29e8c1a

+ 3 - 3
package-lock.json

@@ -4077,9 +4077,9 @@
       }
     },
     "core-js": {
-      "version": "3.33.3",
-      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.33.3.tgz",
-      "integrity": "sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw=="
+      "version": "3.34.0",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.34.0.tgz",
+      "integrity": "sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag=="
     },
     "core-js-compat": {
       "version": "3.33.0",

+ 1 - 1
package.json

@@ -11,7 +11,7 @@
   "dependencies": {
     "@tinymce/tinymce-vue": "^3.2.8",
     "axios": "^1.6.2",
-    "core-js": "^3.33.3",
+    "core-js": "^3.34.0",
     "dompurify": "^3.0.6",
     "element-ui": "^2.15.14",
     "hanzi-writer": "^3.6.0",

+ 9 - 0
src/api/exercise.js

@@ -224,3 +224,12 @@ export function GetUserAnswerRecordList(data) {
 export function GetShareConfig(data) {
   return http.post(`${process.env.VUE_APP_FileServer}?MethodName=sys_config_manager-GetShareConfig`, data);
 }
+
+/**
+ * 结束答题
+ * @param {object} data
+ * @param {string} data.answer_record_id 答题记录id
+ */
+export function EndAnswer(data) {
+  return http.post(`/TeachingServer/ExerciseAnswerManager/EndAnswer`, data);
+}

+ 10 - 2
src/views/exercise_questions/answer/index.vue

@@ -137,6 +137,7 @@ import {
   FillQuestionAnswerRemark,
   GetAnswerRecordReport,
   GetQuestionInfo,
+  EndAnswer,
 } from '@/api/exercise';
 import { subjectiveQuestionList } from './answer';
 import { fileUpload } from '@/api/app';
@@ -329,22 +330,29 @@ export default {
         this.time -= 1;
         if (this.time === 0) {
           clearInterval(this.countDownTimer);
-          this.handleSubmitAnswer();
+          this.endAnswer();
         }
       }, 1000);
     },
+    endAnswer() {
+      EndAnswer({ answer_record_id: this.answer_record_id }).then(() => {
+        this.isSubmit = true;
+      });
+    },
     startAnswer() {
       if (!this.share_record_id) {
         this.curQuestionIndex = 0;
         return;
       }
       StartAnswer({ exercise_id: this.exercise_id, share_record_id: this.share_record_id }).then(
-        ({ answer_mode, answer_record_id }) => {
+        ({ answer_mode, answer_record_id, answer_time_limit_minute }) => {
           this.questionList = this.questionList.map((item) => ({
             ...item,
             isFill: false,
           }));
           this.answer_record_id = answer_record_id;
+          this.answer_time_limit_minute = answer_time_limit_minute;
+          this.time = answer_time_limit_minute * 60;
           this.countDown();
           this.answer_mode = answer_mode;
           this.curQuestionIndex = 0;

+ 0 - 21
src/views/exercise_questions/create/components/create.vue

@@ -70,28 +70,7 @@ import EssayQuestion from './exercises/EssayQuestion.vue';
 export default {
   name: 'CreateMain',
   components: {
-    SelectQuestion,
-    JudgeQuestion,
     SelectQuestionType,
-    MatchingQuestion,
-    FillQuestion,
-    ReadAloudQuestion,
-    ChineseQuestion,
-    WriteQuestion,
-    DialogueQuestion,
-    TalkPictureQuestion,
-    ChooseToneQuestion,
-    RepeatQuestion,
-    ReadQuestion,
-    SortQuestion,
-    ListenSelectQuestion,
-    ListenJudgeQuestion,
-    ListenFillQuestion,
-    WordCardQuestion,
-    AnswerQuestion,
-    WritePictureQuestion,
-    ReplaceAnswerQuestion,
-    EssayQuestion,
   },
   provide() {
     return {

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

@@ -170,8 +170,8 @@ export default {
         .filter((item) => item)
         .forEach((item) => {
           if (item.charCodeAt() === 10) return;
-          // 匹配 span 标签和三个以上的_,并将它们组成数组
-          let str = item.replace(/<span.*?>(.*?)<\/span>|([_]{3,})/gi, '###$1$2###');
+          // 匹配 class 名为 rich-fill 的 span 标签和三个以上的_,并将它们组成数组
+          let str = item.replace(/<span class="rich-fill".*?>(.*?)<\/span>|([_]{3,})/gi, '###$1$2###');
           this.data.model_essay.push(this.splitRichText(str));
         });
     },

+ 0 - 4
src/views/exercise_questions/create/components/exercises/ReadQuestion.vue

@@ -134,10 +134,6 @@ export default {
   name: 'ReadQuestion',
   components: {
     SelectQuestionType,
-    SelectQuestion,
-    JudgeQuestion,
-    MatchingQuestion,
-    FillQuestion,
   },
   mixins: [QuestionMixin],
   inject: ['exercise_id'],

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

@@ -94,7 +94,7 @@ export default {
     };
   },
   data() {
-    const { id } = this.$route.query;
+    const { id, back_url } = this.$route.query;
 
     return {
       exercise_id: id, // 练习id
@@ -106,6 +106,7 @@ export default {
       isSetUp: false, // 设置
       preview: false, // 预览显示
       previewData: {}, // 预览数据
+      back_url: back_url || '/personal_question', // 返回地址
     };
   },
   computed: {
@@ -127,7 +128,7 @@ export default {
   methods: {
     // 返回练习管理
     back() {
-      this.$router.push('/personal_question');
+      this.$router.push(this.back_url);
     },
     /**
      * 添加题目到练习

+ 0 - 23
src/views/exercise_questions/data/PreviewQuestionTypeMixin.js

@@ -23,29 +23,6 @@ import ReplaceAnswerPreview from '../preview/ReplaceAnswerPreview.vue';
 import EssayQuestionPreview from '../preview/EssayQuestionPreview.vue';
 
 const PreviewQuestionTypeMixin = {
-  components: {
-    SelectPreview,
-    JudgePreview,
-    MatchingPreview,
-    ChinesePreview,
-    WritePreview,
-    FillPreview,
-    ReadAloudPreview,
-    DialoguePreview,
-    TalkPictruePreview,
-    ChooseTonePreview,
-    RepeatPreview,
-    ReadPreview,
-    SortPreview,
-    ListenSelectPreview,
-    ListenFillPreview,
-    ListenJudgePreview,
-    WordCardPreview,
-    AnswerQuestionPreview,
-    WritePictruePreview,
-    ReplaceAnswerPreview,
-    EssayQuestionPreview,
-  },
   data() {
     return {
       isEnable,

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

@@ -63,9 +63,6 @@ export default {
     descriptionList() {
       return this.data.description.split(/\s+/);
     },
-    disabled() {
-      return this.isJudgingRightWrong || this.isShowRightAnswer;
-    },
   },
   watch: {
     'data.model_essay': {

+ 0 - 3
src/views/exercise_questions/preview/ListenFillPreview.vue

@@ -64,9 +64,6 @@ export default {
     descriptionList() {
       return this.data.description.split(/\s+/);
     },
-    disabled() {
-      return this.isJudgingRightWrong || this.isShowRightAnswer;
-    },
   },
   watch: {
     'data.model_essay': {

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

@@ -79,9 +79,6 @@ export default {
       }
       return arr;
     },
-    disabled() {
-      return this.isJudgingRightWrong || this.isShowRightAnswer;
-    },
   },
   watch: {
     optionList: {

+ 43 - 16
src/views/exercise_questions/preview/ReadPreview.vue

@@ -10,18 +10,18 @@
     <div class="container">
       <div class="articel" v-html="sanitizeHTML(data.article)"></div>
       <div class="question-list">
-        <div v-if="isAnswer">
+        <template v-if="isAnswer">
           <component
             :is="previewComponents[item.type]"
             v-for="(item, i) in question_list"
             :key="i"
+            ref="preview"
             class="preview"
             :data="item"
-            :answer="answer.question_list[i]"
             @change="changeAnswer(i, item.type, $event)"
           />
-        </div>
-        <div v-else>
+        </template>
+        <template v-else>
           <component
             :is="previewComponents[item.type]"
             v-for="(item, i) in childPreviewData"
@@ -30,7 +30,7 @@
             :data="item"
             @change="changeAnswer(i, item.type, $event)"
           />
-        </div>
+        </template>
       </div>
     </div>
   </div>
@@ -77,8 +77,16 @@ export default {
     isAnswer: {
       handler(val) {
         if (val) {
-          this.data.question_list.forEach(({ id }, i) => {
-            this.getQuestionInfo(id, i);
+          const promises = this.data.question_list.map(({ id }) => {
+            return GetQuestionInfo({ question_id: id });
+          });
+          Promise.all(promises).then((res) => {
+            this.question_list = res.map(({ question }) => {
+              let content = JSON.parse(question.content);
+              if (!question.content) return { answer_list: [] };
+              content.id = question.id;
+              return content;
+            });
           });
         }
       },
@@ -96,16 +104,35 @@ export default {
   },
   methods: {
     changeAnswer(i, type, { answer_list }) {
-      this.data.question_list[i].answer_list = answer_list;
-      this.data.question_list[i].type = type;
+      if (this.disabled) return;
+      this.answer.question_list[i].answer_list = answer_list;
+      this.answer.question_list[i].type = type;
+    },
+    /**
+     * 显示答案
+     * @param {Boolean} isJudgingRightWrong 是否判断对错
+     * @param {Boolean} isShowRightAnswer 是否显示正确答案
+     * @param {Object} userAnswer 用户答案
+     */
+    showAnswer(isJudgingRightWrong, isShowRightAnswer, userAnswer) {
+      this.isJudgingRightWrong = isJudgingRightWrong;
+      this.isShowRightAnswer = isShowRightAnswer;
+      if (userAnswer) this.answer = userAnswer;
+      if (this.question_list.length === this.answer.question_list.length) {
+        return this.fillAnswer(isJudgingRightWrong, isShowRightAnswer);
+      }
+      this.$watch('question_list', (val) => {
+        if (val.length !== this.answer.question_list.length) return;
+        this.fillAnswer(isJudgingRightWrong, isShowRightAnswer);
+      });
     },
-    getQuestionInfo(question_id, i) {
-      GetQuestionInfo({ question_id })
-        .then(({ question }) => {
-          if (!question.content) return;
-          this.$set(this.question_list, i, JSON.parse(question.content));
-        })
-        .catch(() => {});
+    fillAnswer(isJudgingRightWrong, isShowRightAnswer) {
+      this.answer.question_list.forEach(({ id, answer_list }) => {
+        const index = this.question_list.findIndex((item) => item.id === id);
+        if (index !== -1) {
+          this.$refs.preview[index].showAnswer(isJudgingRightWrong, isShowRightAnswer, { answer_list });
+        }
+      });
     },
   },
 };

+ 20 - 2
src/views/exercise_questions/preview/ShortAnswerPreview.vue

@@ -13,8 +13,18 @@
       :file-id="data.file_id_list[0]"
     />
 
-    <el-input v-model="answer.answer_list[0].text" type="textarea" :autosize="{ minRows: 6, maxRows: 36 }" />
+    <el-input
+      v-model="answer.answer_list[0].text"
+      :disabled="disabled"
+      type="textarea"
+      :autosize="{ minRows: 6, maxRows: 36 }"
+    />
     <SoundRecordPreview :wav-blob.sync="answer.answer_list[0].voice_file_id" />
+
+    <div v-if="disabled" class="reference-answer">
+      <div class="title">参考答案</div>
+      <div>{{ data.reference_answer }}</div>
+    </div>
   </div>
 </template>
 
@@ -42,9 +52,17 @@ export default {
   @include preview;
 
   .reference-answer {
+    display: flex;
+    flex-direction: column;
+    row-gap: 8px;
     padding: 12px 24px;
+    font-size: 14px;
+    white-space: pre;
     background-color: $content-color;
-    border-radius: 8px;
+
+    .title {
+      color: #4e5969;
+    }
   }
 }
 </style>

+ 5 - 0
src/views/exercise_questions/preview/components/PreviewMixin.js

@@ -31,6 +31,11 @@ const PreviewMixin = {
       immediate: true,
     },
   },
+  computed: {
+    disabled() {
+      return this.isJudgingRightWrong || this.isShowRightAnswer;
+    },
+  },
   methods: {
     /**
      * 获取答案

+ 11 - 1
src/views/home/personal_question/components/ShareDialog.vue

@@ -27,7 +27,7 @@
 
       <div class="condition-bottom" :style="{ 'grid-template': `30px 32px / repeat(3, 1fr)` }">
         <span>发送方式</span>
-        <el-radio-group v-model="send_type">
+        <el-radio-group v-model="send_type" @input="handleSendType">
           <el-radio v-for="{ type, name } in sendModes" :key="type" :label="type">{{ name }}</el-radio>
         </el-radio-group>
         <template v-if="send_type === sendModes[0].type">
@@ -242,6 +242,16 @@ export default {
         checked: true,
       }));
     },
+    /**
+     * 发送方式改变时处理
+     * 当发送方式为发送至课程时,访问权限只能为仅作答
+     * @param {Number} val 发送方式
+     */
+    handleSendType(val) {
+      if (val === this.sendModes[0].type) {
+        this.access_popedom = this.accessPermissions[1].type;
+      }
+    },
     dialogClose() {
       this.$emit('update:dialogVisible');
     },

+ 1 - 1
src/views/home/public_question/index.vue

@@ -20,7 +20,7 @@
           <span
             v-show="row.teacher_id === $store.state.user.user_code"
             class="link"
-            @click="$router.push({ path: '/exercise', query: { id: row.id } })"
+            @click="$router.push({ path: '/exercise', query: { id: row.id, back_url: '/' } })"
           >
             编辑
           </span>