vue-element-admin-4.2.0 动态路由的使用记录
修改router.js
import Vue from 'vue'
import Router from 'vue-router'
/* Layout */
import Layout from '@/layout'
/* Router Modules */
Vue.use(Router)
/**
* Note: sub-menu only appear when route children.length >= 1
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
*
* hidden: true if set true, item will not show in the sidebar(default is false)
* alwaysShow: true if set true, will always show the root menu
* if not set alwaysShow, when item has more than one children route,
* it will becomes nested mode, otherwise not show the root menu
* redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
* name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name' the icon show in the sidebar
noCache: true if set true, the page will no be cached(default is false)
affix: true if set true, the tag will affix in the tags-view
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
}
*/
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/auth-redirect',
component: () => import('@/views/login/auth-redirect'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/error-page/404'),
hidden: true
},
{
path: '/401',
component: () => import('@/views/error-page/401'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
}
]
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () => new Router({
mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
修改permission.js
注意permission.js中用到的 getAuthMenu()
这个是查询封装好数据结构的菜单接口
import {asyncRoutes, constantRoutes} from '@/router'
import {getAuthMenu} from '@/api/user'
import Layout from '@/layout'
/**
* Use meta.role to determine if the current user has permission
* @param roles
* @param route
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
/**
* 后台查询的菜单数据拼装成路由格式的数据
* @param routes
*/
export function generaMenu(routes, data) {
data.forEach(item => {
const menu = {
path: item.path,
//component: item.component === '#' ? Layout : () => import(`@/views${item.component}`), 已失效
component: item.component === '#' ? Layout : (resolve) => require([`@/views${item.component}`], resolve),
hidden: item.hidden,
children: [],
name: 'menu_' + item.id,
//alwaysShow: item.alwaysShow,
//redirect: item.redirect,
meta: {icon: item.icon, title: item.title}
}
if (item.children) {
generaMenu(menu.children, item.children)
}
routes.push(menu)
})
}
/**
* Filter asynchronous routing tables by recursion
* @param routes asyncRoutes
* @param roles
*/
export function filterAsyncRoutes(routes, roles) {
const res = []
routes.forEach(route => {
const tmp = {...route}
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})
return res
}
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
}
const actions = {
generateRoutes({commit}, roles) {
return new Promise(resolve => {
const loadMenuData = []
// 先查询后台并返回左侧菜单数据并把数据添加到路由
getAuthMenu(state.token).then(response => {
let data = response
if (response.code !== 20000) {
alert(JSON.stringify('菜单数据加载异常'))
// throw new Error('菜单数据加载异常')
} else {
data = response.data.data
Object.assign(loadMenuData, data)
const tempAsyncRoutes = Object.assign([], asyncRoutes)
// tempAsyncRoutes = asyncRoutes
generaMenu(tempAsyncRoutes, loadMenuData)
let accessedRoutes
if (roles.includes('admin')) {
// alert(JSON.stringify(asyncRoutes))
accessedRoutes = tempAsyncRoutes || []
} else {
accessedRoutes = filterAsyncRoutes(tempAsyncRoutes, roles)
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
}
// generaMenu(asyncRoutes, data)
}).catch(error => {
console.log(error)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
返回数据格式参考
{
"success": true,
"code": 20000,
"message": "成功",
"data": {
"data": [{
"id": 1,
"component": "#",
"path": "/organize",
"pid": 0,
"icon": "user",
"title": "组织管理",
"hidden": 0,
"children": [{
"id": 2,
"component": "/organize/facilitator/list",
"path": "/facilitators",
"pid": 1,
"icon": "theme",
"title": "服务商管理",
"hidden": 0,
"children": []
}, {
"id": 3,
"component": "/organize/facilitator/fasign",
"path": "/facilitatorsign",
"pid": 1,
"icon": "skill",
"title": "服务商签约",
"hidden": 0,
"children": []
}]
}
}
}
实体类对象
/**
* 权限表
* @author D.c_h
* @since 2021-05-25
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="Menu对象", description="权限表")
public class Menu implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "组件名")
private String component;
@ApiModelProperty(value = "菜单路径")
private String path;
@ApiModelProperty(value = "父级id")
private Integer pid;
@ApiModelProperty(value = "图标")
private String icon;
@ApiModelProperty(value = "菜单名")
private String title;
@ApiModelProperty(value = "是否隐藏")
private Integer hidden;
}
mysql表结构(测试用)
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for menu
-- ----------------------------
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`component` varchar(111) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '组件名',
`path` varchar(111) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单路径',
`pid` int(11) NULL DEFAULT NULL COMMENT '父级id',
`icon` varchar(22) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图标',
`title` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单名',
`hidden` tinyint(4) NULL DEFAULT NULL COMMENT '是否隐藏',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '权限表' ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
注意
别忘了api文件夹下user.js 要有getAuthMenu()方法,当然你也可以取别的名字^^
参考链接: https://blog.csdn.net/guyan0319/article/details/104632465/