ftl模版表格中根据条件合并行
序章
想到开发中遇到每个ftl模版表格合并行操作时都需要逻辑代码实现比较繁琐,闲着无聊开发个工具解决下。思路是这样的:
每个表格的需要合并列的合并的规则基本一致,也就是数据一样即可在首行的格子设置rowspan,并将除首行外相同数据清空。如以下表格:<table border="1"> <tr> <th>年龄</th> <th>姓名</th> </tr> <tr> <td>23</td> <td>李莉</td> </tr> <tr> <td>23</td> <td>王五</td> </tr> <tr> <td>24</td> <td>赵四</td> </tr> </table>
那这个表格中相同的年龄就可以合并
<table border="1">
<tr>
<th>年龄</th>
<th>姓名</th>
</tr>
<tr>
<!--设置rowspan-->
<td rowspan="2">23</td>
<td>李莉</td>
</tr>
<tr>
<!--清空相同的年龄数据-->
<td></td>
<td>王五</td>
</tr>
<tr>
<td>24</td>
<td>赵四</td>
</tr>
</table>
以上,我们理清楚三点:
- 需要设置的合并列
- 清空的数据列
- 设置rowspan的值
话不多说,开整
步骤1. 新建一个接口RowSpanInterface
public interface RowSpanInterface {
String rowSpanKey();
void cleanRowSpanKey();
void setRowSpan(int row);
}
步骤2. 新建ftl模版
<#assign header25="font-size: 11px;font-family: 楷体;text-align: center;font-weight: bold; background-color: #BE0001; color: #FFFFFF;height: 25px;" />
<#assign center9_list_tr="text-align: center;vertical-align: middle;font-size: 10px;font-family: 楷体;height: 25px;" />
<table>
<caption>战区TOP10</caption>
<tr style="${header25}">
<th>临期月</th>
<th style="border-left-color: #f8e099">top10排名</th>
<th>园区</th>
<th>合同编号</th>
<th>客户名称</th>
<th>客户集群</th>
<th>临期未签约面积(m²)</th>
<th>临期未签约单元</th>
<th>合同开始日期</th>
<th>合同结束日期</th>
<th>合同归属人</th>
<th>是否KA客户</th>
<th>客户owner</th>
</tr>
<#if areaTop10List??>
<#list areaTop10List as item>
<tr style="${center9_list_tr};">
<#if item.month??>
<td rowspan="${item.rowSpan!"1"}">${item.month!""}</td>
</#if>
<td>${item.rank!""}</td>
<td>${item.mallName!""}</td>
<td>${item.contNo!""}</td>
<td>${item.customerName!""}</td>
<td>${item.customerCluster!""}</td>
<td>${item.unSignedSquare!""}</td>
<td>${item.unSignedStore!""}</td>
<td>${item.contStartDate!""}</td>
<td>${item.contEndDate!""}</td>
<td>${item.contOwner!""}</td>
<td>${item.isKACustomer!""}</td>
<td>${item.customerOwner!""}</td>
</tr>
</#list>
</#if>
3. 新建数据模型,并实现接口
@Data
public class AreaTop10VacancyModel implements RowSpanInterface {
private int rowSpan;
//临期月
private String month;
//top10排名
private int rank;
//园区
private String mallName;
//合同编号
private String contNo;
//客户名称
private String customerName;
//客户集群
private String customerCluster;
//临期未签约面积
private String unSignedSquare;
//临期未签约单元
private String unSignedStore;
//合同开始日期
private String contStartDate;
//合同结束日期
private String contEndDate;
//合同归属人
private String contOwner;
//是否KA客户
private String isKACustomer;
//客户owner
private String customerOwner;
@Override
public String rowSpanKey() {
return month;
}
@Override
public void cleanRowSpanKey() {
this.month = null;
}
}
4. 核心处理类
public class RowSpanHandler {
public static void handle(List<? extends RowSpanInterface> list) {
// 使用通配符类型进行流操作,避免强制类型转换
Map<String, Long> countMap = list.stream()
.map(item -> (RowSpanInterface) item)
.collect(Collectors.groupingBy(RowSpanInterface::rowSpanKey, Collectors.counting()));
Set<String> cacheKeys = new HashSet<>();
for (RowSpanInterface rowSpanInterface : list) {
String rowSpanKey = rowSpanInterface.rowSpanKey();
int rowSpan = countMap.get(rowSpanKey).intValue();
if (cacheKeys.contains(rowSpanKey)) {
rowSpanInterface.cleanRowSpanKey();
} else {
cacheKeys.add(rowSpanKey);
rowSpanInterface.setRowSpan(rowSpan);
}
}
}
}
5. 调用
List<AreaTop10VacancyModel> areaTop10List = getTop10List();
RowSpanHandler.handle(areaTop10List);
至此,相同的临期月排名数据已合并,这个方案后期可以维护升级成多个相同列进行多次合并,如果相同临期月中排名一样的需要再次合并的需求,这里不再赘述
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小仓鼠!
评论