feat(auth): 登录态改为滑动续期(后台 24h/7d,打手 7d/30d)

This commit is contained in:
yml2213
2026-10-25 13:28:58 +08:00
parent 81edf530db
commit 2fb7aae13f
31 changed files with 510 additions and 64 deletions
+15 -4
View File
@@ -9,7 +9,7 @@ import {
import { App, Button, Layout, Menu, Typography } from 'antd'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import type { MenuProps } from 'antd'
import { useEffect, useMemo } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router'
import { fetchWorkerAfterSalesCases, fetchWorkerProfile, logoutWorker } from '@/services/worker'
@@ -29,6 +29,7 @@ import {
getWorkerToken,
getWorkerTokenExpiresAt,
getWorkerUsername,
isWorkerSessionExpiryKey,
isWorkerSessionStorageKey,
} from '@/utils/worker-auth'
import { useRealtimeEvents, type RealtimeEvent } from '@/hooks/useRealtimeEvents'
@@ -100,6 +101,8 @@ export default function WorkerLayout() {
[afterSalesPendingCount],
)
const [sessionExpiresAt, setSessionExpiresAt] = useState(() => getWorkerTokenExpiresAt())
useEffect(() => {
const navigateToLogin = () => {
if (window.location.pathname !== '/') {
@@ -107,30 +110,38 @@ export default function WorkerLayout() {
}
}
const handleSessionExpired = () => navigateToLogin()
const handleSessionRenewed = () => setSessionExpiresAt(getWorkerTokenExpiresAt())
const handleStorage = (event: StorageEvent) => {
if (isWorkerSessionStorageKey(event.key) && event.newValue === null) {
if (!isWorkerSessionStorageKey(event.key)) return
if (event.newValue === null) {
expireWorkerSession()
navigateToLogin()
return
}
if (isWorkerSessionExpiryKey(event.key)) {
handleSessionRenewed()
}
}
window.addEventListener('worker-session-expired', handleSessionExpired)
window.addEventListener('worker-session-renewed', handleSessionRenewed)
window.addEventListener('storage', handleStorage)
return () => {
window.removeEventListener('worker-session-expired', handleSessionExpired)
window.removeEventListener('worker-session-renewed', handleSessionRenewed)
window.removeEventListener('storage', handleStorage)
}
}, [navigate])
useEffect(() => {
const delay = getWorkerSessionExpiryDelay(getWorkerTokenExpiresAt())
const delay = getWorkerSessionExpiryDelay(sessionExpiresAt)
if (delay === null) return
const timer = window.setTimeout(() => {
expireWorkerSession()
}, delay)
return () => window.clearTimeout(timer)
}, [])
}, [sessionExpiresAt])
useRealtimeEvents({
url: '/api/v1/worker/realtime',