新闻详情

新闻详情

首页 / 资讯中心 / 详情

SpringBoot + ECharts 后台数据统计报表模块实战

发布时间:2026/10/1 10:29:43来源:尧图网络
SpringBoot + ECharts 后台数据统计报表模块实战
前言在后台管理系统中数据可视化报表是运营人员的核心工具。前端使用 ECharts 绘制折线图、柱状图后端的核心工作就是按照 ECharts 要求的格式封装时间区间内的统计数据。 本文基于一套 B 端管理后台实现 4 大类统计报表营业额统计、用户统计、订单统计、商品销量 TOP10完整讲解需求、接口设计、代码实现、踩坑点。一、核心思路ECharts 绘图需要后端返回两组核心数据X 轴日期列表datelist作为图表横坐标Y 轴对应指标数值列表和日期一一对应。⚠️重点难点时间区间内没有数据的日期也要填充 0保证日期数组和数值数组长度完全一致否则 ECharts 图表会错位。 解决方案循环遍历起止日期生成完整日期序列再去数据库查询有数据的记录最后合并补 0。二、营业额统计折线图2.1 需求分析业务规则统计已完成订单的总金额作为当日营业额支持自定义时间区间查询前端 ECharts 折线图展示X 轴为日期Y 轴为营业额。2.2 接口设计项目内容请求路径/admin/report/turnoverStatistics请求方式GET请求参数begin开始日期end结束日期返回 VO日期字符串数组、营业额数组2.3 后端代码实现VO 实体Data Builder public class TurnoverReportVO { //日期列表逗号分隔 private String dateList; //营业额列表逗号分隔 private String turnoverList; }Controller 层RestController RequestMapping(/admin/report) Slf4j public class ReportController { Autowired private ReportService reportService; GetMapping(/turnoverStatistics) ApiOperation(营业额统计) public ResultTurnoverReportVO turnoverStatistics( DateTimeFormat(pattern yyyy-MM-dd) LocalDate begin, DateTimeFormat(pattern yyyy-MM-dd) LocalDate end) { log.info(营业额统计开始时间{}结束时间{},begin,end); return Result.success(reportService.getTurnoverStatistics(begin,end)); } }Service 核心逻辑Override public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) { //1. 生成begin ~ end之间完整的日期集合 ListLocalDate dateList new ArrayList(); dateList.add(begin); while (!begin.equals(end)){ begin begin.plusDays(1); dateList.add(begin); } //2. 遍历每一天查询当日营业额无数据则为0 ListDouble turnoverList new ArrayList(); for (LocalDate date : dateList) { LocalDateTime beginTime LocalDateTime.of(date, LocalTime.MIN); LocalDateTime endTime LocalDateTime.of(date, LocalTime.MAX); MapString,Object map new HashMap(); map.put(begin,beginTime); map.put(end,endTime); map.put(status, Orders.COMPLETED); Double turnover orderMapper.sumByMap(map); turnover turnover null ? 0.0 : turnover; turnoverList.add(turnover); } //3. 拼接成逗号分隔字符串返回前端 return TurnoverReportVO.builder() .dateList(StringUtils.join(dateList, ,)) .turnoverList(StringUtils.join(turnoverList, ,)) .build(); }Mapper XMLselect idsumByMap resultTypejava.lang.Double select sum(amount) from orders where if testbegin ! null and order_time gt; #{begin} /if if testend ! null and order_time lt; #{end} /if if teststatus ! null and status #{status} /if /where /select三、用户统计折线图3.1 需求分析统计时间区间内总用户量、新增用户量X 轴为日期两条折线累计总用户、当日新增用户。3.2 接口设计路径/admin/report/userStatisticsGET 请求参数begin、end3.3 核心代码Override public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) { //生成完整日期序列 ListLocalDate dateList new ArrayList(); dateList.add(begin); while (!begin.equals(end)){ begin begin.plusDays(1); dateList.add(begin); } ListInteger newUserList new ArrayList(); ListInteger totalUserList new ArrayList(); for (LocalDate date : dateList) { LocalDateTime beginTime LocalDateTime.of(date, LocalTime.MIN); LocalDateTime endTime LocalDateTime.of(date, LocalTime.MAX); MapString,Object map new HashMap(); map.put(end,endTime); //总用户数截止到当天结束 Integer totalUser userMapper.countByMap(map); map.put(begin,beginTime); //新增用户当天新增 Integer newUser userMapper.countByMap(map); newUserList.add(newUser); totalUserList.add(totalUser); } return UserReportVO.builder() .dateList(StringUtils.join(dateList, ,)) .totalUserList(StringUtils.join(totalUserList, ,)) .newUserList(StringUtils.join(newUserList, ,)) .build(); }要点Mapper 使用 Map 传参动态拼接 SQL 条件统计用户创建时间。四、订单统计双折线图4.1 需求统计区间内订单总数、有效订单数计算订单完成率 有效订单 / 总订单。核心逻辑Override public OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end) { ListLocalDate dateList getDateList(begin, end); ListInteger orderCountList new ArrayList(); ListInteger validOrderCountList new ArrayList(); for (LocalDate date : dateList) { LocalDateTime beginTime LocalDateTime.of(date, LocalTime.MIN); LocalDateTime endTime LocalDateTime.of(date, LocalTime.MAX); MapString,Object map new HashMap(); map.put(begin,beginTime); map.put(end,endTime); //当日全部订单 Integer total orderMapper.countByMap(map); map.put(status,Orders.COMPLETED); //当日有效完成订单 Integer valid orderMapper.countByMap(map); orderCountList.add(total); validOrderCountList.add(valid); } //计算区间内总订单、有效订单、完成率 Integer totalOrderCount orderCountList.stream().reduce(Integer::sum).get(); Integer validOrderCount validOrderCountList.stream().reduce(Integer::sum).get(); Double orderCompletionRate 0.0; if(totalOrderCount ! 0){ orderCompletionRate validOrderCount.doubleValue() / totalOrderCount; } return OrderReportVO.builder() .dateList(StringUtils.join(dateList, ,)) .orderCountList(StringUtils.join(orderCountList, ,)) .validOrderCountList(StringUtils.join(validOrderCountList, ,)) .totalOrderCount(totalOrderCount) .validOrderCount(validOrderCount) .orderCompletionRate(orderCompletionRate) .build(); }知识点Stream 流reduce累加集合快速求和。五、商品销量 TOP10柱状图需求查询时间段内销量排名前 10 的商品ECharts 柱状图展示。返回商品名称列表、销量列表。Override public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) { LocalDateTime beginTime LocalDateTime.of(begin, LocalTime.MIN); LocalDateTime endTime LocalDateTime.of(end, LocalTime.MAX); ListGoodsSalesDTO salesTop10 orderMapper.getSalesTop10(beginTime, endTime); //拆分名称、销量两个集合 ListString names salesTop10.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList()); ListInteger values salesTop10.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList()); return SalesTop10ReportVO.builder() .nameList(StringUtils.join(names, ,)) .numberList(StringUtils.join(values, ,)) .build(); }Mapper SQL 核心关联订单明细表按商品分组统计销量排序取前 10。六、开发踩坑总结日期补 0如果跳过无数据日期X 轴和 Y 轴数据长度不一致ECharts 图表渲染错乱必须循环生成完整日期序列LocalDateTime 时间边界LocalTime.MIN是 00:00:00LocalTime.MAX是 23:59:59.999999防止跨天数据丢失null 值判断数据库查询 sum 聚合函数无数据返回 null不做判断直接赋值会空指针前端 ECharts 格式约定后端统一返回逗号分隔字符串前端 split 切割成数组前后端约定好数据格式Map 传参动态 SQL使用 MyBatis 动态标签if灵活拼接查询条件复用 Mapper。七、拓展与面试考点如果数据量很大每次查询数据库压力高可以定时任务预统计存入 Redis报表直接读缓存可以增加导出 Excel 功能把报表数据导出给运营面试常问时间区间统计某天没有数据怎么处理答先预生成起止时间内全部日期遍历日期逐个查询查询结果为空则填充 0保证坐标数组长度一致。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

GitHub热榜解读:AI代码生成与Rust框架崛起,TaoToken统一Key接入实战 2026/10/1 14:58:54

GitHub热榜解读:AI代码生成与Rust框架崛起,TaoToken统一Key接入实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Claude Code常见报错原因问题合集:从环境变量到API Error的排查手册 2026/10/1 14:58:54

Claude Code常见报错原因问题合集:从环境变量到API Error的排查手册

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
DevExpress GridControl 常用属性设置:从列宽到分组汇总的实战清单 2026/10/1 14:58:54

DevExpress GridControl 常用属性设置:从列宽到分组汇总的实战清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
2026最新!十大AI写小说软件综合实力榜:TaoToken统一API接入ai生成小说工具深度测评与推荐 2026/10/1 14:58:54

2026最新!十大AI写小说软件综合实力榜:TaoToken统一API接入ai生成小说工具深度测评与推荐

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
SD NAND嵌入式存储选型与跨平台复用设计实战 2026/10/1 14:58:54

SD NAND嵌入式存储选型与跨平台复用设计实战

做过几个数据记录类设备之后,我对存存储选型这件事的体会特别深:很多产品迭代几天就能搞定主控更换,但存储方案往往是最后被拖后腿的部分。最近一年多,我手头几个项目都在用米客方德的SD NAND做存储,最直接的感受是&am…

阅读更多 →
Win11用户文件夹改名全攻略:从原理到实操的安全指南 2026/10/1 14:58:47

Win11用户文件夹改名全攻略:从原理到实操的安全指南

Win11 装完系统后,C:\Users 下面那个用户文件夹名,往往是很多人第一次意识到“路径不对”的地方。你用微软账户登录,系统可能直接生成一段截断的邮箱前缀当作文件夹名;如果前缀是中文,路径里就会出现中文。试过的人都知…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