feat: 重构菜单项生成逻辑,支持分组和树形结构
This commit is contained in:
@ -1,31 +1,70 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { createGetRoutes, setupLayoutsResult } from '@/plugins/router';
|
import { createGetRoutes, setupLayoutsResult } from '@/plugins/router';
|
||||||
|
import type { MenuItem } from 'primevue/menuitem';
|
||||||
import { routes } from 'vue-router/auto-routes';
|
import { routes } from 'vue-router/auto-routes';
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const menuItems = computed(() => {
|
const menuItems = computed(() => {
|
||||||
let flatArray: Record<string, string>[] = createGetRoutes(router)()
|
let flatArray: MenuItem[] = createGetRoutes(router)()
|
||||||
.filter((route) => !route.path.includes('/:'))
|
.filter((route) => !route.path.includes('/:'))
|
||||||
.map((route) => ({
|
.map((route) => ({
|
||||||
id: route.path,
|
id: route.path,
|
||||||
name: `${(route.name as string) || route.path}`,
|
label: `${(route.name as string) || route.path}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
flatArray = flatArray.map((item, index) => {
|
flatArray = flatArray.map((item, index) => {
|
||||||
let id = item.id;
|
let id = item.id;
|
||||||
if (flatArray.some((item) => item.id.startsWith(`${id}/`))) {
|
if (flatArray.some((item) => item.id.startsWith(`${id}/`))) {
|
||||||
id = `${id}/`;
|
id = `${id}/index`;
|
||||||
}
|
}
|
||||||
// 去掉最前面的 /
|
// 去掉最前面的 /
|
||||||
id = id.replace(/^\//, '');
|
id = id.replace(/^\//, '');
|
||||||
|
|
||||||
|
let parentId = id.replace(/\/[^/]+$/, '');
|
||||||
|
if (parentId === id) {
|
||||||
|
parentId = '_ROOT_';
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
id: id,
|
...item,
|
||||||
parentId: id.replace(/\/[^/]+$/, ''),
|
parentId,
|
||||||
name: item.name,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
console.debug(`flatArray :>> `, JSON.stringify(flatArray, null, 2));
|
const groupItems = flatArray.reduce(
|
||||||
return flatArray;
|
(acc, flatArrItem) => {
|
||||||
|
if (
|
||||||
|
!acc.some((item) => item.id === flatArrItem.parentId) && //
|
||||||
|
flatArrItem.parentId !== '_ROOT_'
|
||||||
|
) {
|
||||||
|
let groupItemParentId = flatArrItem.parentId.replace(/\/[^/]+$/, '');
|
||||||
|
if (groupItemParentId === flatArrItem.parentId) groupItemParentId = '_ROOT_';
|
||||||
|
acc.push({
|
||||||
|
id: flatArrItem.parentId,
|
||||||
|
label: `Group ${flatArrItem.parentId}`,
|
||||||
|
parentId: groupItemParentId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[] as Record<string, string>[],
|
||||||
|
);
|
||||||
|
console.debug(`groupItems :>> `, groupItems);
|
||||||
|
const tree = arrayToTree(flatArray.concat(groupItems), { id: 'id', parentId: 'parentId', rootId: '_ROOT_' });
|
||||||
|
|
||||||
|
// 递归把 children 改为 items
|
||||||
|
function _convertChildrenToItems(tree: MenuItem[]): MenuItem[] {
|
||||||
|
return tree.map((item) => {
|
||||||
|
if (item.children.length) {
|
||||||
|
item.items = _convertChildrenToItems(item.children);
|
||||||
|
} else {
|
||||||
|
item.command = (event) => {
|
||||||
|
router.push({ name: item.label as never });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
delete item.children;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return _convertChildrenToItems(tree);
|
||||||
});
|
});
|
||||||
|
|
||||||
const list = [
|
const list = [
|
||||||
@ -66,11 +105,15 @@ const list = [
|
|||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Tabs :value="list[0].title" scrollable>
|
<Tabs value="MenuTest" scrollable>
|
||||||
<TabList>
|
<TabList>
|
||||||
|
<Tab value="MenuTest"> MenuTest </Tab>
|
||||||
<Tab v-for="item in list" :key="item.title" :value="item.title">{{ item.title }}</Tab>
|
<Tab v-for="item in list" :key="item.title" :value="item.title">{{ item.title }}</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
|
<TabPanel value="MenuTest">
|
||||||
|
<PanelMenu :model="menuItems" />
|
||||||
|
</TabPanel>
|
||||||
<TabPanel v-for="item in list" :key="item.title" :value="item.title">
|
<TabPanel v-for="item in list" :key="item.title" :value="item.title">
|
||||||
<pre>{{ item.json }}</pre>
|
<pre>{{ item.json }}</pre>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
Reference in New Issue
Block a user