Apache ECharts
Apache ECharts介绍:
Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。
官网地址:https://echarts.apache.org/zh/index.html
Apache ECharts入门程序:
进入官网,按照官方给的步骤:
<!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: 'ECharts 入门示例'},tooltip: {},legend: {data: ['销量']},xAxis: {data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);</script></body>
</html>
营业额统计:
业务规则及接口设计:
- 营业额指订单状态为已完成的订单金额合计
- 基于可视化报表的折线图展示营业额数据,X轴为日期,Y轴为营业额
- 根据时间选择区间,展示每天的营业额数据
前端想展示数据,也要设计接口从后端获取数据。
返回数据这一块,因为是前端来展示数据,所以我们提供的数据是要依照前端的规则。
具体代码实现:
Controll层:
@Autowiredprivate ReportService reportService;/*** 营业额统计* @param begin* @param end* @return*/@GetMapping("/turnoverStatistics")@ApiOperation("营业额统计")public Result<TurnoverReportVO> turnoverStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("营业额统计");TurnoverReportVO turnoverReportVO = reportService.turnoverStatistics(begin,end);return Result.success(turnoverReportVO);}
这里有个小细节,就是查询统计营业额,前端传的参数是日期的起始时间和结束时间,
格式是yyyy-MM-dd这种形式,所以,我们也要用这种形式来进行接收。
@DateTimeFormat(pattern = "yyyy-MM-dd"),就用到了这个方法。
Service层:
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 org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.validation.constraints.Min;
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;@Service
public class ReportServiceImpl implements ReportService {@Autowiredprivate OrderMapper orderMapper;@Overridepublic TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {//封装TurnoverReportVO的dateList对象List<LocalDate> datelist = new ArrayList<>();datelist.add(begin);while(!begin.equals(end)){//将日期加到list集合中begin = begin.plusDays(1);datelist.add(begin);}String datejoin = StringUtils.join(datelist, ",");//封装TurnoverReportVO的turnoverList对象List<Double> turnoverlist = new ArrayList<>();for (LocalDate localDate : datelist) {//查询date日期对应的营业额数据,营业额是指:状态为“已完成”的订单金额合计LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate,LocalTime.MAX);//select sum(amount) from orders where order_time > ? and order_time < ? and status = 5Map map = new HashMap();map.put("begin",beginTime);map.put("end",endTime);map.put("status", Orders.COMPLETED);Double turnover = orderMapper.TurnoverOfSum(map);turnover = turnover==null?0.0:turnover;turnoverlist.add(turnover);}for (Double v : turnoverlist) {System.out.println("今日份营业额:"+ v);}//封装TurnoverReportVO对象TurnoverReportVO turnoverReportVO = new TurnoverReportVO();turnoverReportVO.setDateList(datejoin);turnoverReportVO.setTurnoverList(StringUtils.join(turnoverlist,","));return turnoverReportVO;}
}
思路:
我们观察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层及注解:
/*** 动态查询营业额* @param map* @return*/Double TurnoverOfSum(Map map);
<select id="TurnoverOfSum" resultType="java.lang.Double">select sum(amount) from sky_take_out.orders<where><if test="begin != null">and order_time > #{begin}</if><if test="end != null">and order_Time < #{end}</if><if test="status != null"> and status = #{status} </if></where></select>
用户统计:
业务规则及接口设计:
业务规则:
- 基于可视化报表的折线图展示用户数据,X轴为日期,Y轴为用户数
- 根据时间选择区间,展示每天的用户总量和新增用户量数据
用户统计和上面的不同点就是我们的返回值有三个列表:
- dateList
- newUserList
- totalUserList
具体代码实现:
整体的思路和上面的营业额统计差不多
Controll层:
/*** 用户数量统计* @param begin* @param end* @return*/@GetMapping("/userStatistics")@ApiOperation("用户数量统计")public Result<UserReportVO> userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("用户数量统计");UserReportVO userReportVO = reportService.userStatistics(begin,end);return Result.success(userReportVO);}
Service层:
/*** 用户数量统计* @param begin* @param end* @return*/@Overridepublic UserReportVO userStatistics(LocalDate begin, LocalDate end) {//封装UserReportVO的dateList对象List<LocalDate> dateList = new ArrayList<>();while (!begin.equals(end)){dateList.add(begin);begin = begin.plusDays(1);}String datejoin = StringUtils.join(dateList, ",");//封装UserReportVO的totalUserList对象//select count(id) from user where create_time < endTime//封装UserReportVO的newUserList对象//select count(id) from user where create_time > beginTime and create_time < endTimeList<Integer> totalUserList = new ArrayList<>();List<Integer> newUserList = new ArrayList<>();for (LocalDate date : dateList) {LocalDateTime beginTime = LocalDateTime.of(date,LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(date,LocalTime.MAX);Map map = new HashMap();map.put("end",endTime);Integer totalUser = userMapper.UserofSum(map);map.put("begin",beginTime);Integer newUser = userMapper.UserofSum(map);totalUserList.add(totalUser);newUserList.add(newUser);}String totaluserjoin = StringUtils.join(totalUserList, ",");String newluserjoin = StringUtils.join(newUserList, ",");UserReportVO userReportVO = new UserReportVO();userReportVO.setDateList(datejoin);userReportVO.setTotalUserList(totaluserjoin);userReportVO.setNewUserList(newluserjoin);return userReportVO;}
这里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);
<select id="UserofSum" resultType="java.lang.Integer">select count(id) from sky_take_out.user<where><if test="begin != null">and create_time > #{begin}</if><if test="end != null">and create_time < #{end}</if></where></select>
订单统计:
业务规则及接口设计:
业务规则:
- 有效订单指状态为 “已完成” 的订单
- 基于可视化报表的折线图展示订单数据,X轴为日期,Y轴为订单数量
- 根据时间选择区间,展示每天的订单总数和有效订单数
- 展示所选时间区间内的有效订单数、总订单数、订单完成率,订单完成率 = 有效订单数 / 总订单数 * 100%
具体的代码实现:
Controll层:
/*** 订单统计* @param begin* @param end* @return*/@GetMapping("/ordersStatistics")@ApiOperation("订单统计")public Result<OrderReportVO> orderStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("订单统计");OrderReportVO orderReportVO = reportService.ordersStatistics(begin,end);return Result.success(orderReportVO);}
Service层:
/*** 订单统计* @param begin* @param end* @return*/@Overridepublic OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {//封装OrderReportVO的dateList对象List<LocalDate> dateList = new ArrayList<>();while (!begin.equals(end)){dateList.add(begin);begin = begin.plusDays(1);}String datejoin = StringUtils.join(dateList, ",");//封装OrderReportVO的orderCountList对象//封装OrderReportVO的validOrderCountList对象List<Integer> orderCountList = new ArrayList<>();List<Integer> validOrderCountList = new ArrayList<>();for (LocalDate date : dateList) {LocalDateTime beginTime = LocalDateTime.of(date,LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(date,LocalTime.MAX);Map map = new HashMap();map.put("begin",beginTime);map.put("end",endTime);Integer totalorders = orderMapper.OrdersofSum(map);map.put("status",Orders.COMPLETED);Integer validorders = orderMapper.OrdersofSum(map);orderCountList.add(totalorders);validOrderCountList.add(validorders);}String totaljoin = StringUtils.join(orderCountList, ",");String validjoin = StringUtils.join(validOrderCountList,",");//计算时间区间内的订单总数量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.doubleValue();}OrderReportVO orderReportVO = new OrderReportVO();orderReportVO.setDateList(datejoin);orderReportVO.setOrderCountList(totaljoin);orderReportVO.setValidOrderCountList(validjoin);orderReportVO.setTotalOrderCount(totalOrderCount);orderReportVO.setValidOrderCount(validOrderCount);orderReportVO.setOrderCompletionRate(orderCompletionRate);return orderReportVO;}
Mapper层及注解:
/*** 订单统计* @param map* @return*/Integer OrdersofSum(Map map);
<select id="OrdersofSum" resultType="java.lang.Integer">select count(id) from sky_take_out.orders<where><if test="begin != null">and order_time > #{begin}</if><if test="end != null">and order_Time < #{end}</if><if test="status != null">and status=#{status}</if></where></select>
销量排名统计(TOP10):
业务规则及接口设计:

业务规则:
- 根据时间选择区间,展示销量前10的商品(包括菜品和套餐)
- 基于可视化报表的柱状图降序展示商品销量
- 此处的销量为商品销售的份数
具体的代码实现:
Controll层:
/*** TOP10销量统计* @param begin* @param end* @return*/@GetMapping("/top10")@ApiOperation("TOP10销量统计")public Result<SalesTop10ReportVO> Top10Statostics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("TOP10销量统计");SalesTop10ReportVO salesTop10ReportVO = reportService.Top10Statostics(begin,end);return Result.success(salesTop10ReportVO);}
Service层:
/*** TOP10销量统计* @param begin* @param end* @return*/@Overridepublic SalesTop10ReportVO Top10Statostics(LocalDate begin, LocalDate end) {LocalDateTime beginTime = LocalDateTime.of(begin,LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(end,LocalTime.MAX);System.out.println("开始时间是:"+beginTime);System.out.println("结束时间是:"+endTime);List<GoodsSalesDTO> goodsSalesDTOList = orderMapper.GetTop10(beginTime,endTime);List<String> names = goodsSalesDTOList.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());String nameList = StringUtils.join(names, ",");List<Integer> numbers = goodsSalesDTOList.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());String numberList = StringUtils.join(numbers, ",");SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();salesTop10ReportVO.setNameList(nameList);salesTop10ReportVO.setNumberList(numberList);return salesTop10ReportVO;}
这题的从sql语句开始分析比较简单
select od.name,sum(od.number) number from order_detail od,orders o
where od.order_id = o.id and o.status = 5 and o.order_time < 2024-05-04 and o.order_time > 2024-05-10
group by od.name
order by number desc
limit 0,10
根据传入的时间范围来获取数据。
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) numberfrom sky_take_out.order_detail od,sky_take_out.orders owhere od.order_id = o.id and o.status = 5<if test="beginTime != null">and o.order_time > #{beginTime}</if><if test="endTime != null">and o.order_Time < #{endTime}</if>group by od.nameorder by number desclimit 0,10</select>
结果展示:
相关文章:

