Bläddra i källkod

添加填空题

Michael Wang 3 år sedan
förälder
incheckning
03874a8e78

+ 0 - 5
src/features/OnlineExam/Examing/BooleanQuestionView.vue

@@ -102,11 +102,6 @@ const optionWithNames = { true: "正确", false: "错误" };
   grid-row-gap: 10px;
 }
 
-.question-body {
-  font-size: 18px;
-  /* margin-bottom: 10px; */
-}
-
 .ops {
   display: flex;
   align-items: flex-end;

+ 0 - 5
src/features/OnlineExam/Examing/ChoiceQuestionView.vue

@@ -155,11 +155,6 @@ function answerQuestion(studentAnswer: string) {
   grid-row-gap: 10px;
 }
 
-.question-body {
-  font-size: 18px;
-  /* margin-bottom: 10px; */
-}
-
 .ops {
   display: flex;
   align-items: flex-end;

+ 125 - 0
src/features/OnlineExam/Examing/FillBlankQuestionView.vue

@@ -0,0 +1,125 @@
+<script setup lang="ts">
+import { store } from "@/store/store";
+import QuestionBody from "./QuestionBody.vue";
+
+let isShowAnswer = $ref(false);
+function toggleShowAnswer() {
+  isShowAnswer = !isShowAnswer;
+}
+
+const examQuestion = $computed(() => store.exam.currentQuestion);
+const rightAnswerTransform = $computed(() => {
+  return (
+    examQuestion.rightAnswer &&
+    examQuestion.rightAnswer
+      .join("")
+      .split("##")
+      .map((v, i) => `${i + 1}、${v}<br>`)
+      .join("")
+  );
+});
+
+const questionBody = $computed(() => {
+  let len = 0;
+  return examQuestion.body.replace(
+    /_{5,}/g,
+    () =>
+      "<span style='display: inline-block; min-width: 80px; border-bottom: 1px solid black; text-align: center'>" +
+      (answerSplited[len++]?.replace(/</g, "&lt;").replace(/>/g, "&gt;") ||
+        `(${len})`) +
+      "</span>"
+  );
+});
+
+const inputNumber = $computed(() => {
+  return examQuestion.body.match(/_{5,}/g)!.length;
+});
+
+const answerSplited = $computed(() => {
+  return examQuestion.studentAnswer?.split("##") ?? [];
+});
+
+function inputAnswer(e: Event, index: number) {
+  const newAnswer = [...answerSplited];
+  const ele = <HTMLInputElement>e.target;
+  newAnswer[index] = ele.value;
+  examQuestion.studentAnswer = newAnswer.join("##");
+
+  store.updateExamQuestion({
+    order: examQuestion.order,
+    studentAnswer: examQuestion.studentAnswer,
+  });
+}
+</script>
+
+<template>
+  <div class="question-view">
+    <QuestionBody :questionBody="questionBody" />
+    <div class="ops">
+      <div class="score">({{ examQuestion.questionScore }}分)</div>
+    </div>
+    <div
+      v-for="(option, index) in inputNumber"
+      :key="examQuestion.questionId + index"
+      class="option"
+    >
+      <span class="question-options">{{ index + 1 }}. </span>
+      <input
+        type="text"
+        maxlength="5000"
+        name="question"
+        class="input-answer"
+        :value="answerSplited[index]"
+        @input="(e) => inputAnswer(e, index)"
+      />
+    </div>
+    <div class="reset">
+      <span v-if="store.examShouldShowAnswer">
+        <n-button type="success" @click="toggleShowAnswer"> 显示答案 </n-button>
+      </span>
+      <div v-if="isShowAnswer">
+        正确答案:
+        <div class="right-answer-section" v-html="rightAnswerTransform"></div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.question-view {
+  display: grid;
+  grid-row-gap: 10px;
+}
+
+.ops {
+  display: flex;
+  align-items: flex-end;
+}
+
+.stu-answer {
+  width: 100px;
+  border-bottom: 1px solid black;
+  text-align: center;
+}
+
+.option {
+  display: flex;
+  line-height: 24px;
+}
+.input-answer {
+  width: 400px;
+  height: 30px;
+  border: 1px solid black;
+  border-radius: 5px;
+  padding: 0px 2px;
+}
+.question-options {
+  padding-right: 10px;
+}
+</style>
+
+<style>
+div.right-answer-section > p {
+  display: inline;
+}
+</style>

+ 8 - 0
src/features/OnlineExam/Examing/QuestionBody.vue

@@ -100,6 +100,14 @@ function getAudioPlayedTimes(name: string) {
 </template>
 
 <style>
+.question-body {
+  font-size: 18px;
+}
+
+.question-body img {
+  display: inline-block;
+}
+
 .audio-div {
   display: inline-flex;
   align-items: center;

+ 7 - 16
src/features/OnlineExam/Examing/QuestionViewSingle.vue

@@ -2,7 +2,7 @@
 import { store } from "@/store/store";
 import ChoiceQuestionView from "./ChoiceQuestionView.vue";
 import BooleanQuestionView from "./BooleanQuestionView.vue";
-// import FillBlankQuestionView from "./FillBlankQuestionView";
+import FillBlankQuestionView from "./FillBlankQuestionView.vue";
 // import TextQuestionView from "./TextQuestionView";
 
 const examQuestion = $computed(() => store.exam.currentQuestion);
@@ -27,21 +27,12 @@ const examQuestion = $computed(() => store.exam.currentQuestion);
         v-if="examQuestion.questionType === 'TRUE_OR_FALSE'"
         :key="examQuestion.order"
       />
-      <!--
-      <template
-        v-if="
-          question &&
-          question.questionType === 'FILL_UP' &&
-          examQuestion.questionType === 'FILL_UP'
-        "
-      >
-        <fill-blank-question-view
-          :key="examQuestion.order"
-          :question="question"
-          :examQuestion="examQuestion"
-        />
-      </template>
-      <template
+      <FillBlankQuestionView
+        v-if="examQuestion.questionType === 'FILL_UP'"
+        :key="examQuestion.order"
+      />
+
+      <!--<template
         v-if="
           question &&
           question.questionType === 'ESSAY' &&

+ 1 - 1
src/store/store.ts

@@ -112,7 +112,7 @@ export const useStore = defineStore("ecs", {
       store.exam.examQuestionList.map((eq) => {
         if (eq.order == order) {
           const upEq: typeof eq = {} as any;
-          // 仅设置getQuestionContent时,不更新dirty
+          // 仅设置getQuestionContent时,不更新dirty
           if (getQuestionContent === undefined) {
             upEq.dirty = true;
           } else {