【树形权限】树形列表权限互斥选择、el-tree设置禁用等等

文章目录

    • 一、实现如上树形列表
      • 1.1 首先要就是渲染树形列表
      • 1.2 然后通过插槽处理头部标题
      • 1.3 再通过插槽处理表格body体内容
      • 1.4 让body体中的选框和表头中的选框产生关联
    • 二、将 el-tree 整棵树设为禁用状态
    • 三、动态表格合并

需求:按照权限管理配置的数据权限树展开;点击查看按钮后进入其他指定机构选择弹窗为一树形结构
在这里插入图片描述
本文章对项目中出现得关键点进行总结。

数字化管理平台
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
权限系统-商城
个人博客地址

一、实现如上树形列表

在 element 官方表格示例中,实现树形表格列表数据渲染,非常简单。只需要按部就班,替换相关的数据即可。
但是很明显,我们这个项目中的需求,除了树形列表外,还有一些非常规的需求(😓想拿板砖拍死产品🤯的心都有了,有没有想过开发啥感受😶,好不好实现🤢!)。没有办法,还是得硬着头皮上,谁让咱没有话语权,说干就干,着手研究。这个过程一定要跟后端商量好交互的数据格式,不然自己干自己的,你最后会很痛苦(PS:最好有一个靠谱的经验丰富的后端来配合你,能让你节省很多时间,少走很多弯路)。

1.1 首先要就是渲染树形列表

很简单,直接贴代码

<el-table:data="tableData"style="width: 100%"row-key="id"lazy:tree-props="{children: 'children', hasChildren: 'hasChildren'}"><el-table-column type="index" label="序号"></el-table-column><el-table-column prop="name" label="名称"></el-table-column><el-table-column prop="one_level"></el-table-column><el-table-column prop="two_level"></el-table-column><el-table-column prop="three_level"></el-table-column><el-table-column prop="four_level"> </el-table-column><el-table-column prop="operation" label="其他指定机构"></el-table-column>
</el-table>

1.2 然后通过插槽处理头部标题

这里的数据只需要渲染名称一行,后面全部都是选框,所以就是头部那里也需要重新去搞一下。
el-table 本身是带有 type=checkbox 属性来实现复选功能的,当时就尝试了四个,但是你需要实现互斥关系,并且还需要加一些文字,自带的就多少有点不够用了。
所以这个使用采用插槽 #header 去重写头部,并使用 el-radio 填充,实现单选互斥效果,代码如下:

<el-table:data="tableData"style="width: 100%"row-key="id"lazy:tree-props="{children: 'children', hasChildren: 'hasChildren'}"><el-table-column type="index" label="序号"></el-table-column><el-table-column prop="name" label="名称"></el-table-column><el-table-column prop="one_level"><template #header><div><el-radio v-model="tableHeader.level" label="1" @change="headerChange(1)">一级组织机构内所有数据</el-radio></div></template></el-table-column><el-table-column prop="two_level"><template #header><div><el-radiov-model="tableHeader.level"label="2"@change="headerChange(2)">本级组织机构及下属组织机构数据</el-radio></div></template></el-table-column><el-table-column prop="three_level"><template #header><div><el-radio v-model="tableHeader.level" label="3" @change="headerChange(3)">本账号及下属组织机构数据</el-radio></div></template></el-table-column><el-table-column prop="four_level"><template #header><div><el-radio v-model="tableHeader.level" label="4" @change="headerChange(4)">本账号数据</el-radio></div></template></el-table-column><el-table-column prop="operation" label="其他指定机构"></el-table-column>
</el-table>

1.3 再通过插槽处理表格body体内容

