首页统计-柱状图和折线图

This commit is contained in:
19173159168
2025-09-14 23:21:53 +08:00
parent 4fa7688afc
commit 682b8c45fe
8 changed files with 461 additions and 90 deletions

View File

@ -1,5 +1,6 @@
package com.ruoyi.orders.controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -8,6 +9,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.operation.domain.Company;
import com.ruoyi.operation.service.ICompanyService;
import com.ruoyi.orders.domain.ZcOrderCarChange;
import com.ruoyi.orders.dto.StatisticsHomeOrder;
import com.ruoyi.orders.service.IZcOrderCarChangeService;
import com.ruoyi.orders.util.OrderStatusEnum;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -167,4 +169,21 @@ public class ZcOrderMainController extends BaseController
return toAjax(flag);
}
@PostMapping("/statisticsHomeOrder")
@ResponseBody
public AjaxResult statisticsHomeOrder(String type) {
List<StatisticsHomeOrder> list = new ArrayList<StatisticsHomeOrder>();
if(type.equals("hour")) {
list = zcOrderMainService.statisticsOrderByHour();
}else if(type.equals("week")) {
list = zcOrderMainService.statisticsOrderByWeek();
}else if(type.equals("month")) {
list = zcOrderMainService.statisticsOrderByMonth();
}else if(type.equals("year")) {
list = zcOrderMainService.statisticsOrderByYear();
}
return AjaxResult.success(list);
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.orders.dto;
import java.math.BigDecimal;
public class StatisticsHomeOrder {
private String keyType;
private String name;
private int totalCount;
private BigDecimal totalAmount;
private int rentcarCount;
private BigDecimal rentcarAmount;
private int rentbatteryCount;
private BigDecimal rentbatteryAmount;
public String getKeyType() {
return keyType;
}
public void setKeyType(String keyType) {
this.keyType = keyType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public BigDecimal getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}
public int getRentcarCount() {
return rentcarCount;
}
public void setRentcarCount(int rentcarCount) {
this.rentcarCount = rentcarCount;
}
public BigDecimal getRentcarAmount() {
return rentcarAmount;
}
public void setRentcarAmount(BigDecimal rentcarAmount) {
this.rentcarAmount = rentcarAmount;
}
public int getRentbatteryCount() {
return rentbatteryCount;
}
public void setRentbatteryCount(int rentbatteryCount) {
this.rentbatteryCount = rentbatteryCount;
}
public BigDecimal getRentbatteryAmount() {
return rentbatteryAmount;
}
public void setRentbatteryAmount(BigDecimal rentbatteryAmount) {
this.rentbatteryAmount = rentbatteryAmount;
}
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.orders.mapper;
import java.util.List;
import com.ruoyi.orders.domain.ZcOrderMain;
import com.ruoyi.orders.domain.ZcOrderSub;
import com.ruoyi.orders.dto.StatisticsHomeOrder;
import com.ruoyi.orders.dto.StoreOrderStats;
import org.apache.ibatis.annotations.Param;
@ -103,4 +104,12 @@ public interface ZcOrderMainMapper
List<StoreOrderStats> selectTopStoreOrderStats(@Param("limit") int limit);
int selectOrderCountByCarRuleId(@Param("carRuleId")Long carRuleId);
List<StatisticsHomeOrder> statisticsOrderByHour();
List<StatisticsHomeOrder> statisticsOrderByWeek();
List<StatisticsHomeOrder> statisticsOrderByMonth();
List<StatisticsHomeOrder> statisticsOrderByYear();
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.orders.service;
import java.util.List;
import com.ruoyi.orders.domain.ZcOrderMain;
import com.ruoyi.orders.dto.StatisticsHomeOrder;
import com.ruoyi.orders.dto.StoreOrderStats;
/**
@ -74,4 +75,12 @@ public interface IZcOrderMainService
public int selectOrderCountByCarRuleId(Long carRuleId);
public List<StatisticsHomeOrder> statisticsOrderByHour();
public List<StatisticsHomeOrder> statisticsOrderByWeek();
public List<StatisticsHomeOrder> statisticsOrderByMonth();
public List<StatisticsHomeOrder> statisticsOrderByYear();
}

View File

@ -1,8 +1,7 @@
package com.ruoyi.orders.service.impl;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.*;
import com.ruoyi.api.DataPushApi;
import com.ruoyi.common.utils.DateUtils;
@ -11,6 +10,7 @@ import com.ruoyi.operation.domain.ZcCar;
import com.ruoyi.operation.service.IZcCarService;
import com.ruoyi.operation.util.CarStatusEnum;
import com.ruoyi.orders.dto.RefundRequest;
import com.ruoyi.orders.dto.StatisticsHomeOrder;
import com.ruoyi.orders.dto.StoreOrderStats;
import com.ruoyi.orders.service.IZcOrderSubService;
import com.ruoyi.orders.util.OrderStatusEnum;
@ -28,8 +28,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.StringUtils;
@ -350,4 +348,24 @@ public class ZcOrderMainServiceImpl implements IZcOrderMainService
return zcOrderMainMapper.selectOrderCountByCarRuleId(carRuleId);
}
@Override
public List<StatisticsHomeOrder> statisticsOrderByHour() {
return zcOrderMainMapper.statisticsOrderByHour();
}
@Override
public List<StatisticsHomeOrder> statisticsOrderByWeek() {
return zcOrderMainMapper.statisticsOrderByWeek();
}
@Override
public List<StatisticsHomeOrder> statisticsOrderByMonth() {
return zcOrderMainMapper.statisticsOrderByMonth();
}
@Override
public List<StatisticsHomeOrder> statisticsOrderByYear() {
return zcOrderMainMapper.statisticsOrderByYear();
}
}

View File

@ -6,6 +6,7 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.*;
import com.ruoyi.orders.dto.StatisticsHomeOrder;
import com.ruoyi.orders.dto.StoreOrderStats;
import com.ruoyi.orders.service.IZcOrderMainService;
import com.ruoyi.system.domain.SysNotice;
@ -154,6 +155,9 @@ public class SysIndexController extends BaseController
List<StoreOrderStats> storeOrderStats = zcOrderMainService.getTopStoreOrderStats(9);
mmap.put("storeOrderStats", storeOrderStats);
List<StatisticsHomeOrder> statisticsHomeOrders = zcOrderMainService.statisticsOrderByMonth();
mmap.put("statisticsHomeOrders", statisticsHomeOrders);
List<SysNotice> sysNotices = noticeService.selectHomeNoticeList();
mmap.put("sysNotices", sysNotices);

View File

@ -298,4 +298,67 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
SELECT count(1) as orderCount FROM zc_order_main where rent_car_rule_id = #{carRuleId} and order_status in ('WAIT_PAY','WAIT_PICK','RENT_ING','WAIT_RETURN','RENT_OVERDUE')
</select>
<select id="statisticsOrderByHour" resultType="com.ruoyi.orders.dto.StatisticsHomeOrder">
SELECT
HOUR(create_time) as keyType,
count(1) as totalCount,
sum(amount) as totalAmount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN 1 ELSE 0 END) as rentcarCount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN amount ELSE 0 END) as rentcarAmount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN 1 ELSE 0 END) as rentbatteryCount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN amount ELSE 0 END) as rentbatteryAmount
FROM zc_order_sub
WHERE DATE(create_time) = CURDATE()
AND suborder_type IN ('RENTCAR', 'RENTBATTEY')
GROUP BY HOUR(create_time)
ORDER BY keyType;
</select>
<select id="statisticsOrderByWeek" resultType="com.ruoyi.orders.dto.StatisticsHomeOrder">
SELECT
DAYNAME(create_time) as name,
DAYOFWEEK(create_time) as keyType,
count(1) as totalCount,
sum(amount) as totalAmount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN 1 ELSE 0 END) as rentcarCount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN amount ELSE 0 END) as rentcarAmount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN 1 ELSE 0 END) as rentbatteryCount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN amount ELSE 0 END) as rentbatteryAmount
FROM zc_order_sub
WHERE YEARWEEK(create_time, 1) = YEARWEEK(CURDATE(), 1)
AND suborder_type IN ('RENTCAR', 'RENTBATTEY')
GROUP BY DAYOFWEEK(create_time), DAYNAME(create_time)
ORDER BY keyType;
</select>
<select id="statisticsOrderByMonth" resultType="com.ruoyi.orders.dto.StatisticsHomeOrder">
SELECT
DAY(create_time) as keyType,
count(1) as totalCount,
sum(amount) as totalAmount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN 1 ELSE 0 END) as rentcarCount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN amount ELSE 0 END) as rentcarAmount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN 1 ELSE 0 END) as rentbatteryCount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN amount ELSE 0 END) as rentbatteryAmount
FROM zc_order_sub
WHERE MONTH(create_time) = MONTH(CURDATE())
AND YEAR(create_time) = YEAR(CURDATE())
AND suborder_type IN ('RENTCAR', 'RENTBATTEY')
GROUP BY DAY(create_time)
ORDER BY keyType;
</select>
<select id="statisticsOrderByYear" resultType="com.ruoyi.orders.dto.StatisticsHomeOrder">
SELECT
MONTH(create_time) as keyType,
count(1) as totalCount,
sum(amount) as totalAmount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN 1 ELSE 0 END) as rentcarCount,
SUM(CASE WHEN suborder_type = 'RENTCAR' THEN amount ELSE 0 END) as rentcarAmount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN 1 ELSE 0 END) as rentbatteryCount,
SUM(CASE WHEN suborder_type = 'RENTBATTEY' THEN amount ELSE 0 END) as rentbatteryAmount
FROM zc_order_sub
WHERE YEAR(create_time) = YEAR(CURDATE())
AND suborder_type IN ('RENTCAR', 'RENTBATTEY')
GROUP BY MONTH(create_time), MONTHNAME(create_time)
ORDER BY keyType;
</select>
</mapper>

View File

@ -341,6 +341,22 @@
<div class="box box-success box-widget" style="border: 1px solid #e5e5e5">
<div class="box-header" style="border-bottom: 1px dashed #797979;">
<h3 class="box-title" style="font-weight: bold">销售额趋势</h3>
<div class="pull-right">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-default btn-sm" onclick="switchSalesPeriod('hour')">
<input type="radio" name="period" autocomplete="off"> 今日
</label>
<label class="btn btn-default btn-sm" onclick="switchSalesPeriod('week')">
<input type="radio" name="period" autocomplete="off"> 本周
</label>
<label class="btn btn-default btn-sm active" onclick="switchSalesPeriod('month')">
<input type="radio" name="period" autocomplete="off" checked> 本月
</label>
<label class="btn btn-default btn-sm " onclick="switchSalesPeriod('year')">
<input type="radio" name="period" autocomplete="off" > 全年
</label>
</div>
</div>
</div>
<div class="box-body chat">
<canvas id="salesTrendChart" width="400" height="120"></canvas>
@ -377,6 +393,22 @@
<div class="box box-success box-widget" style="border: 1px solid #e5e5e5; margin-top: 20px;">
<div class="box-header" style="border-bottom: 1px dashed #797979;">
<h3 class="box-title" style="font-weight: bold">平台订单量</h3>
<div class="pull-right">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-default btn-sm" onclick="switchOrderPeriod('hour')">
<input type="radio" name="period" autocomplete="off"> 今日
</label>
<label class="btn btn-default btn-sm" onclick="switchOrderPeriod('week')">
<input type="radio" name="period" autocomplete="off"> 本周
</label>
<label class="btn btn-default btn-sm active" onclick="switchOrderPeriod('month')">
<input type="radio" name="period" autocomplete="off" checked> 本月
</label>
<label class="btn btn-default btn-sm " onclick="switchOrderPeriod('year')">
<input type="radio" name="period" autocomplete="off" > 全年
</label>
</div>
</div>
</div>
<div class="box-body chat">
<canvas id="orderVolumeChart" width="500" height="120"></canvas>
@ -396,106 +428,245 @@
<script th:src="@{/ruoyi/js/common.js?v=4.7.4}"></script>
<script th:src="@{/ruoyi/chart.js?v=4.7.4}"></script>
<script th:inline="javascript">
$('#pay-qrcode').click(function(){
var html=$(this).html();
parent.layer.open({
title: false,
type: 1,
closeBtn:false,
shadeClose:true,
area: ['600px', '360px'],
content: html
});
});
// 全局图表实例变量
var salesChartInstance = null;
var orderVolumeChartInstance = null;
/* 用户管理-重置密码 */
function toPage(title,url) {
$.modal.openTab(title, url);
}
var currentPeriod = 'month';
var currentPeriod2 = 'month';
function noticeList(){
var url = ctx + "/system/notice";
$.modal.openTab("通知公告",url);
}
function noticeDetail(noticeId){
var url = ctx + "/system/notice/detail/"+noticeId;
$.modal.openTab("通知公告",url);
}
var salesData = null;
var initialOrderVolumeData = null;
// 初始化平台订单量图表
var statisticsHomeOrders = [[${statisticsHomeOrders}]];
var salesDataLabels = [], orderVolumeDataLabels = [];
var salesDataDatasets1 = [];
var orderVolumeDataDatasets1 = [],orderVolumeDataDatasets2 = [];
// 销售额趋势图表数据
var salesData = {
labels: ['10月', '11月', '12月', '01月', '02月', '03月', '04月', '05月', '06月', '07月', '08月', '09月'],
datasets: [{
label: '销售额',
data: [300, 750, 1000, 450, 150, 480, 250, 300, 650, 500, 200, 350],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
};
$('#pay-qrcode').click(function(){
var html=$(this).html();
parent.layer.open({
title: false,
type: 1,
closeBtn:false,
shadeClose:true,
area: ['600px', '360px'],
content: html
});
});
/* 用户管理-重置密码 */
function toPage(title,url) {
$.modal.openTab(title, url);
}
function noticeList(){
var url = ctx + "/system/notice";
$.modal.openTab("通知公告",url);
}
function noticeDetail(noticeId){
var url = ctx + "/system/notice/detail/"+noticeId;
$.modal.openTab("通知公告",url);
}
// 销毁图表的通用函数
function destroyChart(chartInstance) {
if (chartInstance) {
chartInstance.destroy();
chartInstance = null;
}
return null;
}
// 创建销售额趋势图表
var ctxSales = document.getElementById('salesTrendChart').getContext('2d');
var salesChart = new Chart(ctxSales, {
type: 'bar',
data: salesData,
options: {
scales: {
y: {
beginAtZero: true
function createSalesChart() {
var ctxSales = document.getElementById('salesTrendChart').getContext('2d');
salesChartInstance = new Chart(ctxSales, {
type: 'bar',
data: salesData,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
// 创建平台订单量图表
function createOrderVolumeChart() {
var ctxOrderVolume = document.getElementById('orderVolumeChart').getContext('2d');
orderVolumeChartInstance = new Chart(ctxOrderVolume, {
type: 'line',
data: initialOrderVolumeData,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
// 切换订单周期函数
function switchOrderPeriod(period) {
currentPeriod = period;
generateMockData(period);
}
// 加载数据
function generateMockData(period) {
var str = "日";
if(period == 'hour'){
str = "时";
}else if(period == 'week'){
str = "";
}else if(period == 'month'){
str = "日";
}else if(period == 'year'){
str = "月";
}
$.ajax({
url: ctx + "/orders/order/statisticsHomeOrder",
method: 'POST',
data: {
type: period
},
success: function(response) {
// 清空数据数组
orderVolumeDataLabels = [];
orderVolumeDataDatasets1 = [];
orderVolumeDataDatasets2 = [];
var statisticsHomeOrders = response.data;
// alert(JSON.stringify(statisticsHomeOrders))
for (var i = 0; i < statisticsHomeOrders.length; i++){
orderVolumeDataLabels.push(statisticsHomeOrders[i].keyType + str);
orderVolumeDataDatasets1.push(statisticsHomeOrders[i].rentcarCount);
orderVolumeDataDatasets2.push(statisticsHomeOrders[i].rentbatteryCount);
}
// 销毁已存在的图表
destroyChart(orderVolumeChartInstance);
initVolumeData();
createOrderVolumeChart();
},
error: function(xhr, status, error) {
console.error('获取订单量数据失败:', error);
// 可以显示错误提示
}
});
}
// 切换订单周期函数
function switchSalesPeriod(period) {
currentPeriod2 = period;
generateMockData2(period);
}
// 加载数据
function generateMockData2(period) {
var str = "日";
if(period == 'hour'){
str = "时";
}else if(period == 'week'){
str = "";
}else if(period == 'month'){
str = "日";
}else if(period == 'year'){
str = "月";
}
$.ajax({
url: ctx + "/orders/order/statisticsHomeOrder",
method: 'POST',
data: {
type: period
},
success: function(response) {
// 清空数据数组
salesDataLabels = [];
salesDataDatasets1 = [];
var statisticsHomeOrders = response.data;
for (var i = 0; i < statisticsHomeOrders.length; i++){
salesDataLabels.push(statisticsHomeOrders[i].keyType+str);
salesDataDatasets1.push(statisticsHomeOrders[i].totalAmount)
}
// 销毁已存在的图表
destroyChart(salesChartInstance);
initVolumeData2();
createSalesChart();
},
error: function(xhr, status, error) {
console.error('获取订单量数据失败:', error);
// 可以显示错误提示
}
});
}
// 页面加载完成后初始化图表
$(document).ready(function() {
for (var i = 0; i < statisticsHomeOrders.length; i++){
orderVolumeDataLabels.push(statisticsHomeOrders[i].keyType+"日");
orderVolumeDataDatasets1.push(statisticsHomeOrders[i].rentcarCount);
orderVolumeDataDatasets2.push(statisticsHomeOrders[i].rentbatteryCount);
salesDataLabels.push(statisticsHomeOrders[i].keyType+"日");
salesDataDatasets1.push(statisticsHomeOrders[i].totalAmount)
}
// 初始化销售额趋势图表
initVolumeData2()
createSalesChart();
initVolumeData()
createOrderVolumeChart();
});
// 租车订单百分比圆环图数据
var rentCarData = {
labels: ['租车订单'],
datasets: [{
data: [56],
backgroundColor: ['#36A2EB'],
hoverBackgroundColor: ['#FF6384']
}]
};
function initVolumeData() {
initialOrderVolumeData = {
labels: orderVolumeDataLabels,
datasets: [
{
label: '租车',
data: orderVolumeDataDatasets1,
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2,
fill: false
},
{
label: '租电',
data: orderVolumeDataDatasets2,
backgroundColor: 'rgba(165,229,150,0.2)',
borderColor: 'rgb(57,222,21)',
borderWidth: 2,
fill: false
}
]
};
}
// 平台订单量折线图数据
var orderVolumeData = {
labels: ['10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'],
datasets: [
{
label: '租车',
data: [10, 15, 5, 30, 45, 45, 45, 45, 65, 45, 10, 30, 30, 60, 45],
function initVolumeData2() {
salesData = {
labels: salesDataLabels,
datasets: [{
label: '销售额',
data: salesDataDatasets1,
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2,
fill: false // 不填充区域
},
{
label: '租电',
data: [30, 15, 15, 30, 45, 60, 60, 45, 45, 45, 45, 45, 45, 75, 50],
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 2,
fill: false // 不填充区域
}
]
};
// 创建平台订单量折线图
var ctxOrderVolume = document.getElementById('orderVolumeChart').getContext('2d');
var orderVolumeChart = new Chart(ctxOrderVolume, {
type: 'line',
data: orderVolumeData,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
borderWidth: 1
}]
};
}
</script>
</body>