滑动续期与多标签同步、列表报错提示、分页排序体验改进
This commit is contained in:
+21
-4
@@ -92,6 +92,7 @@ async function handleUnauthorized(sentToken: string) {
|
||||
const waited = await waitForSessionRefresh(sentToken)
|
||||
if (waited) await new Promise<void>((resolve) => setTimeout(resolve, 0))
|
||||
const auth = useAuthStore()
|
||||
auth.syncFromStorage()
|
||||
if (sentToken !== auth.token) return
|
||||
auth.logout()
|
||||
if (location.pathname !== '/login') {
|
||||
@@ -140,11 +141,25 @@ function trackSessionRefresh(token: string): () => void {
|
||||
}
|
||||
}
|
||||
|
||||
function applySessionRefresh(value: unknown) {
|
||||
if (!value || typeof value !== 'object') return
|
||||
/** 滑动续期:后端对临过期令牌在响应头中换发同会话新令牌;仅当发送时令牌仍是
|
||||
* 当前会话令牌才应用(与 401 处理同一快照原则,防旧会话迟到响应覆盖新会话)。 */
|
||||
function applyRenewedSession(resp: Response, sentToken: string) {
|
||||
// 测试环境的最小 Response stub 可能无 headers
|
||||
const token = resp.headers?.get('X-Renewed-Token')
|
||||
const expiresAt = resp.headers?.get('X-Renewed-Expires-At')
|
||||
if (!token || !expiresAt || !sentToken) return
|
||||
const auth = useAuthStore()
|
||||
auth.syncFromStorage()
|
||||
if (sentToken !== auth.token) return
|
||||
auth.setSession(token, expiresAt)
|
||||
}
|
||||
|
||||
function applySessionRefresh(value: unknown): boolean {
|
||||
if (!value || typeof value !== 'object') return false
|
||||
const refresh = value as { token?: unknown; expiresAt?: unknown }
|
||||
if (typeof refresh.token !== 'string' || typeof refresh.expiresAt !== 'string') return
|
||||
if (typeof refresh.token !== 'string' || typeof refresh.expiresAt !== 'string') return false
|
||||
useAuthStore().setSession(refresh.token, refresh.expiresAt)
|
||||
return true
|
||||
}
|
||||
|
||||
/** 统一请求封装:注入 JWT、401 登出、错误转 ApiError;
|
||||
@@ -190,7 +205,8 @@ async function doRequest<T>(
|
||||
// 202/204 等成功响应可能无 body,直接 resp.json() 会抛 Unexpected end of JSON input
|
||||
const text = await resp.text()
|
||||
const result = (text ? JSON.parse(text) : undefined) as T
|
||||
if (opts.refreshesSession && sentToken) applySessionRefresh(result)
|
||||
const bodyRefreshed = !!sentToken && !!opts.refreshesSession && applySessionRefresh(result)
|
||||
if (!bodyRefreshed) applyRenewedSession(resp, sentToken ?? '')
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -214,6 +230,7 @@ export async function rawFetch(
|
||||
body: opts.body,
|
||||
})
|
||||
if (!resp.ok) await parseError(resp, sentToken)
|
||||
applyRenewedSession(resp, sentToken ?? '')
|
||||
return resp
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user