253 lines
5.5 KiB
Vue
253 lines
5.5 KiB
Vue
<template>
|
|
<div class="index">
|
|
<div :class="{ 'has-logo': showLogo }" class="sidebar-container">
|
|
<!-- logo -->
|
|
<Logo v-if="showLogo" :collapse="isCollapse" />
|
|
<!-- 菜单 -->
|
|
<happy-scroll color="rgba(0,0,0,0.5)" size="5" class="menu-scroll-container">
|
|
<el-menu
|
|
:collapse="isCollapse"
|
|
:background-color="variables.menuBg"
|
|
:text-color="variables.menuText"
|
|
:unique-opened="true"
|
|
:active-text-color="variables.menuActiveText"
|
|
:collapse-transition="true"
|
|
:default-active="activeMenu"
|
|
mode="vertical"
|
|
class="el-menu-vertical"
|
|
>
|
|
<sidebar-item
|
|
v-for="(route, index) in permissionRoutes"
|
|
:key="route.path + index"
|
|
:item="route"
|
|
:base-path="route.path"
|
|
:is-collapse="isCollapse"
|
|
/>
|
|
</el-menu>
|
|
</happy-scroll>
|
|
<button
|
|
class="sidebar-collapse-btn"
|
|
:class="{ collapsed: isCollapse }"
|
|
:title="isCollapse ? '展开菜单' : '折叠菜单'"
|
|
@click="toggleSideBar"
|
|
>
|
|
<i :class="isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from "vuex";
|
|
import SidebarItem from "./SidebarItem.vue";
|
|
import variables from "@/styles/variables.scss";
|
|
import Logo from "./Logo.vue";
|
|
|
|
export default {
|
|
name: "Sidebar",
|
|
components: { SidebarItem, Logo },
|
|
computed: {
|
|
...mapGetters(["permission_routes", "sidebar", "userType", "orgType"]),
|
|
|
|
showLogo() {
|
|
return true;
|
|
},
|
|
|
|
variables() {
|
|
return variables;
|
|
},
|
|
|
|
isCollapse() {
|
|
return !this.sidebar.opened;
|
|
},
|
|
|
|
permissionRoutes() {
|
|
const routes = this.permission_routes || [];
|
|
return routes;
|
|
},
|
|
|
|
activeMenu() {
|
|
const route = this.$route;
|
|
const { meta, path } = route;
|
|
|
|
if (meta.activeMenu) {
|
|
return meta.activeMenu;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
},
|
|
|
|
mounted() {
|
|
console.log("Sidebar mounted - 权限路由:", this.permissionRoutes);
|
|
},
|
|
|
|
methods: {
|
|
toggleSideBar() {
|
|
this.$store.dispatch("app/toggleSideBar");
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.index {
|
|
width: 100%;
|
|
height: 100vh;
|
|
position: relative;
|
|
|
|
.sidebar-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
box-sizing: border-box;
|
|
position: relative;
|
|
transition: width 0.25s ease;
|
|
}
|
|
|
|
.menu-scroll-container {
|
|
flex: 1;
|
|
width: 100%;
|
|
overflow-x: hidden;
|
|
|
|
::v-deep .happy-scroll-container {
|
|
width: 100% !important;
|
|
min-width: unset !important;
|
|
|
|
.happy-scroll-content {
|
|
width: 100%;
|
|
min-width: unset !important;
|
|
box-sizing: border-box;
|
|
}
|
|
}
|
|
}
|
|
|
|
.sidebar-collapse-btn {
|
|
position: absolute;
|
|
right: 16px;
|
|
bottom: 18px;
|
|
z-index: 10;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 42px;
|
|
height: 42px;
|
|
color: #8a94a6;
|
|
font-size: 18px;
|
|
cursor: pointer;
|
|
background: #ffffff;
|
|
border: 1px solid #eef2f7;
|
|
border-radius: 50%;
|
|
box-shadow: 0 8px 22px rgba(31, 45, 61, 0.12);
|
|
transition: all 0.25s ease;
|
|
|
|
&:hover {
|
|
color: #1e6fff;
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 12px 26px rgba(30, 111, 255, 0.18);
|
|
}
|
|
|
|
&.collapsed {
|
|
right: 11px;
|
|
}
|
|
}
|
|
|
|
// 更具体的选择器
|
|
::v-deep .el-menu-vertical {
|
|
border: none;
|
|
height: 100%;
|
|
width: 100% !important;
|
|
min-width: 100% !important;
|
|
box-sizing: border-box;
|
|
|
|
.el-submenu__title,
|
|
.el-menu-item {
|
|
height: 56px;
|
|
line-height: 56px;
|
|
margin: 6px 14px;
|
|
padding: 0 18px !important;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
border-radius: 12px;
|
|
transition: all 0.25s ease;
|
|
}
|
|
|
|
.el-submenu__title span,
|
|
.el-menu-item span {
|
|
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
}
|
|
|
|
.el-submenu__title:hover,
|
|
.el-menu-item:not(.is-active):hover {
|
|
color: #1e6fff !important;
|
|
background: #f4f8ff !important;
|
|
}
|
|
|
|
.el-menu-item.is-active {
|
|
color: #ffffff !important;
|
|
background: linear-gradient(135deg, #1e6fff, #5d8dff) !important;
|
|
|
|
}
|
|
|
|
.el-menu-item.is-active i,
|
|
.el-menu-item.is-active span {
|
|
color: #ffffff !important;
|
|
}
|
|
|
|
// 子菜单容器
|
|
.el-menu--inline {
|
|
// 子菜单项
|
|
.el-menu-item {
|
|
// 激活的子菜单项
|
|
&.is-active {
|
|
background: linear-gradient(135deg, #1e6fff, #5d8dff) !important;
|
|
color: #ffffff !important;
|
|
|
|
|
|
&:before {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
// 非激活状态的悬停效果
|
|
&:not(.is-active):hover {
|
|
background-color: #f4f8ff !important;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 折叠状态
|
|
::v-deep .el-menu--collapse {
|
|
width: 64px !important;
|
|
min-width: 64px !important;
|
|
|
|
.el-submenu__title,
|
|
.el-menu-item {
|
|
margin: 6px 8px;
|
|
padding: 0 !important;
|
|
text-overflow: clip;
|
|
justify-content: center;
|
|
}
|
|
|
|
.el-submenu__title span,
|
|
.el-menu-item span {
|
|
opacity: 0;
|
|
transform: translateX(-6px);
|
|
}
|
|
|
|
// 折叠状态下的子菜单激活样式
|
|
.el-menu--popup {
|
|
.el-menu-item {
|
|
&.is-active {
|
|
color: #ffffff !important;
|
|
background: linear-gradient(135deg, #1e6fff 0%, #244fbd 100%) !important;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|