苍穹外卖day11笔记

这篇具有很好参考价值的文章主要介绍了苍穹外卖day11笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今日首先介绍前端技术Apache ECharts,说明后端需要准备的数据,然后讲解具体统计功能的实现,包括营业额统计、用户统计、订单统计、销量排名。

一、ECharts

是什么

ECharts是一款基于 Javascript 的数据可视化图表库。我们用它来展示图表数据。

入门案例

步骤

1). 引入echarts.js 文件

2). 为 ECharts 准备一个设置宽高的 DOM

3). 初始化echarts实例

4). 指定图表的配置项和数据

5). 使用指定的配置项和数据显示图表

代码

js文件在黑马对应项目自取。

测试用的html代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>ECharts</title>
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.js"></script>
  </head>
  <body>
    <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
      // 基于准备好的dom,初始化echarts实例
      var myChart = echarts.init(document.getElementById('main'));

      // 指定图表的配置项和数据
      var option = {
        title: {
          text: '班级出勤人数'
        },
        tooltip: {},
        legend: {

          data: ['人数']
        },
        xAxis: {
          type: 'category',
          data: ['星期1', '星期2', '星期3', '星期4', '星期5']
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            name: '人数',
            type: 'line',
            data: [160, 71, 66, 73, 68],
            smooth: true

          }
        ]
      };

      // 使用刚指定的配置项和数据显示图表。
      myChart.setOption(option);
    </script>
  </body>
</html>

结果页面如下:

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

然后我们打开ECharts官网Apache ECharts 选择一个图案来试着改一下。

首先进入官网,点击所有示例。

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

然后点击一个自己喜欢的样式:

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

复制左边的代码到原代码的option位置:

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

复制后代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>ECharts</title>
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.js"></script>
  </head>
  <body>
    <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
      // 基于准备好的dom,初始化echarts实例
      var myChart = echarts.init(document.getElementById('main'));

      // 指定图表的配置项和数据
      var option = {
  title: {
    text: 'Stacked Area Chart'
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'cross',
      label: {
        backgroundColor: '#6a7985'
      }
    }
  },
  legend: {
    data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']
  },
  toolbox: {
    feature: {
      saveAsImage: {}
    }
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: [
    {
      type: 'category',
      boundaryGap: false,
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    }
  ],
  yAxis: [
    {
      type: 'value'
    }
  ],
  series: [
    {
      name: 'Email',
      type: 'line',
      stack: 'Total',
      areaStyle: {},
      emphasis: {
        focus: 'series'
      },
      data: [120, 132, 101, 134, 90, 230, 210]
    },
    {
      name: 'Union Ads',
      type: 'line',
      stack: 'Total',
      areaStyle: {},
      emphasis: {
        focus: 'series'
      },
      data: [220, 182, 191, 234, 290, 330, 310]
    },
    {
      name: 'Video Ads',
      type: 'line',
      stack: 'Total',
      areaStyle: {},
      emphasis: {
        focus: 'series'
      },
      data: [150, 232, 201, 154, 190, 330, 410]
    },
    {
      name: 'Direct',
      type: 'line',
      stack: 'Total',
      areaStyle: {},
      emphasis: {
        focus: 'series'
      },
      data: [320, 332, 301, 334, 390, 330, 320]
    },
    {
      name: 'Search Engine',
      type: 'line',
      stack: 'Total',
      label: {
        show: true,
        position: 'top'
      },
      areaStyle: {},
      emphasis: {
        focus: 'series'
      },
      data: [820, 932, 901, 934, 1290, 1330, 1320]
    }
  ]
};

      // 使用刚指定的配置项和数据显示图表。
      myChart.setOption(option);
    </script>
  </body>
</html>

页面展示结果如下:

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

总结

传输的两列数据,分别是下标和数据。在如下位置:

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

二、营业额统计

查看接口文档

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

分析

控制层

控制层只要接收数据传给业务层,返回VO(已经有设计好的TurnoverReportVO了)就可以。重点在业务层和持久层。

