131 lines
3.3 KiB
JavaScript
131 lines
3.3 KiB
JavaScript
import Menu from 'ant-design-vue/es/menu'
|
|
import { mapState } from 'vuex'
|
|
|
|
const { Item, SubMenu } = Menu
|
|
|
|
export default {
|
|
name: 'SideMenu',
|
|
props: {
|
|
collapsed: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
openKeys: [],
|
|
selectedKeys: [],
|
|
cachedOpenKeys: [],
|
|
}
|
|
},
|
|
mounted() {
|
|
this.updateMenu()
|
|
},
|
|
computed: {
|
|
rootSubmenuKeys() {
|
|
return this.menu.map(item => item.path)
|
|
},
|
|
...mapState({
|
|
menu: state => state.user.menu,
|
|
}),
|
|
},
|
|
watch: {
|
|
$route: function() {
|
|
this.updateMenu()
|
|
},
|
|
collapsed: function(newValue) {
|
|
this.openKeys = newValue ? [] : this.cachedOpenKeys
|
|
},
|
|
},
|
|
methods: {
|
|
onOpenChange(openKeys) {
|
|
const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1)
|
|
if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
|
|
this.openKeys = openKeys
|
|
} else {
|
|
this.openKeys = latestOpenKey ? [latestOpenKey] : []
|
|
}
|
|
},
|
|
updateMenu() {
|
|
const routes = this.$route.matched.concat()
|
|
this.selectedKeys = [routes.pop().path]
|
|
// 如果父路由有redirectDefaultChild参数, 说明必须让父路由高亮, 父路由的上级展开
|
|
if (routes[routes.length - 1].meta.redirectDefaultChild) {
|
|
this.selectedKeys = [routes.pop().path]
|
|
}
|
|
this.cachedOpenKeys = routes.map(item => item.path)
|
|
this.openKeys = this.collapsed ? [] : this.cachedOpenKeys
|
|
// setTimeout(() => {
|
|
// document
|
|
// .querySelector(".side-menu .ant-menu-item-selected")
|
|
// ?.closest(".side-menu>[role='menuitem']")
|
|
// .scrollIntoView();
|
|
// }, 1000);
|
|
},
|
|
|
|
// render
|
|
renderItem(menu) {
|
|
if (menu.hidden) {
|
|
return null
|
|
} else {
|
|
return menu.children && !menu.alwaysShow && !menu.meta.redirectDefaultChild
|
|
? this.renderSubMenu(menu)
|
|
: this.renderMenuItem(menu)
|
|
}
|
|
},
|
|
renderMenuItem(menu) {
|
|
let menuItem
|
|
if (menu.meta?.url) {
|
|
menuItem = (
|
|
<a href={menu.meta.url} target="_blank">
|
|
{this.renderIcon(menu.meta.icon)}
|
|
<span>{menu.meta.title}</span>
|
|
</a>
|
|
)
|
|
} else {
|
|
menuItem = (
|
|
<RouterLink to={{ path: menu.path }}>
|
|
{this.renderIcon(menu.meta.icon)}
|
|
<span>{menu.meta.title}</span>
|
|
</RouterLink>
|
|
)
|
|
}
|
|
return <Item key={menu.path}>{menuItem}</Item>
|
|
},
|
|
renderSubMenu(menu) {
|
|
return (
|
|
<SubMenu key={menu.path}>
|
|
<span slot="title">
|
|
{this.renderIcon(menu.meta.icon)}
|
|
<span>{menu.meta.title}</span>
|
|
</span>
|
|
{menu.children.map(item => this.renderItem(item))}
|
|
</SubMenu>
|
|
)
|
|
},
|
|
renderIcon(icon) {
|
|
if (!icon) {
|
|
return null
|
|
}
|
|
return <a-icon type={icon} />
|
|
},
|
|
},
|
|
|
|
render() {
|
|
const menuTree = this.menu.map(item => {
|
|
return this.renderItem(item)
|
|
})
|
|
return (
|
|
<Menu
|
|
theme={this.$store.state.app.navTheme}
|
|
mode="inline"
|
|
vModel={this.selectedKeys}
|
|
openKeys={this.openKeys}
|
|
on={{ openChange: this.onOpenChange }}>
|
|
{menuTree}
|
|
</Menu>
|
|
)
|
|
},
|
|
}
|