110 lines
2.7 KiB
TypeScript
110 lines
2.7 KiB
TypeScript
import {
|
|
ElButton,
|
|
ElIcon,
|
|
ElMenu,
|
|
ElMenuItem,
|
|
ElMenuItemGroup,
|
|
ElSubMenu,
|
|
type MenuItemRegistered,
|
|
} from 'element-plus'
|
|
import { elIcons } from '@/common/element/element.ts'
|
|
|
|
export interface Menu extends G.TreeNode {
|
|
// Id
|
|
id: string
|
|
// 编码
|
|
sn: string
|
|
// 上级 Id; 层级为 1 的节点值为 0
|
|
pid: string
|
|
// 菜单名称
|
|
title: string
|
|
// 图标
|
|
icon: string
|
|
// 层级; >= 1
|
|
tier: number
|
|
// 排序
|
|
sort: number
|
|
// 路由名称
|
|
routeName: string
|
|
// 面包路径
|
|
breadcrumb: string[]
|
|
// 类型
|
|
menuCategory: 'Catalog' | 'Group' | 'Page' | 'SubPage' | 'Btn'
|
|
// 子菜单
|
|
children?: Menu[]
|
|
}
|
|
|
|
export default defineComponent(
|
|
({menus}, {emit}) => {
|
|
const onMenuClick = (it: MenuItemRegistered) => emit('menuClick', it.index)
|
|
const renderMenu = (it: Menu) => {
|
|
let renderChildNode: (() => VNode[] | undefined) | undefined = undefined
|
|
if (it.children != null && it.children.length > 0) {
|
|
renderChildNode = () => (it.children?.map(renderMenu))
|
|
}
|
|
let currentNode: VNode
|
|
switch (it.menuCategory) {
|
|
case 'Catalog': {
|
|
currentNode = (<ElSubMenu index={it.id}>
|
|
{{
|
|
title: () => <span>{it.title}</span>,
|
|
default: renderChildNode,
|
|
}}
|
|
</ElSubMenu>)
|
|
break
|
|
}
|
|
case 'Group': {
|
|
currentNode = (<ElMenuItemGroup title={it.title}>
|
|
{{
|
|
default: renderChildNode,
|
|
}}
|
|
</ElMenuItemGroup>)
|
|
break
|
|
}
|
|
case 'Page': {
|
|
currentNode = (<ElMenuItem index={it.id} onClick={onMenuClick}>
|
|
{{
|
|
default: () => <span>{it.title}</span>,
|
|
}}
|
|
</ElMenuItem>)
|
|
break
|
|
}
|
|
default:
|
|
currentNode = (<></>)
|
|
}
|
|
return currentNode
|
|
}
|
|
const isCollapse = ref(false)
|
|
|
|
return () => (<>
|
|
<ElMenu collapse={isCollapse.value} style={{height: '100%', overflow: 'auto', '--el-menu-base-level-padding': '10px'}} class={'menus'}>
|
|
{{
|
|
default: () => menus.map(renderMenu),
|
|
}}
|
|
</ElMenu>
|
|
<ElButton style={{position: 'absolute', right: 0, bottom: 0, width: '32px', height: '32px'}} onClick={() => {
|
|
isCollapse.value = !isCollapse.value
|
|
}}>
|
|
<ElIcon style={{cursor: 'pointer'}}>
|
|
{
|
|
isCollapse.value ? <elIcons.Fold/> : <elIcons.Expand/>
|
|
}
|
|
</ElIcon>
|
|
</ElButton>
|
|
</>)
|
|
},
|
|
{
|
|
props: {
|
|
menus: {
|
|
type: Object as PropType<Menu[]>,
|
|
required: true,
|
|
validator: (value: Menu[]) => value != null && value.length > 0,
|
|
},
|
|
},
|
|
emits: {
|
|
menuClick: (id: string) => id != null,
|
|
},
|
|
name: 'AAside',
|
|
})
|
|
|