业务层

具体要处理得到两类,或者说两列数据,包括:

  1. 日期列表
  2. 营业额列表

所以步骤便是:

  1. 获取日期列表
  2. 获取日期对应的营业额的列表
  3. 封装返回 

持久层

那么持久层需要的操作就在第2步,即:

  • 根据日期查找当日营业额

之后几个案例都是大差不差的层次结构,除了数据的种类要求不同。

 具体代码

控制层

@RestController
@Slf4j
@Api(tags = "统计相关")
@RequestMapping("/admin/report")
public class ReportController {

    @Autowired
    private ReportService reportService;

    @GetMapping("/turnoverStatistics")
    public Result turnoverStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                                     @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        TurnoverReportVO turnoverReportVO = reportService.turnoverStatistics(begin, end);
        return Result.success(turnoverReportVO);
    }
}

业务层

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrdersMapper ordersMapper;

    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        // 1. 获取日期列表
        List<LocalDate> list = getDateList(begin, end);
        // 2. 查询每日营业额
        List<Double> result = new ArrayList<>();
        Double turnover;
        LocalDateTime dayBegin;
        LocalDateTime dayEnd;
        if (list != null && list.size() > 0) {
            dayBegin = LocalDateTime.of(list.get(0), LocalTime.MIN);  // 知识点2和3
            dayEnd = LocalDateTime.of(list.get(0), LocalTime.MAX);  // 知识点2和3
        } else {
            return new TurnoverReportVO();
        }
        for (LocalDate localDate : list) {
            Map<String, Object> map = new HashMap<>();
            map.put("status", Orders.COMPLETED);
            map.put("begin", dayBegin);
            map.put("end", dayEnd);
            turnover = ordersMapper.sumByMap(map);  // 知识点4
            result.add(turnover == null ? 0 : turnover);

            dayBegin = dayBegin.plusDays(1);
            dayEnd = dayEnd.plusDays(1);
        }
        // 3. 返回
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setDateList(StringUtils.join(list, ","));
        turnoverReportVO.setTurnoverList(StringUtils.join(result, ","));
        return turnoverReportVO;
    }

    private List<LocalDate> getDateList(LocalDate begin, LocalDate end) {
        List<LocalDate> list = new ArrayList<>();
        while (begin.compareTo(end) <= 0) {  // 知识点1
            list.add(begin);
            begin = begin.plusDays(1);
        }
        return list;
    }
}

4个知识点

这里体现了4个知识点:

  1. 日期之间用compareTo比较
  2. LocalDate和LocalTime组合成LocalDateTime,用LocalDateTime的of方法
  3. LocalTime.MIN与LocalTime.MAX
  4. 用Map封装数据交给mapper查找。

持久层

直接上xml文件了:

elect id="sumByMap" resultType="java.lang.Double">
    select sum(amount)
    from orders
    <where>
        <if test="status!=null and status!=''">
            status = #{status}
        </if>
        <if test="begin!=null and end!=null">
            and order_time between #{begin} and #{end}
        </if>
    </where>
</select>

三、用户统计

接口文档

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

 分析所需数据

由于三层的架构都大差不差,所以直接介绍所需数据的不同。

  1. 日期列表
  2. 新增用户数列表
  3. 总用户数列表

具体代码

控制层

@GetMapping("/userStatistics")
public Result userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                                 @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
    UserReportVO userReportVO = reportService.userStatistics(begin, end);
    return Result.success(userReportVO);
}

业务层

