wlzboy
5 天以前 fe33646ee6e2d1e57f2b51812e94983a0e9efb04
feat: 修复统计
11个文件已修改
174 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleMileageStatsController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/VehicleGpsSegmentMileageMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/qy_wechat_config.sql 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleMileageStatsController.java
@@ -114,7 +114,7 @@
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            sdf.setLenient(false); // 严格解析日期
            Date date = sdf.parse(statDate.trim());
            logger.info("---> 手动计算车辆里程汇总,车辆ID: {}, 日期: {}", vehicleId, date);
            VehicleMileageStats stats = vehicleMileageStatsService.calculateAndSaveMileageStats(vehicleId, date);
            // 修复String到Date转换问题,添加更好的错误处理
            if (stats != null) {
ruoyi-admin/src/main/resources/application.yml
@@ -58,7 +58,7 @@
    basename: i18n/messages
  profiles:
    # 环境 dev|test|prod
    active: dev
    active: prod
  # 文件上传
  servlet:
    multipart:
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -110,6 +110,18 @@
    }
    /**
     * 日期型字符串转化为日期
     * @param date
     * @param format
     * @return
     */
    public static final String formatDate(Date date, String format){
        return new SimpleDateFormat(format).format(date);
    }
    public static  final  String formatDate(Date date){
        return new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS).format(date);
    }
    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
