import { useEffect, useMemo, useState } from "react"; import { Navigate, type RouteObject, useRoutes } from "react-router-dom"; import { fetchDynamicRoutes } from "../api/upms"; import { LoadingView } from "../components/LoadingView"; import { DefaultLayout } from "../layouts/DefaultLayout"; import { SidebarLayout } from "../layouts/SidebarLayout"; import { DashboardPage } from "../pages/DashboardPage"; import { LoginPage } from "../pages/LoginPage"; import { NotFoundPage } from "../pages/NotFoundPage"; import { RoutePlaceholderPage } from "../pages/RoutePlaceholderPage"; import type { RouteNode } from "../types/route"; const layoutRegistry = { DEFAULT: DefaultLayout, SIDEBAR: SidebarLayout }; function toChildRoute(route: RouteNode): RouteObject { const Component = route.component === "dashboard" ? DashboardPage : RoutePlaceholderPage; return { path: route.path === "/" ? "" : route.path.replace(/^\//, ""), element: }; } function buildRoutes(dynamicRoutes: RouteNode[]): RouteObject[] { const grouped = dynamicRoutes.reduce>((acc, route) => { acc[route.layout] ??= []; acc[route.layout].push(route); return acc; }, {}); const layoutRoutes = Object.entries(grouped).map(([layout, routes]) => { const Layout = layoutRegistry[layout as keyof typeof layoutRegistry] ?? DefaultLayout; return { path: "/", element: , children: routes.map(toChildRoute) } satisfies RouteObject; }); return [ { path: "/login", element: }, ...layoutRoutes, { path: "*", element: } ]; } export function AppRouter() { const [dynamicRoutes, setDynamicRoutes] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { fetchDynamicRoutes() .then((routes) => setDynamicRoutes(routes)) .catch(() => setDynamicRoutes([ { id: "dashboard", path: "/", name: "dashboard", component: "dashboard", layout: "SIDEBAR", meta: { title: "控制台", hidden: false, permissionCodes: ["dashboard:view"] }, children: [] } ]) ) .finally(() => setLoading(false)); }, []); const routes = useMemo(() => { if (loading) { return [{ path: "*", element: }]; } const nextRoutes = buildRoutes(dynamicRoutes); if (dynamicRoutes.length === 0) { nextRoutes.unshift({ path: "/", element: }); } return nextRoutes; }, [dynamicRoutes, loading]); return useRoutes(routes); }