import type { RouteObject } from 'react-router-dom';
import BeyondHiding from '@/components/BeyondHiding';
import { $t } from '@/locales';
/**
* Get global menus by auth routes
*
* @param routes Auth routes
*/
export function filterRoutesToMenus(routes: RouteObject[]) {
// 先根据 handle?.order 对路由做排序
const sortedRoutes = sortRoutesByOrder(routes);
const menus: App.Global.Menu[] = [];
for (const route of sortedRoutes) {
// 如果节点存在 path(注意:这里假设空字符串或 undefined 均视为无 path)
if (route.path && !route.handle?.hideInMenu) {
// 如果存在 children,则递归处理
const newNode = getGlobalMenuByBaseRoute(route);
if (route.children && route.children.length) {
const filteredChildren = filterRoutesToMenus(route.children);
if (filteredChildren?.length) {
newNode.children = filteredChildren;
}
}
menus.push(newNode);
} else if (route.children && route.children.length) {
// 如果当前节点没有 path,但有 children,则递归处理 children,
menus.push(...filterRoutesToMenus(route.children));
// 如果既没有 path 也没有 children,则该节点直接被过滤掉
}
}
return menus;
}
/**
* sort routes by order
*
* @param routes routes
*/
export function sortRoutesByOrder(routes: RouteObject[]) {
routes.sort((next, prev) => (Number(next.handle?.order) || 0) - (Number(prev.handle?.order) || 0));
routes.forEach(sortRouteByOrder);
return routes;
}
/**
* sort route by order
*
* @param route route
*/
function sortRouteByOrder(route: RouteObject) {
if (route.children?.length) {
route.children.sort((next, prev) => (Number(next.handle?.order) || 0) - (Number(prev.handle?.order) || 0));
route.children.forEach(sortRouteByOrder);
}
return route;
}
/**
* Get global menu by route
*
* @param route
*/
export function getGlobalMenuByBaseRoute(route: RouteObject): App.Global.Menu {
const { path } = route;
const { i18nKey, icon = import.meta.env.VITE_MENU_ICON, localIcon, title } = route.handle ?? {};
const label = i18nKey ? $t(i18nKey) : title;
const menu: App.Global.Menu = {
icon: (
),
key: path || '',
label: ,
title: label
};
return menu;
}
/**
* Get active first level menu key
*
* @param route
*/
export function getActiveFirstLevelMenuKey(route: App.Global.TabRoute) {
const { activeMenu, hideInMenu } = route.handle;
const name = route.pathname;
const routeName = (hideInMenu ? activeMenu : name) || name;
const [_, firstLevelRouteName] = routeName.split('/');
return `/${firstLevelRouteName}`;
}
export function mergeMenus(menus: App.Global.Menu[], newMenus: App.Global.Menu[]) {
newMenus.forEach(newMenu => {
const newMenuKey = newMenu.key.split('/'); // 分割路径
function findAndMergeParent(currentMenus: App.Global.Menu[], menuPath: string[]): boolean {
for (const menu of currentMenus) {
// 判断当前菜单的路径是否匹配,使用 startsWith 来判断路径的前缀
const menuKeyParts = menu.key.split('/');
// 如果路径的前缀一致,进一步递归查找子菜单
if (menuKeyParts[1] === menuPath[1]) {
// 如果匹配到父级菜单的路径并且这个菜单没有 children,则初始化 children
if (!menu.children) {
menu.children = [];
}
// 如果 newMenu 的路径和当前菜单的路径匹配,递归查找它的子菜单
if (menuPath.length === 3) {
// 如果路径已完全匹配,将 newMenu 添加到子菜单中
menu.children.push(newMenu);
return true;
}
// 如果路径部分匹配,递归检查当前菜单的 children
return findAndMergeParent(menu.children || [], menuPath.slice(1));
}
}
return false;
}
// 如果没有找到父级,将 newMenu 直接添加到 menus
if (!findAndMergeParent(menus, newMenuKey)) {
menus.push(newMenu);
}
});
return menus;
}
export function getSelectKey(route: Router.Route) {
const { activeMenu, hideInMenu } = route.handle;
const name = route.pathname as string;
const routeName = (hideInMenu ? activeMenu : name) || name;
return [routeName];
}