generate-routes-backend.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import type { RouteRecordRaw } from 'vue-router';
  2. import type {
  3. ComponentRecordType,
  4. GenerateMenuAndRoutesOptions,
  5. RouteRecordStringComponent,
  6. } from '@vben-core/typings';
  7. import { mapTree } from '@vben-core/shared/utils';
  8. import { getRoles } from './role.tool';
  9. /**
  10. * 动态生成路由 - 后端方式
  11. */
  12. async function generateRoutesByBackend(
  13. options: GenerateMenuAndRoutesOptions,
  14. ): Promise<RouteRecordRaw[]> {
  15. const { fetchMenuListAsync, layoutMap = {}, pageMap = {} } = options;
  16. try {
  17. const menuRoutes = await fetchMenuListAsync?.(
  18. getRoles('backend', options.roles),
  19. );
  20. if (!menuRoutes) {
  21. return [];
  22. }
  23. const normalizePageMap: ComponentRecordType = {};
  24. for (const [key, value] of Object.entries(pageMap)) {
  25. normalizePageMap[normalizeViewPath(key)] = value;
  26. }
  27. const routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap);
  28. return routes;
  29. } catch (error) {
  30. console.error(error);
  31. throw error;
  32. }
  33. }
  34. function convertRoutes(
  35. routes: RouteRecordStringComponent[],
  36. layoutMap: ComponentRecordType,
  37. pageMap: ComponentRecordType,
  38. ): RouteRecordRaw[] {
  39. return mapTree(routes, (node) => {
  40. const route = node as unknown as RouteRecordRaw;
  41. const { component, name } = node;
  42. if (!name) {
  43. console.error('route name is required', route);
  44. }
  45. // layout转换
  46. if (component && layoutMap[component]) {
  47. route.component = layoutMap[component];
  48. // 页面组件转换
  49. } else if (component) {
  50. const normalizePath = normalizeViewPath(component);
  51. const pageKey = normalizePath.endsWith('.vue')
  52. ? normalizePath
  53. : `${normalizePath}.vue`;
  54. if (pageMap[pageKey]) {
  55. route.component = pageMap[pageKey];
  56. } else {
  57. console.error(`route component is invalid: ${pageKey}`, route);
  58. route.component = pageMap['/_core/fallback/not-found.vue'];
  59. }
  60. }
  61. return route;
  62. });
  63. }
  64. function normalizeViewPath(path: string): string {
  65. // 去除相对路径前缀
  66. const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, '');
  67. // 确保路径以 '/' 开头
  68. const viewPath = normalizedPath.startsWith('/')
  69. ? normalizedPath
  70. : `/${normalizedPath}`;
  71. // 这里耦合了vben-admin的目录结构
  72. return viewPath.replace(/^\/views/, '');
  73. }
  74. export { generateRoutesByBackend };