/** * 该插件可根据菜单配置自动生成 ANTD menu组件 * menuOptions示例: * [ * { * name: '菜单名称', * path: '菜单路由', * meta: { * icon: '菜单图标', * invisible: 'boolean, 是否不可见, 默认 false', * }, * children: [子菜单配置] * }, * { * name: '菜单名称', * path: '菜单路由', * meta: { * icon: '菜单图标', * invisible: 'boolean, 是否不可见, 默认 false', * }, * children: [子菜单配置] * } * ] * * i18n: 国际化配置。系统默认会根据 options route配置的 path 和 name 生成英文以及中文的国际化配置,如需自定义或增加其他语言,配置 * 此项即可。如: * i18n: { * messages: { * zh_CN: {dashboard: {name: '监控中心'}} * * } * } **/ import Menu from 'ant-design-vue/es/menu'; import Icon from 'ant-design-vue/es/icon'; import { getUserInfo } from '@/utils'; const { Item, SubMenu } = Menu; export default { name: 'IMenu', props: { options: { type: Array, required: true, }, theme: { type: String, required: false, default: 'dark', }, mode: { type: String, required: false, default: 'inline', }, collapsed: { type: Boolean, required: false, default: false, }, i18n: Object, }, data() { return { selectedKeys: [], sOpenKeys: [], cachedOpenKeys: [], menuData: [], }; }, computed: { menuTheme() { return this.theme == 'light' ? this.theme : 'dark'; }, }, created() { const { menuList } = getUserInfo(); this.menuData = menuList.filter(i => i.menuType === 'MENU'); this.updateMenu(); // // 自定义国际化配置 // if (this.i18n && this.i18n.messages) { // const messages = this.i18n.messages; // Object.keys(messages).forEach(key => { // this.$i18n.mergeLocaleMessage(key, messages[key]); // }); // } }, watch: { i18n(val) { if (val && val.messages) { const messages = this.i18n.messages; Object.keys(messages).forEach(key => { this.$i18n.mergeLocaleMessage(key, messages[key]); }); } }, collapsed(val) { if (val) { this.cachedOpenKeys = this.sOpenKeys; this.sOpenKeys = []; } else { this.sOpenKeys = this.cachedOpenKeys; } }, $route: function() { this.updateMenu(); }, sOpenKeys(val) { this.$emit('openChange', val); this.$emit('update:openKeys', val); }, }, methods: { renderIcon(h, icon, key) { if (this.$scopedSlots.icon && icon && icon !== 'none') { const vnodes = this.$scopedSlots.icon({ icon, key }); vnodes.forEach(vnode => { vnode.data.class = vnode.data.class ? vnode.data.class : []; vnode.data.class.push('anticon'); }); return vnodes; } return !icon || icon == 'none' ? null : h(Icon, { props: { type: icon } }); }, renderMenuItem(h, menu) { const tag = 'router-link'; const config = { props: { to: menu.path }, attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' }, }; return h(Item, { key: menu.menuId }, [ h(tag, config, [this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName]), ]); }, renderSubMenu(h, menu) { const subItem = [ h( 'span', { slot: 'title', attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' }, }, [this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName], ), ]; const itemArr = []; menu.children.forEach(item => { itemArr.push(this.renderItem(h, item)); }); return h(SubMenu, { key: menu.menuId }, subItem.concat(itemArr)); }, renderItem(h, menu) { return menu.children && menu.children.length ? this.renderSubMenu(h, menu) : this.renderMenuItem(h, menu); }, renderMenu(h, menuTree) { let menuArr = []; menuTree.forEach((menu, i) => { menuArr.push(this.renderItem(h, menu)); }); return menuArr; }, updateMenu() { this.selectedKeys = this.getSelectedKey(this.$route); // let openKeys = matchedRoutes.map(item => item.path); // openKeys = openKeys.slice(0, openKeys.length - 1); // if (!fastEqual(openKeys, this.sOpenKeys)) { // this.collapsed || this.mode === 'horizontal' // ? (this.cachedOpenKeys = openKeys) // : (this.sOpenKeys = openKeys); // } this.sOpenKeys = this.getOpenKeysByPath(this.$route.path); }, getSelectedKey(route) { const { path } = route; return [this.menuData.find(m => m.menuUrl === path).menuId]; }, getOpenKeysByPath(path) { const { menuList } = getUserInfo(); const { parentMenuId } = this.menuData.find(m => m.menuUrl === path); const parentMenus = [parentMenuId]; const res = [parentMenuId]; while (parentMenus.length) { const menuId = parentMenus.pop(); const parentMenu = menuList.find(m => m.menuId === menuId); if (parentMenu.parentMenuId !== 0) { parentMenus.push(parentMenu.parentMenuId); res.push(parentMenu.parentMenuId); } } return res; }, }, render(h) { return h( Menu, { props: { theme: this.menuTheme, mode: this.$props.mode, selectedKeys: this.selectedKeys, openKeys: this.sOpenKeys, }, on: { 'update:openKeys': val => { this.sOpenKeys = val; }, click: obj => { obj.selectedKeys = [obj.key]; this.$emit('select', obj); }, }, }, this.renderMenu(h, this.options), ); }, };