目录

一、Apache ECharts【前端】

1. 介绍

2. 入门案例

二、营业额统计

1. 需求分析和设计

1 产品原型

2 业务规则

3 接口设计

2. 代码开发

3. 功能测试

三、用户统计

1. 需求分析和设计

1 产品原型

2 业务规则

3 接口设计

2. 代码开发

 3. 功能测试

四、订单统计

1. 需求分析和设计

1 产品原型

2 业务规则

3 接口设计

2. 代码开发

3. 功能测试

五、销量排名Top10

1. 需求分析和设计

1 产品原型

2 业务规则

3 接口设计

2. 代码开发

3. 功能测试

一、Apache ECharts【前端】

1. 介绍

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

常见效果展示:

1). 柱形图

 

2). 饼形图  

3). 折线图

总结:不管是哪种形式的图形,最本质的东西实际上是数据,它其实是对数据的一种可视化展示。

2. 入门案例

Apache Echarts官方提供的快速入门:快速上手 - 使用手册 - Apache ECharts

效果展示:

实现步骤:

1). 引入echarts.js 文件(当天资料已提供)

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

3). 初始化echarts实例

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

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

代码开发:

ECharts

测试:使用浏览器方式打开即可。

总结:使用Echarts,重点在于研究当前图表所需的数据格式。通常是需要后端提供符合格式要求的动态数据,然后响应给前端来展示图表。

二、营业额统计

1. 需求分析和设计

1 产品原型

营业额统计是基于折现图来展现,并且按照天来展示的。实际上,就是某一个时间范围之内的每一天的营业额。同时,不管光标放在哪个点上,那么它就会把具体的数值展示出来。并且还需要注意日期并不是固定写死的,是由上边时间选择器来决定。比如选择是近7天、或者是近30日,或者是本周,就会把相应这个时间段之内的每一天日期通过横坐标展示。

原型图 :

2 业务规则

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

3 接口设计

通过上述原型图,设计出对应的接口。

注意:具体返回数据一般由前端来决定,前端展示图表,具体折现图对应数据是什么格式,是有固定的要求的。 所以说,后端需要去适应前端,它需要什么格式的数据,我们就给它返回什么格式的数据。

2. 代码开发

//在sky-pojo模块,TurnoverReportVO.java已定义

package com.sky.vo;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class TurnoverReportVO implements Serializable {

//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03

private String dateList;

//营业额,以逗号分隔,例如:406.0,1520.0,75.0

private String turnoverList;

}

--------------

//创建ReportController

//根据接口定义创建ReportController:

package com.sky.controller.admin;

import com.sky.result.Result;

import com.sky.service.ReportService;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.format.annotation.DateTimeFormat;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

@RestController

@Api(tags = "数据统计相关接口")

@RequestMapping("/admin/report")

public class ReportController {

@Autowired

private ReportService reportService;

@GetMapping("/turnoverStatistics")

@ApiOperation("营业额统计接口")

public Result turnoverStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,

@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){

return reportService.turnoverStatistics(begin, end);

}

}

-------------

//创建ReportService

package com.sky.service;

import com.sky.result.Result;

import java.time.LocalDate;

public interface ReportService {

/**

* 统计营业额

* @param begin

* @param end

* @return

*/

Result turnoverStatistics(LocalDate begin, LocalDate end);

}

-------------

//ReportServiceImpl

package com.sky.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.sky.mapper.OrderMapper;

import com.sky.result.Result;

import com.sky.service.ReportService;

import com.sky.vo.TurnoverReportVO;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.time.LocalDate;

import java.time.LocalDateTime;

import java.time.LocalTime;

import java.time.format.DateTimeFormatter;

import java.util.ArrayList;

import java.util.List;

import java.util.stream.Collectors;

@Service

