1.Apache ECharts
Apache ECharts 是一款基于 Javascript 的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。
官网地址:Apache ECharts
Apache Echarts官方提供的快速入门:快速上手 - 使用手册 - Apache ECharts
总结:使用Echarts,重点在于研究当前图表所需的数据格式。通常是需要后端提供符合格式要求的动态数据,然后响应给前端来展示图表。
2.营业额统计
1.需求分析与设计
2.代码开发
ReportController
@DateTimeFormat(pattern = "YYYY-MM-DD") LocalDate begin一开始这样子写的,然后就报错400,bad request。所以记得格式一定要写正确
![](https://i-blog.csdnimg.cn/blog_migrate/4325afcd5f46084f086ddb572b880e47.png)
ReportServiceImpl
这里常用map作为参数是因为这几个接口相似,但是属性不太一样,所以用map就可以得到对应最符合他们需要的对象,而不是一个DTO。
@Service
public class ReportServiceImpl implements ReportService {
@Autowired
private OrderMapper orderMapper;
/**
* 根据时间区间统计营业额
* @param begin
* @param end
* @return
*/
public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
//获取横坐标:日期
List<LocalDate> dateList=new ArrayList<>();
dateList.add(begin);
//添加begin-end的日期
while (!begin.equals(end)){
begin=begin.plusDays(1);//日期计算,获取指定日期后1天的日期
dateList.add(begin);
}
//获取纵坐标:营业额
List<Double> turnoverList=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("status", Orders.COMPLETED);
map.put("begin",beginTime);
map.put("end",endTime);
Double turnover = orderMapper.sumByMap(map);
turnover=turnover==null?0.0:turnover;
turnoverList.add(turnover);
}
//数据封装
return TurnoverReportVO.builder()
.dateList(StringUtils.join(dateList, ","))
.turnoverList(StringUtils.join(turnoverList, ","))
.build();
}
}
OrderMapper.xml
<select id="sumByMap" resultType="java.lang.Double">
select sum(amount) 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.用户统计
1.需求分析与设计
2.代码开发
ReportController
/**
*用户数据统计
* @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){
return Result.success(reportService.getUserStatistics(begin,end));
}
ReportServiceImpl
/**
* 根据时间区间统计用户量
*
* @param begin
* @param end
* @return
*/
public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
//日期
List<LocalDate> dateList = new ArrayList<>();
dateList.add(begin);
while (!begin.equals(end)) {
begin = begin.plusDays(1);
dateList.add(begin);
}
List<Integer> newUserList = new ArrayList<>();//新增用户数
List<Integer> totalUserList = new ArrayList<>();//总用户数
for (LocalDate date : dateList) {
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
//总用户数 select count(id) from user where create_Time<endTime
//新增用户数 select count(id) from user where create_time>beginTime and create_Time<endTime
Map map = new HashMap<>();
map.put("end", endTime);
Integer totalUser = userMapper.countByMap(map);
map.put("bengin", beginTime);
Integer newUser = userMapper.countByMap(map);
newUserList.add(newUser);
totalUserList.add(totalUser);
}
return UserReportVO.builder().
dateList(StringUtils.join(dateList, ",")).
newUserList(StringUtils.join(newUserList, ",")).
totalUserList(StringUtils.join(totalUserList, ",")).
build();
}
UserMapper.xml
<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>
4.订单统计
1.需求分析与设计
2.代码开发
ReportController
/**
* 订单数据统计
* @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){
return Result.success(reportService.getOrderStatistics(begin,end));
}
ReportServiceImpl
/**
* 根据时间区间统计订单
*
* @param begin
* @param end
* @return
*/
public OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end) {
List<LocalDate> dateList = new ArrayList<>();
dateList.add(begin);
while (!begin.equals(end)) {
begin = begin.plusDays(1);
dateList.add(begin);
}
//每日订单总数
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);
//查询每天订单总数 select count(id) from orders where order_time >? and order_time<?
Map map=new HashMap<>();
map.put("begin",beginTime);
map.put("end",endTime);
Integer totalOrder = orderMapper.countByMap(map);
//查询每天订单有效数 select count(id) from orders where order_time >? and order_time<? and status=?
map.put("status", Orders.COMPLETED);
Integer validOrder =orderMapper.countByMap(map);
orderCountList.add(totalOrder);
validOrderCountList.add(validOrder);
}
//时间区间内的总订单数
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;
}
return OrderReportVO.builder()
.dateList(StringUtils.join(dateList,","))
.orderCountList(StringUtils.join(orderCountList,","))
.validOrderCountList(StringUtils.join(validOrderCountList,","))
.totalOrderCount(totalOrderCount)
.validOrderCount(validOrderCount)
.orderCompletionRate(orderCompletionRate)
.build();
}
OrderMapper.xml
<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>
5.销量排名Top10
1.需求分析与设计
2.代码开发
ReportController
/**
* 销量排名统计
* @param begin
* @param end
* @return
*/
@GetMapping("/top10")
@ApiOperation("销量排名统计")
public Result<SalesTop10ReportVO> top10(
@DateTimeFormat(pattern = "yyyy-MM-dd")
LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd")
LocalDate end){
return Result.success(reportService.getSalesTop10(begin,end));
}
ReportServiceImpl
GoodsSalesDTO::getName这是什么写法
GoodsSalesDTO::getName
是一种 Java 8 中的方法引用(Method Reference)写法。
在这种写法中,GoodsSalesDTO::getName
表示引用了 GoodsSalesDTO
类的 getName
方法,但没有直接调用该方法。这种写法适用于 lambda 表达式中只调用一个已存在的方法的情况。
map
方法需要一个函数作为参数,该函数将会被应用于 Stream 中的每个元素。GoodsSalesDTO::getName
就是这个函数,它接收一个 GoodsSalesDTO
对象并调用其 getName
方法来获取该对象的 name 属性。
通过这种方式,map
方法能够将 GoodsSalesDTO
对象的 name 属性抽取出来,并将其作为字符串的元素添加到新的 Stream 中。
/**
* 销量排名统计
* @param begin
* @param end
* @return
*/
public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {
LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
List<GoodsSalesDTO> goodsSalesDTOList=orderMapper.getSalesTop10(beginTime,endTime);
String nameList = StringUtils.join(goodsSalesDTOList.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList()), ",");
String numberList = StringUtils.join(goodsSalesDTOList.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList()), ",");
return SalesTop10ReportVO.builder()
.nameList(nameList)
.numberList(numberList)
.build();
}
OrderMapper.xml
通过订单号和订单菜品详情匹配查找到相应订单菜品详情中菜品的数量和名字。
GROUP BY
子句的作用是对查询结果进行分组,以便进行聚合计算或者对每个分组进行进一步的统计或筛选。
limit 0,10 只返回前10条记录。
<select id="getSalesTop10" resultType="com.sky.dto.GoodsSalesDTO">
select od.name name, sum(od.number) number from order_detail od,orders o
where od.order_id = o.id
and o.status=5
<if test="beginTime !=null"> and order_time >= #{beginTime}</if>
<if test="endTime !=null"> and order_time <= #{endTime}</if>
group by name
order by number desc
limit 0,10
</select>
改bug:
一开始报错500,后面差错发现是因为mapper里面的参数名和xml里面的名字不一致导致的。