Files
stock/refer/frontend/src/components/AccessGuard.tsx
T

47 lines
1.4 KiB
TypeScript

import { Navigate, useLocation } from 'react-router-dom'
import { useQuery } from '@tanstack/react-query'
import { Loader2 } from 'lucide-react'
import { api } from '@/lib/api'
function getStoredToken(): string | null {
try { return localStorage.getItem('access_token') } catch { return null }
}
export function AccessGuard({ children, requireAdmin = false }: { children: React.ReactNode; requireAdmin?: boolean }) {
const location = useLocation()
const token = getStoredToken()
const { data: status, isLoading } = useQuery({
queryKey: ['access-auth-status', token],
queryFn: () => api.accessAuthStatus(),
// 即使 token 为空也查询一次,用于确认服务端是否启用了门控
enabled: true,
staleTime: 5 * 60 * 1000,
})
if (isLoading) {
return (
<div className="h-screen w-full flex items-center justify-center bg-base text-foreground">
<Loader2 className="h-6 w-6 animate-spin text-accent" />
</div>
)
}
// 未启用门控,直接放行
if (!status?.enabled) {
return <>{children}</>
}
// 未验证,跳转到登录页
if (!status.verified) {
return <Navigate to="/verify" state={{ from: location.pathname }} replace />
}
// 需要管理员权限但当前非管理员
if (requireAdmin && status.role !== 'admin') {
return <Navigate to="/" replace />
}
return <>{children}</>
}