You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Thymeleaf将ResultSet数据映射到HTML周状态表并实现状态顺延

自行车周状态表格实现方案

核心思路是不要在模板层做复杂的状态匹配和顺延逻辑,先在Controller层把数据预处理成模板可直接渲染的结构,再传给页面,避免Thymeleaf写冗余难维护的判断逻辑。

步骤1:Controller层数据预处理

首先调整Controller里的逻辑,提前算好每辆自行车在周内每一天的最终状态:

  • 先固定当前自然周的7个日期,按周一到周日排序生成weekDates列表,统一使用LocalDate类型(截断时分秒,避免日期匹配失败)
  • 把查询得到的weekList按自行车ID分组,再按状态变更日期升序排序
  • 对每辆自行车,先取周前最后一条状态作为初始状态,再逐天遍历周日期:如果当天有状态变更,就更新当前状态为最新值,把当天的状态存入双层映射结构,最终得到bikeId -> 日期 -> 状态详情的映射表
  • 把周日期列表、预处理好的日状态映射、全量自行车列表都传入Model

参考代码:

// 1. 生成当前自然周的7个日期(周一到周日,示例以2022-05-03当周为例,可替换为动态计算逻辑)
List<LocalDate> weekDates = new ArrayList<>();
LocalDate weekStart = LocalDate.of(2022,5,3);
for (int i=0; i<7; i++){
    weekDates.add(weekStart.plusDays(i));
}

// 2. 按bikeId分组状态记录
Map<Long, List<BikeWeek>> statusGroupByBike = weekList.stream()
        .collect(Collectors.groupingBy(BikeWeek::getId));

// 3. 预处理每辆车每天的状态
Map<Long, Map<LocalDate, BikeWeek>> dailyStatusMap = new HashMap<>();
for (Bike bike : bikes) {
    List<BikeWeek> bikeStatuses = statusGroupByBike.getOrDefault(bike.getId(), Collections.emptyList())
            .stream()
            .sorted(Comparator.comparing(BikeWeek::getDate))
            .toList();
    // 初始状态取周前最后一条(日期早于周起始的那条,即SQL中row_number=1且不在周区间的记录)
    BikeWeek currentStatus = bikeStatuses.stream()
            .filter(s -> s.getDate().before(java.sql.Date.valueOf(weekStart)))
            .findFirst()
            .orElse(null);
    Map<LocalDate, BikeWeek> dayStatus = new HashMap<>();
    for (LocalDate day : weekDates) {
        // 检查当天是否有状态变更,有则更新当前状态
        final LocalDate targetDay = day;
        Optional<BikeWeek> dayChange = bikeStatuses.stream()
                .filter(s -> s.getDate().equals(java.sql.Date.valueOf(targetDay)))
                .findFirst();
        if (dayChange.isPresent()){
            currentStatus = dayChange.get();
        }
        dayStatus.put(day, currentStatus);
    }
    dailyStatusMap.put(bike.getId(), dayStatus);
}

// 4. 传入Model
model.addAttribute("weekDates", weekDates);
model.addAttribute("dailyStatusMap", dailyStatusMap);
model.addAttribute("bikes", bikes);

注意:如果BikeWeek.getDate()返回的是java.util.Date类型,建议在SQL查询时直接转为日期类型截断时间,或者在Java层统一转成LocalDate再做比较,避免时分秒不一致导致日期匹配失败。

步骤2:Thymeleaf模板渲染

模板层只做遍历渲染,不需要写状态顺延的判断逻辑:

  • 表头遍历weekDates生成周一到周日的列,不用硬写固定日期
  • 表体先遍历bikes生成每一行的自行车信息列
  • 每行内再遍历weekDates,直接从dailyStatusMap里取对应自行车、对应日期的状态渲染即可

参考模板代码:

<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th style="text-align: left;">bike</th>
<th th:each="day : ${weekDates}" style="text-align: center;" th:text="${#temporals.format(day, 'EEEE')}"></th>
</tr>
</thead>
<tbody>
<tr th:each="bike : ${bikes}">
<td style="text-align: left;" th:text="${bike.name} + ' ' + ${bike.number}"></td>
<td th:each="day : ${weekDates}" style="text-align: center;">
    <span th:if="${dailyStatusMap[bike.id][day] != null}" 
          th:text="${dailyStatusMap[bike.id][day].status} + ' (' + ${dailyStatusMap[bike.id][day].name} + ' ' + ${dailyStatusMap[bike.id][day].surname} + ')'">
    </span>
    <span th:unless="${dailyStatusMap[bike.id][day] != null}">无状态记录</span>
</td>
</tr>
</tbody>
</table>
</div>

如果需要展示租用人姓名/姓氏,直接在单元格里取对应字段即可;如果某辆车完全没有状态记录,也可以自定义展示默认值。

内容的提问来源于stack exchange,提问作者Vitalii Pshenychniuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:24:57