场景:后端返回排好序的列表,前端按照将前几行按某一列字段进行行合并,后几行按照某几个列字段进行行合并,以实现1对2,2对4,4对8的table效果
// 页面使用,定义列字段参数
export function getContractColumns(): ProTableProps["columns"] {
return [
{
title: "序号",
dataIndex: "no",
render(text: any, record: any, index: number) {
return index + 1;
},
fixed: "left",
},
{
title: "编号1",
dataIndex: "contractNo1",
// 根据编号1进行行合并
rowMergeKey: ["contractNo1"],
},
{
title: "编号2",
dataIndex: "contractNo2",
// 根据编号1和编号2,2个字段进行行合并
rowMergeKey: ["contractNo1", "contractNo2"],
},
]
// table自定义组件中
const formatColumns = useCallback(() => {
const dataSource = tableData;
return (
columns?.map((column:ProTableColumnConfig) => {
return {
...column,
// 关键代码----------start
onCell: (rowData, rowIndex: number) => {
if (column.rowMergeKey?.length && dataSource?.length) {
const { rowMergeKey } = column;
// 过滤条件
const filters = {}
// 关键字段拼接字符串
let keyString = ''
// 每列每行,行合并值
const rowSpanMap = {}
rowMergeKey.forEach((mergeKey: string) => {
filters[mergeKey] = null;
})
forEach(dataSource, (row, i) => {
const rowKeyString = rowMergeKey.map((mergeKey: string, i:number) => row[mergeKey]).join('-');
if (rowKeyString !== keyString) {
// 重新赋值
forEach(filters, (v: any, k: string) => {
filters[k] = row[k]
})
// 计算当前行重复数
const rowSameCount = filterArrayByFilters(dataSource, filters).length;
rowSpanMap[i] = rowSameCount;
keyString = rowKeyString
} else {
rowSpanMap[i] = 0;
}
})
return { rowSpan: rowSpanMap[rowIndex] }
}
return {}
}
// 关键代码----------end
};
}) || []
);
}, []);
// 根据对象过滤数组
export function filterArrayByFilters(array: any, filters: any, startIndex: number) {
let bool = true;
let hasFirst = false;
let preIndex = startIndex;
return array.filter((obj: any, i: number) => {
// 第一个重复没出现之前为true
if (!hasFirst) {
bool = true;
}
if (i < startIndex) {
bool = false;
}
// 对每个过滤条件进行检查,确保对象符合所有条件
const isRepeat = Object.keys(filters).every(key => {
return (obj[key] === filters[key]) && bool;
});
// 紧挨着的才算重复次数
if (isRepeat && !hasFirst) {
hasFirst = true;
bool = true;
preIndex = i;
} else if (hasFirst) {
if (isRepeat && (i - preIndex === 1)) {
bool = true;
preIndex = i;
} else {
bool = false;
}
} else {
bool = false;
}
return bool;
});
}