public class ReportServiceImpl implements ReportService {

@Autowired

private OrderMapper orderMapper;

@Override

public Result turnoverStatistics(LocalDate begin, LocalDate end) {

TurnoverReportVO vo = new TurnoverReportVO();

List dateList = new ArrayList<>();

List amountList = new ArrayList<>();

while (!(begin.isAfter(end))) {

//1. 把日期添加到dateList里

dateList.add(begin);

//2. 查询这一天的营业额,添加到amountList里

LocalDateTime startOfDay = LocalDateTime.of(begin, LocalTime.MIN);

LocalDateTime endOfDay = LocalDateTime.of(begin, LocalTime.MAX);

Double amount = orderMapper.sumAmountByDate(startOfDay, endOfDay);

amount = amount == null ? 0D : amount;

amountList.add(amount);

//3. 到下一天

begin = begin.plusDays(1);

}

//dateList 日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03

String dateListStr = dateList.stream()

.map(localDate -> localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))

.collect(Collectors.joining(","));

vo.setDateList(dateListStr);

//turnoverList 营业额,以逗号分隔,例如:406.0,1520.0,75.0

String turnoverListStr = amountList.stream()

.map(Object::toString)

.collect(Collectors.joining(","));

vo.setTurnoverList(turnoverListStr);

return Result.success(vo);

}

}

------------

//OrderMapper

@Select("select sum(amount) from orders where status = 5 and order_time between #{start} and #{end}")

Double sumAmountByDate(LocalDateTime start, LocalDateTime end);

3. 功能测试

可以通过如下方式进行测试:

接口文档测试 前后端联调测试

启动服务器,启动nginx,直接采用前后端联调测试。

进入数据统计模块

1). 查看近7日营业额统计

 

2). 查看近30日营业额统计

 

进入开发者模式,查看返回数据

 也可通过断点方式启动,查看每步执行情况。

三、用户统计

1. 需求分析和设计

1 产品原型

所谓用户统计,实际上统计的是用户的数量。通过折线图来展示,上面这根蓝色线代表的是用户总量,下边这根绿色线代表的是新增用户数量,是具体到每一天。所以说用户统计主要统计两个数据,一个是总的用户数量,另外一个是新增用户数量。

原型图 :

2 业务规则

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

3 接口设计

根据上述原型图设计接口。

2. 代码开发

//在sky-pojo模块,UserReportVO.java已定义

package com.sky.vo;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class UserReportVO implements Serializable {

//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03

private String dateList;

//用户总量,以逗号分隔,例如:200,210,220

private String totalUserList;

//新增用户,以逗号分隔,例如:20,21,10

private String newUserList;

}

--------------

//ReportController

@GetMapping("/userStatistics")

@ApiOperation("用户统计接口")

public Result userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,

@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){

return reportService.userStatistics(begin, end);

}

-------------

//ReportService

/**

* 统计用户

* @param begin

* @param end

* @return

*/

Result userStatistics(LocalDate begin, LocalDate end);

------------

//ReportServiceImpl

@Override

public Result userStatistics(LocalDate begin, LocalDate end) {

UserReportVO vo = new UserReportVO();

List dateList = new ArrayList<>();

List totalCountList = new ArrayList<>();

List newCountList = new ArrayList<>();

while (!(begin.isAfter(end))) {

//把日期加到dateList集合里

dateList.add(begin);

//获取截止到当天的用户总量 select count(*) from user where create_time <= 当天日期

LocalDateTime endOfDay = LocalDateTime.of(begin, LocalTime.MAX);

Integer totalCount = userMapper.countByDate(null, endOfDay);

totalCountList.add(totalCount==null?0:totalCount);

//获取当天的新用户数量 select count(*) from user where create_time between 当天日期开始时间 and 当天日期结束时间

LocalDateTime startOfDay = LocalDateTime.of(begin, LocalTime.MIN);

Integer newCount = userMapper.countByDate(startOfDay, endOfDay);

newCountList.add(newCount==null?0:newCount);

//到下一天

begin = begin.plusDays(1);

}

//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03

String dateListStr = dateList.stream()

.map(date -> date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))

.collect(Collectors.joining(","));

