From 0d492e4760cc52960c3b4e6cf27e0e9339f1a11d Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Mon, 29 Dec 2025 15:50:44 +0800 Subject: [PATCH] perf: Display menu based on role --- frontend/src/router/dynamic.ts | 89 ++++++++++++++++++++++++++++++++++ frontend/src/router/index.ts | 5 +- frontend/src/router/watch.ts | 2 + 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 frontend/src/router/dynamic.ts diff --git a/frontend/src/router/dynamic.ts b/frontend/src/router/dynamic.ts new file mode 100644 index 000000000..913cd89f9 --- /dev/null +++ b/frontend/src/router/dynamic.ts @@ -0,0 +1,89 @@ +import LayoutDsl from '@/components/layout/LayoutDsl.vue' +import { i18n } from '@/i18n' +import { useUserStore } from '@/stores/user' +import type { Router } from 'vue-router' +const userStore = useUserStore() +const t = i18n.global.t + +const dynamicRouterList = [ + { + path: '/ds', + component: LayoutDsl, + name: 'ds-menu', + redirect: '/ds/index', + children: [ + { + path: 'index', + name: 'ds', + component: import('@/views/ds/index.vue'), + meta: { title: t('menu.Data Connections'), iconActive: 'ds', iconDeActive: 'noDs' }, + }, + ], + }, +] as any[] + +const reduceRouters = (router: Router, invalid_router_name_list: string[]) => { + const tree = router.getRoutes() + const invalid_name_set = [] as any + invalid_router_name_list.forEach((router_name: string) => { + router.removeRoute(router_name) + invalid_name_set.push(router_name) + }) + + const pathsSet = new Set(invalid_router_name_list) + + function processNode(node: any): boolean { + if (node.name && pathsSet.has(node.name)) { + return true + } + if (node.children) { + const newChildren: any[] = [] + + for (const child of node.children) { + const shouldRemove = processNode(child) + if (!shouldRemove) { + newChildren.push(child) + } + } + + if (newChildren.length > 0) { + node.children = newChildren + return false + } else { + node.children = undefined + } + } + + return false + } + + let i = 0 + while (i < tree.length) { + if (processNode(tree[i])) { + tree.splice(i, 1) + } else { + i++ + } + } +} + +export const generateDynamicRouters = (router: Router) => { + if (userStore.isAdmin || userStore.isSpaceAdmin) { + dynamicRouterList.forEach((item: any) => router.addRoute(item)) + } else { + const router_name_list = [] as string[] + const stack = [...dynamicRouterList] + while (stack.length) { + const item = stack.pop() + if (item.name) { + router_name_list.push(item.name) + } + if (item.children?.length) { + item.children.forEach((child: any) => { + stack.push(child) + }) + } + } + reduceRouters(router, router_name_list) + } +} diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index b229ee33a..a2314d378 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -64,9 +64,10 @@ export const routes = [ }, ], }, - { + /* { path: '/ds', component: LayoutDsl, + name: 'ds-menu', redirect: '/ds/index', children: [ { @@ -76,7 +77,7 @@ export const routes = [ meta: { title: t('menu.Data Connections'), iconActive: 'ds', iconDeActive: 'noDs' }, }, ], - }, + }, */ { path: '/dashboard', component: LayoutDsl, diff --git a/frontend/src/router/watch.ts b/frontend/src/router/watch.ts index 432840b32..ff5276f02 100644 --- a/frontend/src/router/watch.ts +++ b/frontend/src/router/watch.ts @@ -4,6 +4,7 @@ import { useAppearanceStoreWithOut } from '@/stores/appearance' import { useUserStore } from '@/stores/user' import { request } from '@/utils/request' import type { Router } from 'vue-router' +import { generateDynamicRouters } from './dynamic' const appearanceStore = useAppearanceStoreWithOut() const userStore = useUserStore() @@ -35,6 +36,7 @@ export const watchRouter = (router: Router) => { } if (!userStore.getUid) { await userStore.info() + generateDynamicRouters(router) } if (to.path === '/' || accessCrossPermission(to)) { next('/chat')