mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-17 17:26:38 +08:00
171 lines
5.1 KiB
Vue
171 lines
5.1 KiB
Vue
<script setup lang="ts">
|
|
import { computed, defineAsyncComponent } from 'vue';
|
|
import { AdminLayout, LAYOUT_SCROLL_EL_ID } from '@sa/materials';
|
|
import type { LayoutMode } from '@sa/materials';
|
|
import { useAppStore } from '@/store/modules/app';
|
|
import { useThemeStore } from '@/store/modules/theme';
|
|
import GlobalHeader from '../modules/global-header/index.vue';
|
|
import GlobalSider from '../modules/global-sider/index.vue';
|
|
import GlobalTab from '../modules/global-tab/index.vue';
|
|
import GlobalContent from '../modules/global-content/index.vue';
|
|
import GlobalFooter from '../modules/global-footer/index.vue';
|
|
import ThemeDrawer from '../modules/theme-drawer/index.vue';
|
|
import { provideMixMenuContext } from '../modules/global-menu/context';
|
|
|
|
defineOptions({
|
|
name: 'BaseLayout'
|
|
});
|
|
|
|
const appStore = useAppStore();
|
|
const themeStore = useThemeStore();
|
|
const { childLevelMenus, isActiveFirstLevelMenuHasChildren } = provideMixMenuContext();
|
|
|
|
const GlobalMenu = defineAsyncComponent(() => import('../modules/global-menu/index.vue'));
|
|
|
|
const layoutMode = computed(() => {
|
|
const vertical: LayoutMode = 'vertical';
|
|
const horizontal: LayoutMode = 'horizontal';
|
|
return themeStore.layout.mode.includes(vertical) ? vertical : horizontal;
|
|
});
|
|
|
|
const headerProps = computed(() => {
|
|
const { mode } = themeStore.layout;
|
|
|
|
const headerPropsConfig: Record<UnionKey.ThemeLayoutMode, App.Global.HeaderProps> = {
|
|
vertical: {
|
|
showLogo: false,
|
|
showMenu: false,
|
|
showMenuToggler: true
|
|
},
|
|
'vertical-mix': {
|
|
showLogo: false,
|
|
showMenu: false,
|
|
showMenuToggler: false
|
|
},
|
|
'vertical-hybrid-header-first': {
|
|
showLogo: !isActiveFirstLevelMenuHasChildren.value,
|
|
showMenu: true,
|
|
showMenuToggler: false
|
|
},
|
|
horizontal: {
|
|
showLogo: true,
|
|
showMenu: true,
|
|
showMenuToggler: false
|
|
},
|
|
'top-hybrid-sidebar-first': {
|
|
showLogo: true,
|
|
showMenu: true,
|
|
showMenuToggler: false
|
|
},
|
|
'top-hybrid-header-first': {
|
|
showLogo: true,
|
|
showMenu: true,
|
|
showMenuToggler: isActiveFirstLevelMenuHasChildren.value
|
|
}
|
|
};
|
|
|
|
return headerPropsConfig[mode];
|
|
});
|
|
|
|
const siderVisible = computed(() => themeStore.layout.mode !== 'horizontal');
|
|
|
|
const isVerticalMix = computed(() => themeStore.layout.mode === 'vertical-mix');
|
|
|
|
const isVerticalHybridHeaderFirst = computed(() => themeStore.layout.mode === 'vertical-hybrid-header-first');
|
|
|
|
const isTopHybridSidebarFirst = computed(() => themeStore.layout.mode === 'top-hybrid-sidebar-first');
|
|
|
|
const isTopHybridHeaderFirst = computed(() => themeStore.layout.mode === 'top-hybrid-header-first');
|
|
|
|
const siderWidth = computed(() => getSiderWidth());
|
|
|
|
const siderCollapsedWidth = computed(() => getSiderCollapsedWidth());
|
|
|
|
function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
|
const {
|
|
mixChildMenuWidth,
|
|
collapsedWidth,
|
|
width: themeWidth,
|
|
mixCollapsedWidth,
|
|
mixWidth: themeMixWidth
|
|
} = themeStore.sider;
|
|
|
|
const width = isCollapsed ? collapsedWidth : themeWidth;
|
|
const mixWidth = isCollapsed ? mixCollapsedWidth : themeMixWidth;
|
|
|
|
if (isTopHybridHeaderFirst.value) {
|
|
return isActiveFirstLevelMenuHasChildren.value ? width : 0;
|
|
}
|
|
|
|
if (isVerticalHybridHeaderFirst.value && !isActiveFirstLevelMenuHasChildren.value) {
|
|
return 0;
|
|
}
|
|
|
|
const isMixMode = isVerticalMix.value || isTopHybridSidebarFirst.value || isVerticalHybridHeaderFirst.value;
|
|
let finalWidth = isMixMode ? mixWidth : width;
|
|
|
|
if (isVerticalMix.value && appStore.mixSiderFixed && childLevelMenus.value.length) {
|
|
finalWidth += mixChildMenuWidth;
|
|
}
|
|
|
|
if (isVerticalHybridHeaderFirst.value && appStore.mixSiderFixed && childLevelMenus.value.length) {
|
|
finalWidth += mixChildMenuWidth;
|
|
}
|
|
|
|
return finalWidth;
|
|
}
|
|
|
|
function getSiderWidth() {
|
|
return getSiderAndCollapsedWidth(false);
|
|
}
|
|
|
|
function getSiderCollapsedWidth() {
|
|
return getSiderAndCollapsedWidth(true);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<AdminLayout
|
|
v-model:sider-collapse="appStore.siderCollapse"
|
|
:mode="layoutMode"
|
|
:scroll-el-id="LAYOUT_SCROLL_EL_ID"
|
|
:scroll-mode="themeStore.layout.scrollMode"
|
|
:is-mobile="appStore.isMobile"
|
|
:full-content="appStore.fullContent"
|
|
:fixed-top="themeStore.fixedHeaderAndTab"
|
|
:header-height="themeStore.header.height"
|
|
:tab-visible="themeStore.tab.visible"
|
|
:tab-height="themeStore.tab.height"
|
|
:content-class="appStore.contentXScrollable ? 'overflow-x-hidden' : ''"
|
|
:sider-visible="siderVisible"
|
|
:sider-width="siderWidth"
|
|
:sider-collapsed-width="siderCollapsedWidth"
|
|
:footer-visible="themeStore.footer.visible"
|
|
:footer-height="themeStore.footer.height"
|
|
:fixed-footer="themeStore.footer.fixed"
|
|
:right-footer="themeStore.footer.right"
|
|
>
|
|
<template #header>
|
|
<GlobalHeader v-bind="headerProps" />
|
|
</template>
|
|
<template #tab>
|
|
<GlobalTab />
|
|
</template>
|
|
<template #sider>
|
|
<GlobalSider />
|
|
</template>
|
|
<GlobalMenu />
|
|
<GlobalContent />
|
|
<ThemeDrawer />
|
|
<template #footer>
|
|
<GlobalFooter />
|
|
</template>
|
|
</AdminLayout>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
#__SCROLL_EL_ID__ {
|
|
@include scrollbar();
|
|
}
|
|
</style>
|