功能介绍:支付宝小程序手写表格实现行内合并,依据动态数据自动计算每次需求合并的值,本次记录行内合并,如果列内合并,同理即可实现
前端技术:grid布局 display:grid
先看实现效果:

axml:
<view class="leasePlanView" style="padding-top:{{systemInfo.statusBarHeight + systemInfo.titleBarHeight + 15}}px">
<view class="tableInfo por">
<view class="head com_flex_between">
<view a:for="{{ tableHead }}" class="item table-item com_font_26">
{{item.title}}
</view>
</view>
<view class="tableContent grid-container">
<view a:for="{{ order_detail.billList }}" a:for-index="idx" class="grid-row">
<view class="grid-cell com_flex_center">
{{item.term}}
</view>
<view class="grid-cell com_flex_center">
内容
</view>
<view class="grid-cell com_flex_center {{mergeInfo[idx].shouldMerge ? 'merge-cell-' + mergeInfo[idx].mergeRows : ''}} {{(!mergeInfo[idx].showNormal && !mergeInfo[idx].shouldMerge) ? 'hide-cell' : ''}}">
<block a:if="{{mergeInfo[idx].showNormal}}">
<view class="com_color_third">-</view>
</block>
<block a:elif="{{mergeInfo[idx].shouldMerge}}">
<view class="com_flex_center_column com_font_20">
我是合并数据
</view>
</block>
</view>
<view class="grid-cell com_flex_center_column">
内容
</view>
</view>
</view>
</view>
</view>
js:
最重要的处理逻辑是processMergeData这个方法,根据实际需求可自行修改,只要是表格合并,处理逻辑都是相通的。
Page({
data: {
tableHead: [{
title: '第一列'
},
{
title: '第二列'
},
{
title: '第三列'
},
{
title: '第四列'
}
],
mergeInfo: [], // 存储合并信息
order_detail:{
billList:[{
term: '1',
discountAmount: '',
},{
term: '2',
discountAmount: '',
},{
term: '3',
discountAmount: '100',
},{
term: '4',
discountAmount: '100',
},{
term: '5',
discountAmount: '200',
},{
term: '6',
discountAmount: '200',
},{
term: '7',
discountAmount: '300',
},{
term: '8',
discountAmount: '300',
},{
term: '9',
discountAmount: '300',
},{
term: '10',
discountAmount: '',
},{
term: '11',
discountAmount: '',
},{
term: '12',
discountAmount: '',
}]
}
},
onLoad(query) {
this.processMergeData();
},
// 处理合并数据
processMergeData() {
const { billList } = this.data.order_detail;
const mergeInfo = [];
// 遍历数据计算需要合并的行
for (let i = 0; i < billList.length; i++) {
const current = billList[i];
if (current.discountAmount === null || !current.discountAmount) {
// discountAmount 为 null 时正常显示
mergeInfo[i] = {
shouldMerge: false,
mergeRows: 1,
showNormal: true // 添加标记,表示需要正常显示
};
continue;
}
console.log(mergeInfo[i],'mergeInfo[i]mergeInfo[i]')
// 如果当前行已经被标记为合并,跳过
if (mergeInfo[i]) continue;
let mergeCount = 1;
// 向下查找相同 discountAmount 值的行
for (let j = i + 1; j < billList.length; j++) {
if (billList[j].discountAmount === current.discountAmount) {
mergeCount++;
// 标记被合并的行
mergeInfo[j] = {
shouldMerge: false,
mergeRows: 0,
showNormal: false
};
} else {
break;
}
}
// 标记合并起始行
mergeInfo[i] = {
shouldMerge: mergeCount > 1,
mergeRows: mergeCount,
showNormal: false
};
}
console.log(mergeInfo,'mergeInfo')
this.setData({ mergeInfo });
}
});
css实现:
重点在grid布局和动态合并行数
.leasePlanView {
width: 100%;
min-height: 100vh;
}
.bill_box{
padding: 12rpx 16rpx 0;
}
.tableInfo {
padding: 30rpx 16rpx;
width: 710rpx;
margin: -32rpx auto 0;
background-color: white;
border-radius: 20rpx;
z-index: 2;
}
.tableTitle {
margin-bottom: 16rpx;
padding: 0 14rpx;
height: 32rpx;
font-family: PingFangSC-Medium, PingFang SC;
}
.tableInfo .head {
background: rgba(255, 68, 36, 0.05);
border-radius: 20rpx 20rpx 0rpx 0rpx;
margin-top: 28rpx;
border: 1rpx solid #E8E8E8;
border-bottom: none;
}
.table-item{
height: 85rpx;
width: 169rpx;
text-align: center;
font-family: PingFangSC-Medium, PingFang SC;
line-height: 85rpx;
}
.tableInfo .item {
font-weight: 500;
color: #000000;
}
/* 表格边框实现 */
.tableContent{
border: 1rpx solid #E8E8E8;
display: grid;
grid-template-columns: repeat(1, 1fr);
}
.border-bottom{
border-bottom: 1rpx solid #E8E8E8;
}
.border-left{
border-left: 1rpx solid #E8E8E8;
}
.grid-row:last-child .grid-cell{
border-bottom: none;
}
.amount:first-child{
border-left: none;
}
.returnDate .bottom {
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 22rpx;
margin-top: 4rpx;
}
.tableInfo .amount {
font-weight: 400;
flex: auto;
position: relative;
}
.tableInfo .totalAmount{
width: 169rpx;
height: 85rpx;
text-align: center;
}
.grid-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
border: 1rpx solid #E8E8E8;
}
.grid-row {
display: contents;
}
.grid-cell {
padding: 10rpx;
border-bottom: 1rpx solid #E8E8E8;
border-left: 1rpx solid #E8E8E8;
height: 85rpx;
text-align: center;
}
.grid-cell:first-child {
border-left: none;
}
/* 动态合并行数的样式 */
.merge-cell-2 {
grid-row: span 2;
height: 170rpx;
}
.merge-cell-3 {
grid-row: span 3;
height: 255rpx;
}
.merge-cell-4 {
grid-row: span 4;
height: 340rpx;
}
.hide-cell {
display: none;
}