zb-admin/src/layout/LayoutColumns/index.vue

223 lines
5.3 KiB
Vue

<template>
<div class="main-columns">
<div class="layout-columns-aside">
<div class="logo flex-center">
<img src="@/assets/image/logo.png" alt="logo" />
</div>
<el-scrollbar>
<div class="menu-wrap">
<div
class="item-menu-wrap"
:class="{
'active-menu':activeCurrentMenu===item.path
}"
v-for="item in menusRoutes"
:key="item.path"
@click="handleChangeMenu(item)"
>
<el-icon :size="20">
<component :is="item?.meta?.icon"></component>
</el-icon>
<span class="title">{{ item?.meta?.title }}</span>
</div>
</div>
</el-scrollbar>
</div>
<div class="layout-columns-sub" :style="{ width: isCollapse ? '60px' : '210px' }">
<div class="logo flex-center">
<span v-show="subMenus.length">{{ isCollapse ? "Vue" : "Vue Admin Perfect" }}</span>
</div>
<el-scrollbar >
<el-menu
:collapse="isCollapse"
:router="false"
:default-active="activeMenu"
:unique-opened="SettingStore.themeConfig.uniqueOpened"
:collapse-transition="false"
class="menu-columns"
>
<SubMenu
:basePath="basePath"
:menuList="subMenus"
/>
</el-menu>
</el-scrollbar>
</div>
<div class="container">
<div class="layout-header">
<div class="header-tool">
<HeaderToolLeft/>
<HeaderToolRight/>
</div>
<TagsView v-if="themeConfig.showTag"/>
</div>
<Main/>
<Footer/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import {usePermissionStore} from "@/store/modules/permission"
import { useSettingStore } from "@/store/modules/setting";
import SubItem from '../components/SubMenu/SubItem.vue'
import Footer from '../components/Footer/index.vue'
import SubMenu from '../components/SubMenu/SubMenu.vue'
import TagsView from '../components/TagsView/index.vue'
const PermissionStore = usePermissionStore()
const SettingStore = useSettingStore()
const route = useRoute()
const router = useRouter();
import HeaderToolRight from '../components/Header/ToolRight.vue'
import HeaderToolLeft from '../components/Header/ToolLeft.vue'
import Main from '../components/Main/index.vue'
// 获取路由
const permission_routes = computed(() => PermissionStore.permission_routes)
// 获取路由
const menusRoutes = computed(()=>{
return PermissionStore.permission_routes.filter(item=>!item.hidden)
})
const activeCurrentMenu = ref('')
// 主题配置
const themeConfig = computed(() =>SettingStore.themeConfig)
const isCollapse = computed(() =>!SettingStore.isCollapse)
const activeMenu = computed(() => {
const { meta, path } = route
if (meta.activeMenu) {
return meta.activeMenu
}
return path
})
const basePath = ref<string>('/')
const subMenus = ref([])
watch(()=>[route],()=>{
if (!menusRoutes.value.length) return;
const [firstMenu] = route.matched
activeCurrentMenu.value = firstMenu.path;
let menuItem = menusRoutes.value.find(item=>firstMenu.path === item.path)
if(menuItem&&menuItem.children?.length) {
subMenus.value = menuItem.children
}else {
subMenus.value = []
}
basePath.value = firstMenu.path
},{
deep: true,
immediate:true
})
const handleChangeMenu = (item)=>{
router.push(item.path);
}
</script>
<style lang="scss" scoped>
.main-columns{
display: flex;
flex-direction: row!important;
height: 100%;
width: 100%;
}
.layout-columns-aside{
flex-shrink: 0;
width: 80px;
height: 100%;
background-color: #304156;
.el-scrollbar{
height: calc(100% - 55px);
}
.logo {
box-sizing: border-box;
height: 50px;
img {
width: 32px;
object-fit: contain;
}
}
.menu-wrap{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.item-menu-wrap{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 70px;
width: 70px;
cursor: pointer;
transition: all .3s ease;
}
.active-menu{
background: #1890ff;
border-radius: 5px;
}
.title{
color: #e5eaf3;
}
.el-icon{
color: #e5eaf3;
}
}
}
.layout-columns-sub{
flex-shrink: 0;
width:200px;
box-sizing: border-box;
flex-direction: column;
overflow: hidden;
transition: all 0.3s ease;
background: white;
border-right: 1px solid #eee;
.el-scrollbar{
height: calc(100vh - 50px);
}
.logo {
width: 100%;
box-sizing: border-box;
height: 50px;
border-bottom: 1px solid #eee;
span{
font-weight: bold;
white-space: nowrap;
}
}
::v-deep(.menu-columns){
border-right: none;
}
}
.container{
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
}
.layout-header{
background: white;
transition: width 0.28s;
flex-shrink: 0;
box-sizing: border-box;
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
.header-tool{
height: 50px;
width: 100%;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
padding: 0 10px 0 0;
box-sizing: border-box;
justify-content: space-between;
}
}
</style>