feat(layout): add sidebar-topbar layout

This commit is contained in:
z9130 2024-10-09 12:19:42 +08:00
parent 0ed2928c19
commit d921b78951
7 changed files with 41 additions and 8 deletions

View File

@ -3,7 +3,8 @@ type LayoutType =
| 'header-nav' | 'header-nav'
| 'mixed-nav' | 'mixed-nav'
| 'sidebar-mixed-nav' | 'sidebar-mixed-nav'
| 'sidebar-nav'; | 'sidebar-nav'
| 'sidebar-topbar';
type ThemeModeType = 'auto' | 'dark' | 'light'; type ThemeModeType = 'auto' | 'dark' | 'light';

View File

@ -104,6 +104,8 @@ interface HeaderPreferences {
hidden: boolean; hidden: boolean;
/** header显示模式 */ /** header显示模式 */
mode: LayoutHeaderModeType; mode: LayoutHeaderModeType;
/** header高度适用于 layout 为 sidebar-topbar 模式 */
height: number;
} }
interface LogoPreferences { interface LogoPreferences {

View File

@ -97,6 +97,7 @@ interface VbenLayoutProps {
* header-nav * header-nav
* mixed-nav & * mixed-nav &
* sidebar-mixed-nav * sidebar-mixed-nav
* sidebar-topbar +
* full-content * full-content
* @default sidebar-nav * @default sidebar-nav
*/ */

View File

@ -120,7 +120,11 @@ const sidebarEnableState = computed(() => {
*/ */
const sidebarMarginTop = computed(() => { const sidebarMarginTop = computed(() => {
const { headerHeight, isMobile } = props; const { headerHeight, isMobile } = props;
return isMixedNav.value && !isMobile ? headerHeight : 0; console.log(props);
return (isMixedNav.value && !isMobile) ||
currentLayout.value === 'sidebar-topbar'
? headerHeight
: 0;
}); });
/** /**
@ -167,7 +171,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 === 'sidebar-topbar',
); );
/** /**
@ -199,6 +204,7 @@ const mainStyle = computed(() => {
headerFixed.value && headerFixed.value &&
currentLayout.value !== 'header-nav' && currentLayout.value !== 'header-nav' &&
currentLayout.value !== 'mixed-nav' && currentLayout.value !== 'mixed-nav' &&
currentLayout.value !== 'sidebar-topbar' &&
showSidebar.value && showSidebar.value &&
!props.isMobile !props.isMobile
) { ) {
@ -291,7 +297,10 @@ const headerWrapperStyle = computed((): CSSProperties => {
const fixed = headerFixed.value; const fixed = headerFixed.value;
return { return {
height: isFullContent.value ? '0' : `${headerWrapperHeight.value}px`, height: isFullContent.value ? '0' : `${headerWrapperHeight.value}px`,
left: isMixedNav.value ? 0 : mainStyle.value.sidebarAndExtraWidth, left:
isMixedNav.value || currentLayout.value === 'sidebar-topbar'
? 0
: mainStyle.value.sidebarAndExtraWidth,
position: fixed ? 'fixed' : 'static', position: fixed ? 'fixed' : 'static',
top: top:
headerIsHidden.value || isFullContent.value headerIsHidden.value || isFullContent.value
@ -335,12 +344,18 @@ const showHeaderToggleButton = computed(() => {
isSideMode.value && isSideMode.value &&
!isSidebarMixedNav.value && !isSidebarMixedNav.value &&
!isMixedNav.value && !isMixedNav.value &&
!props.isMobile) !props.isMobile &&
currentLayout.value !== 'sidebar-topbar')
); );
}); });
const showHeaderLogo = computed(() => { const showHeaderLogo = computed(() => {
return !isSideMode.value || isMixedNav.value || props.isMobile; return (
!isSideMode.value ||
isMixedNav.value ||
props.isMobile ||
currentLayout.value === 'sidebar-topbar'
);
}); });
watch( watch(
@ -454,7 +469,10 @@ function handleHeaderToggle() {
:z-index="sidebarZIndex" :z-index="sidebarZIndex"
@leave="() => emit('sideMouseLeave')" @leave="() => emit('sideMouseLeave')"
> >
<template v-if="isSideMode && !isMixedNav" #logo> <template
v-if="isSideMode && !isMixedNav && currentLayout !== 'sidebar-topbar'"
#logo
>
<slot name="logo"></slot> <slot name="logo"></slot>
</template> </template>

View File

@ -153,6 +153,7 @@ const headerSlots = computed(() => {
<VbenAdminLayout <VbenAdminLayout
v-model:sidebar-extra-visible="sidebarExtraVisible" v-model:sidebar-extra-visible="sidebarExtraVisible"
:content-compact="preferences.app.contentCompact" :content-compact="preferences.app.contentCompact"
:header-height="preferences.header.height"
:footer-enable="preferences.footer.enable" :footer-enable="preferences.footer.enable"
:footer-fixed="preferences.footer.fixed" :footer-fixed="preferences.footer.fixed"
:header-hidden="preferences.header.hidden" :header-hidden="preferences.header.hidden"
@ -211,6 +212,7 @@ const headerSlots = computed(() => {
#breadcrumb #breadcrumb
> >
<Breadcrumb <Breadcrumb
v-if="preferences.app.layout !== 'sidebar-topbar'"
:hide-when-only-one="preferences.breadcrumb.hideOnlyOne" :hide-when-only-one="preferences.breadcrumb.hideOnlyOne"
:show-home="preferences.breadcrumb.showHome" :show-home="preferences.breadcrumb.showHome"
:show-icon="preferences.breadcrumb.showIcon" :show-icon="preferences.breadcrumb.showIcon"

View File

@ -33,6 +33,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,
'sidebar-topbar': MixedNav,
}; };
const PRESET = computed((): PresetItem[] => [ const PRESET = computed((): PresetItem[] => [
@ -61,6 +62,11 @@ const PRESET = computed((): PresetItem[] => [
tip: $t('preferences.fullContentTip'), tip: $t('preferences.fullContentTip'),
type: 'full-content', type: 'full-content',
}, },
{
name: '侧边菜单 + 顶部栏布局',
tip: '顶部栏仅用于显示全局信息或操作,不包含菜单。',
type: 'sidebar-topbar',
},
]); ]);
function activeClass(theme: string): string[] { function activeClass(theme: string): string[] {

View File

@ -45,7 +45,7 @@ function defineOverridesPreferences(preferences: DeepPartial<Preferences>) {
// 检查更新的时间间隔,单位为分钟 // 检查更新的时间间隔,单位为分钟
checkUpdatesInterval: 1, checkUpdatesInterval: 1,
// 开启布局设置按钮 // 开启布局设置按钮
enablePreferences: false, enablePreferences: true,
enableRefreshToken: false, enableRefreshToken: false,
}, },
theme: { theme: {
@ -59,6 +59,9 @@ function defineOverridesPreferences(preferences: DeepPartial<Preferences>) {
semiDarkHeader: false, semiDarkHeader: false,
semiDarkSidebar: true, semiDarkSidebar: true,
}, },
header: {
height: 50,
},
footer: { footer: {
enable: false, enable: false,
fixed: false, fixed: false,