目录
- Apache ECharts
- 介绍
- 入门案例
- 实现步骤
- 代码
- 总结
- 需求1
- Service层思路
- 代码实现
- Controller层
- ReportController
- Service层
- ReportService
- ReportServiceImpl
- Mapper层
- OrderMapper
- OrderMapper.xml
- 需求2
- Service层思路
- 代码实现
- Controller层
- ReportController
- Service层
- ReportService
- ReportServiceImpl
- Mapper层
- UserMapper
- UserMapper.xml
- 需求3
- Service层思路
- 代码实现
- Controller层
- ReportController
- Service层
- ReportService
- ReportServiceImpl
- countOrder
- Mapper层
- OrderMapper
- OrderMapper.xml
Apache ECharts
介绍
基于javascript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。
官网地址:https://echarts.apache.org/zh/index.html
入门案例
Apache Echarts官方提供的快速入门:https://echarts.apache.org/handbook/zh/get-started/
实现步骤
1.引入echarts.js
2.提供一个设置了宽高的DOM
3.初始化echarts实例
4.指定图表的配置项,数据
5.指定图表引用的配置项和数据
代码
echartsDemo.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: 'ECharts 入门示例'},tooltip: {},legend: {data: ['销量']},xAxis: {data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);</script></body>
</html>
总结
使用echarts图表重点在于分析图表需要的数据,一般后端需要以前端要求的格式响应需要的数据给前端以实现图表化
需求1
营业额统计
约定:以字符串的形式返回日期和营业额,数据之间以逗号隔开
Service层思路
根据前端传递的开始日期和结束日期封装日期集合
遍历日期集合,使用map集合封装查询条件,查询每天的营业额,将值为null的营业额设置为0,并添加到集合中去
使用StringUtils的join()方法将日期集合,营业额集合转换成以逗号隔开的字符串,并封装为返回值类型返回
代码实现
Controller层
ReportController
@Api("数据统计相关接口")
@RequestMapping("/admin/report")
@Slf4j
@RestController
public class ReportController {@Autowiredprivate ReportService reportService;/*** 获取店铺营业额** @param begin* @param end* @return*/@ApiOperation("获取店铺营业额")@GetMapping("/turnoverStatistics")public Result<TurnoverReportVO> getTurnover(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {log.info("获取店铺营业额,参数为:{},{}", begin, end);return Result.success(reportService.getTurnover(begin, end));}
}
Service层
ReportService
public interface ReportService {/*** 统计店铺某时间段内营业额** @param begin* @param end* @return*/TurnoverReportVO getTurnover(LocalDate begin, LocalDate end);
}
ReportServiceImpl
@Service
public class ReportServiceImpl implements ReportService {@Autowiredprivate OrderMapper orderMapper;/*** 统计店铺某时间段内营业额** @param begin* @param end* @return*/@Overridepublic TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {//封装日期集合List<LocalDate> dateList = new ArrayList<>();dateList.add(begin);while (!begin.equals(end)) {begin = begin.plusDays(1);dateList.add(begin);}//查询营业额List<Double> turnoverList = new ArrayList<>();for (LocalDate localDate : dateList) {LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);Map map = new HashMap();map.put("status", Orders.COMPLETED);map.put("begin", beginTime);map.put("end", endTime);Double dayTurnover = orderMapper.sumByMap(map);dayTurnover = dayTurnover == null ? 0.0 : dayTurnover;turnoverList.add(dayTurnover);}return TurnoverReportVO.builder().dateList(StringUtils.join(dateList, ",")).turnoverList(StringUtils.join(turnoverList, ",")).build();}
}
Mapper层
OrderMapper
@Mapper
public interface OrderMapper {/*** 动态条件查询店铺营业额** @param map* @return*/Double sumByMap(Map map);}
OrderMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.OrderMapper"><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>
</mapper>
需求2
用户统计
统计用户总量和新增用户量
Service层思路
根据前端传递的开始日期和结束日期封装日期集合
遍历日期集合,使用map集合封装结束日期,查询每天的用户总量,再封装开始日期,查询每天的新增用户量,将两者封装到集合中去
使用StringUtils的join()方法将日期集合,用户总量集合,新增用户量集合转换成以逗号隔开的字符串,并封装为返回值类型返回
代码实现
Controller层
ReportController
/*** 用户统计** @param begin* @param end* @return*/@ApiOperation("用户统计")@GetMapping("/userStatistics")public Result<UserReportVO> getUserStatistic(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {log.info("用户统计,参数为:{},{}", begin, end);return Result.success(reportService.getUserStatistic(begin, end));}
Service层
ReportService
/*** 指定时间段内用户统计** @param begin* @param end* @return*/UserReportVO getUserStatistic(LocalDate begin, LocalDate end);
ReportServiceImpl
/*** 统计用户数量** @param begin* @param end* @return*/@Overridepublic UserReportVO getUserStatistic(LocalDate begin, LocalDate end) {//存放从begin到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 localDate : dateList) {LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);Map map = new HashMap();map.put("end", endTime);Integer totalUser = userMapper.countByMap(map);map.put("begin", 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();}
Mapper层
UserMapper
/*** 动态统计用户数** @param map* @return*/Integer countByMap(Map map);
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>
需求3
订单统计
统计指定时间区间内的订单总数,有效订单总数,订单完成率(有效订单数/订单总数),每日订单总数,每日有效订单数
Service层思路
时间区间内总订单数的计算(stream流的使用,reduce,方法引用)
根据前端传递的开始日期和结束日期封装日期集合
遍历日期集合,使用map集合封装查询条件,查询每天的订单总量和有效订单总量,将两者封装到集合中去
使用stream流的reduce()方法合并集合,并调用Integer的sum()方法求和,计算订单总量和有效订单总量,计算订单完成率
使用StringUtils的join()方法将每日订单总量集合,每日有效订单集合,日期集合转换成以逗号隔开的字符串,并封装数据返回
代码实现
Controller层
ReportController
/*** 订单数据统计** @param begin* @param end* @return*/@ApiOperation("统计订单数据")@GetMapping("/ordersStatistics")public Result<OrderReportVO> getOrderStatistic(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {log.info("统计订单数量,参数为:{},{}", begin, end);return Result.success(reportService.getOrderStatistic(begin, end));}
Service层
ReportService
/*** 指定时间段内订单统计** @param begin* @param end* @return*/OrderReportVO getOrderStatistic(LocalDate begin, LocalDate end);
ReportServiceImpl
/*** 订单统计** @param begin* @param end* @return*/@Overridepublic OrderReportVO getOrderStatistic(LocalDate begin, LocalDate end) {//存放从begin到end的日期List<LocalDate> dateList = new ArrayList<>();dateList.add(begin);while (!begin.equals(end)) {begin = begin.plusDays(1);dateList.add(begin);}//存放每日订单数// select count(id) from orders where order_time > ? and order_time < ?List<Integer> orderCountList = new ArrayList<>();//存放每日有效订单数// select count(id) from orders where order_time > ? and order_time < ? and status = ?List<Integer> validOrderCountList = new ArrayList<>();//查询每日订单数据for (LocalDate localDate : dateList) {LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);Integer validDayOrderCount = countOrder(beginTime, endTime, Orders.COMPLETED);Integer dayOrderCount = countOrder(beginTime, endTime, null);orderCountList.add(dayOrderCount);validOrderCountList.add(validDayOrderCount);}//计算指定时间区间内的订单总数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, ",")).orderCompletionRate(orderCompletionRate).totalOrderCount(totalOrderCount).validOrderCount(validOrderCount).orderCountList(StringUtils.join(orderCountList, ",")).validOrderCountList(StringUtils.join(validOrderCountList, ",")).build();}
countOrder
/*** 根据条件统计订单数据** @param beginTime* @param endTime* @param status* @return*/private Integer countOrder(LocalDateTime beginTime, LocalDateTime endTime, Integer status) {Map map = new HashMap();map.put("begin", beginTime);map.put("end", endTime);map.put("status", status);Integer orderCount = orderMapper.countOrderByMap(map);return orderCount;}
Mapper层
OrderMapper
/*** 动态统计订单数** @param map* @return*/Integer countOrderByMap(Map map);
OrderMapper.xml
<select id="countOrderByMap" 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>