1.首先看下项目结构,设置权限用到的文件(一个是在store下modules下面的permission.js和 src下的permission.js)
2.先看src下面的permisssion.js
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
try {
const hasRoles = store.getters.permission_routes && store.getters.permission_routes.length > 0
if (hasRoles) {//判断是否已经获取过菜单权限
next()
} else {
// 获取
const accessRoutes = await store.dispatch('permission/generateRoutes')
if (accessRoutes && accessRoutes.length > 0) {
// 重要 使用addRoutes
router.addRoutes(accessRoutes)
if (accessRoutes[0].path == '*') {
next({ path: '/401', replace: true })
} else {
next({ ...to, replace: true })
}
} else {
next({ path: '/401', replace: true })
}
}
} catch (error) {
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next('/login')
NProgress.done()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
NProgress.done()
}
}
})
3.store下面的permission.js
需要引入的其他js文件
import { asyncRoutes, constantRoutes } from '@/router'
import { logout, getInfo } from '@/api/user'
import { removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'
a.工具类
function hasPermission(roles, route) {
if (route.meta && route.meta.role) {
return roles.some(role => route.meta.role === role)
} else {
return true
}
}
function routeRedirect(routes) {
const obj = routes.find(v => v.path && v.children && v.children.length)
if (obj) {
const redirect = obj.path === '/' ? `/${obj.children[0].path}` : `${obj.path}/${obj.children[0].path}`
const index = routes.findIndex(v => v.path === '/')
if (index > -1) {
routes[index].redirect = redirect
} else {
const route = {
path: '/',
redirect: redirect,
hidden: true
}
routes.unshift(route)
}
}
return routes
}
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
}
b.权限实现
const state = {
routes: [],//权限
loginData: {}//登陆人信息
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.routes = constantRoutes.concat(routes)
},
SET_LOGIN_DATA: (state, loginData) => {
state.loginData = loginData
},
RESET_ROUTES: (state) => {
state.routes = []
}
}
const actions = {
// 获取权限菜单
generateRoutes({ commit }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const list = res.data.nodes
const roles = list.map(v => v.path)
let accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
accessedRoutes = routeRedirect(accessedRoutes)
commit('SET_ROUTES', accessedRoutes)
commit('SET_LOGIN_DATA', res.data)
resolve(accessedRoutes)
}).catch(error => {
reject(error)
})
})
},
logout({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
removeToken()
resetRouter()
commit('RESET_ROUTES')// 路由清空
resolve()
}).catch(error => {
reject(error)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
4.查看router.js 里面有两个数组。 第一个是 constantRoutes不需要权限,第二个是asyncRoutes需要权限。然后给每个需要权限的路由添加 meta对象,定义role属性,值为path。 下面是如何定义role。其实如果子路由 里面没有做权限就不需要 设置role。(我这里子路由也做了权限)
{
path: '/',
component: Layout,
meta: { title: '', role: '/' },//ROLE
children: [
{
path: '',
component: () => import('@/views/message/inbox'),
name: 'Inbox',
meta: { title: '', role: '/' },//ROLE
hidden: true,
children: [
{
path: 'inbox/detail/:id',
component: () => import('@/views/message/inbox-detail'),
name: 'InboxDetail',
meta: { title: '', activeMenu: '/' },
hidden: true
}
]
},
{
path: 'outbox',
component: () => import('@/views/message/outbox'),
name: 'Outbox',
meta: { title: '', activeMenu: '/', role: '/outbox' },//ROLE
hidden: true,
children: [
{
path: 'detail/:id',
component: () => import('@/views/message/outbox-detail'),
name: 'OutboxDetail',
meta: { title: '', activeMenu: '/' },
hidden: true
}
]
},
{
path: 'audit',
component: () => import('@/views/message/audit'),
name: 'Audit',
meta: { title: '', activeMenu: '/', role: '/audit' },//ROLE
hidden: true,
children: [
{
path: 'detail/:id',
component: () => import('@/views/message/audit-detail'),
name: 'AuditDetail',
meta: { title: '', activeMenu: '/' },
hidden: true
}
]
},
{
path: 'send/message',
component: () => import('@/views/message/send'),
name: 'SendMessage',
meta: { title: '', activeMenu: '/', role: '/send/message' },//ROLE
hidden: true,
children: [
{
path: 'detail',
component: () => import('@/views/message/send-detail'),
name: 'SendDetail',
meta: { title: '', activeMenu: '/' },
hidden: true
}
]
}
]
},
5.要把你的路由表整理一份给后端人员,path最重要。
下面是你需要给后端人员沟通给你返回的权限列表格式。(这里是我定的,用的时候也可以根据自己的习惯来) path对应mata里面的 role
1: {name: "收件箱", code: "001001", path: "/", type: "menu"}
2: {name: "发件箱", code: "001002", path: "/outbox", type: "menu"}
3: {name: "我的审核", code: "001003", path: "/audit", type: "menu"}
4: {name: "发消息", code: "001003", path: "/send/message", type: "menu"}
5: {name: "通讯录", code: "002", path: "/mail-list", type: "menu"}
6: {name: "认证情况", code: "002001", path: "/mail-list/authentication", type: "menu"}
10: {name: "系统设置", code: "003001", path: "/set-up/system", type: "menu"}
13: {name: "通知规则", code: "003001001", path: "/set-up/system?name=rule", type: "menu"}