fix(auth): 解决认证错误处理和会话管理问题

- 替换 AUTH_INVALID_TOKEN_CODE 为 AUTH_RELOGIN_REQUIRED_CODES 数组支持多种错误码
- 实现 hasClearableSessionState 和 hasRecordedUnauthorizedSession 函数优化会话清理逻辑
- 添加 clearQueryCache 选项控制查询缓存清理行为
- 修复马来西亚手机号正则验证模式导致的用户名验证问题
- 更新 API 错误消息处理优先级,优先使用服务端返回的消息
- 添加服务器消息检查函数 hasServerMessage 避免重复错误提示
- 在登录表单中实现密码可见性切换功能
- 添加密码可见性国际化文案支持
- 实现页面历史记录抽屉组件和相关动效
- 优化模态框背景遮罩样式和键盘事件处理
- 调整多个组件的 z-index 层级避免显示冲突
This commit is contained in:
JiaJun
2026-06-01 17:46:01 +08:00
parent 87e8aca97d
commit 72b6de499e
51 changed files with 3812 additions and 149 deletions

View File

@@ -20,6 +20,7 @@ const LOGIN_PROMPT_DEDUP_MS = 1200
interface ClearAuthenticatedSessionOptions {
clearBrowserStorage?: boolean
clearQueryCache?: boolean
}
interface UnauthorizedSessionOptions extends ClearAuthenticatedSessionOptions {
@@ -37,6 +38,26 @@ function clearBrowserStorageData() {
}
}
function hasClearableSessionState() {
const snapshot = useAuthStore.getState()
return Boolean(
snapshot.status !== 'anonymous' ||
snapshot.accessToken ||
snapshot.refreshToken ||
snapshot.currentUser ||
snapshot.apiAuthToken ||
snapshot.apiAuthTokenExpiresAt ||
snapshot.apiAuthServerTime,
)
}
function hasRecordedUnauthorizedSession() {
const snapshot = useAuthStore.getState()
return snapshot.status === 'anonymous' && Boolean(snapshot.lastUnauthorizedAt)
}
export function registerCurrentUserInitializer(
initializer: CurrentUserInitializer | null,
) {
@@ -57,11 +78,19 @@ export function isAuthenticated() {
export function clearAuthenticatedSession({
clearBrowserStorage = true,
clearQueryCache = true,
}: ClearAuthenticatedSessionOptions = {}) {
useAuthStore.getState().markUnauthorized()
queryClient.clear()
const alreadyUnauthorized = hasRecordedUnauthorizedSession()
if (clearBrowserStorage) {
if (!alreadyUnauthorized) {
useAuthStore.getState().markUnauthorized()
}
if (clearQueryCache && !alreadyUnauthorized) {
queryClient.clear()
}
if (clearBrowserStorage && !alreadyUnauthorized) {
clearBrowserStorageData()
}
}
@@ -71,12 +100,21 @@ export function handleUnauthorizedSession({
openLoginModal = false,
showLoginRequiredToast = false,
}: UnauthorizedSessionOptions = {}) {
clearAuthenticatedSession({ clearBrowserStorage })
clearAuthenticatedSession({
clearBrowserStorage,
clearQueryCache: hasClearableSessionState(),
})
if (!openLoginModal && !showLoginRequiredToast) {
return
}
const modalStore = openLoginModal ? useModalStore.getState() : null
if (modalStore?.modals.desktopLogin) {
return
}
const now = Date.now()
const shouldPrompt = now - lastLoginPromptAt > LOGIN_PROMPT_DEDUP_MS
@@ -91,10 +129,7 @@ export function handleUnauthorizedSession({
}
if (openLoginModal) {
const modalStore = useModalStore.getState()
modalStore.closeAllModals()
modalStore.setModalOpen('desktopLogin', true)
modalStore?.openExclusiveModal('desktopLogin')
}
}