赞
踩
本项目采用的模板为vue-element-admin i18n分支
在网上看了很多教程,发现都写的很复杂(本人比较菜) , 用尽千辛万苦终于实现了这个功能
首先修改src/store/modules目录下的permission.js文件
为了区分,下面先附上原文件代码
import { asyncRoutes, constantRoutes } from '@/router' /** * 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 } } /** * 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 => { let accessedRoutes if (roles.includes('admin')) { accessedRoutes = asyncRoutes || [] } else { accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) } commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) } } export default { namespaced: true, state, mutations, actions }
下面附上修改后的代码
```java ```java import { asyncRoutes, constantRoutes } from '@/router' import { getMenu } from '@/api/menu' 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 * @param data */ export function generaMenu(routes, data) { const len = data.length // eslint-disable-next-line no-const-assign for (let i = 0; i < len; i++) { /* alert(data[i].path) alert(data[i].meta.title)*/ const menu = { path: data[i].path + '', // component: () => import(`${item.component}`), component: Layout, alwaysShow: data[i].alwaysShow, redirect: data[i].redirect + '', name: data[i].name + '', // hidden: true, meta: { title: data[i].meta.title + '', icon: data[i].meta.icon }, children: [] } // alert('data[i].children' + data[i].children) if (data[i].children) { const children = data[i].children for (let j = 0; j < children.length; j++) { const viewPath = children[j].component const childrenList = { path: children[j].path + '', component: (resolve) => require([`@/views/${viewPath}`], resolve), name: children[j].name + '', // hidden: true, // component: () => import(`@/views/${viewPath}`), meta: { title: children[j].meta.title + '', icon: children[j].meta.icon } } menu.children.push(childrenList) } } routes.push(menu) /* data.forEach(item => { alert(JSON.stringify(item)) const menu = { path: item.path + '', // component: () => import(`${item.component}`), component: Layout, name: item.name + '', // hidden: true, meta: { title: item.title + '', icon: item.icon, roles: ['admin'] }, children: [] } if (item.children) { const children = data.children children.forEach(item1 => { const childrenList = { path: item1.path + '', component: () => import(`${item1.component}`), name: item1.name + '', // hidden: true, meta: { title: item1.title + '', icon: item1.icon, roles: ['admin'] } } menu.children.push(childrenList) }) } 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 => { // 先查询后台并返回左侧菜单数据并把数据添加到路由 getMenu().then(response => { const data = response.data // Object.assign(loadMenuData, data) generaMenu(asyncRoutes, data) let accessedRoutes if (roles.includes('admin')) { // alert(JSON.stringify(asyncRoutes)) accessedRoutes = asyncRoutes || [] } else { accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) } commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) // generaMenu(asyncRoutes, data) }).catch(error => { console.log(error) }) }) } } /* const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { let accessedRoutes if (roles.includes('admin')) { console.log('asyncRoutes' + asyncRoutes) accessedRoutes = asyncRoutes || [] console.log('accessedRoutes' + accessedRoutes) } else { accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) } commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) } }*/ export default { namespaced: true, state, mutations, actions }
代码详细介绍
引入后台接口的方法(也就是封装好的axios,然后把接口统一写在一个js文件里,用的时候直接引入,方便后期维护)
首先在@/api目录下(也就是src/api目录)新建menu.js文件,定义一个方法用来获取数据
import request from '@/utils/request'
export function getMenu() {
return request({
url: '/menu/selectMenu',
method: 'post',
})
}
然后在@/store/moudles下的permission.js中引入
import { getMenu } from '@/api/menu'
1
改写actions.generateRoutes方法
思路: 首先调用接口getMenu从后台获取数据,利generaMenu(asyncRoutes, data) 方法组织数据结构为routes的数据结构(generaMenu为自定义的方法)
const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { // 先查询后台并返回左侧菜单数据并把数据添加到路由 getMenu().then(response => { const data = response.data // Object.assign(loadMenuData, data) generaMenu(asyncRoutes, data) let accessedRoutes if (roles.includes('admin')) { // alert(JSON.stringify(asyncRoutes)) accessedRoutes = asyncRoutes || [] } else { accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) } commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) // generaMenu(asyncRoutes, data) }).catch(error => { console.log(error) }) }) } }
3.编写generaMenu方法
思路: 就是把获取的数据转换为routes的格式,如下,更加详细的请看目录@/router/index.js下的数据结构
这里只给出示例,因为我的数据当时在编写的时候就在后台进行转换了,所以我的转换方法并不适用你们自己的!
请自行编写转换方法思路!!!!
请自行编写转换方法思路!!!!
请自行编写转换方法思路!!!!
数据结构:
{
path: '/documentation',
component: Layout,
children: [
{
path: 'index',
component: () => import('@/views/documentation/index'),
name: 'Documentation',
meta: { title: 'documentation', icon: 'documentation', affix: true }
}
]
}
generaMenu方法代码
export function generaMenu(routes, data) { const len = data.length // eslint-disable-next-line no-const-assign for (let i = 0; i < len; i++) { /* alert(data[i].path) alert(data[i].meta.title)*/ const menu = { path: data[i].path + '', // component: () => import(`${item.component}`), component: Layout, alwaysShow: data[i].alwaysShow, redirect: data[i].redirect + '', name: data[i].name + '', // hidden: true, meta: { title: data[i].meta.title + '', icon: data[i].meta.icon }, children: [] } // alert('data[i].children' + data[i].children) if (data[i].children) { const children = data[i].children for (let j = 0; j < children.length; j++) { const viewPath = children[j].component const childrenList = { path: children[j].path + '', component: (resolve) => require([`@/views/${viewPath}`], resolve), name: children[j].name + '', // hidden: true, // component: () => import(`@/views/${viewPath}`), meta: { title: children[j].meta.title + '', icon: children[j].meta.icon } } menu.children.push(childrenList) } } routes.push(menu) } }
对应的数据库表结构
请自行编写转换方法思路!!!!
请自行编写转换方法思路!!!!
请自行编写转换方法思路!!!!
需要引入Layoutimport Layout from ‘@/layout’
只要可以把数据转换为规定的结构即可!!
根据角色权限动态生成路由菜单
在以上基础上只需要修改接口接收role参数,然后把参数传入后台,后台根据角色信息返回该角色可访问的菜单列表即可
export function getMenu(data) {
return request({
url: '/menu/selectMenu',
method: 'post',
params: data
})
}
const roleName = roles[0]
getMenu({ roleName: roleName }).then(response => {
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。