Unverified Commit 7eb46668 by Sendya

feat: dynamic menu

parent 4e827600
{
"message": "",
"result": [
{
"title": "首页",
"key": "",
"name": "index",
"component": "BasicLayout",
"redirect": "/dashboard/workplace",
"children": [
{
"title": "仪表盘",
"key": "dashboard",
"component": "RouteView",
"icon": "dashboard",
"children": [
{
"title": "分析页",
"key": "analysis",
"icon": ""
},
{
"title": "监控页",
"key": "monitor",
"icon": ""
},
{
"title": "工作台",
"key": "workplace",
"icon": ""
}
]
},
{
"title": "系统管理",
"key": "system",
"component": "PageView",
"icon": "setting",
"children": [
{
"title": "用户管理",
"key": "userList"
},
{
"title": "角色管理",
"key": "roleList"
},
{
"title": "权限管理",
"key": "tableList"
}
]
}
]
}
],
"status": 200,
"timestamp": 1534844188679
}
\ No newline at end of file
......@@ -21,13 +21,12 @@ router.beforeEach((to, from, next) => {
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
store
.dispatch('GetInfo')
store.dispatch('GetInfo')
.then(res => {
const roles = res.result && res.result.role
// 调用 vuex 的 从后端获取用户的路由菜单,动态添加可访问路由表
store.dispatch('GenerateRoutes', { roles }).then(() => {
// 根据roles权限生成可访问的路由表
// 动态添加可访问路由表
// 把已获取到的路由菜单加入到路由表中
router.addRoutes(store.getters.addRouters)
const redirect = decodeURIComponent(from.query.redirect || to.path)
if (to.path === redirect) {
......
import { asyncRouterMap, constantRouterMap } from '@/config/router.config'
/**
* 过滤账户是否拥有某一个权限,并将菜单从加载列表移除
*
* @param permission
* @param route
* @returns {boolean}
*/
function hasPermission (permission, route) {
if (route.meta && route.meta.permission) {
let flag = false
for (let i = 0, len = permission.length; i < len; i++) {
flag = route.meta.permission.includes(permission[i])
if (flag) {
return true
}
}
return false
}
return true
}
/**
* 单账户多角色时,使用该方法可过滤角色不存在的菜单
*
* @param roles
* @param route
* @returns {*}
*/
// eslint-disable-next-line
function hasRole(roles, route) {
if (route.meta && route.meta.roles) {
return route.meta.roles.includes(roles.id)
} else {
return true
}
}
function filterAsyncRouter (routerMap, roles) {
const accessedRouters = routerMap.filter(route => {
if (hasPermission(roles.permissionList, route)) {
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, roles)
}
return true
}
return false
})
return accessedRouters
}
import { constantRouterMap } from '@/config/router.config'
import { generatorDynamicRouter } from '@/utils/routerUtil'
const permission = {
state: {
......@@ -62,13 +13,20 @@ const permission = {
}
},
actions: {
/**
* 构建获取和构建路由和菜单信息
* @param commit
* @param data
* @returns {Promise<any>}
* @constructor
*/
GenerateRoutes ({ commit }, data) {
return new Promise(resolve => {
const { roles } = data
const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
commit('SET_ROUTERS', accessedRouters)
generatorDynamicRouter(data).then(routers => {
commit('SET_ROUTERS', routers)
resolve()
})
})
}
}
}
......
import { axios } from '@/utils/request'
// eslint-disable-next-line
import { UserLayout, BasicLayout, RouteView, BlankLayout, PageView } from '@/layouts'
// 前端路由表
const constantRouterComponents = {
// 基础页面 layout 必须引入
BasicLayout: BasicLayout,
BlankLayout: BlankLayout,
RouteView: RouteView,
PageView: PageView,
// 你需要动态引入的页面组件
analysis: () => import('@/views/dashboard/Analysis'),
workplace: () => import('@/views/dashboard/Workplace'),
monitor: () => import('@/views/dashboard/Monitor')
// ...more
}
// 前端未找到页面路由(固定不用改)
const notFoundRouter = {
path: '*', redirect: '/404', hidden: true
}
/**
* 获取后端路由信息的 axios API
* @returns {Promise}
*/
export const getRouterByUser = () => {
return axios({
url: '/user/dynamic-menu',
method: 'get'
/* headers: {
'Access-Token': 'xxx'
}
*/
})
}
/**
* 获取路由菜单信息
*
* 1. 调用 getRouterByUser() 访问后端接口获得路由结构数组
* @see https://github.com/sendya/ant-design-pro-vue/blob/feature/dynamic-menu/public/dynamic-menu.json
* 2. 调用
* @returns {Promise<any>}
*/
export const generatorDynamicRouter = () => {
return new Promise((resolve, reject) => {
// ajax
getRouterByUser().then(res => {
const result = res.result
const routers = generator(result)
routers.push(notFoundRouter)
resolve(routers)
}).catch(err => {
reject(err)
})
})
}
/**
* 格式化 后端 结构信息并递归生成层级路由表
*
* @param routerMap
* @param parent
* @returns {*}
*/
export const generator = (routerMap, parent) => {
return routerMap.map(item => {
const currentRouter = {
// 路由地址 动态拼接生成如 /dashboard/workplace
path: `${parent && parent.path || ''}/${item.key}`,
// 路由名称,建议唯一
name: item.name || item.key || '',
// 该路由对应页面的 组件
component: constantRouterComponents[item.component || item.key],
// meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
meta: { title: item.title, icon: item.icon || undefined, permission: item.key && [ item.key ] || null }
}
// 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
currentRouter.path = currentRouter.path.replace('//', '/')
// 重定向
item.redirect && (currentRouter.redirect = item.redirect)
// 是否有子菜单,并递归处理
if (item.children && item.children.length > 0) {
// Recursion
currentRouter.children = generator(item.children, currentRouter)
}
return currentRouter
})
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment