当前位置: 首页 > news >正文

Day11 数据统计 图形报表

Apache ECharts

介绍

入门案例

总结:使用 Echarts,重点在于研究当前图表所需的数据格式。通常是需要后端提供符合格式要求的动态数据,然后响应给前端来展示图表

营业额统计

需求分析和设计

业务规则:

· 营业额指订单状态为已完成的订单金额合计

· 基于可视化报表折线图展示营业额数据,X轴为日期,Y轴为营业额

· 根据时间选择区间,展示每天的营业额数据        

代码开发

我们首先需要一个传给前端的 VO

package com.sky.vo;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TurnoverReportVO implements Serializable {//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03private String dateList;//营业额,以逗号分隔,例如:406.0,1520.0,75.0private String turnoverList;}
package com.sky.controller.admin;import com.sky.result.Result;
import com.sky.service.ReportService;
import com.sky.vo.TurnoverReportVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDate;
import java.time.LocalDateTime;@RestController
@Slf4j
@Api(tags = "统计数据相关接口")
@RequestMapping("/admin/report")
public class ReportController{@AutowiredReportService reportService;@GetMapping("turnoverStatistics")@ApiOperation("统计营业额")public Result<TurnoverReportVO> turnoverReportVOResult(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("统计数据:{},{}",begin,end);return Result.success(reportService.getReportStatistic(begin, end));}
}
package com.sky.service.impl;import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import com.sky.service.ReportService;
import com.sky.vo.TurnoverReportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Slf4j
@Service
public class ReportServiceImpl implements ReportService {@AutowiredOrderMapper orderMapper;/*** 统计指定时间区间内的营业额数据* @param begin* @param end* @return*/@Overridepublic TurnoverReportVO getReportStatistic(LocalDate begin, LocalDate end) {//当前集合用来存从 begin 到 end 的每一天List<LocalDate> localDates = new ArrayList<>();localDates.add(begin);while(!begin.equals(end)){begin = begin.plusDays(1);localDates.add(begin);}//存放每天的营业额List<Double> turnoverList = new ArrayList<>();for(LocalDate localDate: localDates){//查询 date 日期对应的营业额数据,营业额是指,状态为"已完成"的订单的金额的合计LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);Map map = new HashMap();map.put("begin", beginTime);map.put("end", endTime);map.put("status", Orders.COMPLETED);Double turnover = orderMapper.sumByMap(map);if(turnover == null) turnover = 0.0;turnoverList.add(turnover);}TurnoverReportVO turnoverReportVO = TurnoverReportVO.builder().dateList(StringUtils.join(localDates, ",")).turnoverList(StringUtils.join(turnoverList, ",")).build();return turnoverReportVO;}
}
  <select id="sumByMap" resultType="java.lang.Double">select sum(amount) from sky_take_out.orders<where><if test="begin != null">and order_time &gt; #{begin}</if><if test="end != null">and order_time &lt; #{end}</if><if test="status != null">and status = #{status}</if></where></select>

功能测试

用户统计

需求分析和设计

业务规则:

·基于可视化报表的折线图展示用户数据,x轴为日期,y轴为用户数

·根据时间选择区间,展示每天的用户总量和新增用户量数据

代码开发

package com.sky.vo;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserReportVO implements Serializable {//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03private String dateList;//用户总量,以逗号分隔,例如:200,210,220private String totalUserList;//新增用户,以逗号分隔,例如:20,21,10private String newUserList;}
    @GetMapping("/userStatistics")@ApiOperation("用户统计")public Result<UserReportVO> userReportVOResult(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("用户数据:{},{}",begin,end);return Result.success(reportService.getUserStatistic(begin, end));}
    @Overridepublic UserReportVO getUserStatistic(LocalDate begin, LocalDate end) {//当前集合用来存从 begin 到 end 的每一天List<LocalDate> localDates = new ArrayList<>();localDates.add(begin);while(!begin.equals(end)){begin = begin.plusDays(1);localDates.add(begin);}// 存放每天的新增用户数量List<Integer> newUserList = new ArrayList<>();//存放每天的总用户数量List<Integer> totalUserList = new ArrayList<>();for(LocalDate localDate: localDates){//查询 date 日期对应的营业额数据,营业额是指,状态为"已完成"的订单的金额的合计LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);Map map = new HashMap();map.put("end", endTime);//总用户数量Integer totalUser = userMapper.coutByMap(map);totalUserList.add(totalUser);map.put("begin", beginTime);//新增用户数量Integer newUser = userMapper.coutByMap(map);newUserList.add(newUser);}return UserReportVO.builder().dateList(StringUtils.join(localDates, ",")).totalUserList(StringUtils.join(totalUserList, ",")).newUserList(StringUtils.join(newUserList, ",")).build();}
    <select id="coutByMap" resultType="java.lang.Integer">select COUNT(id) from sky_take_out.user<where><if test="begin != null">and create_time &gt; #{begin}</if><if test="end != null">and create_time &lt; #{end}</if></where></select>

功能测试

订单统计

需求分析和设计

代码开发

package com.sky.vo;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserReportVO implements Serializable {//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03private String dateList;//用户总量,以逗号分隔,例如:200,210,220private String totalUserList;//新增用户,以逗号分隔,例如:20,21,10private String newUserList;}
    @GetMapping("/ordersStatistics")@ApiOperation("用户统计")public Result<OrderReportVO> orderReportVOResult(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("用户数据:{},{}",begin,end);return Result.success(reportService.getOrderStatistic(begin, end));}
    @Overridepublic OrderReportVO getOrderStatistic(LocalDate begin, LocalDate end) {//当前集合用来存从 begin 到 end 的每一天List<LocalDate> localDates = new ArrayList<>();localDates.add(begin);while(!begin.equals(end)){begin = begin.plusDays(1);localDates.add(begin);}//存放每天的订单总数List<Integer> orderCountList = new ArrayList<>();//存放每天的有效订单数List<Integer> validOrderCountList = new ArrayList<>();//存放每天的有效订单数// 遍历localDates集合,查询每天的有效订单数和订单总数for (LocalDate localDate : localDates) {//查询每天订单总数LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);Integer orderCount = getOrderCount(beginTime, endTime, null);//查询每天有效订单数Integer validOrderCount = getOrderCount(beginTime, endTime, Orders.COMPLETED);orderCountList.add(orderCount);validOrderCountList.add(validOrderCount);}//计算订单总数Integer totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();//计算有效订单总数Integer validOrderCount = validOrderCountList.stream().reduce(Integer::sum).get();//计算订单完成率Double orderCompleteRate = 0.0;if(totalOrderCount != 0){orderCompleteRate = validOrderCount / totalOrderCount.doubleValue();}return OrderReportVO.builder().orderCountList(StringUtils.join(orderCountList, ",")).validOrderCountList(StringUtils.join(validOrderCountList, ",")).dateList(StringUtils.join(localDates, ",")).totalOrderCount(totalOrderCount).validOrderCount(validOrderCount).orderCompletionRate(orderCompleteRate).build();}private Integer getOrderCount(LocalDateTime begin, LocalDateTime end, Integer status){Map map = new HashMap();map.put("begin", begin);map.put("end", end);map.put("status", status);return orderMapper.countByMap(map);}
    <select id="countByMap" resultType="java.lang.Integer">select COUNT(0) from sky_take_out.orders<where><if test="begin != null">and order_time &gt; #{begin}</if><if test="end != null">and order_time &lt; #{end}</if><if test="status != null">and status = #{status}</if></where></select>

功能测试

销量排名Top 10

需求分析和设计

代码开发

package com.sky.vo;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SalesTop10ReportVO implements Serializable {//商品名称列表,以逗号分隔,例如:鱼香肉丝,宫保鸡丁,水煮鱼private String nameList;//销量列表,以逗号分隔,例如:260,215,200private String numberList;}

这里还需要一个 DTO 用来封装查数据库返回的数据

package com.sky.dto;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GoodsSalesDTO implements Serializable {//商品名称private String name;//销量private Integer number;
}
    @GetMapping("/top10")@ApiOperation("销量排名Top10")public Result<SalesTop10ReportVO> salesTop10ReportVOResult(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("销量前10数据统计:{},{}",begin,end);return Result.success(reportService.getSalesTop10(begin, end));}
    @Overridepublic SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);List<GoodsSalesDTO> salesTop10 = orderMapper.getSalesTop10(beginTime, endTime);List<String> names = salesTop10.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());String nameList = StringUtils.join(names, ",");List<Integer> numbers = salesTop10.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());String numberList = StringUtils.join(numbers, ",");return SalesTop10ReportVO.builder().nameList(nameList).numberList(numberList).build();}
    <select id="getSalesTop10" resultType="com.sky.dto.GoodsSalesDTO">select od.name, sum(od.number) as number from sky_take_out.order_detail od, sky_take_out.orders owhere od.order_id = o.id and o.status = 5<if test="begin != null">and order_time &gt; #{begin}</if><if test="end != null">and order_time &lt; #{end}</if>group by od.nameorder by sum(od.number) desclimit 0, 10</select>

注意这个 sum(od.number) 要起别名为 number 不然封装不进去!!!

功能测试

http://www.xdnf.cn/news/1347049.html

相关文章:

  • RKLLM 模型转换从0开始
  • vagrant怎么在宿主机操作虚拟机里面的系统管理和软件安装
  • 2025软件供应链安全技术路线未来趋势预测
  • vim的使用
  • Retrieval-Augmented Generation(RAG)
  • 为什么访问HTTPS站点时,会发生SSL证书错误
  • Trie 树(字典树)
  • 8月22号打卡
  • FFmpeg及 RTSP、RTMP
  • GitGithub相关(自用,持续更新update 8/23)
  • 文件下载和文件上传漏洞
  • LeetCode第1695题 - 删除子数组的最大得分
  • CSS自定义属性(CSS变量)
  • Jenkins发布spring项目踩坑——nohup java -jar发布后显示成功,但实际jps查询并未运行
  • kubernetes中pod的管理及优化
  • Python打卡Day49 CBAM注意力
  • Apache Ozone 2.0.0集群部署
  • 微信原生下载互联网oss资源保存到本地
  • CCleaner v1.2.3.4 中文解锁注册版,系统优化,隐私保护,极速清理
  • Unreal Engine Class System
  • 图数据库(neo4j)基础: 分类/标签 节点 关系 属性
  • 蓝牙部分解析和代码建构
  • set_disable_timing应用举例
  • OpenCV 图像边缘检测
  • 从“配置化思维”到“前端效率革命”:xiangjsoncraft 如何用 JSON 简化页面开发?
  • k8s 简介及部署方法以及各方面应用
  • 子类(派生类)使用父类(基类)的成员
  • 快速了解神经网络
  • AI赋能体育训练突破:AI动作捕捉矫正精准、战术分析系统提效率,运动员破瓶颈新路径
  • 数据结构之深入探索归并排序