|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import Menu from 'ant-design-vue/es/menu'
import Icon from 'ant-design-vue/es/icon'
const { Item, SubMenu } = Menu
export default {
name: 'SMenu',
props: {
menu: {
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
}
},
data () {
return {
openKeys: [],
selectedKeys: [],
cachedOpenKeys: []
}
},
computed: {
|
|
37
38
|
rootSubmenuKeys: vm => {
const keys = []
|
|
39
40
41
42
|
vm.menu.forEach(item => keys.push(item.path))
return keys
}
},
|
|
43
|
mounted () {
|
|
44
45
46
47
48
|
this.updateMenu()
},
watch: {
collapsed (val) {
if (val) {
|
|
49
|
this.cachedOpenKeys = this.openKeys.concat()
|
|
50
51
52
53
54
|
this.openKeys = []
} else {
this.openKeys = this.cachedOpenKeys
}
},
|
|
55
|
$route: function () {
|
|
56
57
58
59
|
this.updateMenu()
}
},
methods: {
|
|
60
61
|
// select menu item
onOpenChange (openKeys) {
|
|
62
|
|
|
63
64
65
66
|
// 在水平模式下时执行,并且不再执行后续
if (this.mode === 'horizontal') {
this.openKeys = openKeys
return
|
|
67
|
}
|
|
68
69
70
|
// 非水平模式时
const latestOpenKey = openKeys.find(key => !this.openKeys.includes(key))
if (!this.rootSubmenuKeys.includes(latestOpenKey)) {
|
|
71
72
|
this.openKeys = openKeys
} else {
|
|
73
|
this.openKeys = latestOpenKey ? [latestOpenKey] : []
|
|
74
75
76
|
}
},
updateMenu () {
|
|
77
78
79
|
const routes = this.$route.matched.concat()
const { hidden } = this.$route.meta
if (routes.length >= 3 && hidden) {
|
|
80
|
routes.pop()
|
|
81
|
this.selectedKeys = [routes[routes.length - 1].path]
|
|
82
|
} else {
|
|
83
|
this.selectedKeys = [routes.pop().path]
|
|
84
|
}
|
|
85
|
let openKeys = []
|
|
86
|
if (this.mode === 'inline') {
|
|
87
|
routes.forEach(item => {
|
|
88
89
90
|
openKeys.push(item.path)
})
}
|
|
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
// update-begin-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
// 包含冒号的是动态菜单
if (this.selectedKeys[0].includes(':')) {
let selectedKey = this.$route.fullPath
this.selectedKeys = [selectedKey]
let newOpenKeys = []
this.fullOpenKeys(this.menu, selectedKey, newOpenKeys)
if (newOpenKeys.length > 0) {
openKeys = newOpenKeys.reverse()
}
}
// update-end-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
|
|
105
106
107
108
109
110
|
//update-begin-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
if(!this.selectedKeys || this.selectedKeys[0].indexOf(":")<0){
this.collapsed ? (this.cachedOpenKeys = openKeys) : (this.openKeys = openKeys)
}
//update-end-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
},
|
|
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// update-begin-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
// 递归查找当前选中的菜单和父级菜单,填充openKeys
fullOpenKeys(menus, selectedKey, openKeys) {
for (let item of menus) {
if (item.path === selectedKey) {
openKeys.push(item.path)
this.$emit('updateMenuTitle', item)
return true
} else if (Array.isArray(item.children)) {
if (this.fullOpenKeys(item.children, selectedKey, openKeys)) {
openKeys.push(item.path)
return true
}
}
}
},
// update-end-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
|
|
128
|
|
|
129
130
131
|
// render
renderItem (menu) {
if (!menu.hidden) {
|
|
132
|
return menu.children && !menu.alwaysShow ? this.renderSubMenu(menu) : this.renderMenuItem(menu)
|
|
133
134
135
136
137
138
139
140
141
142
143
144
145
|
}
return null
},
renderMenuItem (menu) {
const target = menu.meta.target || null
const tag = target && 'a' || 'router-link'
let props = { to: { name: menu.name } }
if(menu.route && menu.route === '0'){
props = { to: { path: menu.path } }
}
const attrs = { href: menu.path, target: menu.meta.target }
|
|
146
|
if (menu.children && menu.alwaysShow) {
|
|
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
// 把有子菜单的 并且 父菜单是要隐藏子菜单的
// 都给子菜单增加一个 hidden 属性
// 用来给刷新页面时, selectedKeys 做控制用
menu.children.forEach(item => {
item.meta = Object.assign(item.meta, { hidden: true })
})
}
return (
<Item {...{ key: menu.path }}>
<tag {...{ props, attrs }}>
{this.renderIcon(menu.meta.icon)}
<span>{menu.meta.title}</span>
</tag>
</Item>
)
},
renderSubMenu (menu) {
const itemArr = []
|
|
166
|
if (!menu.alwaysShow) {
|
|
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
menu.children.forEach(item => itemArr.push(this.renderItem(item)))
}
return (
<SubMenu {...{ key: menu.path }}>
<span slot="title">
{this.renderIcon(menu.meta.icon)}
<span>{menu.meta.title}</span>
</span>
{itemArr}
</SubMenu>
)
},
renderIcon (icon) {
if (icon === 'none' || icon === undefined) {
return null
}
const props = {}
typeof (icon) === 'object' ? props.component = icon : props.type = icon
return (
<Icon {... { props } }/>
)
|
|
188
189
|
}
},
|
|
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
render () {
const { mode, theme, menu } = this
const props = {
mode: mode,
theme: theme,
openKeys: this.openKeys
}
const on = {
select: obj => {
this.selectedKeys = obj.selectedKeys
this.$emit('select', obj)
},
openChange: this.onOpenChange
}
const menuTree = menu.map(item => {
if (item.hidden) {
return null
}
return this.renderItem(item)
})
// {...{ props, on: on }}
return (
<Menu vModel={this.selectedKeys} {...{ props, on: on }}>
{menuTree}
</Menu>
|
|
217
218
|
)
}
|
|
219
|
}
|