Files
Situation-Awareness-Platfor…/src/layouts/DefaultLayout/index.vue

212 lines
7.1 KiB
Vue
Raw Normal View History

2025-03-12 18:41:20 +08:00
<template>
2025-03-14 20:03:14 +08:00
<d-layout class="d-layout h-full" :class="{ 'home-background': isHome }">
2025-03-12 18:41:20 +08:00
<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);
2025-03-14 20:03:14 +08:00
const isHome = computed(() => route.name === 'home');
2025-03-12 18:41:20 +08:00
// 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;
}
2025-03-14 20:03:14 +08:00
.home-background {
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
2025-03-21 11:00:56 +08:00
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 1)),url('@/assets/imgs/home/bg.png');
2025-03-14 20:03:14 +08:00
background-size: cover;
background-position: center;
z-index: -1;
}
}
2025-03-12 18:41:20 +08:00
</style>