Michael Wang 6 лет назад
Родитель
Сommit
383bed39c2

+ 36 - 0
src/features/OnlineExam/Examing/ArrowNavView.vue

@@ -0,0 +1,36 @@
+<template>
+  <div>
+    <div class="prev">
+      <template v-if="previousExamQuestion">
+        <router-link :to="{ path: '/online-exam/exam/' + this.$route.params.examId, query: { 'examRecordId': this.$route.query.examRecordId, 'examQuestionId': previousExamQuestion.id }}">上一题</router-link>
+      </template>
+
+      <template v-else>
+        <div>上一题</div>
+      </template>
+    </div>
+    <div class="next">
+      <template v-if="nextExamQuestion">
+        <router-link :to="{ path: '/online-exam/exam/' + this.$route.params.examId, query: { 'examRecordId': this.$route.query.examRecordId, 'examQuestionId': nextExamQuestion.id }}">下一题</router-link>
+      </template>
+
+      <template v-else>
+        <div>下一题</div>
+      </template>
+    </div>
+
+  </div>
+</template>
+
+<script>
+export default {
+  name: "ArrowNavView",
+  data() {
+    return {};
+  },
+  props: {
+    previousExamQuestion: Object,
+    nextExamQuestion: Object
+  }
+};
+</script>

+ 57 - 34
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -2,12 +2,13 @@
   <div class="container">
     <div class="header">
       <RemainTime></RemainTime>
-      <OverallProgress :exam-question-list="examQuestionList"></OverallProgress>
-      <QuestionFilters :exam-question-list="examQuestionList"></QuestionFilters>
+      <OverallProgress :exam-question-list="validQuestions"></OverallProgress>
+      <QuestionFilters :exam-question-list="validQuestions"></QuestionFilters>
       <Button class="qm-primary-button">交卷</Button>
     </div>
     <div class="main">
       <QuestionView :exam-question="examQuestion"></QuestionView>
+      <ArrowNavView :previous-exam-question="preExamQuestion" :next-exam-question="nextExamQuestion"></ArrowNavView>
     </div>
     <div class="side">
       <div class="question-nav">
@@ -25,60 +26,82 @@ import RemainTime from "./RemainTime.vue";
 import OverallProgress from "./OverallProgress.vue";
 import QuestionFilters from "./QuestionFilters.vue";
 import QuestionView from "./QuestionView.vue";