@Override
public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
    // 1. 获取日期列表
    List<LocalDate> dateList = getDateList(begin, end);
    // 2. 获取用户数量列表
    List<Integer> newUserList = new ArrayList<>();
    List<Integer> totalUserList = new ArrayList<>();

    LocalDateTime dayBegin;
    LocalDateTime dayEnd;

    if (dateList != null && dateList.size() > 0) {
        dayBegin = LocalDateTime.of(dateList.get(0), LocalTime.MIN);
        dayEnd = LocalDateTime.of(dateList.get(0), LocalTime.MAX);
    } else {
        return new UserReportVO();
    }
    Integer totalUser;
    Integer newUser;
    for (LocalDate localDate : dateList) {
        Map<String, Object> map = new HashMap<>();
        map.put("end", dayEnd);
        totalUser = userMapper.countByMap(map);
        totalUserList.add(totalUser == null ? 0 : totalUser);
        map.put("begin", dayBegin);
        newUser = userMapper.countByMap(map);
        newUserList.add(newUser == null ? 0 : newUser);

        dayBegin = dayBegin.plusDays(1);
        dayEnd = dayEnd.plusDays(1);
    }
    // 3. 返回
    UserReportVO userReportVO = new UserReportVO();
    userReportVO.setDateList(StringUtils.join(dateList, ","));
    userReportVO.setNewUserList(StringUtils.join(newUserList, ","));
    userReportVO.setTotalUserList(StringUtils.join(totalUserList, ","));
    return userReportVO;
}

3个注意的点

第一点,获取日期列表可以抽取出来,供营业额统计、用户统计共同调用。

小tips,抽取函数的快捷键是 ctrl + alt + m 哦。

第二点,持久层的两次查找,可以巧妙的用一个函数来完成的。用动态sql的if判断,分为有begin时间的判断和没有begin时间的判断进行处理。具体看下面持久层代码。

第三点,两个统计都要判断持久层查到的结果是不是null,是的话要归为0哦。

持久层

<select id="countByMap" resultType="java.lang.Integer">
    select count(*) from user
    <where>
        <if test="end!=null">
            and create_time &lt;= #{end}
        </if>
        <if test="begin!=null">
            and create_time &gt;= #{begin}
        </if>
    </where>
</select>

四、订单统计

接口文档

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

所需数据

  1. 日期列表
  2. 所有订单每日总数列表
  3. 所有订单总数
  4. 有效订单每日总数列表
  5. 有效订单总数
  6. 订单完成率

具体代码

控制层

@GetMapping("/ordersStatistics")
public Result ordersStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                               @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
    OrderReportVO orderReportVO = reportService.ordersStatistics(begin, end);
    return Result.success(orderReportVO);
}

业务层

@Override
public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
    OrderReportVO orderReportVO = new OrderReportVO();
    // 1. 日期列表
    List<LocalDate> dateList = getDateList(begin, end);
    if (dateList == null) {
        return orderReportVO;
    }
    // 2. 订单数列表
    List<Integer> totalOrderList = new ArrayList<>();
    // 3. 有效订单数列表
    List<Integer> validOrderList = new ArrayList<>();
    // 4. 订单总数
    Integer totalOrderCount = 0;
    // 5. 有效订单总数
    Integer validOrderCount = 0;
    for (LocalDate localDate : dateList) {
        Map map = new HashMap();
        map.put("begin", LocalDateTime.of(localDate, LocalTime.MIN));
        map.put("end", LocalDateTime.of(localDate, LocalTime.MAX));
        Integer total = ordersMapper.countByMap(map);
        total = total == null ? 0 : total;
        map.put("status", Orders.COMPLETED);
        Integer valid = ordersMapper.countByMap(map);
        valid = valid == null ? 0 : valid;
        totalOrderList.add(total);
        validOrderList.add(valid);
        totalOrderCount += total;
        validOrderCount += valid;
    }
    // 6. 订单完成率
    Double completionR = 0.0;
    if (totalOrderCount != null) {
        completionR = validOrderCount * 1.0 / totalOrderCount;
    }

    orderReportVO.setDateList(StringUtils.join(dateList, ","));
    orderReportVO.setOrderCountList(StringUtils.join(totalOrderList, ","));
    orderReportVO.setValidOrderCountList(StringUtils.join(validOrderList, ","));
    orderReportVO.setTotalOrderCount(totalOrderCount);
    orderReportVO.setValidOrderCount(validOrderCount);
    orderReportVO.setOrderCompletionRate(completionR);

    return orderReportVO;
}

