1.业务需求:
合并指定的列 相同数据的单元格
2.效果展示:
3. 实现思路:
el-table组件主要靠span-method方法实现合并
表格数据是后端提供的动态数据
实现代码
<template>
<el-card class="full-table" shadow="hover" style="margin-top: 8px">
<el-table :data="state.tableData" :span-method="objectSpanMethod">
<el-table-column " prop="aaa" label="aaa" show-overflow-tooltip />
<el-table-column prop="bbb" label="bbb" show-overflow-tooltip />
<el-table-column prop="ccc" label="ccc" show-overflow-tooltip />
<el-table-column prop="ddd" label="ddd" show-overflow-tooltip />
<el-table-column prop="eee" label="eee" show-overflow-tooltip />
</el-table>
</el-card>
</template>
<script lang="ts" setup name="aaa">
import { onMounted, reactive } from 'vue';
import type { TableColumnCtx } from 'element-plus'
import { getAPI } from '/@/utils/axios-utils';
import { api } from '/@/api-services/api';
import { detailInput, } from '/@/api-services/models';
interface SpanMethodProps {
row: detailInput
column: TableColumnCtx<detailInput>
rowIndex: number
columnIndex: number
}
const state = reactive({
loading: false,
tableData: [] as any,
queryParams: {
warehouseId: 0,
inventoryId: 0,
isCloud: 0,
includeZero: 0
},
cellList1: [] as any, // 第一列合并单元格信息
cellList2: [] as any, // 其他列合并单元格信息
});
onMounted(async () => {
await handleQuery();
});
// 获取列表数据
const handleQuery = async () => {
state.loading = true
let params = Object.assign(state.queryParams);
let res = await getAPI(api).apiPost(params);
state.tableData = res.data.result ?? []
state.loading = false
//将相同的仓库Id排序,方便后续合并
let idList = state.tableData.sort((a: any, b: any) => {
return a.warehouseId - b.warehouseId
})
state.cellList1 = computeCell(idList, "warehouseId", 'inventoryId');
state.cellList2 = computeCell(idList, "inventoryId", "warehouseId");
}
// 根据需要合并的单元格字段排序
const computeCell = (tableBody: any, key: any, key1: any) => {
// tableBody 为 表格数据 , key,key1 为需要合并的字段
let cellList = [];
let count: any;
for (let i = 0; i < tableBody.length; i++) {
if (i == 0) {
cellList.push(1);
count = 0;
} else {
// 其他列需要满足的条件
if (key == 'inventoryId') {
if (tableBody[i][key] == tableBody[i - 1][key] && tableBody[i][key1] == tableBody[i - 1][key1]) {
// 比较前后两个元素是否相等,相等的话对应索引的元素的值+1,并且在其后增加一个0占位(防止合并过后表格数据错位),否则的话增加一个1占位,并记录当前索引,往复循环,构造一个给 rowspan 取值判断合并的数组:
cellList[count] += 1;
cellList.push(0);
} else {
cellList.push(1);
count = i;
}
} else {
// 第一列需要满足的条件
if (tableBody[i][key] == tableBody[i - 1][key]) {
cellList[count] += 1;
cellList.push(0);
} else {
cellList.push(1);
count = i;
}
}
}
}
return cellList;
}
// 合并单元格
const mergeCellVertical = (cellList: any, rowIndex: any) => {
const rowCell = cellList[rowIndex];
if (rowCell > 0) {
const colCell = 1;
return {
rowspan: rowCell,
colspan: colCell,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
// 合并单元格
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
// 第一列的合并
if (columnIndex === 0) {
return mergeCellVertical(state.cellList1, rowIndex);
}
// 其他列合并
if (columnIndex === 1 || columnIndex === 2 || columnIndex === 3) {
return mergeCellVertical(state.cellList2, rowIndex);
}
}
</script>