在网上看了很多教程,写的很乱,代码也没有给全。通过对比多篇博客,最终整理出了这篇文章,详细介绍了修改的过程。
一、概述
vue模板:vue-admin-template-4.4.0
1.1 效果展示
根据当前登录用户的角色信息生成对应的菜单栏。
比如,student可以查看到的菜单栏:
admin可以查看的菜单栏:
1.2 原理简单说明(选读)
可以最后读这部分内容加深对角色权限路由的理解
📌 项目中的路由均写在src\router\index.js 中,其中默认包含constantRoutes ,这就是我们需要解析的固定路由,无论用户的角色是什么,都需要显示这些路由内容。
export const constantRoutes = [
...
]
为了根据权限动态的生成路由,我们需要添加asyncRoutes ,这里面的内容将根据用户角色权限会动态生成。
export const asyncRoutes = [
...
]
📌 在src\store\modules\permission.js 中,通过分析asyncRoutes 里面的角色权限和当前用户所拥有的角色权限,生成用户可查看到的路由列表permission_routes 。
📌 在src\layout\components\Sidebar\index.vue 中,遍历permission_routes 显示菜单栏。
二、后端响应(选读)
前端的每一个请求的操作之前都会获取的用户信息,获取用户的用户名(name)、头像(avatar)和角色(roles)。
项目默认只需要name和avatar,现在我们添加了角色roles。
此时获取用户的响应是这样的。
{
"msg":"成功",
"code":20000,
"roles":["admin"],
"name":"admin",
"avatar":"http://www.weixintouxiang.cn/weixin/20140607090832328.gif"
}
三、配置(正文)
要修改以下7个文件:
文件名 | 修改方式 | 作用 |
---|
src\router\index.js | 修改 | 路由设置 | src\store\modules\user.js | 修改 | 获取角色信息 | src\store\modules\permission.js | 增加 | 根据角色解析路由 | src\store\getters.js | 修改 | VUEX的Getters | src\store\index.js | 修改 | 设置所需的VUEX模块 | src\permission.js | 修改 | 权限逻辑修改 | src\layout\components\Sidebar\index.vue | 修改 | 侧边栏解析修改 |
3.1 src\router\index.js
固定路由的写法,不需要任何权限,所有角色都可以访问。
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/index',
hidden: true,
children: [{
path: 'index',
component: () => import('@/views/index/index')
}]
}
]
需要我们添加的地方,根据权限显示的路由
export const asyncRoutes = [
{
path: '/webManage',
component: Layout,
meta: { roles: ['admin'] },
children: [
{
path: 'index',
name: '网站管理',
component: () => import('@/views/webManage/index'),
meta: { title: '网站管理', icon: 'cog-fill' }
}
]
},
{ path: '*', redirect: '/404', hidden: true }
]
通过修改meta 属性中roles
只有admin角色可以查看:
meta: { roles: ['admin'] }
admin和manager都可以查看
meta: { roles: ['admin', 'manager] }
注意:{ path: '*', redirect: '/404', hidden: true } 必须放在最后面,并且只能放在asyncRoutes 中,如果放在constantRoutes 中的话,刷新页面会报404。
3.3 src\store\modules\user.js
修改以下部分:
2.4 src\store\modules\permission.js
添加该文件:
import { asyncRoutes, constantRoutes } from '@/router'
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
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 accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
2.5 src\store\getters.js
修改以下部分:
2.6 src\permission.js
替换以下文件:
import router, { constantRoutes } from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login']
router.beforeEach(async(to, from, next) => {
NProgress.start()
document.title = getPageTitle(to.meta.title)
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
const { roles } = await store.dispatch('user/getInfo')
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
router.options.routes = constantRoutes.concat(accessRoutes)
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
} catch (error) {
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
2.7 src\layout\components\Sidebar\index.vue
修改以下内容:
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
|