浏览代码

feat: auto activate subMenu on select root menu (#5147)

* feat: auto activate subMenu on click root menu

* fix: prop name fixed

* chore: test and docs update
Netfan 3 月之前
父节点
当前提交
2efb5b71c3

+ 1 - 0
docs/src/en/guide/essentials/settings.md

@@ -217,6 +217,7 @@ const defaultPreferences: Preferences = {
     globalSearch: true,
   },
   sidebar: {
+    autoActivateChild: false,
     collapsed: false,
     collapsedShowTitle: false,
     enable: true,

+ 1 - 0
docs/src/guide/essentials/settings.md

@@ -240,6 +240,7 @@ const defaultPreferences: Preferences = {
     globalSearch: true,
   },
   sidebar: {
+    autoActivateChild: false,
     collapsed: false,
     collapsedShowTitle: false,
     enable: true,

+ 1 - 0
packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap

@@ -65,6 +65,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
     "globalSearch": true,
   },
   "sidebar": {
+    "autoActivateChild": false,
     "collapsed": false,
     "collapsedShowTitle": false,
     "enable": true,

+ 1 - 0
packages/@core/preferences/src/config.ts

@@ -65,6 +65,7 @@ const defaultPreferences: Preferences = {
     globalSearch: true,
   },
   sidebar: {
+    autoActivateChild: false,
     collapsed: false,
     collapsedShowTitle: false,
     enable: true,

+ 2 - 0
packages/@core/preferences/src/types.ts

@@ -125,6 +125,8 @@ interface NavigationPreferences {
 }
 
 interface SidebarPreferences {
+  /** 点击目录时自动激活子菜单   */
+  autoActivateChild: boolean;
   /** 侧边栏是否折叠 */
   collapsed: boolean;
   /** 侧边栏折叠时,是否显示title */

+ 10 - 0
packages/effects/layouts/src/basic/menu/use-extra-menu.ts

@@ -15,6 +15,9 @@ function useExtraMenu() {
 
   const menus = computed(() => accessStore.accessMenus);
 
+  /** 记录当前顶级菜单下哪个子菜单最后激活 */
+  const defaultSubMap = new Map<string, string>();
+
   const route = useRoute();
   const extraMenus = ref<MenuRecordRaw[]>([]);
   const sidebarExtraVisible = ref<boolean>(false);
@@ -32,6 +35,12 @@ function useExtraMenu() {
     sidebarExtraVisible.value = hasChildren;
     if (!hasChildren) {
       await navigation(menu.path);
+    } else if (preferences.sidebar.autoActivateChild) {
+      await navigation(
+        defaultSubMap.has(menu.path)
+          ? (defaultSubMap.get(menu.path) as string)
+          : menu.path,
+      );
     }
   };
 
@@ -89,6 +98,7 @@ function useExtraMenu() {
         menus.value,
         currentPath,
       );
+      if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath);
       extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
       extraMenus.value = rootMenu?.children ?? [];
     },

+ 23 - 1
packages/effects/layouts/src/widgets/preferences/blocks/layout/sidebar.vue

@@ -1,17 +1,23 @@
 <script setup lang="ts">
+import type { LayoutType } from '@vben/types';
+
 import { $t } from '@vben/locales';
 
 import NumberFieldItem from '../number-field-item.vue';
 import SwitchItem from '../switch-item.vue';
 
-defineProps<{ disabled: boolean }>();
+defineProps<{ currentLayout?: LayoutType; disabled: boolean }>();
 
 const sidebarEnable = defineModel<boolean>('sidebarEnable');
 const sidebarWidth = defineModel<number>('sidebarWidth');
 const sidebarCollapsedShowTitle = defineModel<boolean>(
   'sidebarCollapsedShowTitle',
 );
+const sidebarAutoActivateChild = defineModel<boolean>(
+  'sidebarAutoActivateChild',
+);
 const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
+const sidebarExpandOnHover = defineModel<boolean>('sidebarExpandOnHover');
 </script>
 
 <template>
@@ -21,12 +27,28 @@ const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
   <SwitchItem v-model="sidebarCollapsed" :disabled="!sidebarEnable || disabled">
     {{ $t('preferences.sidebar.collapsed') }}
   </SwitchItem>
+  <SwitchItem
+    v-model="sidebarExpandOnHover"
+    :disabled="!sidebarEnable || disabled || !sidebarCollapsed"
+    :tip="$t('preferences.sidebar.expandOnHoverTip')"
+  >
+    {{ $t('preferences.sidebar.expandOnHover') }}
+  </SwitchItem>
   <SwitchItem
     v-model="sidebarCollapsedShowTitle"
     :disabled="!sidebarEnable || disabled || !sidebarCollapsed"
   >
     {{ $t('preferences.sidebar.collapsedShowTitle') }}
   </SwitchItem>
+  <SwitchItem
+    v-model="sidebarAutoActivateChild"
+    :disabled="
+      !sidebarEnable || currentLayout !== 'sidebar-mixed-nav' || disabled
+    "
+    :tip="$t('preferences.sidebar.autoActivateChildTip')"
+  >
+    {{ $t('preferences.sidebar.autoActivateChild') }}
+  </SwitchItem>
   <NumberFieldItem
     v-model="sidebarWidth"
     :disabled="!sidebarEnable || disabled"

+ 7 - 0
packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue

@@ -87,6 +87,10 @@ const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
 const sidebarCollapsedShowTitle = defineModel<boolean>(
   'sidebarCollapsedShowTitle',
 );
+const sidebarAutoActivateChild = defineModel<boolean>(
+  'sidebarAutoActivateChild',
+);
+const SidebarExpandOnHover = defineModel<boolean>('sidebarExpandOnHover');
 
 const headerEnable = defineModel<boolean>('headerEnable');
 const headerMode = defineModel<LayoutHeaderModeType>('headerMode');
@@ -299,10 +303,13 @@ async function handleReset() {
 
             <Block :title="$t('preferences.sidebar.title')">
               <Sidebar
+                v-model:sidebar-auto-activate-child="sidebarAutoActivateChild"
                 v-model:sidebar-collapsed="sidebarCollapsed"
                 v-model:sidebar-collapsed-show-title="sidebarCollapsedShowTitle"
                 v-model:sidebar-enable="sidebarEnable"
+                v-model:sidebar-expand-on-hover="SidebarExpandOnHover"
                 v-model:sidebar-width="sidebarWidth"
+                :current-layout="appLayout"
                 :disabled="!isSideMode"
               />
             </Block>

+ 5 - 1
packages/locales/src/langs/en-US/preferences.json

@@ -45,7 +45,11 @@
     "width": "Width",
     "visible": "Show Sidebar",
     "collapsed": "Collpase Menu",
-    "collapsedShowTitle": "Show Menu Title"
+    "collapsedShowTitle": "Show Menu Title",
+    "autoActivateChild": "Auto Activate SubMenu",
+    "autoActivateChildTip": "`Enabled` to automatically activate the submenu while click menu.",
+    "expandOnHover": "Expand On Hover",
+    "expandOnHoverTip": "When the mouse hovers over menu, \n `Enabled` to expand children menus \n `Disabled` to expand whole sidebar."
   },
   "tabbar": {
     "title": "Tabbar",

+ 5 - 1
packages/locales/src/langs/zh-CN/preferences.json

@@ -45,7 +45,11 @@
     "width": "宽度",
     "visible": "显示侧边栏",
     "collapsed": "折叠菜单",
-    "collapsedShowTitle": "折叠显示菜单名"
+    "collapsedShowTitle": "折叠显示菜单名",
+    "autoActivateChild": "自动激活子菜单",
+    "autoActivateChildTip": "点击顶层菜单时,自动激活第一个子菜单或者上一次激活的子菜单",
+    "expandOnHover": "鼠标悬停展开",
+    "expandOnHoverTip": "鼠标在折叠区域悬浮时,`启用`则展开当前子菜单,`禁用`则展开整个侧边栏"
   },
   "tabbar": {
     "title": "标签栏",