1个注意的巩固知识点

还是用动态sql来巧妙的满足一个函数查询两种不同的数据,即status的if判断是否查询。

持久层

<select id="countByMap" resultType="java.lang.Integer">
    select count(id) from orders
    <where>
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="begin != null">
            and order_time &gt;= #{begin}
        </if>
        <if test="end != null">
            and order_time &lt;= #{end}
        </if>
    </where>
</select>

没啥好说的,算一个巩固练习。

五、销量排名top10

接口文档

苍穹外卖day11笔记,笔记,java,spring boot,maven,spring,intellij-idea

所需数据

  1. 商品名列表
  2. 销量列表

具体代码

控制层

@GetMapping("/top10")
public Result top10(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                    @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
    SalesTop10ReportVO salesTop10ReportVO = reportService.top10(begin, end);
    return Result.success(salesTop10ReportVO);
}

业务层

@Override
public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
    List<GoodsSalesDTO> goodsSalesDTOS = ordersMapper.countSaleTop10(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));
    if (goodsSalesDTOS == null) {
        return new SalesTop10ReportVO();
    }

    List<String> nameList = new ArrayList<>();
    List<Integer> numberList = new ArrayList<>();
    for (GoodsSalesDTO goodsSalesDTO : goodsSalesDTOS) {
        nameList.add(goodsSalesDTO.getName());
        numberList.add(goodsSalesDTO.getNumber());
    }  // 思考:这里可不可以简写?


    SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
    salesTop10ReportVO.setNameList(StringUtils.join(nameList, ","));
    salesTop10ReportVO.setNumberList(StringUtils.join(numberList, ","));
    return salesTop10ReportVO;
}

2个注意的点

第一个,下面持久层的多表查询。

第二个,查询到DTO后,对象数据到两列数据的转换。

  • 法一,普通方法,老老实实用两个List添加。
  • 法二,流方法。值得练习,公司中可能会见到、用到很多,资深程序员必备。

练习:用流的写法完成查询数据到两个列表数据的转换

尝试用流的写法完成。

答案如下:

@Override
public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
    List<GoodsSalesDTO> goodsSalesDTOS = ordersMapper.countSaleTop10(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));
    if (goodsSalesDTOS == null) {
        return new SalesTop10ReportVO();
    }

//        List<String> nameList = new ArrayList<>();
//        List<Integer> numberList = new ArrayList<>();
//        for (GoodsSalesDTO goodsSalesDTO : goodsSalesDTOS) {
//            nameList.add(goodsSalesDTO.getName());
//            numberList.add(goodsSalesDTO.getNumber());
//        }
    // ==========注意这里的写法==========
    List<String> nameList = goodsSalesDTOS.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
    List<Integer> numberList = goodsSalesDTOS.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());
    // ==========注意上面的写法==========

    SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
    salesTop10ReportVO.setNameList(StringUtils.join(nameList, ","));
    salesTop10ReportVO.setNumberList(StringUtils.join(numberList, ","));
    return salesTop10ReportVO;
}

持久层

<select id="countSaleTop10" resultType="com.sky.dto.GoodsSalesDTO">
    select t2.name, sum(t2.number) as number
    from orders as t1
             inner join order_detail as t2
                        on t1.id = t2.order_id
    where t1.status = 5
      and t1.order_time >= #{begin}
      and t1.order_time &lt;= #{end}
    group by t2.name
    order by number desc limit 0, 10;
</select>

复习

1.ECharts最少需要准备几列数据?

2.LocalDateTime的比较,以及比较接口讲解的复习

3.日期时间的拼接、时间在一天的最大、最小值

4.Map封装数据进行查找的代码手法

5.统计中,持久层查询为null的归0化处理;

6.查找增量与总量时的简写mapper查询。文章来源地址https://www.toymoban.com/news/detail-641467.html

