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