繼續(xù)上一節(jié)的內(nèi)容,本節(jié)學(xué)習(xí)Apache ECharts,實(shí)現(xiàn)營(yíng)業(yè)額統(tǒng)計(jì)、用戶統(tǒng)計(jì)、訂單統(tǒng)計(jì)和銷量排名Top10功能。
數(shù)據(jù)統(tǒng)計(jì)效果圖:
Apache ECharts
Apache ECharts 是一款基于 Javascript 的數(shù)據(jù)可視化圖表庫(kù),提供直觀,生動(dòng),可交互,可個(gè)性化定制的數(shù)據(jù)可視化圖表。
常見(jiàn)效果:柱形圖、餅形圖、折線圖
入門(mén)案例
Apache Echarts官方提供的快速入門(mén)
實(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ù)顯示圖表
<!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: { // 圖表標(biāo)題
text: 'ECharts 入門(mén)示例'
},
tooltip: {},
legend: { // 圖例
data: ['銷量']
},
xAxis: { // x軸
data: ['襯衫', '羊毛衫', '雪紡衫', '褲子', '高跟鞋', '襪子']
},
yAxis: {},
series: [ // y軸數(shù)據(jù)
{
name: '銷量',
type: 'bar', // 指定柱狀圖類型
data: [5, 20, 36, 10, 10, 20]
}
]
};
// 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
使用Echarts,重點(diǎn)在于研究當(dāng)前圖表所需的數(shù)據(jù)格式。通常是需要后端提供符合格式要求的動(dòng)態(tài)數(shù)據(jù),然后響應(yīng)給前端來(lái)展示圖表。
營(yíng)業(yè)額統(tǒng)計(jì)
營(yíng)業(yè)額統(tǒng)計(jì)基于折現(xiàn)圖來(lái)展現(xiàn),并且按照天來(lái)展示的,不管光標(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)表的折線圖展示營(yíng)業(yè)額數(shù)據(jù),X軸為日期,Y軸為營(yíng)業(yè)額、根據(jù)時(shí)間選擇區(qū)間,展示每天的營(yíng)業(yè)額數(shù)據(jù)
通過(guò)上述原型圖,設(shè)計(jì)出對(duì)應(yīng)的接口。具體返回?cái)?shù)據(jù)一般由前端來(lái)決定,前端展示圖表,具體折現(xiàn)圖對(duì)應(yīng)數(shù)據(jù)是什么格式,是有固定的要求的。所以后端需要去適應(yīng)前端,它需要什么格式的數(shù)據(jù),我們就給它返回什么格式的數(shù)據(jù)。
根據(jù)接口定義設(shè)計(jì)對(duì)應(yīng)的VO,在sky-pojo模塊,TurnoverReportVO.java已定義。
@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;
}
根據(jù)接口定義創(chuàng)建admin.ReportController:
/**
* 報(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));
}
}
創(chuàng)建ReportServiceImpl實(shí)現(xiàn)類,實(shí)現(xiàn)getTurnover方法:
@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) {
//dateList用于存放從begin到end范圍內(nèi)的每天的日期
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) { //計(jì)算每個(gè)日期該天的營(yíng)業(yè)額
//查詢data日期對(duì)應(yīng)的營(yíng)業(yè)額 要求狀態(tài)為"已完成"的訂單金額合計(jì)
//給data日期加上時(shí)分秒 因?yàn)閿?shù)據(jù)庫(kù)里存的是LocalDateTime類型 而data是LocalDate類型
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);//LocalTime.MIN對(duì)應(yīng)一天開(kāi)始的時(shí)刻'00:00'
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);//LocalTime.MAX對(duì)應(yīng)一天結(jié)束的時(shí)刻'23:59:59.999999999'
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,",")) //指定分隔符拼接list里的字符串
.turnoverList(StringUtils.join(turnoverList,","))
.build();
}
}
在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 <![CDATA[>]]>= #{begin}
</if>
<if test="end != null">
and order_time <![CDATA[<]]>= #{end}
</if>
</where>
</select>
這里日期的大于等于和小于等于因?yàn)槭钦嘉环?,原本需要用一些占位符代替?/p>
>=寫(xiě)成>=
<=寫(xiě)成<=
我使用了CDATA區(qū),這種寫(xiě)法也可以,可以參考:java特殊文件 屬性文件properties和XML文件
進(jìn)入數(shù)據(jù)統(tǒng)計(jì)模塊查看近7日營(yíng)業(yè)額統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-797734.html
用戶統(tǒng)計(jì)
通過(guò)折線圖來(lái)展示用戶的數(shù)量,藍(lán)色線代表的是用戶總量,綠色線代表的是新增用戶數(shù)量,具體到每一天。所以說(shuō)用戶統(tǒng)計(jì)主要統(tǒng)計(jì)兩個(gè)數(shù)據(jù),一個(gè)是總的用戶數(shù)量,另外一個(gè)是新增用戶數(shù)量。
業(yè)務(wù)規(guī)則:基于可視化報(bào)表的折線圖展示用戶數(shù)據(jù),X軸為日期,Y軸為用戶數(shù)、根據(jù)時(shí)間選擇區(qū)間,展示每天的用戶總量和新增用戶量數(shù)據(jù)
根據(jù)用戶統(tǒng)計(jì)接口的返回結(jié)果設(shè)計(jì)VO,在sky-pojo模塊,UserReportVO.java已定義
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserReportVO implements Serializable {
//日期,以逗號(hào)分隔,例如:2022-10-01,2022-10-02,2022-10-03
private String dateList;
//用戶總量,以逗號(hào)分隔,例如:200,210,220
private String totalUserList;
//新增用戶,以逗號(hào)分隔,例如:20,21,10
private String newUserList;
}
ReportController中創(chuàng)建userStatistics方法:
/**
* 用戶數(shù)據(jù)統(tǒng)計(jì)
* @param begin
* @param end
* @return
*/
@GetMapping("/userStatistics")
@ApiOperation("用戶數(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));
}
在ReportServiceImpl實(shí)現(xiàn)類中實(shí)現(xiàn)getUserStatistics方法:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)用戶數(shù)量
* @param begin
* @param end
* @return
*/
public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
//dateList用于存放從begin到end范圍內(nèi)的每天的日期
List<LocalDate> dateList = new ArrayList<>();
dateList.add(begin);
while (!begin.equals(end)){
begin = begin.plusDays(1);//日期計(jì)算,獲得指定日期后1天的日期
dateList.add(begin);
}
List<Integer> newUserList = new ArrayList<>(); //新增用戶數(shù)
List<Integer> totalUserList = new ArrayList<>(); //總用戶數(shù)
for (LocalDate date : dateList) {//計(jì)算每個(gè)日期該天的新增用戶數(shù)量和總用戶數(shù)量
//給data日期加上時(shí)分秒 因?yàn)閿?shù)據(jù)庫(kù)里存的是LocalDateTime類型 而data是LocalDate類型
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);//LocalTime.MIN對(duì)應(yīng)一天開(kāi)始的時(shí)刻'00:00'
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);//LocalTime.MAX對(duì)應(yīng)一天結(jié)束的時(shí)刻'23:59:59.999999999'
//新增用戶數(shù)量 select count(id) from user where create_time >= ? and create_time <= ?
Integer newUser = getUserCount(beginTime, endTime);
//總用戶數(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)類中創(chuàng)建私有方法getUserCount:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)用戶數(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);
}
在UserMapper接口中聲明countByMap方法:
/**
* 根據(jù)動(dòng)態(tài)條件統(tǒng)計(jì)用戶數(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>
進(jìn)入數(shù)據(jù)統(tǒng)計(jì)模塊,查看近7日用戶統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
訂單統(tǒng)計(jì)
通過(guò)一個(gè)折現(xiàn)圖來(lái)展現(xiàn)訂單,藍(lán)色的線代表的是訂單總數(shù),而下邊這根綠色的線代表的是有效訂單數(shù),即狀態(tài)是已完成的訂單,分別反映的是每一天的數(shù)據(jù)。上面還有3個(gè)數(shù)字,分別是訂單總數(shù)、有效訂單、訂單完成率,它指的是整個(gè)時(shí)間區(qū)間之內(nèi)總的數(shù)據(jù)。
業(yè)務(wù)規(guī)則:有效訂單指狀態(tài)為 “已完成” 的訂單、基于可視化報(bào)表的折線圖展示訂單數(shù)據(jù),X軸為日期,Y軸為訂單數(shù)量、根據(jù)時(shí)間選擇區(qū)間,展示每天的訂單總數(shù)和有效訂單數(shù)、展示所選時(shí)間區(qū)間內(nèi)的有效訂單數(shù)、總訂單數(shù)、訂單完成率,訂單完成率 = 有效訂單數(shù) / 總訂單數(shù) * 100%
根據(jù)訂單統(tǒng)計(jì)接口的返回結(jié)果設(shè)計(jì)VO,在sky-pojo模塊,OrderReportVO.java已定義
@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;
}
在ReportController中根據(jù)訂單統(tǒng)計(jì)接口創(chuàng)建orderStatistics方法:
/**
* 訂單數(shù)據(jù)統(tǒng)計(jì)
* @param begin
* @param end
* @return
*/
@GetMapping("/ordersStatistics")
@ApiOperation("用戶數(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));
}
在ReportServiceImpl實(shí)現(xiàn)類中實(shí)現(xiàn)getOrderStatistics方法:
/**
* 根據(jù)時(shí)間區(qū)間統(tǒng)計(jì)訂單數(shù)量
* @param begin
* @param end
* @return
*/
public OrderReportVO getOrderStatistics(LocalDate begin, LocalDate end){
//dateList用于存放從begin到end范圍內(nèi)的每天的日期
List<LocalDate> dateList = new ArrayList<>();
dateList.add(begin);
while (!begin.equals(end)){
begin = begin.plusDays(1);//日期計(jì)算,獲得指定日期后1天的日期
dateList.add(begin);
}
//每天訂單總數(shù)集合
List<Integer> orderCountList = new ArrayList<>();
//每天有效訂單數(shù)集合
List<Integer> validOrderCountList = new ArrayList<>();
for (LocalDate date : dateList) {//計(jì)算每個(gè)日期該天的總訂單數(shù)和有效訂單數(shù)
//給data日期加上時(shí)分秒 因?yàn)閿?shù)據(jù)庫(kù)里存的是LocalDateTime類型 而data是LocalDate類型
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);//LocalTime.MIN對(duì)應(yīng)一天開(kāi)始的時(shí)刻'00:00'
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);//LocalTime.MAX對(duì)應(yīng)一天結(jié)束的時(shí)刻'23:59:59.999999999'
//查詢每天的總訂單數(shù) select count(id) from orders where order_time >= ? and order_time <= ?
Integer orderCount = getOrderCount(beginTime, endTime, null);
//查詢每天的有效訂單數(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)類中提供私有方法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);
}
在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>
進(jìn)入數(shù)據(jù)統(tǒng)計(jì)模塊查看近7日訂單統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
銷量排名Top10
銷量排名指的就是菜品和套餐銷售的數(shù)量排名。通過(guò)柱形圖來(lái)展示銷量排名,這些銷量是按照降序來(lái)排列,并且只需要統(tǒng)計(jì)銷量排名前十的商品。
業(yè)務(wù)規(guī)則:根據(jù)時(shí)間選擇區(qū)間,展示銷量前10的商品(包括菜品和套餐)、基于可視化報(bào)表的柱狀圖降序展示商品銷量、此處的銷量為商品銷售的份數(shù)
根據(jù)銷量排名接口的返回結(jié)果設(shè)計(jì)VO,在sky-pojo模塊,SalesTop10ReportVO.java已定義
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SalesTop10ReportVO implements Serializable {
//商品名稱列表,以逗號(hào)分隔,例如:魚(yú)香肉絲,宮保雞丁,水煮魚(yú)
private String nameList;
//銷量列表,以逗號(hào)分隔,例如:260,215,200
private String numberList;
}
在ReportController中根據(jù)銷量排名接口創(chuàng)建top10方法:
/**
* 銷量排名統(tǒng)計(jì)
* @param begin
* @param end
* @return
*/
@GetMapping("/top10")
@ApiOperation("銷量排名統(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));
}
在ReportServiceImpl實(shí)現(xiàn)類中實(shí)現(xiàn)getSalesTop10方法:
/**
* 查詢指定時(shí)間區(qū)間內(nèi)的銷量排名top10
* @param begin
* @param end
* @return
* */
public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end){
//給data日期加上時(shí)分秒 因?yàn)閿?shù)據(jù)庫(kù)里存的是LocalDateTime類型 而data是LocalDate類型
LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);//LocalTime.MIN對(duì)應(yīng)一天開(kāi)始的時(shí)刻'00:00'
LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);//LocalTime.MAX對(duì)應(yīng)一天結(jié)束的時(shí)刻'23:59:59.999999999'
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接口中聲明getSalesTop10方法:
/**
* 查詢商品銷量排名
* @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>
這個(gè)select需要注意,返回的是List類型,并且查詢語(yǔ)句也容易寫(xiě)錯(cuò)。
查看近30日銷量排名Top10統(tǒng)計(jì)
進(jìn)入開(kāi)發(fā)者模式,查看返回?cái)?shù)據(jù)
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-797734.html
到了這里,關(guān)于SpringBoot+SSM項(xiàng)目實(shí)戰(zhàn) 蒼穹外賣(mài)(11) Apache ECharts的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!