vue3+element-plus权限控制实现(el-tree父子级不关联情况处理)

2023-09-14 13:36:52


前言

在开发后台管理系统的时候,用户的权限控制是一个常见的需求。这里需要探讨下按钮的级别的权限控制,以及实现中使用element-plus tree 组件的使用细节。


一、遇到的交互场景

基于原有的基础上实现按钮级别的权限控制,原有的如下图每一个菜单都有一个唯一ID,PID(父级ID),现在需要扩展的功能,就是添加一个button按钮控制,其中主要的细节交互:

  1. 取消选中子级menu/button,父级不关联取消;
  2. 选中/取消父级catalog/menu,子级全部选中/取消;
  3. 选中/取消部分子级menu/button,父级关联半选中状态(indeterminate=true);

其中我用的是el-tree 组件,我用button:xxx业务按钮;这样的方式来命名,后端也给了区分类型的字段type:catalog(目录),menu(菜单),button(按钮)。

在这里插入图片描述

el-tree 中 check-strictly 属性

el-tree 中 check-strictly 属性,为了实现取消选中子级menu/button,父级不关联取消,这里check-strictly设置为true;设置后点击父级也不关联子级选中了,用户用起来不方便,这里就需要我们自己处理
在这里插入图片描述

二、处理父级的半选中以及选中交互

el-tree

 <el-tree
            ref="treeRef"
            :check-strictly="true"
            :data="treeData"
            show-checkbox
            default-expand-all
            node-key="id"
            highlight-current
            :default-checked-keys="variable.roleForm.featureIds"
            :props="defaultProps"
            @check="hanleCheck"
            @check-change="checkChange"
          />
const defaultProps = {
  children: 'children',
  label: function (treeData: any, treeNode: any) {
    return treeData?.name
  }
}

check,check-change 事件

这里主要用的事件 check,check-change
在这里插入图片描述

const hanleCheck = (data:any, node:any) => {
  console.log(data, node);
  // 获取当前节点是否被选中
  const isChecked = treeRef.value!.getNode(data).checked
  // 如果当前节点被选中,则遍历下级子节点并选中,如果当前节点取消选中,则遍历下级节点并取消
  if (isChecked) {
    // 判断该节点是否有下级节点,如果有那么遍历设置下级节点为选中
    data.children && data.children.length > 0 && setChildreChecked(data.children, true)
  } else {
    // 如果节点取消选中,则取消该节点下的子节点选中
    data.children && data.children.length > 0 && setChildreChecked(data.children, false)
  }
  function setChildreChecked(node:any, isChecked:boolean) {
    node.forEach((item:any) => {
      item.children && item.children.length > 0 && setChildreChecked(item.children, isChecked)
      // // 修改勾选状态
      treeRef.value!.setChecked(item.id, isChecked,false)
    })
  }
}

const checkChange = (data, checked, indeterminate) => {
      // console.log(data, checked, indeterminate);
      // 选中全部子节点,父节点也默认选中,但是子节点再次取消勾选或者全部子节点取消勾选也不会影响父节点勾选状态
      let checkNode = treeRef.value!.getNode(data)//获取当前节点
      // 勾选部分子节点,父节点变为半选状态
      if (checkNode.parent && checkNode.parent.childNodes.some(ele => ele.checked)) {
        checkNode.parent.indeterminate = true
      }
      // 勾选全部子节点,父节点变为全选状态
      if (checkNode.parent && checkNode.parent.childNodes.every(ele => ele.checked)) {
        checkNode.parent.checked = true
        checkNode.parent.indeterminate = false
      }
      // 如果取消所有第二节点的勾选状态,则第一层父节点也取消勾选
      if (checkNode.level == 2 && checkNode.parent.childNodes.every(ele => !ele.checked)) {
        checkNode.parent.checked = false
        checkNode.parent.indeterminate = false
      }
}

其中,上面用的

      treeRef.value!.setChecked(item.id, isChecked,false)

看文档说第三个属性是是否要递归,我觉得是设置了true后,应该帮我递归选中/取消关联的节点,但没有生效,所以还是自己递归下;(有大佬能指出是我的用法有问题吗?劳烦指出)
在这里插入图片描述

编辑进来,父级的半选状态处理

上述方法实现后,我们就可以实现上述交互了,但这里要注意的一点,就是点击编辑进入的,父级的半选状态没有选中,也就是说 checkNode.parent.indeterminate 这个没有被设置为true;下面打个补丁。

const editRole = async (row: any) => {
  const { permissionIds} = await detailApi({ id: row.id })
  await nextTick()
   setCheckedKeys(permissionIds)  // 返回用户的权限id后,根据id选中树节点

  permissionIds.forEach((id:any) => {
    const nodeData = treeRef.value!.getNode(id)  // 根据权限id,获取每个选中的树节点
    console.log('nodeData',nodeData)
    console.log('nodeData.parent?.id',nodeData.parent?.id)
    // 反显,上面setCheckedKeys后,如果父级没有选中,则把半选状态设置true
    if(nodeData?.parent?.id != 0 &&  !nodeData?.parent?.checked){
      nodeData.parent.indeterminate = true
    }
  });
}

