Files
stock/serve/frontend/src/main.tsx
T
2026-07-04 16:59:25 +08:00

52 lines
1.9 KiB
TypeScript

import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router-dom'
import { QueryClient, QueryClientProvider, QueryCache } from '@tanstack/react-query'
import { router } from './router'
import './index.css'
// 全局认证拦截: 任何 query/mutation 收到 401 (未登录/会话过期) → 跳登录页。
// api.ts 的 request() 已对 401 静默 (不弹 toast), 这里统一负责跳转。
// 排除 /login 自身的请求, 避免登录页请求失败又跳登录形成死循环。
const _redirectToLogin = (() => {
let redirecting = false
return (err: unknown) => {
if (redirecting) return
if (!(err instanceof Error)) return
const msg = err.message || ''
// 401 (未登录/会话过期) → 跳登录页
// 403 未初始化 (面板未设密码, 公网访问) → 也跳登录页(显示设密码提示)
const is401 = msg.includes('未登录') || msg.includes('会话已过期') || msg.includes('401')
const isNotInit = msg.includes('尚未初始化访问密码') || msg.includes('NOT_INITIALIZED')
if (!is401 && !isNotInit) return
// 已在登录页则不跳(避免死循环)
if (window.location.pathname === '/login') return
redirecting = true
const redirect = encodeURIComponent(window.location.pathname + window.location.search)
window.location.href = `/login?redirect=${redirect}`
}
})()
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (err) => _redirectToLogin(err),
}),
defaultOptions: {
queries: {
staleTime: 5_000, // 5s 内复用,与 §4.2 Repository 不变量一致
refetchOnWindowFocus: false,
},
mutations: {
onError: (err) => _redirectToLogin(err),
},
},
})
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</React.StrictMode>
)