generate-routes-backend.ts 2.2 KB

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