vue 权限分组

在权限设计时,分为部门、岗位、人员三部分, 人员下面挂部门,部门下面挂岗位,岗位下面挂菜单,用户在进行授权时,勾选了操作权限,默认数据权限也进行勾选。

权限组:查询、新增、修改、删除

用户交互如下:

1、选中新增、修改、删除中的任何一个复选框时,查询框也选中。

2、选中查询框时,新增、修改、删除不变。

3、取消选中查询框时,新增、修改、删除都取消选中。

代码如下:

javascript 复制代码
<template>
  <div>
    <el-tree
      ref="treeRef"
      class="permission-tree"
      :data="menuTree"
      show-checkbox
      node-key="id"
      default-expand-all
      :expand-on-click-node="false"
      :check-on-click-node="true"
      @check="handleCheck"
      :props="{
        label: 'title'
      }"
    >
    </el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      menuTree: [
        {
          id: '1717148200757',
          code: 'departmentManagement',
          title: '部门管理 ',
          name: '部门管理 ',
          parentIdId: null,
          children: [
            {
              id: '1717148287418',
              parentIdId: '1717148200757',
              code: 'department',
              title: '部门',
              name: '部门 ',
              children: [
                {
                  id: 'department:query',
                  code: 'department:query',
                  name: '查询',
                  title: '查询',
                  parentIdId: '1717148287418',
                  dataPermission: true
                },
                {
                  id: 'department:add',
                  code: 'department:add',
                  name: '新增',
                  title: '新增',
                  parentIdId: '1717148287418',
                  dataPermission: false
                },
                {
                  id: 'department:update',
                  code: 'department:update',
                  name: '修改',
                  title: '修改',
                  parentIdId: '1717148287418',
                  dataPermission: false
                },
                {
                  id: 'department:delete',
                  code: 'department:delete',
                  name: '删除',
                  title: '删除',
                  parentIdId: '1717148287418',
                  dataPermission: false
                }
              ]
            }
          ]
        },
        {
          id: '1717148223729',
          code: 'jobManagement',
          title: '岗位管理',
          name: '岗位管理',
          parentId: null,
          children: [
            {
              id: '1717148366037',
              parentId: '1717148223729',
              code: 'jobInside',
              title: '岗位',
              name: '岗位',
              children: [
                {
                  id: 'permissionManagement:position:query',
                  code: 'permissionManagement:position:query',
                  name: '查询',
                  title: '查询',
                  parentIdId: '1717148366037',
                  dataPermission: true
                },
                {
                  id: 'permissionManagement:position:add',
                  code: 'permissionManagement:position:add',
                  name: '新增',
                  title: '新增',
                  parentIdId: '1717148366037',
                  dataPermission: false
                },
                {
                  id: 'permissionManagement:position:update',
                  code: 'permissionManagement:position:update',
                  name: '修改',
                  title: '修改',
                  parentIdId: '1717148366037',
                  dataPermission: false
                },
                {
                  id: 'permissionManagement:position:delete',
                  code: 'permissionManagement:position:delete',
                  name: '删除',
                  title: '删除',
                  parentIdId: '1717148366037',
                  dataPermission: false
                }
              ]
            }
          ]
        },
        {
          id: '1717148248870',
          code: 'userManagement',
          title: '用户管理',
          name: '用户管理',
          parentId: null,
          children: [
            {
              id: '1717148408202',
              parentId: '1717148248870',
              code: 'userAdmin',
              title: '用户',
              name: '用户',
              children: [
                {
                  id: 'userAdmin:query',
                  code: 'userAdmin:query',
                  name: '查询',
                  title: '查询',
                  parentIdId: '1717148408202',
                  dataPermission: true
                },
                {
                  id: 'userAdmin:add',
                  code: 'userAdmin:add',
                  name: '新增',
                  title: '新增',
                  parentIdId: '1717148408202',
                  dataPermission: false
                },
                {
                  id: 'userAdmin:update',
                  code: 'userAdmin:update',
                  name: '修改',
                  title: '修改',
                  parentIdId: '1717148408202',
                  dataPermission: false
                },
                {
                  id: 'userAdmin:delete',
                  code: 'userAdmin:delete',
                  name: '删除',
                  title: '删除',
                  parentIdId: '1717148408202',
                  dataPermission: false
                }
              ]
            }
          ]
        }
      ]
    };
  },
  methods: {
    /**
     * 复选框选中事件
     * 实现的效果:
     * 1、查询节点选中时,其相邻兄弟节点不变
     * 2、查询节点取消选中时,其相邻兄弟节点取消选中
     * 3、其相邻兄弟节点任何一个选中时,查询节点必选中
     * 注:查询节点 dataPermission:true
     * **/
    handleCheck(data) {
      if (!data.children) {
        // 获取当前叶子节点的兄弟节点
        const sublingsNode = this.getSiblingsById(this.menuTree, data.id);
        // 获取当前叶子节点中为查询节点的项
        const dataPermissionItem = [data, ...sublingsNode].find(
          (item) => item.dataPermission
        );

        if (data.dataPermission) {
          // 操作的是查询节点时,将其兄弟节点设置为取消选中状态
          sublingsNode.forEach((item) => {
            this.$refs.treeRef.setChecked(item, false);
          });
        } else {
          // 操作的是兄弟节点时,将查询节点设置为选中状态
          this.$refs.treeRef.setChecked(dataPermissionItem, true);
        }
      }
    },

    /**
     * 通过当前节点的 id 查找兄弟节点
     * treeData:树形结构的数据源
     * nodeId:当前节点的 id
     * **/
    getSiblingsById(treeData, nodeId) {
      function findSiblings(nodes) {
        for (const node of nodes) {
          if (node.id === nodeId) {
            return nodes.filter((item) => item.id !== nodeId);
          }
          if (node.children) {
            const siblings = findSiblings(node.children, node.id);
            if (siblings) return siblings;
          }
        }
        return null;
      }

      return findSiblings(treeData, null);
    }
  }
};
</script>

