yxh
yxh
7 天以前 09dc74e264b6262cbe41c9c8476e24705871d4a6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import axios from 'axios'
import { getAccessToken } from '@/utils/auth'
 
/**
 * 【2026-11-05 起:本文件已无调用方】
 * ---------------------------------------------------
 * 业务改为「退出登录**不释放**工位」(一人多工位/多端登录:一台退出不能清掉另一台的岗位),
 * 释放工位改为三种明确途径:
 *   ① 医生点「离座」;② 闭诊统一清空;③ 管理员「清空工位」/ 接班医生「接管」。
 * 本工具函数保留(后端 /ecg/doctor/release-my-beds 也保留),仅用于运维/管理侧需要时手动调用。
 *
 * ---------- 以下为原注释 ----------
 * 手动「退出登录」时释放诊室工位。
 *
 * 背景
 * ----
 * 医生在「诊室选择」(`roomselect`) 页选好床位后即**占用**该床位
 * (后端写在 `clinic_room.doc_id` / `status`)。
 * 若医生不点「离座」而直接退出系统,床位会一直显示被占用,其他医生无法使用。
 *
 * 【重要变更(本次)】只保留「手动退出登录」这一条路径
 * ---------------------------------------------------------------
 * 原先覆盖 4 条路径:手动退出、空闲 30 分钟自动登出、令牌失效(401)、`pagehide`(刷新/关页)。
 * 实测问题:后三条会把「令牌到期 / 刷新页面 / 离开一会儿」误当成「医生离座」,
 * 导致工位被清空 —— 医生回来看到工作台只剩只读、并提示"请重新就坐",而工位已变空闲。
 *
 * 现在的口径:
 *   · **只有手动「退出登录」**(以及诊室选择页的手动「离座」)才释放工位;
 *   · 空闲超时(`useIdleLogout`)只要求重新输密码,工位保留;
 *   · 401 / 刷新令牌失败只清本地凭证,工位保留;
 *   · 不再注册 `pagehide` 兜底(刷新页面不应该丢工位);
 *   · 医生真的下班忘离座的兜底:① 闭诊时系统统一清空当班工位;② 管理员「清空工位」。
 *
 * 为什么用**裸 axios** 而不是项目的 request
 * ----------------------------------------
 * 本函数可能在鉴权状态不稳时被调用,若走项目 request 的 401 拦截器,
 * 会再次触发"刷新令牌失败 → 强制登出"的递归。裸 axios 不挂任何拦截器,天然断开这条链。
 *
 * 为什么用**服务端按 userId 反查**而不是前端传床位号
 * ------------------------------------------------
 * 本函数运行时前端缓存可能已被清理(拿不到 roomId/bedNo);且前端缓存若与库中不一致
 * 就会"释放不掉"。故后端提供无参接口 `/ecg/doctor/release-my-beds`,按当前登录用户
 * 反查其占用的全部床位。前端只需带上令牌。
 *
 * ⚠️ 本文件**不要 import `@/config/axios/config`**:避免与 service.ts 形成循环依赖。
 *   这里直接用同一个环境变量拼接,效果等价且无环。
 *
 * 失败处理:本函数**永不抛异常**(退出流程不应因它而中断)。
 */
 
/** API 基础路径(与 `config/axios/config.ts` 的 base_url 计算方式一致,避免循环依赖) */
const BASE_URL = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL
 
/** 保证同一轮退出只调用一次(多个退出路径可能同时触发) */
let releasing = false
 
export async function releaseBedOnExit(reason?: string): Promise<void> {
  if (releasing) return
 
  const token = getAccessToken()
  if (!token) return // 无令牌 ⇒ 本来就没登录,无需释放
 
  releasing = true
  try {
    await axios.post(
      `${BASE_URL}/ecg/doctor/release-my-beds`,
      {},
      {
        headers: { Authorization: 'Bearer ' + token },
        timeout: 3000 // 退出流程不能久等
      }
    )
    console.info('[release-bed] 已请求释放床位', reason ?? '')
  } catch (e) {
    // 静默失败:退出流程不应被阻塞(例如令牌已过期、网络中断)
    console.warn('[release-bed] 释放床位失败(忽略)', reason ?? '', e)
  } finally {
    releasing = false
  }
}