From f406c7a538b81922c57121cc628e71f591cd16b3 Mon Sep 17 00:00:00 2001
From: zzs <hi@vio.vin>
Date: Thu, 13 Feb 2025 12:00:25 +0800
Subject: [PATCH] feat: kingdee style menu

---
 src/layouts/default/menu/index.vue         | 35 +++++++++++++++++++++-
 src/layouts/default/sider/KingdeeSider.vue |  2 +-
 src/store/modules/permission.ts            |  5 ++--
 3 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/src/layouts/default/menu/index.vue b/src/layouts/default/menu/index.vue
index 8ebb3a8..f060cd9 100644
--- a/src/layouts/default/menu/index.vue
+++ b/src/layouts/default/menu/index.vue
@@ -2,6 +2,7 @@
 import type { CSSProperties } from 'vue'
 
 import { computed, defineComponent, toRef, unref } from 'vue'
+import { useRoute } from 'vue-router'
 import { useSplitMenu } from './useLayoutMenu'
 import { BasicMenu } from '@/components/Menu'
 import { SimpleMenu } from '@/components/SimpleMenu'
@@ -19,6 +20,7 @@ import { isHttpUrl } from '@/utils/is'
 import { useRootSetting } from '@/hooks/setting/useRootSetting'
 import { useAppInject } from '@/hooks/web/useAppInject'
 import { useDesign } from '@/hooks/web/useDesign'
+import type { Menu } from '@/router/types'
 
 export default defineComponent({
   name: 'LayoutMenu',
@@ -36,6 +38,10 @@ export default defineComponent({
       type: [String] as PropType<Nullable<MenuModeEnum>>,
       default: '',
     },
+    isScoped: {
+      type: Boolean,
+      default: false,
+    },
   },
   setup(props) {
     const go = useGo()
@@ -88,8 +94,35 @@ export default defineComponent({
       ]
     })
 
+    const currentPath = useRoute()
+    /**
+     * 获取路径的第一个部分,例如 "/dashboard/analysis" -> "/dashboard"
+     * @param path 需要解析的路径
+     * @returns 第一个路径部分
+     */
+    function getFirstPathSegment(path: string): string {
+      if (!path || typeof path !== 'string')
+        return '/'
+
+      const segments = path.split('/').filter(Boolean) // 移除空字符串
+      return segments.length > 0 ? `/${segments[0]}` : '/'
+    }
+    /**
+     * 从菜单列表中查找与 `current` 匹配的一级菜单,并返回其 children
+     * @param menus 菜单列表
+     * @param current 当前路径的第一级,如 "/dashboard"
+     * @returns 匹配的 children,未找到则返回 []
+     */
+    function findChildrenByFirstPathSegment(menus: Menu[], current: string): Menu[] {
+      if (!current || !menus || menus.length === 0)
+        return []
+
+      const foundMenu = menus.find(menu => getFirstPathSegment(menu.path) === current)
+      return foundMenu?.children ?? []
+    }
     const getCommonProps = computed(() => {
-      const menus = unref(menusRef)
+      const current = getFirstPathSegment(currentPath.path)
+      const menus = findChildrenByFirstPathSegment(unref(menusRef), current)
       return {
         menus,
         beforeClickFn: beforeMenuClickFn,
diff --git a/src/layouts/default/sider/KingdeeSider.vue b/src/layouts/default/sider/KingdeeSider.vue
index 26cb409..05e53c0 100644
--- a/src/layouts/default/sider/KingdeeSider.vue
+++ b/src/layouts/default/sider/KingdeeSider.vue
@@ -91,7 +91,7 @@ const getTrigger = h(LayoutTrigger)
     <template v-if="getShowTrigger" #trigger>
       <LayoutTrigger />
     </template>
-    <LayoutMenu :theme="getMenuTheme" :menu-mode="getMode" :split-type="getSplitType" />
+    <LayoutMenu :theme="getMenuTheme" :menu-mode="getMode" :split-type="getSplitType" :is-scoped="true" />
     <DragBar ref="dragBarRef" />
   </Sider>
 </template>
diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts
index 2e6f71a..1a36381 100644
--- a/src/store/modules/permission.ts
+++ b/src/store/modules/permission.ts
@@ -7,7 +7,6 @@ import { useAppStoreWithOut } from './app'
 import { store } from '@/store'
 import type { AppRouteRecordRaw, Menu } from '@/router/types'
 import { asyncRoutes } from '@/router/routes'
-import about from '@/router/routes/modules/about'
 import dashboard from '@/router/routes/modules/dashboard'
 import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic'
 import { transformRouteToMenu } from '@/router/helper/menuHelper'
@@ -226,14 +225,14 @@ export const usePermissionStore = defineStore('app-permission', {
           routeList = transformObjToRoute(routeList)
           //  Background routing to menu structure
           //  后台路由到菜单结构
-          const backMenuList = transformRouteToMenu([dashboard, ...routeList, about])
+          const backMenuList = transformRouteToMenu([dashboard, ...routeList])
           this.setBackMenuList(backMenuList)
           // remove meta.ignoreRoute item
           // 删除 meta.ignoreRoute 项
           routeList = filter(routeList, routeRemoveIgnoreFilter)
           routeList = routeList.filter(routeRemoveIgnoreFilter)
           routeList = flatMultiLevelRoutes(routeList)
-          routes = [PAGE_NOT_FOUND_ROUTE, dashboard, ...routeList, about]
+          routes = [PAGE_NOT_FOUND_ROUTE, dashboard, ...routeList]
           break
       }