引言

后台管理系统的搭建,主要的难点就行如何控制系统的权限,下面是我阅读了antd-pro-of-vue的权限控制后,自己总结了一下。
其实权限控制,主要就是控制每个用户拥有的菜单和路由。大致的步骤我会提供一个个章节一步步的描述一下。

菜单管理

首先我们把系统主页的完整菜单放到菜单管理处来管理,就是使用一个树形控件来管理菜单,如下菜单管理章节所示,我们点击某个节点后,可以在下方的单行表格看到该节点的信息,点击删除按钮可以删除该节点,点击修改按钮可以修改该节点的信息,或者为该节点添加子节点。
在这里插入图片描述

角色管理

然后,我们开始通过角色管理来创建角色,我们点击新增角色后,可以打开一个弹窗,弹窗里面有一颗菜单树,我们可以点击任意需要页面内增删改查等等权限的节点来为其添加页面内权限。我们会把选择的节点汇成一颗改角色对应的菜单树,还可以在这颗树的下面提供表单为该角色录入角色名称和其他这个角色相关的信息,这里也是忘记绘制了。
在这里插入图片描述相关逻辑

<template>
  <div>
      <a-tree :checkable="true"
            @check="handlerChecked"
            @select="handlerSelectNode"
     />
  </div>
</template>

<script>
export default {
data(){
 return {
  // 选中节点的key[]
   checkedKeys:[],
   // 角色的权限数组
   permissions:[],
   // actionList的编辑弹窗的显隐
   visiable:false,
   // actionList编辑窗口添加的相关值
   pageAuth:{},
 }
},
methods:{
  handlerSelectNode(selectedKeys, {node}){
      // 这里不应该为叶子节点时弹出,应该为需要actionList的节点弹出,因为CURD页面也是叶子节点。上面图片描述有误,这里纠正
     // if(node.dataRef.isLeaf)  
      if(node.dataRef.needActions)
      {
        this.visiable=true  
      }
  },
  handlerChecked(checkedKeys, {halfCheckedKeys}){
    this.checkedKeys=[...checkedKeys,...halfCheckedKeys]
  },
  // 处理actionList的添加
  handlerAddActionList(pageKey,auth){
     this.pageAuth[pageKey]=auth
     /*
       auth数据格式
       actionList:['add','update','export'],
       ...
     */
  },
  addRole(){
     this.checkedKeys.forEach(v=>{
        this.permissions.push({
           ...this.pageAuth[v],
           permissionId:v,
        })
     })
     const role={
      name:'角色名称',
      permissions:this.permissions,
     }
     return role
  },
}
}
</script>

<style>

</style>

得到的角色数据像这样:

	const role= {
				id: 'admin',
				name: '管理员',
				status: 1,
				creatorId: 'system',
				createTime: 1497160610259,
				permissions: [
					{
						permissionId: 'page1',
						permissionName: '页面1',
						actionList: ['add', 'query', 'get', 'update', 'delete'],
					},
					{
						permissionId: 'page2',
						permissionName: '页面2',
						actionList: ['add', 'query', 'get', 'update', 'delete'],
					},
				],
			}

用户管理

最后就是用户管理了,我们直接为改用户分配角色,然后录入用户名等信息即可创建一名新的用户。
在这里插入图片描述
用户的数据格式如下:

 const user={
      name:'hhh',
      token:'asfdsadsadfsad',
      roles:[
        {name:'admin1',permissions:[
          {actionList:['add','delete'],permissionId:'xxManage'},
        ]
        },
        {name:'admin2',permissions:[]},
      ],
   }

方案

以下是如何来得到当前登录用户拥有路由的方案:

  1. 后端可以返回路由表给前端,采用这种方案时,上面角色管理处的逻辑做稍许改动即可
  2. 后端返回前端permissions,前端这边根据permissions和完整的异步路由表得到当前登录用户的路由表,然后将这个路由表挂载到路由上(router.addRoute(route))
    tip:系统侧边菜单根据当前登录用户的路由表生成。路由项包含菜单需要的某些属性,然后过滤掉不在菜单的路由项即可得到渲染菜单的树形数据。

路由表的过滤

function hasPermission (permission, route) {
  if (route.meta && route.meta.permission) {
  // return  permission.some(p => route.meta.permission.includes(p))
    const item=permission.find(v=>route.meta.permission.includes(v.permissionId))
    if(item) return item.actionList
    else return false
  }
  return true              
}

function filterAsyncRouter (routerMap, user) {
  const accessedRouters = routerMap.filter(route => {
  // 取出该用户完整的permission。如果该有多个角色,需要合并得到完整的permmssion
    const  hasAuth=hasPermission(user.permissions, route)   
     if (hasAuth) {
      if(Array.isArray(hasAuth)) route.meta.actionList=hasAuth   // 把actionList添加到meta上
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, roles)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

// asyncRoutes是完整的异步路由表。得到的routes是用户最终的路由表
const routes=filterAsyncRouter(asyncRoutes,user)
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