diff --git a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java index a1a1058..ffe6250 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java @@ -53,7 +53,7 @@ public class CpTextController { @Autowired private CpTextMapper cpTextMapper; -// @AnonymousAccess + @AnonymousAccess @ApiOperation(value = "分页查询文本内容", notes = "分页查询文本内容") @RequestMapping(method = RequestMethod.GET) @ApiImplicitParams({ diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/controller/OrderDetailAnalysisController.java b/aircraft-system/src/main/java/com/aircraft/modules/order/controller/OrderDetailAnalysisController.java index 4e0dc09..d449b77 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/controller/OrderDetailAnalysisController.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/controller/OrderDetailAnalysisController.java @@ -61,8 +61,6 @@ public class OrderDetailAnalysisController { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); } } - - @ApiOperation("按日范围分析子单任务") @GetMapping("/day") // 额外返回:时间范围内任务列表 diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/OrderDetail.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/OrderDetail.java index 7280423..4ff9be1 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/OrderDetail.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/OrderDetail.java @@ -1,5 +1,6 @@ package com.aircraft.modules.order.domain; +import cn.hutool.core.date.DateTime; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.aircraft.base.BaseEntity; @@ -8,6 +9,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.math.BigDecimal; +import java.time.LocalDateTime; /** *

diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/DailyStat.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/DailyStat.java index 014005d..9c7b395 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/DailyStat.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/DailyStat.java @@ -6,5 +6,7 @@ import lombok.Data; @Data public class DailyStat { private String date; - private Long dailyCount;//每日数量 + private Long dailyTotalCount;//每日总数量 + private Long dailyCompletedCount;//每日完成数量 + private Long dailyFailedCount;//每日失败数量 } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/MonthlyStat.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/MonthlyStat.java index 195b1df..4a5b86e 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/MonthlyStat.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/MonthlyStat.java @@ -5,5 +5,7 @@ import lombok.Data; @Data public class MonthlyStat { private String month; - private Long monthlyCount;//每月数量 + private Long monthlyTotalCount;//每月数量 + private Long monthlyCompletedCount;//每月完成数量 + private Long monthlyFailedCount;//每月失败数量 } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java index 2e5f584..117949f 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java @@ -19,7 +19,7 @@ public class OrderDetailAnalysisResult { private BigDecimal failedRate; // 任务失败率 private Double averageTaskCycle; // 平均任务周期 - private BigDecimal droneUsageRate; // 无人机使用率 + private BigDecimal droneUsageRate; // 今日无人机使用率 private List routeDistribution; // 景区路线统计分布 private PageInfo pageInfo; // 分页信息 diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/QuarterlyStat.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/QuarterlyStat.java index e0a8254..8761da7 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/QuarterlyStat.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/QuarterlyStat.java @@ -5,5 +5,7 @@ import lombok.Data; @Data public class QuarterlyStat { private String quarter; // 季度标识(如2025-Q1) - private Long QuarterlyCount; // 每季度数量 + private Long quarterlyTotalCount; // 每季度数量 + private Long quarterlyCompletedCount;//每季完成数量 + private Long quarterlyFailedCount;//每季失败数量 } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/YearlyStat.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/YearlyStat.java index bdfa560..69613dd 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/YearlyStat.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/YearlyStat.java @@ -5,5 +5,7 @@ import lombok.Data; @Data public class YearlyStat { private String year; - private Long yearlyCount; + private Long yearlyTotalCount;//每年总数量 + private Long yearlyCompletedCount;//每年完成数量 + private Long yearlyFailedCount;//每年失败数量 } \ No newline at end of file diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java index 3c89502..881338a 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java @@ -88,7 +88,7 @@ public class OrderAnalysisServiceImpl implements OrderAnalysisService { String dateStr = current.format(DAY_FORMATTER); DailyStat stat = new DailyStat(); stat.setDate(dateStr); - stat.setDailyCount(dailyCountMap.getOrDefault(dateStr, 0L)); + stat.setDailyTotalCount(dailyCountMap.getOrDefault(dateStr, 0L)); dailyStats.add(stat); current = current.plusDays(1); // 移至下一天 } @@ -128,7 +128,7 @@ public class OrderAnalysisServiceImpl implements OrderAnalysisService { String monthStr = current.format(MONTH_FORMATTER); MonthlyStat stat = new MonthlyStat(); stat.setMonth(monthStr); - stat.setMonthlyCount(monthlyCountMap.getOrDefault(monthStr, 0L)); + stat.setMonthlyTotalCount(monthlyCountMap.getOrDefault(monthStr, 0L)); monthlyStats.add(stat); current = current.plusMonths(1); // 移至下一月 } @@ -175,7 +175,7 @@ public class OrderAnalysisServiceImpl implements OrderAnalysisService { QuarterlyStat stat = new QuarterlyStat(); stat.setQuarter(quarterStr); - stat.setQuarterlyCount(quarterCountMap.getOrDefault(quarterStr, 0L)); + stat.setQuarterlyTotalCount(quarterCountMap.getOrDefault(quarterStr, 0L)); quarterlyStats.add(stat); // 移至下一季度第一天 @@ -216,7 +216,7 @@ public class OrderAnalysisServiceImpl implements OrderAnalysisService { String yearStr = String.valueOf(year); YearlyStat stat = new YearlyStat(); stat.setYear(yearStr); - stat.setYearlyCount(yearCountMap.getOrDefault(yearStr, 0L)); + stat.setYearlyTotalCount(yearCountMap.getOrDefault(yearStr, 0L)); yearlyStats.add(stat); } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java index df30fba..a59973e 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java @@ -6,6 +6,7 @@ import com.aircraft.modules.order.controller.OrderAnalysisController; import com.aircraft.modules.order.domain.OrderDetail; import com.aircraft.modules.order.domain.dto.*; import com.aircraft.modules.order.mapper.OrderDetailMapper; +import com.aircraft.modules.order.service.IOrderDetailService; import com.aircraft.modules.order.service.OrderDetailAnalysisService; import com.aircraft.modules.route.domain.CpRoute; import com.aircraft.modules.route.mapper.CpRouteMapper; @@ -21,10 +22,7 @@ import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; -import java.time.Duration; -import java.time.LocalDate; -import java.time.YearMonth; -import java.time.ZoneId; +import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.Temporal; import java.util.*; @@ -55,6 +53,8 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic private EmScenicMapper emScenicMapper; @Autowired private AircraftDeviceService aircraftDeviceService; + @Autowired + private IOrderDetailService orderDetailService; @Override public OrderDetailAnalysisResult analyzeAllOrderDetails(List allDetails) { @@ -69,30 +69,36 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic return buildEmptyResult(); } - // 2. 按日分组统计每日订单量 - Map dailyCountMap = orders.stream() + // 2. 时间范围内总订单量 + Map dailyTotalCountMap = orders.stream() + .filter(order -> order.getCreateTime() != null) // 过滤掉创建时间为空的订单 .collect(Collectors.groupingBy( order -> { + // 将订单创建时间转换为yyyy-MM-dd格式的日期字符串 LocalDate localDate = order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - return localDate.format(DAY_FORMATTER); // 按日期字符串分组 + return localDate.format(DAY_FORMATTER); }, - Collectors.counting() // 统计每组数量 + Collectors.counting() )); - System.out.println(dailyCountMap); + System.out.println(dailyTotalCountMap); // 3. 填充每日统计数据(确保日期连续性,即使某天无订单也显示0) List dailyStats = new ArrayList<>(); LocalDate current = start; + // 4.计算每日完成量和失败量 + Map dailyCompletedMap = calculateDailyStatusCount(orders, STATUS_COMPLETED); + Map dailyFailedMap = calculateDailyStatusCount(orders, STATUS_FAILED); while (!current.isAfter(end)) { String dateStr = current.format(DAY_FORMATTER); DailyStat stat = new DailyStat(); stat.setDate(dateStr); - stat.setDailyCount(dailyCountMap.getOrDefault(dateStr, 0L)); + stat.setDailyTotalCount(dailyTotalCountMap.getOrDefault(dateStr, 0L));//每日任务总数量 + stat.setDailyCompletedCount(dailyCompletedMap.getOrDefault(dateStr, 0L)); //每日完成量 + stat.setDailyFailedCount(dailyFailedMap.getOrDefault(dateStr, 0L));//每日失败量 dailyStats.add(stat); current = current.plusDays(1); // 移至下一天 } - // 4. 构建并返回完整结果 return buildAnalysisResult(orders, dailyStats); } @@ -119,12 +125,15 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic List monthlyStats = new ArrayList<>(); LocalDate current = start.withDayOfMonth(1); // 从当月第一天开始 LocalDate endMonth = end.withDayOfMonth(1); // 结束月份第一天 - + Map monthlyCompletedMap = calculateMonthlyStatusCount(orders, STATUS_COMPLETED); + Map monthlyFailedMap = calculateMonthlyStatusCount(orders, STATUS_FAILED); while (!current.isAfter(endMonth)) { String monthStr = current.format(MONTH_FORMATTER); MonthlyStat stat = new MonthlyStat(); stat.setMonth(monthStr); - stat.setMonthlyCount(monthlyCountMap.getOrDefault(monthStr, 0L)); + stat.setMonthlyTotalCount(monthlyCountMap.getOrDefault(monthStr, 0L)); + stat.setMonthlyCompletedCount(monthlyCompletedMap.getOrDefault(monthStr, 0L)); + stat.setMonthlyFailedCount(monthlyFailedMap.getOrDefault(monthStr, 0L)); monthlyStats.add(stat); current = current.plusMonths(1); // 移至下一月 } @@ -146,7 +155,7 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic .collect(Collectors.groupingBy( order -> { // 将 java.util.Date 转换为 java.time.YearMonth - YearMonth yearMonth = YearMonth.from(order.getCreateTime().toInstant().atZone(ZoneId.systemDefault())); + YearMonth yearMonth = YearMonth.from(order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); int quarter = (yearMonth.getMonthValue() - 1) / 3 + 1; return yearMonth.format(YEAR_FORMATTER) + "-Q" + quarter; }, @@ -159,7 +168,8 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic // 调整至当前季度第一天(如2025-05-10 → 2025-04-01) currentQuarterStart = currentQuarterStart.minusMonths((currentQuarterStart.getMonthValue() - 1) % 3); currentQuarterStart = currentQuarterStart.withDayOfMonth(1); - + Map quarterlyCompletedMap = calculateQuarterlyStatusCount(orders, STATUS_COMPLETED); + Map quarterlyFailedMap = calculateQuarterlyStatusCount(orders, STATUS_FAILED); while (!currentQuarterStart.isAfter(end)) { // 计算当前季度标识(如2025-Q2) int quarter = (currentQuarterStart.getMonthValue() - 1) / 3 + 1; @@ -167,7 +177,9 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic QuarterlyStat stat = new QuarterlyStat(); stat.setQuarter(quarterStr); - stat.setQuarterlyCount(quarterCountMap.getOrDefault(quarterStr, 0L)); + stat.setQuarterlyTotalCount(quarterCountMap.getOrDefault(quarterStr, 0L)); + stat.setQuarterlyCompletedCount(quarterlyCompletedMap.getOrDefault(quarterStr, 0L)); + stat.setQuarterlyFailedCount(quarterlyFailedMap.getOrDefault(quarterStr, 0L)); quarterlyStats.add(stat); // 移至下一季度第一天 @@ -199,12 +211,15 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic List yearlyStats = new ArrayList<>(); int startYear = start.getYear(); int endYear = end.getYear(); - + Map yearlyCompletedMap = calculateYearlyStatusCount(orders, STATUS_COMPLETED); + Map yearlyFailedMap = calculateYearlyStatusCount(orders, STATUS_FAILED); for (int year = startYear; year <= endYear; year++) { String yearStr = String.valueOf(year); YearlyStat stat = new YearlyStat(); stat.setYear(yearStr); - stat.setYearlyCount(yearCountMap.getOrDefault(yearStr, 0L)); + stat.setYearlyTotalCount(yearCountMap.getOrDefault(yearStr, 0L)); + stat.setYearlyCompletedCount(yearlyCompletedMap.getOrDefault(yearStr, 0L)); + stat.setYearlyFailedCount(yearlyFailedMap.getOrDefault(yearStr, 0L)); yearlyStats.add(stat); } @@ -268,8 +283,10 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic double averageTaskCycle = calculateAverageTaskCycle(orderDetails); result.setAverageTaskCycle(averageTaskCycle); - // 新增: 计算无人机使用率 - BigDecimal droneUsageRate = calculateDroneUsageRate(orderDetails); + // 新增: 计算今日无人机使用率 + BigDecimal droneUsageRate = calculateTodayDroneUsageRate(); +// 时间范围内的无人机使用率 +// BigDecimal droneUsageRate = calculateTodayDroneUsageRate(orderDetails); result.setDroneUsageRate(droneUsageRate); // 5. 景区路线订单分布 @@ -286,6 +303,42 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic return result; } + //计算当日无人机使用率 + private BigDecimal calculateTodayDroneUsageRate() { + //1. 获取今日订单中出现的无人机数量(去重) + LocalDate today = LocalDate.now(); + LocalDateTime todayStart = today.atStartOfDay(); + LocalDateTime todayEnd = today.plusDays(1).atStartOfDay(); + + QueryWrapper orderQueryWrapper = new QueryWrapper<>(); + // 筛选今日创建的订单 + orderQueryWrapper.ge("create_time", todayStart) + .lt("create_time", todayEnd); + + List todayOrders = orderDetailService.list(orderQueryWrapper); + + Set usedDroneIds = new HashSet<>(); + for (OrderDetail order : todayOrders) { + Long droneId = order.getDeviceId(); + if (droneId != null) { + usedDroneIds.add(droneId); + } + } + int usedDroneCount = usedDroneIds.size(); + + + // 2. 获取无人机总量 + QueryWrapper queryWrapper = new QueryWrapper<>(); + int totalDroneCount = aircraftDeviceService.count(queryWrapper); + + // 3. 计算使用率(保留两位小数) + if (totalDroneCount == 0) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf((double) usedDroneCount / totalDroneCount) + .setScale(2, RoundingMode.HALF_UP); + } + //计算平均任务周期 private double calculateAverageTaskCycle(List orderDetails) { //获取任务数 @@ -307,7 +360,7 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic return (double) totalSeconds / (60.0 * completedTaskCount); } - //计算无人机使用率 + //计算时间范围内无人机使用率 private BigDecimal calculateDroneUsageRate(List orderDetails) { // 1. 获取时间范围内订单中出现的无人机数量(去重) Set usedDroneIds = orderDetails.stream() @@ -329,7 +382,7 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic } /** - * 按状态统计任务数量 + * 按状态统计时间范围内的任务数量 */ private long countTasksByStatus(List tasks, Integer status) { return tasks.stream() @@ -337,6 +390,54 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic .count(); } + /** + * 按日期和状态统计每日订单数量 + */ + private Map calculateDailyStatusCount(List orderDetails, Integer status) { + return orderDetails.stream() + .filter(order -> order.getOrderItemStatus().equals(status)) + .collect(Collectors.groupingBy( + order -> order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(DAY_FORMATTER), + Collectors.counting() + )); + } + + /** + * 按月份和状态统计每月订单数量 + */ + private Map calculateMonthlyStatusCount(List orderDetails, Integer status) { + return orderDetails.stream() + .filter(order -> order.getOrderItemStatus().equals(status)) + .collect(Collectors.groupingBy( + order -> order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(MONTH_FORMATTER), + Collectors.counting() + )); + } + + /** + * 按季节和状态统计每计季节订单数量 + */ + private Map calculateQuarterlyStatusCount(List orderDetails, Integer status) { + return orderDetails.stream() + .filter(order -> order.getOrderItemStatus().equals(status)) + .collect(Collectors.groupingBy( + order -> order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(QUARTER_FORMATTER), + Collectors.counting() + )); + } + + /** + * 按年份和状态统计每计年订单数量 + */ + private Map calculateYearlyStatusCount(List orderDetails, Integer status) { + return orderDetails.stream() + .filter(order -> order.getOrderItemStatus().equals(status)) + .collect(Collectors.groupingBy( + order -> order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(YEAR_FORMATTER), + Collectors.counting() + )); + } + /** * 计算比率(保留两位小数) */