@@ -138,6 +138,6 @@
     * @return
     */
    public List<SysTask> selectTaskByVehicleIdAndDate(@Param("vehicleId") Long vehicleId,
                                                      @Param("startTime") Date startTime,
                                                      @Param("endTime") Date endTime);
                                                      @Param("startTime") String startTime,
                                                      @Param("endTime") String endTime);
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java
@@ -60,8 +60,8 @@
     * @return GPS坐标列表
     */
    public List<VehicleGps> selectGpsDataByTimeRange(@Param("vehicleId") Long vehicleId,
                                                       @Param("startTime") Date startTime,
                                                       @Param("endTime") Date endTime);
                                                       @Param("startTime") String startTime,
                                                       @Param("endTime") String endTime);
    /**
     * 查询活跃车辆ID列表
@@ -69,7 +69,7 @@
     * @param startTime 起始时间
     * @return 车辆ID列表
     */
    public List<Long> selectActiveVehicleIds(@Param("startTime") Date startTime);
    public List<Long> selectActiveVehicleIds(@Param("startTime") String startTime);
    
    /**
     * 查询未被计算的GPS坐标(不在tb_vehicle_gps_calculated表中的记录)
@@ -80,6 +80,6 @@
     * @return 未被计算的GPS坐标列表
     */
    public List<VehicleGps> selectUncalculatedGps(@Param("vehicleId") Long vehicleId,
                                                    @Param("startTime") Date startTime,
                                                    @Param("endTime") Date endTime);
                                                    @Param("startTime") String startTime,
                                                    @Param("endTime") String endTime);
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
@@ -3,6 +3,8 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import com.ruoyi.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -97,10 +99,11 @@
    public int batchCalculateSegmentMileage(Date startTime, Date endTime) {
        try {
//            logger.info("开始批量计算GPS分段里程 - 时间范围: {} 到 {}", startTime, endTime);
            String startTimeStr = DateUtils.formatDate(startTime,DateUtils.YYYY_MM_DD_HH_MM_SS);
            String endTimeStr = DateUtils.formatDate(endTime,DateUtils.YYYY_MM_DD_HH_MM_SS);
            // 查询在指定时间范围内有GPS数据的所有车辆(添加慢SQL监控)
            long startQueryTime = System.currentTimeMillis();
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTimeStr);
            long queryTime = System.currentTimeMillis() - startQueryTime;
            
            // 慢查询警告(超过1秒)
@@ -168,8 +171,9 @@
            
            logger.info("开始补偿计算 - 回溯天数: {}, 时间范围: {} 到 {}", lookbackDays, startTime, endTime);
            
            String startTimeStr=DateUtils.formatDate(startTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
            // 查询所有活跃车辆
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTimeStr);
            
            if (vehicleIds == null || vehicleIds.isEmpty()) {
                logger.info("没有找到活跃车辆");
@@ -179,10 +183,12 @@
            int successCount = 0;
            int totalUncalculated = 0;
            
            String endTimeStr=DateUtils.formatDate(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
            for (Long vehicleId : vehicleIds) {
                try {
                    // 查询该车辆未被计算的GPS数据
                    List<VehicleGps> uncalculatedGps = vehicleGpsMapper.selectUncalculatedGps(vehicleId, startTime, endTime);
                    List<VehicleGps> uncalculatedGps = vehicleGpsMapper.selectUncalculatedGps(vehicleId, startTimeStr, endTimeStr);
                    
                    if (uncalculatedGps == null || uncalculatedGps.isEmpty()) {
                        logger.debug("车辆 {} 没有未计算的GPS数据", vehicleId);
@@ -241,14 +247,16 @@
    public int calculateVehicleSegmentMileage(Long vehicleId, Date startTime, Date endTime) {
        try {
            // 查询车辆在时间范围内的GPS数据
            List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, startTime, endTime);
            String startTimeStr=DateUtils.formatDate(startTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
            String endTimeStr=DateUtils.formatDate(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
            List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, startTimeStr, endTimeStr);
            
            if (gpsList == null || gpsList.isEmpty()) {
                logger.debug("车辆ID: {} 在时间范围 {} 到 {} 内无GPS数据", vehicleId, startTime, endTime);
                return 0;
            }
            
            logger.info("车辆ID: {} 查询到 {} 条GPS数据 startTime:{},endTime:{}", vehicleId, gpsList.size(),startTime,endTime);
//            logger.info("车辆ID: {} 查询到 {} 条GPS数据 startTime:{},endTime:{}", vehicleId, gpsList.size(),startTime,endTime);
            
            return calculateVehicleSegmentMileageWithGpsList(vehicleId, gpsList, startTime, endTime);
            
@@ -284,7 +292,7 @@
            // 处理每个时间段并计算里程
            int savedCount = processSegmentedGpsData(vehicleId, segmentedData, config);
            
            logger.info("车辆 {} 计算完成,保存了 {} 个时间段的里程数据", vehicleId, savedCount);
//            logger.info("车辆 {} 计算完成,保存了 {} 个时间段的里程数据", vehicleId, savedCount);
            
            // 自动触发每日统计汇总
            if (savedCount > 0) {
@@ -319,7 +327,7 @@
        // 获取是否跳过已计算GPS点的配置
        String skipCalculatedConfig = configService.selectConfigByKey("gps.mileage.skip.calculated");
        config.skipCalculated = skipCalculatedConfig == null || "true".equalsIgnoreCase(skipCalculatedConfig);
        logger.info("控制跳过重复计算标识: {}", config.skipCalculated);
//        logger.info("控制跳过重复计算标识: {}", config.skipCalculated);
        
        return config;
    }
@@ -383,7 +391,7 @@
        
        // 如果本段只有1个点,且没有上一段的最后一个点,无法计算距离
        if (segmentGpsList.size() == 1 && previousSegmentLastPoint == null) {
            logger.debug("车辆 {} 时间段 {} 只有1个GPS点且无前置点,暂存待下一段计算", vehicleId, segmentStartTime);
//            logger.debug("车辆 {} 时间段 {} 只有1个GPS点且无前置点,暂存待下一段计算", vehicleId, segmentStartTime);
            return false;
        }
        
@@ -428,7 +436,7 @@
                distance, gpsIdList, gpsIds, config.calculateMethod);
            
            // 保存到数据库
            logger.info("保存车辆分时段里程到数据库中,车辆ID: {}, 时间段: {} 到 {}", vehicleId, segmentStartTime, segmentEndTime);
//            logger.info("保存车辆分时段里程到数据库中,车辆ID: {}, 时间段: {} 到 {}", vehicleId, segmentStartTime, segmentEndTime);
            segmentMileageMapper.insertVehicleGpsSegmentMileage(segment);
            
            // 记录已计算的GPS点(如果开启了重复计算控制)
@@ -436,9 +444,9 @@
                recordCalculatedGpsPoints(gpsIdList, segment.getSegmentId(), vehicleId);
            }
            
            logger.debug("车辆 {} 时间段 {} 到 {} 里程: {}km, GPS点数: {}, GPS IDs: {}",
                       vehicleId, segmentStartTime, segmentEndTime, distance, segmentGpsList.size(),
                       gpsIds.length() > 50 ? gpsIds.substring(0, 50) + "..." : gpsIds);
//            logger.debug("车辆 {} 时间段 {} 到 {} 里程: {}km, GPS点数: {}, GPS IDs: {}",
//                       vehicleId, segmentStartTime, segmentEndTime, distance, segmentGpsList.size(),
//                       gpsIds.length() > 50 ? gpsIds.substring(0, 50) + "..." : gpsIds);
            
            return true;
            
@@ -560,7 +568,7 @@
            for (Date statDate : affectedDates) {
                try {
                    mileageStatsService.aggregateFromSegmentMileage(vehicleId, statDate);
                    logger.info("车辆 {} 日期 {} 的统计数据已自动汇总生成", vehicleId, statDate);
//                    logger.info("车辆 {} 日期 {} 的统计数据已自动汇总生成", vehicleId, statDate);
                } catch (Exception e) {
                    logger.error("车辆 {} 日期 {} 自动汇总统计失败", vehicleId, statDate, e);
                }
@@ -662,8 +670,8 @@
            );
            totalDistance = totalDistance.add(BigDecimal.valueOf(gapDistance));
            
            logger.debug("跨段间隙距离: {}km (上一段末点 -> 当前段首点)",
                String.format("%.3f", gapDistance));
//            logger.debug("跨段间隙距离: {}km (上一段末点 -> 当前段首点)",
//                String.format("%.3f", gapDistance));
        }
        
        // 2. 再计算当前段内部的距离(如果有2个或以上GPS点)
@@ -840,10 +848,12 @@
                                      Date segmentStartTime, Date segmentEndTime) {
        try {
            // 查询该车辆正在执行的任务列表
            List<SysTask> activeTasks = sysTaskMapper.selectTaskByVehicleIdAndDate(vehicleId,segmentStartTime,segmentEndTime);
          String segmentStartTimeStr =  DateUtils.formatDate(segmentStartTime, "yyyy-MM-dd HH:mm:ss");
          String segmentEndTimeStr =  DateUtils.formatDate(segmentEndTime, "yyyy-MM-dd HH:mm:ss");
            List<SysTask> activeTasks = sysTaskMapper.selectTaskByVehicleIdAndDate(vehicleId,segmentStartTimeStr,segmentEndTimeStr);
            
            if (activeTasks == null || activeTasks.isEmpty()) {
                logger.debug("车辆 {} 在时间段 {} - {} 没有正在执行的任务", vehicleId, segmentStartTime, segmentEndTime);
                logger.info("车辆 {} 在时间段 {} - {} 没有正在执行的任务", vehicleId, segmentStartTime, segmentEndTime);
                return;
            }
            
@@ -859,8 +869,8 @@
                    segment.setTaskId(task.getTaskId());
                    segment.setTaskCode(task.getTaskCode());
                    
                    logger.debug("车辆 {} 时间段 {} - {} 关联任务: taskId={}, taskCode={}",
                               vehicleId, segmentStartTime, segmentEndTime, task.getTaskId(), task.getTaskCode());
//                    logger.debug("车辆 {} 时间段 {} - {} 关联任务: taskId={}, taskCode={}",
//                               vehicleId, segmentStartTime, segmentEndTime, task.getTaskId(), task.getTaskCode());
                    break; // 找到一个匹配的任务即可
                }
            }
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
@@ -4,6 +4,7 @@
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
@@ -11,6 +12,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import com.ruoyi.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -115,27 +117,33 @@
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            Date dayEnd = calendar.getTime();
            
            String dayStartStr=DateUtils.formatDate(dayStart, DateUtils.YYYY_MM_DD_HH_MM_SS);
            String dayEndStr=DateUtils.formatDate(dayEnd, DateUtils.YYYY_MM_DD_HH_MM_SS);
            // 2. 查询车辆在该日期的GPS数据(按时间排序)
            List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, dayStart, dayEnd);
            List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, dayStartStr, dayEndStr);
            
            if (gpsList == null || gpsList.isEmpty()) {
//                logger.info("车辆ID: {} 在日期: {} 无GPS数据", vehicleId, statDate);
                logger.info("---> 车辆ID:{} 在日期:{} 无GPS数据", vehicleId, statDate);
                return null;
            }
//            logger.info("车辆ID:{} GPS数据条数:{}", vehicleId, gpsList.size());
//            logger.info("---> 车辆ID:{} GPS数据条数:{}", vehicleId, gpsList.size());
            // 3. 查询车辆在该日期的任务时间区间
            List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
//            logger.info("---> 车辆ID:{} 任务时间区间数:{}", vehicleId, taskIntervals.size());
           List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd).stream().filter(e -> e.getSegmentDistance() != null && e.getSegmentDistance().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
           List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd);
           int totalGpsPoints = mileages.stream()
                .filter(segment -> segment.getGpsPointCount() != null)
                .mapToInt(VehicleGpsSegmentMileage::getGpsPointCount)
                .sum();
//           logger.info("---> 车辆ID:{} 任务时间:{} 里程时间:{}", vehicleId,
//                   taskIntervals.stream().map(e->"开始时间:"+DateUtils.formatDate(e.getStartTime())+",结束时间:"+DateUtils.formatDate(e.getEndTime())).collect(Collectors.joining()),
//                   mileages.stream().map(e->"开始时间:"+DateUtils.formatDate(e.getSegmentStartTime())+",结束时间:"+DateUtils.formatDate(e.getSegmentEndTime())).collect(Collectors.joining()));
            BigDecimal taskDistance = getTaskDistance(taskIntervals,mileages);
//            logger.info("---> 车辆ID:{} 任务总里程:{}", vehicleId, taskDistance);
            MileageCalculation calculation = calculateMileage(gpsList, taskDistance);
//            logger.info("计算出车辆当天总里程,车辆ID:{},总里程:{},任务里程:{}",vehicleId,calculation.totalMileage,calculation.taskMileage);
//            logger.info("---> 计算出车辆当天总里程,车辆ID:{},总里程:{},任务里程:{}",vehicleId,calculation.totalMileage,calculation.taskMileage);
            // 5. 查询或创建统计记录
            VehicleMileageStats stats = vehicleMileageStatsMapper.selectByVehicleIdAndDate(vehicleId, statDate);
            boolean isNew = (stats == null);
@@ -164,7 +172,7 @@
            stats.setTaskMileage(calculation.taskMileage);
            stats.setNonTaskMileage(calculation.nonTaskMileage);
            stats.setTaskRatio(calculation.taskRatio);
            stats.setGpsPointCount(gpsList.size());
            stats.setGpsPointCount(totalGpsPoints);
            stats.setTaskCount(taskIntervals == null ? 0 : taskIntervals.size());
//            logger.info("车辆ID: {} 日期: {} 里程统计完成 - 总里程: {}km, 任务里程: {}km, 非任务里程: {}km, 占比: {}",
@@ -177,14 +185,16 @@
                vehicleMileageStatsMapper.updateVehicleMileageStats(stats);
            }
            
            logger.info("车辆ID: {} 日期: {} 里程统计完成 - 总里程: {}km, 任务里程: {}km, 非任务里程: {}km, 占比: {}",
                       vehicleId, statDate, calculation.totalMileage, calculation.taskMileage,
                       calculation.nonTaskMileage, calculation.taskRatio);