+import ArrowNavView from "./ArrowNavView.vue";
 
 export default {
+  name: "ExamingHome",
   data() {
     return {
       exam: null,
       paperStruct: null,
+      validQuestions: [],
       examQuestionList: [],
+      preExamQuestion: null,
+      nextExamQuestion: null,
       examQuestion: null
     };
   },
   async mounted() {
-    const exam = await this.$http.get(
-      "/api/ecs_exam_work/exam/" + this.$route.params.examId
-    );
-    this.exam = exam.data;
+    this.init();
+  },
+  beforeRouteUpdate(to, from, next) {
+    this.init();
+    next();
+  },
+  methods: {
+    init: async function() {
+      const exam = await this.$http.get(
+        "/api/ecs_exam_work/exam/" + this.$route.params.examId
+      );
+      this.exam = exam.data;
 
-    const paperStruct = await this.$http.get(
-      "/api/exam_question/paper_struct/?exam_record_id=" +
-        this.$route.query.examRecordId
-    );
-    this.paperStruct = paperStruct.data;
+      const paperStruct = await this.$http.get(
+        "/api/exam_question/paper_struct/?exam_record_id=" +
+          this.$route.query.examRecordId
+      );
+      this.paperStruct = paperStruct.data;
 
-    // FIXME: global API processing. mock or not
-    const examQuestionList = await this.$http.get(
-      "/api/mock/exam_question/?exam_record_id=" +
-        this.$route.query.examRecordId
-    );
-    this.examQuestionList = examQuestionList.data;
+      // FIXME: global API processing. mock or not
+      const examQuestionList = await this.$http.get(
+        "/api/mock/exam_question/?exam_record_id=" +
+          this.$route.query.examRecordId
+      );
+      this.examQuestionList = examQuestionList.data;
+      this.validQuestions = this.examQuestionList.filter(
+        q => q.nestedQuestion === false
+      );
 
-    // 初始化套题的答案,为回填部分选项做准备
-    // for (let q of this.examQuestionList) {
-    //   if (q.subQuestionList.length > 0) {
-    //     q.stuAnswer = [];
-    //     for (let sq of q.subQuestionList) {
-    //       q.stuAnswer.push(sq.stuAnswer);
-    //     }
-    //   }
-    // }
+      // 初始化套题的答案,为回填部分选项做准备
+      // for (let q of this.examQuestionList) {
+      //   if (q.subQuestionList.length > 0) {
+      //     q.stuAnswer = [];
+      //     for (let sq of q.subQuestionList) {
+      //       q.stuAnswer.push(sq.stuAnswer);
+      //     }
+      //   }
+      // }
 
-    if (!this.$route.query.examQuestionId) {
-      this.$router.push(
-        this.$route.fullPath + "&examQuestionId=" + this.examQuestionList[0].id
+      if (!this.$route.query.examQuestionId) {
+        this.$router.push(
+          this.$route.fullPath +
+            "&examQuestionId=" +
+            this.examQuestionList[0].id
+        );
+        return;
+      }
+      this.examQuestion = this.examQuestionList.find(
+        eq => eq.id == this.$route.query.examQuestionId // number == string
       );
-      return;
+      this.preExamQuestion = this.validQuestions[this.examQuestion.orders - 2];
+      this.nextExamQuestion = this.validQuestions[this.examQuestion.orders];
     }
-    this.examQuestion = this.examQuestionList.find(
-      eq => eq.id == this.$route.query.examQuestionId // number == string
-    );
   },
   components: {
     RemainTime,
     OverallProgress,
     QuestionFilters,
-    QuestionView
+    QuestionView,
+    ArrowNavView
   }
 };
 </script>

+ 11 - 21
src/features/OnlineExam/Examing/NestedQuestionView.vue

@@ -1,29 +1,19 @@
 <template>
   <div class="question-view">
     <div class="question-body" v-html="question.body"></div>
-    <!-- <div class="ops">
-      <div class="stu-answer"> {{stuAnswer}}</div>
-      <i-button @click="resetQuestion(examQuestion.id)">重置</i-button>
-      <div class="score">({{question.questionScore}}分)</div>
-    </div>
-    <div v-for="(option, index) in question.options" :key="option.id" class="option" @click="toggleAnswer(index)">
-      <input type="checkbox" name="question" value="optionName[index]" :checked="stuAnswer.includes(optionName[index])" />
-      <span>{{optionName[index]}}: </span>
-      <span class="question-options" v-html="option.content"></span>
-    </div> -->
-    <template v-if="subQuestion.questionType === 'SINGLE_ANSWER_QUESTION'">
+    <template v-if="subQuestion && subQuestion.questionType === 'SINGLE_ANSWER_QUESTION'">
       <single-question-view :question="subQuestion" :examQuestion="examQuestion" />
     </template>
-    <template v-if="subQuestion.questionType === 'MULTIPLE_ANSWER_QUESTION'">
+    <template v-if="subQuestion && subQuestion.questionType === 'MULTIPLE_ANSWER_QUESTION'">
       <multiple-question-view :question="subQuestion" :examQuestion="examQuestion" />
     </template>
-    <template v-if="subQuestion.questionType === 'BOOL_ANSWER_QUESTION'">
+    <template v-if="subQuestion && subQuestion.questionType === 'BOOL_ANSWER_QUESTION'">
       <boolean-question-view :question="subQuestion" :examQuestion="examQuestion" />
     </template>
-    <template v-if="subQuestion.questionType === 'FILL_BLANK_QUESTION'">
+    <template v-if="subQuestion && subQuestion.questionType === 'FILL_BLANK_QUESTION'">
       <fill-blank-question-view :question="subQuestion" :examQuestion="examQuestion" />
     </template>
-    <template v-if="subQuestion.questionType === 'TEXT_ANSWER_QUESTION'">
+    <template v-if="subQuestion && subQuestion.questionType === 'TEXT_ANSWER_QUESTION'">
       <text-question-view :question="subQuestion" :examQuestion="examQuestion" />
     </template>
   </div>
@@ -39,11 +29,7 @@ import TextQuestionView from "./TextQuestionView";
 export default {
   name: "NestedQuestionView",
   data() {
-    return {
-      subQuestion: this.question.subQuestionList[
-        this.examQuestion.subNumber - 1
-      ]
-    };
+    return {};
   },
   props: {
     question: Object,
@@ -62,7 +48,11 @@ export default {
       });
     }
   },
-  watch: {},
+  computed: {
+    subQuestion: function() {
+      return this.question.subQuestionList[this.examQuestion.subNumber - 1];
+    }
+  },
   components: {
     SingleQuestionView,
     MultipleQuestionView,

+ 7 - 7
src/features/OnlineExam/Examing/QuestionView.vue

@@ -17,7 +17,7 @@
     <template v-if="question.questionType === 'TEXT_ANSWER_QUESTION'">
       <text-question-view :question="question" :examQuestion="examQuestion" />
     </template>
-    <template v-if="question.parentQuestion !== null">
+    <template v-if="examQuestion.parentQuestion">
       <nested-question-view :question="question" :examQuestion="examQuestion" />
     </template>
   </div>
@@ -65,12 +65,12 @@ export default {
             .toString()
             .replace(new RegExp("###", "g"), "_______");
           //将题干中的两个##数字##替换为下划线
-          // var baseIndex = examQuestion.orders - 1;
-          // repQuestion.body = repQuestion.body
-          //   .toString()
-          //   .replace(/##(\d+)##/g, function(a, b) {
-          //     return "__" + (baseIndex + parseInt(b)) + "__";
-          //   });
+          var baseIndex = examQuestion.orders - 1;
+          repQuestion.body = repQuestion.body
+            .toString()
+            .replace(/##(\d+)##/g, function(a, b) {
+              return "__" + parseInt(b) + "__";
+            });
           // repQuestion.body = $sce.trustAsHtml(repQuestion.body);
         }
       };

