feat: The accordion mode of the menu is configurable
							parent
							
								
									a0423eb9ba
								
							
						
					
					
						commit
						c28adc9a94
					
				|  | @ -77,6 +77,8 @@ interface Preference { | ||||||
|   logo: string; |   logo: string; | ||||||
|   /** logo是否可见 */ |   /** logo是否可见 */ | ||||||
|   logoVisible: boolean; |   logoVisible: boolean; | ||||||
|  |   /** 导航菜单手风琴模式 */ | ||||||
|  |   navigationAccordion: boolean; | ||||||
|   /** 导航菜单是否切割,只在 layout=mixed-nav 生效 */ |   /** 导航菜单是否切割,只在 layout=mixed-nav 生效 */ | ||||||
|   navigationSplit: boolean; |   navigationSplit: boolean; | ||||||
|   /** 导航菜单风格 */ |   /** 导航菜单风格 */ | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ defineProps<{ disabled?: boolean; disabledNavigationSplit?: boolean }>(); | ||||||
| 
 | 
 | ||||||
| const navigationStyle = defineModel<string>('navigationStyle'); | const navigationStyle = defineModel<string>('navigationStyle'); | ||||||
| const navigationSplit = defineModel<boolean>('navigationSplit'); | const navigationSplit = defineModel<boolean>('navigationSplit'); | ||||||
|  | const navigationAccordion = defineModel<boolean>('navigationAccordion'); | ||||||
| 
 | 
 | ||||||
| const stylesItems: SelectListItem[] = [ | const stylesItems: SelectListItem[] = [ | ||||||
|   { label: $t('preference.rounded'), value: 'rounded' }, |   { label: $t('preference.rounded'), value: 'rounded' }, | ||||||
|  | @ -29,10 +30,16 @@ const stylesItems: SelectListItem[] = [ | ||||||
|   > |   > | ||||||
|     {{ $t('preference.navigation-style') }} |     {{ $t('preference.navigation-style') }} | ||||||
|   </ToggleItem> |   </ToggleItem> | ||||||
|   <SwitchItem v-model="navigationSplit" :disabled="disabledNavigationSplit"> |   <SwitchItem | ||||||
|  |     v-model="navigationSplit" | ||||||
|  |     :disabled="disabledNavigationSplit || disabled" | ||||||
|  |   > | ||||||
|     {{ $t('preference.navigation-split') }} |     {{ $t('preference.navigation-split') }} | ||||||
|     <template #tip> |     <template #tip> | ||||||
|       {{ $t('preference.navigation-split-tip') }} |       {{ $t('preference.navigation-split-tip') }} | ||||||
|     </template> |     </template> | ||||||
|   </SwitchItem> |   </SwitchItem> | ||||||
|  |   <SwitchItem v-model="navigationAccordion" :disabled="disabled"> | ||||||
|  |     {{ $t('preference.navigation-accordion') }} | ||||||
|  |   </SwitchItem> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -52,11 +52,15 @@ function updateLocale(value: string) { | ||||||
|     :page-progress="preference.pageProgress" |     :page-progress="preference.pageProgress" | ||||||
|     :tabs-icon="preference.tabsIcon" |     :tabs-icon="preference.tabsIcon" | ||||||
|     :locale="preference.locale" |     :locale="preference.locale" | ||||||
|  |     :navigation-accordion="preference.navigationAccordion" | ||||||
|     :navigation-style="preference.navigationStyle" |     :navigation-style="preference.navigationStyle" | ||||||
|     :navigation-split="preference.navigationSplit" |     :navigation-split="preference.navigationSplit" | ||||||
|     :side-collapse-show-title="preference.sideCollapseShowTitle" |     :side-collapse-show-title="preference.sideCollapseShowTitle" | ||||||
|     :page-transition-enable="preference.pageTransitionEnable" |     :page-transition-enable="preference.pageTransitionEnable" | ||||||
|     @update:navigation-style="(value) => handleUpdate('navigationStyle', value)" |     @update:navigation-style="(value) => handleUpdate('navigationStyle', value)" | ||||||
|  |     @update:navigation-accordion=" | ||||||
|  |       (value) => handleUpdate('navigationAccordion', value) | ||||||
|  |     " | ||||||
|     @update:navigation-split="(value) => handleUpdate('navigationSplit', value)" |     @update:navigation-split="(value) => handleUpdate('navigationSplit', value)" | ||||||
|     @update:dynamic-title="(value) => handleUpdate('dynamicTitle', value)" |     @update:dynamic-title="(value) => handleUpdate('dynamicTitle', value)" | ||||||
|     @update:tabs-icon="(value) => handleUpdate('tabsIcon', value)" |     @update:tabs-icon="(value) => handleUpdate('tabsIcon', value)" | ||||||
|  |  | ||||||
|  | @ -54,6 +54,7 @@ const colorGrayMode = defineModel<boolean>('colorGrayMode'); | ||||||
| const colorPrimary = defineModel<string>('colorPrimary'); | const colorPrimary = defineModel<string>('colorPrimary'); | ||||||
| const navigationStyle = defineModel<string>('navigationStyle'); | const navigationStyle = defineModel<string>('navigationStyle'); | ||||||
| const navigationSplit = defineModel<boolean>('navigationSplit'); | const navigationSplit = defineModel<boolean>('navigationSplit'); | ||||||
|  | const navigationAccordion = defineModel<boolean>('navigationAccordion'); | ||||||
| const pageProgress = defineModel<boolean>('pageProgress'); | const pageProgress = defineModel<boolean>('pageProgress'); | ||||||
| const pageTransition = defineModel<string>('pageTransition'); | const pageTransition = defineModel<string>('pageTransition'); | ||||||
| const pageTransitionEnable = defineModel<boolean>('pageTransitionEnable'); | const pageTransitionEnable = defineModel<boolean>('pageTransitionEnable'); | ||||||
|  | @ -197,6 +198,7 @@ function handleReset() { | ||||||
|               <Navigation |               <Navigation | ||||||
|                 v-model:navigation-style="navigationStyle" |                 v-model:navigation-style="navigationStyle" | ||||||
|                 v-model:navigation-split="navigationSplit" |                 v-model:navigation-split="navigationSplit" | ||||||
|  |                 v-model:navigation-accordion="navigationAccordion" | ||||||
|                 :disabled="isFullContent" |                 :disabled="isFullContent" | ||||||
|                 :disabled-navigation-split="!isMixedNav" |                 :disabled-navigation-split="!isMixedNav" | ||||||
|               /> |               /> | ||||||
|  |  | ||||||
|  | @ -50,6 +50,7 @@ function getTransitionName(route: RouteLocationNormalizedLoaded) { | ||||||
|         <component |         <component | ||||||
|           :is="Component" |           :is="Component" | ||||||
|           v-if="renderRouteView" |           v-if="renderRouteView" | ||||||
|  |           v-show="!route.meta.iframeSrc" | ||||||
|           :key="route.fullPath" |           :key="route.fullPath" | ||||||
|           class="h-[1000px]" |           class="h-[1000px]" | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|  | @ -183,6 +183,7 @@ function wrapperMenus(menus: MenuRecordRaw[]) { | ||||||
|     <template #menu> |     <template #menu> | ||||||
|       <LayoutMenu |       <LayoutMenu | ||||||
|         mode="vertical" |         mode="vertical" | ||||||
|  |         :accordion="preference.navigationAccordion" | ||||||
|         :rounded="isMenuRounded" |         :rounded="isMenuRounded" | ||||||
|         :collapse-show-title="preference.sideCollapseShowTitle" |         :collapse-show-title="preference.sideCollapseShowTitle" | ||||||
|         :collapse="preference.sideCollapse" |         :collapse="preference.sideCollapse" | ||||||
|  | @ -206,6 +207,7 @@ function wrapperMenus(menus: MenuRecordRaw[]) { | ||||||
|     <!-- 侧边额外区域 --> |     <!-- 侧边额外区域 --> | ||||||
|     <template #side-extra> |     <template #side-extra> | ||||||
|       <LayoutExtraMenu |       <LayoutExtraMenu | ||||||
|  |         :accordion="preference.navigationAccordion" | ||||||
|         :rounded="isMenuRounded" |         :rounded="isMenuRounded" | ||||||
|         :menus="wrapperMenus(extraMenus)" |         :menus="wrapperMenus(extraMenus)" | ||||||
|         :collapse="preference.sideExtraCollapse" |         :collapse="preference.sideExtraCollapse" | ||||||
|  |  | ||||||
|  | @ -12,7 +12,10 @@ interface Props extends MenuProps { | ||||||
|   menus: MenuRecordRaw[]; |   menus: MenuRecordRaw[]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| defineProps<Props>(); | withDefaults(defineProps<Props>(), { | ||||||
|  |   accordion: true, | ||||||
|  |   menus: () => [], | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| const route = useRoute(); | const route = useRoute(); | ||||||
| const { navigation } = useNavigation(); | const { navigation } = useNavigation(); | ||||||
|  | @ -25,6 +28,7 @@ async function handleSelect(key: string) { | ||||||
| <template> | <template> | ||||||
|   <Menu |   <Menu | ||||||
|     :rounded="rounded" |     :rounded="rounded" | ||||||
|  |     :accordion="accordion" | ||||||
|     :collapse="collapse" |     :collapse="collapse" | ||||||
|     :default-active="route.path" |     :default-active="route.path" | ||||||
|     :menus="menus" |     :menus="menus" | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ interface Props extends MenuProps { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const props = withDefaults(defineProps<Props>(), { | const props = withDefaults(defineProps<Props>(), { | ||||||
|  |   accordion: true, | ||||||
|   menus: () => [], |   menus: () => [], | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | @ -25,6 +26,7 @@ function handleMenuSelect(key: string) { | ||||||
|     :rounded="rounded" |     :rounded="rounded" | ||||||
|     :collapse-show-title="collapseShowTitle" |     :collapse-show-title="collapseShowTitle" | ||||||
|     :collapse="collapse" |     :collapse="collapse" | ||||||
|  |     :accordion="accordion" | ||||||
|     :default-active="defaultActive" |     :default-active="defaultActive" | ||||||
|     :menus="menus" |     :menus="menus" | ||||||
|     :theme="theme" |     :theme="theme" | ||||||
|  |  | ||||||
|  | @ -78,6 +78,7 @@ preference: | ||||||
|   navigation-menu: Navigation Menu |   navigation-menu: Navigation Menu | ||||||
|   navigation-style: Navigation menu style |   navigation-style: Navigation menu style | ||||||
|   navigation-split: Navigation Menu Separation |   navigation-split: Navigation Menu Separation | ||||||
|  |   navigation-accordion: Sidebar Navigation Menu Accordion mode | ||||||
|   navigation-split-tip: When enabled, the sidebar shows the top bar's submenu |   navigation-split-tip: When enabled, the sidebar shows the top bar's submenu | ||||||
|   interface-control: Interface Layout Control |   interface-control: Interface Layout Control | ||||||
|   breadcrumb: Breadcrumb |   breadcrumb: Breadcrumb | ||||||
|  |  | ||||||
|  | @ -73,6 +73,7 @@ preference: | ||||||
|   animation: 动画 |   animation: 动画 | ||||||
|   navigation-menu: 导航菜单 |   navigation-menu: 导航菜单 | ||||||
|   navigation-style: 导航菜单风格 |   navigation-style: 导航菜单风格 | ||||||
|  |   navigation-accordion: 侧边导航菜单手风琴模式 | ||||||
|   navigation-split: 导航菜单分离 |   navigation-split: 导航菜单分离 | ||||||
|   navigation-split-tip: 开启时,侧边栏显示顶栏对应菜单的子菜单 |   navigation-split-tip: 开启时,侧边栏显示顶栏对应菜单的子菜单 | ||||||
|   interface-control: 界面布局控制 |   interface-control: 界面布局控制 | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ const defaultPreference: Preference = { | ||||||
|   locale: 'zh-CN', |   locale: 'zh-CN', | ||||||
|   logo: 'https://cdn.jsdelivr.net/gh/vbenjs/vben-cdn-static@0.1.2/vben-admin/admin-logo.png', |   logo: 'https://cdn.jsdelivr.net/gh/vbenjs/vben-cdn-static@0.1.2/vben-admin/admin-logo.png', | ||||||
|   logoVisible: true, |   logoVisible: true, | ||||||
|  |   navigationAccordion: true, | ||||||
|   navigationSplit: true, |   navigationSplit: true, | ||||||
|   navigationStyle: 'rounded', |   navigationStyle: 'rounded', | ||||||
|   pageProgress: true, |   pageProgress: true, | ||||||
|  |  | ||||||
|  | @ -269,7 +269,7 @@ const useTabsStore = defineStore('tabs', { | ||||||
|       await this.closeTab(this.tabs[index], router); |       await this.closeTab(this.tabs[index], router); | ||||||
|     }, |     }, | ||||||
|     getTabPath(tab: RouteRecordNormalized | TabItem) { |     getTabPath(tab: RouteRecordNormalized | TabItem) { | ||||||
|       return (tab as TabItem).fullPath || tab.path; |       return decodeURIComponent((tab as TabItem).fullPath || tab.path); | ||||||
|     }, |     }, | ||||||
|     /** |     /** | ||||||
|      * @zh_CN 固定标签页 |      * @zh_CN 固定标签页 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 vben
						vben