• Apache ECharts


    Apache ECharts介绍:

    Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。

    官网地址:https://echarts.apache.org/zh/index.html

    Apache ECharts入门程序:

    进入官网,按照官方给的步骤:

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8" />
    5. <title>EChartstitle>
    6. <script src="echarts.js">script>
    7. head>
    8. <body>
    9. <div id="main" style="width: 600px;height:400px;">div>
    10. <script type="text/javascript">
    11. // 基于准备好的dom,初始化echarts实例
    12. var myChart = echarts.init(document.getElementById('main'));
    13. // 指定图表的配置项和数据
    14. var option = {
    15. title: {
    16. text: 'ECharts 入门示例'
    17. },
    18. tooltip: {},
    19. legend: {
    20. data: ['销量']
    21. },
    22. xAxis: {
    23. data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    24. },
    25. yAxis: {},
    26. series: [
    27. {
    28. name: '销量',
    29. type: 'bar',
    30. data: [5, 20, 36, 10, 10, 20]
    31. }
    32. ]
    33. };
    34. // 使用刚指定的配置项和数据显示图表。
    35. myChart.setOption(option);
    36. script>
    37. body>
    38. html>

     

    营业额统计:

    业务规则及接口设计:

    • 营业额指订单状态为已完成的订单金额合计
    • 基于可视化报表的折线图展示营业额数据,X轴为日期,Y轴为营业额
    • 根据时间选择区间,展示每天的营业额数据

     

     前端想展示数据,也要设计接口从后端获取数据。

    返回数据这一块,因为是前端来展示数据,所以我们提供的数据是要依照前端的规则。

     具体代码实现:

    Controll层:

    1. @Autowired
    2. private ReportService reportService;
    3. /**
    4. * 营业额统计
    5. * @param begin
    6. * @param end
    7. * @return
    8. */
    9. @GetMapping("/turnoverStatistics")
    10. @ApiOperation("营业额统计")
    11. public Result turnoverStatistics(
    12. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
    13. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){
    14. log.info("营业额统计");
    15. TurnoverReportVO turnoverReportVO = reportService.turnoverStatistics(begin,end);
    16. return Result.success(turnoverReportVO);
    17. }

    这里有个小细节,就是查询统计营业额,前端传的参数是日期的起始时间和结束时间,

    格式是yyyy-MM-dd这种形式,所以,我们也要用这种形式来进行接收。

    @DateTimeFormat(pattern = "yyyy-MM-dd"),就用到了这个方法。

     Service层:

    1. package com.sky.service.impl;
    2. import com.sky.entity.Orders;
    3. import com.sky.mapper.OrderMapper;
    4. import com.sky.service.ReportService;
    5. import com.sky.vo.TurnoverReportVO;
    6. import org.apache.commons.lang3.StringUtils;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.stereotype.Service;
    9. import javax.validation.constraints.Min;
    10. import java.time.LocalDate;
    11. import java.time.LocalDateTime;
    12. import java.time.LocalTime;
    13. import java.util.ArrayList;
    14. import java.util.HashMap;
    15. import java.util.List;
    16. import java.util.Map;
    17. @Service
    18. public class ReportServiceImpl implements ReportService {
    19. @Autowired
    20. private OrderMapper orderMapper;
    21. @Override
    22. public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
    23. //封装TurnoverReportVO的dateList对象
    24. List datelist = new ArrayList<>();
    25. datelist.add(begin);
    26. while(!begin.equals(end)){
    27. //将日期加到list集合中
    28. begin = begin.plusDays(1);
    29. datelist.add(begin);
    30. }
    31. String datejoin = StringUtils.join(datelist, ",");
    32. //封装TurnoverReportVO的turnoverList对象
    33. List turnoverlist = new ArrayList<>();
    34. for (LocalDate localDate : datelist) {
    35. //查询date日期对应的营业额数据,营业额是指:状态为“已完成”的订单金额合计
    36. LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);
    37. LocalDateTime endTime = LocalDateTime.of(localDate,LocalTime.MAX);
    38. //select sum(amount) from orders where order_time > ? and order_time < ? and status = 5
    39. Map map = new HashMap();
    40. map.put("begin",beginTime);
    41. map.put("end",endTime);
    42. map.put("status", Orders.COMPLETED);
    43. Double turnover = orderMapper.TurnoverOfSum(map);
    44. turnover = turnover==null?0.0:turnover;
    45. turnoverlist.add(turnover);
    46. }
    47. for (Double v : turnoverlist) {
    48. System.out.println("今日份营业额:"+ v);
    49. }
    50. //封装TurnoverReportVO对象
    51. TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
    52. turnoverReportVO.setDateList(datejoin);
    53. turnoverReportVO.setTurnoverList(StringUtils.join(turnoverlist,","));
    54. return turnoverReportVO;
    55. }
    56. }
    思路:

    我们观察TurnoverReportVO对象里面有两个值,dateList,turnoverList

    一个是日期列表,一个是营业额列表。

    我们观察前端页面也能看成

    横坐标:是日期   纵坐标:是营业额。

     所以我们Service层的思路就很简单了

    1:封装dateList对象

    创建一个LocalDate的列表,然后通过LocalDate提供的库函数plusDay,将日期由begin一直加到end,并且TurnoverReportVO对象中的dateList对象是一个String,所以我们再调用String.utils的方法对这个列表进行逗号分割。

    2:封装turnoverList对象

    我们已经有了每一天的日期了,我们需要每一天的营业额(当然这里也不一定是每一天的,我们前端界面是可以选择的,有可能是一周,也有可能是一个月)。

    这个turnoverList对象的封装就需要查询数据库了

    select sum(amout) from orders where order_time > ? and order_time < ? and status = 5

    我们创建一个map对象里面有beginTime,endTime,status,然后传到mapper层,查询数据中的数据。

    3:最后再封装TurnoverReportVO对象返回。

    Mapper层及注解:

    1. /**
    2. * 动态查询营业额
    3. * @param map
    4. * @return
    5. */
    6. Double TurnoverOfSum(Map map);

    用户统计:

    业务规则及接口设计:

    业务规则:

    • 基于可视化报表的折线图展示用户数据,X轴为日期,Y轴为用户数
    • 根据时间选择区间,展示每天的用户总量和新增用户量数据

     

    用户统计和上面的不同点就是我们的返回值有三个列表:

    • dateList
    • newUserList
    • totalUserList

     具体代码实现:

    整体的思路和上面的营业额统计差不多

    Controll层:

    1. /**
    2. * 用户数量统计
    3. * @param begin
    4. * @param end
    5. * @return
    6. */
    7. @GetMapping("/userStatistics")
    8. @ApiOperation("用户数量统计")
    9. public Result userStatistics(
    10. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
    11. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){
    12. log.info("用户数量统计");
    13. UserReportVO userReportVO = reportService.userStatistics(begin,end);
    14. return Result.success(userReportVO);
    15. }

    Service层:

    1. /**
    2. * 用户数量统计
    3. * @param begin
    4. * @param end
    5. * @return
    6. */
    7. @Override
    8. public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
    9. //封装UserReportVO的dateList对象
    10. List dateList = new ArrayList<>();
    11. while (!begin.equals(end)){
    12. dateList.add(begin);
    13. begin = begin.plusDays(1);
    14. }
    15. String datejoin = StringUtils.join(dateList, ",");
    16. //封装UserReportVO的totalUserList对象
    17. //select count(id) from user where create_time < endTime
    18. //封装UserReportVO的newUserList对象
    19. //select count(id) from user where create_time > beginTime and create_time < endTime
    20. List totalUserList = new ArrayList<>();
    21. List newUserList = new ArrayList<>();
    22. for (LocalDate date : dateList) {
    23. LocalDateTime beginTime = LocalDateTime.of(date,LocalTime.MIN);
    24. LocalDateTime endTime = LocalDateTime.of(date,LocalTime.MAX);
    25. Map map = new HashMap();
    26. map.put("end",endTime);
    27. Integer totalUser = userMapper.UserofSum(map);
    28. map.put("begin",beginTime);
    29. Integer newUser = userMapper.UserofSum(map);
    30. totalUserList.add(totalUser);
    31. newUserList.add(newUser);
    32. }
    33. String totaluserjoin = StringUtils.join(totalUserList, ",");
    34. String newluserjoin = StringUtils.join(newUserList, ",");
    35. UserReportVO userReportVO = new UserReportVO();
    36. userReportVO.setDateList(datejoin);
    37. userReportVO.setTotalUserList(totaluserjoin);
    38. userReportVO.setNewUserList(newluserjoin);
    39. return userReportVO;
    40. }

    这里Service层的业务就是封装三个列表

    要想封装这个用户,我们需要去调userMapper

    我们想要知道总共的用户的sql是:

    //select count(id) from user where create_time < endTime

    截至到这个end时间时候的用户数量。

    而新增用户的sql是:

    //select count(id) from user where create_time > beginTime and create_time < endTime

    我们要给这个新增确定一个日期范围。 

    userMapper及注解:

    Integer UserofSum(Map map);

     订单统计:

    业务规则及接口设计:

    业务规则:

    • 有效订单指状态为 “已完成” 的订单
    • 基于可视化报表的折线图展示订单数据,X轴为日期,Y轴为订单数量
    • 根据时间选择区间,展示每天的订单总数和有效订单数
    • 展示所选时间区间内的有效订单数、总订单数、订单完成率,订单完成率 = 有效订单数 / 总订单数 * 100%

    具体的代码实现: 

    Controll层:

    1. /**
    2. * 订单统计
    3. * @param begin
    4. * @param end
    5. * @return
    6. */
    7. @GetMapping("/ordersStatistics")
    8. @ApiOperation("订单统计")
    9. public Result orderStatistics(
    10. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
    11. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){
    12. log.info("订单统计");
    13. OrderReportVO orderReportVO = reportService.ordersStatistics(begin,end);
    14. return Result.success(orderReportVO);
    15. }

    Service层:

    1. /**
    2. * 订单统计
    3. * @param begin
    4. * @param end
    5. * @return
    6. */
    7. @Override
    8. public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
    9. //封装OrderReportVO的dateList对象
    10. List dateList = new ArrayList<>();
    11. while (!begin.equals(end)){
    12. dateList.add(begin);
    13. begin = begin.plusDays(1);
    14. }
    15. String datejoin = StringUtils.join(dateList, ",");
    16. //封装OrderReportVO的orderCountList对象
    17. //封装OrderReportVO的validOrderCountList对象
    18. List orderCountList = new ArrayList<>();
    19. List validOrderCountList = new ArrayList<>();
    20. for (LocalDate date : dateList) {
    21. LocalDateTime beginTime = LocalDateTime.of(date,LocalTime.MIN);
    22. LocalDateTime endTime = LocalDateTime.of(date,LocalTime.MAX);
    23. Map map = new HashMap();
    24. map.put("begin",beginTime);
    25. map.put("end",endTime);
    26. Integer totalorders = orderMapper.OrdersofSum(map);
    27. map.put("status",Orders.COMPLETED);
    28. Integer validorders = orderMapper.OrdersofSum(map);
    29. orderCountList.add(totalorders);
    30. validOrderCountList.add(validorders);
    31. }
    32. String totaljoin = StringUtils.join(orderCountList, ",");
    33. String validjoin = StringUtils.join(validOrderCountList,",");
    34. //计算时间区间内的订单总数量
    35. Integer totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();
    36. //计算时间区间内的有效订单数量
    37. Integer validOrderCount = validOrderCountList.stream().reduce(Integer::sum).get();
    38. //计算订单完成率
    39. Double orderCompletionRate = 0.0;
    40. if(totalOrderCount!=0){
    41. orderCompletionRate = validOrderCount.doubleValue()/totalOrderCount.doubleValue();
    42. }
    43. OrderReportVO orderReportVO = new OrderReportVO();
    44. orderReportVO.setDateList(datejoin);
    45. orderReportVO.setOrderCountList(totaljoin);
    46. orderReportVO.setValidOrderCountList(validjoin);
    47. orderReportVO.setTotalOrderCount(totalOrderCount);
    48. orderReportVO.setValidOrderCount(validOrderCount);
    49. orderReportVO.setOrderCompletionRate(orderCompletionRate);
    50. return orderReportVO;
    51. }

    Mapper层及注解:

    1. /**
    2. * 订单统计
    3. * @param map
    4. * @return
    5. */
    6. Integer OrdersofSum(Map map);

    销量排名统计(TOP10):

    业务规则及接口设计:

    业务规则:

    • 根据时间选择区间,展示销量前10的商品(包括菜品和套餐)
    • 基于可视化报表的柱状图降序展示商品销量
    • 此处的销量为商品销售的份数

    具体的代码实现:

     Controll层:

    1. /**
    2. * TOP10销量统计
    3. * @param begin
    4. * @param end
    5. * @return
    6. */
    7. @GetMapping("/top10")
    8. @ApiOperation("TOP10销量统计")
    9. public Result Top10Statostics(
    10. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
    11. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){
    12. log.info("TOP10销量统计");
    13. SalesTop10ReportVO salesTop10ReportVO = reportService.Top10Statostics(begin,end);
    14. return Result.success(salesTop10ReportVO);
    15. }

    Service层:

    1. /**
    2. * TOP10销量统计
    3. * @param begin
    4. * @param end
    5. * @return
    6. */
    7. @Override
    8. public SalesTop10ReportVO Top10Statostics(LocalDate begin, LocalDate end) {
    9. LocalDateTime beginTime = LocalDateTime.of(begin,LocalTime.MIN);
    10. LocalDateTime endTime = LocalDateTime.of(end,LocalTime.MAX);
    11. System.out.println("开始时间是:"+beginTime);
    12. System.out.println("结束时间是:"+endTime);
    13. List goodsSalesDTOList = orderMapper.GetTop10(beginTime,endTime);
    14. List names = goodsSalesDTOList.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
    15. String nameList = StringUtils.join(names, ",");
    16. List numbers = goodsSalesDTOList.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());
    17. String numberList = StringUtils.join(numbers, ",");
    18. SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
    19. salesTop10ReportVO.setNameList(nameList);
    20. salesTop10ReportVO.setNumberList(numberList);
    21. return salesTop10ReportVO;
    22. }

    这题的从sql语句开始分析比较简单

    1. select od.name,sum(od.number) number from order_detail od,orders o
    2. where od.order_id = o.id and o.status = 5 and o.order_time < 2024-05-04 and o.order_time > 2024-05-10
    3. group by od.name
    4. order by number desc
    5. limit 0,10

    根据传入的时间范围来获取数据

    Mapper层及注解:

    1. /**
    2. * TOP10销量统计
    3. * @param beginTime
    4. * @param endTime
    5. * @return
    6. */
    7. List GetTop10(LocalDateTime beginTime, LocalDateTime endTime);

    结果展示:

  • 相关阅读:
    中秋的秋
    Uniapp 文件选择插件 Ba-FilePicker
    Java入门级简单定时任务TimerTask
    62. 不同路径
    Redis与分布式:主从复制
    Java正则表达式 提取文本中所有的匹配数据
    快速排序模拟实现
    PLONK 的工作原理:第 1 部分
    三入职场!你可以从我身上学到这些(附毕业Vlog)
    【Unity开发】VSCode 代码补全缺失问题的各种修复方法
  • 原文地址:https://blog.csdn.net/m0_73966521/article/details/138631369