vo.setDateList(dateListStr);

//用户总量,以逗号分隔,例如:200,210,220

String totalListStr = totalCountList.stream()

.map(Objects::toString)

.collect(Collectors.joining(","));

vo.setTotalUserList(totalListStr);

//新增用户,以逗号分隔,例如:20,21,10

String newListStr = newCountList.stream()

.map(Objects::toString)

.collect(Collectors.joining(","));

vo.setNewUserList(newListStr);

return Result.success(vo);

}

-------------

//UserMapper

/**

* 统计指定日期范围内的用户数量

*/

Integer countByDate(LocalDateTime startOfDay, LocalDateTime endOfDay);

-------------

//UserMapper.xml

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 3. 功能测试

可以通过如下方式进行测试:

接口文档测试 前后端联调测试

进入数据统计模块

1). 查看近7日用户统计

进入开发者模式,查看返回数据

2). 查看近30日用户统计

进入开发者模式,查看返回数据

也可通过断点方式启动,查看每步执行情况。

四、订单统计

1. 需求分析和设计

1 产品原型

订单统计通过一个折现图来展现,折线图上有两根线,这根蓝色的线代表的是订单总数,而下边这根绿色的线代表的是有效订单数,指的就是状态是已完成的订单就属于有效订单,分别反映的是每一天的数据。上面还有3个数字,分别是订单总数、有效订单、订单完成率,它指的是整个时间区间之内总的数据。

原型图:

2 业务规则

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

3 接口设计

根据上述原型图设计接口。

2. 代码开发

//在sky-pojo模块,OrderReportVO.java已定义

package com.sky.vo;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class OrderReportVO implements Serializable {

//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03

private String dateList;

//每日订单数,以逗号分隔,例如:260,210,215

private String orderCountList;

//每日有效订单数,以逗号分隔,例如:20,21,10

private String validOrderCountList;

//订单总数

private Integer totalOrderCount;

//有效订单数

private Integer validOrderCount;

//订单完成率

private Double orderCompletionRate;

}

--------------

//ReportController

@GetMapping("/ordersStatistics")

@ApiOperation("订单统计接口")

public Result orderStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,

@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){

return reportService.orderStatistics(begin, end);

}

--------------

//ReportService

/**

* 统计订单

* @param begin

* @param end

* @return

*/

Result orderStatistics(LocalDate begin, LocalDate end);

--------------

//ReportServiceImpl

@Override

public Result orderStatistics(LocalDate begin, LocalDate end) {

OrderReportVO vo = new OrderReportVO();

List dateList = new ArrayList<>();

List countList = new ArrayList<>();

List completeCountList = new ArrayList<>();

while (!(begin.isAfter(end))) {

//把日期添加到dateList里

dateList.add(begin);

//统计当天的订单数量

LocalDateTime startOfDay = LocalDateTime.of(begin, LocalTime.MIN);

LocalDateTime endOfDay = LocalDateTime.of(begin, LocalTime.MAX);

Integer count = orderMapper.countStatistics(startOfDay, endOfDay, null);

countList.add(count==null?0:count);

//统计当天的有效订单数量

Integer completeCount = orderMapper.countStatistics(startOfDay, endOfDay, Orders.COMPLETED);

completeCountList.add(completeCount == null ? 0 : completeCount);

//到下一天

begin = begin.plusDays(1);

}

//日期,以逗号分隔,例如:2022-10-01,2022-10-02,2022-10-03

String dateListStr = dateList.stream()

.map(date -> date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))

.collect(Collectors.joining(","));

vo.setDateList(dateListStr);

//每日订单数,以逗号分隔,例如:260,210,215 select count(*) from orders where order_time >= ? and order_time <= ?

String countListStr = countList.stream()

.map(Objects::toString)

.collect(Collectors.joining(","));

vo.setOrderCountList(countListStr);

//每日有效订单数,以逗号分隔,例如:20,21,10 select count(*) from orders where order_time >= ? and order_time <= ? and status = 5