总结

后台管理系统常见的权限控制需求,这里讲button实现交互细节处理,

  1. 取消选中子级menu/button,父级不关联取消;
  2. 选中/取消父级catalog/menu,子级全部选中/取消;
  3. 选中/取消部分子级menu/button,父级关联半选中状态(indeterminate=true);
    下篇再补上button 的根据权限控制显示,用vue3 的指令实现,谢谢关注
更多推荐

(并查集) 1971. 寻找图中是否存在路径 ——【Leetcode每日一题】

❓1971.寻找图中是否存在路径难度:简单有一个具有n个顶点的双向图,其中每个顶点标记从0到n-1(包含0和n-1)。图中的边用一个二维整数数组edges表示,其中edges[i]=[ui,vi]表示顶点ui和顶点vi之间的双向边。每个顶点对由最多一条边连接,并且没有顶点存在与自身相连的边。请你确定是否存在从顶点sou

为何学linux及用处

目前企业使用的操作系统无非就是国产类的,windows和linux类。我们要提升自己的技能,需要学习这两款。我记得在大学时期,学习过windows以及linux,但当时觉得又不常用,就学的模棱两可。毕业之后,你会发现,其实这两种操作系统是很主流的。为什么学?下面就是一些工作中遇到的例子分享一下。我记得在企业中有次遇到数

一款固定资产设备管理系统、对常用资产设备进行信息化管理

一、开源项目简介EAM固定资产设备管理系统,满足中小企业基本需求,对常用资产设备进行信息化管理,包含自定义支持各类设备、自带导入导出、维护工作统计、采购管理、文档管理、合同管理等功能。实现企业对资产的基本管理,包含对资产的登记、维修、调拨、转移等基本功能的支持,并提供对资产的耗材、库存进行管理,有完善的组织架构,非常适

2023/09/17

文章目录1.vscode展开所有代码快捷键ctrl+k+j2.git删除所有stash或指定stashgitstashdrop[可选stash名]3.vue在函数默认参数后增加新参数4.gitpush添加“-u”参数5.vscode快捷输入符号$的使用6.WebGL之什么是GLB&GLTF文件?7.WebGL之什么是H

Appium混合页面点击方法tap的使用

原生应用开发,是在Android、IOS等移动平台上利用官方提供的开发语言、开发类库、开发工具进行App开发;HTML5(h5)应用开发,是利用Web技术进行的App开发。目前,市面上很多app都是原生和h5混合开发,这样做的好处在于:1)开发效率高,节约时间同一套代码Android和IOS基本都可用。2)更新和部署比

SpringMVC之JSON返回及异常处理

目录JSON处理导入依赖配置Spring-mvc.xml@ResponseBody注解使用测试目录JSON处理导入依赖配置Spring-mvc.xml@ResponseBody注解使用测试Jackson定义用法常用注解统一异常处理为什么要全局异常处理?异常处理思路SpringMVC异常分类综合案例异常处理方式一异常处理

Call短路触发版本SIP对讲求助终端

SV-2701VPCall短路触发版本SIP对讲求助终端一、描述SV-2701VP是我司的一款壁挂式求助对讲终端,具有10/100M以太网接口,支持G.711与G.722音频解码,其接收SIP网络的音频数据,实时解码播放。配置一路线路输入,一路线路输出,可将内部音源输出到外接功放,还有Mic输入,一路继电器输出和一路呼

Python 3.11的10个高效新特性

1、模式匹配Python3.11引入了模式匹配,可以简化复杂的条件逻辑。下面是一个使用模式匹配来处理不同类型数据结构的例子:defprocess_data(data):matchdata:case0:print("Receivedzero")case[x,y]:print(f"Receivedalist:{x},{y}

基于Qt5的计算器设计

Qt5的信号与槽✨描述:信号槽是Qt框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式(发布-订阅模式)。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信

Java基础常考知识点(基础、集合、异常、JVM)

Java基础常考知识点基础JDK、JRE、JVM之间的区别hashCode()与equals()之间的关系String、StringBuffer、StringBuilder的区别泛型中extends和super的区别==和equals⽅法的区别重载和重写的区别深拷⻉和浅拷⻉什么是字节码?采⽤字节码的好处是什么?Java

vue3 - 基于 Vue3 + Vite4 + TypeScript5 + Element-Plus + Pinia 技术栈的后台管理系统

GitHubDemo地址在线预览jh-vue3-admin项目地址|在线预览##项目介绍jh-vue3-admin是基于Vue3+Vite4+TypeScript5+Element-Plus+Pinia等最新主流技术栈构建的后台管理系统前端模板。特性:基于vue-admin-template项目升级到vue3版本通过M

热文推荐