joken-前端工程师

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::

概论

  • 主要是通过一个唯一标识name或者id来过滤判断用户所处的角色是否有路由的权限或者按钮的权限
  • 一般路由都有一个一个name可以作为唯一标识
  • 一般按钮的话,可以自定义一个name作为标识
业务逻辑

后台通过选中路由或者按钮给角色,代表这个角色有数组中name[]的权限,用户或者部门再绑定角色,实现权限的管理
image
示例后台:

  • 先给角色分配权限
    image
  • 再给用户分配角色,实现用户拥有该角色绑定的权限
    image
路由过滤方式

通过路由守卫事件过滤权限路由,核心之处就是唯一标识name过滤
如下示例代码:
image

根据name:string[] 过滤完路由后,组合一般性可以直接访问的路由和权限路由
类似如下:
image
image

按钮权限实现方式:通过自定义指令过滤按钮是否显示来实现按钮权限

示例代码:

// permission.ts
// 引入vue中定义的指令对应的类型定义
import { Directive } from 'vue'
export const permission: Directive = {
  // mounted是指令的一个生命周期
  mounted(el, binding) {
    // value 获取用户使用自定义指令绑定的内容
    const { value } = binding
    // 获取用户所有的权限按钮
    const permissionBtn = wsCache.get('permission')
    // 判断用户使用自定义指令,是否使用正确了
    if (value && value instanceof Array && value.length > 0) {
      const permissionFunc = value
      //判断传递进来的按钮权限,用户是否拥有
      //Array.some(), 数组中有一个结果是true返回true,剩下的元素不会再检测
      const hasPermission = permissionBtn.some((btnName: any) => {
        return permissionFunc.includes(btnName)
      }) 
       // 当用户没有这个按钮权限时,设置隐藏/移除这个按钮
      if (!hasPermission) {
        el.style.display = 'none'
        // el.parentNode.removeChild(el);
      }
    } else {
      throw new Error('need roles! Like v-permission="[\'admin\',\'editor\']"')
    }
  }
}


上面代码的核心就是:

const hasPermission = permissionBtn.some((btnName: any) => {
        return permissionFunc.includes(btnName)
      })

有权限则自定义指令让这个按钮显示,没权限则不让显示

  • 按钮权限绑定 业务示例图
    image

  • 指令使用示意图
    image

vue3 实现按钮权限指令示例代码:

import type { App, Directive, DirectiveBinding } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import router from '@/router'

const { t } = useI18n()

const hasPermission = (value: string): boolean => {
  const permission = (router.currentRoute.value.meta.permission || []) as string[]
  if (!value) {
    throw new Error(t('permission.hasPermission'))
  }
  if (permission.includes(value)) {
    return true
  }
  return false
}
function hasPermi(el: Element, binding: DirectiveBinding) {
  const value = binding.value

  const flag = hasPermission(value)
  if (!flag) {
    el.parentNode?.removeChild(el)
  }
}
const mounted = (el: Element, binding: DirectiveBinding<any>) => {
  hasPermi(el, binding)
}

const permiDirective: Directive = {
  mounted
}

export const setupPermissionDirective = (app: App<Element>) => {
  app.directive('hasPermi', permiDirective)
}

export default permiDirective

注册指令

import type { App } from 'vue'
import { setupPermissionDirective } from './permission/hasPermi'

/**
 * 导出指令:v-xxx
 * @methods hasPermi 按钮权限,用法: v-hasPermi
 */
export const setupPermission = (app: App<Element>) => {
  setupPermissionDirective(app)
}

按钮和路由菜单的关系业务示意图:
image
自定义路由的时候把按钮一个个也绑定到页面

总结

权限管理的核心就是通过一个类似allowRoutes:name:string[] 和 一个allowBtns:name:string[] 绑定给角色,通过允许的name去过滤路由或者按钮

相关文章

posted on 2024-06-04 22:03  joken1310  阅读(71)  评论(0编辑  收藏  举报