+ 9 - 46
src/features/OnlineExam/Examing/TextQuestionView.vue

@@ -1,13 +1,12 @@
 <template>
   <div class="question-view">
-    <div class="question-body" v-html="questionBody"></div>
+    <div class="question-body" v-html="question.body"></div>
     <div class="ops">
       <i-button @click="resetQuestion(examQuestion.id)">重置</i-button>
       <div class="score">({{question.questionScore}}分)</div>
     </div>
-    <div v-for="(option, index) in stuAnswer.split('##')" :key="index" class="option">
-      <span class="question-options">{{index+1}}. </span>
-      <input type="text" name="question" :value="option" @input="inputAnswer" />
+    <div class="option">
+      <input :model="stuAnswer" type="text" name="question" />
     </div>
 
   </div>
@@ -18,22 +17,8 @@ const optionName = ["A", "B", "C", "D", "E", "F"];
 export default {
   name: "TextQuestionView",
   data() {
-    const questionNumber = this.question.body.split(/_{5,}/).length - 1;
-
-    const answers = this.examQuestion.stuAnswer
-      ? this.examQuestion.stuAnswer.split("##")
-      : "##".repeat(questionNumber - 1).split("##");
-    let questionBody = this.question.body.replace(
-      /_{5,}/g,
-      () =>
-        "<span style='display: inline-block; min-width: 80px; border-bottom: 1px solid black'>" +
-        (answers.shift() || questionNumber - answers.length) +
-        "</span>"
-    );
     return {
-      questionNumber,
-      questionBody,
-      stuAnswer: this.examQuestion.stuAnswer || "##".repeat(questionNumber - 1)
+      stuAnswer: this.examQuestion.stuAnswer
     };
   },
   props: {
@@ -41,38 +26,16 @@ export default {
     examQuestion: Object
   },
   methods: {
-    answerQuestion: function(examQuestionId, stuAnswer) {
-      this.stuAnswer = stuAnswer;
-      this.$http.put("/api/exam_question/" + examQuestionId, { stuAnswer });
+    answerQuestion: function(examQuestionId) {
+      this.$http.put("/api/exam_question/" + examQuestionId, {
+        stuAnswer: this.stuAnswer
+      });
     },
     resetQuestion: function(examQuestionId) {
-      this.stuAnswer = "##".repeat(this.questionNumber - 1);
-      setTimeout(this.inputAnswer, 100);
+      this.stuAnswer = null;
       this.$http.put("/api/exam_question/" + examQuestionId, {
         stuAnswer: null
       });
-    },
-    inputAnswer: function(e) {
-      const questionNumber = this.question.body.split(/_{5,}/).length - 1;
-      let ans = "";
-      document
-        .querySelectorAll(".option input")
-        .forEach(e => (ans += e.value + "##"));
-      console.log(ans);
-      this.stuAnswer = ans.slice(0, -2);
-      const answers = this.stuAnswer.split("##");
-      this.questionBody = this.question.body.replace(
-        /_{5,}/g,
-        () =>
-          "<span style='display: inline-block; min-width: 80px; border-bottom: 1px solid black'>" +
-          (answers.shift() || questionNumber - answers.length) +
-          "</span>"
-      );
-    }
-  },
-  watch: {
-    stuAnswer: function() {
-      // question.body =
     }
   }
 };