index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <template>
  2. <div class="data-check">
  3. <div class="check-menu">
  4. <div class="check-menu-body">
  5. <ul>
  6. <li
  7. v-for="(item, index) in studentList"
  8. :key="item.id"
  9. :class="{ 'is-active': dataCheckStore.curStudent?.id === item.id }"
  10. @click="onSelectStudent(index)"
  11. >
  12. {{ item.examNumber }}
  13. </li>
  14. </ul>
  15. </div>
  16. <div class="check-menu-page">
  17. <SimplePagination
  18. :total="total"
  19. :page-size="pageSize"
  20. @change="onChangeListPage"
  21. />
  22. </div>
  23. </div>
  24. <div class="check-body">
  25. <ScanImage
  26. v-if="dataCheckStore.curPage && isOriginImage"
  27. :key="dataCheckStore.curPage.kid"
  28. @prev="onPrevPage"
  29. @next="onNextPage"
  30. />
  31. <SliceImage v-if="dataCheckStore.curPage && !isOriginImage" />
  32. </div>
  33. <CheckAction @search="onSearch" />
  34. </div>
  35. </template>
  36. <script setup lang="ts">
  37. import { ref, reactive, onMounted, computed, onBeforeUnmount } from "vue";
  38. import { message } from "ant-design-vue";
  39. import { CaretLeftOutlined, CaretRightOutlined } from "@ant-design/icons-vue";
  40. import { AbsentCheckListFilter } from "@/ap/types/absentCheck";
  41. import { DataCheckListItem } from "@/ap/types/dataCheck";
  42. import { absentCheckList } from "@/ap/absentCheck";
  43. import { StudentPage } from "../DataCheck/types";
  44. import { useDataCheckStore, useUserStore } from "@/store";
  45. import SimplePagination from "@/components/SimplePagination/index.vue";
  46. import ScanImage from "../DataCheck/ScanImage/index.vue";
  47. import SliceImage from "../DataCheck/SliceImage/index.vue";
  48. import CheckAction from "./CheckAction.vue";
  49. defineOptions({
  50. name: "AbsentCheck",
  51. });
  52. const dataCheckStore = useDataCheckStore();
  53. dataCheckStore.resetInfo();
  54. const userStore = useUserStore();
  55. let searchModel = {} as AbsentCheckListFilter;
  56. const pageNumber = ref(1);
  57. const pageSize = ref(20);
  58. const total = ref(0);
  59. const pageCount = ref(0);
  60. const studentList = ref<DataCheckListItem[]>([]);
  61. const dataList = ref<StudentPage[]>([]);
  62. const loading = ref(false);
  63. async function getList() {
  64. loading.value = true;
  65. const datas = {
  66. ...searchModel,
  67. pageNumber: pageNumber.value,
  68. pageSize: pageSize.value,
  69. };
  70. const res = await absentCheckList(datas).catch(() => null);
  71. loading.value = false;
  72. if (!res) return;
  73. total.value = res.totalCount;
  74. pageCount.value = res.pageCount;
  75. studentList.value = res.result;
  76. parseStudentPageList(res.result);
  77. }
  78. function parseStudentPageList(students: DataCheckListItem[]) {
  79. dataList.value = [] as StudentPage[];
  80. students.forEach((student, studentIndex) => {
  81. student.papers.forEach((paper, paperIndex) => {
  82. if (!paper.pages) return;
  83. paper.pages.forEach((page, pageIndex) => {
  84. const row: StudentPage = {
  85. ...page,
  86. paperId: paper.id,
  87. paperIndex,
  88. paperNumber: paper.number,
  89. pageIndex,
  90. studentIndex,
  91. studentId: student.id,
  92. examId: searchModel.examId,
  93. kid: `${student.id}-${studentIndex}-${paperIndex}-${pageIndex}`,
  94. };
  95. dataList.value.push(row);
  96. });
  97. });
  98. });
  99. }
  100. // imageType
  101. const isOriginImage = computed(() => {
  102. return dataCheckStore.imageType === "ORIGIN";
  103. });
  104. // table
  105. async function onChangeListPage(index: number) {
  106. pageNumber.value = index;
  107. await getList();
  108. selectPage(0);
  109. }
  110. async function onSearch(datas: AbsentCheckListFilter) {
  111. searchModel = { ...datas };
  112. if (!searchModel.subjectCode) {
  113. return;
  114. }
  115. pageNumber.value = 1;
  116. await getList();
  117. selectPage(0);
  118. }
  119. onSearch({ examId: userStore.curExam.id } as AbsentCheckListFilter);
  120. // student
  121. function onSelectStudent(index: number) {
  122. const student = studentList.value[index];
  123. const pageIndex = dataList.value.findIndex(
  124. (item) => item.studentId === student.id
  125. );
  126. if (pageIndex === -1) return;
  127. selectPage(pageIndex);
  128. }
  129. async function onPrevStudent() {
  130. if (dataCheckStore.curStudentIndex <= 0) {
  131. if (pageNumber.value === 1) {
  132. message.error("没有上一个学生了");
  133. return;
  134. }
  135. pageNumber.value--;
  136. await getList();
  137. onSelectStudent(studentList.value.length - 1);
  138. return;
  139. }
  140. onSelectStudent(dataCheckStore.curStudentIndex - 1);
  141. }
  142. async function onNextStudent() {
  143. if (dataCheckStore.curStudentIndex >= studentList.value.length - 1) {
  144. if (pageNumber.value >= pageCount.value) {
  145. message.error("没有下一个学生了");
  146. return;
  147. }
  148. pageNumber.value++;
  149. await getList();
  150. onSelectStudent(0);
  151. return;
  152. }
  153. onSelectStudent(dataCheckStore.curStudentIndex + 1);
  154. }
  155. // page
  156. function selectPage(index: number) {
  157. dataCheckStore.setInfo({
  158. curPage: dataList.value[index],
  159. curPageIndex: index,
  160. });
  161. if (!dataCheckStore.curPage) return;
  162. const curStudent = studentList.value[
  163. dataCheckStore.curPage.studentIndex
  164. ] as DataCheckListItem;
  165. dataCheckStore.setInfo({
  166. curStudent,
  167. curStudentIndex: dataCheckStore.curPage.studentIndex,
  168. });
  169. }
  170. async function onPrevPage() {
  171. if (dataCheckStore.curPageIndex <= 0) {
  172. if (pageNumber.value === 1) {
  173. message.error("没有上一张了");
  174. return;
  175. }
  176. pageNumber.value--;
  177. await getList();
  178. selectPage(dataList.value.length - 1);
  179. return;
  180. }
  181. selectPage(dataCheckStore.curPageIndex - 1);
  182. }
  183. async function onNextPage() {
  184. if (dataCheckStore.curPageIndex >= dataList.value.length - 1) {
  185. if (pageNumber.value >= pageCount.value) {
  186. message.error("没有下一张了");
  187. return;
  188. }
  189. pageNumber.value++;
  190. await getList();
  191. selectPage(0);
  192. return;
  193. }
  194. selectPage(dataCheckStore.curPageIndex + 1);
  195. }
  196. // shortcut
  197. function registShortcut() {
  198. document.addEventListener("keydown", shortcutHandle);
  199. }
  200. function removeShortcut() {
  201. document.removeEventListener("keydown", shortcutHandle);
  202. }
  203. function shortcutHandle(e: KeyboardEvent) {
  204. const moveAction = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
  205. if (!moveAction.includes(e.code) || e.repeat) {
  206. return;
  207. }
  208. e.preventDefault();
  209. if (e.code === "ArrowUp") {
  210. onPrevStudent();
  211. return;
  212. }
  213. if (e.code === "ArrowDown") {
  214. onNextStudent();
  215. return;
  216. }
  217. if (e.code === "ArrowLeft") {
  218. onPrevPage();
  219. return;
  220. }
  221. if (e.code === "ArrowRight") {
  222. onNextPage();
  223. return;
  224. }
  225. }
  226. onMounted(() => {
  227. registShortcut();
  228. });
  229. onBeforeUnmount(() => {
  230. removeShortcut();
  231. });
  232. </script>