<script lang="ts"> import { h, defineComponent, VNode, toRaw } 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>