125 lines
2.5 KiB
Vue
125 lines
2.5 KiB
Vue
![]() |
<script lang="ts">
|
|||
|
import { h, defineComponent, VNode } from 'vue'
|
|||
|
import { usePermissionsStore } from '/admin/stores/modules/user/permissions'
|
|||
|
import MenuItem from './item.vue'
|
|||
|
import menus from './menus.vue'
|
|||
|
import { useUserStore } from '/admin/stores/modules/user'
|
|||
|
import { Menu } from '/admin/types/Menu'
|
|||
|
|
|||
|
/**
|
|||
|
* 递归渲染 Menu 节点
|
|||
|
*/
|
|||
|
function getVNodes(menus: Menu[] | undefined, _subMenuClass: string | undefined): VNode[] {
|
|||
|
const vnodes: VNode[] = []
|
|||
|
menus?.forEach(menu => {
|
|||
|
if (!menu.meta?.hidden) {
|
|||
|
let vnode: VNode
|
|||
|
const len = menu.children?.length
|
|||
|
if (len) {
|
|||
|
vnode = h(
|
|||
|
MenuItem,
|
|||
|
{
|
|||
|
subMenuClass: _subMenuClass,
|
|||
|
menu,
|
|||
|
},
|
|||
|
{
|
|||
|
default: () => getVNodes(menu.children, 'children-menu'),
|
|||
|
},
|
|||
|
)
|
|||
|
} else {
|
|||
|
vnode = h(MenuItem, {
|
|||
|
subMenuClass: _subMenuClass,
|
|||
|
menu,
|
|||
|
})
|
|||
|
}
|
|||
|
vnodes.push(vnode)
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
return vnodes
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* filter menus
|
|||
|
*
|
|||
|
* @param menus
|
|||
|
*/
|
|||
|
function filterMenus(menus: Menu[] | undefined): Menu[] {
|
|||
|
const newMenus: Menu[] = []
|
|||
|
|
|||
|
menus?.forEach(m => {
|
|||
|
if (m.meta?.hidden) {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
if (isHasOnlyChild(m) && m.children?.length) {
|
|||
|
newMenus.push(
|
|||
|
Object.assign({
|
|||
|
path: m.children[0].path,
|
|||
|
meta: m.children[0].meta,
|
|||
|
name: m.name,
|
|||
|
}),
|
|||
|
)
|
|||
|
} else {
|
|||
|
newMenus.push(m)
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
return newMenus
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* is has only child
|
|||
|
*
|
|||
|
* @param menu
|
|||
|
*/
|
|||
|
function isHasOnlyChild(menu: Menu): boolean {
|
|||
|
if (menu.children === undefined) {
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
if (menu.children.length > 1 || !menu.children.length) {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
if (menu.children[0].children?.length) {
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
export default defineComponent({
|
|||
|
props: {
|
|||
|
subMenuClass: {
|
|||
|
type: String,
|
|||
|
require: true,
|
|||
|
},
|
|||
|
menuClass: {
|
|||
|
type: String,
|
|||
|
require: true,
|
|||
|
},
|
|||
|
},
|
|||
|
setup(props, ctx) {
|
|||
|
const permissionsStore = usePermissionsStore()
|
|||
|
const userStore = useUserStore()
|
|||
|
|
|||
|
// 后端的 permissions 返回 undefined,则认为该后端无权限系统
|
|||
|
const permissions = userStore.getPermissions === undefined ? [] : userStore.getPermissions
|
|||
|
const vnodes = getVNodes(filterMenus(permissionsStore.getMenusFrom(permissions)), props.subMenuClass)
|
|||
|
|
|||
|
return () => {
|
|||
|
return h(
|
|||
|
menus,
|
|||
|
{
|
|||
|
class: 'border-none side-menu ' + props.menuClass,
|
|||
|
},
|
|||
|
{
|
|||
|
default: () => vnodes,
|
|||
|
},
|
|||
|
)
|
|||
|
}
|
|||
|
},
|
|||
|
})
|
|||
|
</script>
|