zhangjie 1 mese fa
parent
commit
ca8ea02e38

+ 2 - 0
src/render/ap/types/dataCheck.ts

@@ -101,6 +101,8 @@ export interface DataCheckListItem {
   device: string;
   // 考生最新关联的各张图片
   papers: PaperItem[];
+  handleQuestionIndexs?: number[];
+  originQuestions?: string[];
 }
 
 export type DataCheckListResult = PageResult<DataCheckListItem>;

+ 4 - 1
src/render/styles/pages.less

@@ -965,11 +965,14 @@
       left: 50%;
       transform: translate(-50%, -50%);
       transform-origin: 0 0;
+      > img {
+        display: block;
+      }
 
       .select-option {
         position: absolute;
         top: 0;
-        border: 2px solid @brand-color;
+        border: 1px solid @brand-color;
         line-height: 1;
         text-align: center;
         cursor: pointer;

+ 2 - 6
src/render/views/ExamNumberCheck/CheckAction.vue

@@ -110,6 +110,8 @@ const questions = ref([] as string[]);
 watch(
   () => dataCheckStore.curPage?.question?.result,
   (val) => {
+    // console.log(`dataCheckStore.curPage?.question?.result:${Date.now()}`, val);
+
     if (!val) {
       questions.value = [];
       return;
@@ -121,12 +123,6 @@ watch(
     immediate: true,
   }
 );
-watch(
-  () => dataCheckStore.imageType,
-  (val) => {
-    imageType.value = val;
-  }
-);
 
 async function onQuestionsChange() {
   if (!dataCheckStore.curPage) return;

+ 1 - 1
src/render/views/ExamNumberCheck/EditExamNumberDialog.vue

@@ -26,7 +26,7 @@
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref, watch, computed } from "vue";
+import { onMounted, ref, watch } from "vue";
 import { message } from "ant-design-vue";
 import { getTextAreaRows } from "@/utils";
 import useModal from "@/hooks/useModal";

+ 37 - 15
src/render/views/ExamNumberCheck/QuestionPanel.vue

@@ -30,7 +30,10 @@
         :class="[
           'question-item',
           `question-item-${index}`,
-          { 'is-error': checkQuestionError(item) },
+          {
+            'is-error': checkQuestionError(item),
+            'is-checked': checkQuestionChecked(index),
+          },
         ]"
       >
         <span>{{ getQuestionNo(index) }}:</span>
@@ -90,6 +93,7 @@ import { useDataCheckStore } from "@/store";
 import { vEleClickOutsideDirective } from "@/directives/eleClickOutside";
 import { getSliceFileUrl, recogResultTransform } from "@/utils/tool";
 import useUpload from "./useUpload";
+import useTask from "./useTask";
 
 defineOptions({
   name: "QuestionPanel",
@@ -112,6 +116,7 @@ const emit = defineEmits(["update:questions", "change", "examNumberChange"]);
 
 const dataCheckStore = useDataCheckStore();
 const { save } = useUpload();
+const { checkExamNumber, checkQuestionError } = useTask();
 
 const questionList = ref([] as string[]);
 const curQuestion = ref("");
@@ -132,17 +137,6 @@ function getQuestionNo(index: number) {
   const no = index + 26;
   return no < 10 ? `0${no}` : `${no}`;
 }
-function checkQuestionError(cont: string) {
-  if (!cont) return true;
-  if (cont.length > 1) return true;
-  return false;
-}
-
-function checkExamNumber(examNumber: string) {
-  if (!examNumber) return false;
-  if (examNumber.includes(".")) return false;
-  return true;
-}
 
 function getQuesionCont(cont: string) {
   if (!cont) return "#";
@@ -150,6 +144,11 @@ function getQuesionCont(cont: string) {
   return cont;
 }
 
+function checkQuestionChecked(index: number) {
+  if (!dataCheckStore.curStudent) return false;
+  return dataCheckStore.curStudent.handleQuestionIndexs?.includes(index);
+}
+
 // question edit
 const quesionEditShow = ref(false);
 const quesionEditPos = ref({
@@ -205,6 +204,17 @@ function onSaveQuesion() {
   questionList.value[curQuestionIndex.value] = questionCont;
   quesionEditShow.value = false;
 
+  // 修改状态
+  const index = curQuestionIndex.value;
+  const oldVal = dataCheckStore.curStudent.originQuestions[index];
+  dataCheckStore.curStudent.handleQuestionIndexs =
+    dataCheckStore.curStudent.handleQuestionIndexs?.filter(
+      (item) => item !== index
+    );
+  if (oldVal !== questionCont) {
+    dataCheckStore.curStudent.handleQuestionIndexs?.push(index);
+  }
+
   emit("update:questions", questionList.value);
   emit("change", questionList.value);
 }
@@ -215,7 +225,6 @@ function onEditExamNumber() {
   if (!dataCheckStore.curPage) return;
   editExamNumberDialogRef.value?.open();
 }
-const curPage = computed(() => dataCheckStore.curPage);
 async function examNumberModified(examNumber: string) {
   if (!dataCheckStore.curStudent) return;
 
@@ -226,6 +235,8 @@ async function examNumberModified(examNumber: string) {
 watch(
   () => props.questions,
   (val) => {
+    // console.log(`props.questions:${Date.now()}`, val);
+
     if (!val) return;
     questionList.value = [...val];
   },
@@ -280,6 +291,16 @@ onMounted(() => {});
         }
       }
 
+      &.is-checked {
+        color: @success-color;
+
+        .ant-btn.ant-gray {
+          border-color: @success-color;
+          color: @success-color;
+          background-color: #f6ffed;
+        }
+      }
+
       > span {
         display: inline-block;
         width: 30px;
@@ -288,8 +309,9 @@ onMounted(() => {});
         font-size: 13px;
       }
       .ant-btn {
-        padding-left: 10px;
-        padding-right: 10px;
+        padding-left: 5px;
+        padding-right: 5px;
+        min-width: 32px;
 
         &.is-active {
           border-color: @brand-color;

+ 8 - 3
src/render/views/ExamNumberCheck/ScanImage/RecogEditDialog.vue

@@ -82,7 +82,7 @@ import { message } from "ant-design-vue";
 import useModal from "@/hooks/useModal";
 import { RecogBlock } from "@/utils/recog/recog";
 import { getBoxImageSize, recogResultTransform } from "@/utils/tool";
-import { useUserStore } from "@/store";
+import { useUserStore, useDataCheckStore } from "@/store";
 
 defineOptions({
   name: "RecogEditDialog",
@@ -98,6 +98,7 @@ const props = defineProps<{
 
 const emit = defineEmits(["confirm", "close"]);
 const userStore = useUserStore();
+const dataCheckStore = useDataCheckStore();
 
 const selectResult = ref([] as string[]);
 
@@ -148,6 +149,8 @@ const areaImgStyle = ref({});
 function areaImgLoad() {
   const areaImgDom = areaImgRef.value as HTMLImageElement;
   const boxDom = areaImgDom.parentNode?.parentNode as HTMLDivElement;
+  const recogDpi = dataCheckStore.curPage.recogDpi || 150;
+  const scaleRate = (1.5 * 150) / recogDpi;
 
   const imgSize = getBoxImageSize({
     box: {
@@ -155,8 +158,8 @@ function areaImgLoad() {
       height: boxDom.offsetHeight - 22,
     },
     img: {
-      width: areaImgDom.naturalWidth,
-      height: areaImgDom.naturalHeight,
+      width: areaImgDom.naturalWidth * scaleRate,
+      height: areaImgDom.naturalHeight * scaleRate,
     },
     rotate: 0,
   });
@@ -249,6 +252,8 @@ watch(
 watch(
   () => props.recogData,
   (val) => {
+    console.log(`props.recogData:${Date.now()}`, val);
+
     if (!val) return;
     selectResult.value = [...props.recogData.result];
   }

+ 30 - 6
src/render/views/ExamNumberCheck/ScanImage/index.vue

@@ -82,8 +82,9 @@
   />
   <!-- EditExamNumberDialog -->
   <EditExamNumberDialog
+    v-if="dataCheckStore.curStudent"
     ref="editExamNumberDialogRef"
-    :data="info.examNumber"
+    :data="dataCheckStore.curStudent.examNumber"
     @confirm="examNumberModified"
   />
   <!-- ConfirmTips -->
@@ -204,8 +205,11 @@ function initImageSize() {
     getTemporaryImgViewConfig(route.path) ||
     objAssign(imageSize.value, imgSize);
 
+  // console.log(`image-loaded:${Date.now()}`, dataCheckStore.curPage.sheetUri);
+
   nextTick(() => {
     updateRecogList();
+    updatePageTasks(dataCheckStore.curPage);
   });
 }
 
@@ -290,7 +294,6 @@ function updateRecogList() {
   });
 
   parseRecogBlocks();
-  updatePageTasks(dataCheckStore.curPage);
 }
 // recogBlocks
 const recogBlocks = ref<RecogBlock[]>([]);
@@ -372,6 +375,7 @@ async function examNumberModified(examNumber: string) {
 
   dataCheckStore.modifyExamNumber(examNumber);
   await save();
+  taskFinished();
 }
 
 // area click
@@ -398,6 +402,17 @@ async function onRecogEditConfirm(result: string[]) {
     dataCheckStore.curPage.question.result.splice(index, 1, result.join(""));
     curRecogBlock.value.result = result;
     await save();
+    taskFinished();
+
+    // 修改状态
+    const oldVal = dataCheckStore.curStudent.originQuestions[index];
+    dataCheckStore.curStudent.handleQuestionIndexs =
+      dataCheckStore.curStudent.handleQuestionIndexs?.filter(
+        (item) => item !== index
+      );
+    if (oldVal !== result) {
+      dataCheckStore.curStudent.handleQuestionIndexs?.push(index);
+    }
   }
 }
 
@@ -460,6 +475,8 @@ function onSetRecogStyle() {
 watch(
   () => dataCheckStore.curPage?.question?.result,
   (val) => {
+    console.log(`dataCheckStore.curPage?.question?.result:${Date.now()}`, val);
+
     if (!val) return;
     updateRecogList();
 
@@ -480,19 +497,26 @@ watch(
 watch(
   () => dataCheckStore.curTask,
   (val) => {
+    // console.log(`dataCheckStore.curTask:${Date.now()}`, val);
+
+    // Add async
     if (!val) {
       editExamNumberDialogRef.value?.close();
       recogEditDialogRef.value?.close();
+      curRecogBlock.value = null; // Clear block when task is null
       return;
     }
     if (val.type === "examNumber") {
+      recogEditDialogRef.value?.close(); // Close other dialog
       editExamNumberDialogRef.value?.open();
     } else {
-      const questionRecog = recogList.value.find(
-        (item) => item.index === val.questionIndex
+      editExamNumberDialogRef.value?.close(); // Close other dialog
+      // Find block in recogBlocks (already processed with styles)
+      const questionRecogBlock = recogBlocks.value.find(
+        (item) => item.index - 1 === val.questionIndex
       );
-      if (!questionRecog) return;
-      onAreaClick(questionRecog);
+      if (!questionRecogBlock) return;
+      onAreaClick(questionRecogBlock);
     }
   },
   {

+ 2 - 0
src/render/views/ExamNumberCheck/api.ts

@@ -26,6 +26,8 @@ export const allCheckList = async (
       checked: cacheList.includes(item.imageName),
     };
   });
+  console.log(data);
+
   return Promise.resolve(data);
 };
 

+ 39 - 23
src/render/views/ExamNumberCheck/index.vue

@@ -2,7 +2,7 @@
   <div class="data-check exam-number-check">
     <div class="check-menu">
       <div class="check-menu-head">
-        <a-tabs v-model:menuKey="menuKey" size="small" @change="menuChange">
+        <a-tabs v-model:activeKey="menuKey" size="small" @change="menuChange">
           <a-tab-pane key="examNumber" tab="准考证号"></a-tab-pane>
           <a-tab-pane key="question" tab="客观题"></a-tab-pane>
         </a-tabs>
@@ -46,7 +46,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed, onBeforeUnmount } from "vue";
+import { ref, reactive, onMounted, onBeforeUnmount } from "vue";
 import { message } from "ant-design-vue";
 import {
   CaretLeftOutlined,
@@ -72,7 +72,7 @@ const dataCheckStore = useDataCheckStore();
 const appStore = useAppStore();
 dataCheckStore.resetInfo();
 
-const menuKey = ref("examNumber");
+const menuKey = ref("");
 
 let searchModel = {} as DataCheckListFilter;
 const pageNumber = ref(1);
@@ -103,7 +103,7 @@ async function getAllStudents(data: AllCheckFilter) {
   allStudentList.value = res;
 }
 
-async function getList() {
+function getList() {
   studentList.value = buildStudentList(
     allStudentList.value.slice(
       (pageNumber.value - 1) * pageSize.value,
@@ -123,6 +123,7 @@ function buildStudentList(dataList: StudentCheckItem[]): DataCheckListItem[] {
       ...item,
       id: studentId,
       examNumber: item.zkzh,
+      originQuestions: [...questions],
       papers: [
         {
           id: `${studentId}_1`,
@@ -183,8 +184,7 @@ function parseStudentPageList(students: DataCheckListItem[]) {
 }
 
 // menu
-async function menuChange(key: string) {
-  menuKey.value = key;
+async function menuChange() {
   allStudentList.value = menuStudents.value[menuKey.value];
   total.value = allStudentList.value.length;
   pageCount.value = Math.ceil(total.value / pageSize.value);
@@ -201,22 +201,37 @@ function onChangeListPage(index: number) {
 }
 async function onSearch(data: AllCheckFilter) {
   await getAllStudents(data);
-  const mk = menuStudents.value["examNumber"].length
-    ? "examNumber"
-    : "question";
-  await menuChange(mk);
+  if (menuKey.value && menuStudents.value[menuKey.value].length) {
+    await menuChange();
+    return;
+  }
+
+  const mk = menuStudents.value.examNumber.length ? "examNumber" : "question";
+  menuKey.value = mk;
+  await menuChange();
 }
 
 // student
 async function onSelectStudent(index: number) {
+  dataCheckStore.setInfo({
+    taskList: [],
+    curTask: null,
+  });
   const student = studentList.value[index];
   if (!student) return;
-  if (student.checked) {
-    const info = await getExamNumberInfo(student.imageName);
-    if (info) {
-      student.examNumber = info.zkzh;
-      student.papers[0].pages[0].question.result = info.questions;
-    }
+
+  const info = await getExamNumberInfo(student.imageName);
+  if (info) {
+    const handleQuestionIndexs = [];
+    student.originQuestions.forEach((item, index) => {
+      if (info.questions[index] && item !== info.questions[index]) {
+        handleQuestionIndexs.push(index);
+      }
+    });
+
+    student.handleQuestionIndexs = handleQuestionIndexs;
+    student.examNumber = info.zkzh;
+    student.papers[0].pages[0].question.result = info.questions;
   }
 
   const pageIndex = dataList.value.findIndex(
@@ -235,7 +250,7 @@ async function onPrevStudent() {
     }
 
     pageNumber.value--;
-    await getList();
+    getList();
     await onSelectStudent(studentList.value.length - 1);
     return;
   }
@@ -244,6 +259,9 @@ async function onPrevStudent() {
 }
 
 async function onNextStudent() {
+  if (!dataCheckStore.curStudent) return;
+
+  dataCheckStore.curStudent.checked = true;
   if (dataCheckStore.curStudentIndex >= studentList.value.length - 1) {
     if (pageNumber.value >= pageCount.value) {
       message.error("没有下一个学生了");
@@ -251,7 +269,7 @@ async function onNextStudent() {
     }
 
     pageNumber.value++;
-    await getList();
+    getList();
     await onSelectStudent(0);
     return;
   }
@@ -275,7 +293,7 @@ function getImgSize(url: string) {
   return new Promise<{ width: number; height: number }>((resolve) => {
     const img = new Image();
     img.src = url;
-    console.log(url);
+    // console.log(url);
 
     img.onload = () => {
       resolve({
@@ -297,8 +315,6 @@ async function selectPage(index: number) {
     curPageIndex: index,
   });
 
-  updatePageTasks(dataList.value[index]);
-
   if (!dataCheckStore.curPage) return;
 
   const curStudent = studentList.value[
@@ -318,7 +334,7 @@ async function onPrevPage() {
     }
 
     pageNumber.value--;
-    await getList();
+    getList();
     await selectPage(dataList.value.length - 1);
     return;
   }
@@ -334,7 +350,7 @@ async function onNextPage() {
     }
 
     pageNumber.value++;
-    await getList();
+    getList();
     await selectPage(0);
     return;
   }

+ 44 - 25
src/render/views/ExamNumberCheck/useTask.ts

@@ -1,38 +1,32 @@
 import { useDataCheckStore, useAppStore } from "@/store";
-import { StudentPage } from "./types";
+import { StudentPage, TaskItem } from "./types";
 
 export default function useTask() {
   const dataCheckStore = useDataCheckStore();
 
   function updatePageTasks(curPage: StudentPage) {
-    if (!curPage) {
+    if (!curPage || !dataCheckStore.curStudent) {
       dataCheckStore.setInfo({
-        taskList:[],
+        taskList: [],
         curTask: null,
       });
       return;
     }
-  
-    if (menuKey.value === "examNumber") {
-      const taskList = [
-        {
-          id: `examNumber_${curPage.studentId}`
-          type: "examNumber",
-          questionIndex: 0,
-          paperIndex: 0,
-          pageIndex: 0,
-          studentId: curPage.studentId,
-          finished: false,
-        },
-      ];
-      dataCheckStore.setInfo({
-        taskList,
-        curTask: taskList[0],
+
+    const taskList = [] as TaskItem[];
+    const examNumber = dataCheckStore.curStudent.examNumber;
+    if (!examNumber || examNumber.includes(".")) {
+      taskList.push({
+        id: `examNumber_${curPage.studentId}`,
+        type: "examNumber",
+        questionIndex: 0,
+        paperIndex: 0,
+        pageIndex: 0,
+        studentId: curPage.studentId,
+        finished: false,
       });
-      return;
     }
-  
-    const taskList = [];
+
     curPage.question?.result.map((item, index) => {
       if (!item || item.length > 1) {
         taskList.push({
@@ -46,15 +40,13 @@ export default function useTask() {
         });
       }
     });
-  
+
     dataCheckStore.setInfo({
       taskList,
       curTask: taskList[0],
     });
   }
 
-  
-
   function updateNextUnfinishTask() {
     const task = dataCheckStore.taskList.find((item) => !item.finished);
     dataCheckStore.curTask = task || null;
@@ -69,9 +61,36 @@ export default function useTask() {
     updateNextUnfinishTask();
   }
 
+  function checkExamNumber(examNumber: string) {
+    if (!examNumber) return false;
+    if (examNumber.includes(".")) return false;
+    return true;
+  }
+
+  function checkQuestionError(cont: string) {
+    if (!cont) return true;
+    if (cont.length > 1) return true;
+    return false;
+  }
+
+  function checkPageFinished(questions: string[], examNumber: string) {
+    if (!questions.length || !examNumber) return false;
+
+    const examNumberFinished = checkExamNumber(examNumber);
+    if (!examNumberFinished) return false;
+
+    const questionFinished = !questions.some((item) =>
+      checkQuestionError(item)
+    );
+    return questionFinished;
+  }
+
   return {
     updatePageTasks,
     updateNextUnfinishTask,
     taskFinisheHandle,
+    checkExamNumber,
+    checkQuestionError,
+    checkPageFinished,
   };
 }