import { lazy, Suspense } from 'react'; import { createBrowserRouter, Navigate, type RouteObject } from 'react-router'; import { Spin } from 'antd'; import type { MenuRecord } from '@/types/auth'; import AuthGuard from './authGuard'; import { menusToRoutes } from './dynamicRoutes'; // eslint-disable-next-line react-refresh/only-export-components const AdminLayout = lazy(() => import('@/layouts/AdminLayout')); // eslint-disable-next-line react-refresh/only-export-components const LoginPage = lazy(() => import('@/pages/login')); // eslint-disable-next-line react-refresh/only-export-components const ProfilePage = lazy(() => import('@/pages/profile')); // eslint-disable-next-line react-refresh/only-export-components const DashboardPage = lazy(() => import('@/pages/dashboard')); // eslint-disable-next-line react-refresh/only-export-components const NotFound = lazy(() => import('@/pages/error/404')); // eslint-disable-next-line react-refresh/only-export-components const LazyLoad: React.FC<{ children: React.ReactNode }> = ({ children }) => ( }> {children} ); // Static children of admin route (not from menus) // These are always available: default redirect, profile, 404 const adminStaticChildren: RouteObject[] = [ { index: true, element: }, { path: 'dashboard', element: , }, { path: 'profile', element: , }, // Catch-all 404 { path: '*', element: }, ]; export const router = createBrowserRouter([ { path: '/login', element: , }, { id: 'admin', path: '/', element: ( ), children: adminStaticChildren, errorElement: , }, ]); /** Dashboard static menu item — injected as the first sidebar entry */ const STATIC_MENU: MenuRecord = { id: -1, parentId: 0, name: '工作台', path: '/dashboard', component: 'dashboard', icon: 'ep:house', type: 2, sort: 0, status: 0, visible: true, keepAlive: true, }; /** * Inject dynamic routes from backend menus into the admin layout. * Prepend a static "工作台" dashboard menu, return the merged menus * so the caller can store them correctly. */ export function addDynamicRoutes(menus: MenuRecord[]): MenuRecord[] { const mergedMenus = [STATIC_MENU, ...menus]; const dynamicRoutes = menusToRoutes(mergedMenus); router.patchRoutes('admin', [...adminStaticChildren, ...dynamicRoutes]); // Only force re-match when the current URL is under the admin layout // and matched to the catch-all 404 (e.g., page refresh before routes existed). const { pathname } = router.state.location; const isLogin = pathname === '/login'; const is404 = router.state.matches.some( (m) => m.route.path === '*', ); if (!isLogin && is404) { router.navigate(pathname, { replace: true }); } return mergedMenus; } /** * Remove dynamic routes (called on logout). * Resets admin children back to static-only. */ export function resetDynamicRoutes() { router.patchRoutes('admin', adminStaticChildren); }