到了这里,关于苍穹外卖day11笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 苍穹外卖day11——数据统计图形报表(Apache ECharts)

    常见图表     快速上手 - Handbook - Apache ECharts   VO设计 对应的映射文件     对应的映射文件     对应的映射文件         对应的映射文件    

    2024年02月14日
    浏览(31)
  • itheima苍穹外卖项目学习笔记--Day9: 订单模块

    (1). 查询历史订单 在OrderController中,创建查询方法 在OrderServiceImpl中,创建分页查询方法,及其父类接口 在OrderMapper中,添加查询方法,并在映射文件中写入动态SQL语句 在OrderDetailMapper中,实现根据订单id查询订单明细 (2). 查询订单详细 在OrderController中,创建查询订单详细方

    2024年02月16日
    浏览(50)
  • itheima苍穹外卖项目学习笔记--Day7:缓存商品 / 购物车

    通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: 每个分类下的菜品保存一份缓存数据 数据库中菜品数据有变更时清理缓存数据 修改用户端接口 DishController 的 list 方法,加入缓存处理逻辑 修改管理端接口 DishController 的相关方法,加入清理缓存的逻辑,需要

    2024年02月16日
    浏览(38)
  • Java项目-苍穹外卖-Day10-SpirngTask及WebSocket

    本章实现的业务功能 超时未支付订单自动取消,配送中订单商家忘点完成自动再固定时间检查且修改成完成状态 来单提醒功能 催单提醒功能 一般的话周几和第几日是不能同时出现的 因为比如 4月15日 周四 可能4月15日不是周四 可能冲突的 所以周和日一般只能有一个 现在有

    2024年02月09日
    浏览(28)
  • itheima苍穹外卖项目学习笔记--Day1:项目介绍与开发环境搭建

    (1). 前端环境搭建 前端工程基于 nginx 运行 启动nginx:双击 nginx.exe 即可启动 nginx 服务,访问端口号为 80 (2). 后端环境搭建 后端工程基于 maven 进行项目构建,并且进行分模块开发 (3). 前后端联调 修改数据库中明文密码,改为MD5加密后的密文 修改Java代码,前端提交的密码进行

    2024年02月15日
    浏览(29)
  • 苍穹外卖day10——订单状态定时处理(Spring Task)、来单提醒和客户催单(WebSocket)

       对于超时没处理的需要定时程序处理。基于SpringTask实现。 来单提醒和客户催单。基于WebSocket实现。     周几通常不能和日一起指定。   cron表达式在线生成器 在线Cron表达式生成器  创建定时任务类     新建一个task包中一个类如下 在OrderMapper中 运行测试无误。     导

    2024年02月14日
    浏览(38)
  • itheima苍穹外卖项目学习笔记--Day10: 订单状态定时处理/来单提醒和客户催单

    Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。 定位:定时任务框架 作用:定时自动执行某段Java代码 cron表达式其实就是一个字符串,通过cron表达式可以定义任务触发的时间构成规则: 分为6或7个域,由空格分隔开, 每个域代表一个

    2024年02月17日
    浏览(40)
  • 苍穹外卖-day10:Spring Task、订单状态定时处理、来单提醒(WebSocket的应用)、客户催单(WebSocket的应用)

    Spring Task 订单状态定时处理 WebSocket 来单提醒 客户催单 功能实现: 订单状态定时处理 、 来单提醒 和 客户催单 订单状态定时处理: 来单提醒: 客户催单: 1.1 介绍 Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间 自动执行 某个代码逻辑。 定位 :定时任务框

    2024年04月28日
    浏览(31)
  • 苍穹外卖day02项目日志

    参考产品原型,设计表和接口。 1.1.1设计表 看员工管理的产品原型: 有员工姓名、账号、手机号、账号状态、最后操作时间等。 注意,操作一栏不是字段,其中的启用禁用才是。 再看添加员工的原型:  可以发现还有性别和身份证号。 不要忘了旁边: 还有密码。 总结出了

    2024年02月14日
    浏览(57)
  • 黑马苍穹外卖学习Day12

    结果 Controller层 Service实现类

    2024年01月25日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包