可直接使用,按照配置,支持多层级合并行
文章目录
页面使用
在需要调用的页面使用:
html
<el-table v-loading="loading" :data="tableList" height="500px" style="width: 100%" border
:span-method="handleSpanMethod">
...
javascript
import mergeCellsMixin from '@/mixins/mergeCellsMixin'
mixins: [mergeCellsMixin],
method:{
getList() {
console.log('getList', this.form)
this.tableList = [{
id: '12987122',
demandNo: '12347214823',
deliveryLocation: '送货地点1',
applicant: '申请人1',
costCenter: '王小虎',
amount1: '234',
amount2: '3.2',
amount3: 10
}, {
id: '12987123',
demandNo: '12347214823',
deliveryLocation: '送货地点1',
applicant: '申请人1',
costCenter: '王小虎',
amount1: '165',
amount2: '4.43',
amount3: 12
}, {
id: '12987124',
demandNo: '12347214823',
deliveryLocation: '送货地点2',
applicant: '申请人1',
costCenter: '王小虎',
amount1: '324',
amount2: '1.9',
amount3: 9
}, {
id: '12987125',
demandNo: '12347214823',
deliveryLocation: '送货地点2',
applicant: '申请人1',
costCenter: '王小虎',
amount1: '621',
amount2: '2.2',
amount3: 17
}, {
id: '12987126',
demandNo: '12347214823',
deliveryLocation: '送货地点2',
applicant: '申请人2',
costCenter: '王小虎',
amount1: '539',
amount2: '4.1',
amount3: 15
}, {
id: '12987126',
demandNo: '123472148000',
deliveryLocation: '送货地点2',
applicant: '申请人2',
costCenter: '王小虎',
amount1: '539',
amount2: '4.1',
amount3: 15
}]
this.getSpanArr()
},
// 获取合并数组
getSpanArr() {
// key: 当前字段名 dependsOn: 当前字段依赖哪些前面字段
this.mergeRules = [
{ key: 'demandNo', dependsOn: [] },
{ key: 'deliveryLocation', dependsOn: ['demandNo'] },
{ key: 'applicant', dependsOn: ['demandNo', 'deliveryLocation'] },
{ key: 'costCenter', dependsOn: ['demandNo', 'deliveryLocation', 'applicant'] }
]
this.spanArr = this.createSpanArr(this.tableList, this.mergeRules)
},
// 合并单元格
handleSpanMethod({ row, column, rowIndex, columnIndex }) {
// 获取对应的合并数组
const spanMap = {
0: this.spanArr.demandNo, // 需求单合并
1: this.spanArr.deliveryLocation, // 送货地点合并
2: this.spanArr.applicant, // 申请人合并
3: this.spanArr.costCenter // 成本中心合并
};
return this.mergeCells(spanMap, { row, column, rowIndex, columnIndex })
},
}
mergeCellsMixin.js
javascript
export default {
data() {
return {
}
},
methods: {
/**
* @description 创建合并数组
* @param {Array} tableList 表格数据
* @param {Array} mergeRules 合并规则 ({key: 当前字段名 dependsOn: 当前字段依赖哪些前面字段})
* @example tableList = [
{demandNo: '', deliveryLocation: '',applicant: '',costCenter: '',materialName:''}]
* @example mergeRules = [
{ key: 'demandNo', dependsOn: [] },
{ key: 'deliveryLocation', dependsOn: ['demandNo'] },
{ key: 'applicant', dependsOn: ['demandNo', 'deliveryLocation'] },
{ key: 'costCenter', dependsOn: ['demandNo', 'deliveryLocation', 'applicant'] }]
* */
createSpanArr(tableList, mergeRules) {
// 存放每个字段对应的合并数组
const spanArr = {}
// 记录每个字段当前合并块的起始索引位置
const posMap = {}
// 最终返回值
const result = {}
// 初始化每个字段的数组
mergeRules.forEach(rule => {
spanArr[rule.key] = [];
result[rule.key] = spanArr[rule.key];
posMap[rule.key] = 0;
});
for (let i = 0; i < tableList.length; i++) {
if (i === 0) {
mergeRules.forEach(rule => {
// 所有字段在第一行都开启新块,设为 1
spanArr[rule.key].push(1)
// 当前字段从第 0 行开始合并
posMap[rule.key] = 0
});
} else {
// 当前行
const curr = tableList[i]
// 上一行
const prev = tableList[i - 1]
for (const rule of mergeRules) {
// key: 当前字段名 dependsOn: 当前字段依赖哪些前面字段
const { key, dependsOn } = rule
// 检查依赖字段是否一致
const depsMatch = dependsOn.every(dep => curr[dep] === prev[dep])
if (!depsMatch) {
// 如果依赖不一致,则当前字段开启新块,并重置后续字段
spanArr[key].push(1);
posMap[key] = i;
// 后续字段都设为新块
const index = mergeRules.indexOf(rule);
for (let j = index + 1; j < mergeRules.length; j++) {
const nextKey = mergeRules[j].key;
spanArr[nextKey].push(1);
posMap[nextKey] = i;
}
break;
} else {
// 当前字段值一致时继续合并
if (curr[key] === prev[key]) {
// 当前字段值一致时,行数加 1
spanArr[key][posMap[key]] += 1;
// 当前行标记为被合并
spanArr[key].push(0);
} else {
// 否则开启新块
spanArr[key].push(1);
// 更新当前字段的起始行号
posMap[key] = i;
}
}
}
}
}
return result;
},
/**
* @description 合并单元格
* @param {Object} spanMap 创建的合并数组
* @param {} row 当前行
* @param {} column 当前列
* @param {} rowIndex 当前行索引
* @param {} columnIndex 当前列索引
* @example spanMap = {
0: this.spanArr.demandNo,
1: this.spanArr.deliveryLocation,
2: this.spanArr.applicant,
3: this.spanArr.costCenter }
* */
mergeCells(spanMap, { row, column, rowIndex, columnIndex }) {
// 获取对应的 spanArr
const spanArr = spanMap[columnIndex];
if (spanArr) {
const r = spanArr[rowIndex];
const c = spanArr[rowIndex] > 0 ? 1 : 0;
return [r, c];
}
return [1, 1]; // 默认不合并
}
}
}