// 路由表工具 import { AddItemArgs, DeepSeparateArgs, RouteConfig, Routes } from './type' import { ItemType, SubMenuType } from 'antd/lib/menu/hooks/useItems' import { LazyExoticComponent, ReactNode, Suspense } from 'react' import { cloneDeep, isObject } from 'lodash-es' import { Items } from '../context/router' import { Link } from 'react-router-dom' import { ProcessLoading } from '@/components/Loading' // 添加item项 function addItem(args: AddItemArgs) { const { curPath, route } = args const { name, icon, children } = route const o: ItemType = { key: curPath, label: Array.isArray(children) ? name : {name}, children: [] } if (icon) { o.icon = icon } if (!children || !children?.length) { // @ts-ignore delete o.children } return o } // 是否添加到topItems function isPushTopItems(route: RouteConfig) { const { layout } = route if ('layout' in route) { if (isObject(layout)) { // 不渲染左侧sider组件,肯定不加leftItems if ('headerRender' in layout && layout.headerRender === false) { return false } // 不渲染 if ('topItemRender' in layout && layout.topItemRender === false) { return false } } } return true } // 是否添加到leftItems function isPushLeftItems(route: RouteConfig) { const { layout } = route if ('layout' in route) { if (isObject(layout)) { // 不渲染左侧sider组件,肯定不加leftItems if ('leftSiderRender' in layout && layout.leftSiderRender === false) { return false } // 不渲染 if ('leftItemRender' in layout && layout.leftItemRender === false) { return false } } } return true } // 分离路由,筛选出需要left,和top分开渲染的路由 function deepSeparate(args: DeepSeparateArgs) { const { route, leftItems, topItems, parentPath, routeAccess } = args const { name, layout, children, path, access } = route // 无权限 if (access && !routeAccess[access]) return // 如果不存在名字 || 不需要布局 if (!name || layout === false) return const curPath = `${parentPath}/${path!}` const o = addItem({ route, curPath }) const isLeft = isPushLeftItems(route) const isTop = isPushTopItems(route) isLeft && leftItems?.push(cloneDeep(o)) isTop && topItems?.push(cloneDeep(o)) const lastLeftItem = leftItems?.at(-1) as SubMenuType const lastTopItem = topItems?.at(-1) as SubMenuType const nextLeftItems = lastLeftItem?.children const nextTopItems = lastTopItem?.children children?.forEach(child => { const args: DeepSeparateArgs = { route: child, parentPath: curPath, leftItems: nextLeftItems, topItems: nextTopItems, routeAccess } !isLeft && delete args.leftItems !isTop && delete args.topItems deepSeparate(args) }) } // 获取菜单配置项 export function getItems(layoutReoutes: Routes, routeAccess: Record) { // 找到layout需要使用的路由配置 const leftItems: Items = [] const topItems: Items = [] layoutReoutes.forEach(route => { deepSeparate({ route, leftItems, topItems, parentPath: '', routeAccess }) }) return { leftItems, topItems } } // 过滤路由配置权限 // export function filterRoutesAccess(routes: Routes, checkFn: (access: string) => boolean) { // const _deep = (list: Routes) => { // for (let i = 0; i < list.length; i++) { // const curRoute = list[i] // const { access, children } = curRoute // const isNext = children?.length // if (!access) { // isNext && _deep(children) // continue // } // if (checkFn(access)) { // isNext && _deep(children) // } else { // list.splice(i, 1) // i-- // } // } // } // _deep(routes) // } /** * @description 路由懒加载 * @param {Element} Com 需要访问的组件 * @returns element */ export const lazyLoad = (Com: LazyExoticComponent): ReactNode => { return ( }> ) } /** * @description 递归查询对应的路由 * @param {String} path 当前访问地址 * @param {Array} routes 路由列表 * @returns RouteConfig */ export const searchRoute = (aimPath: string, routes: Routes): RouteConfig => { const lastStr = aimPath.split('/').at(-1) const _deep = (routes: Routes) => { let result: RouteConfig = {} for (let i = 0; i < routes.length; i++) { const item = routes[i] if (item.path === lastStr) return item if (item.children?.length) { const res = _deep(item.children) if (Object.keys(res).length) result = res } } return result } return _deep(routes) }