diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index f4ef003..6e67928 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -84,6 +84,16 @@ export async function request( } + if (res.status === 403) { + const err = await res.json().catch(() => ({ detail: 'Forbidden' })); + if (err.detail === 'Not authenticated' || err.detail === '需要管理员权限') { + localStorage.removeItem('aiflow_token'); + localStorage.removeItem('aiflow_user'); + window.location.href = '/login'; + throw new Error('未登录或权限不足'); + } + } + if (!res.ok) { const err = await res.json().catch(() => ({ detail: '请求失败' })); diff --git a/frontend/src/components/layout/AdminLayout.tsx b/frontend/src/components/layout/AdminLayout.tsx index 5cd3b65..fd74038 100644 --- a/frontend/src/components/layout/AdminLayout.tsx +++ b/frontend/src/components/layout/AdminLayout.tsx @@ -191,6 +191,15 @@ const AdminLayout: React.FC = () => { const location = useLocation(); + // 后台必须登录且为管理员 + useEffect(() => { + const token = localStorage.getItem('aiflow_token'); + if (!token || !user || user.role !== 'admin') { + logout(); + navigate('/login', { replace: true }); + } + }, [user, logout, navigate]); + const navCrumb = (() => { for (const g of adminNavGroups) {