refactor(useMetaLayoutsMenuOptions): 优化路由过滤与排序逻辑
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user