241 lines
6.1 KiB
Vue

<template>
<el-container class="layout-container">
<el-aside width="collapse" class="layout-aside" :class="shrink ? 'shrink' : ''">
<div :class="menuCollapse ? 'fixed-menu-collapse fxc' : 'fixed-menu-expand fxsb'">
<div v-show="!menuCollapse" class="menu-logo">
<el-link type="primary" @click="refresh" class="pl-20 pr-4">
<img src="@/assets/img/logo-sm.png" class="fxc" height="34px" alt="logo" />
</el-link>
</div>
<el-link class="plr-10 w-56" @click="menuToggle">
<el-icon :size="20">
<Fold v-show="!menuCollapse" />
<Expand v-show="menuCollapse" />
</el-icon>
</el-link>
</div>
<el-scrollbar class="scrollbar-menu-wrapper" :class="shrink ? 'shrink' : ''">
<AsideMenu />
</el-scrollbar>
</el-aside>
<el-container>
<el-header>
<TopHeader />
</el-header>
<el-main>
<el-scrollbar style="width: 100%;">
<!-- 路由展示区 -->
<!-- { Component }指当前路由所对应的组件 -->
<RouterView v-slot="{ Component }">
<!-- 添加过渡动画 需要确保插入的component元素只有一个根节点, 否则报错. component中的根元素的transition会覆盖transitionName的样式
而且需要保证component中根元素的宽度相同所以最好是统一给component添加一个根元素 -->
<transition :name="transitionName">
<KeepAlive>
<Component :is="Component" v-if="keepAlive" :key="$route.path" />
</KeepAlive>
</transition>
<!-- 添加过渡动画 需要确保插入的component元素只有一个根节点 -->
<transition :name="transitionName">
<Component :is="Component" v-if="!keepAlive" :key="$route.path" />
</transition>
</RouterView>
</el-scrollbar>
</el-main>
</el-container>
<div class="aside-menu-shade">
</div>
</el-container>
</template>
<script setup>
import TopHeader from '@/components/TopHeader.vue'
import AsideMenu from '@/components/AsideMenu.vue'
import { ref, reactive, computed, watch, onBeforeMount } from 'vue'
import { useRouter, RouterView } from 'vue-router'
import { Expand, Fold } from '@element-plus/icons-vue'
import { showShade, closeShade } from '@/assets/js/shade'
import { useConfig } from '@/store/config'
import { useEventListener } from '@vueuse/core'
import { storeToRefs } from 'pinia'
const router = useRouter()
const config = useConfig()
const { shrink, menuCollapse } = storeToRefs(config)
const currentRoute = reactive(router.currentRoute)
// 默认动画效果, 向左滑动
let transitionName = 'slide-left'
const keepAlive = computed(() => {
return currentRoute.value.meta.keepAlive
})
/** 固定菜单头展开折叠动画时间 刷新页面时菜单不会展开或折叠, 设置持续时间为0, 不产生动画 */
const menuAnimationDuration = ref(0)
// 菜单折叠展开切换
function menuToggle() {
menuAnimationDuration.value = '300ms'
if (menuCollapse.value) {
// console.log("折叠状态下, 进行展开菜单")
if (shrink.value) {
// 收缩时, 展开遮罩
showShade(() => {
// console.log("这里定义关闭遮罩回调函数, 关闭遮罩后, 折叠菜单")
config.setMenuCollapse(true)
})
}
} else {
// console.log("展开状态下, 进行折叠菜单, 关闭掉侧栏遮罩")
closeShade()
}
// 切换菜单折叠状态
config.setMenuCollapse(!menuCollapse.value)
}
function onAdaptiveLayout() {
// 获取当前窗口宽度
const clientWidth = document.body.clientWidth
// console.log("menuCollapse:", menuCollapse.value, config.getMenuCollapse(), "clientWidth:", clientWidth)
// 设定aside是否收缩
if (clientWidth < 800) {
config.setShrink(true)
if (!menuCollapse.value) {
// 展开状态下, 收起菜单
menuToggle()
}
} else {
config.setShrink(false)
}
}
onBeforeMount(() => {
onAdaptiveLayout()
useEventListener(window, 'resize', onAdaptiveLayout)
})
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
// console.log("路由变化,如果是收缩状态,则收起菜单:", newValue, oldValue)
if (shrink.value && !menuCollapse.value) {
// console.log("收缩状态下, 且菜单展开时, 收起菜单")
menuToggle()
}
})
function refresh() {
// console.log("刷新页面")
location.reload()
}
</script>
<style scoped>
.layout-container {
height: 100vh;
}
header {
width: 100%;
height: 44px;
padding: 0px;
background-color: var(--el-bg-color);
display: flex;
justify-content: center;
align-items: center;
}
aside {
background-color: var(--el-fg-color);
}
aside.shrink {
width: 44px;
}
.layout-aside {
margin: 0;
height: 100vh;
overflow: hidden;
transition: width .3s ease;
}
main {
height: calc(100vh - 44px);
width: 100%;
padding: 0px;
overflow: hidden;
}
.menu-logo {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/** 菜单折叠 */
@keyframes menuCollapse {
0% {
width: 200px;
}
100% {
width: 44px;
}
}
/** 菜单展开 */
@keyframes menuExpand {
0% {
width: 44px;
}
100% {
width: 200px;
}
}
.fixed-menu-collapse {
position: fixed;
z-index: 9999;
height: 44px;
width: 44px;
/* 引用上面定义的@keyframes名称 */
animation-name: menuCollapse;
/* 动画持续时间 */
animation-duration: v-bind('menuAnimationDuration');
animation-timing-function: ease-in-out;
background-color: var(--el-fg-color);
}
.fixed-menu-expand {
position: fixed;
z-index: 9999;
height: 44px;
width: 200px;
/* 引用上面定义的@keyframes名称 */
animation-name: menuExpand;
/* 动画持续时间 */
animation-duration: v-bind('menuAnimationDuration');
animation-timing-function: ease-in-out;
background-color: var(--el-fg-color);
z-index: 9999999
}
.scrollbar-menu-wrapper {
top: 44px;
height: calc(100vh - 44px);
background-color: var(--el-fg-color);
}
.scrollbar-menu-wrapper.shrink {
position: fixed;
left: 0;
z-index: 9999999
}
</style>