Selaa lähdekoodia

简答题和套题

Michael Wang 6 vuotta sitten
vanhempi
commit
c3e989740e

+ 10 - 0
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -54,6 +54,16 @@ export default {
     );
     this.examQuestionList = examQuestionList.data;
 
+    // 初始化套题的答案,为回填部分选项做准备
+    // 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

+ 1 - 1
src/features/OnlineExam/Examing/FillBlankQuestionView.vue

@@ -58,7 +58,7 @@ export default {
       document
         .querySelectorAll(".option input")
         .forEach(e => (ans += e.value + "##"));
-      console.log(ans);
+      // console.log(ans);
       this.stuAnswer = ans.slice(0, -2);
       const answers = this.stuAnswer.split("##");
       this.questionBody = this.question.body.replace(

+ 98 - 0
src/features/OnlineExam/Examing/NestedQuestionView.vue

@@ -0,0 +1,98 @@
+<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'">
+      <single-question-view :question="subQuestion" :examQuestion="examQuestion" />
+    </template>
+    <template v-if="subQuestion.questionType === 'MULTIPLE_ANSWER_QUESTION'">
+      <multiple-question-view :question="subQuestion" :examQuestion="examQuestion" />
+    </template>
+    <template v-if="subQuestion.questionType === 'BOOL_ANSWER_QUESTION'">
+      <boolean-question-view :question="subQuestion" :examQuestion="examQuestion" />
+    </template>
+    <template v-if="subQuestion.questionType === 'FILL_BLANK_QUESTION'">
+      <fill-blank-question-view :question="subQuestion" :examQuestion="examQuestion" />
+    </template>
+    <template v-if="subQuestion.questionType === 'TEXT_ANSWER_QUESTION'">
+      <text-question-view :question="subQuestion" :examQuestion="examQuestion" />
+    </template>
+  </div>
+</template>
+
+<script>
+import SingleQuestionView from "./SingleQuestionView";
+import MultipleQuestionView from "./MultipleQuestionView";
+import BooleanQuestionView from "./BooleanQuestionView";
+import FillBlankQuestionView from "./FillBlankQuestionView";
+import TextQuestionView from "./TextQuestionView";
+
+export default {
+  name: "NestedQuestionView",
+  data() {
+    return {
+      subQuestion: this.question.subQuestionList[
+        this.examQuestion.subNumber - 1
+      ]
+    };
+  },
+  props: {
+    question: Object,
+    examQuestion: Object
+  },
+  methods: {
+    answerQuestion: function() {
+      this.$http.put("/api/exam_question/" + this.examQuestion.id, {
+        stuAnswer: this.stuAnswer
+      });
+    },
+    resetQuestion: function(examQuestionId) {
+      this.stuAnswer = "";
+      this.$http.put("/api/exam_question/" + examQuestionId, {
+        stuAnswer: null
+      });
+    }
+  },
+  watch: {},
+  components: {
+    SingleQuestionView,
+    MultipleQuestionView,
+    BooleanQuestionView,
+    FillBlankQuestionView,
+    TextQuestionView
+  }
+};
+</script>
+
+<style scoped>
+.question-view {
+  display: block;
+}
+
+.ops {
+  display: flex;
+  align-items: flex-end;
+}
+
+.stu-answer {
+  width: 100px;
+  border-bottom: 1px solid black;
+}
+
+.option {
+  display: flex;
+}
+.question-options {
+  text-align: left;
+  padding-left: 10px;
+}
+</style>

+ 19 - 8
src/features/OnlineExam/Examing/QuestionView.vue

@@ -14,6 +14,12 @@
     <template v-if="question.questionType === 'FILL_BLANK_QUESTION'">
       <fill-blank-question-view :question="question" :examQuestion="examQuestion" />
     </template>
+    <template v-if="question.questionType === 'TEXT_ANSWER_QUESTION'">
+      <text-question-view :question="question" :examQuestion="examQuestion" />
+    </template>
+    <template v-if="question.parentQuestion !== null">
+      <nested-question-view :question="question" :examQuestion="examQuestion" />
+    </template>
   </div>
 </template>
 
@@ -22,6 +28,8 @@ import SingleQuestionView from "./SingleQuestionView";
 import MultipleQuestionView from "./MultipleQuestionView";
 import BooleanQuestionView from "./BooleanQuestionView";
 import FillBlankQuestionView from "./FillBlankQuestionView";
+import TextQuestionView from "./TextQuestionView";
+import NestedQuestionView from "./NestedQuestionView";
 
 export default {
   name: "QuestionView",
@@ -40,7 +48,8 @@ export default {
       }
       const res = await this.$http.get(
         "/api/exam_question/question/?question_id=" +
-          this.examQuestion.questionId
+          (this.examQuestion.questionId ||
+            this.examQuestion.parentQuestion.questionId)
       );
       const question = res.data;
       const examQuestion = this.examQuestion;
@@ -56,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 "__" + (baseIndex + parseInt(b)) + "__";
+          //   });
           // repQuestion.body = $sce.trustAsHtml(repQuestion.body);
         }
       };
@@ -122,7 +131,9 @@ export default {
     SingleQuestionView,
     MultipleQuestionView,
     BooleanQuestionView,
-    FillBlankQuestionView
+    FillBlankQuestionView,
+    TextQuestionView,
+    NestedQuestionView
   }
 };
 </script>

+ 103 - 0
src/features/OnlineExam/Examing/TextQuestionView.vue

@@ -0,0 +1,103 @@
+<template>
+  <div class="question-view">
+    <div class="question-body" v-html="questionBody"></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>
+
+  </div>
+</template>
+
+<script>
+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)
+    };
+  },
+  props: {
+    question: Object,
+    examQuestion: Object
+  },
+  methods: {
+    answerQuestion: function(examQuestionId, stuAnswer) {
+      this.stuAnswer = stuAnswer;
+      this.$http.put("/api/exam_question/" + examQuestionId, { stuAnswer });
+    },
+    resetQuestion: function(examQuestionId) {
+      this.stuAnswer = "##".repeat(this.questionNumber - 1);
+      setTimeout(this.inputAnswer, 100);
+      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 =
+    }
+  }
+};
+</script>
+
+<style scoped>
+.question-view {
+  display: block;
+}
+
+.ops {
+  display: flex;
+  align-items: flex-end;
+}
+
+.stu-answer {
+  width: 100px;
+  border-bottom: 1px solid black;
+}
+
+.option {
+  /* display: flex; */
+}
+.question-options {
+  text-align: left;
+  padding-left: 10px;
+}
+</style>