借鉴了小谷69同学的帖子,又根据自己的需求进行了调整。
需求为:序号根据业务id合并,合并后的业务数据再根据时间进行二次合并。
一、准备两个变量
data() {
return {
// 合并行
mergeArr: [],
// 排序号
indexNum: {},
}
}
二、准备合并行方法
colMethod(columnArr, data) {
// columnArr 合并行所在的列字段
// data 需要合并的表格数据
let column = {}
let position = 0
// 遍历合并的列数据
columnArr.forEach((prop) => {
column[prop] = []
// 遍历合并的行数据
data.forEach((row, rowIndex) => {
// 第N列第一行
column[prop][rowIndex] = [1, 1]
if (rowIndex === 0) {
// 记录当前行号
position = 0
} else if (row[prop] === data[rowIndex - 1][prop]) {
// 当前行数据等于上一行,根据记录的行号,计算需要合并几行。
column[prop][position][0] += 1
// 当前行 隐藏不显示
column[prop][rowIndex][0] = 0
} else {
// 不相等之后,重置记录行号
position = rowIndex
}
})
})
return column
}
三、准备表格调用的合并方法 :span-method="objectSpanMethod
// 表格调用的合并方法
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
let arr = this.mergeArr[column.property] || []
if (column.type == 'index' && this.mergeArr['id'])
return this.mergeArr['id'][rowIndex]
else if (arr.length) return arr[rowIndex]
else[1, 1]
},
四、合并逻辑
getList() {
const _this = this;
// 计算合并的行
this.mergeArr = this.colMethod(['id'], this.reportList)
// 浅拷贝处理数据
let dataBase = Array.from(this.reportList);
let saleIdArr = this.colMethod(['id'], dataBase)
// 先根据saleId合并第一次,将数据源根据合并下标处理为多段数据源
let newData = []
saleIdArr.saleId.forEach( (item, index) => {
if (item[0] > 0) {
let res = []
for (let i = 0; i < item[0]; i++) {
res.push(dataBase.slice(0,1)[0])
this.$delete(dataBase, 0)
}
newData.push(res)
}
})
// 根据合并后的数据,分段处理time的合并行下标
let outArr = []
for (let i = 0; i < newData.length; i++) {
let obt = _this.colMethod(['time'], newData[i]);
if (obt.outboundTime.length > 0) {
outArr.push(obt.outboundTime)
}
}
// 处理time合并行
let finishRes = []
outArr.forEach( item => {
if (item.length > 1) {
for (let i = 0; i < item.length; i++) {
finishRes.push(item[i])
}
} else {
finishRes.push(item[0])
}
})
// 赋值给总合并行集合
this.mergeArr.outboundTime = finishRes
//排列序号
this.indexObj()
}
// 排列序号
indexObj() {
let num = 0;
this.mergeArr['id'].forEach((item, index) => {
if (item[0] != 0) {
this.indexNum[index] = num += 1
}
})
},
<el-table-column label="序号" align="center" width="55" type="index"
:resizable="false" :index="indexMethod" />
五、处理排序
<el-table-column label="序号" align="center" width="55" type="index"
:resizable="false" :index="indexMethod" />
// 排列序号
indexObj() {
let num = 0;
this.mergeArr['id'].forEach((item, index) => {
if (item[0] != 0) {
this.indexNum[index] = num += 1
}
})
},
// 自定义序号
indexMethod(index) {
return this.indexNum[index]
},
借鉴文章el-table表格的行合并以及合并后序号的处理_elementui表格合并行序号出错_小谷69的博客-CSDN博客
附加:原生table合并行
需求不变,因打印功能,el-table适配性不好,改为原生table布局,合并行要素为rowspan,所以在遍历数据时要分开控制rowspan,同理根据业务id分段数据源,分别处理各自的time合并行
<tr v-for="(item, index) in reportList" :key="index" class="text-center">
<td style="width: 60px" v-if="item.rowspan > 0" :rowspan="item.rowspan">{{ item.orderList }}</td>
<td style="width: 150px" v-if="item.rowspans > 0" :rowspan="item.rowspans">{{ item.time }}</td>
</tr>
getList() {
// 根据saleId计算合并的行
let saleIdSpan = this.getSpanArrN(this.reportList, 'id')
let orderList = 1
saleIdSpan.forEach((item, index) => {
this.reportList[index].rowspan = item
this.reportList[index].orderList = item > 0 ? orderList++ : orderList
})
// 浅拷贝表格数据,用于分段截取
let dataBase = Array.from(this.reportList);
// 先根据saleId一级合并行,将数据源根据合并下标处理为多段数据源
let newData = []
saleIdSpan.forEach( (item, index) => {
if (item > 0) {
let res = []
for (let i = 0; i < item; i++) {
res.push(dataBase.slice(0,1)[0])
this.$delete(dataBase, 0)
}
newData.push(res)
}
})
// 根据合并后的数据,分段处理outboundTime的合并行下标
let outArr = []
for (let i = 0; i < newData.length; i++) {
let obt = this.getSpanArrN(newData[i], 'time')
outArr = outArr.concat(obt)
}
// 赋值outboundTime合并行
outArr.forEach((item, index) => {
this.reportList[index].rowspans = item
})
},
getSpanArrN(data, prop) {
let count = 0; // 用来记录需要合并行的起始位置
let mergeObj = []
data.forEach((item, index) => {
if (index === 0) {
mergeObj.push(1);
} else {
if (item[prop] === data[index - 1][prop]) {
mergeObj[count] += 1;
mergeObj.push(0);
} else {
count = index;
mergeObj.push(1);
}
}
})
return mergeObj
}