蒼穹外賣(mài)-day11
課程內(nèi)容
-
Apache ECharts
-
營(yíng)業(yè)額統(tǒng)計(jì)
-
用戶(hù)統(tǒng)計(jì)
-
訂單統(tǒng)計(jì)
-
銷(xiāo)量排名Top10
功能實(shí)現(xiàn):數(shù)據(jù)統(tǒng)計(jì)
數(shù)據(jù)統(tǒng)計(jì)效果圖:
1. Apache ECharts
1.1 介紹
Apache ECharts 是一款基于 Javascript 的數(shù)據(jù)可視化圖表庫(kù),提供直觀,生動(dòng),可交互,可個(gè)性化定制的數(shù)據(jù)可視化圖表。 官網(wǎng)地址:Apache ECharts
常見(jiàn)效果展示:
1). 柱形圖
2). 餅形圖
3). 折線(xiàn)圖
總結(jié):不管是哪種形式的圖形,最本質(zhì)的東西實(shí)際上是數(shù)據(jù),它其實(shí)是對(duì)數(shù)據(jù)的一種可視化展示。
1.2 入門(mén)案例
Apache Echarts官方提供的快速入門(mén):快速上手 - 使用手冊(cè) - Apache ECharts
效果展示:
實(shí)現(xiàn)步驟:
1). 引入echarts.js 文件(當(dāng)天資料已提供)
2). 為 ECharts 準(zhǔn)備一個(gè)設(shè)置寬高的 DOM
3). 初始化echarts實(shí)例
4). 指定圖表的配置項(xiàng)和數(shù)據(jù)
5). 使用指定的配置項(xiàng)和數(shù)據(jù)顯示圖表
代碼開(kāi)發(fā):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ECharts</title>
<!-- 引入剛剛下載的 ECharts 文件 -->
<script src="echarts.js"></script>
</head>
<body>
<!-- 為 ECharts 準(zhǔn)備一個(gè)定義了寬高的 DOM -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于準(zhǔn)備好的dom,初始化echarts實(shí)例
var myChart = echarts.init(document.getElementById('main'));
// 指定圖表的配置項(xiàng)和數(shù)據(jù)
var option = {
title: {
text: 'ECharts 入門(mén)示例'
},
tooltip: {},
legend: {
data: ['銷(xiāo)量']
},
xAxis: {
data: ['襯衫', '羊毛衫', '雪紡衫', '褲子', '高跟鞋', '襪子']
},
yAxis: {},
series: [
{
name: '銷(xiāo)量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
};
// 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
測(cè)試:(當(dāng)天資料中已提供)
使用瀏覽器方式打開(kāi)即可。
總結(jié):使用Echarts,重點(diǎn)在于研究當(dāng)前圖表所需的數(shù)據(jù)格式。通常是需要后端提供符合格式要求的動(dòng)態(tài)數(shù)據(jù),然后響應(yīng)給前端來(lái)展示圖表。
2. 營(yíng)業(yè)額統(tǒng)計(jì)
2.1 需求分析和設(shè)計(jì)
2.1.1 產(chǎn)品原型
營(yíng)業(yè)額統(tǒng)計(jì)是基于折現(xiàn)圖來(lái)展現(xiàn),并且按照天來(lái)展示的。實(shí)際上,就是某一個(gè)時(shí)間范圍之內(nèi)的每一天的營(yíng)業(yè)額。同時(shí),不管光標(biāo)放在哪個(gè)點(diǎn)上,那么它就會(huì)把具體的數(shù)值展示出來(lái)。并且還需要注意日期并不是固定寫(xiě)死的,是由上邊時(shí)間選擇器來(lái)決定。比如選擇是近7天、或者是近30日,或者是本周,就會(huì)把相應(yīng)這個(gè)時(shí)間段之內(nèi)的每一天日期通過(guò)橫坐標(biāo)展示。
原型圖:
業(yè)務(wù)規(guī)則:
-
營(yíng)業(yè)額指訂單狀態(tài)為已完成的訂單金額合計(jì)
-
基于可視化報(bào)表的折線(xiàn)圖展示營(yíng)業(yè)額數(shù)據(jù),X軸為日期,Y軸為營(yíng)業(yè)額
-
根據(jù)時(shí)間選擇區(qū)間,展示每天的營(yíng)業(yè)額數(shù)據(jù)
2.1.2 接口設(shè)計(jì)
通過(guò)上述原型圖,設(shè)計(jì)出對(duì)應(yīng)的接口。
注意:具體返回?cái)?shù)據(jù)一般由前端來(lái)決定,前端展示圖表,具體折現(xiàn)圖對(duì)應(yīng)數(shù)據(jù)是什么格式,是有固定的要求的。 所以說(shuō),后端需要去適應(yīng)前端,它需要什么格式的數(shù)據(jù),我們就給它返回什么格式的數(shù)據(jù)。
2.2 代碼開(kāi)發(fā)
2.2.1 VO設(shè)計(jì)
根據(jù)接口定義設(shè)計(jì)對(duì)應(yīng)的VO:
在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 {
//日期,以逗號(hào)分隔,例如:2022-10-01,2022-10-02,2022-10-03
private String dateList;
//營(yíng)業(yè)額,以逗號(hào)分隔,例如:406.0,1520.0,75.0
private String turnoverList;
}
2.2.2 Controller層
根據(jù)接口定義創(chuàng)建ReportController:
package com.sky.controller.admin;
import com.sky.result.Result;
import com.sky.service.ReportService;
import com.sky.vo.TurnoverReportVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
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;
/**
* 報(bào)表
*/
@RestController
@RequestMapping("/admin/report")
@Slf4j
@Api(tags = "統(tǒng)計(jì)報(bào)表相關(guān)接口")
public class ReportController {
@Autowired
private ReportService reportService;
/**
* 營(yíng)業(yè)額數(shù)據(jù)統(tǒng)計(jì)
*
* @param begin
* @param end
* @return
*/
@GetMapping("/turnoverStatistics")
@ApiOperation("營(yíng)業(yè)額數(shù)據(jù)統(tǒng)計(jì)")
public Result<TurnoverReportVO> turnoverStatistics(
@DateTimeFormat(pattern = "yyyy-MM-dd")
LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd")
LocalDate end) {
return Result.success(reportService.getTurnover(begin, end));
}
}
2.2.3 Service層接口
創(chuàng)建ReportService接口,聲明getTurnover方法:
package com.sky.service;
import com.sky.vo.TurnoverReportVO;
import java.time.LocalDate;
public interface ReportService {
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)營(yíng)業(yè)額
* @param beginTime
* @param endTime
* @return
*/
TurnoverReportVO getTurnover(LocalDate beginTime, LocalDate endTime);
}
2.2.4 Service層實(shí)現(xiàn)類(lèi)
創(chuàng)建ReportServiceImpl實(shí)現(xiàn)類(lèi),實(shí)現(xiàn)getTurnover方法:
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class ReportServiceImpl implements ReportService {
@Autowired
private OrderMapper orderMapper;
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)營(yíng)業(yè)額
* @param begin
* @param end
* @return
*/
public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
List<LocalDate> dateList = new ArrayList<>();
dateList.add(begin);
while (!begin.equals(end)){
begin = begin.plusDays(1);//日期計(jì)算,獲得指定日期后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);
}
//數(shù)據(jù)封裝
return TurnoverReportVO.builder()
.dateList(StringUtils.join(dateList,","))
.turnoverList(StringUtils.join(turnoverList,","))
.build();
}
}
2.2.5 Mapper層
在OrderMapper接口聲明sumByMap方法:
/**
* 根據(jù)動(dòng)態(tài)條件統(tǒng)計(jì)營(yíng)業(yè)額
* @param map
*/
Double sumByMap(Map map);
在OrderMapper.xml文件中編寫(xiě)動(dòng)態(tài)SQL:
<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>
2.3 功能測(cè)試
可以通過(guò)如下方式進(jìn)行測(cè)試:
-
接口文檔測(cè)試
-
前后端聯(lián)調(diào)測(cè)試
啟動(dòng)服務(wù)器,啟動(dòng)nginx,直接采用前后端聯(lián)調(diào)測(cè)試。
進(jìn)入數(shù)據(jù)統(tǒng)計(jì)模塊
1). 查看近7日營(yíng)業(yè)額統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
2). 查看近30日營(yíng)業(yè)額統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
也可通過(guò)斷點(diǎn)方式啟動(dòng),查看每步執(zhí)行情況。
2.4 代碼提交
后續(xù)步驟和其它功能代碼提交一致,不再贅述。
3. 用戶(hù)統(tǒng)計(jì)
3.1 需求分析和設(shè)計(jì)
3.1.1 產(chǎn)品原型
所謂用戶(hù)統(tǒng)計(jì),實(shí)際上統(tǒng)計(jì)的是用戶(hù)的數(shù)量。通過(guò)折線(xiàn)圖來(lái)展示,上面這根藍(lán)色線(xiàn)代表的是用戶(hù)總量,下邊這根綠色線(xiàn)代表的是新增用戶(hù)數(shù)量,是具體到每一天。所以說(shuō)用戶(hù)統(tǒng)計(jì)主要統(tǒng)計(jì)兩個(gè)數(shù)據(jù),一個(gè)是總的用戶(hù)數(shù)量,另外一個(gè)是新增用戶(hù)數(shù)量。
原型圖:
業(yè)務(wù)規(guī)則:
-
基于可視化報(bào)表的折線(xiàn)圖展示用戶(hù)數(shù)據(jù),X軸為日期,Y軸為用戶(hù)數(shù)
-
根據(jù)時(shí)間選擇區(qū)間,展示每天的用戶(hù)總量和新增用戶(hù)量數(shù)據(jù)
3.1.2 接口設(shè)計(jì)
根據(jù)上述原型圖設(shè)計(jì)接口。
3.2 代碼開(kāi)發(fā)
3.2.1 VO設(shè)計(jì)
根據(jù)用戶(hù)統(tǒng)計(jì)接口的返回結(jié)果設(shè)計(jì)VO:
在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 {
//日期,以逗號(hào)分隔,例如:2022-10-01,2022-10-02,2022-10-03
private String dateList;
//用戶(hù)總量,以逗號(hào)分隔,例如:200,210,220
private String totalUserList;
//新增用戶(hù),以逗號(hào)分隔,例如:20,21,10
private String newUserList;
}
3.2.2 Controller層
根據(jù)接口定義,在ReportController中創(chuàng)建userStatistics方法:
/**
* 用戶(hù)數(shù)據(jù)統(tǒng)計(jì)
* @param begin
* @param end
* @return
*/
@GetMapping("/userStatistics")
@ApiOperation("用戶(hù)數(shù)據(jù)統(tǒng)計(jì)")
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));
}
3.2.3 Service層接口
在ReportService接口中聲明getUserStatistics方法:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)用戶(hù)數(shù)量
* @param begin
* @param end
* @return
*/
UserReportVO getUserStatistics(LocalDate begin, LocalDate end);
3.2.4 Service層實(shí)現(xiàn)類(lèi)
在ReportServiceImpl實(shí)現(xiàn)類(lèi)中實(shí)現(xiàn)getUserStatistics方法:
@Override
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<>(); //新增用戶(hù)數(shù)
List<Integer> totalUserList = new ArrayList<>(); //總用戶(hù)數(shù)
for (LocalDate date : dateList) {
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
//新增用戶(hù)數(shù)量 select count(id) from user where create_time > ? and create_time < ?
Integer newUser = getUserCount(beginTime, endTime);
//總用戶(hù)數(shù)量 select count(id) from user where create_time < ?
Integer totalUser = getUserCount(null, endTime);
newUserList.add(newUser);
totalUserList.add(totalUser);
}
return UserReportVO.builder()
.dateList(StringUtils.join(dateList,","))
.newUserList(StringUtils.join(newUserList,","))
.totalUserList(StringUtils.join(totalUserList,","))
.build();
}
在ReportServiceImpl實(shí)現(xiàn)類(lèi)中創(chuàng)建私有方法getUserCount:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)用戶(hù)數(shù)量
* @param beginTime
* @param endTime
* @return
*/
private Integer getUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
Map map = new HashMap();
map.put("begin",beginTime);
map.put("end", endTime);
return userMapper.countByMap(map);
}
3.2.5 Mapper層
在UserMapper接口中聲明countByMap方法:
/**
* 根據(jù)動(dòng)態(tài)條件統(tǒng)計(jì)用戶(hù)數(shù)量
* @param map
* @return
*/
Integer countByMap(Map map);
在UserMapper.xml文件中編寫(xiě)動(dòng)態(tài)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>
3.3 功能測(cè)試
可以通過(guò)如下方式進(jìn)行測(cè)試:
-
接口文檔測(cè)試
-
前后端聯(lián)調(diào)測(cè)試
進(jìn)入數(shù)據(jù)統(tǒng)計(jì)模塊
1). 查看近7日用戶(hù)統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
2). 查看近30日用戶(hù)統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
也可通過(guò)斷點(diǎn)方式啟動(dòng),查看每步執(zhí)行情況。
3.4 代碼提交
后續(xù)步驟和其它功能代碼提交一致,不再贅述。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-807487.html
4. 訂單統(tǒng)計(jì)
4.1 需求分析和設(shè)計(jì)
4.1.1 產(chǎn)品原型
訂單統(tǒng)計(jì)通過(guò)一個(gè)折現(xiàn)圖來(lái)展現(xiàn),折線(xiàn)圖上有兩根線(xiàn),這根藍(lán)色的線(xiàn)代表的是訂單總數(shù),而下邊這根綠色的線(xiàn)代表的是有效訂單數(shù),指的就是狀態(tài)是已完成的訂單就屬于有效訂單,分別反映的是每一天的數(shù)據(jù)。上面還有3個(gè)數(shù)字,分別是訂單總數(shù)、有效訂單、訂單完成率,它指的是整個(gè)時(shí)間區(qū)間之內(nèi)總的數(shù)據(jù)。
原型圖:
業(yè)務(wù)規(guī)則:
-
有效訂單指狀態(tài)為 “已完成” 的訂單
-
基于可視化報(bào)表的折線(xiàn)圖展示訂單數(shù)據(jù),X軸為日期,Y軸為訂單數(shù)量
-
根據(jù)時(shí)間選擇區(qū)間,展示每天的訂單總數(shù)和有效訂單數(shù)
-
展示所選時(shí)間區(qū)間內(nèi)的有效訂單數(shù)、總訂單數(shù)、訂單完成率,訂單完成率 = 有效訂單數(shù) / 總訂單數(shù) * 100%
4.1.2 接口設(shè)計(jì)
根據(jù)上述原型圖設(shè)計(jì)接口。
4.2 代碼開(kāi)發(fā)
4.2.1 VO設(shè)計(jì)
根據(jù)訂單統(tǒng)計(jì)接口的返回結(jié)果設(shè)計(jì)VO:
在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 {
//日期,以逗號(hào)分隔,例如:2022-10-01,2022-10-02,2022-10-03
private String dateList;
//每日訂單數(shù),以逗號(hào)分隔,例如:260,210,215
private String orderCountList;
//每日有效訂單數(shù),以逗號(hào)分隔,例如:20,21,10
private String validOrderCountList;
//訂單總數(shù)
private Integer totalOrderCount;
//有效訂單數(shù)
private Integer validOrderCount;
//訂單完成率
private Double orderCompletionRate;
}
4.2.2 Controller層
在ReportController中根據(jù)訂單統(tǒng)計(jì)接口創(chuàng)建orderStatistics方法:
/**
* 訂單數(shù)據(jù)統(tǒng)計(jì)
* @param begin
* @param end
* @return
*/
@GetMapping("/ordersStatistics")
@ApiOperation("用戶(hù)數(shù)據(jù)統(tǒng)計(jì)")
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));
}
4.2.3 Service層接口
在ReportService接口中聲明getOrderStatistics方法:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)訂單數(shù)量
* @param begin
* @param end
* @return
*/
OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end);
4.2.4 Service層實(shí)現(xiàn)類(lèi)
在ReportServiceImpl實(shí)現(xiàn)類(lèi)中實(shí)現(xiàn)getOrderStatistics方法:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)訂單數(shù)量
* @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);
}
//每天訂單總數(shù)集合
List<Integer> orderCountList = new ArrayList<>();
//每天有效訂單數(shù)集合
List<Integer> validOrderCountList = new ArrayList<>();
for (LocalDate date : dateList) {
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
//查詢(xún)每天的總訂單數(shù) select count(id) from orders where order_time > ? and order_time < ?
Integer orderCount = getOrderCount(beginTime, endTime, null);
//查詢(xún)每天的有效訂單數(shù) select count(id) from orders where order_time > ? and order_time < ? and status = ?
Integer validOrderCount = getOrderCount(beginTime, endTime, Orders.COMPLETED);
orderCountList.add(orderCount);
validOrderCountList.add(validOrderCount);
}
//時(shí)間區(qū)間內(nèi)的總訂單數(shù)
Integer totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();
//時(shí)間區(qū)間內(nèi)的總有效訂單數(shù)
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();
}
在ReportServiceImpl實(shí)現(xiàn)類(lèi)中提供私有方法getOrderCount:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)指定狀態(tài)的訂單數(shù)量
* @param beginTime
* @param endTime
* @param status
* @return
*/
private Integer getOrderCount(LocalDateTime beginTime, LocalDateTime endTime, Integer status) {
Map map = new HashMap();
map.put("status", status);
map.put("begin",beginTime);
map.put("end", endTime);
return orderMapper.countByMap(map);
}
4.2.5 Mapper層
在OrderMapper接口中聲明countByMap方法:
/**
*根據(jù)動(dòng)態(tài)條件統(tǒng)計(jì)訂單數(shù)量
* @param map
*/
Integer countByMap(Map map);
在OrderMapper.xml文件中編寫(xiě)動(dòng)態(tài)SQL:
<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>
4.3 功能測(cè)試
可以通過(guò)如下方式進(jìn)行測(cè)試:
-
接口文檔測(cè)試
-
前后端聯(lián)調(diào)
重啟服務(wù),直接采用前后端聯(lián)調(diào)測(cè)試。
進(jìn)入數(shù)據(jù)統(tǒng)計(jì)模塊
1). 查看近7日訂單統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
2). 查看近30日訂單統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
也可通過(guò)斷點(diǎn)方式啟動(dòng),查看每步執(zhí)行情況。
4.4 代碼提交
后續(xù)步驟和其它功能代碼提交一致,不再贅述。
5. 銷(xiāo)量排名Top10
5.1 需求分析和設(shè)計(jì)
5.1.1 產(chǎn)品原型
所謂銷(xiāo)量排名,銷(xiāo)量指的是商品銷(xiāo)售的數(shù)量。項(xiàng)目當(dāng)中的商品主要包含兩類(lèi):一個(gè)是套餐,一個(gè)是菜品,所以銷(xiāo)量排名其實(shí)指的就是菜品和套餐銷(xiāo)售的數(shù)量排名。通過(guò)柱形圖來(lái)展示銷(xiāo)量排名,這些銷(xiāo)量是按照降序來(lái)排列,并且只需要統(tǒng)計(jì)銷(xiāo)量排名前十的商品。
原型圖:
業(yè)務(wù)規(guī)則:
-
根據(jù)時(shí)間選擇區(qū)間,展示銷(xiāo)量前10的商品(包括菜品和套餐)
-
基于可視化報(bào)表的柱狀圖降序展示商品銷(xiāo)量
-
此處的銷(xiāo)量為商品銷(xiāo)售的份數(shù)
5.1.2 接口設(shè)計(jì)
根據(jù)上述原型圖設(shè)計(jì)接口。
5.2 代碼開(kāi)發(fā)
5.2.1 VO設(shè)計(jì)
根據(jù)銷(xiāo)量排名接口的返回結(jié)果設(shè)計(jì)VO:
在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 {
//商品名稱(chēng)列表,以逗號(hào)分隔,例如:魚(yú)香肉絲,宮保雞丁,水煮魚(yú)
private String nameList;
//銷(xiāo)量列表,以逗號(hào)分隔,例如:260,215,200
private String numberList;
}
5.2.2 Controller層
在ReportController中根據(jù)銷(xiāo)量排名接口創(chuàng)建top10方法:
/**
* 銷(xiāo)量排名統(tǒng)計(jì)
* @param begin
* @param end
* @return
*/
@GetMapping("/top10")
@ApiOperation("銷(xiāo)量排名統(tǒng)計(jì)")
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));
}
5.2.3 Service層接口
在ReportService接口中聲明getSalesTop10方法:
/**
* 查詢(xún)指定時(shí)間區(qū)間內(nèi)的銷(xiāo)量排名top10
* @param begin
* @param end
* @return
*/
SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end);
5.2.4 Service層實(shí)現(xiàn)類(lèi)
在ReportServiceImpl實(shí)現(xiàn)類(lèi)中實(shí)現(xiàn)getSalesTop10方法:
/**
* 查詢(xún)指定時(shí)間區(qū)間內(nèi)的銷(xiāo)量排名top10
* @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();
}
5.2.5 Mapper層
在OrderMapper接口中聲明getSalesTop10方法:
/**
* 查詢(xún)商品銷(xiāo)量排名
* @param begin
* @param end
*/
List<GoodsSalesDTO> getSalesTop10(LocalDateTime begin, LocalDateTime end);
在OrderMapper.xml文件中編寫(xiě)動(dòng)態(tài)SQL:
<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="begin != null">
and order_time >= #{begin}
</if>
<if test="end != null">
and order_time <= #{end}
</if>
group by name
order by number desc
limit 0, 10
</select>
5.3 功能測(cè)試
可以通過(guò)如下方式進(jìn)行測(cè)試:
-
接口文檔測(cè)試
-
前后端聯(lián)調(diào)
重啟服務(wù),直接采用前后端聯(lián)調(diào)測(cè)試。
查看近30日銷(xiāo)量排名Top10統(tǒng)計(jì)
若查詢(xún)的某一段時(shí)間沒(méi)有銷(xiāo)量數(shù)據(jù),則顯示不出效果。
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
也可通過(guò)斷點(diǎn)方式啟動(dòng),查看每步執(zhí)行情況。
5.4 代碼提交
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-807487.html
后續(xù)步驟和其它功能代碼提交一致,不再贅述。
到了這里,關(guān)于項(xiàng)目實(shí)戰(zhàn)————蒼穹外賣(mài)(DAY11)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!