index.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <template>
  2. <div class="review">
  3. <div class="review-head">
  4. <h2 v-if="reviewStore.curTask" class="review-title">
  5. {{ reviewStore.curTask.examNumber }} - {{ reviewStore.curTask.name }} -
  6. CET4
  7. </h2>
  8. <div class="review-stat">
  9. <p class="color-success">
  10. <CheckCircleFilled />已处理:{{ progress.finishCount }}
  11. </p>
  12. <p class="color-error">
  13. <CloseCircleFilled />未处理:{{ progress.todoCount }}
  14. </p>
  15. </div>
  16. <div class="review-prev">
  17. <a-button v-if="reviewStore.tabKey === 'review'" :disabled="loading">
  18. <template #icon><ArrowLeftOutlined /></template> 上一个
  19. </a-button>
  20. </div>
  21. </div>
  22. <!-- body -->
  23. <div class="review-body">
  24. <ReviewImage />
  25. <!-- ReviewMarkPan -->
  26. <ReviewMarkPan
  27. v-if="reviewStore.curTask"
  28. :task-info="{
  29. examNumber: reviewStore.curTask.examNumber,
  30. name: reviewStore.curTask.name,
  31. }"
  32. @mark="onMark"
  33. />
  34. </div>
  35. <!-- action -->
  36. <ReviewAction @mark="onMark" @reset="onReset" @search="onSearch" />
  37. <!-- reset confirm -->
  38. <ResetConfirmDialog
  39. ref="resetConfirmDialogRef"
  40. :subject="resetSubject"
  41. @confirm="onResetConfirm"
  42. />
  43. </div>
  44. </template>
  45. <script setup lang="ts">
  46. import { computed, ref, reactive, onMounted, watch } from "vue";
  47. import {
  48. CheckCircleFilled,
  49. CloseCircleFilled,
  50. ArrowLeftOutlined,
  51. } from "@ant-design/icons-vue";
  52. import { message } from "ant-design-vue";
  53. import {
  54. reviewTaskList,
  55. reviewTaskReset,
  56. reviewTaskSave,
  57. reviewProgress,
  58. } from "@/ap/review";
  59. import { ReviewTaskListItem } from "@/ap/types/review";
  60. import { SubjectItem } from "@/ap/types/base";
  61. import { useUserStore, useReviewStore } from "@/store";
  62. import useLoading from "@/hooks/useLoading";
  63. import ReviewAction from "./ReviewAction.vue";
  64. import ReviewImage from "./ReviewImage.vue";
  65. import ResetConfirmDialog from "./ResetConfirmDialog.vue";
  66. import ReviewMarkPan from "./ReviewMarkPan.vue";
  67. const userStore = useUserStore();
  68. const reviewStore = useReviewStore();
  69. defineOptions({
  70. name: "review",
  71. });
  72. // 任务进度
  73. const progress = ref({
  74. finishCount: 0,
  75. todoCount: 0,
  76. });
  77. async function updateProgress() {
  78. const res = await reviewProgress({ examId: userStore.curExam.id });
  79. progress.value = res || {};
  80. }
  81. // 任务相关
  82. const searchModel = reactive({
  83. examId: userStore.curExam.id,
  84. subjectCode: "",
  85. });
  86. const { loading, setLoading } = useLoading();
  87. const dataList = ref<ReviewTaskListItem[]>([]);
  88. const curTaskIndex = ref(0);
  89. async function getTasks() {
  90. // TODO:假设一次取3个
  91. const res = await reviewTaskList(searchModel);
  92. dataList.value = res || [];
  93. }
  94. function setCurTask() {
  95. reviewStore.setInfo({ curTask: dataList.value[curTaskIndex.value] });
  96. }
  97. async function getNextTask() {
  98. if (curTaskIndex.value >= dataList.value.length - 1) {
  99. await getTasks();
  100. if (!dataList.value.length) {
  101. message.error("没有下一个了!");
  102. reviewStore.setInfo({ curTask: null });
  103. return;
  104. }
  105. curTaskIndex.value = 0;
  106. setCurTask();
  107. return;
  108. }
  109. curTaskIndex.value++;
  110. setCurTask();
  111. }
  112. async function getPrevTask() {
  113. if (loading.value) return;
  114. loading.value = true;
  115. if (curTaskIndex.value <= 0) {
  116. let result = true;
  117. await getTasks().catch(() => {
  118. result = false;
  119. });
  120. if (!result) return;
  121. loading.value = false;
  122. if (!dataList.value.length) {
  123. message.error("没有上一个了!");
  124. reviewStore.setInfo({ curTask: null });
  125. return;
  126. }
  127. curTaskIndex.value = dataList.value.length - 1;
  128. setCurTask();
  129. return;
  130. }
  131. curTaskIndex.value--;
  132. setCurTask();
  133. }
  134. // actions
  135. async function onMark(result: boolean) {
  136. if (!reviewStore.curTask) return;
  137. if (loading.value) return;
  138. loading.value = true;
  139. try {
  140. await reviewTaskSave({ id: reviewStore.curTask.id, result });
  141. reviewStore.setInfo({
  142. curTask: Object.assign({}, reviewStore.curTask, {
  143. markStatus: result,
  144. }),
  145. });
  146. if (reviewStore.tabKey === "history") return;
  147. await getNextTask();
  148. } catch (error) {
  149. loading.value = false;
  150. }
  151. }
  152. async function onSearch(subjectCode: string) {
  153. searchModel.subjectCode = subjectCode;
  154. await getTasks();
  155. curTaskIndex.value = 0;
  156. setCurTask();
  157. }
  158. const resetConfirmDialogRef = ref();
  159. const resetSubject = ref<SubjectItem | null>(null);
  160. async function onReset(data: SubjectItem | null) {
  161. resetSubject.value = data;
  162. resetConfirmDialogRef.value?.open();
  163. }
  164. function onResetConfirm() {
  165. onSearch("");
  166. }
  167. // watch
  168. watch(
  169. () => reviewStore.tabKey,
  170. (val) => {
  171. if (val === "review") {
  172. reviewStore.setInfo({
  173. curTask: dataList.value[curTaskIndex.value] || null,
  174. });
  175. }
  176. }
  177. );
  178. onMounted(() => {
  179. // test
  180. dataList.value = [
  181. {
  182. id: 1,
  183. name: "考生2",
  184. studentCode: "360080241304012",
  185. subjectCode: "SX0001",
  186. subjectName: "数学",
  187. examNumber: "360080241304012",
  188. markStatus: false,
  189. breachCount: 1,
  190. pages: [
  191. {
  192. index: 1,
  193. uri: "",
  194. },
  195. {
  196. index: 2,
  197. uri: "",
  198. },
  199. ],
  200. },
  201. ];
  202. reviewStore.setInfo({
  203. curTask: dataList.value[curTaskIndex.value] || null,
  204. tabKey: "review",
  205. });
  206. });
  207. </script>