vue-element-admin改为从后台拿动态路由(菜单)- 上
改为从后台拿动态路由,大概如下步骤:
1、后台增加接口,返回动态路由数据
2、前端增加请求动态路由接口请求
3、修改 src/route/index.js 去掉原有的动态路由,增加组件名和组件对象映射 map
4、修改 src/store/modules/permission.js 修改当前 权限判断处理方法 generateRoutes
一、后台增加接口
1、后台随便添加一个 Controller 随便加一个接口,添加如下代码。正常 str 内容应该从数据库中查询得到,为了避免信息量过多这里直接写一个 json 返回
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 | @RequestMapping (value = "/getPermission" , method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody @ApiOperation (value = "得到当前登录用户所有的权限(Route 菜单 + Permission 按钮)" , notes = "得到当前登录用户所有的权限(Route 菜单 + Permission 按钮)" ) public Response<User> getPermission() throws Exception { String str = "[\n" + " {\n" + " component: 'layout',\n" + " path: '/interface_test',\n" + " name: 'interface_test',\n" + " meta: { title: '接口测试', icon: 'el-icon-data-line' },\n" + " redirect: '/interface_test/test_case',\n" + " alwaysShow: true,\n" + " children: [\n" + " {\n" + " path: 'public_step',\n" + " name: 'public_step',\n" + " meta: { title: '公共步骤' },\n" + " component: 'public_step'\n" + " }\n" + " ]\n" + " }]" ; JSONArray jsonObject = JSONArray.parseArray(str); Map<String, Object> retMap = new HashMap<>(); retMap.put( "routes" , jsonObject); Response response = Response.success(retMap); return response; } |
2、使用 postman 等工具请求接口,返回如下。其中 code、data 可能跟你的包装有所不同,关键就是返回 routes 下的内容
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 | { "code" : 0 , "msg" : "请求成功" , "data" : { "routes" : [ { "redirect" : "/interface_test/test_case" , "path" : "/interface_test" , "component" : "layout" , "children" : [ { "path" : "public_step" , "component" : "public_step" , "meta" : { "title" : "公共步骤" }, "name" : "public_step" } ], "meta" : { "icon" : "el-icon-data-line" , "title" : "接口测试" }, "name" : "interface_test" , "alwaysShow" : true } ] } } |
二、前端增加接口请求
1、前端打开 src/api/role.js 文件,插入刚增加的接口请求,代码如下
1 2 3 4 5 6 | export function getPermission() { return request({ url: '/manage/role/getPermission', method: 'get' }) } |
三、去掉原有的动态路由,增加组件名和组件对象映射 map
我这里后续的代码是,将从后台请求回来的路由和 route/index.js 中的动态路由组合后一起做为当前路由返回,所以这里要删除之前增加的动态路由,如果你是替换那就不用管。
1、打开 src/route/index.js 文件
去掉之前引入的 router 组件
从 asyncRoutes 动态路由中删除之前的定义,只保留 404。如果你是替换 asyncRoutes 动态路由,那一定要在最后添加一个 404,要不然输入一个不存在的 url 后不会显示 404,而是一个白屏。
2、组件名和组件对象映射 map
由于后台请求回来的数据不是组件对象而是组件名称,所以要将名称转为 组件对象,这里定义的就是名称和对象的对应关系。代码如下
1 2 3 4 5 6 | // 组件名 和 组件对象 映射表,用于后续根据后台传过来的 组件名 替换成 组件对象 使用 export const componentMap = { 'layout': require('@/layout').default, 'test_case': () => import('@/views/functional_test/test_case_manage/test_case').then(m => m.default), 'public_step': () => import('@/views/functional_test/test_data_manage/public_step').then(m => m.default) } |
注:由于是通过组件名称对应,所以后台添加的组件名,一定要跟这里定义个名称一样。
四、权限判断处理方法 generateRoutes
1、打开 src/store/modules/permission.js 修改如下
增加 api 引用
修改 generateRoutes 权限判断
代码如下
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 37 38 39 40 41 42 43 44 | const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { // 从后台请求到的路由 getPermission().then(response => { // 整理后台返回的路由 let accessedRoutes = response.data.routes.filter(item => { return pruningRoutes(item) }) accessedRoutes = accessedRoutes.concat(asyncRoutes) // 合并异步路由(例如将404页面合并入可访问路由) accessedRoutes = filterAsyncRoutes(accessedRoutes, roles) // 通过递归根据角色过滤异步路由 commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) }) } } /** * 整理后台返回的路由 * @param route 路由 * @returns {{children}|*} */ function pruningRoutes(route) { // 路由中有 component 属性,将组件字符串转换为组件对象 if (route.component && typeof route.component === 'string') { route.component = componentMap[route.component] } // 路由中有 props 属性,将 props 字符串转换为 props 对象 if (route.props && typeof route.props === 'string') { route.props = JSON.parse(route.props) } // 路由中有 children,循环递归处理 children if (route.children && route.children.length > 0) { for (let i = 0; i < route.children.length; i++) { pruningRoutes(route.children[i]) } return route } else { delete route.children } } |
代码讲解
改动如下:
五、重启后效果如下
六、后续 - 数据库设计
这次只定义了 role、role_route、route、route_meta 表,后续的用户角色对应表、资源路由对应表等还没创建。表结构如下
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | CREATE TABLE `role` ( ` name ` varchar (50) NOT NULL COMMENT '角色名称' , ` desc ` varchar (50) NOT NULL COMMENT '角色描述' , `id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT '自增id' , `is_delete` bit (1) NOT NULL DEFAULT b '0' COMMENT '是否删除' , `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间' , `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT= '角色信息表' ; CREATE TABLE `role_route` ( `role_id` bigint (20) NOT NULL COMMENT '角色 id' , `route_id` bigint (20) NOT NULL COMMENT '路由信息' , `id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT '自增id' , `is_delete` bit (1) NOT NULL DEFAULT b '0' COMMENT '是否删除' , `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间' , `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8 COMMENT= '角色对应路由信息表' ; CREATE TABLE `route` ( `id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT '自增id' , `path` varchar (255) NOT NULL COMMENT '路由匹配的路径,注意根节点前要加/' , ` name ` varchar (255) NOT NULL COMMENT '路由的名称' , `component` varchar (255) NOT NULL COMMENT '对应加载的组件' , `redirect` varchar (255) DEFAULT NULL COMMENT '重定向的路由路径' , `hidden` bit (1) NOT NULL COMMENT '在菜单中是否隐藏。true:隐藏,默认 false' , `always_show` bit (1) NOT NULL COMMENT '是否始终显示根菜单。true:无论有没有子节点都显示,false:必须有子节点才显示' , `props` varchar (255) DEFAULT NULL COMMENT '传递数据的 props 属性' , `route_meta_id` bigint (20) NOT NULL COMMENT '元信息 id' , `parent_id` bigint (20) NOT NULL COMMENT '父分类的 id' , `sort` int (11) NOT NULL COMMENT '排序' , `is_delete` bit (1) NOT NULL DEFAULT b '0' COMMENT '是否删除' , `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间' , `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8 COMMENT= '路由信息表' ; CREATE TABLE `route_meta` ( `id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT '自增id' , `title` varchar (255) NOT NULL COMMENT '页面标题' , `icon` varchar (255) DEFAULT NULL COMMENT '图标' , `no_cache` bit (1) NOT NULL COMMENT '是否禁用缓存页面。true:禁止缓存页面(默认值为false)' , `affix` bit (1) NOT NULL COMMENT '标签视图中是否可关闭。true:不允许关闭(默认 false)' , `breadcrumb` bit (1) NOT NULL COMMENT '是否显示面包屑。false:不在面包屑中显示(默认值为 true)' , `is_delete` bit (1) NOT NULL DEFAULT b '0' COMMENT '是否删除' , `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间' , `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8 COMMENT= '路由 Meta 信息表' ; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!