苍穹外卖数据可视化
文章目录
- 1、用户统计
- 2、订单统计
- 3、销量排名Top10
1、用户统计
所谓用户统计,实际上统计的是用户的数量。通过折线图来展示,上面这根蓝色线代表的是用户总量,下边这根绿色线代表的是新增用户数量,是具体到每一天。所以说用户统计主要统计两个数据,一个是总的用户数量,另外一个是新增用户数量。
原型图:

业务规则:
- 基于可视化报表的折线图展示用户数据,X轴为日期,Y轴为用户数
- 根据时间选择区间,展示每天的用户总量和新增用户量数据
接口设计
根据上述原型图设计接口。
VO设计
根据用户统计接口的返回结果设计VO

@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;}
根据接口定义,在ReportController中创建userStatistics方法
/*** 用户统计* @param begin* @param end* @return*/@ApiOperation("用户统计")@GetMapping("/userStatistics")public Result<UserReportVO> userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("营业额统计:{},{}",begin,end);//调用业务获取用户统计数据UserReportVO userReportVO = reportService.getUserStatistics(begin,end);return Result.success(userReportVO);}
在ReportService接口中声明getUserStatistics方法
/*** 用户统计数据* @param begin* @param end* @return*/UserReportVO getUserStatistics(LocalDate begin, LocalDate end);
在ReportServiceImpl实现类中实现getUserStatistics方法
/*** 用户统计数据** @param begin* @param end* @return*/@Overridepublic UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {//目标获取用户统计数据:用户每天总数量,每天新增数量 、 每天日期列表//获取每天新增用户数量//select count(*) from user where create_time >= 当天最小时间 and create_time <= 当天最大时间//获取每天用户总数量//select count(*) from user where create_time <= 当天最大时间//1、根据开始日期与结束日期生成每天日期集合列表List<LocalDate> dateList = getDateList(begin, end);//2、定义存储每天新增用户 和 每天新增用户集合ArrayList<Integer> createUserList = new ArrayList<>();ArrayList<Integer> totalUserList = new ArrayList<>();//3、遍历日期列表,每天数据for (LocalDate date : dateList) {//定义每天最大时间和最小时间LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(date,LocalTime.MAX);//执行sql//将参数封装到map里Map<String,Object> map = new HashMap<>();//查询总用户map.put("endTime",endTime);Integer totalUser = userMapper.countByMap(map);totalUser = totalUser == null ? 0 : totalUser;totalUserList.add(totalUser);//查询新增用户,只需要再加一个开始条件map.put("beginTime",beginTime);Integer createUser = userMapper.countByMap(map);createUser = createUser == null ? 0 : createUser;createUserList.add(createUser);}//封装返回数据return UserReportVO.builder().dateList(StringUtils.join(dateList,",")).totalUserList(StringUtils.join(totalUserList,",")).newUserList(StringUtils.join(createUserList,",")).build();}
在UserMapper接口中声明countByMap方法
/*** 根据动态条件统计用户数量* @param map* @return*/Integer countByMap(Map map);
在UserMapper.xml文件中编写动态SQL
<select id="countByMap" resultType="java.lang.Integer">select count(id) from user<where><if test="begin != null">and create_time >= #{begin}</if><if test="end != null">and create_time <= #{end}</if></where>
</select>
2、订单统计
订单统计通过一个折现图来展现,折线图上有两根线,这根蓝色的线代表的是订单总数,而下边这根绿色的线代表的是有效订单数,指的就是状态是已完成的订单就属于有效订单,分别反映的是每一天的数据。上面还有3个数字,分别是订单总数、有效订单、订单完成率,它指的是整个时间区间之内总的数据。
原型图:

业务规则:
- 有效订单指状态为 “已完成” 的订单
- 基于可视化报表的折线图展示订单数据,X轴为日期,Y轴为订单数量
- 根据时间选择区间,展示每天的订单总数和有效订单数
- 展示所选时间区间内的有效订单数、总订单数、订单完成率,订单完成率 = 有效订单数 / 总订单数 * 100%
接口设计
根据上述原型图设计接口。
VO设计
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderReportVO implements Serializable {//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03private String dateList;//每日订单数,以逗号分隔,例如:260,210,215private String orderCountList;//每日有效订单数,以逗号分隔,例如:20,21,10private String validOrderCountList;//订单总数private Integer totalOrderCount;//有效订单数private Integer validOrderCount;//订单完成率private Double orderCompletionRate;}
在ReportController中根据订单统计接口创建orderStatistics方法
@GetMapping("/ordersStatistics")@ApiOperation("订单数据统计")public Result<OrderReportVO> orderStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("订单数量统计{},{}",begin,end);//调用业务OrderReportVO orderReportVO = reportService.getOrderStatistics(begin,end);return Result.success(orderReportVO);}
在ReportService中根据订单统计接口
/*** 订单统计数据* @param begin* @param end* @return*/OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end);
实现Service
/*** 订单统计数据** @param begin* @param end* @return*/@Overridepublic OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end) {//订单统计:日期列表dateList,每天订单数量列表//1、根据开始日期与结束日期生成列表List<LocalDate> dateList = getDateList(begin, end);//2、定义每天订单总数量 List<Integer> orderCountList 和每天有效订单数量列表 List<Integer> validOrderCountListList<Integer> orderCountList = new ArrayList<>();List<Integer> validOrderCountList = new ArrayList<>();//3、遍历日期列表dateListfor (LocalDate date : dateList) {//生成当天最大时间和最小时间LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);Map<String, Object> map = new HashMap<>();//获取当天订单map.put("beginTime",beginTime);map.put("endTime",endTime);Integer orderCount = orderMapper.orderCountByToday(map);orderCount = orderCount == null?0:orderCount;orderCountList.add(orderCount);//获取有效订单map.put("status", Orders.COMPLETED);Integer validOrder = orderMapper.orderCountByToday(map);validOrder = validOrder == null?0:validOrder;validOrderCountList.add(validOrder);}//4、计算所有天订单总数量和有效订单总数量Integer totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();Integer validOrderCount = validOrderCountList.stream().reduce(Integer::sum).get();Double orderCompletionRate = 0.0;//5、计算完成率if (totalOrderCount != 0){orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;}//6、封装数据返回return OrderReportVO.builder().dateList(StringUtils.join(dateList,",")).orderCountList(StringUtils.join(orderCountList,",")).validOrderCountList(StringUtils.join(validOrderCountList,",")).totalOrderCount(totalOrderCount).validOrderCount(validOrderCount).orderCompletionRate(orderCompletionRate).build();}
mapper层实现
/*** 获取订单数* @param map* @return*/Integer orderCountByToday(Map<String, Object> map);
<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 >= #{begin}</if><if test="end != null">and order_time <= #{end}</if></where>
</select>
3、销量排名Top10
所谓销量排名,销量指的是商品销售的数量。项目当中的商品主要包含两类:一个是套餐,一个是菜品,所以销量排名其实指的就是菜品和套餐销售的数量排名。通过柱形图来展示销量排名,这些销量是按照降序来排列,并且只需要统计销量排名前十的商品。
原型图:

业务规则:
- 根据时间选择区间,展示销量前10的商品(包括菜品和套餐)
- 基于可视化报表的柱状图降序展示商品销量
- 此处的销量为商品销售的份数
接口设计
据上述原型图设计接口。
VO设计
根据销量排名接口的返回结果设计VO

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SalesTop10ReportVO implements Serializable {//商品名称列表,以逗号分隔,例如:鱼香肉丝,宫保鸡丁,水煮鱼private String nameList;//销量列表,以逗号分隔,例如:260,215,200private String numberList;}
Controller层
在ReportController中根据销量排名接口创建top10方法
@ApiOperation("销售top10统计")@GetMapping("/top10")public Result<SalesTop10ReportVO> salesTop10Statistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("销售前10排名{},{}",begin,end);SalesTop10ReportVO salesTop10ReportVO = reportService.getSalesTop10(begin,end);return Result.success(salesTop10ReportVO);}
Service层接口
/*** 销售前10统计* @param begin* @param end* @return*/SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end);
接口实现类
/*** 销售前10统计** @param begin* @param end* @return*/@Overridepublic SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {//目标:top10统计:商品名称列表 List<String> nameList,每天销量列表List<Integer> numberList//获取最大和最小时间LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);//查询top商品和销量List<GoodsSalesDTO> goodsSalesDTOS = orderMapper.getTop10(beginTime,endTime);//获取商品名称列表集合List<String> nameList = goodsSalesDTOS.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());//获取销量列表集合List<Integer> numberList = goodsSalesDTOS.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());return SalesTop10ReportVO.builder().nameList(StringUtils.join(nameList,",")).numberList(StringUtils.join(numberList,",")).build();}
mapper层
/*** 获取top10* @param beginTime* @param endTime* @return*/List<GoodsSalesDTO> getTop10(LocalDateTime beginTime, LocalDateTime endTime);
<select id="getTop10" resultType="com.sky.dto.GoodsSalesDTO">select od.name,sum(od.number) number from orders oinner join order_detail od on o.id = od.order_id<where><if test="beginTime != null">and order_time >= #{beginTime}</if><if test="endTime != null">and order_time <= #{endTime}</if></where>group by od.name order by number desc limit 10</select>
相关文章:

苍穹外卖数据可视化
文章目录 1、用户统计2、订单统计3、销量排名Top10 1、用户统计 所谓用户统计,实际上统计的是用户的数量。通过折线图来展示,上面这根蓝色线代表的是用户总量,下边这根绿色线代表的是新增用户数量,是具体到每一天。所以说用户统计…...

AWS需要实名吗?
AWS作为全球领先的云计算服务提供商,对于实名认证有着严格的要求。实名认证是指用户在使用AWS服务时需要提供真实有效的个人身份信息,以便AWS能够对用户的身份进行验证和管理。对于AWS而言,实名认证是确保用户安全和服务质量的重要环节&#…...

Android下HWC以及drm_hwcomposer普法(下)
Android下HWC以及drm_hwcomposer普法(下) 引言 不容易啊,写到这里。经过前面的普法(上),我相信童鞋们对HWC和drm_hwcomposer已经有了一定的认知了。谷歌出品,必须精品。我们前面的篇章见分析到啥来了,对了分析到了HwcDisplay::in…...

【评价类模型】熵权法
1.客观赋权法: 熵权法是一种客观求权重的方法,所有客观求权重的模型中都要有以下几步: 1.正向化处理: 极小型指标:取值越小越好的指标,例如错误率、缺陷率等。 中间项指标:取值在某个范围内较…...

PG 窗口函数
一,简介 窗口函数也叫分析函数,也叫OLAP函数,通过partition by分组,这里的窗口表示范围,,可以不指定PARATITION BY,会将这个表当成一个大窗口。 二,应用场景 (1)用于分…...

冯喜运:5.31晚间黄金原油行情分析及尾盘操作策略
【黄金消息面分析】:周五(5月31日),最新发布的数据显示,美国4月核心PCE物价指数月率录得0.2%,低于预期(0.3%),经济学家认为,核心指数比整体指数更能反映通胀。除此之外,美…...

Vue 框选区域放大(纯JavaScript实现)
需求:长按鼠标左键框选区域,松开后放大该区域,继续框选继续放大,反向框选恢复原始状态 实现思路:根据鼠标的落点,放大要显示的内容(内层盒子),然后利用水平偏移和垂直偏…...

C#加密与java 互通
文章目录 前言对方接口签名要求我方对接思路1.RSA 加密2.AES256加密 完整的加密帮助类 前言 提示:这里可以添加本文要记录的大概内容: 在我们对接其他公司接口的时候,时常会出现对方使用的开发语言和我方使用的开发语言不同的情况ÿ…...

C#【进阶】特殊语法
特殊语法、值和引用类型 特殊语法 文章目录 特殊语法1、var隐式类型2、设置对象初始值3、设置集合初始值4、匿名类型5、可空类型6、空合并操作符7、内插字符串8、单句逻辑简略写法 值和引用类型1、判断值和引用类型2、语句块3、变量的生命周期4、结构体中的值和引用5、类中的值…...

c语言之向文件读写数据块
c语言需要向文件读写数据块需要用到fread语句和fwrite语句 fread语句的语法格式 fread(butter,size,count,fp) butter:读取的数据存入内存地址 size:读取的字节大小 count:读取数据的个数 fp:读取的文件指针 fwrite语句语法格式 fwrite(butter,size,count,fp…...

6键编程智能照明:编程指南与深度解析
6键编程智能照明:编程指南与深度解析 随着智能家居的普及,智能照明系统逐渐成为现代家庭不可或缺的一部分。而6键编程智能照明,以其高度的灵活性和个性化设置,受到了越来越多消费者的青睐。那么,如何对6键编程智能照明…...

sql server 中的6种约束
一、约束定义 约束是用于定义和实施表的规则和限制,以确保数据的完整性和一致性。 即对一张表中的属性操作进行限制。 二、约束分类 通过定义约束,可以对数据库中的数据进行限制,以下是常见的约束: 1. 主键约束(Pr…...

师彼长技以助己(2)产品思维
师彼长技以助己(2)产品思维 前言 我把产品思维称之为:人生底层的能力以及蹉跎别人还蹉跎自己的能力,前者说明你应该具备良好产品思维原因,后者是你没有好的产品思维去做产品带来的灾难。 人欲即天理 请大家谈谈看到这…...

Redis学习笔记【基础篇】
SQL vs NOSQL SQL(Structured Query Language)和NoSQL(Not Only SQL)是两种不同的数据库处理方式,它们在多个维度上有所差异,主要区别包括: 数据结构: SQL(关系型数据库)…...

【文献阅读】基于模型设计的汽车软件质量属性
参考文献:《基于模型设计满足汽车软件质量和快速交付的挑战》,深向科技在2024年MATLAB XEPO大会的演讲 Tips:KISS原则,全称为“Keep It Simple, Stupid”,直译为“保持简单,愚蠢的人也能懂”...

撸广告赚金币小游戏app开发
在app上投放广告有哪些注意事项? 在app上投放广告需要注意以下几个方面。 首先,要选择合适的广告形式。根据自己的需求和目标受众,选择合适的广告形式,如横幅广告、插屏广告、视频广告等。不同的广告形式适用于不同的场景和目标…...

海外高清短视频:四川京之华锦信息技术公司
海外高清短视频:探索世界的新窗口 在数字化时代的浪潮下,海外高清短视频成为了人们探索世界、了解异国风情的新窗口。四川京之华锦信息技术公司这些短视频以其独特的视角、丰富的内容和高清的画质,吸引了无数观众的目光,让人们足…...

16:00面试,16:08就出来了,问的问题有点变态。。。
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到8月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…...

Android MediaCodec 简明教程(九):使用 MediaCodec 解码到纹理,使用 OpenGL ES 进行处理,并编码为 MP4 文件
系列文章目录 Android MediaCodec 简明教程(一):使用 MediaCodecList 查询 Codec 信息,并创建 MediaCodec 编解码器Android MediaCodec 简明教程(二):使用 MediaCodecInfo.CodecCapabilities 查…...

Neo4j安装部署及python连接neo4j操作
Neo4j安装部署及python连接neo4j操作 Neo4j安装和环境配置 安装依赖库: sudo apt-get install wget curl nano software-properties-common dirmngr apt-transport-https gnupg gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y 增加Neo4 GPG key&…...

一维时间序列信号的改进小波降噪方法(MATLAB R2021B)
目前国内外对于小波分析在降噪方面的方法研究中,主要有小波分解与重构法降噪、小波阈值降噪、小波变换模极大值法降噪等三类方法。 (1)小波分解与重构法降噪 早在1988 年,Mallat提出了多分辨率分析的概念,利用小波分析的多分辨率特性进行分…...

Java整合EasyExcel实战——3(上下列相同合并单元格策略)
参考:https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06 准备条件 依赖 <dependency><groupId>com.alibaba</gr…...

dmdts连接kingbase8报错
dmdts连接kingbase报错 环境介绍1 人大金仓jdbc配置2 dmdts 人大金仓jdbc默认配置3 dmdts 修改jdbc配置4 达梦产品学习使用列表 环境介绍 dts版本 使用dmdts连接kingbase金仓数据库报错 无效的URL 对比jdbc连接串,修改配置解决 1 人大金仓jdbc配置 配置URL模版信息等 类名…...

【算法训练 day44 分割等和子集】
目录 一、分割等和子集-LeetCode 416思路实现代码1.二维dp代码2.一维dp代码 问题总结 一、分割等和子集-LeetCode 416 Leecode链接: leetcode 416 文章链接: 代码随想录 视频链接: B站 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&…...

前端实习记录——git篇(一些问题与相关命令)
1、版本控制 (1)版本回滚 git log // 查看版本git reset --mixed HEAD^ // 回滚到修改状态,文件内容没有变化git reset --soft HEAD^ // 回滚暂存区,^的个数代表几个版本git reset --hard HEAD^ // 回滚到修改状态ÿ…...

XML Web 服务技术解析:WSDL 与 SOAP 原理、应用案例一览
XML Web服务是一种用于在网络上发布、发现和使用应用程序组件的技术。它基于一系列标准和协议,如WSDL、SOAP、RDF和RSS。下面是一些相关的内容: WSDL(Web服务描述语言):用于描述Web服务的基于XML的语言,定义…...

解析Java中1000个常用类:FunctionalInterface类,你学会了吗?
Java 8 引入了一系列新的特性和改进,其中之一便是函数式编程。函数式接口(Functional Interface)是函数式编程的核心概念之一。本文将深入探讨 FunctionalInterface 注解,介绍其用法、重要性,并通过示例展示如何在实际开发中应用函数式接口。 什么是函数式接口? 函数式…...

Kafka自定义分区器编写教程
1.创建java类MyPartitioner并实现Partitioner接口 点击灯泡选择实现方法,导入需要实现的抽象方法 2.实现方法 3.自定义分区器的使用 在自定义生产者消息发送时,属性配置上加入自定义分区器 properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,&q…...

python移动文件
测试1(直接把B文件夹移动到了A里,成为了A的子文件夹) import os import shutil# 移动文件夹,B文件夹在当前目录没有了,跑到了A的子文件里 ## shutil.move(./example1/B/, ./example1/A/)测试2(B文件不动,将B文件里的所有的子文件夹移动到A内…...

eNSP学习——OSPF的DR与BDR
目录 相关命令 原理概述 实验内容 实验目的 实验拓扑 实验编址 实验步骤 1、基本配置 2、搭建基本的OSPF网络 3、查看默认情况下的DR/BDR状态 4、根据现网需求影响DR/BDR选举 相关命令 [R4]int g0/0/0 [R4-GigabitEthernet0/0/0]ospf network-type p2mp //在接…...