|
@@ -0,0 +1,198 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import QuestionIndex from "./QuestionIndex.vue";
|
|
|
+// import QuestionBody from "./QuestionBody";
|
|
|
+import QuestionViewSingle from "./QuestionViewSingle.vue";
|
|
|
+import { store } from "@/store/store";
|
|
|
+import { httpApp } from "@/plugins/axiosApp";
|
|
|
+import { watch } from "vue";
|
|
|
+import { ExamQuestion } from "@/types/student-client";
|
|
|
+// import splitPane from "vue-splitpane";
|
|
|
+import { Star, StarOutline } from "@vicons/ionicons5";
|
|
|
+
|
|
|
+// let parentPaneHeight = $ref(50);
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => store.exam.currentQuestion?.order,
|
|
|
+ async () => {
|
|
|
+ store.exam.currentQuestion && (await updateQuestion());
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+);
|
|
|
+
|
|
|
+function transferWellNumber(body: string | null) {
|
|
|
+ if (body === null) return null;
|
|
|
+ //将题干中的三个#替换为下划线
|
|
|
+ //将题干中的两个##数字##替换为下划线
|
|
|
+ return body
|
|
|
+ .replace(new RegExp("###", "g"), "_______")
|
|
|
+ .replace(/##(\d+)##/g, function (a, b: string) {
|
|
|
+ return "__" + parseInt(b) + "__";
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+type QuestionUnitContent = Pick<
|
|
|
+ ExamQuestion,
|
|
|
+ "answerType" | "body" | "questionOptionList" | "questionType" | "rightAnswer"
|
|
|
+>;
|
|
|
+async function updateQuestion() {
|
|
|
+ const currentExamQuestion = store.exam.currentQuestion; // 避免以后执行时,this.examQuestion换掉了
|
|
|
+ const examRecordDataId = store.exam.examRecordDataId;
|
|
|
+ const { order, questionId } = currentExamQuestion;
|
|
|
+ let qContentRes: {
|
|
|
+ body: string;
|
|
|
+ hasAudios: boolean;
|
|
|
+ questionUnitList: QuestionUnitContent[];
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ qContentRes = (
|
|
|
+ await httpApp.get(
|
|
|
+ `/api/ecs_oe_student/examQuestion/getQuestionContent?questionId=${questionId}&exam_record_id=${examRecordDataId}`,
|
|
|
+ { "axios-retry": { retries: 5, retryDelay: () => 3000 } }
|
|
|
+ )
|
|
|
+ ).data;
|
|
|
+ } catch (e) {
|
|
|
+ logger({
|
|
|
+ cnl: ["server"],
|
|
|
+ pgu: "AUTO",
|
|
|
+ act: "获取试题内容失败",
|
|
|
+ possibleError: e,
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!qContentRes) return;
|
|
|
+
|
|
|
+ // Object.assign(currentExamQuestion, qContentRes.data);
|
|
|
+
|
|
|
+ let i = 0;
|
|
|
+ //判断是否为套题
|
|
|
+ const isNestedQuestion = qContentRes.questionUnitList.length > 1;
|
|
|
+ store.exam.examQuestionList.forEach((q) => {
|
|
|
+ if (q.questionId === questionId) {
|
|
|
+ q.getQuestionContent = true;
|
|
|
+ let qc = qContentRes.questionUnitList[i++];
|
|
|
+ q.answerType = qc.answerType;
|
|
|
+ q.parentBody = transferWellNumber(qContentRes.body);
|
|
|
+ q.body = transferWellNumber(qc.body)!;
|
|
|
+ q.questionOptionList = qc.questionOptionList;
|
|
|
+ q.questionType = qc.questionType;
|
|
|
+ q.rightAnswer = qc.rightAnswer;
|
|
|
+ q.isNestedQuestion = isNestedQuestion;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 对于某些图片套题,会导致高度计算错误,需多次nextTick
|
|
|
+ // this.$nextTick(() => {
|
|
|
+ // this.$nextTick(() => {
|
|
|
+ // // 从非套题进入套题时,会根据套题的内容动态调整套题的默认高度
|
|
|
+ // const parentQuestion =
|
|
|
+ // document.getElementsByClassName("parent-question")[0];
|
|
|
+ // if (parentQuestion) {
|
|
|
+ // this.parentPaneHeight =
|
|
|
+ // 5 +
|
|
|
+ // (100 * parentQuestion.clientHeight) /
|
|
|
+ // (document.body.clientHeight - 160);
|
|
|
+ // if (this.parentPaneHeight > 60) {
|
|
|
+ // this.parentPaneHeight = 60;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // });
|
|
|
+ {
|
|
|
+ // cache next question content
|
|
|
+ if (order < store.exam.examQuestionList.length) {
|
|
|
+ void httpApp.get(
|
|
|
+ "/api/ecs_oe_student/examQuestion/getQuestionContent?questionId=" +
|
|
|
+ store.exam.examQuestionList[order].questionId +
|
|
|
+ "&exam_record_id=" +
|
|
|
+ examRecordDataId,
|
|
|
+ { noErrorMessage: true }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function toggleSign() {
|
|
|
+ store.updateExamQuestion({
|
|
|
+ order: store.exam.currentQuestion.order,
|
|
|
+ isSign: !store.exam.currentQuestion.isSign,
|
|
|
+ });
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ v-if="store.exam.currentQuestion.getQuestionContent"
|
|
|
+ class="question-container"
|
|
|
+ >
|
|
|
+ <div class="question-header">
|
|
|
+ <n-icon
|
|
|
+ :component="store.exam.currentQuestion.isSign ? Star : StarOutline"
|
|
|
+ class="star"
|
|
|
+ @click="toggleSign"
|
|
|
+ />
|
|
|
+ <question-index />
|
|
|
+ </div>
|
|
|
+ <!-- <split-pane
|
|
|
+ v-if="parentQuestionBody"
|
|
|
+ :minPercent="10"
|
|
|
+ :defaultPercent="parentPaneHeight"
|
|
|
+ split="horizontal"
|
|
|
+ >
|
|
|
+ <template #paneL>
|
|
|
+ <div v-if="parentQuestionBody" class="question-view parent-question">
|
|
|
+ <question-body
|
|
|
+ :key="examQuestion.questionId"
|
|
|
+ :questionBody="parentQuestionBody"
|
|
|
+ :examQuestion="examQuestion"
|
|
|
+ style="margin-bottom: 20px"
|
|
|
+ ></question-body>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #paneR>
|
|
|
+ <QuestionViewSingle :question="question" :examQuestion="examQuestion" />
|
|
|
+ </template>
|
|
|
+ </split-pane>
|
|
|
+ -->
|
|
|
+ <QuestionViewSingle v-if="!store.exam.currentQuestion.parentBody" />
|
|
|
+ </div>
|
|
|
+ <div v-else>试题获取中...</div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.question-container {
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+.question-container >>> .splitter-pane {
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+.question-container >>> .vue-splitter-container {
|
|
|
+ height: calc(100% - 42px);
|
|
|
+}
|
|
|
+.question-container >>> .splitter-pane-resizer.horizontal {
|
|
|
+ height: 15px;
|
|
|
+}
|
|
|
+.question-view {
|
|
|
+ padding: 20px 30px;
|
|
|
+ font-size: 16px;
|
|
|
+ text-align: left;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.question-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.star {
|
|
|
+ font-size: 36px;
|
|
|
+ color: #ffcc00;
|
|
|
+ align-self: flex-start;
|
|
|
+}
|
|
|
+.star:hover {
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+div.hr {
|
|
|
+ border-bottom: 1px dashed gray;
|
|
|
+}
|
|
|
+</style>
|