Browse Source

修改路由为动态。待完善

main
李金 7 months ago
parent
commit
d18a4b98f4
  1. 8
      src/App.tsx
  2. 6
      src/pages/dashboard/index.tsx
  3. 127
      src/routes.tsx
  4. 3
      src/service/system.ts
  5. 8
      src/store/user.ts

8
src/App.tsx

@ -1,4 +1,4 @@
import { AppContextProvider } from '@/context.ts'
import { AppContextProvider } from '@/context.ts'
import { initI18n } from '@/i18n.ts' import { initI18n } from '@/i18n.ts'
import { appAtom, appStore, changeLanguage } from '@/store/system.ts' import { appAtom, appStore, changeLanguage } from '@/store/system.ts'
import { userMenuDataAtom } from '@/store/user.ts' import { userMenuDataAtom } from '@/store/user.ts'
@ -14,7 +14,7 @@ import PageLoading from '@/components/page-loading'
function App() { function App() {
const [ appData, ] = useAtom(appAtom) const [ appData, ] = useAtom(appAtom)
const { data = [], isLoading, refetch } = useAtomValue(userMenuDataAtom)
const { data = [], isLoading, isFetching, refetch } = useAtomValue(userMenuDataAtom)
useEffect(() => { useEffect(() => {
initI18n() initI18n()
@ -28,10 +28,12 @@ function App() {
}, [ appData.token ]) }, [ appData.token ])
if (isLoading) {
if (isLoading || isFetching) {
return <PageLoading/> return <PageLoading/>
} }
console.log('app render', data)
return ( return (
<ConfigProvider> <ConfigProvider>
<AppContextProvider value={{ <AppContextProvider value={{

6
src/pages/dashboard/index.tsx

@ -1,5 +1,5 @@
import {ProCard} from '@ant-design/pro-components'
import {createFileRoute} from '@tanstack/react-router'
import { ProCard } from '@ant-design/pro-components'
import { createFileRoute, createLazyFileRoute } from '@tanstack/react-router'
const Index = () => { const Index = () => {
@ -19,7 +19,7 @@ const Index = () => {
) )
} }
export const Route = createFileRoute('/dashboard')({
export const Route = createLazyFileRoute('/dashboard')({
component: Index, component: Index,
}) })
export default Index export default Index

127
src/routes.tsx

@ -8,6 +8,7 @@ import EmptyLayout from '@/layout/EmptyLayout.tsx'
import ListPageLayout from '@/layout/ListPageLayout.tsx' import ListPageLayout from '@/layout/ListPageLayout.tsx'
import { Route as DashboardImport } from '@/pages/dashboard' import { Route as DashboardImport } from '@/pages/dashboard'
import { Route as LoginRouteImport } from '@/pages/login' import { Route as LoginRouteImport } from '@/pages/login'
import { generateUUID } from '@/utils/uuid.ts'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { import {
AnyRoute, AnyRoute,
@ -85,10 +86,10 @@ const notAuthRoute = createRoute({
component: NotPermission component: NotPermission
}) })
const dashboardRoute = DashboardImport.update({
path: '/dashboard',
getParentRoute: () => layoutAuthRoute,
} as any)
// const dashboardRoute = DashboardImport.update({
// path: '/dashboard',
// getParentRoute: () => layoutAuthRoute,
// } as any)
const loginRoute = LoginRouteImport.update({ const loginRoute = LoginRouteImport.update({
path: '/login', path: '/login',
@ -165,50 +166,21 @@ declare module '@tanstack/react-router' {
} }
} }
const routeTree = rootRoute.addChildren(
[
//非Layout
loginRoute,
emptyRoute,
//不带权限Layout
layoutNormalRoute.addChildren([
notAuthRoute,
]),
//带权限Layout
dashboardRoute,
authRoute.addChildren(
[
layoutAuthRoute.addChildren(
[
menusRoute,
departmentsRoute,
usersRoute,
rolesRoute,
]
),
]
)
]
)
export const generateDynamicRoutes = (menuData: MenuItem[]) => {
export const generateDynamicRoutes = (menuData: MenuItem[], parentRoute: AnyRoute) => {
// 递归生成路由,如果有routes则递归生成子路由 // 递归生成路由,如果有routes则递归生成子路由
const generateRoutes = (menu: MenuItem, parentRoute: AnyRoute) => { const generateRoutes = (menu: MenuItem, parentRoute: AnyRoute) => {
console.log('gen route', menu)
const path = menu.path?.replace(parentRoute.options?.path, '') const path = menu.path?.replace(parentRoute.options?.path, '')
const isLayout = menu.children && menu.children.length > 0 && menu.type === 'menu' const isLayout = menu.children && menu.children.length > 0 && menu.type === 'menu'
if (isLayout && !menu.component) {
if (isLayout && (!menu.path || !menu.component)) {
//没有component的layout,直接返回 //没有component的layout,直接返回
console.log('no-page')
return createRoute({ return createRoute({
getParentRoute: () => parentRoute,
id: path!,
component: ListPageLayout,
getParentRoute: () => layoutAuthRoute,
id: `/layout-no-path-${generateUUID()}`,
component: RootLayout,
}) })
} }
@ -219,11 +191,17 @@ export const generateDynamicRoutes = (menuData: MenuItem[]) => {
} as any } as any
if (isLayout) { if (isLayout) {
options.id = path!
options.id = path ?? `/layout-${generateUUID()}`
} else { } else {
options.path = path!
if (!path) {
console.log(`${menu.name}没有设置视图`)
} else {
options.path = path
}
} }
console.log('gen route', options)
//删除掉parentRoute的path,避免重复 //删除掉parentRoute的path,避免重复
const route = createRoute(options).lazy(async () => { const route = createRoute(options).lazy(async () => {
@ -238,51 +216,94 @@ export const generateDynamicRoutes = (menuData: MenuItem[]) => {
} }
if (!component) { if (!component) {
return createLazyRoute(menu.path)({
return createLazyRoute(options.path)({
component: () => <div>404 Not Found</div> component: () => <div>404 Not Found</div>
}) })
} }
//处理component路径
component = component.replace(/^\/pages/, '')
component = component.replace(/^\//, '')
console.log('load', `/pages/${component}`)
/* @vite-ignore */ /* @vite-ignore */
const d = await import(`${component}`)
const d = await import(`/pages/${component}`)
if (d.Route) { if (d.Route) {
console.log(d.Route)
return d.Route return d.Route
} }
if (d.GenRoute) { if (d.GenRoute) {
return d.GenRoute(menu.path)
return d.GenRoute(options.path)
} }
return createLazyRoute(menu.path)({
return createLazyRoute(options.path)({
component: d.default || d component: d.default || d
}) })
}) })
return route
return route
} }
// 对menuData递归生成路由,只处理type =1 的菜单 // 对menuData递归生成路由,只处理type =1 的菜单
const did = (menus: MenuItem[], parentRoute: AnyRoute) => { const did = (menus: MenuItem[], parentRoute: AnyRoute) => {
return menus.filter((item) => item.type === 'menu').map((item) => {
return menus.filter((item) => item.type === 'menu').map((item, index) => {
// 如果有children则递归生成子路由,同样只处理type =1 的菜单 // 如果有children则递归生成子路由,同样只处理type =1 的菜单
const route = generateRoutes(item, parentRoute) const route = generateRoutes(item, parentRoute)
// console.log(route)
if (item.children && item.children.length > 0) { if (item.children && item.children.length > 0) {
const children = did(item.children, route) const children = did(item.children, route)
if (children.length > 0) { if (children.length > 0) {
route.addChildren(children) route.addChildren(children)
} }
} }
route.init({ originalIndex: index })
return route return route
}) })
} }
return did(menuData, rootRoute)
const routes = did(menuData, parentRoute)
parentRoute.addChildren(routes)
} }
const routeTree = rootRoute.addChildren(
[
//非Layout
loginRoute,
emptyRoute,
const router = createRouter({
//不带权限Layout
layoutNormalRoute.addChildren([
notAuthRoute,
]),
//带权限Layout
// dashboardRoute,
authRoute.addChildren(
[
layoutAuthRoute
/*.addChildren(
[
menusRoute,
departmentsRoute,
usersRoute,
rolesRoute,
]
),*/
]),
]
)
export const RootProvider = memo((props: { context: Partial<IRootContext> }) => {
generateDynamicRoutes(props.context.menuData ?? [], layoutAuthRoute)
const router = createRouter({
routeTree, routeTree,
context: { queryClient, menuData: [] }, context: { queryClient, menuData: [] },
defaultPreload: 'intent' defaultPreload: 'intent'
})
export const RootProvider = memo((props: { context: Partial<IRootContext> }) => {
})
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>

3
src/service/system.ts

@ -1,3 +1,4 @@
import { IPageResult } from '@/types'
import { IUserInfo } from '@/types/user' import { IUserInfo } from '@/types/user'
import request from '../request.ts' import request from '../request.ts'
import { LoginRequest, LoginResponse } from '@/types/login' import { LoginRequest, LoginResponse } from '@/types/login'
@ -20,7 +21,7 @@ const systemServ = {
return request.get<IUserInfo>('/sys/user/info') return request.get<IUserInfo>('/sys/user/info')
}, },
menus: () => { menus: () => {
return request.get<IMenu[]>('/sys/user/menus')
return request.get<IPageResult<IMenu[]>>('/sys/user/menus')
} }
}, },

8
src/store/user.ts

@ -1,8 +1,8 @@
import { appAtom } from '@/store/system.ts' import { appAtom } from '@/store/system.ts'
import { IMenu } from '@/types/menus'
import { IUserInfo } from '@/types/user' import { IUserInfo } from '@/types/user'
import { AxiosResponse } from 'axios'
import { atom } from 'jotai/index' import { atom } from 'jotai/index'
import { IApiResult, IAuth, MenuItem } from '@/types'
import { IApiResult, IAuth, IPageResult, MenuItem } from '@/types'
import { LoginRequest } from '@/types/login' import { LoginRequest } from '@/types/login'
import { atomWithMutation, atomWithQuery } from 'jotai-tanstack-query' import { atomWithMutation, atomWithQuery } from 'jotai-tanstack-query'
import systemServ from '@/service/system.ts' import systemServ from '@/service/system.ts'
@ -45,13 +45,13 @@ export const currentUserAtom = atomWithQuery<IApiResult<IUserInfo>, any, IUserIn
} }
}) })
export const userMenuDataAtom = atomWithQuery<any, MenuItem[]>((get) => ({
export const userMenuDataAtom = atomWithQuery<IApiResult<IPageResult<IMenu[]>>, any, MenuItem[]>((get) => ({
enabled: false, enabled: false,
queryKey: [ 'user_menus', get(appAtom).token ], queryKey: [ 'user_menus', get(appAtom).token ],
queryFn: async () => { queryFn: async () => {
return await systemServ.user.menus() return await systemServ.user.menus()
}, },
select: (data: AxiosResponse) => {
select: (data) => {
return formatMenuData(data.data.rows as any ?? []) return formatMenuData(data.data.rows as any ?? [])
}, },
cacheTime: 1000 * 60, cacheTime: 1000 * 60,

Loading…
Cancel
Save