|
@@ -0,0 +1,142 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { store } from "@/store/store";
|
|
|
+import { onMounted, onUnmounted } from "vue";
|
|
|
+import QuestionBody from "./QuestionBody.vue";
|
|
|
+
|
|
|
+let isShowAnswer = $ref(false);
|
|
|
+function toggleShowAnswer() {
|
|
|
+ isShowAnswer = !isShowAnswer;
|
|
|
+}
|
|
|
+
|
|
|
+const examQuestion = $computed(() => store.exam.currentQuestion);
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ window.addEventListener("keyup", keyup);
|
|
|
+});
|
|
|
+onUnmounted(() => {
|
|
|
+ window.removeEventListener("keyup", keyup);
|
|
|
+});
|
|
|
+function keyup(e: KeyboardEvent) {
|
|
|
+ const { tagName = "" } = document?.activeElement || {};
|
|
|
+ if (
|
|
|
+ examQuestion.questionType === "TRUE_OR_FALSE" &&
|
|
|
+ ["BODY", "A", "BUTTON", "DIV"].includes(tagName)
|
|
|
+ ) {
|
|
|
+ if ("KeyY" === e.code) {
|
|
|
+ answerQuestion("true");
|
|
|
+ }
|
|
|
+ if ("KeyN" === e.code) {
|
|
|
+ answerQuestion("false");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function answerQuestion(studentAnswer: "true" | "false") {
|
|
|
+ store.updateExamQuestion({
|
|
|
+ order: examQuestion.order,
|
|
|
+ studentAnswer,
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const optionWithNames = { true: "正确", false: "错误" };
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="question-view">
|
|
|
+ <question-body :questionBody="examQuestion.body" />
|
|
|
+ <div class="ops">
|
|
|
+ <div class="stu-answer">
|
|
|
+ {{ optionWithNames[examQuestion.studentAnswer] }}
|
|
|
+ </div>
|
|
|
+ <div class="score">({{ examQuestion.questionScore }}分)</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ :class="[
|
|
|
+ examQuestion.studentAnswer === 'true' && 'row-selected',
|
|
|
+ 'option',
|
|
|
+ ]"
|
|
|
+ class="tw-flex tw-items-center"
|
|
|
+ @click="() => answerQuestion('true')"
|
|
|
+ >
|
|
|
+ <input
|
|
|
+ type="radio"
|
|
|
+ name="question"
|
|
|
+ value="true"
|
|
|
+ :checked="examQuestion.studentAnswer === 'true'"
|
|
|
+ />
|
|
|
+ <span class="question-options">正确</span>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ :class="[
|
|
|
+ examQuestion.studentAnswer === 'false' && 'row-selected',
|
|
|
+ 'option',
|
|
|
+ ]"
|
|
|
+ class="tw-flex tw-items-center"
|
|
|
+ @click="() => answerQuestion('false')"
|
|
|
+ >
|
|
|
+ <input
|
|
|
+ type="radio"
|
|
|
+ name="question"
|
|
|
+ value="false"
|
|
|
+ :checked="examQuestion.studentAnswer === 'false'"
|
|
|
+ />
|
|
|
+ <div class="question-options">错误</div>
|
|
|
+ </div>
|
|
|
+ <div class="reset">
|
|
|
+ <span v-if="store.examShouldShowAnswer">
|
|
|
+ <n-button type="success" @click="toggleShowAnswer"> 显示答案 </n-button>
|
|
|
+ </span>
|
|
|
+ <div v-if="isShowAnswer">
|
|
|
+ 正确答案:
|
|
|
+ <div>
|
|
|
+ {{ optionWithNames[examQuestion.rightAnswer] }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.question-view {
|
|
|
+ display: grid;
|
|
|
+ grid-row-gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.question-body {
|
|
|
+ font-size: 18px;
|
|
|
+ /* margin-bottom: 10px; */
|
|
|
+}
|
|
|
+
|
|
|
+.ops {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+}
|
|
|
+
|
|
|
+.stu-answer {
|
|
|
+ width: 100px;
|
|
|
+ border-bottom: 1px solid black;
|
|
|
+ text-align: center;
|
|
|
+ height: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.option {
|
|
|
+ display: flex;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 5px;
|
|
|
+ height: 26px;
|
|
|
+}
|
|
|
+
|
|
|
+.option:hover {
|
|
|
+ background-color: aliceblue;
|
|
|
+}
|
|
|
+
|
|
|
+.row-selected {
|
|
|
+ background-color: aliceblue;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.question-options {
|
|
|
+ text-align: left;
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+</style>
|