Forráskód Böngészése

bug修复和联通扫描端

刘洋 9 hónapja
szülő
commit
6419403ffa

+ 2 - 1
package.json

@@ -30,6 +30,7 @@
     "pinia": "^2.1.6",
     "pinia-plugin-persistedstate": "^3.2.1",
     "spark-md5": "^3.0.2",
+    "uuid": "^11.0.0-0",
     "v3-drag-zoom": "^1.1.20",
     "vue": "^3.4.32",
     "vue-echarts": "^7.0.0-beta.0",
@@ -74,4 +75,4 @@
     "webpack-cli": "^5.1.4",
     "webpack-dev-server": "^4.15.1"
   }
-}
+}

+ 73 - 2
src/main/preload/index.ts

@@ -6,8 +6,36 @@
 const { contextBridge, ipcRenderer } = require("electron");
 const os = require("os");
 const path = require("path");
+const fs = require("fs");
+const { v4: uuidv4 } = require("uuid");
+const execs = require("child_process").exec;
+
 const isDev = process.env.NODE_ENV === "development";
 
+const isRunning = (query: string, cb: Function) => {
+  // let platform = process.platform;
+  // let cmd = "";
+  // switch (platform) {
+  //   case "win32":
+  //     cmd = `tasklist`;
+  //     break;
+  //   case "darwin":
+  //     cmd = `ps -ax | grep ${query}`;
+  //     break;
+  //   case "linux":
+  //     cmd = `ps -A`;
+  //     break;
+  //   default:
+  //     break;
+  // }
+  execs(
+    "cmd /c chcp 65001>nul && tasklist /FO CSV",
+    (err: any, stdout: any, stderr: any) => {
+      cb(stdout.toLowerCase().indexOf(query.toLowerCase()) > -1);
+    }
+  );
+};
+
 contextBridge.exposeInMainWorld("electronApi", {
   getComputerName: () => {
     return os.hostname();
@@ -18,12 +46,55 @@ contextBridge.exposeInMainWorld("electronApi", {
   windowMin: () => {
     ipcRenderer.send("window-min");
   },
-  startScanExe: () => {
+  startScanExe: (arr: string[]) => {
     let scanExeFold: string = isDev
       ? process.cwd()
       : process.env.PORTABLE_EXECUTABLE_DIR || "";
     const exePath = path.join(scanExeFold as string, "test.exe");
     console.log("exePath", exePath);
-    ipcRenderer.send("startExe", exePath + " 参数1 参数2 参数3");
+    ipcRenderer.send("startExe", exePath + " " + arr.join(" "));
+  },
+  getUuid: () => {
+    return new Promise((rs, rj) => {
+      let userDir = os.homedir();
+      let uuidFilePath = path.resolve(userDir, "scanUuid.txt");
+      if (fs.existsSync(uuidFilePath)) {
+        fs.readFile(uuidFilePath, "utf8", (err: any, data: any) => {
+          if (err) rj('"获取uuid文件异常!"');
+          rs(data);
+        });
+      } else {
+        const uuid = uuidv4();
+        fs.writeFile(uuidFilePath, uuid, (err: any) => {
+          if (err) {
+            rj("uuid保存异常!");
+          } else {
+            rs(uuid);
+          }
+        });
+      }
+    });
+  },
+  watchScanProcess: () => {
+    let num = 10;
+    const watchStep = (rs: any, rj: any) => {
+      isRunning("client.exe", (status: boolean) => {
+        if (status) {
+          rs(true);
+        } else {
+          if (num == 0) {
+            rj();
+            return;
+          }
+          num--;
+          setTimeout(() => {
+            watchStep(rs, rj);
+          }, 1000);
+        }
+      });
+    };
+    return new Promise((rs, rj) => {
+      watchStep(rs, rj);
+    });
   },
 });

+ 11 - 2
src/render/ap/baseDataConfig.ts

@@ -68,10 +68,10 @@ export const getCardList = (params: { examId: number } & PageBaseParams) =>
   });
 
 export const importCard = async (params: {
-  examId: number;
+  examId: any;
   subjectCode: string;
   remark?: string;
-  file: File;
+  file: any;
 }) => {
   const md5 = await getFileMD5(params.file);
   const formData = obj2formData(params);
@@ -134,3 +134,12 @@ export const importStu = async (params: {
     },
   });
 };
+
+export const exportStu = (params: { examId: any }) => {
+  return request({
+    url: "/api/admin/student/import/template",
+    method: "get",
+    params,
+    download: true,
+  });
+};

+ 6 - 0
src/render/ap/system.ts

@@ -12,6 +12,12 @@ export const adminLogin = (params: { loginName: string; password: string }) =>
     params,
     loading: true,
   });
