refactor(useMetaLayoutsMenuOptions): 优化路由过滤与排序逻辑
All checks were successful
CI/CD Pipeline / playwright (push) Successful in 4m9s
CI/CD Pipeline / build-and-deploy (push) Successful in 4m27s

This commit is contained in:
严浩
2025-10-27 14:04:58 +08:00
parent 267bf75bc1
commit d4d9620db2

View File

@@ -48,9 +48,8 @@ export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref<M
const menuMap = new Map<string, MenuOption>(); const menuMap = new Map<string, MenuOption>();
const rootMenus: MenuOption[] = []; const rootMenus: MenuOption[] = [];
// 过滤和排序路由 // 过滤路由
const validRoutes = routes const validRoutes = routes.filter((route) => {
.filter((route) => {
// 过滤掉不需要显示的路由 // 过滤掉不需要显示的路由
if (route.meta?.hideInMenu === true || route.meta?.layout === false) { if (route.meta?.hideInMenu === true || route.meta?.layout === false) {
return false; return false;
@@ -64,46 +63,53 @@ export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref<M
return false; return false;
} }
return true; return true;
}) });
// 排序路由,确保父路由总是在子路由之前,同级路由则根据 `meta.order` 排序
.sort((a: RouteRecordRaw, b: RouteRecordRaw) => { // 排序路由:先按路径深度分组,再按 order 排序
const sortedRoutes = validRoutes.slice().sort((a: RouteRecordRaw, b: RouteRecordRaw) => {
const pathA = a.path; const pathA = a.path;
const pathB = b.path; const pathB = b.path;
// 1. 首先按路径深度排序(确保父路由在子路由之前)
const depthA = pathA.split('/').filter(Boolean).length;
const depthB = pathB.split('/').filter(Boolean).length;
if (depthA !== depthB) {
return depthA - depthB;
}
// 2. 获取父路径,判断是否为同一父级下的路由
const segmentsA = pathA.split('/').filter(Boolean); const segmentsA = pathA.split('/').filter(Boolean);
const segmentsB = pathB.split('/').filter(Boolean); const segmentsB = pathB.split('/').filter(Boolean);
const parentAPath = `/${segmentsA.slice(0, -1).join('/')}`; const parentA = segmentsA.length > 1 ? `/${segmentsA.slice(0, -1).join('/')}` : '/';
const parentBPath = `/${segmentsB.slice(0, -1).join('/')}`; const parentB = segmentsB.length > 1 ? `/${segmentsB.slice(0, -1).join('/')}` : '/';
// 如果不是同级路由,则按路径排序,确保父路由在前 // 如果父路径不同,按父路径字母顺序排序
if (parentAPath !== parentBPath) { if (parentA !== parentB) {
return pathA.localeCompare(pathB); return parentA.localeCompare(parentB);
} }
// 同级路由,处理 `meta.order` // 3. 同一父级下的路由,按 order 排序
const orderA = a.meta?.order; const orderA = a.meta?.order;
const orderB = b.meta?.order; const orderB = b.meta?.order;
const hasOrderA = orderA !== undefined; const hasOrderA = typeof orderA === 'number';
const hasOrderB = orderB !== undefined; const hasOrderB = typeof orderB === 'number';
// 当一个有 order 而另一个没有时,有 order 的排在前面 // 有 order 的排在没有 order 的前面
if (hasOrderA !== hasOrderB) { if (hasOrderA && !hasOrderB) return -1;
return hasOrderA ? -1 : 1; if (!hasOrderA && hasOrderB) return 1;
}
// 当两个都有 order 时,按 order 值升序排序 // 都有 order 时,按 order 值升序排序
if (hasOrderA && hasOrderB) { if (hasOrderA && hasOrderB) {
const orderDiff = orderA - orderB; const diff = (orderA as number) - (orderB as number);
if (orderDiff !== 0) { if (diff !== 0) return diff;
return orderDiff;
}
} }
// order 相同或都没有 order按路径字母顺序排序 // order 相同或都没有 order按路径字母顺序排序
return pathA.localeCompare(pathB); return pathA.localeCompare(pathB);
}); });
// 构建菜单树 // 构建菜单树
for (const route of validRoutes) { for (const route of sortedRoutes) {
const pathSegments = route.path.split('/').filter(Boolean); const pathSegments = route.path.split('/').filter(Boolean);
const routeName = route.name as string; const routeName = route.name as string;
@@ -147,30 +153,32 @@ export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref<M
} }
} }
// 添加调试日志
if (import.meta.env.DEV) {
console.debug(
'排序后的路由:',
sortedRoutes.map((route) => ({
path: route.path,
name: route.name,
order: route.meta?.order,
})),
);
}
return rootMenus; return rootMenus;
} }
// console.debug( if (import.meta.env.DEV) {
// '原始路由:', console.debug(
// JSON.stringify( '原始路由:',
// routes.map((route) => ({ routes.map((route) => ({
// // path path: route.path,
// // name name: route.name,
// // meta order: route.meta?.order,
// ...route, })),
// props: undefined, );
// children: undefined, console.debug('转换后的菜单:', options.value);
// instances: undefined, }
// leaveGuards: undefined,
// updateGuards: undefined,
// enterCallbacks: undefined,
// components: undefined,
// })),
// null,
// 0,
// ),
// );
// console.debug('转换后的菜单:', JSON.stringify(options.value, null, 0));
return { return {
options, options,