zhangjie пре 1 месец
родитељ
комит
2a122472c3

+ 2 - 0
app.ini

@@ -0,0 +1,2 @@
+[base]
+serverUrl=http://192.168.10.214:8080

+ 17 - 0
src/main/index.ts

@@ -86,6 +86,23 @@ function registEvent() {
       event.sender.send("got-page-size-ini", content);
     });
   });
+
+  ipcMain.handle("get-app-ini", async () => {
+    const appPath = isDev ? process.cwd() : path.dirname(app.getPath("exe"));
+    const iniFilePath = path.resolve(appPath, "app.ini");
+    try {
+      const data = await fs.promises.readFile(iniFilePath, "utf8");
+      const content = IniParser.parse(data);
+      return content;
+    } catch (err: any) {
+      logger.error(`读取或解析 app.ini 文件失败: ${err.message}`);
+      dialog.showErrorBox(
+        "错误",
+        `读取或解析 app.ini 文件失败!\n${err.message}`
+      );
+      return null; // 返回 null 表示失败
+    }
+  });
 }
 
 app.on("ready", async () => {

+ 3 - 0
src/main/preload/index.ts

@@ -105,4 +105,7 @@ contextBridge.exposeInMainWorld("electronApi", {
       cb(content);
     });
   },
+  getAppIni: () => {
+    return ipcRenderer.invoke("get-app-ini");
+  },
 });

+ 5 - 5
src/render/App.vue

@@ -14,11 +14,11 @@
 <script lang="ts" name="App" setup>
 import { useAppStore, useUserStore } from "./store";
 const appStore = useAppStore();
-const userStore = useUserStore();
-userStore.initHeatBeat();
-if (userStore.userInfo) {
-  userStore.startHeatBeat();
-}
+// const userStore = useUserStore();
+// userStore.initHeatBeat();
+// if (userStore.userInfo) {
+//   userStore.startHeatBeat();
+// }
 </script>
 <style lang="less">
 .app-in {

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

@@ -55,6 +55,7 @@ export interface PaperPageItem {
   selective: { type: string; result: string } | null;
   recogData: string | null;
   recogUri?: string | null;
+  recogDpi: number;
 }
 
 // 某张缺页时没有id和pages等其他字段

+ 1 - 0
src/render/components.d.ts

@@ -16,6 +16,7 @@ declare module 'vue' {
     ADescriptions: typeof import('@qmth/ui')['Descriptions']
     ADescriptionsItem: typeof import('@qmth/ui')['DescriptionsItem']
     ADivider: typeof import('@qmth/ui')['Divider']
+    ADrawer: typeof import('@qmth/ui')['Drawer']
     AForm: typeof import('@qmth/ui')['Form']
     AFormItem: typeof import('@qmth/ui')['FormItem']
     AInput: typeof import('@qmth/ui')['Input']

+ 1 - 1
src/render/store/modules/app/index.ts

@@ -13,7 +13,7 @@ export const useAppStore = defineStore<"app", any, any, any>("app", {
       tip: "",
     },
     timeDiff: 0,
-    serverUrl: "http://192.168.10.214:8080",
+    serverUrl: "",
   }),
   actions: {
     setServerStatus(obj: any) {

+ 4 - 9
src/render/views/ExamNumberCheck/EditExamNumberDialog.vue

@@ -1,23 +1,18 @@
 <template>
-  <a-modal
-    v-model:open="visible"
-    :width="424"
-    style="top: 10vh"
-    title="输入考号"
-    @ok="confirm"
-  >
+  <a-drawer v-model:open="visible" :width="396" title="输入考号">
     <a-form ref="formRef" :label-col="{ style: { width: '50px' } }">
       <a-form-item label="考号">
-        <div class="exam-number">
+        <div class="exam-number" style="margin-bottom: 10px">
           <a-input
             v-model:value="examNumber"
             placeholder="请输入"
             allow-clear
           ></a-input>
         </div>
+        <a-button type="primary" @click="confirm">保存</a-button>
       </a-form-item>
     </a-form>
-  </a-modal>
+  </a-drawer>
 </template>
 
 <script setup lang="ts">

+ 6 - 6
src/render/views/ExamNumberCheck/QuestionPanel.vue

@@ -1,16 +1,16 @@
 <template>
   <div class="question-panel">
-    <a-descriptions v-if="info" class="panel-info" :column="10">
-      <a-descriptions-item label="准考证号" :span="10">
+    <a-form :label-col="{ style: { width: '80px' } }">
+      <a-form-item label="准考证号">
         <a-button class="ant-gray m-r-4px">{{ info.examNumber }}</a-button>
         <a-button @click="onEditPaperType">
           <template #icon><SwapOutlined /></template>
         </a-button>
-      </a-descriptions-item>
-      <a-descriptions-item label="问题" :span="10">
+      </a-form-item>
+      <a-form-item label="问题" :span="10">
         {{ info.info }}
-      </a-descriptions-item>
-    </a-descriptions>
+      </a-form-item>
+    </a-form>
     <div
       v-if="!simple && dataCheckStore.curPage?.question"
       ref="panelBodyRef"

+ 40 - 1
src/render/views/ExamNumberCheck/ScanImage/index.vue

@@ -208,6 +208,42 @@ function getNumberResult(
   return Array.from(nResult).map((item) => item || 0);
 }
 
+function transformRecogData(
+  recogItem: RecognizeArea,
+  scaleRate: number
+): RecognizeArea {
+  if (scaleRate === 1) return recogItem;
+
+  return {
+    ...recogItem,
+    fillArea: {
+      x: recogItem.fillArea.x * scaleRate,
+      y: recogItem.fillArea.y * scaleRate,
+      w: recogItem.fillArea.w * scaleRate,
+      h: recogItem.fillArea.h * scaleRate,
+    },
+    optionSizes: recogItem.optionSizes.map((item) => {
+      return {
+        x: item.x * scaleRate,
+        y: item.y * scaleRate,
+        w: item.w * scaleRate,
+        h: item.h * scaleRate,
+        filled: item.filled,
+      };
+    }),
+    fillSize: {
+      w: recogItem.fillSize.w * scaleRate,
+      h: recogItem.fillSize.h * scaleRate,
+    },
+    fillPosition: recogItem.fillPosition.map((item) => {
+      return {
+        x: item.x * scaleRate,
+        y: item.y * scaleRate,
+      };
+    }),
+  };
+}
+
 // recog data
 const recogList = ref<RecognizeArea[]>([]);
 function updateRecogList() {
@@ -215,6 +251,8 @@ function updateRecogList() {
 
   if (!dataCheckStore.curPage) return;
   const regdata = dataCheckStore.curPage.recogData;
+  const recogDpi = dataCheckStore.curPage.recogDpi || 150;
+  const scaleRate = recogDpi / 150;
   if (!regdata) return;
 
   let index = 0;
@@ -233,7 +271,8 @@ function updateRecogList() {
         getNumberResult(questionResult, ABC),
         result === "#"
       );
-      recogList.value.push(recogItem);
+
+      recogList.value.push(transformRecogData(recogItem, scaleRate));
     });
   });
 

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

@@ -35,6 +35,7 @@ export const allCheckList = async (): Promise<DataCheckListResult> => {
               selective: null,
               recogData: null,
               recogUri: `${appStore.serverUrl}/omr/${item.imageName}.json`,
+              recogDpi: 150,
             },
           ],
         },
