wlzboy
2025-12-04 4f2925f1974844b66225ac70ae35065b8262b315
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
@@ -6,7 +6,9 @@
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -181,8 +183,14 @@
    @Override
    public int batchCalculateMileageStats(Date statDate) {
        try {
            // 计算查询开始时间(7天前)
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(statDate);
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            Date startTime = calendar.getTime();
            // 查询所有活跃车辆
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
            
            if (vehicleIds == null || vehicleIds.isEmpty()) {
                logger.info("没有找到活跃车辆");
@@ -389,26 +397,69 @@
                }
            }
            
            // 4. 查询该日期的任务时间区间,计算任务里程和非任务里程
            List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
            // 4. 计算任务里程和非任务里程(优化:优先使用task_id直接聚合)
            BigDecimal taskMileage = BigDecimal.ZERO;
            BigDecimal nonTaskMileage = BigDecimal.ZERO;
            int taskCount = 0;  // 任务数量
            
            // 4.1 统计有task_id的分段数量
            int segmentsWithTask = 0;
            for (VehicleGpsSegmentMileage segment : segments) {
                Date segStart = segment.getSegmentStartTime();
                Date segEnd = segment.getSegmentEndTime();
                BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO;
                if (segment.getTaskId() != null) {
                    segmentsWithTask++;
                }
            }
            // 4.2 如果大部分分段都有task_id,使用优化方案(直接按task_id聚合)
            if (segmentsWithTask > segments.size() * 0.8) {
                logger.debug("车辆ID: {} 日期: {} 使用优化方案:直接按task_id聚合({}个分段有task_id,占比{}%)",
                           vehicleId, statDate, segmentsWithTask, (segmentsWithTask * 100.0 / segments.size()));
                
                // 计算该分段与任务时段的重叠比例
                double taskRatio = calculateTaskOverlapRatio(segStart, segEnd, taskIntervals);
                // 使用Set统计去重的任务ID数量
                Set<Long> uniqueTaskIds = new HashSet<>();
                
                // 分摇里程
                BigDecimal taskDist = segDistance.multiply(BigDecimal.valueOf(taskRatio));
                BigDecimal nonTaskDist = segDistance.multiply(BigDecimal.valueOf(1 - taskRatio));
                // 直接按task_id分组聚合
                for (VehicleGpsSegmentMileage segment : segments) {
                    BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO;
                    if (segment.getTaskId() != null) {
                        // 有任务ID,计入任务里程
                        taskMileage = taskMileage.add(segDistance);
                        uniqueTaskIds.add(segment.getTaskId());
                    } else {
                        // 没有任务ID,计入非任务里程
                        nonTaskMileage = nonTaskMileage.add(segDistance);
                    }
                }
                
                taskMileage = taskMileage.add(taskDist);
                nonTaskMileage = nonTaskMileage.add(nonTaskDist);
                // 设置去重后的任务数量
                taskCount = uniqueTaskIds.size();
            } else {
                // 4.3 降级方案:使用原有的时间重叠计算方式
                logger.debug("车辆ID: {} 日期: {} 使用降级方案:时间重叠计算(只有{}个分段有task_id,占比{}%)",
                           vehicleId, statDate, segmentsWithTask, (segmentsWithTask * 100.0 / segments.size()));
                List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
                for (VehicleGpsSegmentMileage segment : segments) {
                    Date segStart = segment.getSegmentStartTime();
                    Date segEnd = segment.getSegmentEndTime();
                    BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO;
                    // 计算该分段与任务时段的重叠比例
                    double taskRatio = calculateTaskOverlapRatio(segStart, segEnd, taskIntervals);
                    // 分摊里程
                    BigDecimal taskDist = segDistance.multiply(BigDecimal.valueOf(taskRatio));
                    BigDecimal nonTaskDist = segDistance.multiply(BigDecimal.valueOf(1 - taskRatio));
                    taskMileage = taskMileage.add(taskDist);
                    nonTaskMileage = nonTaskMileage.add(nonTaskDist);
                }
                // 设置任务数量
                taskCount = taskIntervals == null ? 0 : taskIntervals.size();
            }
            
            // 计算任务里程占比
@@ -457,7 +508,7 @@
            stats.setNonTaskMileage(nonTaskMileage.setScale(2, RoundingMode.HALF_UP));
            stats.setTaskRatio(taskRatio);
            stats.setGpsPointCount(totalGpsPoints);
            stats.setTaskCount(taskIntervals == null ? 0 : taskIntervals.size());
            stats.setTaskCount(taskCount);
            stats.setSegmentCount(segments.size());
            stats.setDataSource("segment"); // 标记数据来源为分段汇总
            
@@ -485,8 +536,14 @@
    @Override
    public int batchAggregateFromSegmentMileage(Date statDate) {
        try {
            // 计算查询开始时间(7天前)
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(statDate);
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            Date startTime = calendar.getTime();
            // 查询所有活跃车辆
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
            
            if (vehicleIds == null || vehicleIds.isEmpty()) {
                logger.info("没有找到活跃车辆");