yxh
2026-10-18 01ee694a3bb8048372fc793a8de314d70b688b35
src/hooks/web/useIdleLogout.ts
@@ -1,7 +1,6 @@
import { watch } from 'vue'
import { useIdle } from '@vueuse/core'
import { ElMessage } from 'element-plus'
import { releaseBedOnExit } from '@/utils/releaseBed'
/**
 * 空闲超时自动退出(需求:30 分钟不操作才要求重新输入密码)。
@@ -18,6 +17,7 @@
 *   · 有任何鼠标/键盘/触摸/滚动操作 → 计时器重置;
 *   · 连续 30 分钟**无任何操作** → 主动清理登录态并跳转登录页(要求重新输密码);
 *   · 有操作时不主动登出(token 自身的续期由 axios 拦截器的 refresh-token 负责)。
 *   · 【本次】空闲登出**不再释放诊室工位**(工位保留,重新登录即可继续使用)。
 *
 * 用法(在 permission.ts 中调用一次即可,内部自带幂等保护):
 *   setupIdleLogout()
@@ -99,26 +99,28 @@
}
/**
 * 实际执行空闲登出:释放床位 + 清理本地凭证并跳转登录页。
 * 实际执行空闲登出:**只清本地凭证并跳转登录页,不释放工位**。
 *
 * 之所以不调用 userStore.loginOut()(那是"主动退出"):
 *   · 那个接口会请求后端注销 token — 对本场景没必要,且可能因网络问题卡住;
 *   · 空闲登出只需保证本地凭证清干净 + 回到登录页。
 *
 * ⚠️ 但**必须**单独调一次「释放床位」:
 *   医生在「诊室选择」页选好床位后就占用了该床位(`clinic_room.doc_id`)。
 *   原先本函数只清本地凭证、不通知后端 ⇒ 空闲超时后床位**一直显示被占用**,
 *   其他医生选不到这个床位。这正是"医生忘了离座就退出系统"的主要场景。
 * 【重要变更(本次)】空闲超时**不再释放诊室工位**。
 * ---------------------------------------------------------------
 * 原先本函数会先调 `releaseBedOnExit('idle-timeout')`,把 `clinic_room.doc_id` 清空。
 * 实测问题:医生离开电脑 30 分钟以上(例如去做检查、离开 1 小时回来),
 * 回来时工位已经被释放 → 工作台只能只读、并提示"请重新就坐",
 * 而医生本人并没有离座。这不符合实际使用场景。
 *
 * 现在的口径:
 *   · 空闲超时 → **只要求重新输入密码**(token 清掉、回登录页),**工位保留**;
 *   · 重新登录后 `roomStore.fetchMySeat()` 会自动恢复「我的工位」,可直接继续使用;
 *   · 工位的释放只发生在**用户主动操作**:手动「离座」、手动「退出登录」。
 *   · 医生真的下班忘离座的兜底:① 闭诊时系统统一清空当班工位;② 管理员可在
 *     诊室管理页「清空工位」。
 */
async function doIdleLogout(): Promise<void> {
  ElMessage.warning(`已超过 ${IDLE_TIMEOUT_MINUTES} 分钟未操作,请重新登录`)
  // 先释放床位,再清凭证 —— 顺序不能反:释放接口需要携带当前令牌
  try {
    await releaseBedOnExit('idle-timeout')
  } catch {
    /* releaseBedOnExit 内部已兜底,不会抛错;此处仅为防御性写法 */
  }
  cleanupCredentials()