动态合并单元格

131 阅读2分钟

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 };
    }
};

  1. tableDataComputed 计算属性:
  • 使用 Map 来存储每个 id 对应的行索引、出现次数以及需要合并的列的信息。
  • 遍历 tableData,如果 id 不在 idMap 中,初始化该 id 的信息;如果 id 已经存在,增加计数并检查列的内容是否相同,如果相同则记录合并的起始和结束索引。
  1. arraySpanMethod 方法:
  • 检查当前列是否是序号列(columnIndex === 0),如果是,则不合并。
  • 对于其他列,如果当前行是合并的起始行,则返回合并的行数和列数;否则返回 { rowspan: 0, colspan: 0 } 表示不显示该单元格。