Files
vueadmin/src/layouts/components/level1Menu.vue
2026-01-16 11:54:18 +08:00

148 lines
3.1 KiB
Vue

<template>
<a-menu mode="inline" theme="dark" :selected-keys="selectedKeys" @select="handleSelect" class="level1-menu">
<a-menu-item v-for="item in menuList" :key="item.path">
<template #icon>
<component :is="item.meta?.icon || 'AppstoreOutlined'" />
</template>
{{ item.meta?.title || item.name }}
</a-menu-item>
</a-menu>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useLayoutStore } from '@/stores/modules/layout'
import { getUserMenu } from '@/api/menu'
const route = useRoute()
const router = useRouter()
const layoutStore = useLayoutStore()
const menuList = ref([])
const selectedKeys = ref([])
// 获取菜单数据
const getMenuList = async () => {
try {
const res = await getUserMenu()
if (res.code === 200) {
menuList.value = res.data || []
}
} catch (error) {
console.error('获取菜单失败:', error)
// 模拟数据
menuList.value = [
{
path: '/home',
name: 'Home',
meta: { title: '首页', icon: 'HomeOutlined' }
},
{
path: '/system',
name: 'System',
meta: { title: '系统管理', icon: 'SettingOutlined' },
children: [
{
path: '/system/user',
name: 'User',
meta: { title: '用户管理', icon: 'UserOutlined' }
},
{
path: '/system/role',
name: 'Role',
meta: { title: '角色管理', icon: 'TeamOutlined' }
},
{
path: '/system/menu',
name: 'Menu',
meta: { title: '菜单管理', icon: 'MenuOutlined' }
}
]
}
]
}
}
// 更新选中的菜单
const updateSelectedKeys = () => {
// 查找当前路由对应的一级菜单
const path = route.path
const matched = route.matched
if (matched.length > 0) {
const topPath = matched[0].path
selectedKeys.value = [topPath]
// 查找对应的菜单项
const selectedMenu = menuList.value.find(item => item.path === topPath)
if (selectedMenu) {
layoutStore.setSelectedParentMenu(selectedMenu)
}
}
}
// 处理菜单选择
const handleSelect = ({ key }) => {
const selectedMenu = menuList.value.find(item => item.path === key)
if (selectedMenu) {
layoutStore.setSelectedParentMenu(selectedMenu)
// 如果没有子菜单,直接跳转
if (!selectedMenu.children || selectedMenu.children.length === 0) {
router.push(key)
}
}
}
// 监听路由变化
watch(() => route.path, () => {
updateSelectedKeys()
}, { immediate: true })
onMounted(() => {
getMenuList()
})
</script>
<style scoped lang="scss">
.level1-menu {
height: calc(100% - 64px);
border-right: none;
background-color: #001529;
:deep(.ant-menu-item) {
height: 60px;
line-height: 60px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0;
margin: 0;
.anticon {
font-size: 20px;
margin-bottom: 4px;
}
.ant-menu-title-content {
font-size: 12px;
line-height: 1.2;
}
&:hover {
color: #ffffff;
background-color: #1890ff;
}
&.ant-menu-item-selected {
background-color: #1890ff;
&::after {
display: none;
}
}
}
}
</style>