feat: header mixed layout (#5263)
* feat: new layout header-mixed * fix: header-mixed layout update * feat: layout preference update * fix: extra menus follow layout setting
This commit is contained in:
parent
07c4ad05f4
commit
ff8d5ca351
1
packages/@core/base/typings/src/app.d.ts
vendored
1
packages/@core/base/typings/src/app.d.ts
vendored
@ -1,5 +1,6 @@
|
|||||||
type LayoutType =
|
type LayoutType =
|
||||||
| 'full-content'
|
| 'full-content'
|
||||||
|
| 'header-mixed-nav'
|
||||||
| 'header-nav'
|
| 'header-nav'
|
||||||
| 'mixed-nav'
|
| 'mixed-nav'
|
||||||
| 'sidebar-mixed-nav'
|
| 'sidebar-mixed-nav'
|
||||||
|
@ -82,6 +82,10 @@ function usePreferences() {
|
|||||||
() => appPreferences.value.layout === 'header-nav',
|
() => appPreferences.value.layout === 'header-nav',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isHeaderMixedNav = computed(
|
||||||
|
() => appPreferences.value.layout === 'header-mixed-nav',
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 是否为混合导航模式
|
* @zh_CN 是否为混合导航模式
|
||||||
*/
|
*/
|
||||||
@ -93,7 +97,12 @@ function usePreferences() {
|
|||||||
* @zh_CN 是否包含侧边导航模式
|
* @zh_CN 是否包含侧边导航模式
|
||||||
*/
|
*/
|
||||||
const isSideMode = computed(() => {
|
const isSideMode = computed(() => {
|
||||||
return isMixedNav.value || isSideMixedNav.value || isSideNav.value;
|
return (
|
||||||
|
isMixedNav.value ||
|
||||||
|
isSideMixedNav.value ||
|
||||||
|
isSideNav.value ||
|
||||||
|
isHeaderMixedNav.value
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const sidebarCollapsed = computed(() => {
|
const sidebarCollapsed = computed(() => {
|
||||||
@ -214,6 +223,7 @@ function usePreferences() {
|
|||||||
globalSearchShortcutKey,
|
globalSearchShortcutKey,
|
||||||
isDark,
|
isDark,
|
||||||
isFullContent,
|
isFullContent,
|
||||||
|
isHeaderMixedNav,
|
||||||
isHeaderNav,
|
isHeaderNav,
|
||||||
isMixedNav,
|
isMixedNav,
|
||||||
isMobile,
|
isMobile,
|
||||||
|
@ -31,9 +31,17 @@ export function useLayout(props: VbenLayoutProps) {
|
|||||||
*/
|
*/
|
||||||
const isMixedNav = computed(() => currentLayout.value === 'mixed-nav');
|
const isMixedNav = computed(() => currentLayout.value === 'mixed-nav');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为头部混合模式
|
||||||
|
*/
|
||||||
|
const isHeaderMixedNav = computed(
|
||||||
|
() => currentLayout.value === 'header-mixed-nav',
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentLayout,
|
currentLayout,
|
||||||
isFullContent,
|
isFullContent,
|
||||||
|
isHeaderMixedNav,
|
||||||
isHeaderNav,
|
isHeaderNav,
|
||||||
isMixedNav,
|
isMixedNav,
|
||||||
isSidebarMixedNav,
|
isSidebarMixedNav,
|
||||||
|
@ -87,6 +87,7 @@ const { y: mouseY } = useMouse({ target: contentRef, type: 'client' });
|
|||||||
const {
|
const {
|
||||||
currentLayout,
|
currentLayout,
|
||||||
isFullContent,
|
isFullContent,
|
||||||
|
isHeaderMixedNav,
|
||||||
isHeaderNav,
|
isHeaderNav,
|
||||||
isMixedNav,
|
isMixedNav,
|
||||||
isSidebarMixedNav,
|
isSidebarMixedNav,
|
||||||
@ -112,7 +113,9 @@ const getSideCollapseWidth = computed(() => {
|
|||||||
const { sidebarCollapseShowTitle, sidebarMixedWidth, sideCollapseWidth } =
|
const { sidebarCollapseShowTitle, sidebarMixedWidth, sideCollapseWidth } =
|
||||||
props;
|
props;
|
||||||
|
|
||||||
return sidebarCollapseShowTitle || isSidebarMixedNav.value
|
return sidebarCollapseShowTitle ||
|
||||||
|
isSidebarMixedNav.value ||
|
||||||
|
isHeaderMixedNav.value
|
||||||
? sidebarMixedWidth
|
? sidebarMixedWidth
|
||||||
: sideCollapseWidth;
|
: sideCollapseWidth;
|
||||||
});
|
});
|
||||||
@ -145,12 +148,15 @@ const getSidebarWidth = computed(() => {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!sidebarEnableState.value ||
|
!sidebarEnableState.value ||
|
||||||
(sidebarHidden && !isSidebarMixedNav.value && !isMixedNav.value)
|
(sidebarHidden &&
|
||||||
|
!isSidebarMixedNav.value &&
|
||||||
|
!isMixedNav.value &&
|
||||||
|
!isHeaderMixedNav.value)
|
||||||
) {
|
) {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSidebarMixedNav.value && !isMobile) {
|
if ((isHeaderMixedNav.value || isSidebarMixedNav.value) && !isMobile) {
|
||||||
width = sidebarMixedWidth;
|
width = sidebarMixedWidth;
|
||||||
} else if (sidebarCollapse.value) {
|
} else if (sidebarCollapse.value) {
|
||||||
width = isMobile ? 0 : getSideCollapseWidth.value;
|
width = isMobile ? 0 : getSideCollapseWidth.value;
|
||||||
@ -176,7 +182,8 @@ const isSideMode = computed(
|
|||||||
() =>
|
() =>
|
||||||
currentLayout.value === 'mixed-nav' ||
|
currentLayout.value === 'mixed-nav' ||
|
||||||
currentLayout.value === 'sidebar-mixed-nav' ||
|
currentLayout.value === 'sidebar-mixed-nav' ||
|
||||||
currentLayout.value === 'sidebar-nav',
|
currentLayout.value === 'sidebar-nav' ||
|
||||||
|
currentLayout.value === 'header-mixed-nav',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -213,7 +220,7 @@ const mainStyle = computed(() => {
|
|||||||
) {
|
) {
|
||||||
// fixed模式下生效
|
// fixed模式下生效
|
||||||
const isSideNavEffective =
|
const isSideNavEffective =
|
||||||
isSidebarMixedNav.value &&
|
(isSidebarMixedNav.value || isHeaderMixedNav.value) &&
|
||||||
sidebarExpandOnHover.value &&
|
sidebarExpandOnHover.value &&
|
||||||
sidebarExtraVisible.value;
|
sidebarExtraVisible.value;
|
||||||
|
|
||||||
@ -476,7 +483,7 @@ const idMainContent = ELEMENT_ID_MAIN_CONTENT;
|
|||||||
:extra-width="sidebarExtraWidth"
|
:extra-width="sidebarExtraWidth"
|
||||||
:fixed-extra="sidebarExpandOnHover"
|
:fixed-extra="sidebarExpandOnHover"
|
||||||
:header-height="isMixedNav ? 0 : headerHeight"
|
:header-height="isMixedNav ? 0 : headerHeight"
|
||||||
:is-sidebar-mixed="isSidebarMixedNav"
|
:is-sidebar-mixed="isSidebarMixedNav || isHeaderMixedNav"
|
||||||
:margin-top="sidebarMarginTop"
|
:margin-top="sidebarMarginTop"
|
||||||
:mixed-width="sidebarMixedWidth"
|
:mixed-width="sidebarMixedWidth"
|
||||||
:show="showSidebar"
|
:show="showSidebar"
|
||||||
@ -489,7 +496,7 @@ const idMainContent = ELEMENT_ID_MAIN_CONTENT;
|
|||||||
<slot name="logo"></slot>
|
<slot name="logo"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="isSidebarMixedNav">
|
<template v-if="isSidebarMixedNav || isHeaderMixedNav">
|
||||||
<slot name="mixed-menu"></slot>
|
<slot name="mixed-menu"></slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MenuRecordRaw } from '@vben/types';
|
import type { MenuRecordRaw } from '@vben/types';
|
||||||
|
|
||||||
import { computed, useSlots, watch } from 'vue';
|
import { computed, type SetupContext, useSlots, watch } from 'vue';
|
||||||
|
|
||||||
import { useRefresh } from '@vben/hooks';
|
import { useRefresh } from '@vben/hooks';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
@ -39,6 +39,7 @@ const {
|
|||||||
isMixedNav,
|
isMixedNav,
|
||||||
isMobile,
|
isMobile,
|
||||||
isSideMixedNav,
|
isSideMixedNav,
|
||||||
|
isHeaderMixedNav,
|
||||||
layout,
|
layout,
|
||||||
preferencesButtonPosition,
|
preferencesButtonPosition,
|
||||||
sidebarCollapsed,
|
sidebarCollapsed,
|
||||||
@ -83,11 +84,16 @@ const logoCollapsed = computed(() => {
|
|||||||
if (isHeaderNav.value || isMixedNav.value) {
|
if (isHeaderNav.value || isMixedNav.value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return sidebarCollapsed.value || isSideMixedNav.value;
|
return (
|
||||||
|
sidebarCollapsed.value || isSideMixedNav.value || isHeaderMixedNav.value
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const showHeaderNav = computed(() => {
|
const showHeaderNav = computed(() => {
|
||||||
return !isMobile.value && (isHeaderNav.value || isMixedNav.value);
|
return (
|
||||||
|
!isMobile.value &&
|
||||||
|
(isHeaderNav.value || isMixedNav.value || isHeaderMixedNav.value)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 侧边多列菜单
|
// 侧边多列菜单
|
||||||
@ -108,6 +114,8 @@ const {
|
|||||||
headerMenus,
|
headerMenus,
|
||||||
sidebarActive,
|
sidebarActive,
|
||||||
sidebarMenus,
|
sidebarMenus,
|
||||||
|
mixedSidebarActive,
|
||||||
|
mixHeaderMenus,
|
||||||
sidebarVisible,
|
sidebarVisible,
|
||||||
} = useMixedMenu();
|
} = useMixedMenu();
|
||||||
|
|
||||||
@ -154,7 +162,7 @@ watch(
|
|||||||
// 语言更新后,刷新页面
|
// 语言更新后,刷新页面
|
||||||
watch(() => preferences.app.locale, refresh, { flush: 'post' });
|
watch(() => preferences.app.locale, refresh, { flush: 'post' });
|
||||||
|
|
||||||
const slots = useSlots();
|
const slots: SetupContext['slots'] = useSlots();
|
||||||
const headerSlots = computed(() => {
|
const headerSlots = computed(() => {
|
||||||
return Object.keys(slots).filter((key) => key.startsWith('header-'));
|
return Object.keys(slots).filter((key) => key.startsWith('header-'));
|
||||||
});
|
});
|
||||||
@ -267,8 +275,8 @@ const headerSlots = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
<template #mixed-menu>
|
<template #mixed-menu>
|
||||||
<LayoutMixedMenu
|
<LayoutMixedMenu
|
||||||
:active-path="extraActiveMenu"
|
:active-path="isHeaderMixedNav ? mixedSidebarActive : extraActiveMenu"
|
||||||
:menus="wrapperMenus(headerMenus, false)"
|
:menus="wrapperMenus(mixHeaderMenus, false)"
|
||||||
:rounded="isMenuRounded"
|
:rounded="isMenuRounded"
|
||||||
:theme="sidebarTheme"
|
:theme="sidebarTheme"
|
||||||
@default-select="handleDefaultSelect"
|
@default-select="handleDefaultSelect"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { MenuRecordRaw } from '@vben/types';
|
import type { MenuRecordRaw } from '@vben/types';
|
||||||
|
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, nextTick, ref, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
@ -17,7 +17,7 @@ function useExtraMenu() {
|
|||||||
|
|
||||||
/** 记录当前顶级菜单下哪个子菜单最后激活 */
|
/** 记录当前顶级菜单下哪个子菜单最后激活 */
|
||||||
const defaultSubMap = new Map<string, string>();
|
const defaultSubMap = new Map<string, string>();
|
||||||
|
const extraRootMenus = ref<MenuRecordRaw[]>([]);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const extraMenus = ref<MenuRecordRaw[]>([]);
|
const extraMenus = ref<MenuRecordRaw[]>([]);
|
||||||
const sidebarExtraVisible = ref<boolean>(false);
|
const sidebarExtraVisible = ref<boolean>(false);
|
||||||
@ -49,11 +49,13 @@ function useExtraMenu() {
|
|||||||
* @param menu
|
* @param menu
|
||||||
* @param rootMenu
|
* @param rootMenu
|
||||||
*/
|
*/
|
||||||
const handleDefaultSelect = (
|
const handleDefaultSelect = async (
|
||||||
menu: MenuRecordRaw,
|
menu: MenuRecordRaw,
|
||||||
rootMenu?: MenuRecordRaw,
|
rootMenu?: MenuRecordRaw,
|
||||||
) => {
|
) => {
|
||||||
extraMenus.value = rootMenu?.children ?? [];
|
await nextTick();
|
||||||
|
|
||||||
|
extraMenus.value = rootMenu?.children ?? extraRootMenus.value ?? [];
|
||||||
extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
|
extraActiveMenu.value = menu.parents?.[0] ?? menu.path;
|
||||||
|
|
||||||
if (preferences.sidebar.expandOnHover) {
|
if (preferences.sidebar.expandOnHover) {
|
||||||
@ -65,17 +67,16 @@ function useExtraMenu() {
|
|||||||
* 侧边菜单鼠标移出事件
|
* 侧边菜单鼠标移出事件
|
||||||
*/
|
*/
|
||||||
const handleSideMouseLeave = () => {
|
const handleSideMouseLeave = () => {
|
||||||
|
// const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
|
||||||
|
// menus.value,
|
||||||
|
// route.path,
|
||||||
|
// );
|
||||||
|
calcExtraMenus(route.path);
|
||||||
if (preferences.sidebar.expandOnHover) {
|
if (preferences.sidebar.expandOnHover) {
|
||||||
|
sidebarExtraVisible.value = extraMenus.value.length > 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sidebarExtraVisible.value = false;
|
sidebarExtraVisible.value = false;
|
||||||
|
|
||||||
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
|
|
||||||
menus.value,
|
|
||||||
route.path,
|
|
||||||
);
|
|
||||||
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
|
|
||||||
extraMenus.value = rootMenu?.children ?? [];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuMouseEnter = (menu: MenuRecordRaw) => {
|
const handleMenuMouseEnter = (menu: MenuRecordRaw) => {
|
||||||
@ -87,20 +88,36 @@ function useExtraMenu() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
function calcExtraMenus(path: string) {
|
||||||
() => route.path,
|
const currentPath = route.meta?.activePath || path;
|
||||||
(path) => {
|
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
|
||||||
const currentPath = route.meta?.activePath || path;
|
menus.value,
|
||||||
// if (preferences.sidebar.expandOnHover) {
|
currentPath,
|
||||||
// return;
|
);
|
||||||
// }
|
if (preferences.app.layout === 'header-mixed-nav') {
|
||||||
const { findMenu, rootMenu, rootMenuPath } = findRootMenuByPath(
|
const subExtra = findRootMenuByPath(
|
||||||
menus.value,
|
rootMenu?.children ?? [],
|
||||||
currentPath,
|
currentPath,
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
|
extraRootMenus.value = subExtra.rootMenu?.children ?? [];
|
||||||
|
extraActiveMenu.value = subExtra.rootMenuPath ?? '';
|
||||||
|
extraMenus.value = subExtra.rootMenu?.children ?? [];
|
||||||
|
} else {
|
||||||
|
extraRootMenus.value = rootMenu?.children ?? [];
|
||||||
if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath);
|
if (rootMenuPath) defaultSubMap.set(rootMenuPath, currentPath);
|
||||||
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
|
extraActiveMenu.value = rootMenuPath ?? findMenu?.path ?? '';
|
||||||
extraMenus.value = rootMenu?.children ?? [];
|
extraMenus.value = rootMenu?.children ?? [];
|
||||||
|
}
|
||||||
|
if (preferences.sidebar.expandOnHover) {
|
||||||
|
sidebarExtraVisible.value = extraMenus.value.length > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [route.path, preferences.app.layout],
|
||||||
|
([path]) => {
|
||||||
|
calcExtraMenus(path || '');
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
@ -15,12 +15,16 @@ function useMixedMenu() {
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const splitSideMenus = ref<MenuRecordRaw[]>([]);
|
const splitSideMenus = ref<MenuRecordRaw[]>([]);
|
||||||
const rootMenuPath = ref<string>('');
|
const rootMenuPath = ref<string>('');
|
||||||
|
const mixedRootMenuPath = ref<string>('');
|
||||||
|
const mixExtraMenus = ref<MenuRecordRaw[]>([]);
|
||||||
/** 记录当前顶级菜单下哪个子菜单最后激活 */
|
/** 记录当前顶级菜单下哪个子菜单最后激活 */
|
||||||
const defaultSubMap = new Map<string, string>();
|
const defaultSubMap = new Map<string, string>();
|
||||||
const { isMixedNav } = usePreferences();
|
const { isMixedNav, isHeaderMixedNav } = usePreferences();
|
||||||
|
|
||||||
const needSplit = computed(
|
const needSplit = computed(
|
||||||
() => preferences.navigation.split && isMixedNav.value,
|
() =>
|
||||||
|
(preferences.navigation.split && isMixedNav.value) ||
|
||||||
|
isHeaderMixedNav.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
const sidebarVisible = computed(() => {
|
const sidebarVisible = computed(() => {
|
||||||
@ -54,6 +58,10 @@ function useMixedMenu() {
|
|||||||
return needSplit.value ? splitSideMenus.value : menus.value;
|
return needSplit.value ? splitSideMenus.value : menus.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mixHeaderMenus = computed(() => {
|
||||||
|
return isHeaderMixedNav.value ? sidebarMenus.value : headerMenus.value;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 侧边菜单激活路径
|
* 侧边菜单激活路径
|
||||||
*/
|
*/
|
||||||
@ -61,6 +69,10 @@ function useMixedMenu() {
|
|||||||
return (route?.meta?.activePath as string) ?? route.path;
|
return (route?.meta?.activePath as string) ?? route.path;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mixedSidebarActive = computed(() => {
|
||||||
|
return mixedRootMenuPath.value || sidebarActive.value;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 头部菜单激活路径
|
* 头部菜单激活路径
|
||||||
*/
|
*/
|
||||||
@ -118,6 +130,9 @@ function useMixedMenu() {
|
|||||||
if (!rootMenu) {
|
if (!rootMenu) {
|
||||||
rootMenu = menus.value.find((item) => item.path === path);
|
rootMenu = menus.value.find((item) => item.path === path);
|
||||||
}
|
}
|
||||||
|
const result = findRootMenuByPath(rootMenu?.children || [], path, 1);
|
||||||
|
mixedRootMenuPath.value = result.rootMenuPath ?? '';
|
||||||
|
mixExtraMenus.value = result.rootMenu?.children ?? [];
|
||||||
rootMenuPath.value = rootMenu?.path ?? '';
|
rootMenuPath.value = rootMenu?.path ?? '';
|
||||||
splitSideMenus.value = rootMenu?.children ?? [];
|
splitSideMenus.value = rootMenu?.children ?? [];
|
||||||
}
|
}
|
||||||
@ -145,6 +160,9 @@ function useMixedMenu() {
|
|||||||
headerMenus,
|
headerMenus,
|
||||||
sidebarActive,
|
sidebarActive,
|
||||||
sidebarMenus,
|
sidebarMenus,
|
||||||
|
mixedSidebarActive,
|
||||||
|
mixHeaderMenus,
|
||||||
|
mixExtraMenus,
|
||||||
sidebarVisible,
|
sidebarVisible,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import { VbenTooltip } from '@vben-core/shadcn-ui';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
FullContent,
|
FullContent,
|
||||||
|
HeaderMixedNav,
|
||||||
HeaderNav,
|
HeaderNav,
|
||||||
MixedNav,
|
MixedNav,
|
||||||
SidebarMixedNav,
|
SidebarMixedNav,
|
||||||
@ -33,6 +34,7 @@ const components: Record<LayoutType, Component> = {
|
|||||||
'mixed-nav': MixedNav,
|
'mixed-nav': MixedNav,
|
||||||
'sidebar-mixed-nav': SidebarMixedNav,
|
'sidebar-mixed-nav': SidebarMixedNav,
|
||||||
'sidebar-nav': SidebarNav,
|
'sidebar-nav': SidebarNav,
|
||||||
|
'header-mixed-nav': HeaderMixedNav,
|
||||||
};
|
};
|
||||||
|
|
||||||
const PRESET = computed((): PresetItem[] => [
|
const PRESET = computed((): PresetItem[] => [
|
||||||
@ -56,6 +58,11 @@ const PRESET = computed((): PresetItem[] => [
|
|||||||
tip: $t('preferences.mixedMenuTip'),
|
tip: $t('preferences.mixedMenuTip'),
|
||||||
type: 'mixed-nav',
|
type: 'mixed-nav',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: $t('preferences.headerTwoColumn'),
|
||||||
|
tip: $t('preferences.headerTwoColumnTip'),
|
||||||
|
type: 'header-mixed-nav',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: $t('preferences.fullContent'),
|
name: $t('preferences.fullContent'),
|
||||||
tip: $t('preferences.fullContentTip'),
|
tip: $t('preferences.fullContentTip'),
|
||||||
|
@ -44,7 +44,7 @@ const sidebarExpandOnHover = defineModel<boolean>('sidebarExpandOnHover');
|
|||||||
v-model="sidebarAutoActivateChild"
|
v-model="sidebarAutoActivateChild"
|
||||||
:disabled="
|
:disabled="
|
||||||
!sidebarEnable ||
|
!sidebarEnable ||
|
||||||
!['sidebar-mixed-nav', 'mixed-nav', 'sidebar-nav'].includes(
|
!['sidebar-mixed-nav', 'mixed-nav', 'header-mixed-nav'].includes(
|
||||||
currentLayout as string,
|
currentLayout as string,
|
||||||
) ||
|
) ||
|
||||||
disabled
|
disabled
|
||||||
|
@ -0,0 +1,202 @@
|
|||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
class="custom-radio-image"
|
||||||
|
fill="none"
|
||||||
|
height="66"
|
||||||
|
width="104"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<rect
|
||||||
|
id="svg_1"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-opacity="0.02"
|
||||||
|
height="66"
|
||||||
|
rx="4"
|
||||||
|
stroke="null"
|
||||||
|
width="104"
|
||||||
|
x="0.13514"
|
||||||
|
y="0.13514"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="svg_2"
|
||||||
|
d="m-3.37838,3.7543a1.93401,4.02457 0 0 1 1.93401,-4.02457l11.3488,0l0,66.40541l-11.3488,0a1.93401,4.02457 0 0 1 -1.93401,-4.02457l0,-58.35627z"
|
||||||
|
fill="hsl(var(--primary))"
|
||||||
|
stroke="null"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_3"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="5.47439"
|
||||||
|
x="1.64059"
|
||||||
|
y="15.46086"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_4"
|
||||||
|
fill="#ffffff"
|
||||||
|
height="7.67897"
|
||||||
|
rx="2"
|
||||||
|
stroke="null"
|
||||||
|
width="8.18938"
|
||||||
|
x="0.58676"
|
||||||
|
y="1.42154"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_8"
|
||||||
|
fill="hsl(var(--primary))"
|
||||||
|
height="9.07027"
|
||||||
|
rx="2"
|
||||||
|
stroke="null"
|
||||||
|
width="75.91967"
|
||||||
|
x="25.38277"
|
||||||
|
y="1.42876"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_9"
|
||||||
|
fill="#b2b2b2"
|
||||||
|
height="4.4"
|
||||||
|
rx="1"
|
||||||
|
stroke="null"
|
||||||
|
width="3.925"
|
||||||
|
x="27.91529"
|
||||||
|
y="3.69284"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_10"
|
||||||
|
fill="#b2b2b2"
|
||||||
|
height="4.4"
|
||||||
|
rx="1"
|
||||||
|
stroke="null"
|
||||||
|
width="3.925"
|
||||||
|
x="80.75054"
|
||||||
|
y="3.62876"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_11"
|
||||||
|
fill="#b2b2b2"
|
||||||
|
height="4.4"
|
||||||
|
rx="1"
|
||||||
|
stroke="null"
|
||||||
|
width="3.925"
|
||||||
|
x="87.78868"
|
||||||
|
y="3.69981"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_12"
|
||||||
|
fill="#b2b2b2"
|
||||||
|
height="4.4"
|
||||||
|
rx="1"
|
||||||
|
stroke="null"
|
||||||
|
width="3.925"
|
||||||
|
x="94.6847"
|
||||||
|
y="3.62876"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_13"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-opacity="0.08"
|
||||||
|
height="21.51892"
|
||||||
|
rx="2"
|
||||||
|
stroke="null"
|
||||||
|
width="42.9287"
|
||||||
|
x="58.75427"
|
||||||
|
y="14.613"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_14"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-opacity="0.08"
|
||||||
|
height="20.97838"
|
||||||
|
rx="2"
|
||||||
|
stroke="null"
|
||||||
|
width="28.36894"
|
||||||
|
x="26.14342"
|
||||||
|
y="14.613"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_15"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-opacity="0.08"
|
||||||
|
height="21.65405"
|
||||||
|
rx="2"
|
||||||
|
stroke="null"
|
||||||
|
width="75.09493"
|
||||||
|
x="26.34264"
|
||||||
|
y="39.68822"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_5"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="5.47439"
|
||||||
|
x="1.79832"
|
||||||
|
y="28.39462"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_6"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="5.47439"
|
||||||
|
x="1.64059"
|
||||||
|
y="41.80156"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_7"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="5.47439"
|
||||||
|
x="1.64059"
|
||||||
|
y="55.36623"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_16"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-opacity="0.08"
|
||||||
|
height="65.72065"
|
||||||
|
stroke="null"
|
||||||
|
width="12.49265"
|
||||||
|
x="9.85477"
|
||||||
|
y="-0.02618"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_21"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="7.52486"
|
||||||
|
x="35.14924"
|
||||||
|
y="4.07319"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_22"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="7.52486"
|
||||||
|
x="47.25735"
|
||||||
|
y="4.20832"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="svg_23"
|
||||||
|
fill="#e5e5e5"
|
||||||
|
height="2.789"
|
||||||
|
rx="1.395"
|
||||||
|
stroke="null"
|
||||||
|
width="7.52486"
|
||||||
|
x="59.23033"
|
||||||
|
y="4.07319"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</template>
|
@ -2,6 +2,7 @@ import HeaderNav from './header-nav.vue';
|
|||||||
|
|
||||||
export { default as ContentCompact } from './content-compact.vue';
|
export { default as ContentCompact } from './content-compact.vue';
|
||||||
export { default as FullContent } from './full-content.vue';
|
export { default as FullContent } from './full-content.vue';
|
||||||
|
export { default as HeaderMixedNav } from './header-mixed-nav.vue';
|
||||||
export { default as MixedNav } from './mixed-nav.vue';
|
export { default as MixedNav } from './mixed-nav.vue';
|
||||||
export { default as SidebarMixedNav } from './sidebar-mixed-nav.vue';
|
export { default as SidebarMixedNav } from './sidebar-mixed-nav.vue';
|
||||||
export { default as SidebarNav } from './sidebar-nav.vue';
|
export { default as SidebarNav } from './sidebar-nav.vue';
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
"horizontalTip": "水平菜单模式,菜单全部显示在顶部",
|
"horizontalTip": "水平菜单模式,菜单全部显示在顶部",
|
||||||
"twoColumn": "双列菜单",
|
"twoColumn": "双列菜单",
|
||||||
"twoColumnTip": "垂直双列菜单模式",
|
"twoColumnTip": "垂直双列菜单模式",
|
||||||
"mixedMenu": "混合菜单",
|
"headerTwoColumn": "混合双列",
|
||||||
|
"headerTwoColumnTip": "双列、水平菜单共存模式",
|
||||||
|
"mixedMenu": "混合垂直",
|
||||||
"mixedMenuTip": "垂直水平菜单共存",
|
"mixedMenuTip": "垂直水平菜单共存",
|
||||||
"fullContent": "内容全屏",
|
"fullContent": "内容全屏",
|
||||||
"fullContentTip": "不显示任何菜单,只显示内容主体",
|
"fullContentTip": "不显示任何菜单,只显示内容主体",
|
||||||
|
@ -21,9 +21,9 @@ function findMenuByPath(
|
|||||||
* @param menus
|
* @param menus
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
function findRootMenuByPath(menus: MenuRecordRaw[], path?: string) {
|
function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level = 0) {
|
||||||
const findMenu = findMenuByPath(menus, path);
|
const findMenu = findMenuByPath(menus, path);
|
||||||
const rootMenuPath = findMenu?.parents?.[0];
|
const rootMenuPath = findMenu?.parents?.[level];
|
||||||
const rootMenu = rootMenuPath
|
const rootMenu = rootMenuPath
|
||||||
? menus.find((item) => item.path === rootMenuPath)
|
? menus.find((item) => item.path === rootMenuPath)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
Loading…
Reference in New Issue
Block a user