123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- <template>
- <div class="rich-text-question-container">
- <div v-for="(question, index) in questions" :key="index">
- <div class="question">
- <div class="tw-text-xl">
- <span :id="'q-' + question.unionOrder">题号:</span>
- <span>{{ question.unionOrder }}</span>
- </div>
- <div>
- <div class="tw-text-xl">题干:</div>
- <div v-html="getDomByRichTextJSON(question.parentBody)?.innerHTML" />
- <div v-html="getDomByRichTextJSON(question.body)?.innerHTML" />
- <template v-if="question.objective">
- <div v-if="question.options">
- <div
- v-for="(option, index2) in question.options"
- :key="index2"
- class="tw-flex tw-gap-1"
- >
- {{ indexToABCD(option.number) }}.
- <div v-html="getDomByRichTextJSON(option.body)?.innerHTML" />
- </div>
- </div>
- </template>
- </div>
- <div>
- <template v-if="question.objective">
- <span class="tw-text-blue-600">考生答案:</span
- >{{ renderObjective(question.studentAnswer) }}
- </template>
- <template v-else>
- <div class="tw-text-blue-600">
- 考生答案:(字数统计:{{
- getDomByRichTextJSON(question.studentAnswer)?.innerText
- .length ?? 0
- }})
- </div>
- <div
- v-html="getDomByRichTextJSON(question.studentAnswer)?.innerHTML"
- />
- </template>
- </div>
- <div>
- <template v-if="question.objective">
- <span class="tw-text-blue-600">标准答案:</span
- >{{ renderObjective(question.standardAnswer) }}
- </template>
- <template v-else>
- <div class="tw-text-blue-600">标准答案:</div>
- <div
- v-html="getDomByRichTextJSON(question.standardAnswer)?.innerHTML"
- />
- </template>
- </div>
- <div v-if="showScore(question)" style="color: blue">
- 得分 / 总分 :{{
- (question.score ?? "-") + " / " + question.totalScore
- }}
- </div>
- </div>
- <div style="margin-bottom: 20px"></div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { getJSON } from "@/api/jsonMark";
- import { store } from "@/store/store";
- import { onUpdated, watch } from "vue";
- import { renderRichText } from "@/utils/renderJSON";
- import type { RichTextJSON } from "@/types";
- import "viewerjs/dist/viewer.css";
- import Viewer from "viewerjs";
- import { useRoute } from "vue-router";
- const route = useRoute();
- const isSeePaper = route.name === "StudentTrack";
- const showScore = (question: QuestionForRender) =>
- route.name !== "Mark" && question.totalScore;
- interface StudentAnswer {
- mainNumber: number;
- subNumber: string;
- subIndex: string;
- answer: Array<RichTextJSON> | null;
- }
- interface QuestionForRender {
- unionOrder: string;
- parentBody: RichTextJSON | null;
- body: RichTextJSON;
- studentAnswer: Array<RichTextJSON> | null;
- standardAnswer: Array<RichTextJSON> | null;
- score: number | null;
- totalScore: number;
- objective: boolean | null;
- options: Array<{ number: number; body: RichTextJSON }>;
- }
- let questions: QuestionForRender[] = $ref([]);
- async function updateStudentAnswerJSON() {
- return getJSON(store.currentTask?.jsonUrl as string);
- }
- function getDomByRichTextJSON(rt: Array<RichTextJSON> | RichTextJSON | null) {
- const node = document.createElement("div");
- if (!rt) return node;
- if (Array.isArray(rt)) {
- for (const r of rt) {
- node.appendChild(renderRichText(r));
- }
- } else {
- node.appendChild(renderRichText(rt));
- }
- return node;
- }
- watch(
- () => store.currentTask,
- async () => {
- questions.splice(0);
- if (!store.currentTask?.jsonUrl) return;
- const res = await updateStudentAnswerJSON();
- const stuAnswers: StudentAnswer[] = res.data;
- for (const ans of stuAnswers) {
- if (ans.answer && !Array.isArray(ans.answer)) {
- ans.answer = [ans.answer];
- }
- }
- // 查看原卷显示全部题目
- if (isSeePaper) {
- for (const questionBody of store.setting.subject.questions || []) {
- const questionForRender = {} as QuestionForRender;
- const [mainNumber, subNumber] = questionBody.unionOrder.split("-");
- const stuAns: StudentAnswer = stuAnswers.find(
- (v: StudentAnswer) =>
- questionBody.unionOrder ===
- [v.mainNumber, v.subNumber, v.subIndex]
- .filter((v) => typeof v !== "undefined")
- .join("-")
- ) || {
- mainNumber: +mainNumber,
- subNumber: subNumber,
- subIndex: "",
- answer: [],
- };
- const taskQuestion = (store.currentTask?.questionList || []).find(
- (v) =>
- [v.mainNumber, v.subNumber].join("-") === questionBody.unionOrder
- );
- questionForRender.unionOrder = questionBody.unionOrder;
- questionForRender.parentBody = questionBody.parentBody;
- questionForRender.body = questionBody.body;
- questionForRender.options = questionBody.options;
- questionForRender.objective = questionBody.objective;
- questionForRender.standardAnswer = questionBody.answer;
- questionForRender.studentAnswer = stuAns.answer;
- questionForRender.score = taskQuestion?.score || null;
- questionForRender.totalScore = taskQuestion?.maxScore || 0;
- questions.push(questionForRender);
- }
- } else {
- for (const taskQuestion of store.currentTask?.questionList || []) {
- const questionForRender = {} as QuestionForRender;
- const { mainNumber, subNumber } = taskQuestion;
- const questionBody = store.setting.subject.questions.find(
- (ques) => ques.unionOrder === `${mainNumber}-${subNumber}`
- );
- if (!questionBody) continue;
- const stuAns: StudentAnswer = stuAnswers.find(
- (v: StudentAnswer) =>
- questionBody.unionOrder ===
- [v.mainNumber, v.subNumber, v.subIndex]
- .filter((v) => typeof v !== "undefined")
- .join("-")
- ) || {
- mainNumber: +mainNumber,
- subNumber: subNumber,
- subIndex: "",
- answer: [],
- };
- questionForRender.unionOrder = questionBody.unionOrder;
- questionForRender.parentBody = questionBody.parentBody;
- questionForRender.body = questionBody.body;
- questionForRender.standardAnswer = questionBody.answer;
- questionForRender.studentAnswer = stuAns.answer;
- questionForRender.score = taskQuestion.score;
- questionForRender.totalScore = taskQuestion.maxScore;
- questions.push(questionForRender);
- }
- }
- },
- { immediate: true }
- );
- const indexToABCD = (index: number) => "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[index - 1];
- const renderObjective = (ans: any) => {
- if (typeof ans === "boolean") {
- return ans ? "A" : "B";
- } else if (Array.isArray(ans) && typeof ans[0] === "boolean") {
- return ans[0] ? "A" : "B";
- } else if (Array.isArray(ans) && typeof ans[0] === "number") {
- return (ans as unknown as number[]).map((v) => indexToABCD(v)).join("");
- } else if (Array.isArray(ans) && ans.length === 0) {
- return "";
- } else {
- console.log("错误的答案类型", JSON.stringify(ans));
- }
- };
- let viewer: Viewer = null as unknown as Viewer;
- onUpdated(() => {
- viewer && viewer.destroy();
- viewer = new Viewer(
- document.querySelector(".rich-text-question-container") as HTMLElement,
- // document.querySelector("#app") as HTMLElement,
- {
- // inline: true,
- viewed() {
- // viewer.zoomTo(1);
- },
- zIndex: 10000,
- }
- );
- });
- </script>
- <style scoped>
- .question {
- background-color: var(--app-container-bg-color);
- padding: 5px;
- border-radius: 5px;
- }
- .rich-text-question-container {
- background-color: transparent;
- font-size: 16px;
- }
- </style>
- <style>
- .rich-text-question-container img.inline {
- display: inline;
- }
- .rich-text-question-container img {
- cursor: pointer;
- }
- </style>
|