同样,body体通过默认插槽配置对应的内容和选框,这个时候我采用的是el-checkbox,通过样式穿透改其样式让它在页面看起来更加符合产品设计要求。代码如下:

    <el-table:data="tableData"style="width: 100%"row-key="id"lazy:tree-props="{children: 'children', hasChildren: 'hasChildren'}"><el-table-column type="index" label="序号"></el-table-column><el-table-column prop="name" label="名称"></el-table-column><el-table-column prop="one_level"><template #header><div><el-radio v-model="tableHeader.level" label="1" @change="headerChange(1)">一级组织机构内所有数据</el-radio></div></template><template #default="{row, column, $index}"><div><el-checkboxv-model="tableHeader['one_level'+$index]":checked="checked['one_level'+$index]":label="column.property+$index":disabled="cutIdx !== 1"@change="itemChange(column.property+$index, $index)">勾选 {{$index}}~{{row.id}}</el-checkbox></div></template></el-table-column><el-table-column prop="two_level"><template #header><div><el-radiov-model="tableHeader.level"label="2"@change="headerChange(2)">本级组织机构及下属组织机构数据</el-radio></div></template><template #default="{row, column, $index}"><div><el-checkboxv-model="tableHeader['two_level'+$index]":checked="checked['two_level'+$index]":label="column.property+$index":disabled="cutIdx !== 2"@change="itemChange(column.property+$index, $index)">勾选 {{$index}}~{{row.id}}</el-checkbox></div></template></el-table-column><el-table-column prop="three_level"><template #header><div><el-radio v-model="tableHeader.level" label="3" @change="headerChange(3)">本账号及下属组织机构数据</el-radio></div></template><template #default="{row, column, $index}"><div><el-checkboxv-model="tableHeader['three_level'+$index]":checked="checked['three_level'+$index]":label="column.property+$index"@change="itemChange(column.property+$index, $index)":disabled="cutIdx !== 3">勾选 {{$index}}~{{row.id}}</el-checkbox></div></template></el-table-column><el-table-column prop="four_level"><template #header><div><el-radio v-model="tableHeader.level" label="4" @change="headerChange(4)">本账号数据</el-radio></div></template><template #default="{row, column, $index}"><div><el-checkboxv-model="tableHeader['four_level'+$index]":checked="checked['four_level'+$index]":label="column.property+$index"@change="itemChange(column.property+$index, $index)":disabled="cutIdx !== 4">勾选 {{$index}}~{{row.id}}</el-checkbox></div></template></el-table-column><el-table-column prop="operation" label="其他指定机构"><template #default><el-button type="success" size="mini">查看</el-button></template></el-table-column>
</el-table>

1.4 让body体中的选框和表头中的选框产生关联

表头互斥,代表这一但选中其中一个表头,只能选择body体中当前列的选框内容,这个时候我根据表头的选择,禁用非当前列。
当然,如果有特殊需求,你可以适当的自己修改一下。

