Vue3自定义指令实现按钮权限

一、需求前提

登录成功后,后端直接返回了用户的所有权限(路由权限+按钮权限),在已经实现菜单权限的基础上,实现每个页面的按钮权限,树形数据结构如下:

{
    "roles": ["admin"],
    "token": "12345678901234567890",
    "userInfo": {
                   "id": "1",
                   "username": "system",
                   "nickName": "system",
                   "email": null,
                   "phoneNumber": "13131234567",
                   "sex": "1",
                   "avatar": null,
                   "userType": "1"
                },
    "menus": [
        {
            "id": "1",
            "pid": "0",
            "menuName": "home",
            "type": 1,
            "path": "/home",
            "perms": "home",
            "icon": "iconfont icon-shouye",
            "sortNo": 0,
            "selected": null,
            "status": "0",
            "title": "首页",
            "redirect": "",
            "visible": "0",
            "remark": "首页",
            "name": "home",
            "meta": {
                "title": "首页",
                "isHide": false,
                "roles": [
                    "home"
                ],
                "icon": "iconfont icon-shouye",
                "tagsViewName": "首页"
            },
            "children": [],
        },
        {
            "id": "2",
            "pid": "0",
            "menuName": "screen",
            "type": 1,
            "path": "/screen",
            "perms": "screen",
            "icon": "iconfont icon-shuju",
            "sortNo": 3,
            "selected": null,
            "status": "0",
            "title": "信息大屏",
            "redirect": null,
            "visible": "0",
            "remark": "信息大屏",
            "name": "screen",
            "meta": {
                "title": "信息大屏",
                "isHide": false,
                "roles": [
                    "screen"
                ],
                "icon": "iconfont icon-shuju"
            },
            "children": [
              {
                  "id": "21",
                  "pid": "2",
                  "menuName": "firstScreen",
                  "type": 1,
                  "path": "/firstScreen",
                  "perms": "firstScreen",
                  "icon": "ele-FirstAidKit",
                  "sortNo": 0,
                  "selected": null,
                  "status": "0",
                  "title": "大屏1",
                  "redirect": null,
                  "visible": "0",
                  "remark": "大屏1",
                  "name": "firstScreen",
                  "meta": {
                      "title": "大屏1",
                      "isHide": false,
                      "roles": [
                          "firstScreen"
                      ],
                      "icon": "ele-FirstAidKit"
                  },
                  "children": [
                    {
                        "id": "211",
                        "pid": "21",
                        "menuName": "loadingData",
                        "type": 2,
                        "path": "loadingData",
                        "component": "",
                        "perms": "screen:firstScreen:loadingData",
                        "icon": "",
                        "sortNo": 0,
                        "selected": null,
                        "status": "0",
                        "title": "同步数据",
                        "redirect": null,
                        "visible": "0",
                        "remark": "同步数据",
                        "name": "loadingData",
                        "meta": {
                          "title": "同步数据",
                          "isHide": false,
                          "roles": [
                            "screen:firstScreen:loadingData"
                          ],
                          "icon": ""
                        },
                        "children": [],
                    },
                  ],
              },
            ],
        },
    ],             
}

二、实现思路

获取当前路由页面的权限,筛选出当前路由页面拥有的所有按钮权限,判断某个按钮是否拥有权限,没有权限就通过css设置为display:none

三、具体实现步骤(vue3+ts)

1.在src文件下新建directive文件,在directive文件中新建btnPermission.ts文件

具体目录结构如下:

2.在btnPermission.ts中

import type { App } from 'vue';
import { useUserInfo } from '/@/stores/userInfo';

/**
 * 按钮权限指令-无按钮权限不显示
 * @directive 单个按钮权限验证(v-btnPermission="xxx")
 */

export function btnPermission(app: App) {
  app.directive('btnPermission', {
    mounted(el, binding) {
      // 1.从用户信息pinia中拿到用户信息(用户权限)
      const stores = useUserInfo();
      // 2.找到当前路由页面拥有的所有权限
      const btnArr = filterPath(stores.userInfos.menus, window.location.hash.slice(1))
      // 3.判断是否有当前按钮的权限,没有直接不显示
      if (!btnArr.find((item: any) => item.name == binding.value)) {
        el.style.display = 'none'
      }
    },
  });
}

//递归工具函数---判断当前节点是否匹配目标路由
function filterPath(tree: any, path: string) {
  for (let i = 0; i < tree.length; i++) {
    const node = tree[i];
    if (node.path == path) {
      return node.children;
    } else {
      if (node.children && node.children.length > 0) {
        const result: any = filterPath(node.children, path);
        if (result) {
          return result;
        }
      }
    }
  }
}

 3.在directive文件下的index.ts中,注册自定义指令

import type { App } from 'vue';
import { btnPermission } from '/@/directive/btnPermission';

/**
 * 导出指令方法:v-xxx
 * @methods btnPermission 按钮权限指令,用法:v-btnPermission
 */

export function directive(app: App) {
  // 按钮权限指令
  btnPermission(app)
}

 4.在目标页面中使用

  // v-btnPermission="'按钮权限的name值'",真实项目中的字段取用自行与后端协商
  <el-button size="default" v-btnPermission="'loadingData'" type="primary"
          @click="handleSubmit">同步数据</el-button>

猜你喜欢

转载自blog.csdn.net/weixin_48082900/article/details/131377057