String completeListStr = completeCountList.stream()

.map(Objects::toString)

.collect(Collectors.joining(","));

vo.setValidOrderCountList(completeListStr);

//订单总数 select count(*) from orders

Integer totalCount = countList.stream().reduce(Integer::sum).orElse(0);

vo.setTotalOrderCount(totalCount);

//有效订单数 select count(*) from orders where status = 5

Integer completeCount = completeCountList.stream().reduce(Integer::sum).orElse(0);

vo.setValidOrderCount(completeCount);

//订单完成率 有效订单数/订单总数

if (totalCount == 0) {

vo.setOrderCompletionRate(0D);

}else{

vo.setOrderCompletionRate(1.0 * completeCount/totalCount);

}

return Result.success(vo);

}

-----------

//OrderMapper

/**

* 根据日期范围和状态,统计订单数量

*/

Integer countStatistics(LocalDateTime startOfDay, LocalDateTime endOfDay, Integer status);

------------

//OrderMapper.xml

3. 功能测试

可以通过如下方式进行测试:

接口文档测试 前后端联调

重启服务,直接采用前后端联调测试。

进入数据统计模块

1). 查看近7日订单统计

2). 查看近30日订单统计

进入开发者模式,查看返回数据

也可通过断点方式启动,查看每步执行情况

五、销量排名Top10

1. 需求分析和设计

1 产品原型

所谓销量排名,销量指的是商品销售的数量。项目当中的商品主要包含两类:一个是套餐,一个是菜品,所以销量排名其实指的就是菜品和套餐销售的数量排名。通过柱形图来展示销量排名,这些销量是按照降序来排列,并且只需要统计销量排名前十的商品。

原型图:

2 业务规则

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

3 接口设计

2. 代码开发

//在sky-pojo模块,SalesTop10ReportVO.java已定义

package com.sky.vo;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class SalesTop10ReportVO implements Serializable {

//商品名称列表,以逗号分隔,例如:鱼香肉丝,宫保鸡丁,水煮鱼

private String nameList;

//销量列表,以逗号分隔,例如:260,215,200

private String numberList;

}

-------------

//ReportController

@GetMapping("/top10")

@ApiOperation("查询销量排名top10接口")

public Result top10Dishes(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,

@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){

return reportService.top10Dishes(begin, end);

}

-------------

//ReportService

/**

* 查询销量排名top10接口

* @param begin

* @param end

* @return

*/

Result top10Dishes(LocalDate begin, LocalDate end);

------------

//ReportServiceImpl

@Override

public Result top10Dishes(LocalDate begin, LocalDate end) {

SalesTop10ReportVO vo = new SalesTop10ReportVO();

LocalDateTime start = LocalDateTime.of(begin, LocalTime.MIN);

LocalDateTime stop = LocalDateTime.of(end, LocalTime.MAX);

List salesTop10 = orderMapper.salesTop10(start, stop);

//商品名称列表,以逗号分隔,例如:鱼香肉丝,宫保鸡丁,水煮鱼

String names = salesTop10.stream()

.map(GoodsSalesDTO::getName)

.collect(Collectors.joining(","));

vo.setNameList(names);

//销量列表,以逗号分隔,例如:260,215,200

String numbers = salesTop10.stream()

.map(GoodsSalesDTO::getNumber)

.map(Objects::toString)

.collect(Collectors.joining(","));

vo.setNumberList(numbers);

return Result.success(vo);

}

-------------

//OrderMapper

/**

* 查询商品销量前10名

* @param begin

* @param end

*/

List salesTop10(LocalDateTime start, LocalDateTime stop);

------------

//OrderMapper.xml

3. 功能测试

可以通过如下方式进行测试:

接口文档测试 前后端联调

重启服务,直接采用前后端联调测试。

查看近30日销量排名Top10统计

若查询的某一段时间没有销量数据,则显示不出效果。

进入开发者模式,查看返回数据

也可通过断点方式启动,查看每步执行情况。  

       

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。