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