212 lines
7.1 KiB
Vue
212 lines
7.1 KiB
Vue
<template>
|
||
<d-layout class="d-layout h-full" :class="{ 'home-background': isHome }">
|
||
<d-header class="d-header">
|
||
<!-- header -->
|
||
<Header @clickMenu="handleClickMenu" :asideSetShow="asideSetShow" ref="refHeader">
|
||
<!-- 二级导航左侧内容 -->
|
||
<template v-if="$slots.headerLeft && !route?.meta?.hideNav" #info>
|
||
<slot name="headerLeft"></slot>
|
||
</template>
|
||
|
||
<!-- 二级导航右侧内容 -->
|
||
<template v-if="$slots.headerRight && !route?.meta?.hideNav" #menu>
|
||
<slot name="headerRight"></slot>
|
||
</template>
|
||
|
||
<template v-if="$slots.bodyHeader && !route?.meta?.hideNav" #bodyHeader>
|
||
<slot name="bodyHeader"></slot>
|
||
</template>
|
||
<template v-if="$slots.headerBottom && !route?.meta?.hideNav" #headerBottom>
|
||
<slot name="headerBottom"></slot>
|
||
</template>
|
||
</Header>
|
||
</d-header>
|
||
<!-- 顶栏信息 -->
|
||
<div v-if="$slots.contentBanner">
|
||
<slot name="contentBanner"></slot>
|
||
</div>
|
||
<!-- 主体 -->
|
||
<d-layout class="flex-col">
|
||
<d-aside class="left-side-bar" v-if="asideSetShow" :style="{ width: mainMarginLeftWidth + 'px' }">
|
||
<Aside :asideDefaultWidth="mainMarginLeftWidth"></Aside>
|
||
</d-aside>
|
||
<d-drawer v-model="asideVisible" position="left" lock-scroll style="max-height: 100%; top: 0;"
|
||
:style="{ width: '240px', overflowY: 'hidden' }">
|
||
<div class="p-[16px] flex justify-between items-center h-[60px]">
|
||
<GLink class="g-toolbar-left-logo" href="/" />
|
||
<d-icon class="cursor-pointer" name="close" @click="asideVisible = false"></d-icon>
|
||
</div>
|
||
<Aside :asideDefaultWidth="240" @on-select="handleClickMenu" style="height: calc(100% - 60px);padding-top: 0px;"></Aside>
|
||
</d-drawer>
|
||
<d-layout :style="{ marginLeft: mainMarginLeftWidth + 'px', transition: 'margin-left ease 0.1s' }">
|
||
<d-layout :class="responsiveClass" :style="{ minHeight: `calc(100% - ${footerSize?.height.value || 0}px)` }">
|
||
<!-- sidebar -->
|
||
<d-aside class="d-aside mr-[32px] pt-24" v-if="route?.meta?.sidebarType">
|
||
<slot name="sidebar"></slot>
|
||
</d-aside>
|
||
<!-- 内容 -->
|
||
<d-content>
|
||
<slot name="content">
|
||
<RouterView />
|
||
</slot>
|
||
</d-content>
|
||
</d-layout>
|
||
<!-- footer -->
|
||
<!-- <d-footer v-if="!route?.meta?.hiddenFooter" ref="refFooter">
|
||
<slot name="footer">
|
||
<Footer />
|
||
</slot>
|
||
</d-footer> -->
|
||
</d-layout>
|
||
</d-layout>
|
||
|
||
<!-- 浮动工具栏(移动端不显示) -->
|
||
<!-- <ToolsFloat v-if="showToolsFloat" />-->
|
||
|
||
</d-layout>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
defineOptions({ name: 'DefaultLayout' });
|
||
import { RouterView, useRoute, useRouter } from 'vue-router';
|
||
import { computed, ref, watch, watchEffect, onMounted, onUnmounted } from 'vue';
|
||
import Header from '@/components/Header/index.vue';
|
||
import Footer from '@/components/Footer/index.vue';
|
||
import Aside from './aside.vue';
|
||
import { useGlobalInfoStore } from '@/stores/Global';
|
||
|
||
import ToolsFloat from '@/components/ToolsFloat/index.vue';
|
||
import { useStorage, useElementSize } from '@vueuse/core';
|
||
import { usePageResize } from '@/utils/hooks/usePageResize';
|
||
import microApp from '@micro-zoe/micro-app';
|
||
defineProps<{ customAside?: boolean; }>();
|
||
const router = useRouter();
|
||
const solt = defineSlots();
|
||
const sizeStore = usePageResize();
|
||
const globalStore = useGlobalInfoStore();
|
||
const route = useRoute();
|
||
const asideVisible = ref(false);
|
||
const refFooter = ref(null);
|
||
const refHeader: any = ref(null);
|
||
const footerSize = useElementSize(refFooter);
|
||
const isHome = computed(() => route.name === 'home');
|
||
|
||
// aside 设置可见性 header有两层,有顶栏信息,两层sidebar 都不可见
|
||
const asideSetShow = computed(() => {
|
||
if (route.meta.asideMenu === 'drawer') return false;
|
||
return refHeader.value?.height <= 56 && !solt.contentBanner && !route.meta.sidebarType;
|
||
});
|
||
|
||
const emit = defineEmits<{
|
||
clickMenu: [];
|
||
}>();
|
||
watch(route, () => {
|
||
globalStore.setIsNotFound(false); // 切换路由默认不显示404,防止一直显示404
|
||
}, { deep: true });
|
||
|
||
const asideDefaultWidth = useStorage('asideDefaultWidth', sizeStore.isMobile.value ? 0 : 240);
|
||
const mainMarginLeftWidth = computed(() => {
|
||
if (!asideSetShow.value || sizeStore.isMobile.value) {
|
||
return 0;
|
||
} else {
|
||
return asideDefaultWidth.value;
|
||
}
|
||
});
|
||
|
||
// 是否展示浮动工具栏(非移动端 || 未设置隐藏)
|
||
const showToolsFloat = computed(() => {
|
||
return sizeStore.widthType.value !== 'sm' && !route.meta.hiddenToolsFloat;
|
||
});
|
||
|
||
const responsiveClass = computed(() => { // 控制移动和pc布局
|
||
let className = 'm-auto max-w-normal px-normal w-full';
|
||
let viewportContent = 'width=device-width,initial-scale=0,user-scalable=yes,maximum-scale=1.0';
|
||
|
||
if (sizeStore.isMobile.value) { // 设备是否为手机
|
||
if (route?.meta?.hasMobile) { // 是否有手机端页面
|
||
className = 'w-full';
|
||
viewportContent = 'width=device-width, initial-scale=1.0';
|
||
}
|
||
} else {
|
||
if (route?.meta?.className) {
|
||
className = `${route?.meta?.className as string}`;
|
||
}
|
||
if (route.name === 'homepage' && globalStore.namespaceType === 1) { // 组织主页样式特殊处理
|
||
className = 'm-auto min-w-sm px-normal max-w-[1280px] w-full pt-[12px]';
|
||
}
|
||
}
|
||
document?.querySelector("meta[name='viewport']")?.setAttribute('content', viewportContent);
|
||
return className;
|
||
});
|
||
|
||
const handleClickMenu = () => {
|
||
if (sizeStore.isMobile.value || !asideSetShow.value) { // 不可见时弹框
|
||
asideVisible.value = !asideVisible.value;
|
||
} else { // 可见时收起
|
||
asideDefaultWidth.value = asideDefaultWidth.value >= 240 ? 0 : 240;
|
||
}
|
||
};
|
||
|
||
const outOfSearch = ref(true); // 在search页面隐藏footer
|
||
router.afterEach((to, form) => {
|
||
outOfSearch.value = to.name !== 'search';
|
||
});
|
||
microApp.router.afterEach({
|
||
'micoro-app-homeweb-app': (to, from) => {
|
||
outOfSearch.value = to.pathname !== '/search';
|
||
}
|
||
});
|
||
const checkPage = (data: any) => {
|
||
if (data.type === 'checkPage') {
|
||
return 'ready';
|
||
}
|
||
};
|
||
onMounted(() => {
|
||
microApp.addDataListener('micoro-app-homeweb-app', checkPage, false);
|
||
});
|
||
onUnmounted(() => {
|
||
microApp.removeDataListener('micoro-app-homeweb-app', checkPage);
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.left-side-bar {
|
||
position: fixed;
|
||
left: 0;
|
||
bottom: 0;
|
||
top: 56px;
|
||
background-color: #fff;
|
||
z-index: 10;
|
||
border-right: 1px solid #F1F1F8;
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
transition: width ease 0.1s;
|
||
}
|
||
|
||
.g-toolbar-left-logo {
|
||
display: inline-block;
|
||
width: 102px;
|
||
height: 28px;
|
||
background: url(../../assets/imgs/logo/logo.png) no-repeat;
|
||
background-size: contain;
|
||
vertical-align: middle;
|
||
background-position: 0 center;
|
||
}
|
||
|
||
.home-background {
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 1)),url('@/assets/imgs/home/bg.png');
|
||
background-size: cover;
|
||
background-position: center;
|
||
z-index: -1;
|
||
}
|
||
|
||
}
|
||
</style>
|