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);
}