useSubmitPaper.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import router from "@/router";
  2. import { useTimers } from "@/setups/useTimers";
  3. import { store } from "@/store/store";
  4. import { answerAllQuestions } from "./useAnswerQuestions";
  5. export function useRealSubmitPaper(
  6. examId: number,
  7. examRecordDataId: number,
  8. doSnap: () => void
  9. ) {
  10. const { addTimeout } = useTimers();
  11. async function userSubmitPaper(usedExamTimes: {
  12. usedExamSeconds: number;
  13. startTimestamp: number;
  14. }) {
  15. // if (
  16. // store.exam.freezeTime &&
  17. // store.exam.remainTime >
  18. // (store.exam.duration - store.exam.freezeTime) * 60 * 1000
  19. // ) {
  20. // $message.info(`考试开始${store.exam.freezeTime}分钟后才允许交卷。`);
  21. // return;
  22. // }
  23. if (
  24. store.exam.freezeTime &&
  25. usedExamTimes.usedExamSeconds * 1000 +
  26. Date.now() -
  27. usedExamTimes.startTimestamp <
  28. store.exam.freezeTime * 60 * 1000
  29. ) {
  30. $message.info(`考试开始${store.exam.freezeTime}分钟后才允许交卷。`);
  31. return;
  32. }
  33. logger({ cnl: ["server", "local", "console"], act: "学生点击交卷" });
  34. try {
  35. // 交卷前强制提交所有答案
  36. const ret = await answerAllQuestions(true);
  37. if (!ret) {
  38. // 提交答案失败,停止交卷逻辑。
  39. return;
  40. }
  41. } catch (error) {
  42. return;
  43. }
  44. const answered = store.exam.examQuestionList.filter(
  45. (q) => q.studentAnswer !== null
  46. ).length;
  47. const unanswered = store.exam.examQuestionList.filter(
  48. (q) => q.studentAnswer === null
  49. ).length;
  50. const signed = store.exam.examQuestionList.filter(
  51. (q) => q.isStarred
  52. ).length;
  53. $dialog.info({
  54. title: "确认交卷",
  55. content: () => (
  56. <div>
  57. <p>已答题目:{answered}</p>
  58. <p>未答题目:{unanswered}</p>
  59. <p>标记题目:{signed}</p>
  60. </div>
  61. ),
  62. positiveText: "确定",
  63. onPositiveClick: () => {
  64. void realSubmitPaper();
  65. },
  66. });
  67. }
  68. // 多种条件都可能触发交卷,所以要有一个锁来避免重复进入
  69. let sumbitLock = false;
  70. async function realSubmitPaper() {
  71. if (sumbitLock) {
  72. logger({ cnl: ["server"], act: "交卷", stk: "竟然有锁!" });
  73. return;
  74. } else {
  75. sumbitLock = true;
  76. store.exam.isSubmittingPaper = true;
  77. }
  78. store.increaseGlobalMaskCount("realSubmitPaper");
  79. store.spinMessage = "正在交卷,请耐心等待...";
  80. logger({ cnl: ["server"], act: "正在交卷,请耐心等待..." });
  81. let delay = 0;
  82. const oldSnapCount = store.exam.compareResultMap?.size;
  83. if (store.exam.faceCheckEnabled) {
  84. logger({ cnl: ["server"], act: "交卷前抓拍" });
  85. doSnap();
  86. await new Promise((resolve) => setTimeout(resolve, 3 * 1000));
  87. // 根据线上错误排查:可能已经退出页面了,没有数据了
  88. const newSnapCount = store.exam.compareResultMap?.size;
  89. if (store.exam.compareResultMap && newSnapCount - oldSnapCount === 0) {
  90. // 给抓拍照片多2秒处理时间
  91. delay = 8;
  92. logger({ cnl: ["server"], act: "交卷前抓拍", dtl: "3秒内未上传完毕" });
  93. }
  94. }
  95. // 和下行注释的sleep语句不是一样的。sleep之后还可以执行。加上clearTimeout则可拒绝。
  96. // await new Promise(resolve => setTimeout(() => resolve(), delay * 1000));
  97. addTimeout(() => {
  98. store.decreaseGlobalMaskCount("realSubmitPaper");
  99. store.spinMessage = "";
  100. void router
  101. .push({
  102. name: "SubmitPaper",
  103. params: { examId, examRecordDataId },
  104. })
  105. .finally(() => (sumbitLock = false));
  106. }, delay * 1000);
  107. }
  108. return { userSubmitPaper, realSubmitPaper };
  109. }