index.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // 路由components映射
  2. import type { IRouteProps } from 'umi';
  3. import type { MenuItem } from '@/pages/system/Menu/typing';
  4. import { getDetailNameByCode, MENUS_CODE } from './router';
  5. /** localStorage key */
  6. export const MENUS_DATA_CACHE = 'MENUS_DATA_CACHE';
  7. const DetailCode = 'detail';
  8. /**
  9. * 根据url获取映射的组件
  10. * @param files
  11. */
  12. const findComponents = (files: __WebpackModuleApi.RequireContext) => {
  13. const modules = {};
  14. files.keys().forEach((key) => {
  15. // 删除路径开头的./ 以及结尾的 /index;
  16. const str = key.replace(/(\.\/|\.tsx)/g, '').replace('/index', '');
  17. modules[str] = files(key).default;
  18. });
  19. return modules;
  20. };
  21. /**
  22. * 扁平化路由树
  23. * @param routes
  24. */
  25. export const flatRoute = (routes: MenuItem[]): MenuItem[] => {
  26. return routes.reduce<MenuItem[]>((pValue, currValue) => {
  27. const menu: MenuItem[] = [];
  28. const { children, ...extraRoute } = currValue;
  29. menu.push(extraRoute);
  30. return [...pValue, ...menu, ...flatRoute(children || [])];
  31. }, []);
  32. };
  33. /**
  34. * 获取菜单组件
  35. * @param baseCode
  36. */
  37. const findDetailRoute = (baseCode: string, url: string): MenuItem | undefined => {
  38. if (baseCode) {
  39. const allComponents = findComponents(require.context('@/pages', true, /index(\.tsx)$/));
  40. const code = `${baseCode}/Detail`;
  41. const path = `${url}/${DetailCode}/:id`;
  42. const component = allComponents[code];
  43. return component
  44. ? ({ path: path, url: path, name: getDetailNameByCode[code], code } as MenuItem)
  45. : undefined;
  46. }
  47. return undefined;
  48. };
  49. export const handleRoutes = (routes?: MenuItem[], level = 1): MenuItem[] => {
  50. return routes
  51. ? routes.map((item) => {
  52. const detailComponent = findDetailRoute(item.code, item.url);
  53. if (detailComponent) {
  54. item.children = item.children ? [...item.children, detailComponent] : [detailComponent];
  55. }
  56. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  57. if (item.children) {
  58. item.children = handleRoutes(item.children, level + 1);
  59. }
  60. item.level = level;
  61. return item;
  62. })
  63. : [];
  64. };
  65. /**
  66. * 处理为正确的路由格式
  67. * @param extraRoutes 后端菜单数据
  68. * @param level 路由层级
  69. */
  70. const getRoutes = (extraRoutes: MenuItem[], level = 1): IRouteProps[] => {
  71. const allComponents = findComponents(require.context('@/pages', true, /index(\.tsx)$/));
  72. return extraRoutes.map((route) => {
  73. const component = allComponents[route.code] || null;
  74. const _route: IRouteProps = {
  75. key: route.url,
  76. name: route.name,
  77. path: route.url,
  78. };
  79. if (route.children && route.children.length) {
  80. const flatRoutes = getRoutes(flatRoute(route.children || []), level + 1);
  81. const redirect = flatRoutes.filter((r) => r.component)[0]?.path;
  82. _route.children = redirect
  83. ? [
  84. ...flatRoutes,
  85. {
  86. path: _route.path,
  87. redirect: redirect,
  88. },
  89. ]
  90. : flatRoutes;
  91. } else if (component) {
  92. _route.component = component;
  93. }
  94. if (level !== 1) {
  95. _route.exact = true;
  96. }
  97. return _route;
  98. });
  99. };
  100. export const getMenus = (extraRoutes: IRouteProps[]): any[] => {
  101. return extraRoutes.map((route) => {
  102. const children = route.children && route.children.length ? route.children : [];
  103. return {
  104. key: route.url,
  105. name: route.name,
  106. path: route.url,
  107. icon: route.icon,
  108. hideChildrenInMenu: children && children.some((item: any) => item.url.includes(DetailCode)),
  109. exact: route.level !== 1,
  110. children: getMenus(children),
  111. };
  112. });
  113. };
  114. /** 缓存路由数据,格式为 [{ code: url }] */
  115. export const saveMenusCache = (routes: MenuItem[]) => {
  116. const list: MenuItem[] = flatRoute(routes);
  117. const listObject = {};
  118. list.forEach((route) => {
  119. listObject[route.code] = route.url;
  120. });
  121. try {
  122. localStorage.setItem(MENUS_DATA_CACHE, JSON.stringify(listObject));
  123. } catch (e) {
  124. console.log(e);
  125. }
  126. };
  127. /**
  128. * 通过缓存的数据取出相应的路由url
  129. * @param code
  130. */
  131. export const getMenuPathByCode = (code: string): string => {
  132. const menusStr = localStorage.getItem(MENUS_DATA_CACHE) || '{}';
  133. const menusData = JSON.parse(menusStr);
  134. return menusData[code];
  135. };
  136. /**
  137. * 通过缓存的数据取出相应的路由url
  138. * @param code 路由Code
  139. * @param id 路由携带参数
  140. * @param regStr 路由参数code
  141. */
  142. export const getMenuPathByParams = (code: string, id?: string, regStr: string = ':id') => {
  143. const menusData = getMenuPathByCode(code);
  144. return id ? menusData.replace(regStr, id) : menusData;
  145. };
  146. export default getRoutes;
  147. export { MENUS_CODE };