import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom' import { useAuthStore } from '@/store/auth' import { useAppStore } from '@/store/app' import AdminLayout from '@/layouts/AdminLayout' import LoginPage from '@/pages/LoginPage' import ErrorBoundary from '@/components/ErrorBoundary' import { Suspense, useMemo, lazy, useEffect } from 'react' import { Loader2, Shield } from 'lucide-react' import { Button } from '@/components/ui/button' import type { SystemMenu } from '@/api/system' const pages = import.meta.glob('./pages/**/*.tsx') const dynamicComponentMap: Record> = {} for (const path in pages) { let routePath = path.replace(/^\.\/pages/, '').replace(/\.tsx$/, '').replace(/\/index$/, '').toLowerCase() if (routePath === '/loginpage') continue dynamicComponentMap[routePath] = lazy(pages[path] as any) } function ProtectedRoute({ children }: { children: React.ReactNode }) { const isAuthenticated = useAuthStore(s => s.isAuthenticated) if (!isAuthenticated) return return <>{children} } function PublicRoute({ children }: { children: React.ReactNode }) { const isAuthenticated = useAuthStore(s => s.isAuthenticated) if (isAuthenticated) return return <>{children} } function NoPermission() { const logout = useAuthStore(s => s.logout) return (

访问受限

抱歉,您当前暂无任何系统权限,请联系管理员为您分配相关菜单与角色。

) } function AppRoutes() { const menus = useAuthStore(s => s.menus) const isAuthenticated = useAuthStore(s => s.isAuthenticated) const refreshMenus = useAuthStore(s => s.refreshMenus) const hasFetchedMenus = useAuthStore(s => s.hasFetchedMenus) useEffect(() => { if (isAuthenticated && menus.length === 0) refreshMenus() }, [isAuthenticated, menus.length, refreshMenus]) const dynamicRoutes = useMemo(() => { const routes: { path: string; Component: React.ComponentType }[] = [] const traverse = (items: SystemMenu[]) => { items.forEach(item => { if (item.children?.length) traverse(item.children) const routeKey = item.path || item.code if (routeKey && dynamicComponentMap[routeKey]) { routes.push({ path: routeKey, Component: dynamicComponentMap[routeKey] }) } }) } if (menus) traverse(menus) return routes }, [menus]) const Loading =
return ( } /> }> 0 ? : ) : Loading } /> {dynamicRoutes.map(({ path, Component }) => ( } /> ))} {hasFetchedMenus && dynamicRoutes.length === 0 && ( } /> )} {hasFetchedMenus && dynamicRoutes.length > 0 && (

页面不存在或开发中

该菜单没有对应的页面组件,或者路径未匹配。

} /> )}
} />
) } export default function App() { const themeHue = useAppStore(s => s.themeHue) useEffect(() => { document.documentElement.style.setProperty('--theme-hue', themeHue) if (themeHue === '45') { document.documentElement.style.setProperty('--theme-l', '0.65') document.documentElement.style.setProperty('--theme-c', '0.18') document.documentElement.style.setProperty('--theme-l-dark', '0.70') document.documentElement.style.setProperty('--theme-c-dark', '0.16') } else { document.documentElement.style.removeProperty('--theme-l') document.documentElement.style.removeProperty('--theme-c') document.documentElement.style.removeProperty('--theme-l-dark') document.documentElement.style.removeProperty('--theme-c-dark') } }, [themeHue]) return ( ) }