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

Spring Boot按状态及周一至周六分组统计线索并实现图表可视化

问题分析

原代码存在以下核心问题,导致无法实现按线索状态+创建日期所属周一至周六分组统计的需求:

  • 完全未使用线索的创建日期字段,未实现按周几分组的核心逻辑
  • 数组操作逻辑错误:getAndIncrement()先返回当前值再自增,后续counter.get()会指向已自增后的索引,导致数组赋值位置错误,甚至触发索引越界
  • 统计逻辑混乱:每遍历一条线索就创建LeadsDashboard并添加到集合,最终得到的是逐条线索的记录,而非聚合后的统计结果
  • 状态判断冗余:使用多个独立if而非else if,可能导致同一条线索被重复处理
修复方案

1. 明确数据模型定义

确保LeadsDashboard包含统计所需的核心字段:

public class LeadsDashboard {
    private String status;
    private int dayOfWeek; // 0=周一,1=周二...5=周六
    private long count;

    // 生成getter、setter、构造方法
}

2. 基于Java Stream的分组统计实现

利用Stream的分组聚合能力,先按状态+周几统计数量,再整理为前端图表适配的结构:

@Override
public Response<Map<String, List<LeadsDashboard>>> getLeadsDashboards() {
    Response<Map<String, List<LeadsDashboard>>> response = new Response<>();
    User user = userRepository.getById(auditorAware.getCurrentAuditor().get().getId());
    List<Lead> leads = leadRepository.findAll(user.getCompany().getId());

    // 按状态+周几分组统计数量
    Map<String, Map<Integer, Long>> statusDayCountMap = leads.stream()
            .filter(lead -> lead.getCreateDate() != null)
            .collect(Collectors.groupingBy(
                    Lead::getStatus,
                    Collectors.groupingBy(
                            lead -> {
                                // 转换为周一=0到周六=5的索引(排除周日)
                                int sqlServerWeekday = lead.getCreateDate().getDayOfWeek().getValue();
                                return sqlServerWeekday == 1 ? -1 : sqlServerWeekday - 2;
                            },
                            Collectors.counting()
                    )
            ));

    // 转换为前端需要的结构:补全周一到周六的空统计(数量为0)
    Map<String, List<LeadsDashboard>> resMap = new HashMap<>();
    Arrays.stream(Statuses.values())
            .map(Statuses::getStatus)
            .forEach(status -> {
                List<LeadsDashboard> dashboardList = new ArrayList<>();
                for (int day = 0; day < 6; day++) {
                    LeadsDashboard dashboard = new LeadsDashboard();
                    dashboard.setStatus(status);
                    dashboard.setDayOfWeek(day);
                    dashboard.setCount(statusDayCountMap.getOrDefault(status, new HashMap<>()).getOrDefault(day, 0L));
                    dashboardList.add(dashboard);
                }
                resMap.put(status.toLowerCase() + "Leads", dashboardList);
            });

    response.setBody(resMap);
    return response;
}

3. 推荐:SQL层面直接统计(性能更优)

若数据量较大,直接在数据库完成分组统计效率更高,修改Repository接口:

// LeadRepository接口
@Query(value = """
        SELECT l.status, DATEPART(weekday, l.create_date) - 2 AS day_of_week, COUNT(*) AS count
        FROM lead l
        WHERE l.company_id = :companyId
        AND DATEPART(weekday, l.create_date) BETWEEN 2 AND 7 -- 仅统计周一到周六(SQL Server中周日=1,周一=2...周六=7)
        GROUP BY l.status, DATEPART(weekday, l.create_date)
        """, nativeQuery = true)
List<Object[]> countLeadsByStatusAndDayOfWeek(@Param("companyId") Long companyId);

后续在Service中处理查询结果,转换为LeadsDashboard结构即可。

关键说明

  • 周几转换适配:SQL Server中DATEPART(weekday, date)返回1(周日)到7(周六),需转换为0-5对应周一到周六
  • 空值补全:确保每个状态下周一到周六都有统计数据(无数据则为0),保证前端图表横轴连续
  • 分组逻辑:先按状态分组,再按周几聚合,精准匹配需求的统计维度

内容的提问来源于stack exchange,提问作者Christian jire

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:45:34