//            if (taskIntervals != null) {
//                logger.info("---> 同步里程完成,车辆ID: {} 日期: {} 里程统计完成 - 总里程: {}km,任务数量:{} 任务里程: {}km, 非任务里程: {}km, 占比: {}",
//                           vehicleId, statDate, calculation.totalMileage,taskIntervals.size(), calculation.taskMileage,
//                           calculation.nonTaskMileage, calculation.taskRatio);
//            }
            
            return stats;
            
        } catch (Exception e) {
            logger.error("计算车辆里程统计失败 - 车辆ID: {}, 日期: {}", vehicleId, statDate, e);
            logger.error("---> 计算车辆里程统计失败 - 车辆ID: {}, 日期: {}", vehicleId, statDate, e);
            throw new RuntimeException("计算里程统计失败: " + e.getMessage());
        }
    }
@@ -200,9 +210,9 @@
            calendar.setTime(statDate);
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            Date startTime = calendar.getTime();
            String startTimeStr = DateUtils.formatDate(startTime,DateUtils.YYYY_MM_DD_HH_MM_SS);
            // 查询所有活跃车辆
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTimeStr);
            
            if (vehicleIds == null || vehicleIds.isEmpty()) {
                logger.info("没有找到活跃车辆");
@@ -219,7 +229,7 @@
                }
            }
            
            logger.info("批量里程统计完成 - 日期: {}, 总车辆数: {}, 成功: {}", statDate, vehicleIds.size(), successCount);
