当前位置: 首页 > article >正文

vue3.2 + vxe-table4.x 实现多层级结构的 合并、 展开、收起 功能

<template>
  <div style="padding: 20px">
    <vxe-table border :data="list" :height="800" :span-method="rowspanMethod">
      <vxe-column title="一级类目" field="category1">
        <template #default="{ row }">
          <a-space>
            <span>{{ row.category1 }}</span>
            <a-button @click="toggleCategoryExpand(row, '1')">
              {{ showText(row, '1') ? '收起' : '展开' }}
            </a-button>
          </a-space>
        </template>
      </vxe-column>
      <vxe-column title="二级类目" field="category2">
        <template #default="{ row }">
          <a-space>
            <span>{{ row.category2 }}</span>
            <a-button
              v-if="showText(row, '1')"
              @click="toggleCategoryExpand(row, '2')"
            >
              {{ showText(row, '2') ? '收起' : '展开' }}
            </a-button>
          </a-space>
        </template>
      </vxe-column>
      <vxe-column title="三级类目" field="category3"></vxe-column>
      <vxe-column title="报告金额" field="amount"></vxe-column>
      <vxe-column title="合计" field="total"></vxe-column>
    </vxe-table>
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue'
import XEUtils from 'xe-utils'

export default defineComponent({
  setup() {
    const flattenedData = [
      {
        id: '0',
        category: '人工成本',
        parentId: null
      },
      {
        id: '0-0',
        parentId: '0',
        category: '人工成本0-0'
      },
      {
        id: '0-0-0',
        parentId: '0-0',
        category: '人工成本0-0-0'
      },
      {
        id: '0-0-1',
        parentId: '0-0',
        category: '人工成本0-0-1'
      },
      {
        id: '0-1',
        parentId: '0',
        category: '人工成本0-1'
      },
      {
        id: '0-1-0',
        parentId: '0-1',
        category: '人工成本0-1-0'
      },
      {
        id: '0-1-1',
        parentId: '0-1',
        category: '人工成本0-1-1'
      }
    ]
    const treeData = XEUtils.toArrayTree(flattenedData)
    const treeDataTemp = JSON.parse(JSON.stringify(treeData))
    const renderTreeData = ref(treeDataTemp)
    const list = ref([])

    // 工具方法
    const toColTreeData = (treeData) => {
      const options = { children: 'children' }
      const list = []
      const keyMap = {}
      XEUtils.eachTree(
        treeData,
        (item, index, result, paths, parent) => {
          keyMap[item.id] = item
          item.keys = parent ? parent.keys.concat([item.id]) : [item.id]
          if (!item.children || !item.children.length) {
            const row = {}
            item.keys.forEach((key, index) => {
              const level = index + 1
              const obj = keyMap[key]
              row[`category${level}`] = obj.category
              row[`id${level}`] = obj.id
            })
            list.push(row)
          }
        },
        options
      )
      return list
    }

    const rowspanMethod = ({ row, _rowIndex, column, visibleData }) => {
      const fields = ['category1', 'category2']
      const cellValue = row[column.field]
      if (cellValue && fields.includes(column.field)) {
        const prevRow = visibleData[_rowIndex - 1]
        let nextRow = visibleData[_rowIndex + 1]
        if (prevRow && prevRow[column.field] === cellValue) {
          return { rowspan: 0, colspan: 0 }
        } else {
          let countRowspan = 1
          while (nextRow && nextRow[column.field] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex]
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 }
          }
        }
      }
    }

    renderTreeData.value.forEach((item) => {
      if (item.children.length) {
        item.children = []
      }
    })

    list.value = toColTreeData(renderTreeData.value)

    const toggleCategoryExpand = (row, level) => {
      if (level === '1') {
        toggleLevelOne(row)
      }
      if (level === '2') {
        toggleLevelTwo(row)
      }
    }
    const toggleLevelOne = (row) => {
      const { id1 } = row
      const item = renderTreeData.value.find((item) => item.id === id1)
      if (item.children.length) {
        item.children = []
      } else {
        const a = treeData.find((item) => item.id === id1)
        item.children = JSON.parse(JSON.stringify(a.children))
        item.children.forEach((child) => {
          child.children = []
        })
      }
      list.value = toColTreeData(renderTreeData.value)
    }

    const toggleLevelTwo = (row) => {
      const { id1, id2 } = row
      const item1 = renderTreeData.value.find((item) => item.id === id1)
      const item2 = item1.children.find((item) => item.id === id2)
      if (item2.children.length) {
        item2.children = []
      } else {
        const a1 = treeData.find((item) => item.id === id1)
        const a2 = a1.children.find((item) => item.id === id2)
        item2.children = a2.children
      }
      list.value = toColTreeData(renderTreeData.value)
    }

    const showText = (row, level) => {
      const { id1, id2 } = row
      if (level === '1') {
        const item = renderTreeData.value.find((item) => item.id === id1)
        if (item) {
          return item.children.length
        }
        return false
      }
      if (level === '2') {
        const item1 = renderTreeData.value.find((item) => item.id === id1)
        const item2 = item1.children.find((item) => item.id === id2)
        if (item2) {
          return item2.children.length
        }
        return false
      }
    }

    return {
      rowspanMethod,
      toggleCategoryExpand,
      list,
      showText
    }
  }
})
</script>

在这里插入图片描述


http://www.kler.cn/a/565129.html

相关文章:

  • 嵌入式Qt的动平衡仪完整设计方案
  • 大模型的工作原理:分布式训练入门
  • 【FL0088】基于SSM和微信小程序的奶茶点餐小程序
  • Linux的部分常用基础指令
  • Windows AD组策略完整实战文档 | 企业级安全配置指南
  • 35. Spring Boot 2.1.3.RELEASE 应用监控【监控信息可视化】
  • STM32内存五区及堆栈空间大小设置(启动文件浅析)
  • Island架构与部分水合技术解析:下一代Web应用的性能突围
  • 基于C语言模拟一个简易的冯诺依曼式计算机CPU的工作(bupt计导)
  • 无人机的最长悬停时间为什么短于最长飞行时间
  • 蓝桥杯 Java B 组之记忆化搜索(滑雪问题、斐波那契数列)
  • Redis哨兵集群搭建
  • 使用git管理uniapp项目
  • 2025-2-26-C++ 学习:关联容器( Primer 第十一章 (上))空奁如月不欺人,明月归来君试看。
  • python poetry添加某个git仓库的某个分支
  • 基于Python实现的【机器学习】小项目教程案例
  • docker-compose方式启动Kafka Sasl加密认证(无zk)
  • 使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)
  • 东信营销科技巨额补贴仍由盈转亏:毛利率大幅下滑,现金流告急
  • VUE2.0+elementUI+腾讯云点播上传视频