|
@@ -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, "<").replace(/>/g, ">") ||
|
|
|
+ `(${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>
|