import NotPermission from '@/components/error/403.tsx' import NotFound from '@/components/error/404.tsx' import ErrorPage from '@/components/error/error.tsx' import Loading from '@/components/loading' import FetchLoading from '@/components/loading/FetchLoading.tsx' import PageLoading from '@/components/page-loading' import { PageStoreProvider } from '@/store' import { AuthenticatedRoute as AuthenticatedImport } from './_authenticatedRoute.tsx' import EmptyLayout from '@/layout/EmptyLayout.tsx' // import ListPageLayout from '@/layout/ListPageLayout.tsx' // import { Route as DashboardImport } from '@/pages/dashboard' import { Route as LoginRouteImport } from '@/pages/login' import { generateUUID } from '@/utils/uuid.ts' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { AnyRoute, createRootRouteWithContext, createRoute, createRouter, lazyRouteComponent, Outlet, redirect, RouterProvider, // createHashHistory, } from '@tanstack/react-router' // import { TanStackRouterDevtools } from '@tanstack/router-devtools' import { memo, useEffect, useRef } from 'react' import RootLayout from './layout/RootLayout' import { IRootContext, MenuItem } from './global' // import { DevTools } from 'jotai-devtools' import { useAtomValue } from 'jotai' import { userMenuDataAtom } from '@/store/system/user.ts' const PageRootLayout = () => { return } export const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, } } }) const rootRoute = createRootRouteWithContext()({ component: () => ( <> {/**/} {/**/} ), beforeLoad: ({ location }) => { if (location.pathname === '/') { return redirect({ to: '/dashboard' }) } }, loader: () => { }, notFoundComponent: NotFound, pendingComponent: PageLoading, errorComponent: ({ error }) => , }) const emptyRoute = createRoute({ getParentRoute: () => rootRoute, id: '/_empty', component: EmptyLayout, }) const authRoute = AuthenticatedImport.update({ getParentRoute: () => rootRoute, id: '/_authenticated', } as any) const layoutNormalRoute = createRoute({ getParentRoute: () => rootRoute, id: '/_normal_layout', component: PageRootLayout, }) const layoutAuthRoute = createRoute({ getParentRoute: () => authRoute, id: '/_auth_layout', component: PageRootLayout, }) const notAuthRoute = createRoute({ getParentRoute: () => layoutNormalRoute, path: '/not-auth', component: NotPermission }) // const dashboardRoute = DashboardImport.update({ // path: '/dashboard', // getParentRoute: () => layoutAuthRoute, // } as any) const loginRoute = LoginRouteImport.update({ path: '/login', getParentRoute: () => emptyRoute, } as any) // // const menusRoute = createRoute({ // getParentRoute: () => layoutAuthRoute, // path: '/system/menus', // }).lazy(async () => await import('@/pages/system/menus').then(d => d.Route)) // // const departmentsRoute = createRoute({ // getParentRoute: () => layoutAuthRoute, // path: '/system/departments', // }).lazy(async () => await import('@/pages/system/departments').then(d => d.Route)) // // const usersRoute = createRoute({ // getParentRoute: () => layoutAuthRoute, // path: '/system/users', // }).lazy(async () => await import('@/pages/system/users').then(d => d.Route)) // // const rolesRoute = createRoute({ // getParentRoute: () => layoutAuthRoute, // path: '/system/roles', // }).lazy(async () => await import('@/pages/system/roles').then(d => d.Route)) declare module '@tanstack/react-router' { interface FileRoutesByPath { '/_authenticated': { preLoaderRoute: typeof AuthenticatedImport parentRoute: typeof rootRoute }, '/_normal_layout': { preLoaderRoute: typeof layoutNormalRoute parentRoute: typeof rootRoute }, '/_layout': { preLoaderRoute: typeof layoutAuthRoute parentRoute: typeof rootRoute }, // '/': { // preLoaderRoute: typeof DashboardImport // parentRoute: typeof layoutAuthRoute // }, // '/dashboard': { // preLoaderRoute: typeof DashboardImport // parentRoute: typeof layoutAuthRoute // }, '/login': { preLoaderRoute: typeof LoginRouteImport parentRoute: typeof rootRoute }, // '/system/menus': { // preLoaderRoute: typeof menusRoute // parentRoute: typeof layoutAuthRoute // }, // '/system/departments': { // preLoaderRoute: typeof departmentsRoute // parentRoute: typeof layoutAuthRoute // }, // '/system/users': { // preLoaderRoute: typeof usersRoute // parentRoute: typeof layoutAuthRoute // }, // '/system/roles': { // preLoaderRoute: typeof rolesRoute // parentRoute: typeof layoutAuthRoute // }, '/welcome': { preLoaderRoute: typeof rootRoute parentRoute: typeof layoutAuthRoute }, } } const modules = import.meta.glob('./pages/**/*.{jsx,tsx}') console.log(modules) const generateDynamicRoutes = (menuData: MenuItem[], parentRoute: AnyRoute) => { // 递归生成路由,如果有routes则递归生成子路由 const generateRoutes = (menu: MenuItem, parentRoute: AnyRoute) => { const path = menu.path?.replace(parentRoute.options?.path, '') const isLayout = menu.children && menu.children.length > 0 && menu.type === 'menu' if (isLayout && (!menu.path || !menu.component)) { //没有component的layout,直接返回 return createRoute({ getParentRoute: () => layoutAuthRoute, id: `/layout-no-path-${generateUUID()}`, component: EmptyLayout, }) } // @ts-ignore 添加menu属性,方便后面获取 const options = { getParentRoute: () => parentRoute, menu, } as any if (isLayout) { options.id = path ?? `/layout-${generateUUID()}` } else { if (!path) { console.log(`${menu.name}没有设置视图`) options.id = menu.meta.name } else { options.path = path } } let component = menu.component // menu.type // 1,组件(页面),2,IFrame,3,外链接,4,按钮 if (menu.type === 'iframe') { component = '@/components/Iframe' } //处理component路径 component = component.replace(/^\/pages/, '') component = component.replace(/^\//, '') return createRoute({ ...options, // @ts-ignore fix import component: lazyRouteComponent(() => { //处理最后可能包含index || index.tsx || index.jsx if (component.endsWith('.tsx')) { component = component.replace(/\.tsx$/, '') } if (component.endsWith('.jsx')) { component = component.replace(/\.jsx$/, '') } if (component.endsWith('/index')) { component = component.replace(/\/index$/, '') } let module: () => Promise //优先匹配无index的情况 if (modules[`./pages/${component}.tsx`] || modules[`./pages/${component}.jsx`]) { module = modules[`./pages/${component}.tsx`] || modules[`./pages/${component}.jsx`] } else { module = modules[`./pages/${component}/index.tsx`] || modules[`./pages/${component}/index.jsx`] } if (!module) { return NotFound } return module().then((d: any) => { // console.log(d) if (d.Route) { d.Route.update({ path: menu.path, }) } return d }) }), notFoundComponent: NotFound, }) } // 对menuData递归生成路由,只处理type =1 的菜单 const did = (menus: MenuItem[], parentRoute: AnyRoute) => { return menus.filter((item) => item.type === 'menu').map((item, index) => { // 如果有children则递归生成子路由,同样只处理type =1 的菜单 const route = generateRoutes(item, parentRoute) // console.log(route) if (item.children && item.children.length > 0) { const children = did(item.children, route) if (children.length > 0) { route.addChildren(children) } } route.init({ originalIndex: index }) return route }) } const routes = did(menuData, parentRoute) parentRoute.addChildren(routes) } const routeTree = rootRoute.addChildren( [ //非Layout loginRoute, emptyRoute, //不带权限Layout layoutNormalRoute.addChildren([ notAuthRoute, ]), //带权限Layout // dashboardRoute, authRoute.addChildren( [ layoutAuthRoute /*.addChildren( [ menusRoute, departmentsRoute, usersRoute, rolesRoute, ] ),*/ ]), ] ) export const RootProvider = memo((props: { context: Partial }) => { const { data: menuData, isLoading, refetch } = useAtomValue(userMenuDataAtom) const isFetchRef = useRef(false) useEffect(() => { if (isFetchRef.current) { return } isFetchRef.current = true refetch() }, []) if (isLoading) { return } generateDynamicRoutes(menuData ?? [], layoutAuthRoute) // const hashHistory = createHashHistory() const router = createRouter({ routeTree, // history: hashHistory, context: { queryClient, menuData: [] }, defaultPreload: 'intent', defaultPendingComponent: () => }) return ( ) }) export default RootProvider