//            logger.info("批量里程统计完成 - 日期: {}, 总车辆数: {}, 成功: {}", statDate, vehicleIds.size(), successCount);
            return successCount;
            
        } catch (Exception e) {
@@ -231,7 +241,12 @@
    private BigDecimal calculateTotalMileage(List<VehicleGpsSegmentMileage> mileages) {
        if (mileages == null || mileages.isEmpty()) {
            return BigDecimal.ZERO;
        }
        return mileages.stream()
            .filter(mileage -> mileage.getSegmentDistance() != null) // 过滤掉距离为null的分段
            .map(mileage -> mileage.getSegmentDistance())
            .reduce(BigDecimal.ZERO, BigDecimal::add);
@@ -310,7 +325,8 @@
    //计算任务时间段内的里程,应该拿到该任务在工作时间段里的分段距离然后相加
    private List<VehicleGpsSegmentMileage> getTaskDistanceMileage(Long vehicleId, Date segmentStart, Date segmentEnd) {
        return segmentMileageMapper.selectSegmentsByDateRange(vehicleId, segmentStart, segmentEnd);
        List<VehicleGpsSegmentMileage> mileages = segmentMileageMapper.selectSegmentsByDateRange(vehicleId, segmentStart, segmentEnd);
        return mileages != null ? mileages : new ArrayList<>();
    }
    /**
@@ -332,7 +348,9 @@
        // 遍历所有分段里程数据
        for (VehicleGpsSegmentMileage segment : segmentMileages) {
            // 只处理有关联任务ID且有距离数据的分段
//            if (segment.getTaskId() == null || segment.getSegmentDistance() == null) {
//                continue;
//            }
            // 检查该分段是否与任何任务时间段重叠
            Date segmentStart = segment.getSegmentStartTime();
@@ -433,8 +451,6 @@
    @Override
    public VehicleMileageStats aggregateFromSegmentMileage(Long vehicleId, Date statDate) {
        try {
            calculateAndSaveMileageStats(vehicleId, statDate);
            //TODO
            // 1. 获取统计日期的开始和结束时间
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(statDate);
@@ -456,18 +472,23 @@
            }
            List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
            Integer taskCount = taskIntervals.size();
            List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd);
            Integer totalGpsPoints = mileages.stream()
            Integer taskCount = taskIntervals != null ? taskIntervals.size() : 0;
            logger.info("车辆ID: {} 在日期: {} 有 {} 个任务", vehicleId, statDate, taskCount);
            List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd).stream().filter(e -> e.getSegmentDistance() != null && e.getSegmentDistance().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            logger.info("车辆ID: {} 在日期: {} 有 {} 个分段里程数据", vehicleId, statDate, mileages.size());
            Integer totalGpsPoints = mileages != null ? mileages.stream()
                .filter(segment -> segment.getGpsPointCount() != null)
                .mapToInt(VehicleGpsSegmentMileage::getGpsPointCount)
                .sum();
                .sum() : 0;
            BigDecimal taskDistance = getTaskDistance(taskIntervals,mileages);
            BigDecimal totalDistance = calculateTotalMileage(segments);
            BigDecimal nonTaskDistance = totalDistance.subtract(taskDistance);
            BigDecimal taskRatio = taskDistance.divide(totalDistance, 4, RoundingMode.HALF_UP);
            // 防止除零错误
            BigDecimal taskRatio = BigDecimal.ZERO;
            if (totalDistance != null && totalDistance.compareTo(BigDecimal.ZERO) > 0) {
                taskRatio = taskDistance.divide(totalDistance, 4, RoundingMode.HALF_UP);
            }
            // 3. 汇总里程数据
@@ -534,8 +555,10 @@
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            Date startTime = calendar.getTime();
            
            String startTimeStr = DateUtils.formatDate(startTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
            // 查询所有活跃车辆
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTimeStr);
            
            if (vehicleIds == null || vehicleIds.isEmpty()) {
                logger.info("没有找到活跃车辆");
ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -188,14 +188,13 @@
    <select id="selectTaskByVehicleIdAndDate" resultMap="SysTaskResult">
        select tv.task_id, t.actual_start_time,
        IFNULL(t.actual_end_time, NOW()) as t.actual_end_time
        IFNULL(t.actual_end_time, NOW()) as actual_end_time
        from sys_task_vehicle tv
        inner join sys_task t on tv.task_id = t.task_id
        where tv.vehicle_id = #{vehicleId}
        and t.del_flag = '0'
        and (
        (t.actual_end_time is not null and t.actual_start_time > #{startTime} and t.actual_end_time &lt; #{endTime} )
        or (t.actual_end_time is null and t.actual_start_time > ${endTime} )
        (t.actual_start_time &lt;= #{endTime} and (t.actual_end_time is null or t.actual_end_time &gt;= #{startTime}))
        )
        order by t.actual_start_time
    </select>
ruoyi-system/src/main/resources/mapper/system/VehicleGpsSegmentMileageMapper.xml
@@ -64,8 +64,10 @@
    <select id="selectSegmentsByDateRange" resultMap="VehicleGpsSegmentMileageResult">
        <include refid="selectVehicleGpsSegmentMileageVo"/>
        WHERE vehicle_id = #{vehicleId}
          AND segment_start_time &gt;= #{startDate}
          AND segment_end_time &lt;= #{endDate}
          AND segment_start_time &lt;= #{endDate}
          AND segment_end_time &gt;= #{startDate}
          AND segment_start_time IS NOT NULL
          AND segment_end_time IS NOT NULL
        ORDER BY segment_start_time
    </select>
    
ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
@@ -94,10 +94,8 @@
        inner join sys_task t on tv.task_id = t.task_id
        where tv.vehicle_id = #{vehicleId}
          and t.del_flag = '0'
          and (
                (t.actual_end_time is not null and t.actual_start_time &gt; #{startTime} and t.actual_end_time &lt; #{endTime})
                or (t.actual_end_time is null and t.actual_start_time &gt; #{startTime})
        )
          and (t.actual_start_time &lt;= #{endTime} and (t.actual_end_time is null or t.actual_end_time &gt;= #{startTime}))
        order by t.actual_start_time
    </select>
        
sql/qy_wechat_config.sql
@@ -14,6 +14,6 @@
('企业微信服务启用状态', 'qy_wechat.enable', 'false', 'Y', 'admin', SYSDATE(), '', NULL, '企业微信服务是否启用,true-启用,false-禁用'),
('企业微信CorpID', 'qy_wechat.corp_id', 'wx248505bfbab6d0c1', 'N', 'admin', SYSDATE(), '', NULL, '企业微信企业ID'),
('企业微信CorpSecret', 'qy_wechat.corp_secret', '2MCilqWYC0FWjOQ894sbb-s7Lb5sVH4HHuJgOsd9l1k', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用密钥'),
('企业微信AgentId', 'qy_wechat.agent_id', '1000002', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用AgentId');
('企业微信AgentId', 'qy_wechat.agent_id', '21', 'N', 'admin', SYSDATE(), '', NULL, '企业微信应用AgentId');
COMMIT;