ソースを参照

心跳和登出

刘洋 9 ヶ月 前
コミット
90b7a4417b

+ 6 - 1
src/render/App.vue

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

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

@@ -17,3 +17,12 @@ export const getSubjectList = (params: { examId: number | null }) =>
     url: "/api/admin/subject/list",
     params,
   });
+
+export const adminLogout = () =>
+  request({
+    url: "/api/user/logout",
+  });
+export const heatBeatApi = () =>
+  request({
+    url: "/api/sys/heartbeat",
+  });

+ 26 - 2
src/render/store/modules/user/index.ts

@@ -1,6 +1,9 @@
 import { defineStore } from "pinia";
 import router from "@/router";
+import { adminLogout, heatBeatApi } from "@/ap/system";
+import HeatBeatWorker from "@/utils/heatbeat.worker?worker";
 
+const heatBeatWorker = new HeatBeatWorker();
 interface RecogFillSetType {
   fillColor: string;
   fillShow: boolean;
@@ -12,6 +15,7 @@ interface RecogFillSetType {
 export const useUserStore = defineStore<
   "user",
   {
+    heatBeatWorker: Worker | null;
     curExam: Exam | null;
     imageCheckLoopTime: number;
     userInfo: any;
@@ -31,6 +35,8 @@ export const useUserStore = defineStore<
     },
   ],
   state: () => ({
+    heatBeatWorker: null,
+    heatBeatIsActive: false,
     userInfo: null,
     curExam: null,
     imageCheckLoopTime: 0,
@@ -43,8 +49,27 @@ export const useUserStore = defineStore<
     },
   }),
   actions: {
+    initHeatBeat() {
+      this.heatBeatWorker = new HeatBeatWorker();
+      this.heatBeatWorker.onmessage = (e: any) => {
+        const data = e.data;
+        if (typeof e.data === "boolean") {
+          this.heatBeatIsActive = !!data;
+        } else if (e.data === "") {
+          heatBeatApi();
+        }
+      };
+    },
+    startHeatBeat() {
+      this.heatBeatWorker.postMessage(true);
+    },
     setUserInfo(info: any) {
       this.userInfo = info;
+      if (!info) {
+        this.heatBeatWorker.postMessage(false);
+      } else {
+        this.heatBeatWorker.postMessage(true);
+      }
     },
     setCurExam(exam: Exam) {
       this.curExam = exam;
@@ -62,8 +87,7 @@ export const useUserStore = defineStore<
       this.$reset();
     },
     async logout() {
-      //todo 退出登录接口
-      // await logout();
+      await adminLogout();
       this.setUserInfo(null);
       router.push({ name: "Login" });
       window.electronApi?.changeWinSize("small");

+ 32 - 0
src/render/utils/heatbeat.worker.ts

@@ -0,0 +1,32 @@
+class HeatBeatInterval {
+  timer: any = null;
+  send() {
+    postMessage("");
+  }
+  isActive = false;
+  pause() {
+    if (this.timer) {
+      clearInterval(this.timer);
+      this.timer = null;
+    }
+    this.isActive = false;
+    postMessage(false);
+  }
+  resume() {
+    const func = this.send;
+    this.timer = setInterval(func, 10000);
+    this.isActive = true;
+    postMessage(true);
+  }
+}
+
+const heatBeatInterval = new HeatBeatInterval();
+
+addEventListener("message", (e: any) => {
+  const data = e.data as boolean;
+  if (data) {
+    heatBeatInterval.resume();
+  } else {
+    heatBeatInterval.pause();
+  }
+});

+ 0 - 1
src/render/views/Login/LoginWays.vue

@@ -58,7 +58,6 @@ const activeName = ref("scan");
 
 const nextStep = () => {
   if (activeName.value === "scan") {
-    //todo,拉起本地扫描端exe程序,隐藏本browserWindow
     window.electronApi.startScanExe();
   } else {
     emit("next");

+ 1 - 2
src/render/views/Login/index.vue

@@ -49,8 +49,7 @@ const checkEnvHandle = () => {
       curStepIndex.value++;
     })
     .catch(() => {
-      //todo 真实接口下,解除该注释
-      // local.remove("baseUrl");
+      local.remove("baseUrl");
     });
 };
 const willClose = () => {