总结:

在写这部分逻辑时,难点在于取消数据权限时,怎么将操作权限也进行取消,这部分的交互相当于是查询是新增、修改、删除的取消全选操作。在进行这部分交互效果实现时,有考虑过使用 current-change 这个事件,因为这个事件可以获取到一个 Node 对象,在 Node 对象中可以获取到当前节点父节点,从而在父节点下找到当前节点及兄弟节点,从而避免了使用递归的方式查找兄弟节点,这个事件有个问题,无法触发 check 事件,导致在点击复选框选中时,事件未触发,所以退而求其次考虑使用 check 事件,配合递归方法实现最终的交互效果。

补充:

可以将递归函数去掉,使用 elementUI 中提供的 getNode 方法获取当前节点的兄弟节点,修改如下:

javascript 复制代码
<template>
  <div>
    <el-tree
      ref="treeRef"
      class="permission-tree"
      :data="menuTree"
      show-checkbox
      node-key="id"
      default-expand-all
      :expand-on-click-node="false"
      :check-on-click-node="true"
      @check="handleCheck"
      :props="{
        label: 'title'
      }"
    >
    </el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      menuTree: [
        {
          id: '1717148200757',
          code: 'departmentManagement',
          title: '部门管理 ',
          name: '部门管理 ',
          parentIdId: null,
          children: [
            {
              id: '1717148287418',
              parentIdId: '1717148200757',
              code: 'department',
              title: '部门',
              name: '部门 ',
              children: [
                {
                  id: 'department:query',
                  code: 'department:query',
                  name: '查询',
                  title: '查询',
                  parentIdId: '1717148287418',
                  dataPermission: true
                },
                {
                  id: 'department:add',
                  code: 'department:add',
                  name: '新增',
                  title: '新增',
                  parentIdId: '1717148287418',
                  dataPermission: false
                },
                {
                  id: 'department:update',
                  code: 'department:update',
                  name: '修改',
                  title: '修改',
                  parentIdId: '1717148287418',
                  dataPermission: false
                },
                {
                  id: 'department:delete',
                  code: 'department:delete',
                  name: '删除',
                  title: '删除',
                  parentIdId: '1717148287418',
                  dataPermission: false
                }
              ]
            }
          ]
        },
        {
          id: '1717148223729',
          code: 'jobManagement',
          title: '岗位管理',
          name: '岗位管理',
          parentId: null,
          children: [
            {
              id: '1717148366037',
              parentId: '1717148223729',
              code: 'jobInside',
              title: '岗位',
              name: '岗位',
              children: [
                {
                  id: 'permissionManagement:position:query',
                  code: 'permissionManagement:position:query',
                  name: '查询',
                  title: '查询',
                  parentIdId: '1717148366037',
                  dataPermission: true
                },
                {
                  id: 'permissionManagement:position:add',
                  code: 'permissionManagement:position:add',
                  name: '新增',
                  title: '新增',
                  parentIdId: '1717148366037',
                  dataPermission: false
                },
                {
                  id: 'permissionManagement:position:update',
                  code: 'permissionManagement:position:update',
                  name: '修改',
                  title: '修改',
                  parentIdId: '1717148366037',
                  dataPermission: false
                },
                {
                  id: 'permissionManagement:position:delete',
                  code: 'permissionManagement:position:delete',
                  name: '删除',
                  title: '删除',
                  parentIdId: '1717148366037',
                  dataPermission: false
                }
              ]
            }
          ]
        },
        {
          id: '1717148248870',
          code: 'userManagement',
          title: '用户管理',
          name: '用户管理',
          parentId: null,
          children: [
            {
              id: '1717148408202',
              parentId: '1717148248870',
              code: 'userAdmin',
              title: '用户',
              name: '用户',
              children: [
                {
                  id: 'userAdmin:query',
                  code: 'userAdmin:query',
                  name: '查询',
                  title: '查询',
                  parentIdId: '1717148408202',
                  dataPermission: true
                },
                {
                  id: 'userAdmin:add',
                  code: 'userAdmin:add',
                  name: '新增',
                  title: '新增',
                  parentIdId: '1717148408202',
                  dataPermission: false
                },
                {
                  id: 'userAdmin:update',
                  code: 'userAdmin:update',
                  name: '修改',
                  title: '修改',
                  parentIdId: '1717148408202',
                  dataPermission: false
                },
                {
                  id: 'userAdmin:delete',
                  code: 'userAdmin:delete',
                  name: '删除',
                  title: '删除',
                  parentIdId: '1717148408202',
                  dataPermission: false
                }
              ]
            }
          ]
        }
      ]
    };
  },
  methods: {
    /**
     * 复选框选中事件
     * 实现的效果:
     * 1、查询节点选中时,其相邻兄弟节点不变
     * 2、查询节点取消选中时,其相邻兄弟节点取消选中
     * 3、其相邻兄弟节点任何一个选中时,查询节点必选中
     * 注:查询节点 dataPermission:true
     * **/
    handleCheck(data, checked, indeterminate) {
      if (!data.children) {
        // 只处理叶子节点
        const parentNode = this.$refs.treeRef.getNode(data).parent;
        if (parentNode) {
          // 获取当前叶子节点的兄弟节点
          // const sublingsNode = this.getSiblingsById(this.treeData, data.id);
          // 获取当前叶子节点和兄弟节点
          const siblings = parentNode.data.children;
          const dataPermissionItem = siblings.find(
            (item) => item.dataPermission
          );

          if (data.dataPermission) {
            // 如果是查询节点,则取消选中所有非查询兄弟节点
            siblings.forEach((sibling) => {
              if (!sibling.dataPermission) {
                this.$refs.treeRef.setChecked(sibling, false, false);
              }
            });
          } else if (checked) {
            // 如果是非查询节点被选中,则确保查询节点也被选中
            this.$refs.treeRef.setChecked(dataPermissionItem, true, false);
          }
        }
      }
    }

    // /**
    //  * 通过当前节点的 id 查找兄弟节点
    //  * treeData:树形结构的数据源
    //  * nodeId:当前节点的 id
    //  * **/
    // getSiblingsById(treeData, nodeId) {
    //   function findSiblings(nodes) {
    //     for (const node of nodes) {
    //       if (node.id === nodeId) {
    //         return nodes.filter((item) => item.id !== nodeId);
    //       }
    //       if (node.children) {
    //         const siblings = findSiblings(node.children, node.id);
    //         if (siblings) return siblings;
    //       }
    //     }
    //     return null;
    //   }

    //   return findSiblings(treeData, null);
    // }
  }
};
</script>
相关推荐
轻口味39 分钟前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王1 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发1 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
真滴book理喻5 小时前
Vue(四)
前端·javascript·vue.js
程序员_三木5 小时前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
不是鱼6 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
开心工作室_kaic6 小时前
springboot476基于vue篮球联盟管理系统(论文+源码)_kaic
前端·javascript·vue.js
川石教育7 小时前
Vue前端开发-缓存优化
前端·javascript·vue.js·缓存·前端框架·vue·数据缓存
搏博7 小时前
使用Vue创建前后端分离项目的过程(前端部分)
前端·javascript·vue.js