最小改动接入后台实现根据权限动态加载菜单

改动代码片段 + 注释说明

import {list as getRoutes} from ‘@/api/admin/menu’
import Layout from ‘@/layout’

generateRoutes({commit}, roles) {
return new Promise(resolve => {
// 请求后台数据替换src/router/index.js的asyncRoutes异步路由
getRoutes({mode: 3}).then(response => {
// filterAsyncRoutes方法作权限过滤和数据转换,roles为登录用户角色ID集合,如:[1,2]
let accessedRoutes = filterAsyncRoutes(response.data, roles)
commit(‘SET_ROUTES’, accessedRoutes)
resolve(accessedRoutes)
})
})
}

// 递归权限过滤和数据转换
export function filterAsyncRoutes(routes, roles) {
const res = []
routes.forEach(route => {
const tmp = {…route}
if (hasPermission(roles, tmp)) {
const component = tmp.component
if (route.component) {
if (component == ‘Layout’) {
tmp.component = Layout
} else {
// 接口组件字符串转换成组件对象
tmp.component = (resolve) => require([@/views/${component}], resolve)
}
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
}
res.push(tmp)
}
})
return res
}

三. 后端接口

  1. 接口数据分析
    接下来通过后台接口替换配置在src/router/index.js文件中asyncRoutes异步路由。

首先分析下异步路由的数据结构:

通过对上图异步路由的数据观察和了解,得出以下几点:

path在子路由中前面没有反斜杠’/’
根菜单的alwaysShow为true
component组件需通过import完成编译时导入,接口只能返回组件路径字符串,所以这里在接口请求完成后必须有一个组件路径字符串到组件对象的转换过程
meta的roles属性对应的是有该路由访问权限角色唯一标识的集合,这里我使用的是角色ID
2. 接口实现
完成以上的数据分析,接下来就是接口的具体实现了,有关SQL和完整代码请点击 有来商城 youlai-mall 拉取即可,以下仅仅贴出关键代码和分析。

SysMenuMapper

获取菜单列表和对应访问权限的角色ID的集合

SysMenuServiceImpl

将菜单转换成路由,递归生成父子结构树

SysMenuController

REST对外提供接口

  1. 接口测试
    使用接口测试工具测试, http://localhost:9999/youlai-admin/menus?mode=3 ,这里通过网关方式访问,详情请知悉有来商城 youlai-mall 项目。

完整返回数据,看看是不是很匹配asyncRoutes异步路由的数据格式了

{
“code”: “00000”,
“data”: [{
“path”: “/admin”,
“component”: “Layout”,
“alwaysShow”: true,
“name”: “系统管理”,
“meta”: {
“title”: “系统管理”,
“icon”: “documentation”,
“roles”: [2, 1]
},
“children”: [{
“path”: “user”,
“component”: “admin/user”,
“alwaysShow”: false,
“name”: “用户管理”,
“meta”: {
“title”: “用户管理”,
“icon”: “user”,
“roles”: [1]
}
}, {
“path”: “role”,
“component”: “admin/role”,
“alwaysShow”: false,
“name”: “角色管理”,
“meta”: {
“title”: “角色管理”,
“icon”: “peoples”,
“roles”: [2, 1]
}
}, {
“path”: “dept”,
“component”: “admin/dept”,
“alwaysShow”: false,
“name”: “部门管理”,
“meta”: {
“title”: “部门管理”,
“icon”: “tree”,
“roles”: [1, 2]
}
}, {
“path”: “menu”,
“component”: “admin/menu”,
“alwaysShow”: false,
“name”: “菜单管理”,
“meta”: {
“title”: “菜单管理”,
“icon”: “tree-table”,
“roles”: [1, 2]
}
}, {
“path”: “dict”,
“component”: “admin/dict”,
“alwaysShow”: false,
“name”: “字典管理”,
“meta”: {
“title”: “字典管理”,
“icon”: “education”,
“roles”: [1, 2]
}
}]
}],
“msg”: “一切ok”
}
最后要做的就是将组件(component)路径字符串转换成组件对象即可,再次贴出在上文permission.js改造的代码:

if (component == ‘Layout’) {
tmp.component = Layout
} else {
// 接口组件字符串转换成组件对象
tmp.component = (resolve) => require([@/views/${component}], resolve)
}
有一点需要注意的是上面组件动态导入不能使用import,如下:

tmp.component = () => import(@/views/${component})
不然会报以下错误

Error: Cannot find module ‘@/views/***’
原因是webpack不支持import动态导入了,但是之前确实是可以的,所以有些让人想不通,这里使用require动态导入组件即可。
亚马逊测评 www.yisuping.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值