mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-07 13:00:59 +08:00
fix(web): fix 401 unauthorized redirect not working properly (#997)
修复了token过期后页面一直遇到401错误、无法自动跳转登录页的问题 主要改动: 1. httpClient.ts - 去掉延迟跳转的setTimeout,改为立即跳转 - 返回pending promise阻止SWR捕获401错误 - 保存from401标记到sessionStorage,由登录页显示提示 2. LoginPage.tsx - 检测from401标记,显示"登录已过期"提示(永久显示) - 在登录成功时手动关闭过期提示toast - 支持管理员登录、普通登录、OTP验证三种场景 3. TraderConfigModal.tsx - 修复3处直接使用fetch()的问题,改为httpClient.get() - 确保所有API请求都经过统一的401拦截器 4. translations.ts - 添加sessionExpired的中英文翻译 修复效果: - token过期时立即跳转登录页(无延迟) - 登录页持续显示过期提示,直到用户登录成功或手动关闭 - 不会再看到401错误页面或重复的错误提示 Co-authored-by: tinkle-community <tinklefund@gmail.com>
This commit is contained in:
@@ -6,10 +6,9 @@
|
||||
* - Automatic 401 token expiration handling
|
||||
* - Auth state cleanup on unauthorized
|
||||
* - Automatic redirect to login page
|
||||
* - Notification shown on login page after redirect
|
||||
*/
|
||||
|
||||
import { toast } from 'sonner'
|
||||
|
||||
export class HttpClient {
|
||||
// Singleton flag to prevent duplicate 401 handling
|
||||
private static isHandling401 = false
|
||||
@@ -21,13 +20,6 @@ export class HttpClient {
|
||||
HttpClient.isHandling401 = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Show login required notification to user
|
||||
*/
|
||||
private showLoginRequiredNotification(): void {
|
||||
toast.warning('登录已过期,请先登录', { duration: 1800 })
|
||||
}
|
||||
|
||||
/**
|
||||
* Response interceptor - handles common HTTP errors
|
||||
*
|
||||
@@ -53,23 +45,24 @@ export class HttpClient {
|
||||
// Notify global listeners (AuthContext will react to this)
|
||||
window.dispatchEvent(new Event('unauthorized'))
|
||||
|
||||
// Show user-friendly notification (only once)
|
||||
this.showLoginRequiredNotification()
|
||||
|
||||
// Delay redirect to let user see the notification
|
||||
setTimeout(() => {
|
||||
// Only redirect if not already on login page
|
||||
if (!window.location.pathname.includes('/login')) {
|
||||
// Save current location for post-login redirect
|
||||
const returnUrl = window.location.pathname + window.location.search
|
||||
if (returnUrl !== '/login' && returnUrl !== '/') {
|
||||
sessionStorage.setItem('returnUrl', returnUrl)
|
||||
}
|
||||
|
||||
window.location.href = '/login'
|
||||
// Only redirect if not already on login page
|
||||
if (!window.location.pathname.includes('/login')) {
|
||||
// Save current location for post-login redirect
|
||||
const returnUrl = window.location.pathname + window.location.search
|
||||
if (returnUrl !== '/login' && returnUrl !== '/') {
|
||||
sessionStorage.setItem('returnUrl', returnUrl)
|
||||
}
|
||||
// Note: No need to reset flag since we're redirecting
|
||||
}, 1500) // 1.5秒延迟,让用户看到提示
|
||||
|
||||
// Mark that user came from 401 (login page will show notification)
|
||||
sessionStorage.setItem('from401', 'true')
|
||||
|
||||
// Redirect immediately to login page
|
||||
window.location.href = '/login'
|
||||
|
||||
// Return pending promise to prevent error from being caught by SWR/React
|
||||
// The notification will be shown on the login page
|
||||
return new Promise(() => {}) as Promise<Response>
|
||||
}
|
||||
|
||||
throw new Error('登录已过期,请重新登录')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user