This commit is contained in:
van
2026-05-19 17:05:15 +08:00
parent dabc0632bd
commit a82ae229b3
4 changed files with 111 additions and 34 deletions

View File

@@ -1,3 +1,12 @@
@keyframes sidebarFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#app { #app {
.main-container { .main-container {
@@ -34,20 +43,9 @@
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
} }
// 添加进入动画 // 进入动画仅用透明度;勿对侧栏本体使用 transform
animation: slideInLeft 0.5s ease-out; // 否则会影响子菜单弹出层popper-append-to-body的定位出现跑偏、重影。
} animation: sidebarFadeIn 0.45s ease-out;
@keyframes slideInLeft {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
// reset element-ui css // reset element-ui css
.horizontal-collapse-transition { .horizontal-collapse-transition {
@@ -111,16 +109,6 @@
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative; position: relative;
span {
font-size: 14px !important;
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
width: auto !important;
height: auto !important;
overflow: visible !important;
}
&:hover { &:hover {
background: rgba(25, 118, 210, 0.1) !important; background: rgba(25, 118, 210, 0.1) !important;
color: $base-menu-color-active !important; color: $base-menu-color-active !important;
@@ -148,6 +136,61 @@
} }
} }
// 仅在侧栏菜单「未折叠」时强制标题 span 可见;勿写在通用 .el-menu-item 上,
// 否则会覆盖 Element 折叠态样式,导致收起后文字仍挤出侧栏。
.el-menu:not(.el-menu--collapse) {
.el-menu-item,
.el-submenu > .el-submenu__title {
span {
font-size: 14px !important;
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
width: auto !important;
height: auto !important;
overflow: visible !important;
}
}
}
// 侧栏折叠:单行只保留图标(与 hideSidebar / Element 折叠行为对齐)
.el-menu.el-menu--collapse {
.el-menu-item,
.el-submenu > .el-submenu__title {
overflow: hidden !important;
}
// 折叠态不要用 translate 做悬停位移,否则会抖动 referencePopper 浮层错位/叠层
> .el-menu-item:hover,
> .el-submenu > .el-submenu__title:hover {
transform: none !important;
box-shadow: none !important;
}
.el-submenu > .el-submenu__title .el-submenu__icon-arrow {
display: none !important;
}
// 含 el-tooltip 包裹时文字不在 li 的直接子 span 上,故用后代选择器
> .el-menu-item span,
> .el-submenu > .el-submenu__title span {
visibility: hidden !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
overflow: hidden !important;
display: inline-block !important;
margin: 0 !important;
padding: 0 !important;
font-size: 0 !important;
line-height: 0 !important;
}
.svg-icon:hover {
transform: none !important;
}
}
// 子菜单样式优化 // 子菜单样式优化
.el-submenu { .el-submenu {
.el-submenu__title { .el-submenu__title {
@@ -223,6 +266,9 @@
.hideSidebar { .hideSidebar {
.sidebar-container { .sidebar-container {
width: 54px !important; width: 54px !important;
// 折叠时关闭毛玻璃,避免 Chromium 下与 Popper 浮层定位/重影异常
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
} }
.main-container { .main-container {
@@ -375,8 +421,10 @@
} }
} }
// 弹出菜单样式优化 }
.el-menu--popup { .el-menu--popup {
z-index: 3050 !important;
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%) !important; background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%) !important;
border-radius: 12px !important; border-radius: 12px !important;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2) !important; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2) !important;
@@ -393,7 +441,6 @@
&:hover { &:hover {
background: rgba(25, 118, 210, 0.1) !important; background: rgba(25, 118, 210, 0.1) !important;
color: $base-menu-color-active !important; color: $base-menu-color-active !important;
transform: translateX(4px);
} }
&.is-active { &.is-active {

View File

@@ -1,5 +1,12 @@
<template> <template>
<div class="navbar"> <div class="navbar">
<hamburger
v-if="device !== 'mobile'"
id="hamburger-container"
:is-active="sidebar.opened"
class="hamburger-container"
@toggleClick="toggleSideBar"
/>
<breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container" /> <breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container" />
<top-nav v-if="topNav" id="topmenu-container" class="topmenu-container" /> <top-nav v-if="topNav" id="topmenu-container" class="topmenu-container" />
@@ -39,6 +46,7 @@
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import Hamburger from '@/components/Hamburger'
import Breadcrumb from '@/components/Breadcrumb' import Breadcrumb from '@/components/Breadcrumb'
import TopNav from '@/components/TopNav' import TopNav from '@/components/TopNav'
import Screenfull from '@/components/Screenfull' import Screenfull from '@/components/Screenfull'
@@ -50,6 +58,7 @@ import RuoYiDoc from '@/components/RuoYi/Doc'
export default { export default {
emits: ['setLayout'], emits: ['setLayout'],
components: { components: {
Hamburger,
Breadcrumb, Breadcrumb,
TopNav, TopNav,
Screenfull, Screenfull,
@@ -62,7 +71,8 @@ export default {
...mapGetters([ ...mapGetters([
'avatar', 'avatar',
'device', 'device',
'nickName' 'nickName',
'sidebar'
]), ]),
setting: { setting: {
get() { get() {
@@ -76,6 +86,9 @@ export default {
} }
}, },
methods: { methods: {
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
setLayout(event) { setLayout(event) {
this.$emit('setLayout') this.$emit('setLayout')
}, },
@@ -108,6 +121,19 @@ export default {
padding: 0 5px; padding: 0 5px;
} }
.hamburger-container {
float: left;
height: 100%;
line-height: 50px;
cursor: pointer;
transition: background .3s;
-webkit-tap-highlight-color: transparent;
&:hover {
background: rgba(0, 0, 0, .025);
}
}
.breadcrumb-container { .breadcrumb-container {
float: left; float: left;
@@ -118,7 +144,8 @@ export default {
.topmenu-container { .topmenu-container {
position: absolute; position: absolute;
left: 0; left: 50px;
right: 0;
@media (max-width: 768px) { @media (max-width: 768px) {
left: 0; left: 0;

View File

@@ -1,10 +1,10 @@
<template> <template>
<div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<logo v-if="showLogo" :collapse="false" /> <logo v-if="showLogo" :collapse="isMenuCollapse" />
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper"> <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
<el-menu <el-menu
:default-active="activeMenu" :default-active="activeMenu"
:collapse="false" :collapse="isMenuCollapse"
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground" :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
:text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor" :text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
:unique-opened="true" :unique-opened="true"
@@ -34,6 +34,9 @@ export default {
computed: { computed: {
...mapState(["settings"]), ...mapState(["settings"]),
...mapGetters(["sidebarRouters", "sidebar"]), ...mapGetters(["sidebarRouters", "sidebar"]),
isMenuCollapse() {
return !this.sidebar.opened
},
activeMenu() { activeMenu() {
const route = this.$route const route = this.$route
const { meta, path } = route const { meta, path } = route

View File

@@ -68,8 +68,8 @@ export default {
}, },
classObj() { classObj() {
return { return {
hideSidebar: false, // 侧边栏始终展开 hideSidebar: !this.sidebar.opened,
openSidebar: true, // 侧边栏始终展开 openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation, withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile' mobile: this.device === 'mobile'
} }