+export const scanLogin = (params: { device: string; deviceName: string }) =>
+  request({
+    url: "/api/user/scanner/login",
+    params,
+    loading: true,
+  });
 export const getSubjectList = (params: { examId: number | null }) =>
   request({
     url: "/api/admin/subject/list",

+ 1 - 1
src/render/components/SelectSubject/index.vue

@@ -19,7 +19,7 @@ import { getSubjectList } from "@/ap/system";
 
 const props = withDefaults(
   defineProps<{
-    examId: number;
+    examId: any;
     modelValue: string;
     placeholder?: string;
   }>(),

+ 3 - 1
src/render/utils/request.ts

@@ -7,7 +7,7 @@ import { getAuthorization, getMD5 } from "./crypto";
 import router from "@/router";
 import { initSyncTime, fetchTime } from "./syncServerTime";
 import { local } from "@/utils/tool";
-import { useAppStore } from "@/store";
+import { useAppStore, useUserStore } from "@/store";
 import { message } from "@qmth/ui";
 
 function getDeviceId() {
@@ -106,6 +106,7 @@ function createService() {
           );
       };
       if (error.response) {
+        const userStore = useUserStore();
         switch (error.response.status) {
           case 404:
             err(`服务器资源不存在`);
@@ -115,6 +116,7 @@ function createService() {
             break;
           case 401:
             message.error("登录状态已过期");
+            userStore.setUserInfo(null);
             router.replace({ name: "Login" });
             break;
           case 403:

+ 15 - 2
src/render/views/BaseDataConfig/ImportCardDialog.vue

@@ -15,13 +15,21 @@
       <template #file>
         <ImportButton @fileChange="getFile" />
       </template>
+      <template #subjectCode>
+        <SelectSubject
+          v-model="params.subjectCode"
+          :exam-id="userStore.curExam?.id"
+        ></SelectSubject>
+      </template>
     </qm-low-form>
   </my-modal>
 </template>
 <script name="ImportCardDialog" lang="ts" setup>
 import { ref, reactive } from "vue";
 import { importCard } from "@/ap/baseDataConfig";
-
+import { useUserStore } from "@/store";
+import SelectSubject from "@/components/SelectSubject/index.vue";
+const userStore = useUserStore();
 const form = ref();
 const visible = defineModel();
 const emit = defineEmits(["success"]);
@@ -45,7 +53,12 @@ const getFile = (file: any) => {
   params.file = file;
 };
 const submitHandle = () => {
-  form.value.formRef.validate().then(() => {});
+  form.value.formRef.validate().then(() => {
+    importCard({ examId: userStore.curExam?.id, ...params }).then(() => {
+      window.$message.success("导入成功");
+      visible.value = false;
+    });
+  });
 };
 </script>
 <style lang="less" scoped></style>

+ 2 - 2
src/render/views/BaseDataConfig/StuImportFileDialog.vue

@@ -25,7 +25,7 @@
 </template>
 <script name="StuImportFileDialog" lang="ts" setup>
 import { ref, reactive, h } from "vue";
-import { importStu } from "@/ap/baseDataConfig";
+import { importStu, exportStu } from "@/ap/baseDataConfig";
 import { VerticalAlignBottomOutlined } from "@ant-design/icons-vue";
 import { downloadByCrossUrl } from "@/utils/tool";
 import { useUserStore } from "@/store";
@@ -60,7 +60,7 @@ const submitHandle = () => {
   });
 };
 const downloadTpl = () => {
-  downloadByCrossUrl("/api/admin/student/import/template", "考生导入模板");
+  exportStu({ examId: userStore.curExam.id });
 };
 </script>
 <style lang="less" scoped></style>

+ 1 - 0
src/render/views/BaseDataConfig/UserManage.vue

@@ -141,6 +141,7 @@ const toggleStatus = (row: any, status: boolean) => {
     onOk() {
       toggleUserStatus({ userId: row.id, enable: status }).then((res: any) => {
         window.$message.success("操作成功");
+        toPage(1);
       });
     },
     onCancel() {

+ 41 - 2
src/render/views/Login/LoginWays.vue

@@ -52,13 +52,52 @@ import {
   GlobalOutlined,
 } from "@ant-design/icons-vue";
 import FooterInfo from "@/components/FooterInfo/index.vue";
+import { local } from "@/utils/tool";
+import { scanLogin } from "@/ap/system";
+import { useAppStore } from "@/store";
 
 const emit = defineEmits(["next", "toIndex"]);
 const activeName = ref("scan");
 
-const nextStep = () => {
+const nextStep = async () => {
   if (activeName.value === "scan") {
-    window.electronApi.startScanExe();
+    let deviceName = window.electronApi?.getComputerName?.();
+    let device = await window.electronApi?.getUuid?.();
+    let res = await scanLogin({ device, deviceName });
+    console.log("扫描员登录成功", res);
+    let baseUrl = local.get("baseUrl");
+    let ipArr = baseUrl.split("//")[1].split(":");
+    window.electronApi.startScanExe([
+      ...ipArr,
+      res.sessionId,
+      res.accessToken,
+      window.devicePixelRatio,
+    ]);
+    const appStore = useAppStore();
+    appStore.loadingStatus = {
+      spinning: true,
+      tip: "扫描端启动中...",
+    };
+    setTimeout(() => {
+      //如果10秒了扫描端还没启动起来,估计有异常情况,于是关掉全屏loading
+      appStore.loadingStatus = {
+        spinning: false,
+        tip: "",
+      };
+    }, 1000);
+    //同时监测进程,如果发现扫描端启动了,立刻关掉全屏loading,且关掉本项目
+    try {
+      let result = await window.electronApi?.watchScanProcess();
+      if (result) {
+        window.close();
+      }
+    } catch (err: any) {
+      appStore.loadingStatus = {
+        spinning: false,
+        tip: "",
+      };
+      window.$message.error("扫描端启动异常!请检查扫描端文件!");
+    }
   } else {
     emit("next");
   }