在完成一个基本后台管理系统项目开发后,对其中的要点技术进行了小小的回顾

130 阅读3分钟

本项目的主要核心功能就是 权限控制

对于任何一个企业来说,不同角色登录进来, 看到的菜单效果应该不一样,能够做的操作也就不一样。在控制每个员工权限时,我们一般有两种解决方案。

第一种选择:

  • 相对来说, 给每个员工一个一个添加权限非常耗时, 而且非常麻烦

第二种选择

  • 只需要提供一个中间角色的概念, 就可以将所有的权限对应分配给角色
  • 然后给我们的员工分配角色就可以了,非常方便!!!

注意: 第二种就是非常出名的RBAC(role based access control => 基于角色的权限控制) 👏🏻👏🏻👏🏻

总结: RBAC就是给员工分配角色,给角色分配权限

一、关于如何给员工分配角色

image.png

image (2).png

二、关于如何给角色分配权限

image (1).png

image (3).png

image (4).png

三、给角色分配的权限有哪些

我们在给角色分配权限时,针对不同的角色所能看到的页面以及页面内的功能按钮要做不同的控制,实际上我们主要分为三类。包括菜单访问权,按钮操作权,以及api接口访问权。

3.1关于控制角色菜单访问功能的实现

1.权限应用-拆分静态路由-动态路由 image (5).png

静态路由
export const constantRoutes = [
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },

  {
    path: '/404',
    component: () => import('@/views/404'),
    hidden: true
  },

  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [{
      path: 'dashboard',
      name: 'Dashboard',
      component: () => import('@/views/dashboard/index'),
      meta: { title: '首页', icon: 'dashboard' }
    }]
  },

  // 404 page must be placed at the end !!!
  // { path: '*', redirect: '/404', hidden: true }
]
// 动态路由
export const asyncRoutes = [
  departmentRouter,
  roleRouter,
  employeeRouter,
  permissionRouter,
  attendanceRouter,
  approvalRouter,
  salaryRouter,
  socialRouter]

2.权限应用-根据用户权限添加动态路由

image (6).png

image (7).png

Vuex用户模块action中返回result信息

async getUserInfo(context) {
    const result = await getUserInfo()
    context.commit('setUserInfo', result)
    return result // 返回数据
}

权限拦截处筛选-添加路由

// 判断是否获取过资料
      if (!store.getters.userId) {
        const { roles } = await store.dispatch('user/getUserInfo')
        // console.log(roles.menus) // 数组 不确定 可能是8个 1个 0个
        // console.log(asyncRoutes) // 数组 8个
        const filterRoutes = asyncRoutes.filter(item => {
          // return true/false
          return roles.menus.includes(item.name)
        }) // 筛选后的路由
        router.addRoutes([...filterRoutes, { path: '*', redirect: '/404', hidden: true }]) // 添加动态路由信息到路由表
        // router添加动态路由之后 需要转发一下
        next(to.path) // 目的是让路由拥有信息 router的已知缺陷
      } else {
        next() // 放过
      }

针对每个路由模块的配置文件添加name属性,和权限的数据进行对应。 image (8).png 3.权限应用-根据权限显示左侧菜单

image (9).png

image (10).png Vuex中的user模块添加state管理

setRoutes(state, newRoutes) {
    state.routes = [...constantRoutes, ...newRoutes] // 静态路由 + 动态路由
  }

筛选路由后,更新state信息

// 判断是否获取过资料
      if (!store.getters.userId) {
        const { roles } = await store.dispatch('user/getUserInfo')
        // console.log(roles.menus) // 数组 不确定 可能是8个 1个 0个
        // console.log(asyncRoutes) // 数组 8个
        const filterRoutes = asyncRoutes.filter(item => {
          // return true/false
          return roles.menus.includes(item.name)
        }) // 筛选后的路由
        store.commit('user/setRoutes', filterRoutes)
        router.addRoutes([...filterRoutes, { path: '*', redirect: '/404', hidden: true }]) // 添加动态路由信息到路由表
        // router添加动态路由之后 需要转发一下
        next(to.path) // 目的是让路由拥有信息 router的已知缺陷
      } else {
        next() // 放过
      }

使用getters开放路由的访问信息

const getters = {
  routes: state => state.user.routes
}
export default getters

左侧菜单组件读取Vuex中的路由信息

export default {
  computed: {
    ...mapGetters([
      'routes'
    ]),
    // 路由信息的计算属性
    // routes() {
    //   // 返回所有的路由信息
    //   return this.$router.options.routes
    // },
  }
}

退出登录时-重置路由

import { resetRouter } from '@/router'

// 退出登录的action
  logout(context) {
    // 重置路由
    resetRouter()
  }

3.2关于控制角色按钮操作功能的实现

image (11).png

image (12).png

image (13).png

权限应用-自定义指令应用功能权限

image (14).png

// 封装自定义指令 用来控制操作权
Vue.directive('permission', {
  // 会在指令作用的元素插入到页面完成以后触发
  inserted(el, binding) {
    // el 指令作用的元素的dom对象
    console.log(el)
    const points = store.state.user.userInfo?.roles?.points || [] // 当前用户信息的操作权
    if (!points.includes(binding.value)) {
      // 不存在就要删除或者禁用
      el.remove() // 删除元素
      // el.disabled = true
      // 线上的权限数据和线下的代码进行对应
    }
  }
})
<el-button v-permission="'add-employee'" size="mini" type="primary" @click="$router.push('/employee/detail')">添加员工</el-button>

3.3关于控制角色api接口访问功能的实现

前端这里也能判断,不过后端处理居多