update
This commit is contained in:
@@ -8,7 +8,7 @@ function storedActivityTime() {
|
||||
|
||||
/**
|
||||
* 会话按“最后活跃时间”计算,而不是从首次登录起固定倒计时。
|
||||
* 该 ref 被认证 store 与请求层共享,确保 API 活动可以立即影响路由守卫。
|
||||
* 该 ref 被认证 store 与路由守卫共享,确保真实用户活动可以立即影响超时判断。
|
||||
*/
|
||||
export const sessionActivityTime = ref(storedActivityTime())
|
||||
|
||||
@@ -30,3 +30,45 @@ export function clearSessionActivity() {
|
||||
sessionActivityTime.value = 0
|
||||
localStorage.removeItem(LOGIN_TIME_STORAGE_KEY)
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅在用户真实活跃时续期会话:
|
||||
* - 鼠标移动 / 键盘 / 点击 / 触摸(说明用户正在操作)
|
||||
* - 标签页切回可见(说明用户回到界面)
|
||||
* 页面后台轮询接口、切走标签页不会续期,从而“无操作”或“不在当前界面”
|
||||
* 超过空闲时长才会被判定为会话过期并跳回登录。
|
||||
*/
|
||||
let userActivityBound = false
|
||||
let lastTouch = 0
|
||||
const ACTIVITY_THROTTLE = 5000 // 5s 内最多续期一次,避免 mousemove 过于频繁
|
||||
|
||||
const activityEvents = ['mousemove', 'mousedown', 'keydown', 'click', 'touchstart'] as const
|
||||
|
||||
function handleUserActivity() {
|
||||
const now = Date.now()
|
||||
if (now - lastTouch < ACTIVITY_THROTTLE) return
|
||||
lastTouch = now
|
||||
touchSessionActivity()
|
||||
}
|
||||
|
||||
function handleVisibility() {
|
||||
if (!document.hidden) {
|
||||
touchSessionActivity()
|
||||
}
|
||||
}
|
||||
|
||||
export function bindUserActivityListeners() {
|
||||
if (userActivityBound) return
|
||||
userActivityBound = true
|
||||
activityEvents.forEach((evt) =>
|
||||
window.addEventListener(evt, handleUserActivity, { passive: true })
|
||||
)
|
||||
document.addEventListener('visibilitychange', handleVisibility)
|
||||
}
|
||||
|
||||
export function unbindUserActivityListeners() {
|
||||
if (!userActivityBound) return
|
||||
userActivityBound = false
|
||||
activityEvents.forEach((evt) => window.removeEventListener(evt, handleUserActivity))
|
||||
document.removeEventListener('visibilitychange', handleVisibility)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user