headerChange(idx) {if (this.cutIdx !== idx) {this.ids.forEach((_, i) => {if (this.checked[this.cutIdx]) {this.$nextTick(() => {this.$set(this.tableHeader,i + this.levelMap.get(this.cutIdx),false)this.$set(this.checked, this.levelMap.get(this.cutIdx) + i, false)})}})this.cutIdx = idxconsole.log(idx, this.tableHeader, this.levelMap.get(idx), '不同列')}// 清空所有for (const key in this.tableHeader) {if (key !== 'level') {console.log(key, 123123)this.$nextTick(() => {this.$set(this.tableHeader, key, false)this.$set(this.checked, key, false)})}}// 当前下面所有都选中this.ids.forEach((_, i) => {// console.log(levelMap.get(idx) + i)this.$nextTick(() => {this.$set(this.tableHeader, this.levelMap.get(idx) + i, true)this.$set(this.checked, this.levelMap.get(idx) + i, true)console.log(this.tableHeader,this.checked[this.levelMap.get(idx) + i])})})},itemChange(item, idx) {console.log(item, idx, this.checked[item])// this.tableHeader[idx] = truelet _this = thisthis.$nextTick(() => {if (this.checked[item]) {_this.$set(this.checked, item, false)for (const key in this.tableHeader) {if (key === 'level') {this.tableHeader[key] = ''}}} else {_this.$set(this.checked, item, true)}const res = this.ids.every((_, i) => {return this.checked[this.levelMap.get(this.cutIdx) + i] === true})if (res) {for (const key in this.tableHeader) {if (key === 'level') {this.tableHeader[key] = this.cutIdx + ''// this.$set(this.tableHeader, key, this.cutIdx + '')console.log(key, this.levelMap.get(this.cutIdx), this.tableHeader)}}}})},// 递归获取idsgetIds(data) {data.forEach(v => {this.ids.push(v.id)if (v.children && v.children.length > 0) {this.getIds(v.children)}})}

二、将 el-tree 整棵树设为禁用状态

element 官方给出的示例中,是给部分 tree 节点通过 disabled 属性设置禁用状态。它所写的仅是一段静态代码,如果是后端返回得数据很多,我们想要在查看状态下禁用所有树形节点,显然非常麻烦,需要处理大量的数据。
所以这里通过巧用 props 属性,来实现树形节点的禁用效果。

<el-treeref="permissionTree":data="permissionTree":show-checkbox="showCheckbox"node-key="keyId":props="defaultProps">
</el-tree>
data() {return {defaultProps: {label: 'labelName',children: 'childrenList',disabled: this.isDisabled,}}
},
methods: {isDisabled() {return this.$route.params.type === 'view' ? true : false;}
}

三、动态表格合并

一些项目中,需要使用到 elementUI table 组件的方法 :span-method=“objectSpanMethod” 进行单元格的动态合并。查看了官方 API 后,发现简单、直白、明了,无法满足下图业务的需求。所以参考了一些其他的网络资料,具体的思路:在动态处理从后端拿回来的数据的时候,是需要从数据中找到一个唯一的“标识”去判断是否是相同种类的数据。然后根据这个“标识”去做逻辑判断。
在这里插入图片描述

  1. 首先需要在 data 中定义需要数据,根据数组中存储的标识去合并数据

    data() {return {// 合并单元格需要的数据spanArr: [], //遍历数据时,根据相同的标识去存储记录pos: 0, // 二维数组的索引};},
    
  2. 然后在 methods 中定义方法去处理标识(需要合并的数据单元格)

    methods: {// 列表数据处理函数getSpanArr(data) {//页面展示的数据,不一定是全部的数据,所以每次都清空之前存储的 保证遍历的数据是最新的数据。以免造成数据渲染混乱this.spanArr = [];this.pos = 0;//遍历数据data.forEach((item, index) => {//判断是否是第一项if (index === 0) {this.spanArr.push(1);this.pos = 0;} else {//不是第一项时,就根据标识去存储if (data[index].sdTarget === data[index - 1].sdTarget) {// 查找到符合条件的数据时每次要把之前存储的数据+1this.spanArr[this.pos] += 1;this.spanArr.push(0);} else {// 没有符合的数据时,要记住当前的indexthis.spanArr.push(1);this.pos = index;}}});console.log(this.spanArr, this.pos);},// 指定合并的单元格函数objectSpanMethod({ row, column, rowIndex, columnIndex }) {// 页面列表上 表格合并行 -> 第几列(从0开始)// 需要合并多个单元格时 依次增加判断条件即可if (columnIndex === 0) {// 二维数组存储的数据 取出const _row = this.spanArr[rowIndex];const _col = _row > 0 ? 1 : 0;return {rowspan: _row,colspan: _col,};//不可以return {rowspan:0, colspan: 0} 会造成数据不渲染, 也可以不写else,eslint过不了的话就返回false} else {return false;}},},
  3. 最后在 created 或 mounted 中调用处理函数将异步获取到的数据传递过去进行处理:

    mounted() {this.tableData = …. //异步获取数据this.getSpanArr(this.tableData);
    },
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/121061.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vert.x 源码解析(4.x)(一)——Future源码解析

目录 1. 简介 在现代的软件开发中&#xff0c;异步编程已经变得非常重要。它可以提高应用程序的并发性能&#xff0c;使应用程序能够更有效地处理大量的并行操作。Vert.x 是一个面向事件驱动、非阻塞的异步编程框架&#xff0c;它提供了丰富的工具来简化异步编程的复杂性。 如…

解决windows下git操作提示用户名密码错误的问题

当代码从一个平台切换到另一个平台的时候&#xff0c;需要做两步操作&#xff0c;第一步就是更新git的仓库地址&#xff0c;在项目的.git/config文件里面修改&#xff0c;这一步做完之后&#xff0c;就可以推送代码到新的仓库了&#xff0c;这里就是重点来了。 一般第一次推动代…

JVM虚拟机对象探秘

对象的创建 Java是一门面向对象的编程语言&#xff0c;创建对象通常只是通过new关键字。 对象创建过程 当Java虚拟机遇到一条字节码new指令时&#xff0c;首先将去检查这个指令的参数是否能在常量池中定位到 一个类的符号引用&#xff0c;并且检查这个符号引用&#xff08;类…

如何设计微服务

一、序幕 最近在思考&#xff0c;自己哪些不足&#xff0c;需要学习点什么&#xff1f;看着Java基础知识&#xff0c;千遍一律&#xff0c;没有太大的动力需深挖&#xff0c;只能在写业务项目的时候边写边思考边夯实自己的基础。于是看了网上的一些资料&#xff0c;结合以前面试…

linux并发服务器 —— 多线程并发(六)

线程概述 同一个程序中的所有线程均会独立执行相同程序&#xff0c;且共享同一份全局内存区域&#xff1b; 进程是CPU分配资源的最小单位&#xff0c;线程是操作系统调度执行的最小单位&#xff1b; Linux环境下&#xff0c;线程的本质就是进程&#xff1b; ps -Lf pid&…

101序列检测器

本次所做设计&#xff0c;使用数字电路芯片实现的101序列检测器。电路图如下&#xff1a; 主要首先要根据需求画出状态转移方程&#xff0c;然后写出它的逻辑表达式。最后根据所选触发器种类确定电路图。序列由按键控制输入&#xff0c;按键按下&#xff0c;代表输入1 &#xf…

RT-Thread UART

UART 简介 UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;通用异步收发传输器&#xff0c;UART 作为异步串口通信协议的一种&#xff0c;工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。 UART …

Error: Cannot find module ‘timers/promises‘

这个错误很要命 他会导致你本机所有的npm 命令全部报错 首先 这个错误是因为 npm 与 node版本不匹配导致的 最简单的办法就是 查一下你安装的这个npm 的版本适配那个版本的 node 然后将本地的node删除 控制面板写在node 然后去官方文档现在与本地npm 匹配的node.js 这样 你执行…

【LeetCode-中等题】146. LRU 缓存

文章目录 题目方法一&#xff1a;直接继承LinkedHashMap调用api方法二&#xff1a;自定义LinkedHashMap HashMap ListNode LinkedHashMap 题目 LRU缓存是什么&#xff1a;LRU缓存机制&#xff0c;你想知道的这里都有 实现 LRU 缓存算法 方法一&#xff1a;直接继承Linked…

彻底学会Unity从网上加载资源到场景

使用类WWW 该类实例化的对象可以存储多种多媒体资源&#xff0c;只需要在构造函数中附上可访问的资源链接 Unity 中&#xff0c;WWW 类用于实例化互联网上的资源&#xff0c;如文本、图像、音频和视频等。WWW 实例化的对象可以存储多种多媒体素材。以下是一些常见的例子&…

固定资产卡片乱怎么管理

固定资产卡片是记录公司固定资产信息的重要工具&#xff0c;如果管理不善&#xff0c;容易造成卡片混乱、数据错误等问题。 为了避免这种情况的发生&#xff0c;可以采取以下措施&#xff1a;  建立完善的资产管理制度&#xff0c;明确固定资产的分类、标准和使用情况&#x…

C# 中什么是重写(子类改写父类方法)

方法重写是指在继承关系中&#xff0c;子类重新实现父类或基类的某个方法。这种方法允许子类根据需要修改或扩展父类或基类的方法功能。在面向对象编程中&#xff0c;方法重写是一种多态的表现形式&#xff0c;它使得子类可以根据不同的需求和场景提供不同的方法实现。 方法重…

热点探测技术架构设计与实践

1. 概述 说到热点问题&#xff0c;首先我们先理解一下什么是热点&#xff1f; 热点通常意义来说&#xff0c;是指在一段时间内&#xff0c;被广泛关注的物品或事件&#xff0c;例如微博热搜&#xff0c;热卖商品&#xff0c;热点新闻&#xff0c;明星直播等等&#xff0c;所以…

You must install at least one postgresql-client-<version> package

使用主机上的映射端口来连接到 PostgreSQL 数据库。例如&#xff0c;使用以下命令连接到数据库&#xff1a; psql -h localhost -p 5432 -U postgres出现下面的问题&#xff1a; 分析&#xff1a; 如果您在运行 psql 命令时遇到错误消息 You must install at least one pos…

应用案例 | 3D视觉引导解决方案汽车零部件上下料

Part.1 行业背景 三维视觉引导技术在国内外汽车零部件领域得到了广泛应用。随着汽车制造业的不断发展和创新&#xff0c;对于零部件的加工和装配要求越来越高&#xff0c;而三维视觉引导技术能够帮助企业实现更精确、更高效的零部件上下料过程。 纵览国外&#xff0c;部分汽车…

若依 MyBatis改为MyBatis-Plus

主要内容&#xff1a;升级成mybatis-plus&#xff0c;代码生成也是mybatis-plus版本 跟着我一步一步来&#xff0c;就可完成升级&#xff01; 检查&#xff1a;启动程序&#xff0c;先保证若依能启动 第一步&#xff1a;添加依赖 这里需要在两个地方添加&#xff0c;一个是最…

软件游戏丢失d3dcompiler_47.dll怎么办?这个几个解决方法可修复

当我们在玩软件游戏时&#xff0c;有时候会出现丢失 d3dcompiler_47.dll 的问题&#xff0c;这让我们感到非常困扰。d3dcompiler_47.dll 是 DirectX 中的一个重要组件&#xff0c;如果它丢失了&#xff0c;那么很多游戏就无法正常运行。我将和大家分享一下我在解决软件游戏丢失…

计算机竞赛 基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

小白学go基础03-了解Go项目的项目结构

我们先来看看第一个Go项目——Go语言自身——的项目结构是什么样的。Go项目的项目结构自1.0版本发布以来一直十分稳定&#xff0c;直到现在Go项目的顶层结构基本没有大的改变。 截至Go项目commit 1e3ffb0c&#xff08;2019.5.14&#xff09;&#xff0c;Go1.0 项目结构如下&am…

Ansible学习笔记15

1、roles&#xff1a;&#xff08;难点&#xff09; roles介绍&#xff1a; roles&#xff08;角色&#xff09;&#xff1a;就是通过分别将variables&#xff0c;tasks及handlers等放置于单独的目录中&#xff0c;并可以便捷地调用他们的一种机制。 假设我们要写一个playbo…