wanshenmean
10 小时以前 f288ccc545f8cc32bc922c96dfb3cab9a1f92ec6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
 * 菜单数据转换工具
 * 将后端菜单格式转换为 Vben Admin 菜单格式
 */
import type { RouteRecordRaw } from 'vue-router';
import type { BackendMenuNode } from '@/api/modules/menu';
 
/** Element Plus 图标名称映射 */
const iconMap: Record<string, string> = {
  'el-icon-menu': 'Menu',
  'el-icon-user': 'User',
  'el-icon-setting': 'Setting',
  'el-icon-home': 'HomeFilled',
  'el-icon-document': 'Document',
  'el-icon-edit': 'Edit',
  'el-icon-view': 'View',
  'el-icon-delete': 'Delete',
  'el-icon-search': 'Search',
  'el-icon-refresh': 'Refresh',
  'el-icon-download': 'Download',
  'el-icon-upload': 'Upload',
  'el-icon-goods': 'Goods',
  'el-icon-box': 'Box',
  'el-icon-truck': 'Van',
  'el-icon-shop': 'Shop',
  'el-icon-list': 'List',
  'el-icon-grid': 'Grid',
  'el-icon-s-custom': 'UserFilled',
  'el-icon-s-order': 'List',
  'el-icon-s-grid': 'Grid',
  'el-icon-s-home': 'HomeFilled',
  'el-icon-s-data': 'DataLine',
  'el-icon-s-check': 'CircleCheck',
  'el-icon-s-management': 'Management',
};
 
/**
 * 转换图标名称
 * el-icon-menu -> Menu
 */
export function transformIcon(icon?: string): string {
  if (!icon) return 'Menu';
  return iconMap[icon] || 'Menu';
}
 
/**
 * 标准化菜单路径
 * "/Manager/home" -> "/home"
 */
export function normalizePath(url?: string): string {
  if (!url) return '/';
  let path = url.replace('/Manager', '') || '/';
  if (!path.startsWith('/')) {
    path = '/' + path;
  }
  return path;
}
 
/**
 * 检查是否为外部链接
 */
function isExternalUrl(url?: string): boolean {
  if (!url) return false;
  return url.startsWith('http://') || url.startsWith('https://');
}
 
/**
 * 将后端菜单节点转换为 Vben 菜单项
 */
export function transformMenuItem(menu: BackendMenuNode): RouteRecordRaw | null {
  const name = menu.name || menu.text || '未命名';
  const url = menu.url || menu.path || '';
  const path = normalizePath(url);
 
  // 跳过外部链接
  if (isExternalUrl(url)) {
    return null;
  }
 
  const route: RouteRecordRaw = {
    path,
    name: path.replace(/\//g, '_').replace(/^_/, '') || 'root',
    meta: {
      title: name,
      icon: menu.icon || 'el-icon-menu',
    },
  };
 
  // 递归处理子菜单
  if (menu.children?.length) {
    const children = menu.children
      .map((child) => transformMenuItem(child))
      .filter((r): r is RouteRecordRaw => r !== null);
    if (children.length > 0) {
      route.children = children;
    }
  }
 
  return route;
}
 
/**
 * 将后端菜单数组转换为路由数组
 */
export function transformMenuToRoutes(menus: BackendMenuNode[]): RouteRecordRaw[] {
  const routes: RouteRecordRaw[] = [];
 
  menus.forEach((menu) => {
    const route = transformMenuItem(menu);
    if (route) {
      routes.push(route);
    }
  });
 
  return routes;
}
 
/**
 * 将后端菜单数组标准化
 */
export function normalizeMenus(menus: BackendMenuNode[]): BackendMenuNode[] {
  return menus.map((menu) => ({
    ...menu,
    path: normalizePath(menu.url || menu.path),
    icon: menu.icon || 'el-icon-menu',
    children: menu.children ? normalizeMenus(menu.children) : undefined,
  }));
}
 
/**
 * 为菜单列表添加首页项
 */
export function addHomeMenu(menus: BackendMenuNode[]): BackendMenuNode[] {
  const normalized = normalizeMenus(menus);
  normalized.push({
    id: 'home',
    name: '首页',
    text: '首页',
    path: '/home',
    icon: 'el-icon-home',
  });
  return normalized;
}