feat: 添加递归菜单组件 MenuItem
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import MenuItem from '@/components/MenuItem.vue'
|
||||||
|
|
||||||
|
describe('MenuItem 组件', () => {
|
||||||
|
it('应该正确接收菜单项 props', () => {
|
||||||
|
const menu = {
|
||||||
|
id: 1,
|
||||||
|
name: '仪表盘',
|
||||||
|
path: '/dashboard',
|
||||||
|
icon: 'Odometer',
|
||||||
|
sort: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mount(MenuItem, {
|
||||||
|
props: { menu },
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
'el-menu-item': {
|
||||||
|
template: '<div><slot /></div>'
|
||||||
|
},
|
||||||
|
'el-sub-menu': {
|
||||||
|
template: '<div><slot name="title" /><slot /></div>'
|
||||||
|
},
|
||||||
|
'el-icon': {
|
||||||
|
template: '<div><slot /></div>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.props('menu')).toEqual(menu)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确处理有子菜单的菜单项', () => {
|
||||||
|
const menu = {
|
||||||
|
id: 2,
|
||||||
|
name: '系统管理',
|
||||||
|
path: '/system',
|
||||||
|
icon: 'Setting',
|
||||||
|
sort: 2,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: '用户管理',
|
||||||
|
path: '/users',
|
||||||
|
sort: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mount(MenuItem, {
|
||||||
|
props: { menu },
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
'el-menu-item': {
|
||||||
|
template: '<div><slot /></div>'
|
||||||
|
},
|
||||||
|
'el-sub-menu': {
|
||||||
|
template: '<div><slot name="title" /><slot /></div>'
|
||||||
|
},
|
||||||
|
'el-icon': {
|
||||||
|
template: '<div><slot /></div>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.props('menu')).toEqual(menu)
|
||||||
|
expect(wrapper.props('menu').children).toHaveLength(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<el-sub-menu
|
||||||
|
v-if="menu.children && menu.children.length > 0"
|
||||||
|
:index="String(menu.id)"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<el-icon v-if="menu.icon">
|
||||||
|
<component :is="menu.icon" />
|
||||||
|
</el-icon>
|
||||||
|
<span>{{ menu.name }}</span>
|
||||||
|
</template>
|
||||||
|
<menu-item
|
||||||
|
v-for="child in menu.children"
|
||||||
|
:key="child.id"
|
||||||
|
:menu="child"
|
||||||
|
/>
|
||||||
|
</el-sub-menu>
|
||||||
|
|
||||||
|
<el-menu-item
|
||||||
|
v-else
|
||||||
|
:index="menu.path"
|
||||||
|
>
|
||||||
|
<el-icon v-if="menu.icon">
|
||||||
|
<component :is="menu.icon" />
|
||||||
|
</el-icon>
|
||||||
|
<span>{{ menu.name }}</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { MenuItem as MenuItemType } from '@/stores/permission'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
menu: MenuItemType
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user