Kaynağa Gözat

益寿缘医生端-增加医生心跳机制

cgp 1 hafta önce
ebeveyn
işleme
e808bcd4fb
3 değiştirilmiş dosya ile 74 ekleme ve 11 silme
  1. 22 0
      src/api/heartbeat.js
  2. 36 11
      src/layout/components/Navbar.vue
  3. 16 0
      src/views/login.vue

+ 22 - 0
src/api/heartbeat.js

@@ -0,0 +1,22 @@
+import request from '@/utils/request'
+
+/**
+ * 发送心跳
+ * @param {Object} data - 通常不需要传参,后端从 token 获取 doctorId
+ */
+export function sendHeartbeat() {
+  return request({
+    url: '/doctor/online/heartbeat',
+    method: 'post'
+  })
+}
+
+/**
+ * 主动登出在线状态(用于正常退出时)
+ */
+export function logoutOnlineStatus() {
+  return request({
+    url: '/doctor/online/updateOnlineStatusOnLogout',
+    method: 'post'
+  })
+}

+ 36 - 11
src/layout/components/Navbar.vue

@@ -55,6 +55,7 @@
 </template>
 
 <script>
+import { logoutOnlineStatus } from "@/api/heartbeat";
 import { mapGetters } from 'vuex'
 import Breadcrumb from '@/components/Breadcrumb'
 import TopNav from '@/components/TopNav'
@@ -191,18 +192,42 @@ export default {
     toggleSideBar() {
       this.$store.dispatch('app/toggleSideBar')
     },
+    // async logout() {
+    //   this.$confirm('确定注销并退出系统吗?', '提示', {
+    //     confirmButtonText: '确定',
+    //     cancelButtonText: '取消',
+    //     type: 'warning'
+    //   }).then(() => {
+    //     //记录退出登录状态
+    //     logoutOnlineStatus();
+    //     this.$store.dispatch('LogOut').then(() => {
+    //       this.$store.dispatch('imlogout')
+    //       location.href = '/index';
+    //
+    //     })
+    //   }).catch(() => { });
+    // }
     async logout() {
-      this.$confirm('确定注销并退出系统吗?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(() => {
-        this.$store.dispatch('LogOut').then(() => {
-          this.$store.dispatch('imlogout')
-          location.href = '/index';
-
-        })
-      }).catch(() => { });
+      try {
+        await this.$confirm('确定注销并退出系统吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        });
+        //先调用登出在线状态接口(此时 token 还有效!)
+        await logoutOnlineStatus();
+        // 清除本地登录状态
+        await this.$store.dispatch('LogOut');
+        // IM 登出
+        this.$store.dispatch('imlogout');
+        // 跳转登录页
+        this.$router.push({ path: '/login' });
+
+      } catch (error) {
+        if (error !== 'cancel') {
+          console.error('退出过程中发生错误:', error);
+        }
+      }
     }
   }
 }

+ 16 - 0
src/views/login.vue

@@ -67,6 +67,7 @@
 
 <script>
 import { imConfig } from '@/utils/im'
+import { sendHeartbeat } from "@/api/heartbeat";
 import { getCodeImg } from "@/api/common";
 import Cookies from "js-cookie";
 import { encrypt, decrypt } from '@/utils/jsencrypt'
@@ -154,6 +155,8 @@ export default {
           this.$store
             .dispatch("Login", this.loginForm)
             .then((res) => {
+              //登录成功,启动心跳
+              this.startHeartbeat();
               this.$router.push({ path:  "/index" });
             })
             .catch(() => {
@@ -163,6 +166,19 @@ export default {
         }
 
       });
+    },
+    // 启动心跳(每30秒一次)
+    startHeartbeat() {
+      const tick = () => {
+        sendHeartbeat().catch(err => {
+          console.warn('心跳失败:', err);
+          // 可选:如果 token 过期,跳转登录页
+          // if (err.code === 401) { this.$store.dispatch('LogOut'); }
+        });
+        // 继续下一次心跳
+        setTimeout(tick, 30 * 1000);
+      };
+      tick(); // 立即执行第一次
     }
   }
 };