vue-template-admin 页面权限管理
一、前言**在做后台管理系统的时候有幸搞了一下权限管理的功能,所以记录一下这个流程,我是用的是element 的模板vue-template-admin**二、使用步骤1.登录拦击(1)在src目录下创建权限文件夹(2)然后在main中引入(3)在登录成功之后请求getInfo接口获取用户信息(4)getInfo主要放在vuex的user文件中,里面共有Login,GetInfo,logout等接
一、前言
在做后台管理系统的时候有幸搞了一下权限管理的功能,所以记录一下这个流程,我是用的是element 的模板vue-template-admin
二、使用步骤
1.登录拦击
(1)在src目录下创建权限文件夹
(2)然后在main中引入
(3)在登录成功之后必须请求getInfo接口获取用户信息,
(4)getInfo主要放在vuex的user文件中,里面共有Login,GetInfo,logout等接口。GetInfo获取用户信息并存储用户信息之后,接着调用GenerateUserRoutes函数,此函数将根据menuList来过滤掉没有权限的路由
user.js的文件内容为
import { login,logout,getInfo} from '@/api/user'
import cookieUtils from '../../utils/auth'
// eslint-disable-next-line no-unused-vars
import router from '../../router/index'
// eslint-disable-next-line no-unused-vars
import store from '../../store'
import wutong from '@/assets/img/wutong_img.png'
const getDefaultState = () => {
return {
nickname: '',
userId: '',
// avatar: 'https://www.gravatar.com/avatar/6560ed55e62396e40b34aac1e5041028',
avatar: wutong,
roleName: '',
menus: [],
permissions: []
}
}
const state = getDefaultState()
const mutations = {
SET_USER: (state, userInfo) => {
state.nickname = userInfo.nickname
state.userId = userInfo.userId
state.roleName = userInfo.roleName
state.menus = userInfo.menuList
state.permissions = userInfo.permissionList
},
RESET_USER: (state) => {
state.nickname = ''
state.userId = ''
state.roleName = ''
state.menus = []
state.permissions = []
}
}
const actions = {
// user login
Login({
commit
}, loginForm) {
return new Promise((resolve, reject) => {
login(loginForm).then(res => {
if (res.code === '0') {
// cookie中保存前端登录状态
cookieUtils.setJwtToken(res.info.token, '480min')
cookieUtils.setUserType(res.info.type, '480min')
resolve(res)
} else {
window.sessionStorage.removeItem('overdueloan')
reject(res)
}
}).catch(error => {
reject(error)
})
})
},
// get user info
GetInfo({
commit,
state
}) {
return new Promise((resolve, reject) => {
getInfo().then(data => {
// console.log('get User Info: ', data)
// 账号在其他地方登录
if (!data) {
commit('RESET_USER')
window.sessionStorage.removeItem('overdueloan')
// must remove token first
cookieUtils.removeJwtToken()
cookieUtils.removeUserType()
router.push({ path: '/login' })
return
}
// 储存用户信息
commit('SET_USER', data.data.userPermission)
// cookie保存登录状态,仅靠vuex保存的话,页面刷新就会丢失登录状态
// 生成路由
const userPermission = data.data.userPermission
store.dispatch('GenerateUserRoutes', userPermission).then(() => {
// 生成该用户的新路由json操作完毕之后,调用vue-router的动态新增路由方法,将新路由添加
router.addRoutes(store.getters.addRouters)
})
resolve(data)
})
// .catch(error => {
// reject(error)
// })
})
},
// user logout
logout({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then((res) => {
commit('RESET_USER')
window.sessionStorage.removeItem('overdueloan')
// must remove token first
cookieUtils.removeJwtToken()
cookieUtils.removeUserType()
resolve(res)
}).catch(error => {
reject(error)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
getInfo返回的内容为
2.权限路由过滤
(1)此GenerateUserRoutes函数,主要在store的permission.js文件内
(2)store的permission.js文件内内容为:
import { asyncRouterMap, constantRouterMap } from '@/router/index'
/**
* 判断用户是否拥有此菜单
* @param menus
* @param route
*/
function hasPermission(menus, route) {
if (route.menu) {
/*
* 如果这个路由有menu属性,就需要判断用户是否拥有此menu权限
*/
return menus.indexOf(route.menu) > -1
} else {
return true
}
}
/**
* 递归过滤异步路由表,返回符合用户菜单权限的路由表
* @param asyncRouterMap
* @param menus
*/
function filterAsyncRouter(asyncRouterMap, menus) {
const accessedRouters = asyncRouterMap.filter(route => {
// filter,js语法里数组的过滤筛选方法
if (hasPermission(menus, route)) {
if (route.children && route.children.length) {
// 如果这个路由下面还有下一级的话,就递归调用
route.children = filterAsyncRouter(route.children, menus)
// 如果过滤一圈后,没有子元素了,这个父级菜单就也不显示了
return (route.children && route.children.length)
}
return true
}
return false
})
return accessedRouters
}
const permission = {
state: {
routers: constantRouterMap, // 本用户所有的路由,包括了固定的路由和下面的addRouters
addRouters: [], // 本用户的角色赋予的新增的动态路由
jwtToken: ''
},
mutations: {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers) // 将固定路由和新增路由进行合并, 成为本用户最终的全部路由信息
}
},
actions: {
GenerateUserRoutes({ commit }, userPermission) {
// 生成路由
return new Promise(resolve => {
// roles是后台传过来的角色数组,比如['管理员','文章']
const role = userPermission.roleName
const menus = userPermission.menuList
// 声明 该角色可用的路由
let accessedRouters
if (role === '管理员') {
// 如果角色里包含'管理员',那么所有的路由都可以用
// 其实管理员也拥有全部菜单,这里主要是利用角色判断,节省加载时间
accessedRouters = asyncRouterMap
} else {
// 否则需要通过以下方法来筛选出本角色可用的路由
accessedRouters = filterAsyncRouter(asyncRouterMap, menus)
}
// 为了防止F5刷新跑到404
accessedRouters.push({ path: '*', redirect: '/404', hidden: true })
// 执行设置路由的方法
commit('SET_ROUTERS', accessedRouters)
resolve()
})
}
}
}
export default permission
asyncRouterMap是动态路由组: 这里的menu和getInfo返回的menuList的值是对应的
constantRouterMap是静态路由组:如下
export const constantRouterMap = [
{
path: '/login',
component: lazyLoading('login/index'),
hidden: true
},
]
路由表
有一个坑需要注意:当完成权限管理的时候只要F5刷新,或者点击其他路由都会跑到404页面. 这个坑的解决方法是:合并处理过的路由后,手动push404路由到总路由里面
(3)通过getters使用权限管理
或者调用GenerateUserRoutes函数
3.最终效果展示
总结
总结一下思路:总的来说登录之后获取menuList[]用户权限的信息,然后把menuList[]用户权限的信息传给权限过滤的函数,过滤函数主要是通过遍历和递归的方法来过滤一些没有权限的路由。最后通过router.addRoutes(store.getters.addRouters)方法把静态路由和动态路由合并成一个新的路由。menuList可能不是这个格式的,但是大体相似,都是获取一个唯一字段跟路由表的字段做对比看看是否有显示的权限。
更多推荐
所有评论(0)