Skip to content

Commit 24e2081

Browse files
committed
optimize: 修改menu的实现方式
1 parent 5d88af1 commit 24e2081

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

src/features/menu/MenuProvider.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1+
import { emitter, useArray } from '@sa/hooks';
12
import { useCreation } from 'ahooks';
23
import type { FC, PropsWithChildren } from 'react';
34

5+
import { selectActiveFirstLevelMenuKey, setActiveFirstLevelMenuKey } from '@/features/tab/tabStore';
46
import { routes } from '@/router';
5-
import { selectActiveFirstLevelMenuKey, setActiveFirstLevelMenuKey } from '@/store/slice/tab';
67

78
import { useLang } from '../lang';
89
import { useRoute } from '../router';
910

10-
import { filterRoutesToMenus, getActiveFirstLevelMenuKey } from './MenuUtil';
11+
import { filterRoutesToMenus, getActiveFirstLevelMenuKey, mergeMenus } from './MenuUtil';
1112
import { MixMenuContext } from './menuContext';
1213

1314
const MenuProvider: FC<PropsWithChildren> = ({ children }) => {
@@ -17,7 +18,9 @@ const MenuProvider: FC<PropsWithChildren> = ({ children }) => {
1718

1819
const { locale } = useLang();
1920

20-
const menus = useCreation(() => filterRoutesToMenus(routes[0].children || []), [locale]);
21+
const [menus, { updateState }] = useArray<App.Global.Menu, 'key'>(
22+
filterRoutesToMenus(routes.find(r => r.id === '(base)')?.children || [])
23+
);
2124

2225
const firstLevelMenu = menus.map(menu => {
2326
const { children: _, ...rest } = menu;
@@ -49,6 +52,17 @@ const MenuProvider: FC<PropsWithChildren> = ({ children }) => {
4952
dispatch(setActiveFirstLevelMenuKey(routeKey || ''));
5053
}
5154

55+
useMount(() => {
56+
emitter.on('ADD_MENUS', (newMenus: App.Global.Menu[]) => {
57+
console.log('newMenus', newMenus);
58+
updateState(old => mergeMenus(old, newMenus));
59+
});
60+
});
61+
62+
useUpdateEffect(() => {
63+
updateState(menus);
64+
}, [locale]);
65+
5266
const mixMenuContext = useCreation(
5367
() => ({
5468
activeFirstLevelMenuKey,

src/features/menu/MenuUtil.tsx

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,11 @@ import { $t } from '@/locales';
99
* @param routes Auth routes
1010
*/
1111
export function filterRoutesToMenus(routes: RouteObject[]) {
12-
console.log(routes, 'routes');
1312
const menus: App.Global.Menu[] = [];
1413

15-
const cacheRoutes: string[] = [];
16-
1714
for (const route of routes) {
1815
// 如果节点存在 path(注意:这里假设空字符串或 undefined 均视为无 path)
19-
if (route.handle?.keepAlive) {
20-
cacheRoutes.push(route.path as string);
21-
}
16+
2217
if (route.path && !route.handle?.hideInMenu) {
2318
// 如果存在 children,则递归处理
2419
const newNode = getGlobalMenuByBaseRoute(route);
@@ -85,3 +80,43 @@ export function getActiveFirstLevelMenuKey(route: App.Global.TabRoute) {
8580

8681
return firstLevelRouteName;
8782
}
83+
84+
export function mergeMenus(menus: App.Global.Menu[], newMenus: App.Global.Menu[]) {
85+
newMenus.forEach(newMenu => {
86+
const newMenuKey = newMenu.key.split('/'); // 分割路径
87+
88+
function findAndMergeParent(currentMenus: App.Global.Menu[], menuPath: string[]): boolean {
89+
for (const menu of currentMenus) {
90+
// 判断当前菜单的路径是否匹配,使用 startsWith 来判断路径的前缀
91+
const menuKeyParts = menu.key.split('/');
92+
93+
// 如果路径的前缀一致,进一步递归查找子菜单
94+
if (menuKeyParts[1] === menuPath[1]) {
95+
// 如果匹配到父级菜单的路径并且这个菜单没有 children,则初始化 children
96+
if (!menu.children) {
97+
menu.children = [];
98+
}
99+
100+
// 如果 newMenu 的路径和当前菜单的路径匹配,递归查找它的子菜单
101+
if (menuPath.length === 3) {
102+
// 如果路径已完全匹配,将 newMenu 添加到子菜单中
103+
menu.children.push(newMenu);
104+
105+
return true;
106+
}
107+
108+
// 如果路径部分匹配,递归检查当前菜单的 children
109+
return findAndMergeParent(menu.children || [], menuPath.slice(1));
110+
}
111+
}
112+
return false;
113+
}
114+
115+
// 如果没有找到父级,将 newMenu 直接添加到 menus
116+
if (!findAndMergeParent(menus, newMenuKey)) {
117+
menus.push(newMenu);
118+
}
119+
});
120+
121+
return menus;
122+
}

0 commit comments

Comments
 (0)