Переглянути джерело

修复离线考试;单选题和多选题选项乱序

Michael Wang 6 роки тому
батько
коміт
d4e70fe3eb

+ 4 - 2
src/features/OfflineExam/OfflineExamHome.vue

@@ -6,7 +6,7 @@
     </Breadcrumb>
 
     <div class="home">
-      <ecs-offline-list :courses="courses" @reload-list="fetchData"></ecs-offline-list>
+      <ecs-offline-list :courses="courses" @reloadList="fetchData"></ecs-offline-list>
     </div>
   </main-layout>
 </template>
@@ -26,7 +26,9 @@ export default {
   },
   methods: {
     async fetchData() {
-      const res = await this.$http.get("/api/offline_exam/getOfflineCourse");
+      const res = await this.$http.get(
+        "/api/ecs_oe_student/offlineExam/getOfflineCourse"
+      );
 
       this.courses = res.data.map(c => ({
         examRecordDataId: c.examRecordDataId,

+ 4 - 3
src/features/OfflineExam/OfflineExamList.vue

@@ -18,7 +18,8 @@
           <td>
             <div v-if="course.fileUrl">
               <a :href="course.fileUrl" download>
-                <i-icon type="ios-cloud-download"></i-icon>下载作答</a>
+                <i-icon type="ios-cloud-download"></i-icon>下载作答
+              </a>
             </div>
             <div v-else>
               未上传
@@ -34,7 +35,7 @@
                 <i-button class="qm-primary-button">
                   <a class="qm-primary-button" href="https://ecs-static.qmth.com.cn/offline-exam/答题卡.zip" download>下载答题卡</a>
                 </i-button>
-                <ecs-offline-exam-upload :course="course" @reload-list="$emit('reload-list')"></ecs-offline-exam-upload>
+                <ecs-offline-exam-upload :course="course" @reloadList="$emit('reloadList')"></ecs-offline-exam-upload>
               </div>
 
               <div v-else style="display: grid; grid-gap: 10px">
@@ -73,7 +74,7 @@ export default {
   },
   methods: {
     async enterExam(course) {
-      await this.$http.get("/api/offline_exam/start", {
+      await this.$http.get("/api/ecs_oe_student/offlineExam/startOfflineExam", {
         params: { examStudentId: course.examStudentId }
       });
       this.$emit("reloadList");

+ 6 - 4
src/features/OfflineExam/OfflineExamUpload.vue

@@ -1,10 +1,10 @@
 <template>
   <div>
-    <Upload :headers="headers" :data="{fileType: fileType}" :before-upload="handleBeforeUpload" :action="'/api/offline_exam/'+course.examRecordDataId+'/submit'" :max-size="1024*30" :format="['pdf','zip']" :on-format-error="handleFormatError" :on-exceeded-size="handleMaxSize" :on-success="handleSuccess" :on-error="handleError" :show-upload-list="false">
-      <Button type="ghost" icon="ios-cloud-upload-outline" class="qm-primary-button" style="width: 100%;">上传作答</Button>
+    <Upload :headers="headers" :data="{fileType: fileType}" :before-upload="handleBeforeUpload" :action="'/api/ecs_oe_student/offlineExam/submitPaper?examRecordDataId='+course.examRecordDataId" :max-size="1024*30" :format="['pdf','zip']" :on-format-error="handleFormatError" :on-exceeded-size="handleMaxSize" :on-success="handleSuccess" :on-error="handleError" :show-upload-list="false">
+      <Button icon="ios-cloud-upload-outline" class="qm-primary-button" style="width: 100%;">上传作答</Button>
     </Upload>
     <div v-if="file !== null">待上传文件: {{ file.name }}
-      <Button type="text" :loading="loadingStatus">{{ loadingStatus ? '上传中...' : '上传' }}</Button>
+      <Button :loading="loadingStatus">{{ loadingStatus ? '上传中...' : '上传' }}</Button>
     </div>
   </div>
 </template>
@@ -42,6 +42,8 @@ export default {
             return "image/jpeg";
           case "504B0304":
             return "application/zip";
+          case "504B34":
+            return "application/zip";
           default:
             return "Unknown filetype";
         }
@@ -87,7 +89,7 @@ export default {
       this.file = null;
       this.loadingStatus = false;
       this.$Message.success("上传成功");
-      this.$emit("reload-list");
+      this.$emit("reloadList");
     },
     handleError() {
       this.file = null;

+ 14 - 6
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -151,12 +151,20 @@ export default {
     },
     async realSubmitPaper() {
       this.toggleSnapNow();
-      await this.$http.get("/api/ecs_oe_student/examControl/endExam");
-      this.$router.push({
-        path: `/online-exam/exam/${this.$route.params.examId}/examRecordData/${
-          this.$route.params.examRecordDataId
-        }/end`
-      });
+      try {
+        const res = await this.$http.get(
+          "/api/ecs_oe_student/examControl/endExam"
+        );
+        if (res.status === 200) {
+          this.$router.push({
+            path: `/online-exam/exam/${
+              this.$route.params.examId
+            }/examRecordData/${this.$route.params.examRecordDataId}/end`
+          });
+        }
+      } catch (e) {
+        console.log(e);
+      }
     },
     examQuestion() {
       return (

+ 43 - 26
src/features/OnlineExam/Examing/MultipleQuestionView.vue

@@ -2,16 +2,16 @@
   <div class="question-view">
     <question-body :questionBody="question.body" :examQuestionId="examQuestion.id"></question-body>
     <div class="ops">
-      <div class="stu-answer"> {{studentAnswer}}</div>
+      <div class="stu-answer"> {{oldIndexToABCD}}</div>
       <div class="score">({{examQuestion.questionScore}}分)</div>
     </div>
-    <div v-for="(option, index) in question.questionOptionList" :key="option.id" class="option" @click="toggleAnswer(index)">
-      <input type="checkbox" name="question" value="optionName[index]" :checked="studentAnswer && studentAnswer.includes(optionName[index])" />
+    <div v-for="(option, index) in newQuestionOptions" :key="index" class="option" @click="toggleAnswer(option.oldIndex)">
+      <input type="checkbox" name="question" value="option.oldIndex" :checked="studentAnswer && studentAnswer.includes(option.oldIndex)" />
       <span style="padding: 0 10px;">{{optionName[index]}}: </span>
-      <span class="question-options" v-html="option.body"></span>
+      <span class="question-options" v-html="option.value.body"></span>
     </div>
     <div class="reset">
-      <i-button type="warning" size="large" @click="() => answerQuestion(examQuestion.id, null)">重置答案</i-button>
+      <i-button type="warning" size="large" @click="() => answerQuestion(null)">重置答案</i-button>
     </div>
   </div>
 </template>
@@ -26,6 +26,7 @@ export default {
   name: "MultipleQuestionView",
   data() {
     return {
+      questionBody: this.question.body,
       optionName,
       studentAnswer: this.examQuestion.studentAnswer || ""
     };
@@ -41,13 +42,11 @@ export default {
     window.removeEventListener("keyup", this.keyup);
   },
   beforeUpdate() {
-    this.answerQuestion(this.examQuestion.id, this.studentAnswer);
+    this.answerQuestion(this.studentAnswer);
   },
   methods: {
     ...mapMutations(["updateExamQuestion"]),
     keyup(e) {
-      // console.log(e);
-      // console.log(document.activeElement.type);
       if (
         ["BODY", "A", "BUTTON", "DIV"].includes(
           document.activeElement.tagName
@@ -60,11 +59,17 @@ export default {
             .slice(0, this.question.questionOptionList.length)
             .includes(e.code)
         ) {
-          if (this.studentAnswer.includes(e.code[3])) {
-            this.studentAnswer = this.studentAnswer.replace(e.code[3], "");
+          const selectedOldIndex =
+            "" +
+            this.newQuestionOptions.find(v => v.name == e.code[3]).oldIndex;
+          if (this.studentAnswer.includes(selectedOldIndex)) {
+            this.studentAnswer = this.studentAnswer.replace(
+              selectedOldIndex,
+              ""
+            );
           } else {
             this.studentAnswer = this.studentAnswer
-              .concat(e.code[3])
+              .concat(selectedOldIndex)
               .split("")
               .sort()
               .join("");
@@ -72,33 +77,23 @@ export default {
         }
       }
     },
-    toggleAnswer: function(index) {
-      if (this.studentAnswer.includes(optionName[index])) {
-        this.studentAnswer = this.studentAnswer.replace(optionName[index], "");
+    toggleAnswer: function(selectedOldIndex) {
+      if (this.studentAnswer.includes(selectedOldIndex)) {
+        this.studentAnswer = this.studentAnswer.replace(selectedOldIndex, "");
       } else {
         this.studentAnswer = this.studentAnswer
-          .concat(optionName[index])
+          .concat(selectedOldIndex)
           .split("")
           .sort()
           .join("");
       }
-      // this.answerQuestion(this.examQuestion.id, this.studentAnswer);
     },
-    async answerQuestion(examQuestionId, studentAnswer) {
+    async answerQuestion(studentAnswer) {
       let realAnswer = studentAnswer;
       if (studentAnswer === "") {
         realAnswer = null;
       }
       if (realAnswer !== this.examQuestion.studentAnswer) {
-        // await this.$http.post(
-        //   "/api/ecs_oe_student/examQuestion/submitQuestionAnswer",
-        //   [
-        //     {
-        //       order: this.examQuestion.order,
-        //       studentAnswer: realAnswer
-        //     }
-        //   ]
-        // );
         this.updateExamQuestion({
           order: this.$route.params.order,
           studentAnswer: realAnswer
@@ -111,6 +106,28 @@ export default {
       this.studentAnswer = this.examQuestion.studentAnswer || "";
     }
   },
+  computed: {
+    newQuestionOptions() {
+      return this.question.questionOptionList.map((v, i) => {
+        return {
+          value: this.question.questionOptionList[
+            this.examQuestion.optionPermutation[i]
+          ],
+          oldIndex: "" + this.examQuestion.optionPermutation[i],
+          name: optionName[i]
+        };
+      });
+    },
+    oldIndexToABCD() {
+      return (
+        this.examQuestion.studentAnswer &&
+        this.newQuestionOptions
+          .filter(v => this.examQuestion.studentAnswer.includes(v.oldIndex))
+          .map(v => v.name)
+          .join("")
+      );
+    }
+  },
   components: {
     QuestionBody
   }

+ 25 - 22
src/features/OnlineExam/Examing/SingleQuestionView.vue

@@ -2,13 +2,13 @@
   <div class="question-view">
     <question-body :questionBody="questionBody" :examQuestionId="examQuestion.id"></question-body>
     <div class="ops">
-      <div class="stu-answer">{{studentAnswer}}</div>
+      <div class="stu-answer">{{oldIndexToABCD}}</div>
       <div class="score">({{examQuestion.questionScore}}分)</div>
     </div>
-    <div v-for="(option, index) in question.questionOptionList" :key="option.id" class="option" @click="() => answerQuestion(optionName[index])">
-      <input type="radio" name="question" value="optionName[index]" :checked="studentAnswer === optionName[index]" />
+    <div v-for="(option, index) in newQuestionOptions" :key="index" class="option" @click="() => {answerQuestion(option.oldIndex);}">
+      <input type="radio" name="question" :value="option.oldIndex" :checked="studentAnswer === option.oldIndex" />
       <span style="padding: 0 10px;">{{optionName[index]}}: </span>
-      <span class="question-options" v-html="option.body"></span>
+      <span class="question-options" v-html="option.value.body"></span>
     </div>
     <div class="reset">
       <i-button type="warning" size="large" @click="() => answerQuestion(null)">重置答案</i-button>
@@ -19,7 +19,7 @@
 <script>
 import QuestionBody from "./QuestionBody";
 import { createNamespacedHelpers } from "vuex";
-const { mapState, mapMutations } = createNamespacedHelpers("examingHomeModule");
+const { mapMutations } = createNamespacedHelpers("examingHomeModule");
 
 const optionName = ["A", "B", "C", "D", "E", "F"];
 export default {
@@ -59,21 +59,14 @@ export default {
             .slice(0, this.question.questionOptionList.length)
             .includes(e.code)
         ) {
-          this.studentAnswer = e.code[3];
+          this.studentAnswer = this.newQuestionOptions.find(
+            v => v.name == e.code[3]
+          ).oldIndex;
         }
       }
     },
     async answerQuestion(studentAnswer) {
       if (studentAnswer !== this.examQuestion.studentAnswer) {
-        // await this.$http.post(
-        //   "/api/ecs_oe_student/examQuestion/submitQuestionAnswer",
-        //   [
-        //     {
-        //       order: this.examQuestion.order,
-        //       studentAnswer: studentAnswer
-        //     }
-        //   ]
-        // );
         this.updateExamQuestion({
           order: this.$route.params.order,
           studentAnswer
@@ -90,15 +83,25 @@ export default {
     }
   },
   computed: {
-    ...mapState(["paperStruct"]),
     newQuestionOptions() {
-      // TODO: 更换选项,取得paperstruct对应的值
-      const per = this.paperStruct.defaultPaper.questionGruopList[
-        this.examQuestion.order
-      ].questionUnitWrapperList[0].optionPermutation;
-      return this.question.questionOptionList.map((value, index) => {
-        return { value, oldIndex: index, newIndex: per[index] };
+      return this.question.questionOptionList.map((v, i) => {
+        return {
+          value: this.question.questionOptionList[
+            this.examQuestion.optionPermutation[i]
+          ],
+          oldIndex: "" + this.examQuestion.optionPermutation[i],
+          name: optionName[i]
+        };
       });
+    },
+    oldIndexToABCD() {
+      return (
+        this.examQuestion.studentAnswer &&
+        this.newQuestionOptions
+          .filter(v => this.examQuestion.studentAnswer.includes(v.oldIndex))
+          .map(v => v.name)
+          .join("")
+      );
     }
   },
   components: {

+ 4 - 0
src/features/OnlinePractice/OnlinePracticeHome.vue

@@ -65,6 +65,10 @@ export default {
       "/api/ecs_exam_work/exam/queryByNameLike?name=&examType=PRACTICE"
     );
     this.examList = res.data;
+    if (this.examList[0]) {
+      this.examId = this.examList[0].id;
+      await this.fetchList(this.examId);
+    }
   },
   methods: {
     async fetchList(examId) {