|
@@ -0,0 +1,210 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { onlineExamDataApi } from "@/api/onlinePractice";
|
|
|
+import { httpApp } from "@/plugins/axiosApp";
|
|
|
+import router from "@/router";
|
|
|
+import { store } from "@/store/store";
|
|
|
+import { Store } from "@/types/student-client";
|
|
|
+import { onMounted, onUnmounted } from "vue";
|
|
|
+import { useRoute } from "vue-router";
|
|
|
+
|
|
|
+const route = useRoute();
|
|
|
+const examId = +route.params.examId;
|
|
|
+const examRecordDataId = +route.params.examRecordDataId;
|
|
|
+
|
|
|
+let loading = $ref(true);
|
|
|
+let afterExamRemark = $ref("");
|
|
|
+let cheatingRemark = $ref("");
|
|
|
+let showObjectScore = $ref(false);
|
|
|
+let showCheatingRemark = $ref(false);
|
|
|
+
|
|
|
+let examResult: { isWarn: boolean; objectiveScore: number } | null = null;
|
|
|
+
|
|
|
+onMounted(async function () {
|
|
|
+ _hmt.push(["_trackEvent", "考试结束页面", "进入页面"]);
|
|
|
+ logger({ cnl: ["server"], pgn: "考试结束页面", act: "进入页面" });
|
|
|
+
|
|
|
+ try {
|
|
|
+ loading = true;
|
|
|
+ if (!store.exam.examType) {
|
|
|
+ const exam = (await onlineExamDataApi(examId)).data;
|
|
|
+ store.exam.examType = exam.examType;
|
|
|
+
|
|
|
+ if (exam.examType === "PRACTICE") {
|
|
|
+ void router.replace(
|
|
|
+ `/online-practice/exam/${examId}/detail?examRecordDataId=${examRecordDataId}&disableGoBack=true`
|
|
|
+ );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const resp = await httpApp.get(
|
|
|
+ "/api/ecs_exam_work/exam/getExamPropertyFromCacheByStudentSession/" +
|
|
|
+ examId +
|
|
|
+ `/AFTER_EXAM_REMARK,IS_OBJ_SCORE_VIEW,SHOW_CHEATING_REMARK,CHEATING_REMARK`
|
|
|
+ );
|
|
|
+ afterExamRemark = resp.data.AFTER_EXAM_REMARK || "";
|
|
|
+ cheatingRemark = resp.data.CHEATING_REMARK || "";
|
|
|
+ showObjectScore = resp.data.IS_OBJ_SCORE_VIEW === "true";
|
|
|
+ showCheatingRemark = resp.data.SHOW_CHEATING_REMARK === "true";
|
|
|
+
|
|
|
+ loading = false;
|
|
|
+ } catch (error) {
|
|
|
+ logger({
|
|
|
+ cnl: ["server"],
|
|
|
+ pgn: "考试结束页面",
|
|
|
+ dtl: "获取考试设置错误,请在待考列表查看成绩!",
|
|
|
+ });
|
|
|
+ $message.error("获取考试设置错误,请在待考列表查看成绩!");
|
|
|
+ void router.push("/");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (showObjectScore) {
|
|
|
+ await getExamResult();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+let examResultLoading = $ref(true);
|
|
|
+async function getExamResult() {
|
|
|
+ try {
|
|
|
+ const startTime = Date.now();
|
|
|
+ for (let i = 0; i < 20; i++) {
|
|
|
+ examResult = (
|
|
|
+ await httpApp.get(
|
|
|
+ "/api/ecs_oe_student/examControl/getEndExamInfo?examRecordDataId=" +
|
|
|
+ examRecordDataId,
|
|
|
+ { "axios-retry": { retries: 60 }, noErrorMessage: true }
|
|
|
+ )
|
|
|
+ ).data;
|
|
|
+ await new Promise((res) => setTimeout(res, 5 * 1000));
|
|
|
+ if (examResult) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ logger({
|
|
|
+ cnl: ["server"],
|
|
|
+ pgn: "考试结束页面",
|
|
|
+ dtl: "等待时间: " + (Date.now() - startTime) / 1000,
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ logger({
|
|
|
+ cnl: ["server"],
|
|
|
+ pgn: "考试结束页面",
|
|
|
+ dtl: "获取考试设置错误,请在待考列表查看成绩!",
|
|
|
+ });
|
|
|
+ $message.info("获取考试设置错误,请在待考列表查看成绩!");
|
|
|
+ } finally {
|
|
|
+ examResultLoading = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const backTo = $computed(() => {
|
|
|
+ const examType = store.exam.examType;
|
|
|
+ if (examType === "PRACTICE") {
|
|
|
+ return "/online-practice";
|
|
|
+ } else if (examType === "ONLINE_HOMEWORK") {
|
|
|
+ return "/online-homework";
|
|
|
+ }
|
|
|
+
|
|
|
+ return "/online-exam";
|
|
|
+});
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ // 清除考试中间数据
|
|
|
+ store.exam = {} as Store["exam"];
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div v-if="!loading" id="exam-end" class="container">
|
|
|
+ <div class="instructions">
|
|
|
+ <h1 class="tw-text-3xl tw-font-bold tw-text-center">考试已结束</h1>
|
|
|
+ <div class="tw-flex tw-items-center">
|
|
|
+ <img class="user-avatar" :src="store.user.photoPath" alt="无底照" />
|
|
|
+
|
|
|
+ <div v-if="showObjectScore" class="tw-text-center tw-flex-1">
|
|
|
+ <div v-if="examResultLoading" class="score-text">
|
|
|
+ 考试结果计算中...
|
|
|
+ </div>
|
|
|
+ <div v-else>
|
|
|
+ <div v-if="examResult">
|
|
|
+ <div v-if="examResult.isWarn" class="qm-big-text score-text">
|
|
|
+ 客观题得分: 成绩待审核
|
|
|
+ </div>
|
|
|
+ <div v-else class="score-text tw-flex tw-items-center">
|
|
|
+ 客观题得分:
|
|
|
+ <span style="color: red; font-size: 40px">{{
|
|
|
+ examResult.objectiveScore
|
|
|
+ }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-else class="qm-big-text score-text" style="font-size: 20px">
|
|
|
+ 请稍后在待考列表中查看客观题得分。
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="showObjectScore" class="tw-text-center tw-flex-1">
|
|
|
+ <div v-if="examResult">
|
|
|
+ <div v-if="showCheatingRemark && examResult.isWarn">
|
|
|
+ <div class="tw-text-xl">违纪提示:</div>
|
|
|
+ <div style="text-align: left; padding-bottom: 20px">
|
|
|
+ <p v-html="cheatingRemark"></p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="tw-text-xl">考后说明:</div>
|
|
|
+ <div style="text-align: left; padding-bottom: 20px">
|
|
|
+ <p v-html="afterExamRemark"></p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <router-link
|
|
|
+ class="qm-primary-button tw-inline-block tw-text-center tw-w-full"
|
|
|
+ :to="backTo"
|
|
|
+ ondragstart="return false;"
|
|
|
+ >
|
|
|
+ 返回主页
|
|
|
+ </router-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-else>正在等待数据返回...</div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.container {
|
|
|
+ margin: 0 auto;
|
|
|
+ width: 80vw;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.instructions {
|
|
|
+ padding: 40px 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.instructions > h1,
|
|
|
+.instructions > div {
|
|
|
+ padding-bottom: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.user-avatar {
|
|
|
+ display: inline-block;
|
|
|
+ width: 140px;
|
|
|
+ height: 140px;
|
|
|
+ object-fit: contain;
|
|
|
+}
|
|
|
+
|
|
|
+.score-text {
|
|
|
+ font-size: 24px;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style>
|
|
|
+#exam-end img {
|
|
|
+ max-width: 100%;
|
|
|
+ height: auto !important;
|
|
|
+}
|
|
|
+</style>
|