generate-routes-backend.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import type {
  2. ComponentRecordType,
  3. GenerateMenuAndRoutesOptions,
  4. RouteRecordStringComponent,
  5. } from '@vben-core/typings';
  6. import type { RouteRecordRaw } from 'vue-router';
  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. return [];
  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. route.component =
  49. pageMap[
  50. normalizePath.endsWith('.vue')
  51. ? normalizePath
  52. : `${normalizePath}.vue`
  53. ];
  54. }
  55. return route;
  56. });
  57. }
  58. function normalizeViewPath(path: string): string {
  59. // 去除相对路径前缀
  60. const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, '');
  61. // 确保路径以 '/' 开头
  62. const viewPath = normalizedPath.startsWith('/')
  63. ? normalizedPath
  64. : `/${normalizedPath}`;
  65. // 这里耦合了vben-admin的目录结构
  66. return viewPath.replace(/^\/views/, '');
  67. }
  68. export { generateRoutesByBackend };