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

发布时间 2023-09-27 17:14:05作者: 程序员肉包子

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

思路流程

    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 },
            ],
          },
        ],
      }
      this.dataSource = this.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 newArr = [] // 合并数组对象 let mergedArray = data.map((item, index) => { let commonObj = { title: item.title, } let valueMaxArr = { ...commonObj } item.paramList.forEach((paramItem) => { let str = paramItem.paramName valueMaxArr[str] = paramItem.expression }) return valueMaxArr }) // 清空原有数据,并将新的数据覆盖 dataSource.value.length = 0 dataSource.value.push(...mergedArray) // 公共表头 + 动态表头 生成 最终表头 columns.value = [...columnsNode] // 动态表头 changeCoulmns(data) return dataSource.value } // 步骤二: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 >