Files
schoolNews/schoolNewsWeb/src/layouts/SidebarLayout.vue

239 lines
4.5 KiB
Vue
Raw Normal View History

2025-10-27 16:21:00 +08:00
<template>
<div class="sidebar-layout">
<!-- 主内容区域 -->
<div class="layout-content">
<!-- 侧边栏和内容 -->
<div class="content-wrapper" v-if="hasSidebarMenus">
2025-10-27 17:29:25 +08:00
<!-- 侧边栏 -->
<aside class="sidebar">
<!-- Logo区域 -->
<div class="sidebar-header">
<div class="logo-container">
<img src="@/assets/imgs/logo-icon.svg" alt="Logo" class="logo-icon" />
<div class="logo-text">
<div class="logo-title">管理后台</div>
<div class="logo-subtitle">红色思政平台</div>
</div>
2025-10-27 16:21:00 +08:00
</div>
2025-10-27 17:29:25 +08:00
</div>
<!-- 导航菜单 -->
<nav class="sidebar-nav">
<MenuSidebar
:menus="sidebarMenus"
:collapsed="false"
@menu-click="handleMenuClick"
/>
</nav>
</aside>
2025-10-27 16:21:00 +08:00
<!-- 页面内容 -->
<main class="main-content">
<router-view />
</main>
</div>
<!-- 没有侧边栏时直接显示内容 -->
<div class="content-wrapper-full" v-else>
<main class="main-content-full">
<router-view />
</main>
</div>
</div>
</div>
</template>
<script setup lang="ts">
2025-10-27 17:29:25 +08:00
import { computed } from 'vue';
2025-10-27 16:21:00 +08:00
import { useRoute, useRouter } from 'vue-router';
import { useStore } from 'vuex';
import type { SysMenu } from '@/types';
import { MenuType } from '@/types/enums';
2025-10-27 17:29:25 +08:00
import { MenuSidebar } from '@/components';
2025-10-27 16:21:00 +08:00
const route = useRoute();
const router = useRouter();
const store = useStore();
// 获取所有菜单
const allMenus = computed(() => store.getters['auth/menuTree']);
// 获取所有顶层SIDEBAR菜单作为侧边栏
const sidebarMenus = computed(() => {
// 严格过滤type=SIDEBAR 且 layout='SidebarLayout' 的顶层菜单
return allMenus.value.filter((menu: SysMenu) =>
menu.type === MenuType.SIDEBAR &&
!menu.parentID &&
(menu as any).layout === 'SidebarLayout'
);
});
// 是否有侧边栏菜单
const hasSidebarMenus = computed(() => sidebarMenus.value.length > 0);
// 处理菜单点击
function handleMenuClick(menu: SysMenu) {
if (menu.url && menu.url !== route.path) {
router.push(menu.url);
}
}
</script>
<style lang="scss" scoped>
.sidebar-layout {
display: flex;
flex-direction: column;
2025-10-27 17:29:25 +08:00
min-height: 100vh;
2025-10-27 16:21:00 +08:00
background: #f0f2f5;
}
.layout-content {
flex: 1;
display: flex;
flex-direction: column;
}
.content-wrapper {
flex: 1;
display: flex;
2025-10-27 17:29:25 +08:00
gap: 0;
height: 100vh;
overflow: hidden;
2025-10-27 16:21:00 +08:00
}
.sidebar {
2025-10-27 17:29:25 +08:00
width: 256px;
background: #FFFFFF;
border-right: 1px solid rgba(0, 0, 0, 0.1);
2025-10-27 16:21:00 +08:00
flex-shrink: 0;
display: flex;
flex-direction: column;
2025-10-27 17:29:25 +08:00
height: 100vh;
2025-10-27 16:21:00 +08:00
overflow: hidden;
2025-10-27 17:29:25 +08:00
}
2025-10-27 16:21:00 +08:00
2025-10-27 17:29:25 +08:00
.sidebar-header {
padding: 24px 24px 1px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
height: 97px;
2025-10-27 16:21:00 +08:00
}
2025-10-27 17:29:25 +08:00
.logo-container {
2025-10-27 16:21:00 +08:00
display: flex;
align-items: center;
2025-10-27 17:29:25 +08:00
gap: 12px;
}
2025-10-27 16:21:00 +08:00
2025-10-27 17:29:25 +08:00
.logo-icon {
width: 40px;
height: 40px;
flex-shrink: 0;
border-radius: 10px;
}
2025-10-27 16:21:00 +08:00
2025-10-27 17:29:25 +08:00
.logo-text {
display: flex;
flex-direction: column;
}
.logo-title {
font-size: 16px;
font-weight: 400;
line-height: 1.5;
color: #C10007;
}
.logo-subtitle {
font-size: 12px;
font-weight: 400;
line-height: 1.33;
color: #6A7282;
2025-10-27 16:21:00 +08:00
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
2025-10-27 17:29:25 +08:00
padding: 16px 16px 0;
2025-10-27 16:21:00 +08:00
2025-10-27 17:29:25 +08:00
// 美化滚动条(深色,适配白色背景)
2025-10-27 16:21:00 +08:00
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
2025-10-27 17:29:25 +08:00
background: #f1f1f1;
2025-10-27 16:21:00 +08:00
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
2025-10-27 17:29:25 +08:00
background: #c1c1c1;
2025-10-27 16:21:00 +08:00
border-radius: 3px;
&:hover {
2025-10-27 17:29:25 +08:00
background: #a8a8a8;
2025-10-27 16:21:00 +08:00
}
}
}
.main-content {
flex: 1;
2025-10-27 17:29:25 +08:00
background: #F9FAFB;
2025-10-27 16:21:00 +08:00
overflow-y: auto;
2025-10-28 19:04:35 +08:00
/* min-width: 0; */
padding: 20px;
box-sizing: border-box;
height: 100vh;
2025-10-27 16:21:00 +08:00
// 美化滚动条
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
&:hover {
background: #a8a8a8;
}
}
}
.content-wrapper-full {
flex: 1;
}
.main-content-full {
2025-10-27 17:29:25 +08:00
background: #F9FAFB;
height: 100vh;
2025-10-27 16:21:00 +08:00
overflow-y: auto;
2025-10-28 19:04:35 +08:00
padding: 20px;
box-sizing: border-box;
2025-10-27 17:29:25 +08:00
2025-10-27 16:21:00 +08:00
// 美化滚动条
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
&:hover {
background: #a8a8a8;
}
}
}
</style>