From 26edb9e6edc99485b1eae6712c8cb568e5d0d628 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com>
Date: Sat, 5 Sep 2026 12:17:17 +0800
Subject: [PATCH] =?UTF-8?q?task-6(=E5=A3=B3=E5=B1=82/=E8=B7=AF=E7=94=B1):?=
=?UTF-8?q?=20=E5=AE=9A=E4=B9=89=E5=90=8E=E7=AB=AF=E8=8F=9C=E5=8D=95?=
=?UTF-8?q?=E6=A0=91=E5=88=B0=E4=BE=A7=E8=BE=B9=E6=A0=8F=E8=8A=82=E7=82=B9?=
=?UTF-8?q?=E6=98=A0=E5=B0=84=E8=A7=84=E5=88=99=E5=B9=B6=E8=90=BD=E5=9C=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
新增 src/layout/menu-mapper.ts:toSidebarEntries 处理分组/顶级路由叶/畸形节点,
groupKeysForActive 按当前路由展开激活分组;AdminLayout 菜单区改用映射结果,
删除旧 visibleChildren/canSee 死逻辑;8 用例覆盖空树/单叶/缺 route 过滤等。
---
admin-frontend-vue/src/layout/AdminLayout.vue | 42 +++-----
admin-frontend-vue/src/layout/menu-mapper.ts | 46 +++++++++
admin-frontend-vue/tests/task-3.test.ts | 2 +-
admin-frontend-vue/tests/task-6.test.ts | 99 +++++++++++++++++++
4 files changed, 158 insertions(+), 31 deletions(-)
create mode 100644 admin-frontend-vue/src/layout/menu-mapper.ts
create mode 100644 admin-frontend-vue/tests/task-6.test.ts
diff --git a/admin-frontend-vue/src/layout/AdminLayout.vue b/admin-frontend-vue/src/layout/AdminLayout.vue
index 803b5271..734f1f17 100644
--- a/admin-frontend-vue/src/layout/AdminLayout.vue
+++ b/admin-frontend-vue/src/layout/AdminLayout.vue
@@ -5,7 +5,7 @@ import { ElMessage } from 'element-plus'
import { useAdminSessionStore } from '@/stores/admin-session'
import { joinAdminPath } from '@/config/app'
import { pageTitleOf, topbarUserOf } from '@/layout/topbar-model'
-import type { AdminMenuNode } from '@/types/admin'
+import { groupKeysForActive, toSidebarEntries } from '@/layout/menu-mapper'
const route = useRoute()
const router = useRouter()
@@ -13,27 +13,12 @@ const session = useAdminSessionStore()
const collapsed = ref(false)
const activePath = computed(() => route.path)
-const groups = computed(() => session.menuTree.filter((node) => node.children?.length))
+const menuEntries = computed(() => toSidebarEntries(session.menuTree))
+const openedKeys = computed(() => groupKeysForActive(menuEntries.value, route.path))
const pageTitle = computed(() => pageTitleOf(route.meta.title as string | undefined))
const userVm = computed(() => topbarUserOf(session.user))
const logoUrl = joinAdminPath('assets', 'logo.jpg')
-function menuPath(node: AdminMenuNode): string {
- return node.route || '/account/users'
-}
-
-function visibleChildren(node: AdminMenuNode) {
- return (node.children || []).filter((child) => child.route)
-}
-
-function canSee(node: AdminMenuNode) {
- return session.isSuperAdmin.valueOf() || hasMenu(node, String(route.meta.menuKey || '')) || node.route === activePath.value
-}
-
-function hasMenu(node: AdminMenuNode, key: string): boolean {
- return node.key === key || (node.children || []).some((child) => hasMenu(child, key))
-}
-
async function signOut() {
try {
await session.signOut()
@@ -55,23 +40,22 @@ async function signOut() {