vue3项目table表格动态表头生成+行数据合并

这两处地方是动态的,由后端数据返回

思路流程

    1,后端返回数据二次处理

    2,根据后端数据生成动态表头

    3,利用antd 的 customRender 与 rowSpan 设置行合并

 完整代码

<template>
  <Table
    :data-source="dataSource"
    :columns="columns"
    :pagination="false"
    :scroll="{ y: 380 }"
    bordered
    :rowClassName="(_, index) => (index % 2 === 1 ? 'table-striped' : null)"
  >
  </Table>
</template>
<script setup>
  // 显示的数据
  const dataSource = ref([])
  // 最终表头
  const columns = ref([])
  // 公共表头
  const columnsNode = [
    {
      title: '序号',
      dataIndex: 'key',
      key: 'key',
      width: '72px',
      align: 'center',
      customRender: (value, row, index) =>
            columnsInit(value, row, index, 3),
        },
    },
    {
      title: '验证数据ID',
      align: 'center',
      dataIndex: 'validationDataId',
      key: 'validationDataId',
      width: '292px',
      customCell: (record, rowIndex, column) => ({
        style:{
          color: '#0058FB',
          cursor: 'pointer',
        },
        onClick: () => {
          console.log(record, rowIndex, column);      
        },
      })
    },
    {
      title: '预期结果',
      align: 'center',
      children: []
    },
     {
      title: h('div',{},['验证数据信息',h(EditOutlined,{ style:{color:'#0058FB',paddingLeft:'8px',fontSize: '17px',cursor: 'pointer'} ,onClick(){ open.value = true}})]),
      align: 'center',
      children: []
    },
  ]
// 前端虚拟数据
async initTable() {
      // let res = await GetQualifiedDayData(this.params)
      // this.dataSource = this.nodeTable(res)
      // 接口获取数据,此处用data假数据代替返回值
      let data = {
        data: [
          {
            pointName: '名称1',
            limitRange: '<10',
            datas: [
              { date: '1月', valueMax: 100, valueMin: 5, numTotal: 30 },
              { date: '2月', valueMax: 120, valueMin: 15, numTotal: 60 },
              { date: '3月', valueMax: 70, valueMin: 4, numTotal: 50 },
              { date: '4月', valueMax: 60, valueMin: 15, numTotal: 40 },
              { date: '5月', valueMax: 200, valueMin: 2, numTotal: 70 },
              { date: '6月', valueMax: 150, valueMin: 7, numTotal: 90 },
            ],
          },
          {
            pointName: '名称2',
            limitRange: '<12',
            datas: [
              { date: '1月', valueMax: 53, valueMin: 1, numTotal: 55 },
              { date: '2月', valueMax: 86, valueMin: 2, numTotal: 87 },
              { date: '3月', valueMax: 97, valueMin: 2, numTotal: 98 },
              { date: '4月', valueMax: 87, valueMin: 3, numTotal: 89 },
              { date: '5月', valueMax: 97, valueMin: 4, numTotal: 99 },
              { date: '6月', valueMax: 68, valueMin: 2, numTotal: 67 },
            ],
          },
        ],
      }
      dataSource = nodeTable(data)
    },
    // 步骤一:数据二次处理
    // 原数据
    // {
    //   pointName: '名称1',
    //   limitRange: '<10',
    //   datas: [
    //     { date: '1月', valueMax: 100, valueMin: 5, numTotal: 30 },
    //     { date: '2月', valueMax: 120, valueMin: 15, numTotal: 60 },
    //     ...
    //   ],
    // },
    // 转换为
    // { pointName: '名称1', limitRange: '<10', attr: '最高值', data.1月: '100', data.2月: 120, ... }
    // { pointName: '名称1', limitRange: '<10', attr: '最低值', data.1月: '5', data.2月: 15, ... }
    // { pointName: '名称1', limitRange: '<10', attr: '总次数', data.1月: '30', data.2月: 60, ... }

const nodeTable = (data) => {

    let arr = []
    res.data.forEach((item) => {
    // 提取公共部分属性
    let commonObj = {
        pointName: item.pointName,
        limitRange: item.limitRange,
     }
     // 添加各自独有的属性值
     let valueMaxArr = { ...commonObj, attr: '最高值' }
     let valueMinArr = { ...commonObj, attr: '最低值' }
     let numTotalArr = { ...commonObj, attr: '总次数' }
     item.datas.forEach((item2) => {
     let str = item2.date
     valueMaxArr['data.' + str] = item2.valueMax
     valueMinArr['data.' + str] = item2.valueMin
     numTotalArr['data.' + str] = item2.numTotal
     })
     arr.push(valueMaxArr)
     arr.push(valueMinArr)
     arr.push(numTotalArr)
    })
    arr = arr.map((item, index) => {
      item.id = index + 1
      return item
    })
    console.log(arr, 'arar')
    // 公共表头 + 动态表头 生成 最终表头
    columns = [...columnsNode , ...changeCoulmns(res)]

    return arr

}
// 步骤二:table表头二次处理
    // [
    //   {
    //     title: '1月',
    //     dataIndex: 'data.1月',
    //     align: 'center',
    //   },
    //   {
    //     title: '2月',
    //     dataIndex: 'data.2月',
    //     align: 'center',
    //   },
    //   ...
    // ]
 const changeCoulmns = (res) => {
    let addColumns = []
    if (res.length) {
      addColumns = res[0].paramList.map((item,index)=>{
        let str = item.paramName
        return {
          title: str,
          dataIndex: str,
          align: 'center',
        }
      })
    }

    try {
      columnsNode.forEach((item)=>{
        res.forEach((iten)=>{
          // 注意 返回的数据中必须要有title而且必须和公共表头里面的title一样,否则对应不上数据
          if (item.title === iten.title) {
            // 把数据插入到具体的位置
            item.children.splice(0,0,...addColumns) 
            throw new Error('return false')
          }
        })
      })
    } catch (error) {}
  }
// 步骤三:行合并 rowSpan 设值为 0 时,设置的表格不会渲染。
    columnsInit(value, row, index, num) {
      const obj = {
        children: value,
        attrs: {},
      }
      if (index === 0 || index % num === 0) {
        obj.attrs.rowSpan = num
      }
      for (let i = 1; i <= num; i++) {
        if (index % num === i) {
          obj.attrs.rowSpan = 0
        }
      }
      return obj
    },
  },
<script >

 路径:https://blog.csdn.net/weixin_43123984/article/details/125780644?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-5-125780644-blog-106985535.235%5Ev38%5Epc_relevant_sort_base3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-5-125780644-blog-106985535.235%5Ev38%5Epc_relevant_sort_base3&utm_relevant_index=10

posted @ 2023-09-27 17:09  程序员肉包子  阅读(1200)  评论(0编辑  收藏  举报