@@ -139,7 +140,7 @@ export const fetchAndParseData = async (remoteUrl: string): Promise<any> => {
  */
 export const uploadCsvData = async (
   uploadUrl: string,
-  data: any[],
+  data: string[][],
   filename: string = "upload.csv"
 ): Promise<any> => {
   try {

+ 38 - 2
src/render/views/ExamNumberCheck/index.vue

@@ -44,7 +44,7 @@ import { CaretLeftOutlined, CaretRightOutlined } from "@ant-design/icons-vue";
 import { DataCheckListFilter, DataCheckListItem } from "@/ap/types/dataCheck";
 import { allCheckList, fetchAndParseData } from "./api";
 import { StudentPage } from "./types";
-import { useDataCheckStore } from "@/store";
+import { useDataCheckStore, useAppStore } from "@/store";
 
 import SimplePagination from "@/components/SimplePagination/index.vue";
 import ScanImage from "./ScanImage/index.vue";
@@ -55,6 +55,7 @@ defineOptions({
 });
 
 const dataCheckStore = useDataCheckStore();
+const appStore = useAppStore();
 dataCheckStore.resetInfo();
 
 let searchModel = {} as DataCheckListFilter;
@@ -174,9 +175,38 @@ async function onNextStudent() {
   onSelectStudent(dataCheckStore.curStudentIndex + 1);
 }
 
+function getImgDpi(imgWidth: number): number {
+  const dpi = (25.4 * imgWidth) / 183;
+
+  if (Math.abs(dpi - 100) < 5) {
+    return 100;
+  }
+  if (Math.abs(dpi - 150) < 5) {
+    return 150;
+  }
+  return 150;
+}
+
+function getImgSize(url: string) {
+  return new Promise<{ width: number; height: number }>((resolve) => {
+    const img = new Image();
+    img.src = url;
+    console.log(url);
+
+    img.onload = () => {
+      resolve({
+        width: img.width,
+        height: img.height,
+      });
+    };
+  });
+}
+
 // page
 async function selectPage(index: number) {
   const recogData = await fetchAndParseData(dataList.value[index].recogUri);
+  const size = await getImgSize(dataList.value[index].sheetUri);
+  dataList.value[index].recogDpi = getImgDpi(size.width);
   dataList.value[index].recogData = recogData;
   dataCheckStore.setInfo({
     curPage: dataList.value[index],
@@ -259,7 +289,13 @@ function shortcutHandle(e: KeyboardEvent) {
   }
 }
 
-onMounted(() => {
+onMounted(async () => {
+  const appConfig = await window.electronApi.getAppIni();
+  if (!appConfig.base.serverUrl) {
+    message.error("请先设置服务器地址");
+    return;
+  }
+  appStore.setState({ serverUrl: appConfig.base.serverUrl });
   registShortcut();
   onSearch();
 });