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