element table:
<el-table :data="tableData" border style="width: 100%" :span-method="arraySpanMethod">
<el-table-column type="index" width="55" label="序号" align="center" />
<el-table-column prop="date" label="1" min-width="100" align="center" />
<el-table-column prop="date" label="2" min-width="100" align="center" />
<el-table-column prop="address" label="3" min-width="100" align="center" />
<el-table-column prop="field" label="异常字段" min-width="100" align="center" />
<el-table-column prop="config" label="配置" min-width="100" align="center" />
<el-table-column prop="photo" label="是否齐全" min-width="100" align="center" />
<el-table-column prop="boundary" label="是否在边界内" min-width="100" align="center" />
<el-table-column prop="issue" label="问题修改" min-width="100" align="center" />
</el-table>
const tableData = ref([
{
id: '1',
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
field: '字段1',
config: '配置1',
photo: '是',
boundary: '是',
issue: '未修改'
},
{
id: '1',
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
field: '字段1',
config: '配置1',
photo: '是',
boundary: '是',
issue: '已修改'
},
{
id: '2',
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
field: '字段1',
config: '配置1',
photo: '是',
boundary: '是',
issue: '已修改'
},
{
id: '3',
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
field: '字段3',
config: '配置3',
photo: '是',
boundary: '是',
issue: '已修改'
},
])
const tableDataComputed = computed(() => {
const result = [];
const idMap = new Map();
tableData.value.forEach((item, index) => {
if (!idMap.has(item.id)) {
idMap.set(item.id, { index, count: 1, columns: {} });
result.push(item);
} else {
idMap.get(item.id).count++;
for (const key in item) {
if (item[key] === result[idMap.get(item.id).index][key]) {
if (!idMap.get(item.id).columns[key]) {
idMap.get(item.id).columns[key] = { start: idMap.get(item.id).index, end: index };
} else {
idMap.get(item.id).columns[key].end = index;
}
} else {
idMap.get(item.id).columns[key] = null;
}
}
}
});
return { data: result, idMap };
});
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
const { idMap } = tableDataComputed.value;
const id = row.id;
const { count, index, columns } = idMap.get(id);
if (columnIndex === 0) {
return { rowspan: 1, colspan: 1 };
}
if (columns[column.property] && rowIndex === columns[column.property].start) {
const span = columns[column.property].end - columns[column.property].start + 1;
return { rowspan: span, colspan: 1 };
} else if (columns[column.property] && rowIndex > columns[column.property].start && rowIndex <= columns[column.property].end) {
return { rowspan: 0, colspan: 0 };
} else {
return { rowspan: 1, colspan: 1 };
}
};
tableDataComputed 计算属性:
- 使用
Map 来存储每个 id 对应的行索引、出现次数以及需要合并的列的信息。
- 遍历
tableData,如果 id 不在 idMap 中,初始化该 id 的信息;如果 id 已经存在,增加计数并检查列的内容是否相同,如果相同则记录合并的起始和结束索引。
arraySpanMethod 方法:
- 检查当前列是否是序号列(
columnIndex === 0),如果是,则不合并。
- 对于其他列,如果当前行是合并的起始行,则返回合并的行数和列数;否则返回
{ rowspan: 0, colspan: 0 } 表示不显示该单元格。