accessible.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import type {
  2. AccessModeType,
  3. GenerateMenuAndRoutesOptions,
  4. RouteRecordRaw,
  5. } from '@vben/types';
  6. import {
  7. cloneDeep,
  8. generateMenus,
  9. generateRoutesByBackend,
  10. generateRoutesByFrontend,
  11. mapTree,
  12. } from '@vben/utils';
  13. async function generateAccessible(
  14. mode: AccessModeType,
  15. options: GenerateMenuAndRoutesOptions,
  16. ) {
  17. const { router } = options;
  18. options.routes = cloneDeep(options.routes);
  19. // 生成路由
  20. const accessibleRoutes = await generateRoutes(mode, options);
  21. const root = router.getRoutes().find((item) => item.path === '/');
  22. // 动态添加到router实例内
  23. accessibleRoutes.forEach((route) => {
  24. if (root && !route.meta?.noBasicLayout) {
  25. // 为了兼容之前的版本用法,如果包含子路由,则将component移除,以免出现多层BasicLayout
  26. // 如果你的项目已经跟进了本次修改,移除了所有自定义菜单首级的BasicLayout,可以将这段if代码删除
  27. if (route.children && route.children.length > 0) {
  28. delete route.component;
  29. }
  30. root.children?.push(route);
  31. } else {
  32. router.addRoute(route);
  33. }
  34. });
  35. if (root) {
  36. if (root.name) {
  37. router.removeRoute(root.name);
  38. }
  39. router.addRoute(root);
  40. }
  41. // 生成菜单
  42. const accessibleMenus = await generateMenus(accessibleRoutes, options.router);
  43. return { accessibleMenus, accessibleRoutes };
  44. }
  45. /**
  46. * Generate routes
  47. * @param mode
  48. * @param options
  49. */
  50. async function generateRoutes(
  51. mode: AccessModeType,
  52. options: GenerateMenuAndRoutesOptions,
  53. ) {
  54. const { forbiddenComponent, roles, routes } = options;
  55. let resultRoutes: RouteRecordRaw[] = routes;
  56. switch (mode) {
  57. case 'backend': {
  58. resultRoutes = await generateRoutesByBackend(options);
  59. break;
  60. }
  61. case 'frontend': {
  62. resultRoutes = await generateRoutesByFrontend(
  63. routes,
  64. roles || [],
  65. forbiddenComponent,
  66. );
  67. break;
  68. }
  69. }
  70. /**
  71. * 调整路由树,做以下处理:
  72. * 1. 对未添加redirect的路由添加redirect
  73. */
  74. resultRoutes = mapTree(resultRoutes, (route) => {
  75. // 如果有redirect或者没有子路由,则直接返回
  76. if (route.redirect || !route.children || route.children.length === 0) {
  77. return route;
  78. }
  79. const firstChild = route.children[0];
  80. // 如果子路由不是以/开头,则直接返回,这种情况需要计算全部父级的path才能得出正确的path,这里不做处理
  81. if (!firstChild?.path || !firstChild.path.startsWith('/')) {
  82. return route;
  83. }
  84. route.redirect = firstChild.path;
  85. return route;
  86. });
  87. return resultRoutes;
  88. }
  89. export { generateAccessible };