Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
Starter Web Vue
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
product
kim3-web-vue
Starter Web Vue
Commits
c9eb73e3
Commit
c9eb73e3
authored
Jul 05, 2021
by
水落(YangLei)
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 菜单权限代码处理
parent
8816e72c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
118 additions
and
126 deletions
+118
-126
src/components/menu/SideMenu.vue
src/components/menu/SideMenu.vue
+11
-3
src/components/menu/menu.js
src/components/menu/menu.js
+90
-113
src/pages/frame/layouts/AdminLayout.vue
src/pages/frame/layouts/AdminLayout.vue
+8
-3
src/utils/index.js
src/utils/index.js
+5
-1
src/utils/routerUtil.js
src/utils/routerUtil.js
+4
-6
No files found.
src/components/menu/SideMenu.vue
View file @
c9eb73e3
<
template
>
<a-layout-sider
:theme=
"sideTheme"
:class=
"['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']"
width=
"256px"
:collapsible=
"collapsible"
v-model=
"collapsed"
:trigger=
"null"
>
<a-layout-sider
:theme=
"sideTheme"
:class=
"['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']"
width=
"256px"
:collapsible=
"collapsible"
v-model=
"collapsed"
:trigger=
"null"
>
<div
:class=
"['logo', theme]"
>
<router-link
to=
"/dashboard/workplace"
>
<img
src=
"@/assets/img/logo.png"
>
<h1>
{{
systemName
}}
</h1>
<img
src=
"@/assets/img/logo.png"
/
>
<h1>
{{
systemName
}}
</h1>
</router-link>
</div>
<i-menu
:theme=
"theme"
:collapsed=
"collapsed"
:options=
"menuData"
@
select=
"onSelect"
class=
"menu"
/>
...
...
@@ -13,6 +20,7 @@
<
script
>
import
IMenu
from
'
./menu
'
;
import
{
mapState
}
from
'
vuex
'
;
export
default
{
name
:
'
SideMenu
'
,
components
:
{
IMenu
},
...
...
src/components/menu/menu.js
View file @
c9eb73e3
...
...
@@ -27,19 +27,18 @@
* i18n: {
* messages: {
* zh_CN: {dashboard: {name: '监控中心'}}
*
*
* }
* }
**/
import
Menu
from
"
ant-design-vue/es/menu
"
;
import
Icon
from
"
ant-design-vue/es/icon
"
;
import
fastEqual
from
"
fast-deep-equal
"
;
import
{
getI18nKey
}
from
'
@/utils/routerUtil
'
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
"
,
name
:
'
IMenu
'
,
props
:
{
options
:
{
type
:
Array
,
...
...
@@ -48,12 +47,12 @@ export default {
theme
:
{
type
:
String
,
required
:
false
,
default
:
"
dark
"
,
default
:
'
dark
'
,
},
mode
:
{
type
:
String
,
required
:
false
,
default
:
"
inline
"
,
default
:
'
inline
'
,
},
collapsed
:
{
type
:
Boolean
,
...
...
@@ -61,43 +60,37 @@ export default {
default
:
false
,
},
i18n
:
Object
,
openKeys
:
Array
,
},
data
()
{
return
{
selectedKeys
:
[],
sOpenKeys
:
[],
cachedOpenKeys
:
[],
menuData
:
[],
};
},
computed
:
{
menuTheme
()
{
return
this
.
theme
==
"
light
"
?
this
.
theme
:
"
dark
"
;
return
this
.
theme
==
'
light
'
?
this
.
theme
:
'
dark
'
;
},
},
created
()
{
this
.
updateMenu
();
if
(
this
.
options
.
length
>
0
&&
!
this
.
options
[
0
].
fullPath
)
{
this
.
formatOptions
(
this
.
options
,
""
);
}
// 自定义国际化配置
if
(
this
.
i18n
&&
this
.
i18n
.
messages
)
{
const
messages
=
this
.
i18n
.
messages
;
Object
.
keys
(
messages
).
forEach
((
key
)
=>
{
this
.
$i18n
.
mergeLocaleMessage
(
key
,
messages
[
key
]);
});
}
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
:
{
options
(
val
)
{
if
(
val
.
length
>
0
&&
!
val
[
0
].
fullPath
)
{
this
.
formatOptions
(
this
.
options
,
""
);
}
},
i18n
(
val
)
{
if
(
val
&&
val
.
messages
)
{
const
messages
=
this
.
i18n
.
messages
;
Object
.
keys
(
messages
).
forEach
(
(
key
)
=>
{
Object
.
keys
(
messages
).
forEach
(
key
=>
{
this
.
$i18n
.
mergeLocaleMessage
(
key
,
messages
[
key
]);
});
}
...
...
@@ -114,112 +107,96 @@ export default {
this
.
updateMenu
();
},
sOpenKeys
(
val
)
{
this
.
$emit
(
"
openChange
"
,
val
);
this
.
$emit
(
"
update:openKeys
"
,
val
);
this
.
$emit
(
'
openChange
'
,
val
);
this
.
$emit
(
'
update:openKeys
'
,
val
);
},
},
methods
:
{
renderIcon
:
function
(
h
,
icon
,
key
)
{
if
(
this
.
$scopedSlots
.
icon
&&
icon
&&
icon
!==
"
none
"
)
{
renderIcon
(
h
,
icon
,
key
)
{
if
(
this
.
$scopedSlots
.
icon
&&
icon
&&
icon
!==
'
none
'
)
{
const
vnodes
=
this
.
$scopedSlots
.
icon
({
icon
,
key
});
vnodes
.
forEach
(
(
vnode
)
=>
{
vnodes
.
forEach
(
vnode
=>
{
vnode
.
data
.
class
=
vnode
.
data
.
class
?
vnode
.
data
.
class
:
[];
vnode
.
data
.
class
.
push
(
"
anticon
"
);
vnode
.
data
.
class
.
push
(
'
anticon
'
);
});
return
vnodes
;
}
return
!
icon
||
icon
==
"
none
"
?
null
:
h
(
Icon
,
{
props
:
{
type
:
icon
}
});
return
!
icon
||
icon
==
'
none
'
?
null
:
h
(
Icon
,
{
props
:
{
type
:
icon
}
});
},
renderMenuItem
:
function
(
h
,
menu
)
{
let
tag
=
"
router-link
"
;
le
t
config
=
{
props
:
{
to
:
menu
.
fullP
ath
},
attrs
:
{
style
:
"
overflow:hidden;white-space:normal;text-overflow:clip;
"
},
renderMenuItem
(
h
,
menu
)
{
const
tag
=
'
router-link
'
;
cons
t
config
=
{
props
:
{
to
:
menu
.
p
ath
},
attrs
:
{
style
:
'
overflow:hidden;white-space:normal;text-overflow:clip;
'
},
};
if
(
menu
.
meta
&&
menu
.
meta
.
link
)
{
tag
=
"
a
"
;
config
=
{
attrs
:
{
style
:
"
overflow:hidden;white-space:normal;text-overflow:clip;
"
,
href
:
menu
.
meta
.
link
,
target
:
"
_blank
"
,
},
};
}
return
h
(
Item
,
{
key
:
menu
.
fullPath
},
[
h
(
tag
,
config
,
[
this
.
renderIcon
(
h
,
menu
.
meta
?
menu
.
meta
.
icon
:
"
none
"
,
menu
.
fullPath
),
this
.
$t
(
getI18nKey
(
menu
.
fullPath
)),
]),
return
h
(
Item
,
{
key
:
menu
.
menuId
},
[
h
(
tag
,
config
,
[
this
.
renderIcon
(
h
,
menu
.
menuIcon
,
menu
.
menuId
),
menu
.
menuName
]),
]);
},
renderSubMenu
:
function
(
h
,
menu
)
{
let
this_
=
this
;
let
subItem
=
[
renderSubMenu
(
h
,
menu
)
{
const
subItem
=
[
h
(
"
span
"
,
{
slot
:
"
title
"
,
attrs
:
{
style
:
"
overflow:hidden;white-space:normal;text-overflow:clip;
"
}
},
[
this
.
renderIcon
(
h
,
menu
.
meta
?
menu
.
meta
.
icon
:
"
none
"
,
menu
.
fullPath
)
,
this
.
$t
(
getI18nKey
(
menu
.
fullPath
))
,
]
'
span
'
,
{
slot
:
'
title
'
,
attrs
:
{
style
:
'
overflow:hidden;white-space:normal;text-overflow:clip;
'
}
,
}
,
[
this
.
renderIcon
(
h
,
menu
.
menuIcon
,
menu
.
menuId
),
menu
.
menuName
],
),
];
le
t
itemArr
=
[];
menu
.
children
.
forEach
(
function
(
item
)
{
itemArr
.
push
(
this
_
.
renderItem
(
h
,
item
));
cons
t
itemArr
=
[];
menu
.
children
.
forEach
(
item
=>
{
itemArr
.
push
(
this
.
renderItem
(
h
,
item
));
});
return
h
(
SubMenu
,
{
key
:
menu
.
fullPath
},
subItem
.
concat
(
itemArr
));
},
renderItem
:
function
(
h
,
menu
)
{
const
meta
=
menu
.
meta
;
if
(
!
meta
||
!
meta
.
invisible
)
{
let
renderChildren
=
false
;
const
children
=
menu
.
children
;
if
(
children
!=
undefined
)
{
for
(
let
i
=
0
;
i
<
children
.
length
;
i
++
)
{
const
childMeta
=
children
[
i
].
meta
;
if
(
!
childMeta
||
!
childMeta
.
invisible
)
{
renderChildren
=
true
;
break
;
}
}
}
return
menu
.
children
&&
renderChildren
?
this
.
renderSubMenu
(
h
,
menu
)
:
this
.
renderMenuItem
(
h
,
menu
);
}
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
:
function
(
h
,
menuTree
)
{
let
this_
=
this
;
renderMenu
(
h
,
menuTree
)
{
let
menuArr
=
[];
menuTree
.
forEach
(
function
(
menu
,
i
)
{
menuArr
.
push
(
this
_
.
renderItem
(
h
,
menu
,
"
0
"
,
i
));
menuTree
.
forEach
(
(
menu
,
i
)
=>
{
menuArr
.
push
(
this
.
renderItem
(
h
,
menu
));
});
return
menuArr
;
},
formatOptions
(
options
,
parentPath
)
{
options
.
forEach
((
route
)
=>
{
let
isFullPath
=
route
.
path
.
substring
(
0
,
1
)
==
"
/
"
;
route
.
fullPath
=
isFullPath
?
route
.
path
:
parentPath
+
"
/
"
+
route
.
path
;
if
(
route
.
children
)
{
this
.
formatOptions
(
route
.
children
,
route
.
fullPath
);
}
});
},
updateMenu
()
{
const
matchedRoutes
=
this
.
$route
.
matched
.
filter
((
item
)
=>
item
.
path
!==
""
);
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
);
}
// 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
)
{
return
route
.
matched
.
map
((
item
)
=>
item
.
path
);
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
)
{
...
...
@@ -230,19 +207,19 @@ export default {
theme
:
this
.
menuTheme
,
mode
:
this
.
$props
.
mode
,
selectedKeys
:
this
.
selectedKeys
,
openKeys
:
this
.
openKeys
?
this
.
openKeys
:
this
.
sOpenKeys
,
openKeys
:
this
.
sOpenKeys
,
},
on
:
{
"
update:openKeys
"
:
(
val
)
=>
{
'
update:openKeys
'
:
val
=>
{
this
.
sOpenKeys
=
val
;
},
click
:
(
obj
)
=>
{
click
:
obj
=>
{
obj
.
selectedKeys
=
[
obj
.
key
];
this
.
$emit
(
"
select
"
,
obj
);
this
.
$emit
(
'
select
'
,
obj
);
},
},
},
this
.
renderMenu
(
h
,
this
.
options
)
this
.
renderMenu
(
h
,
this
.
options
)
,
);
},
};
src/pages/frame/layouts/AdminLayout.vue
View file @
c9eb73e3
...
...
@@ -23,7 +23,7 @@
v-if=
"fixedSideBar && !isMobile"
:style=
"`width: $
{sideMenuWidth}; min-width: ${sideMenuWidth};max-width: ${sideMenuWidth};`"
class="virtual-side"
>
</div
>
/
>
<drawer
v-if=
"!hideSettingExtend"
v-model=
"showSetting"
placement=
"right"
>
<div
class=
"setting"
slot=
"handler"
>
...
...
@@ -59,9 +59,10 @@
<
script
>
import
LayoutTopHeader
from
'
../components/header/LayoutTopHeader
'
;
import
Drawer
from
'
@/components/tool/Drawer
'
;
import
SideMenu
from
'
@/components/menu/SideMenu
'
;
import
SideMenu
from
'
@/components/menu/SideMenu
.vue
'
;
import
Setting
from
'
../components/setting/Setting
'
;
import
{
mapState
,
mapMutations
,
mapGetters
}
from
'
vuex
'
;
import
{
convertListToTree
,
getUserInfo
}
from
'
@/utils
'
;
// const minHeight = window.innerHeight - 64 - 122
...
...
@@ -74,6 +75,7 @@ export default {
collapsed
:
false
,
showSetting
:
false
,
drawerOpen
:
false
,
menuData
:
[],
};
},
provide
()
{
...
...
@@ -108,7 +110,7 @@ export default {
'
multiPage
'
,
]),
...
mapGetters
(
'
settingModule
'
,
[
'
firstMenu
'
,
'
subMenu
'
,
'
menuData
'
]),
...
mapGetters
(
'
settingModule
'
,
[
'
firstMenu
'
,
'
subMenu
'
]),
hideSettingExtend
()
{
if
(
this
.
hideSetting
===
false
&&
process
.
env
.
NODE_ENV
===
'
development
'
)
{
...
...
@@ -161,6 +163,9 @@ export default {
created
()
{
this
.
correctPageMinHeight
(
this
.
minHeight
-
24
);
this
.
setActivated
(
this
.
$route
);
const
userInfo
=
getUserInfo
();
const
menuData
=
convertListToTree
(
userInfo
?.
menuList
||
[],
false
,
true
);
this
.
menuData
=
menuData
;
},
beforeDestroy
()
{
this
.
correctPageMinHeight
(
-
this
.
minHeight
+
24
);
...
...
src/utils/index.js
View file @
c9eb73e3
...
...
@@ -34,12 +34,16 @@ export function clearUserInfo() {
* @param {Array} menuList 菜单列表
* @param {Boolean} filterMenu 是否过滤掉菜单,只保留目录
*/
export
function
convertListToTree
(
menuList
,
filterMenu
=
false
)
{
export
function
convertListToTree
(
menuList
,
filterMenu
=
false
,
toMenuData
=
false
)
{
let
tempMenu
=
[...
menuList
];
if
(
filterMenu
)
{
tempMenu
=
tempMenu
.
filter
(
m
=>
m
.
menuType
!==
'
MENU
'
);
}
for
(
const
menu
of
menuList
)
{
if
(
toMenuData
)
{
menu
.
name
=
menu
.
menuName
;
menu
.
path
=
menu
.
menuUrl
;
}
if
(
menu
.
parentMenuId
===
0
)
continue
;
const
parent
=
menuList
.
find
(
m
=>
m
.
menuId
===
menu
.
parentMenuId
);
parent
.
children
?
parent
.
children
.
push
(
menu
)
:
(
parent
.
children
=
[
menu
]);
...
...
src/utils/routerUtil.js
View file @
c9eb73e3
...
...
@@ -78,18 +78,16 @@ function loadRoutes(routesConfig) {
// 应用配置
const
{
router
,
store
,
i18n
}
=
appOptions
;
// 如果 routesConfig 有值,则更新到本地,否则从本地获取
if
(
routesConfig
)
{
store
.
commit
(
'
accountModule/setRoutesConfig
'
,
routesConfig
);
}
else
{
routesConfig
=
store
.
getters
[
'
accountModule/routesConfig
'
];
}
routesConfig
=
store
.
getters
[
'
accountModule/routesConfig
'
];
// 提取路由国际化数据
mergeI18nFromRoutes
(
i18n
,
router
.
options
.
routes
);
// 初始化Admin后台菜单数据
const
rootRoute
=
router
.
options
.
routes
.
find
(
item
=>
item
.
path
===
'
/
'
);
const
menuRoutes
=
rootRoute
&&
rootRoute
.
children
;
if
(
menuRoutes
)
{
store
.
commit
(
'
settingModule/setMenuData
'
,
menuRoutes
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment