element-ui树形表格,左边勾选,右边显示选中的数据-功能(如动图)

news2024/9/23 23:25:38

功能如图

功能需求

表格树形表格勾选数据,右边显示对应勾选的数据内容,选中客户,自动勾选所有的店铺(子级),选中其中一个店铺,自动勾选上客户(父级),同时会存在只有客户(下面没有子级的情况),该功能还涉及到全选(不细讲),搜索勾选,搜索其中一个店铺,或者搜索客户显示所有店铺在勾选(如上面动态图)

功能思路

第一步我们确认此时是勾选动作还是取消勾选动作

第二步我们确认此时勾选的数据是当前哪一个

第三步我们确认此时勾选类型的是客户还是店铺

第四步根据勾选动作和勾选类型去做不同的逻辑操作

1.此时是选中状态---此时是选中的是店铺,通过当前页的客户数据下的店铺数据循环跟我们当前选中的数据对比,找到当前选中的客户数据(leftParent),存在两种情况

  • 此时店铺所挂载客户不存在右边,需将客户同时勾选上并往右边加上数据
  • 此时店铺所挂载客户存在右边,只需将店铺数据往右边加

若是此时选中的是客户,存在两种情况

  • 存在有店铺的情况, (勾选客户会自动勾选店铺 触发下面点击店铺的操作)
  • 存在没有店铺 只有客户的情况 (重新写一种情况就是没有店铺,即当前点击的target.shopList没有值,或者为空数组)

2.此时是取消勾选状态--此时是选中的店铺,先通过当前页客户的数据下的店铺数据循环跟我们当前选中的数据对比,找到当前选中的客户数据(leftParent),并此时知道右边所有的数据循环跟当前选中的左边客户数据对比,找到此时右边跟左边的相同的数据(rightParent)

  • 此时找到相同的数据rightParent下的shopList的长度大于0,找到当前店铺的下标,然后取消勾选
  • 当rightParent的shopList的长度等于0时,说明此时的店铺数据全部取消勾选,此时要同时取消该客户的勾选

此时是取消勾选状态-此时选中的是客户,两种情况

  • 点击的客户是没有店铺的情况(直接取消该客户)
  • 点击的客户是存在店铺的情况(点击客户,触发点击事件把所有的店铺也取消勾选,走上面的店铺取消勾选事件)

数据结构

[
  {
    "custId": "460860740775766666",
    "custCode": "ZT10009999",
    "custName": "邵阳县永民雄新置业有限公司",
    "labels": null,
    "labelnames": "智屏传统(剔除福州),乐华代理商",
    "shopCodes": null,
    "shopList": [
      {
        "shopId": "460861654907518976",
        "shopCode": "DP20230625366666",
        "shopName": "智能家庭京东专卖店1号店",
        "labels": null,
        "labelnames": null
      },
      {
        "shopId": "460864194063667200",
        "shopCode": "DP202306258888888",
        "shopName": "酷友天猫优品旗舰店1号店",
        "labels": null,
        "labelnames": null
      },
      {
        "shopId": "460865727429906432",
        "shopCode": "DP20230625188888",
        "shopName": "酷友天猫优品旗舰店2号店",
        "labels": null,
        "labelnames": null
      },
      {
        "shopId": "460888467817926656",
        "shopCode": "DP20230625179999",
        "shopName": "智能家庭京东专卖店2号店",
        "labels": null,
        "labelnames": null
      }
    ]
  },
  {
    "custId": "470195685059002368",
    "custCode": "ZT10006888",
    "custName": "邵阳县大山贸易有限公司",
    "labels": null,
    "labelnames": null,
    "shopCodes": null,
    "shopList": null
  }
]

部分代码如下

            <el-table
              ref="filterCusTable"
              v-loading="leftLoading"
              :data="customerList"
              :show-header="true"
              tooltip-effect="dark"
              :header-cell-class-name="cellClass"
              default-expand-all
              :tree-props="{ children: 'shopList' }"
              row-key="custCode"
              max-height="600"
              min-height="400"
              @select="selectChange"
              @selection-change="handleSelectionChange"
            >
              <el-table-column type="selection" width="30"></el-table-column>
              <el-table-column
                label="客户名称"
                prop="custName"
              ></el-table-column>
              <el-table-column
                label="客户编码"
                prop="custCode"
              ></el-table-column>
              <el-table-column
                label="客户标签"
                prop="labelnames"
              ></el-table-column>
            </el-table>

/**
       * 用于树形表格多选,单选的封装
       * @param selection
       * @param row
       */
      selectChange(selection, row) {
        console.log('selection', selection, row)
        const isCust = Array.isArray(row.shopList)
        //勾选的客户把以下的店铺全部带上勾选
        if (isCust) {
          const isAdd = !this.leftSelectedList.some(
            (cust) => cust.custCode === row.custCode
          )
          console.log('isAdd', isAdd)
          // 这里得 nextTick
          this.$nextTick(() => {
            row.shopList.forEach((shop) =>
              this.$refs.filterCusTable.toggleRowSelection(shop, isAdd)
            )
          })
        }
      },


      //左侧客户选择
      handleSelectionChange(selections) {
        console.log('selections2', selections)
        if (this.initializing == true) return
        //selections是当前页勾选的数据 包含了客户和店铺
        //this.leftSelectedList 一开始进来页面此时左边已经勾选上的数据(切换分页的时候会跟着变化是当前页所勾选的数据)
        // 判断是新增还是减少
        let isAdd = false
        //当前选中的数据
        let target = null
        //选中的方法
        const toggleSelection = (row, selected) =>
          this.$refs.filterCusTable.toggleRowSelection(row, selected)
        console.log('selections2', selections)
        console.log('this.leftSelectedList', this.leftSelectedList)
        if (
          //可能会存在重复的数据
          selections.length > uniqBy(this.leftSelectedList, 'custCode').length
        ) {
          isAdd = true
          //创建一个具有唯一array值的数组,每个值不包含在其他给定的数组中
          target = difference(selections, this.leftSelectedList)[0]
        } else {
          // 取消选择
          target = difference(this.leftSelectedList, selections)[0]
        }

        this.leftSelectedList = selections
        //知道当前target点击的值是什么,就能区分我们当前勾选的是店铺还是客户
        //shopCode可能是null undefined和""
        const isShop = !!target.shopCode //此时就能知道点击的是店铺
        let parent = null
        //如果点击了店铺 通过当前页的数据循环找到当前满足一项的数据
        //就退出循环得到的数据就是父数据(客户)
        if (isShop) {
          parent = this.customerList.find((item) => {
            return (item.shopList || []).some(
              (shop) => shop.shopCode === target.shopCode
            )
          })
          console.log('parent', parent)
        }
        //此时选中
        if (isAdd) {
          if (isShop) {
            //选中的是店铺,需要同时也选中父级的客户行
            toggleSelection(parent, true)
            this.pushToRight(target)
          } else {
            // 当前选中父亲,
            //1.存在有店铺的情况, (勾选客户会自动勾选店铺 触发下面点击店铺的操作)
            //2.存在没有店铺 只有客户的情况 (重新写一种情况就是没有店铺,即当前点击的target.shopList没有值,或者为空数组)
            toggleSelection(target, true)
            this.pushToRight(target)
          }
        }
        //取消选中
        else {
          if (isShop) {
            //如果点击的是店铺 则取消店铺操作勾选 从右边的数据移除
            this.removeRightShop(target)
          } else {
            //如果点击的是客户,还是两种情况
            //1.存在有店铺的情况, (勾选客户会自动勾选店铺 触发下面点击店铺的操作)
            //2.存在没有店铺 只有客户的情况 (重新写一种情况就是没有店铺,即当前点击的target.shopList没有值,或者为空数组)

            //2取消选中客户 没有店铺的情况
            this.removeRightShop(target)
            //1有店铺的情况,判断它此时shopList有数据,取消勾选 自动触发方法
            target.shopList &&
              target.shopList.length > 0 &&
              target.shopList.forEach((row) => toggleSelection(row, false))
          }
        }
      },

      //选中---把数据往右边List加
      pushToRight(row) {
        console.log('row', row)
        const leftParent = this.customerList.find((item) => {
          return (item.shopList || []).some(
            (shop) => shop.shopCode === row.shopCode
          )
        })
        //leftParent可能会存在undefined的情况
        //判断右边的父级(客户)数据是否已经存在右边,并找到此时右边的父级(客户)数据
        const rightParent =
          leftParent &&
          this.rightCustomerList.find(
            (item) => item.custCode === leftParent.custCode
          )
        if (rightParent) {
          // 如果右边已经存在该店铺的客户,
          // 但找不到该店铺的存在则直接push进来
          if (
            !(rightParent.shopList || []).some(
              (shop) => shop.shopCode === row.shopCode
            )
          ) {
            rightParent.shopList.push({ ...row })
          }
        } else {
          //如果右边不存在该店铺的客户
          if (leftParent) {
            const parent = { ...leftParent } //浅拷贝 方便进行数据处理和操作
            parent.shopList = [{ ...row }] //浅拷贝展开操作,生成一个新的对象,用新对象将parent.shopList数组对象替换

            this.rightCustomerList.push(parent) //通过以上的操作 这样就不会影响左边的数据
            // 刷新右边的数据
            this.tableData = this.rightCustomerList.slice(
              (this.pageTwo - 1) * this.pagesize,
              this.pageTwo * this.pagesize
            )
          } else {
            //客户没有店铺的情况,直接添加
            //一定要记得深拷贝一份,否则会出现影响左边数据的存在(如取消勾选掉子的会splice干掉)
            if (!row.shopList || row.shopList.length == 0) {
              let pushRow = JSON.parse(JSON.stringify(row))
              this.rightCustomerList.push(pushRow)
              // 刷新右侧
              this.tableData = this.rightCustomerList.slice(
                (this.pageTwo - 1) * this.pagesize,
                this.pageTwo * this.pagesize
              )
            }
          }
        }
      },
      //取消选中 --把数据从左边删除
      removeRightShop(row) {
        const leftParent = this.customerList.find((item) => {
          return (item.shopList || []).some(
            (shop) => shop.shopCode === row.shopCode
          )
        })

        const rightParent =
          leftParent &&
          this.rightCustomerList.find(
            (item) => item.custCode === leftParent.custCode
          )
        //此时知道右边的当前选中右边选中的数据,然后拿到当前选中的数据,
        //通过当前拿到rightParent数据中的shopList来判断
        //shopList长度大于0的是店铺--取消客户下的店铺
        //shopList长度为0的时候 说明所有店铺都取消,同时要取消该客户

        /*   1.此时找到相同的数据rightParent下的shopList的长度大于0,找到当前店铺的下标,然后取消勾选
        2.当rightParent的shopList的长度等于0时,说明此时的店铺数据全部取消勾选,此时要同时取消该客户的勾选 */
        if (rightParent) {
          //客户有店铺的情况
          console.log('执行了几次', rightParent)
          const shopIndex = rightParent.shopList.findIndex(
            (shop) => shop.shopCode === row.shopCode
          )
          //获取到当前删除店铺的下标 然后取消勾选
          if (shopIndex > -1) {
            rightParent.shopList.splice(shopIndex, 1)
          }
          if (rightParent.shopList.length === 0) {
            const custIndex = this.rightCustomerList.findIndex(
              (item) => item.custCode === rightParent.custCode
            )
            if (custIndex > -1) {
              this.rightCustomerList.splice(custIndex, 1)
              // 刷新右侧
              this.tableData = this.rightCustomerList.slice(
                (this.pageTwo - 1) * this.pagesize,
                this.pageTwo * this.pagesize
              )
              // 左侧取消选中父级
              this.$refs.filterCusTable.toggleRowSelection(leftParent, false)
            }
          }
        } else {
          //客户没有店铺的情况
          console.log('row', row)
          if (!row.shopList || row.shopList.length == 0) {
            const custIndex = this.rightCustomerList.findIndex(
              (item) => item.custCode === row.custCode
            )
            console.log('custIndex', custIndex)
            if (custIndex > -1) {
              this.rightCustomerList.splice(custIndex, 1)
              // 刷新右侧
              this.tableData = this.rightCustomerList.slice(
                (this.pageTwo - 1) * this.pagesize,
                this.pageTwo * this.pagesize
              )
            }
          }
        }
      },

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity Image(RawImage) 实现按轴心放大缩小,序列化存储轴心信息,实现编译器窗口保存轴心

工作时分配给我的要实现的功能&#xff0c;写的时候遇到挺多的坑的&#xff0c;在此记录一下 效果 放大缩小的效果 2.编译器扩展窗口记录 实现点 1.Json序列化存储图片轴心位置, 放大倍率&#xff0c;放大所需要的事件 2.用了编译器扩展工具便于保存轴心信息坑点 1.Imag…

【Linux】多路转接 -- select函数

文章目录 1. 认识select函数2. select函数原型3. socket就绪条件4. select工作流程5. select服务器6. select的优缺点 首先我们要了解一下&#xff0c;什么是多路转接&#xff1f; 多路转接也叫多路复用&#xff0c;是一种用于管理多个IO通道的技术。它能实现同时监听和处理多个…

C++ 访问控制——公有继承、私有继承、保护继承

派生类继承了基类的全部数据成员和除了构造函数和析构函数之外的全部函数成员&#xff0c;但是这些成员的访问属性在派生的过程中是可以调整的。从基类继承的成员&#xff0c;其访问属性由继承方式控制。 基类的成员有public&#xff08;公有&#xff09;、protected&#xff…

ArduPilot开源代码之Companion Computers简单分析

ArduPilot开源代码之Companion Computers简单分析 1. 源由2. 伴机系统2.1 APSync2.2 DroneKit2.3 FlytOS2.4 Maverick2.5 ROS2.6 Rpanion-server 3. 总结4. 参考资料 1. 源由 从稳定性&#xff0c;社区群体&#xff0c;以及开源方式的角度看&#xff0c;Ardupilot是不错的选择…

骑砍二 ATC MOD 使用教程与应用案例解析

骑砍二 ATC MOD 使用教程与应用案例解析 作者&#xff1a;blibli-财不外漏 / NEXUSMODS-PuepleKarmen 案例MOD依赖&#xff1a;ATC - Adonnay’s Troop Changer & AEW - Adonnay’s Exotic Weaponry & New Armor 文本编辑工具&#xff1a;VS Code&#xff08;推荐使用&…

【小沐学NLP】在线AI绘画网站(百度:文心一格)

文章目录 1、简介2、文心一格2.1 功能简介2.2 操作步骤2.3 使用费用2.4 若干示例2.4.1 女孩2.4.2 昙花2.4.3 山水画2.4.4 夜晚2.4.5 古诗2.4.6 二次元2.4.7 帅哥 结语 1、简介 当下&#xff0c;越来越多AI领域前沿技术争相落地&#xff0c;逐步释放出极大的产业价值&#xff0…

Amazon CloudFront 部署小指南(四)- CloudFront Function 基础与诊断

内容简介 本文适用于希望使用 Amazon CloudFront Functions 提升 Amazon CloudFront 边缘计算能力的用户&#xff0c;旨在帮助您更好的进行 CloudFront Functions 的开发、调试、测试、部署等工作。 首先我们会对 CloudFront Function 做个简单的介绍&#xff0c;然后分为七个步…

全志F1C200S嵌入式驱动开发(应用程序开发)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 我们在开发soc驱动的时候,很多情况下也要验证下当前的驱动功能是否正确。当然除了验证驱动功能之外,我们还要编写业务代码和流程代码。这中间就和各行各业有关了,有的是算法,有…

Redis BigKey案例

面试题&#xff1a; 阿里广告平台&#xff0c;海量数据里查询某一固定前缀的key小红书&#xff0c;你如何生产上限制keys*/flushdb/flushall等危险命令以防止误删误用&#xff1f;美团&#xff0c;MEMORY USAGE命令你用过吗&#xff1f;BigKey问题&#xff0c;多大算big&#…

GODOT游戏引擎简介,包含与unity性能对比测试,以及选型建议

GODOT&#xff0c;是一个免费开源的3D引擎。本文以unity作对比&#xff0c;简述两者区别和选型建议。由于是很久以前写的ppt&#xff0c;技术原因视频和部分章节丢失了。建议当做业务参考。 GODOT目前为止遇到3个比较重大的基于&#xff0c;第一个是oprea的合作奖&#xff0c;…

【redis】redis的认识和安装

目录 1.redis是什么2.Redis的特点3.安装redis4.设置远程连接4.1 开启隧道4.2 可视化客户端连接4.3 开启防火墙 5.redis常见数据类型5.1 redis的一些全局命令5.2 数据结构 6. redis的典型应用---缓存&#xff08;cache&#xff09;6.1 使用redis做缓存6.2 缓存穿透&#xff0c;缓…

【绪论0】

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.0 引言No.1 操作系统的概念功能和定义一、操作系统的概念和定义1、电脑的演变 二、操作系统的功能和目标 No.2 操作系统的特征一、并发二、共享三、虚拟四、异步 No.3 操作系统的发展与分类一、手工操作阶段二、批处理阶段…

Windows11 家庭中文版关于本地组策略编辑器gpedit.msc找不到即打不开的解决办法(征诚小张售后实测有效)

Windows11 家庭中文版关于本地组策略编辑器gpedit.msc找不到即打不开的解决办法 根本原因&#xff1a;是因为Windows11家庭中文版的 版本系统没内置安装本地策略组编辑器 好了废话不多说 直接说解决办法 第一步 首先电脑上新建一个空文本文件 输入以下内容&#xff1a; echo o…

Android Studio安装AI编程助手Github Copilot

csdn原创谢绝转载 简介 文档链接 https://docs.github.com/en/copilot/getting-started-with-github-copilot 它是个很牛B的编程辅助工具&#xff0c;装它&#xff0c;快装它&#xff0e; 支持以下IDE: IntelliJ IDEA (Ultimate, Community, Educational)Android StudioAppC…

Qt应用开发(基础篇)——时间类 QDateTime、QDate、QTime

一、前言 时间类QDateTime、QDate、QTime、QTimeZone保存了Qt的时间、日期、时区信息&#xff0c;常用的时间类部件都会用到这些数据结构&#xff0c;常用概念有年、月、日、时、分、秒、毫秒和时区&#xff0c;时间和时区就关系到时间戳和UTC的概念。 UTC时间&#xff0c;又称…

FPGA初步学习之串口发送模块【单字节和字符串的发送】

串口相关简介 UART 在发送或接收过程中的一帧数据由4部分组成&#xff0c;起始位、数据位、奇偶校验位和停止位&#xff0c;如图所示。其中&#xff0c;起始位标志着一帧数据的开始&#xff0c;停止位标志着一帧数据的结束&#xff0c;数据位是一帧数据中的有效数据。 通常用…

【贪心算法】leetcode刷题

贪心算法无固定套路。 核心思想&#xff1a;先找局部最优&#xff0c;再扩展到全局最优。 455.分发饼干 两种思路&#xff1a; 1、从大到小。局部最优就是大饼干喂给胃口大的&#xff0c;充分利用饼干尺寸喂饱一个&#xff0c;全局最优就是喂饱尽可能多的小孩。先遍历的胃口&a…

Win11大小写切换图标关闭方法

大家使用Win11操作系统的时候经常会切换大小写键盘&#xff0c;有些游戏本在游戏过程中需要切换大小写&#xff0c;这个时候电脑的屏幕就会出现大小写切换的图标而影响游戏体验&#xff1b; 那么想要关闭Win11电脑上大小写切换图标&#xff0c;又不知道具体怎么操作&#xff0c…

VS Code search tab

Vs Code search 栏的应用 我发现&#xff0c;在vs code种&#xff0c;上面的搜索框的功能非常多。在最初使用vscode时候&#xff0c;以为这只是一个普通的搜索框。后来&#xff0c;发现它可以用于全局搜索文件&#xff0c;比如使用ctrlshiftp。 后来&#xff0c;我发现&#xf…

lifecycleScope Unresolved reference

描述 导入了lifecycle.lifecycleScope&#xff0c;但是在activity中使用lifecycleScope报错出现Unresolved reference找不到引用。 导包 import androidx.lifecycle.lifecycleScope使用 lifecycleScope.launch(Dispatchers.IO) {...}错误 方案 代码中的activity继承Activ…