2026-02-16 10:17:01 +08:00

179 lines
3.3 KiB
Vue

<template>
<div class="mobile-sidebar-wrapper">
<!-- 遮罩层 -->
<div
class="mobile-sidebar-mask"
:class="{ show: modelValue }"
@click="handleClose"
/>
<!-- 侧边栏 -->
<div
class="mobile-sidebar"
:class="{ open: modelValue }"
>
<div class="mobile-sidebar-header">
<div class="logo">
<img src="@/assets/logo.png" alt="logo" v-if="false">
<span>资金服务平台</span>
</div>
<el-button link @click="handleClose">
<el-icon><Close /></el-icon>
</el-button>
</div>
<div class="mobile-sidebar-content">
<el-menu
:default-active="activeMenu"
:collapse="false"
:collapse-transition="false"
router
>
<sidebar-item
v-for="route in routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { Close } from '@element-plus/icons-vue'
import SidebarItem from '@/layout/components/Sidebar/SidebarItem.vue'
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue'])
const route = useRoute()
// 当前激活的菜单
const activeMenu = computed(() => {
const { meta, path } = route
if (meta.activeMenu) {
return meta.activeMenu
}
return path
})
// 路由列表
const routes = computed(() => {
// 从路由配置中获取菜单
const allRoutes = route.matched[0]?.children || []
return allRoutes.filter(item => !item.hidden)
})
// 关闭侧边栏
const handleClose = () => {
emit('update:modelValue', false)
}
</script>
<style scoped lang="scss">
.mobile-sidebar-wrapper {
display: none;
@media screen and (max-width: 768px) {
display: block;
}
}
.mobile-sidebar-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
opacity: 0;
visibility: hidden;
transition: all 0.3s;
&.show {
opacity: 1;
visibility: visible;
}
}
.mobile-sidebar {
position: fixed;
top: 0;
left: 0;
bottom: 0;
width: 260px;
background: #304156;
z-index: 1000;
transform: translateX(-100%);
transition: transform 0.3s;
display: flex;
flex-direction: column;
&.open {
transform: translateX(0);
}
&-header {
height: 50px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
background: #2b3a4d;
.logo {
color: #fff;
font-size: 16px;
font-weight: 600;
img {
width: 32px;
height: 32px;
margin-right: 10px;
vertical-align: middle;
}
}
.el-button {
color: #fff;
font-size: 20px;
}
}
&-content {
flex: 1;
overflow-y: auto;
:deep(.el-menu) {
border-right: none;
background: transparent;
.el-menu-item,
.el-sub-menu__title {
color: #bfcbd9;
&:hover {
background: #263445;
}
&.is-active {
color: #409eff;
background: #263445;
}
}
}
}
}
</style>