Apache ECharts
Apache ECharts介绍: Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。 官网地址:https://echarts.apache.org/zh/index.html Apache ECh…...

超详细的胎教级Stable Diffusion使用教程(四)
这套课程分为五节课,会系统性的介绍sd的全部功能和实操案例,让你打下坚实牢靠的基础 一、为什么要学Stable Diffusion,它究竟有多强大? 二、三分钟教你装好Stable Diffusion 三、小白快速上手Stable Diffusion 四、Stable dif…...

串口属性中的BM延时计时器问题
如果使用程序修改则需要修改注册表对应位置如下 第一个示例(217) 第二个示例(219) 需要注意的事情是修改前必须点查看串口名称(例如上图是com5) 程序修改: 有没有办法以编程方式更改USB <…...

PyQt6--Python桌面开发(8.QPlainTextEdit纯文本控件)
QPlainTextEdit纯文本控件...

Java | Leetcode Java题解之第83题删除排序链表中的重复元素
题目: 题解: class Solution {public ListNode deleteDuplicates(ListNode head) {if (head null) {return head;}ListNode cur head;while (cur.next ! null) {if (cur.val cur.next.val) {cur.next cur.next.next;} else {cur cur.next;}}return…...

重生奇迹mu再生宝石怎么用有什么用
重生奇迹mu再生宝石有2个用处: 1、在玛雅哥布林处给380装备加PVP属性4追4以上的380级装备,守护宝石一颗,再生宝石一颗,成功得到PVP装备,失败宝石消失,装备无变化; 2、给非套装点强化属性用法跟祝福,灵魂,生命一样直接往装备上敲,成功得到随机强化属性一…...

pdf 文件版面分析--pdfplumber (python 文档解析提取)
pdfplumber 的特点 1、它是一个纯 python 第三方库,适合 python 3.x 版本 2、它用来查看pdf各类信息,能有效提取文本、表格 3、它不支持修改或生成pdf,也不支持对pdf扫描件的处理 import glob import pdfplumber import re from collection…...

PostgreSQL的学习心得和知识总结(一百四十三)|深入理解PostgreSQL数据库之Support event trigger for logoff
目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…...

https免费证书获取
获取免费证书的网址: Certbot 1. 进入你的linux系统,先安装snapd, yum install snapd 2. 启动snapd service snapd start 3.安装 Certbot snap install --classic certbot 注意如下出现此错误时,需要先建立snap 软连接后&am…...

C语言 | Leetcode C语言题解之第74题搜索二维矩阵
题目: 题解: bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {int m matrixSize, n matrixColSize[0];int low 0, high m * n - 1;while (low < high) {int mid (high - low) / 2 low;int x matrix[mid /…...

杰发科技AC7840——软件Sent_HAL39X
0. 序 使用PWM模拟Sent测试下7840的软件sent功能。 参考链接:SENT协议应用笔记 - TechPlus汽车工坊的文章 - 知乎 SENT协议 1. Sent功能测试 使用提供的软件Sent代码在7840上测试,接收数据OK 2. 参考资料 3. 数据解析 我们个根据上述参考资料尝试解析…...

IOS 开发 - block 使用详解
1.Blobk的定义 block的写法相对难记,不必司机应被,只需要在xcode里打出"inlineBlock"--回车, 系统会自动帮你把基础版写法给你匹配出来 //Block的基础声明//等号""之前是blobk的声明,等号“”后面是block的实现/*returnType:返回类型(void、int、String *…...

BUU-[极客大挑战 2019]Http
考察点 信息收集 http构造请求数据包 题目 解题步骤 参考文章:https://zhuanlan.zhihu.com/p/367051798 查看源代码 发现有一个a标签,但是οnclick"return false"就是点击后不会去跳转到Secret.php的页面 所以我就自己拼接url http://no…...

开发Web3 ETF的技术难点
开发Web3 ETF(Exchange-Traded Fund,交易所交易基金)软件时,需要注意以下几个关键问题。开发Web3 ETF软件是一个复杂的过程,涉及到金融、法律和技术多个领域的专业知识。开发团队需要综合考虑上述问题,以确…...

【K8s】Kubectl 常用命令梳理
Kubectl常用命令梳理 下面包含大致涵盖命令只需要替换对应的Pod \ NameSpace 查看 命名空间 是 ’worktest2‘ 下 名字包括 ’todo‘的所有 Pod kubectl -n worktest2 get pod|grep todo查看 所有命名空间下 名字包括 ’todo‘的所有 Pod kubectl get pods --all-namespace…...

机器学习-监督学习
监督学习是机器学习和人工智能中的一个重要分支,它涉及使用已标记的数据集来训练算法,以便对数据进行分类或准确预测结果。监督学习的核心在于通过输入数据(特征)和输出数据(标签或类别)之间的关系…...

搭建Docker私服镜像仓库Harbor
1、概述 Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。 Harbor 的所有组件都在 Dcoker 中部署,所以 Harbor 可使用 Docker Compose 快速部署。 …...

SpringBoot自定义初始化sql文件 支持多类型数据库
我在resources目录下有init.sql初始化sql语句 指定sql文件的地址 sql内容如下: /*角色表*/ INSERT INTO #{schema}ccc_base_role (id, create_time, create_user_id, is_delete, role_name, status, update_time, update_user_id) VALUES(b89e30d81acb88448d412…...

nginx--FastCGI
CGI 概念 nginx通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx并回收进程(下次处理有需要新建),最后nginx在返回给客户端…...

【数据结构】浅谈
✨✨✨专栏:数据结构 🧑🎓个人主页:SWsunlight 目录 一、概念: 二、物理结构: 1、顺序存储结构: 2、链式存储结构: 3、数据索引存储结构: 4、数据散列存储结构…...

简洁大气APP下载单页源码
源码介绍 简洁大气APP下载单页源码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面 效果截图 源码下载 简洁大气APP下载单页源码...

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环
ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环 1、 for i in range(4):Dev.step(i6)for j in range(3):Dev.turnLeft()Dev.step(2)2、 for i in range(4):Dev.step(i3)for j in range(4):Dev.step(2)Dev.turnRight()Dev.step(-i-3)Dev.turnRight()3、 for i …...

Idea入门:一分钟创建一个Java工程
一,新建一个Java工程 1,启动Idea后,选择 [New Project] 2,完善工程信息 填写工程名称,根据实际用途取有意义的英文名称选择Java语言,可以看到还支持Kotlin、Javascript等语言选择包管理和项目构建工具Mav…...

QGraphicsView实现简易地图8『缓存视口周边瓦片』
前文链接:QGraphicsView实现简易地图7『异步加载-多瓦片-无底图』 前7篇的地图加载,都采用最少瓦片数量的算法,即用最少数量的瓦片覆盖视口,以获得最快的加载速度。但是这样会带来一个问题,那就是每当移动地图时&#…...

如何在Java项目中使用Spring Boot快速连接达梦数据库(DM)
前言 在Java开发领域,Spring Boot凭借其简洁快速的特性成为现代应用开发的首选框架。本文将详细介绍如何在Spring Boot项目中整合JDBC以快速连接达梦数据库(DM),并提供一个简单的示例来验证连接是否成功。 一、环境准备与依赖配置 在开始之前…...

QT中的容器
Qt中的容器 关于Qt中的容器类,下面我们来进行一个总结: Qt的容器类比标准模板库(STL)中的容器类更轻巧、安全和易于使用。这些容器类是隐式共享和可重入的,而且他们进行了速度和存储的优化,因此可以减少可…...

安卓手机APP开发__屏幕兼容性概述
安卓手机APP开发__屏幕兼容性概述 目录 概述 屏幕大小 灵活的布局 备选的布局 可改写的图像 像素的深度 深度依赖 备选的位图 向量图形 概述 安卓运行各种各样的设备,它们有不同的屏幕大小和屏幕的像素深度。 系统执行基本的缩放和变形来适配在不同的屏幕…...

Java实现自定义注解,实现不需要token 验证就可以访问接口
目录 1 问题2 实现 1 问题 一个springboot 项目,需要token 验证,前端传过来token ,我们一般在项目全局写一个过滤器,去验证前端传过来的token ,如果有哪些接口不需要token验证,那么就排除这些接口,这个也需要配置。 …...

SpringBoot集成Minio
1.pom文件引入 <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lomb…...

Colab/PyTorch - 003 Transfer Learning For Image Classification
Colab/PyTorch - 003 Transfer Learning For Image Classification 1. 源由2. 迁移学习(ResNet50)2.1 数据集准备2.2 数据增强2.3 数据加载2.4 迁移学习2.5 数据集训练&验证2.6 模型推理 3. 总结4. 参考资料 1. 源由 迁移学习已经彻底改变了 PyTorch 中处理图像分类的方式…...