소스 검색

feat: 切换快捷键

zhangjie 9 달 전
부모
커밋
a333669b81

+ 3 - 3
src/render/components/SelectBoolean/index.vue

@@ -22,10 +22,10 @@ defineOptions({
 const props = withDefaults(
   defineProps<{
     value: boolean | null;
-    type: "BOOLEAN_TYPE" | "BOOLEAN_ENABLE_TYPE";
+    type?: "BOOLEAN_TYPE" | "BOOLEAN_ENABLE_TYPE";
     placeholder?: string;
-    allowClear: boolean;
-    disabled: boolean;
+    allowClear?: boolean;
+    disabled?: boolean;
   }>(),
   {
     placeholder: "请选择",

+ 2 - 0
src/render/store/modules/dataCheck/index.ts

@@ -12,6 +12,7 @@ interface DataCheckState {
   curPage: StudentPage | null;
   curPageIndex: number;
   curStudent: DataCheckListItem | null;
+  curStudentIndex: number;
 }
 
 type UpdateFieldParams = Pick<DataCheckOmrFieldEditParams, "field" | "value">;
@@ -38,6 +39,7 @@ export const useDataCheckStore = defineStore("dataCheck", {
     curPage: null,
     curPageIndex: -1,
     curStudent: null,
+    curStudentIndex: -1,
   }),
 
   getters: {

+ 93 - 14
src/render/views/AbsentCheck/index.vue

@@ -4,10 +4,10 @@
       <div class="check-menu-body">
         <ul>
           <li
-            v-for="item in studentList"
+            v-for="(item, index) in studentList"
             :key="item.id"
             :class="{ 'is-active': dataCheckStore.curStudent?.id === item.id }"
-            @click="onSelectStudent(item)"
+            @click="onSelectStudent(index)"
           >
             {{ item.examNumber }}
           </li>
@@ -36,7 +36,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed } from "vue";
+import { ref, reactive, onMounted, computed, onBeforeUnmount } from "vue";
 import { message } from "ant-design-vue";
 import { CaretLeftOutlined, CaretRightOutlined } from "@ant-design/icons-vue";
 
@@ -62,6 +62,7 @@ let searchModel = {} as AbsentCheckListFilter;
 const pageNumber = ref(1);
 const pageSize = ref(20);
 const total = ref(0);
+const pageCount = ref(0);
 const studentList = ref<DataCheckListItem[]>([]);
 const dataList = ref<StudentPage[]>([]);
 const loading = ref(false);
@@ -78,6 +79,7 @@ async function getList() {
   if (!res) return;
 
   total.value = res.totalCount;
+  pageCount.value = res.pageCount;
   studentList.value = res.result;
 
   parseStudentPageList(res.result);
@@ -107,15 +109,6 @@ function parseStudentPageList(students: DataCheckListItem[]) {
   });
 }
 
-function onSelectStudent(record: DataCheckListItem) {
-  const pageIndex = dataList.value.findIndex(
-    (item) => item.studentId === record.id
-  );
-  if (pageIndex === -1) return;
-
-  selectPage(pageIndex);
-}
-
 // imageType
 const isOriginImage = computed(() => {
   return dataCheckStore.imageType === "ORIGIN";
@@ -135,6 +128,49 @@ async function onSearch(datas: AbsentCheckListFilter) {
 }
 onSearch({ examId: userStore.curExam.id } as AbsentCheckListFilter);
 
+// student
+function onSelectStudent(index: number) {
+  const student = studentList.value[index];
+  const pageIndex = dataList.value.findIndex(
+    (item) => item.studentId === student.id
+  );
+  if (pageIndex === -1) return;
+
+  selectPage(pageIndex);
+}
+
+async function onPrevStudent() {
+  if (dataCheckStore.curStudentIndex <= 0) {
+    if (pageNumber.value === 1) {
+      message.error("没有上一个学生了");
+      return;
+    }
+
+    pageNumber.value--;
+    await getList();
+    onSelectStudent(studentList.value.length - 1);
+    return;
+  }
+
+  onSelectStudent(dataCheckStore.curStudentIndex - 1);
+}
+
+async function onNextStudent() {
+  if (dataCheckStore.curStudentIndex >= studentList.value.length - 1) {
+    if (pageNumber.value >= pageCount.value) {
+      message.error("没有下一个学生了");
+      return;
+    }
+
+    pageNumber.value++;
+    await getList();
+    onSelectStudent(0);
+    return;
+  }
+
+  onSelectStudent(dataCheckStore.curStudentIndex + 1);
+}
+
 // page
 function selectPage(index: number) {
   dataCheckStore.setInfo({
@@ -147,7 +183,10 @@ function selectPage(index: number) {
   const curStudent = studentList.value[
     dataCheckStore.curPage.studentIndex
   ] as DataCheckListItem;
-  dataCheckStore.setInfo({ curStudent });
+  dataCheckStore.setInfo({
+    curStudent,
+    curStudentIndex: dataCheckStore.curPage.studentIndex,
+  });
 }
 
 async function onPrevPage() {
@@ -168,7 +207,7 @@ async function onPrevPage() {
 
 async function onNextPage() {
   if (dataCheckStore.curPageIndex >= dataList.value.length - 1) {
-    if (pageNumber.value >= total.value) {
+    if (pageNumber.value >= pageCount.value) {
       message.error("没有下一张了");
       return;
     }
@@ -181,4 +220,44 @@ async function onNextPage() {
 
   selectPage(dataCheckStore.curPageIndex + 1);
 }
+
+// shortcut
+function registShortcut() {
+  document.addEventListener("keydown", shortcutHandle);
+}
+function removeShortcut() {
+  document.removeEventListener("keydown", shortcutHandle);
+}
+function shortcutHandle(e: KeyboardEvent) {
+  const moveAction = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
+  if (!moveAction.includes(e.code) || e.repeat) {
+    return;
+  }
+
+  e.preventDefault();
+
+  if (e.code === "ArrowUp") {
+    onPrevStudent();
+    return;
+  }
+  if (e.code === "ArrowDown") {
+    onNextStudent();
+    return;
+  }
+  if (e.code === "ArrowLeft") {
+    onPrevPage();
+    return;
+  }
+  if (e.code === "ArrowRight") {
+    onNextPage();
+    return;
+  }
+}
+
+onMounted(() => {
+  registShortcut();
+});
+onBeforeUnmount(() => {
+  removeShortcut();
+});
 </script>

+ 1 - 1
src/render/views/DataCheck/ScanImage/RecogEditDialog.vue

@@ -197,7 +197,7 @@ function removeKeyEvent() {
 }
 
 function keyEventHandle(e: KeyboardEvent) {
-  if (e.code === "Enter") {
+  if (e.code === "Enter" && !e.repeat) {
     e.preventDefault();
     onConfirm();
     return;

+ 93 - 14
src/render/views/DataCheck/index.vue

@@ -4,10 +4,10 @@
       <div class="check-menu-body">
         <ul>
           <li
-            v-for="item in studentList"
+            v-for="(item, index) in studentList"
             :key="item.id"
             :class="{ 'is-active': dataCheckStore.curStudent?.id === item.id }"
-            @click="onSelectStudent(item)"
+            @click="onSelectStudent(index)"
           >
             {{ item.examNumber }}
           </li>
@@ -36,7 +36,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed } from "vue";
+import { ref, reactive, onMounted, computed, onBeforeUnmount } from "vue";
 import { message } from "ant-design-vue";
 import { CaretLeftOutlined, CaretRightOutlined } from "@ant-design/icons-vue";
 
@@ -61,6 +61,7 @@ let searchModel = {} as DataCheckListFilter;
 const pageNumber = ref(1);
 const pageSize = ref(20);
 const total = ref(0);
+const pageCount = ref(0);
 const studentList = ref<DataCheckListItem[]>([]);
 const dataList = ref<StudentPage[]>([]);
 const loading = ref(false);
@@ -77,6 +78,7 @@ async function getList() {
   if (!res) return;
 
   total.value = res.totalCount;
+  pageCount.value = res.pageCount;
   studentList.value = res.result;
 
   parseStudentPageList(res.result);
@@ -106,15 +108,6 @@ function parseStudentPageList(students: DataCheckListItem[]) {
   });
 }
 
-function onSelectStudent(record: DataCheckListItem) {
-  const pageIndex = dataList.value.findIndex(
-    (item) => item.studentId === record.id
-  );
-  if (pageIndex === -1) return;
-
-  selectPage(pageIndex);
-}
-
 // imageType
 const isOriginImage = computed(() => {
   return dataCheckStore.imageType === "ORIGIN";
@@ -135,6 +128,49 @@ async function onSearch(datas: DataCheckListFilter) {
 
 onSearch({ examId: userStore.curExam.id } as DataCheckListFilter);
 
+// student
+function onSelectStudent(index: number) {
+  const student = studentList.value[index];
+  const pageIndex = dataList.value.findIndex(
+    (item) => item.studentId === student.id
+  );
+  if (pageIndex === -1) return;
+
+  selectPage(pageIndex);
+}
+
+async function onPrevStudent() {
+  if (dataCheckStore.curStudentIndex <= 0) {
+    if (pageNumber.value === 1) {
+      message.error("没有上一个学生了");
+      return;
+    }
+
+    pageNumber.value--;
+    await getList();
+    onSelectStudent(studentList.value.length - 1);
+    return;
+  }
+
+  onSelectStudent(dataCheckStore.curStudentIndex - 1);
+}
+
+async function onNextStudent() {
+  if (dataCheckStore.curStudentIndex >= studentList.value.length - 1) {
+    if (pageNumber.value >= pageCount.value) {
+      message.error("没有下一个学生了");
+      return;
+    }
+
+    pageNumber.value++;
+    await getList();
+    onSelectStudent(0);
+    return;
+  }
+
+  onSelectStudent(dataCheckStore.curStudentIndex + 1);
+}
+
 // page
 function selectPage(index: number) {
   dataCheckStore.setInfo({
@@ -147,7 +183,10 @@ function selectPage(index: number) {
   const curStudent = studentList.value[
     dataCheckStore.curPage.studentIndex
   ] as DataCheckListItem;
-  dataCheckStore.setInfo({ curStudent });
+  dataCheckStore.setInfo({
+    curStudent,
+    curStudentIndex: dataCheckStore.curPage.studentIndex,
+  });
 }
 
 async function onPrevPage() {
@@ -168,7 +207,7 @@ async function onPrevPage() {
 
 async function onNextPage() {
   if (dataCheckStore.curPageIndex >= dataList.value.length - 1) {
-    if (pageNumber.value >= total.value) {
+    if (pageNumber.value >= pageCount.value) {
       message.error("没有下一张了");
       return;
     }
@@ -181,4 +220,44 @@ async function onNextPage() {
 
   selectPage(dataCheckStore.curPageIndex + 1);
 }
+
+// shortcut
+function registShortcut() {
+  document.addEventListener("keydown", shortcutHandle);
+}
+function removeShortcut() {
+  document.removeEventListener("keydown", shortcutHandle);
+}
+function shortcutHandle(e: KeyboardEvent) {
+  const moveAction = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
+  if (!moveAction.includes(e.code) || e.repeat) {
+    return;
+  }
+
+  e.preventDefault();
+
+  if (e.code === "ArrowUp") {
+    onPrevStudent();
+    return;
+  }
+  if (e.code === "ArrowDown") {
+    onNextStudent();
+    return;
+  }
+  if (e.code === "ArrowLeft") {
+    onPrevPage();
+    return;
+  }
+  if (e.code === "ArrowRight") {
+    onNextPage();
+    return;
+  }
+}
+
+onMounted(() => {
+  registShortcut();
+});
+onBeforeUnmount(() => {
+  removeShortcut();
+});
 </script>