Fork me on GitHub

Vue+Element-Ui搭建后台管理界面(登录和菜单权限控制[二])

权限管理时发现一篇好的博文

1.根据权限计算路由的代码

/** * 通过meta.role判断是否与当前用户权限匹配 * @param roles * @param route */ function hasRoles (roles, route) { if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { return false } } /** * 递归过滤异步路由表,返回符合用户角色权限的路由表 * @param routes asyncRouterMap * @param roles */ function filterAsyncRouter(asyncRouterMap, roles) { const accessedRouters = asyncRouterMap.filter(route => { // 404 if(route.path === '*'){ return true }else if (hasRoles(roles, route)) { if (route.children && route.children.length) { route.children = filterAsyncRouter(route.children, roles) } return true } return false }) return accessedRouters } GenerateRoutes ({ commit }, data) { return new Promise(resolve => { const { roles } = data let accessedRouters if (roles.includes('admin')) { accessedRouters = asyncRouterMap } else { accessedRouters = filterAsyncRouter(asyncRouterMap, roles) } commit('SET_ROUTERS', accessedRouters) resolve() }) }

 

以上函数接收异步路由表、权限列表,返回在权限列表中的路由,保存在 state.addRouters 中

 

2.动态显示顶部导航和侧边栏

根据 state.addRouters 中的路由,动态生成顶部导航和侧边栏菜单

// 在有权限的路由表里,查找是否有到目标path的路由 // 为了保持路由唯一性,拼接父子路由 function hasDestRoute (froute, permitRouterMap, to) { let r = froute === '/' ? '' : froute return permitRouterMap.some(route => { let path = r + '/' + route.path if (to.path.indexOf(path) !== -1) { return true; } if (route.children && route.children.length) { //如果有孩子就遍历孩子 return hasDestRoute(path, route.children, to) } }) } /** ...省略的代码 */ SET_NOW_ROUTERS: (state, to) => { // 由于首页重定向到 /dashboard,并且不参与权限控制,特殊处理 if(to.path === '/dashboard'){ let dashboard = state.routers.filter(v => v.path === '/' ) state.sidebar_routers = dashboard[0] }else{ // 递归访问 accessedRouters,找到包含to 的那个路由对象,设置给 sidebar_routers state.addRouters.forEach(e => { if (e.children && e.children.length) { if ( hasDestRoute2(e.path, e.children, to)){ if(state.sidebar_routers.path){ // 存在 sidebar_routers 且与目标路由不同 if(state.sidebar_routers.path !== e.path){ state.sidebar_routers = e; } }else{ state.sidebar_routers = e; } } } }) } }

 

3.关键的控制代码

在路由跳转前,判断是否登录、拉取权限、生成菜单等

function hasPermission(roles, permissionRoles) { if (roles.indexOf('admin') >= 0) { return true // admin权限 直接通过 } // 没有配置权限的菜单直接进入 if (!permissionRoles){ return true } return roles.some(role => permissionRoles.indexOf(role) >= 0) } /** ...省略的代码 */ const whiteList = ['/login',] // 不重定向白名单 router.beforeEach((to, from, next) => { // 切换路由时清空上个路由未完成的所有请求 const cancelToken = axios.CancelToken clearRequest.source.cancel && clearRequest.source.cancel('CANCELD_BY_USER') clearRequest.source = cancelToken.source() // 在免登录白名单,直接进入 if(whiteList.indexOf(to.path) !== -1){ next() }else{ if(store.getters.token) { if (to.path === '/login') { next({ path: '/' }) NProgress.done() // }else{ // 判断当前用户是否已拉取完user_info信息 if(store.getters.roles.length === 0){ // 拉取用户信息 store.dispatch('GetUserInfo') .then(resp => { const roles = resp.data.roles store.dispatch('GenerateRoutes', {roles}) .then(()=>{ // 根据roles权限生成可访问的路由表 // 动态添加可访问路由表 router.addRoutes(store.getters.addRouters) next({...to, replace: true}) }) }) .catch((err) => { store.dispatch('FedLogOut').then(()=>{ Message.error({ message: err || '认证失败,请重新登录', duration: 2000, }) next({ path: '/login' }) }) }) }else{ console.log('call GenSidebarRoutes') store.dispatch('GenSidebarRoutes', to) .then(()=> { if(hasPermission(store.getters.roles, to.meta.role)){ next() }else{ next({ path: '/', query: {noGoBack: true} }) } }) } } }else{ // 重定向到登录页 next({ path: '/login', query: {redirect: to.fullpath} }) } } })

 

原文转载于https://www.cnblogs.com/wbjxxzx/p/10081491.html


__EOF__

本文作者Hui Li
本文链接https://www.cnblogs.com/leedev-blog/p/15208540.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Hui_Li  阅读(902)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示