113 lines
2.3 KiB
TypeScript
113 lines
2.3 KiB
TypeScript
import { RouteRecordRaw } from "vue-router";
|
|
import { appRoutes } from "../routes/page";
|
|
|
|
/**
|
|
* 菜单项类型
|
|
*/
|
|
export interface MenuItem {
|
|
id: string;
|
|
parentId?: string;
|
|
path: string;
|
|
sort?: number;
|
|
title?: string;
|
|
icon?: string;
|
|
external?: boolean;
|
|
children?: MenuItem[];
|
|
}
|
|
|
|
/**
|
|
* 转换页面路由为菜单项
|
|
* @param routes 路由配置
|
|
* @returns
|
|
*/
|
|
function routesToItems(routes: RouteRecordRaw[]): MenuItem[] {
|
|
const items: MenuItem[] = [];
|
|
|
|
for (const route of routes) {
|
|
const { meta = {}, parentMeta, path } = route as any;
|
|
const { title, sort, icon } = meta;
|
|
let id = path;
|
|
let paths = route.path.split("/");
|
|
let parentId = paths.slice(0, -1).join("/");
|
|
if (parentMeta) {
|
|
const { title, icon, sort } = parentMeta;
|
|
id = `${path}/index`;
|
|
parentId = path;
|
|
items.push({
|
|
title,
|
|
icon,
|
|
sort,
|
|
path,
|
|
id: path,
|
|
parentId: paths.slice(0, -1).join("/"),
|
|
});
|
|
} else {
|
|
const p = paths.slice(0, -1).join("/");
|
|
if (routes.some((i) => i.path === p) && parentMeta) {
|
|
parentId = p;
|
|
}
|
|
}
|
|
items.push({ id, title, parentId, path, icon, sort });
|
|
}
|
|
|
|
return items;
|
|
}
|
|
|
|
/**
|
|
* 转换菜单项为树形结构
|
|
* @param list 菜单项列表
|
|
* @returns
|
|
*/
|
|
function listToTree(list: MenuItem[]) {
|
|
const map: Record<string, MenuItem> = {};
|
|
const tree: MenuItem[] = [];
|
|
|
|
for (const item of list) {
|
|
map[item.id] = item;
|
|
}
|
|
|
|
for (const item of list) {
|
|
const parent = map[item.parentId as string];
|
|
if (parent) {
|
|
(parent.children || (parent.children = [])).push(item);
|
|
} else {
|
|
tree.push(item);
|
|
}
|
|
}
|
|
|
|
return tree;
|
|
}
|
|
|
|
/**
|
|
* 排序菜单项
|
|
* @param routes 菜单项列表
|
|
* @param key 排序字段
|
|
* @returns
|
|
*/
|
|
function sort<T extends { children?: T[]; [key: string]: any }>(routes: T[], key = "sort") {
|
|
return routes.sort((a, b) => {
|
|
if (Array.isArray(a.children)) {
|
|
a.children = sort(a.children);
|
|
}
|
|
if (Array.isArray(b.children)) {
|
|
b.children = sort(b.children);
|
|
}
|
|
return (a[key] as number) - (b[key] as number);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 扁平化的菜单
|
|
*/
|
|
export const flatMenus = routesToItems(appRoutes);
|
|
|
|
/**
|
|
* 树结构菜单
|
|
*/
|
|
export const treeMenus = listToTree(flatMenus);
|
|
|
|
/**
|
|
* 排序过的树级菜单
|
|
*/
|
|
export const menus = sort(treeMenus);
|