From 08f95b2f159b56fa3bd4f4b348855989de8aa456 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期四, 18 十二月 2025 21:48:18 +0800
Subject: [PATCH] feat: vehicle

---
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java |  616 +++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 430 insertions(+), 186 deletions(-)

diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
index 45fe76f..9936086 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
+++ b/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;
@@ -96,49 +98,82 @@
     @Override
     public int batchCalculateSegmentMileage(Date startTime, Date endTime) {
         try {
-            // 鏌ヨ鎵�鏈夋椿璺冭溅杈�
-            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
+//            logger.info("寮�濮嬫壒閲忚绠桮PS鍒嗘閲岀▼ - 鏃堕棿鑼冨洿: {} 鍒� {}", 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);
+            // 鏌ヨ鍦ㄦ寚瀹氭椂闂磋寖鍥村唴鏈塆PS鏁版嵁鐨勬墍鏈夎溅杈嗭紙娣诲姞鎱QL鐩戞帶锛�
+            long startQueryTime = System.currentTimeMillis();
+            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTimeStr);
+            long queryTime = System.currentTimeMillis() - startQueryTime;
+            
+            // 鎱㈡煡璇㈣鍛婏紙瓒呰繃1绉掞級
+            if (queryTime > 1000) {
+                logger.warn("鏌ヨ娲昏穬杞﹁締ID鑰楁椂杩囬暱: {}ms, 寮�濮嬫椂闂�: {}, 寤鸿妫�鏌� tb_vehicle_gps 琛ㄧ殑绱㈠紩锛堥渶瑕� vehicle_id 鍜� collect_time 缁勫悎绱㈠紩锛�", 
+                    queryTime, startTime);
+            }
+            logger.info("鏌ヨ鍒� {} 杈嗘椿璺冭溅杈嗭紝鏌ヨ鑰楁椂: {}ms", vehicleIds != null ? vehicleIds.size() : 0, queryTime);
             
             if (vehicleIds == null || vehicleIds.isEmpty()) {
                 logger.info("娌℃湁鎵惧埌娲昏穬杞﹁締");
                 return 0;
             }
             
+            logger.info("鎵惧埌 {} 杈嗘椿璺冭溅杈嗭紝寮�濮嬮�愯締璁$畻...", vehicleIds.size());
+            
             int successCount = 0;
-            for (Long vehicleId : vehicleIds) {
+            int failedCount = 0;
+            
+            // 閫愯締璁$畻锛屽寘鍚敊璇鐞嗗拰閲嶈瘯鏈哄埗
+            for (int i = 0; i < vehicleIds.size(); i++) {
+                Long vehicleId = vehicleIds.get(i);
                 try {
+//                    logger.info("姝e湪澶勭悊杞﹁締 {} ({}/{})", vehicleId, i + 1, vehicleIds.size());
+                    
                     int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime);
                     if (segmentCount > 0) {
                         successCount++;
+//                        logger.info("杞﹁締 {} 璁$畻鎴愬姛锛岀敓鎴� {} 涓垎娈佃褰�", vehicleId, segmentCount);
+                    } else {
+//                        logger.debug("杞﹁締 {} 鏃犳湁鏂扮殑GPS鍒嗘鏁版嵁", vehicleId);
                     }
                 } catch (Exception e) {
-                    logger.error("璁$畻杞﹁締 {} 鐨勫垎娈甸噷绋嬪け璐�", vehicleId, e);
+                    failedCount++;
+                    logger.error("璁$畻杞﹁締 {} 鐨勫垎娈甸噷绋嬪け璐� ({}/{})", vehicleId, i + 1, vehicleIds.size(), e);
+                    
+                    // 涓嶄腑鏂暣涓壒澶勭悊锛岀户缁鐞嗕笅涓�杈嗚溅
+                }
+                
+                // 姣忓鐞�10杈嗚溅杈撳嚭涓�娆¤繘搴�
+                if ((i + 1) % 10 == 0) {
+                    logger.info("鎵归噺璁$畻杩涘害: {}/{}, 鎴愬姛: {}, 澶辫触: {}",
+                               i + 1, vehicleIds.size(), successCount, failedCount);
                 }
             }
             
-            logger.info("鎵归噺鍒嗘閲岀▼璁$畻瀹屾垚 - 鏃堕棿鑼冨洿: {} 鍒� {}, 鎬昏溅杈嗘暟: {}, 鎴愬姛: {}", 
-                       startTime, endTime, vehicleIds.size(), successCount);
+            logger.info("鎵归噺鍒嗘閲岀▼璁$畻瀹屾垚 - 鏃堕棿鑼冨洿: {} 鍒� {}, 鎬昏溅杈嗘暟: {}, 鎴愬姛: {}, 澶辫触: {}",
+                       startTime, endTime, vehicleIds.size(), successCount, failedCount);
             return successCount;
             
         } catch (Exception e) {
-            logger.error("鎵归噺璁$畻鍒嗘閲岀▼澶辫触", e);
-            throw new RuntimeException("鎵归噺璁$畻澶辫触: " + e.getMessage());
+            logger.error("鎵归噺璁$畻鍒嗘閲岀▼澶辫触 - 鏃堕棿鑼冨洿: {} 鍒� {}", startTime, endTime, e);
+            throw new RuntimeException("鎵归噺璁$畻澶辫触: " + e.getMessage(), e);
         }
     }
 
     @Override
     public int compensateCalculation(int lookbackDays) {
         try {
-            // 璁$畻鏃堕棿鑼冨洿
+            // 璁$畻鏃堕棿鑼冨洿锛堝洖婧寚瀹氬ぉ鏁帮級
             Calendar cal = Calendar.getInstance();
             Date endTime = cal.getTime();
             cal.add(Calendar.DAY_OF_MONTH, -lookbackDays);
             Date startTime = cal.getTime();
             
             logger.info("寮�濮嬭ˉ鍋胯绠� - 鍥炴函澶╂暟: {}, 鏃堕棿鑼冨洿: {} 鍒� {}", lookbackDays, startTime, endTime);
-            
+
+            String startTimeStr=DateUtils.formatDate(startTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
             // 鏌ヨ鎵�鏈夋椿璺冭溅杈�
-            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
+            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTimeStr);
             
             if (vehicleIds == null || vehicleIds.isEmpty()) {
                 logger.info("娌℃湁鎵惧埌娲昏穬杞﹁締");
@@ -147,11 +182,13 @@
             
             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);
@@ -162,9 +199,30 @@
                     logger.info("杞﹁締 {} 鍙戠幇 {} 涓湭璁$畻鐨凣PS鐐癸紝寮�濮嬭ˉ鍋胯绠�...", 
                                vehicleId, uncalculatedGps.size());
                     
+                    // 鑾峰彇鏈绠桮PS鏁版嵁鐨勬椂闂磋寖鍥�
+                    Date uncalculatedStartTime = parseDateTime(uncalculatedGps.get(0).getCollectTime());
+                    Date uncalculatedEndTime = parseDateTime(uncalculatedGps.get(uncalculatedGps.size() - 1).getCollectTime());
+                    
+                    // 鏌ユ壘璇ユ椂闂存涔嬪墠鏈�鍚庝竴涓凡澶勭悊鐨凣PS鍧愭爣ID
+                    Long lastCalculatedGpsId = segmentMileageMapper.selectLastCalculatedGpsId(vehicleId, uncalculatedStartTime);
+                    
+                    if (lastCalculatedGpsId != null) {
+                        logger.info("杞﹁締 {} 鎵惧埌鏈�鍚庝竴涓凡澶勭悊鐨凣PS鐐笽D: {}锛屽皢涓庢湭澶勭悊鏁版嵁涓�璧疯绠�", vehicleId, lastCalculatedGpsId);
+                        
+                        // 灏嗘渶鍚庝竴涓凡澶勭悊鐨凣PS鐐瑰姞鍏ュ垪琛ㄥ墠闈紝浣滀负鍓嶇疆鐐�
+                        VehicleGps lastCalculatedGps = vehicleGpsMapper.selectVehicleGpsById(lastCalculatedGpsId);
+                        if (lastCalculatedGps != null) {
+                            uncalculatedGps.add(0, lastCalculatedGps); // 鎻掑叆鍒板垪琛ㄦ渶鍓嶉潰
+                            logger.info("宸插皢GPS鐐� {} 浣滀负鍓嶇疆鐐瑰姞鍏ヨ绠楀垪琛�", lastCalculatedGpsId);
+                        }
+                    } else {
+                        logger.info("杞﹁締 {} 娌℃湁鎵惧埌宸插鐞嗙殑鍓嶇疆 GPS鐐癸紝浠庣涓�涓湭澶勭悊鐐瑰紑濮嬭绠�", vehicleId);
+                    }
+                    
                     // 閲嶆柊璁$畻璇ヨ溅杈嗗湪璇ユ椂闂磋寖鍥寸殑鍒嗘閲岀▼
                     // 娉ㄦ剰锛氳繖閲屼細閲嶆柊璁$畻鏁翠釜鏃堕棿鑼冨洿锛岀‘淇濊竟缂樿妭鐐硅姝g‘澶勭悊
-                    int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime);
+                    int segmentCount = calculateVehicleSegmentMileageWithGpsList(
+                        vehicleId, uncalculatedGps, uncalculatedStartTime, uncalculatedEndTime);
                     
                     if (segmentCount > 0) {
                         successCount++;
@@ -188,176 +246,57 @@
     @Override
     public int calculateVehicleSegmentMileage(Long vehicleId, Date startTime, Date endTime) {
         try {
-            // 鑾峰彇閰嶇疆鐨勬椂闂撮棿闅旓紙鍒嗛挓锛�
-            int segmentMinutes = configService.selectConfigByKey("gps.mileage.segment.minutes") != null 
-                ? Integer.parseInt(configService.selectConfigByKey("gps.mileage.segment.minutes")) 
-                : 5;
-            
-            // 鑾峰彇璁$畻鏂瑰紡閰嶇疆
-            String calculateMethod = configService.selectConfigByKey("gps.mileage.calculate.method");
-            if (calculateMethod == null || calculateMethod.isEmpty()) {
-                calculateMethod = "tianditu";
-            }
-            
-            // 鑾峰彇鏄惁璺宠繃宸茶绠桮PS鐐圭殑閰嶇疆
-            String skipCalculatedConfig = configService.selectConfigByKey("gps.mileage.skip.calculated");
-            boolean skipCalculated = skipCalculatedConfig == null || "true".equalsIgnoreCase(skipCalculatedConfig);
-            
             // 鏌ヨ杞﹁締鍦ㄦ椂闂磋寖鍥村唴鐨凣PS鏁版嵁
-            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: {} 鏌ヨ鍒� {} 鏉PS鏁版嵁", vehicleId, gpsList.size());
+//            logger.info("杞﹁締ID: {} 鏌ヨ鍒� {} 鏉PS鏁版嵁 startTime:{},endTime:{}", vehicleId, gpsList.size(),startTime,endTime);
             
-            // 鎸夋椂闂存鍒嗙粍GPS鏁版嵁
-            Map<Date, List<VehicleGps>> segmentedData = segmentGpsDataByTime(gpsList, segmentMinutes);
+            return calculateVehicleSegmentMileageWithGpsList(vehicleId, gpsList, startTime, endTime);
             
-            int savedCount = 0;
-            VehicleGps previousSegmentLastPoint = null; // 璁板綍涓婁竴涓椂闂存鐨勬渶鍚庝竴涓偣
-            
-            // 閬嶅巻姣忎釜鏃堕棿娈碉紝璁$畻閲岀▼
-            for (Map.Entry<Date, List<VehicleGps>> entry : segmentedData.entrySet()) {
-                Date segmentStartTime = entry.getKey();
-                List<VehicleGps> segmentGpsList = entry.getValue();
-                
-                if (segmentGpsList.size() < 2) {
-                    // 濡傛灉鏈鍙湁1涓偣锛屼絾鏈変笂涓�娈电殑鏈�鍚庝竴涓偣锛屼粛鍙绠楄法娈佃窛绂�
-                    if (segmentGpsList.size() == 1 && previousSegmentLastPoint != null) {
-                        // 淇濈暀褰撳墠鐐逛綔涓轰笅涓�娈电殑鍓嶇疆鐐癸紝浣嗕笉鍒涘缓璁板綍
-                        previousSegmentLastPoint = segmentGpsList.get(0);
-                    }
-                    continue; // 鑷冲皯闇�瑕�2涓偣鎵嶈兘璁$畻璺濈
-                }
-                
-                // 妫�鏌ユ槸鍚﹀凡瀛樺湪璇ユ椂闂存鐨勮褰�
-                VehicleGpsSegmentMileage existing = segmentMileageMapper.selectByVehicleIdAndTime(vehicleId, segmentStartTime);
-                if (existing != null) {
-                    logger.debug("杞﹁締 {} 鏃堕棿娈� {} 鐨勫垎娈甸噷绋嬪凡瀛樺湪锛岃烦杩�", vehicleId, segmentStartTime);
-                    // 鏇存柊涓婁竴娈垫渶鍚庝竴涓偣
-                    previousSegmentLastPoint = segmentGpsList.get(segmentGpsList.size() - 1);
-                    continue;
-                }
-                
-                // 璁$畻鏃堕棿娈电殑缁撴潫鏃堕棿
-                Calendar cal = Calendar.getInstance();
-                cal.setTime(segmentStartTime);
-                cal.add(Calendar.MINUTE, segmentMinutes);
-                Date segmentEndTime = cal.getTime();
-                
-                // 璁$畻璇ユ椂闂存鐨勯噷绋嬶紙鍖呮嫭璺ㄦ璺濈锛�
-                BigDecimal distance = calculateSegmentDistanceWithGap(segmentGpsList, calculateMethod, previousSegmentLastPoint);
-                
-                // 鏀堕泦GPS ID鍒楄〃锛堝寘鎷笂涓�娈电殑鏈�鍚庝竴涓偣锛屽洜涓鸿法娈甸棿闅欒窛绂讳篃鐢ㄥ埌浜嗗畠锛�
-                List<Long> gpsIdList = new ArrayList<>();
-                // 濡傛灉鏈変笂涓�娈电殑鏈�鍚庝竴涓偣锛屽厛娣诲姞瀹冪殑ID
-                if (previousSegmentLastPoint != null && previousSegmentLastPoint.getGpsId() != null) {
-                    gpsIdList.add(previousSegmentLastPoint.getGpsId());
-                }
-                // 鍐嶆坊鍔犲綋鍓嶆鐨勬墍鏈塆PS鐐笽D
-                for (VehicleGps gps : segmentGpsList) {
-                    if (gps.getGpsId() != null) {
-                        gpsIdList.add(gps.getGpsId());
-                    }
-                }
-                String gpsIds = gpsIdList.stream()
-                    .map(String::valueOf)
-                    .collect(java.util.stream.Collectors.joining(","));
-                
-                // 鍒涘缓鍒嗘閲岀▼璁板綍
-                VehicleGpsSegmentMileage segment = new VehicleGpsSegmentMileage();
-                segment.setVehicleId(vehicleId);
-                
-                // 浠嶨PS鏁版嵁鎴栬溅杈嗚〃鑾峰彇杞︾墝鍙�
-                String vehicleNo = segmentGpsList.get(0).getVehicleNo();
-                if (vehicleNo == null || vehicleNo.trim().isEmpty()) {
-                    // GPS鏁版嵁涓病鏈夎溅鐗屽彿锛屼粠杞﹁締琛ㄦ煡璇�
-                    VehicleInfo vehicleInfo = vehicleInfoMapper.selectVehicleInfoById(vehicleId);
-                    if (vehicleInfo != null) {
-                        vehicleNo = vehicleInfo.getVehicleNo();
-                    }
-                }
-                segment.setVehicleNo(vehicleNo);
-                
-                segment.setSegmentStartTime(segmentStartTime);
-                segment.setSegmentEndTime(segmentEndTime);
-                
-                // 璧风偣鍧愭爣
-                VehicleGps firstPoint = segmentGpsList.get(0);
-                segment.setStartLongitude(BigDecimal.valueOf(firstPoint.getLongitude()));
-                segment.setStartLatitude(BigDecimal.valueOf(firstPoint.getLatitude()));
-                
-                // 缁堢偣鍧愭爣
-                VehicleGps lastPoint = segmentGpsList.get(segmentGpsList.size() - 1);
-                segment.setEndLongitude(BigDecimal.valueOf(lastPoint.getLongitude()));
-                segment.setEndLatitude(BigDecimal.valueOf(lastPoint.getLatitude()));
-                
-                segment.setSegmentDistance(distance);
-                segment.setGpsPointCount(gpsIdList.size()); // GPS鐐规暟锛氬寘鎷竟缂樼偣 + 褰撳墠娈电殑鐐�
-                segment.setGpsIds(gpsIds); // 璁剧疆GPS ID鍒楄〃
-                segment.setCalculateMethod(calculateMethod);
-                
-                // 鏌ヨ骞跺叧鑱旀鍦ㄦ墽琛岀殑浠诲姟
-                associateActiveTask(segment, vehicleId, segmentStartTime, segmentEndTime);
-                
-                // 淇濆瓨鍒版暟鎹簱
-                segmentMileageMapper.insertVehicleGpsSegmentMileage(segment);
-                
-                // 鏇存柊涓婁竴娈垫渶鍚庝竴涓偣锛屼緵涓嬩竴娈典娇鐢�
-                previousSegmentLastPoint = segmentGpsList.get(segmentGpsList.size() - 1);
-                
-                // 璁板綍宸茶绠楃殑GPS鐐瑰埌鐘舵�佽〃锛堝鏋滃紑鍚簡閲嶅璁$畻鎺у埗锛�
-                if (skipCalculated && segment.getSegmentId() != null) {
-                    for (Long gpsId : gpsIdList) {
-                        try {
-                            segmentMileageMapper.insertGpsCalculated(gpsId, segment.getSegmentId(), vehicleId);
-                        } catch (Exception e) {
-                            // 蹇界暐閲嶅閿紓甯革紝缁х画澶勭悊
-                            logger.debug("璁板綍GPS璁$畻鐘舵�佸け璐ワ紝鍙兘宸插瓨鍦�: gpsId={}", gpsId);
-                        }
-                    }
-                }
-                
-                savedCount++;
-                
-                logger.debug("杞﹁締 {} 鏃堕棿娈� {} 鍒� {} 閲岀▼: {}km, GPS鐐规暟: {}, GPS IDs: {}", 
-                           vehicleId, segmentStartTime, segmentEndTime, distance, segmentGpsList.size(), 
-                           gpsIds.length() > 50 ? gpsIds.substring(0, 50) + "..." : gpsIds);
+        } catch (Exception e) {
+            logger.error("璁$畻杞﹁締 {} 鍒嗘閲岀▼澶辫触", vehicleId, e);
+            throw new RuntimeException("璁$畻鍒嗘閲岀▼澶辫触: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鏍规嵁鎻愪緵鐨凣PS鍒楄〃璁$畻杞﹁締鍒嗘閲岀▼
+     * @param vehicleId 杞﹁締ID
+     * @param gpsList GPS鍒楄〃锛堝凡鎸夋椂闂存帓搴忥級
+     * @param startTime 璧峰鏃堕棿
+     * @param endTime 缁撴潫鏃堕棿
+     * @return 鐢熸垚鐨勫垎娈垫暟閲�
+     */
+    private int calculateVehicleSegmentMileageWithGpsList(Long vehicleId, List<VehicleGps> gpsList, 
+                                                           Date startTime, Date endTime) {
+        try {
+            // 楠岃瘉杈撳叆鏁版嵁
+            if (gpsList == null || gpsList.isEmpty()) {
+                logger.debug("杞﹁締ID: {} 鍦ㄦ椂闂磋寖鍥� {} 鍒� {} 鍐呮棤GPS鏁版嵁", vehicleId, startTime, endTime);
+                return 0;
             }
             
-            logger.info("杞﹁締 {} 璁$畻瀹屾垚锛屼繚瀛樹簡 {} 涓椂闂存鐨勯噷绋嬫暟鎹�", vehicleId, savedCount);
+            // 鍔犺浇閰嶇疆鍙傛暟
+            MileageCalculationConfig config = loadMileageCalculationConfig();
             
-            // 鑷姩瑙﹀彂姹囨�荤敓鎴愭瘡鏃ョ粺璁★紙濡傛灉鏈夋暟鎹淇濆瓨锛�
+            // 鎸夋椂闂存鍒嗙粍GPS鏁版嵁
+            Map<Date, List<VehicleGps>> segmentedData = segmentGpsDataByTime(gpsList, config.segmentMinutes);
+            
+            // 澶勭悊姣忎釜鏃堕棿娈靛苟璁$畻閲岀▼
+            int savedCount = processSegmentedGpsData(vehicleId, segmentedData, config);
+            
+//            logger.info("杞﹁締 {} 璁$畻瀹屾垚锛屼繚瀛樹簡 {} 涓椂闂存鐨勯噷绋嬫暟鎹�", vehicleId, savedCount);
+            
+            // 鑷姩瑙﹀彂姣忔棩缁熻姹囨��
             if (savedCount > 0) {
-                try {
-                    // 鑾峰彇娑夊強鐨勬棩鏈熻寖鍥达紝瑙﹀彂姹囨��
-                    Set<Date> affectedDates = new HashSet<>();
-                    Calendar cal = Calendar.getInstance();
-                    
-                    for (Map.Entry<Date, List<VehicleGps>> entry : segmentedData.entrySet()) {
-                        cal.setTime(entry.getKey());
-                        cal.set(Calendar.HOUR_OF_DAY, 0);
-                        cal.set(Calendar.MINUTE, 0);
-                        cal.set(Calendar.SECOND, 0);
-                        cal.set(Calendar.MILLISECOND, 0);
-                        affectedDates.add(cal.getTime());
-                    }
-                    
-                    // 瀵规瘡涓秹鍙婄殑鏃ユ湡锛岃Е鍙戞眹鎬�
-                    for (Date statDate : affectedDates) {
-                        try {
-                            mileageStatsService.aggregateFromSegmentMileage(vehicleId, statDate);
-                            logger.info("杞﹁締 {} 鏃ユ湡 {} 鐨勭粺璁℃暟鎹凡鑷姩姹囨�荤敓鎴�", vehicleId, statDate);
-                        } catch (Exception e) {
-                            logger.error("杞﹁締 {} 鏃ユ湡 {} 鑷姩姹囨�荤粺璁″け璐�", vehicleId, statDate, e);
-                        }
-                    }
-                } catch (Exception e) {
-                    logger.error("瑙﹀彂鑷姩姹囨�诲け璐�", e);
-                }
+                triggerDailyMileageAggregation(vehicleId, segmentedData);
             }
             
             return savedCount;
@@ -366,6 +305,305 @@
             logger.error("璁$畻杞﹁締 {} 鍒嗘閲岀▼澶辫触", vehicleId, e);
             throw new RuntimeException("璁$畻鍒嗘閲岀▼澶辫触: " + e.getMessage());
         }
+    }
+    
+    /**
+     * 鍔犺浇閲岀▼璁$畻閰嶇疆鍙傛暟
+     */
+    private MileageCalculationConfig loadMileageCalculationConfig() {
+        MileageCalculationConfig config = new MileageCalculationConfig();
+        
+        // 鑾峰彇鏃堕棿闂撮殧閰嶇疆锛堝垎閽燂級
+        config.segmentMinutes = configService.selectConfigByKey("gps.mileage.segment.minutes") != null 
+            ? Integer.parseInt(configService.selectConfigByKey("gps.mileage.segment.minutes")) 
+            : 5;
+        
+        // 鑾峰彇璁$畻鏂瑰紡閰嶇疆
+        config.calculateMethod = configService.selectConfigByKey("gps.mileage.calculate.method");
+        if (config.calculateMethod == null || config.calculateMethod.isEmpty()) {
+            config.calculateMethod = "tianditu";
+        }
+        
+        // 鑾峰彇鏄惁璺宠繃宸茶绠桮PS鐐圭殑閰嶇疆
+        String skipCalculatedConfig = configService.selectConfigByKey("gps.mileage.skip.calculated");
+        config.skipCalculated = skipCalculatedConfig == null || "true".equalsIgnoreCase(skipCalculatedConfig);
+//        logger.info("鎺у埗璺宠繃閲嶅璁$畻鏍囪瘑: {}", config.skipCalculated);
+        
+        return config;
+    }
+    
+    /**
+     * 澶勭悊鍒嗘鍚庣殑GPS鏁版嵁骞惰绠楅噷绋�
+     * @param vehicleId 杞﹁締ID
+     * @param segmentedData 鍒嗘鍚庣殑GPS鏁版嵁
+     * @param config 璁$畻閰嶇疆
+     * @return 鎴愬姛淇濆瓨鐨勫垎娈垫暟閲�
+     */
+    private int processSegmentedGpsData(Long vehicleId, Map<Date, List<VehicleGps>> segmentedData, 
+                                         MileageCalculationConfig config) {
+        int savedCount = 0;
+        VehicleGps previousSegmentLastPoint = null; // 璁板綍涓婁竴涓椂闂存鐨勬渶鍚庝竴涓偣
+        
+        // 閬嶅巻姣忎釜鏃堕棿娈碉紝璁$畻閲岀▼
+        for (Map.Entry<Date, List<VehicleGps>> entry : segmentedData.entrySet()) {
+            Date segmentStartTime = entry.getKey();
+            List<VehicleGps> segmentGpsList = entry.getValue();
+            
+            // 鏍¢獙褰撳墠鏃堕棿娈垫暟鎹�
+            if (!isSegmentValidForCalculation(segmentGpsList, previousSegmentLastPoint, vehicleId, segmentStartTime)) {
+                // 淇濈暀褰撳墠鐐逛綔涓轰笅涓�娈电殑鍓嶇疆鐐癸紙濡傛灉鏈夌殑璇濓級
+                if (!segmentGpsList.isEmpty()) {
+                    previousSegmentLastPoint = segmentGpsList.get(0);
+                }
+                continue;
+            }
+            
+            // 妫�鏌ユ槸鍚﹀凡瀛樺湪璇ユ椂闂存鐨勮褰�
+            if (isSegmentAlreadyCalculated(vehicleId, segmentStartTime, segmentGpsList)) {
+                previousSegmentLastPoint = segmentGpsList.get(segmentGpsList.size() - 1);
+                continue;
+            }
+            
+            // 璁$畻骞朵繚瀛樺垎娈甸噷绋�
+            boolean success = calculateAndSaveSegment(vehicleId, segmentStartTime, segmentGpsList, 
+                                                       previousSegmentLastPoint, config);
+            if (success) {
+                savedCount++;
+            }
+            
+            // 鏇存柊涓婁竴娈垫渶鍚庝竴涓偣锛屼緵涓嬩竴娈典娇鐢�
+            previousSegmentLastPoint = segmentGpsList.get(segmentGpsList.size() - 1);
+        }
+        
+        return savedCount;
+    }
+    
+    /**
+     * 鏍¢獙鏃堕棿娈垫暟鎹槸鍚︽湁鏁�
+     */
+    private boolean isSegmentValidForCalculation(List<VehicleGps> segmentGpsList, 
+                                                  VehicleGps previousSegmentLastPoint,
+                                                  Long vehicleId, Date segmentStartTime) {
+        // 濡傛灉褰撳墠娈垫病鏈塆PS鐐癸紝璺宠繃
+        if (segmentGpsList == null || segmentGpsList.isEmpty()) {
+            return false;
+        }
+        
+        // 濡傛灉鏈鍙湁1涓偣锛屼笖娌℃湁涓婁竴娈电殑鏈�鍚庝竴涓偣锛屾棤娉曡绠楄窛绂�
+        if (segmentGpsList.size() == 1 && previousSegmentLastPoint == null) {
+//            logger.debug("杞﹁締 {} 鏃堕棿娈� {} 鍙湁1涓狦PS鐐逛笖鏃犲墠缃偣锛屾殏瀛樺緟涓嬩竴娈佃绠�", vehicleId, segmentStartTime);
+            return false;
+        }
+        
+        return true;
+    }
+    
+    /**
+     * 妫�鏌ユ椂闂存鏄惁宸茶璁$畻
+     */
+    private boolean isSegmentAlreadyCalculated(Long vehicleId, Date segmentStartTime, List<VehicleGps> segmentGpsList) {
+        VehicleGpsSegmentMileage existing = segmentMileageMapper.selectByVehicleIdAndTime(vehicleId, segmentStartTime);
+        if (existing != null) {
+            logger.debug("杞﹁締 {} 鏃堕棿娈� {} 鐨勫垎娈甸噷绋嬪凡瀛樺湪锛岃烦杩�", vehicleId, segmentStartTime);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * 璁$畻骞朵繚瀛樺崟涓椂闂存鐨勯噷绋�
+     */
+    private boolean calculateAndSaveSegment(Long vehicleId, Date segmentStartTime, 
+                                             List<VehicleGps> segmentGpsList,
+                                             VehicleGps previousSegmentLastPoint,
+                                             MileageCalculationConfig config) {
+        try {
+            // 璁$畻鏃堕棿娈电殑缁撴潫鏃堕棿
+            Date segmentEndTime = calculateSegmentEndTime(segmentStartTime, config.segmentMinutes);
+            
+            // 璁$畻璇ユ椂闂存鐨勯噷绋嬶紙鍖呮嫭璺ㄦ璺濈锛�
+            BigDecimal distance = calculateSegmentDistanceWithGap(segmentGpsList, config.calculateMethod, previousSegmentLastPoint);
+            
+            // 鏀堕泦GPS ID鍒楄〃
+            List<Long> gpsIdList = collectGpsIds(segmentGpsList, previousSegmentLastPoint);
+            String gpsIds = gpsIdList.stream()
+                .map(String::valueOf)
+                .collect(java.util.stream.Collectors.joining(","));
+
+            // 鍒涘缓鍒嗘閲岀▼璁板綍
+            VehicleGpsSegmentMileage segment = buildSegmentMileageRecord(
+                vehicleId, segmentStartTime, segmentEndTime, segmentGpsList, 
+                distance, gpsIdList, gpsIds, config.calculateMethod);
+            
+            // 淇濆瓨鍒版暟鎹簱
+//            logger.info("淇濆瓨杞﹁締鍒嗘椂娈甸噷绋嬪埌鏁版嵁搴撲腑,杞﹁締ID: {}, 鏃堕棿娈�: {} 鍒� {}", vehicleId, segmentStartTime, segmentEndTime);
+            segmentMileageMapper.insertVehicleGpsSegmentMileage(segment);
+            
+            // 璁板綍宸茶绠楃殑GPS鐐癸紙濡傛灉寮�鍚簡閲嶅璁$畻鎺у埗锛�
+            if (config.skipCalculated && segment.getSegmentId() != null) {
+                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);
+            
+            return true;
+            
+        } catch (Exception e) {
+            logger.error("淇濆瓨杞﹁締 {} 鏃堕棿娈� {} 鐨勯噷绋嬭褰曞け璐�", vehicleId, segmentStartTime, e);
+            return false;
+        }
+    }
+    
+    /**
+     * 璁$畻鏃堕棿娈电粨鏉熸椂闂�
+     */
+    private Date calculateSegmentEndTime(Date segmentStartTime, int segmentMinutes) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(segmentStartTime);
+        cal.add(Calendar.MINUTE, segmentMinutes);
+        return cal.getTime();
+    }
+    
+    /**
+     * 鏀堕泦GPS ID鍒楄〃锛堝寘鎷墠缃偣锛�
+     */
+    private List<Long> collectGpsIds(List<VehicleGps> segmentGpsList, VehicleGps previousSegmentLastPoint) {
+        List<Long> gpsIdList = new ArrayList<>();
+        
+        // 濡傛灉鏈変笂涓�娈电殑鏈�鍚庝竴涓偣锛屽厛娣诲姞瀹冪殑ID锛堢敤浜庤绠楄法娈佃窛绂伙級
+        if (previousSegmentLastPoint != null && previousSegmentLastPoint.getGpsId() != null) {
+            gpsIdList.add(previousSegmentLastPoint.getGpsId());
+        }
+        
+        // 鍐嶆坊鍔犲綋鍓嶆鐨勬墍鏈塆PS鐐笽D
+        for (VehicleGps gps : segmentGpsList) {
+            if (gps.getGpsId() != null) {
+                gpsIdList.add(gps.getGpsId());
+            }
+        }
+        
+        return gpsIdList;
+    }
+    
+    /**
+     * 鏋勫缓鍒嗘閲岀▼璁板綍瀵硅薄
+     */
+    private VehicleGpsSegmentMileage buildSegmentMileageRecord(Long vehicleId, Date segmentStartTime, 
+                                                                 Date segmentEndTime, List<VehicleGps> segmentGpsList,
+                                                                 BigDecimal distance, List<Long> gpsIdList, 
+                                                                 String gpsIds, String calculateMethod) {
+        VehicleGpsSegmentMileage segment = new VehicleGpsSegmentMileage();
+        segment.setVehicleId(vehicleId);
+        
+        // 鑾峰彇杞︾墝鍙�
+        String vehicleNo = getVehicleNo(vehicleId, segmentGpsList.get(0));
+        segment.setVehicleNo(vehicleNo);
+        
+        // 璁剧疆鏃堕棿鑼冨洿
+        segment.setSegmentStartTime(segmentStartTime);
+        segment.setSegmentEndTime(segmentEndTime);
+        
+        // 璁剧疆璧风偣鍧愭爣
+        VehicleGps firstPoint = segmentGpsList.get(0);
+        segment.setStartLongitude(BigDecimal.valueOf(firstPoint.getLongitude()));
+        segment.setStartLatitude(BigDecimal.valueOf(firstPoint.getLatitude()));
+        
+        // 璁剧疆缁堢偣鍧愭爣
+        VehicleGps lastPoint = segmentGpsList.get(segmentGpsList.size() - 1);
+        segment.setEndLongitude(BigDecimal.valueOf(lastPoint.getLongitude()));
+        segment.setEndLatitude(BigDecimal.valueOf(lastPoint.getLatitude()));
+        
+        // 璁剧疆閲岀▼鏁版嵁
+        segment.setSegmentDistance(distance);
+        segment.setGpsPointCount(gpsIdList.size());
+        segment.setGpsIds(gpsIds);
+        segment.setCalculateMethod(calculateMethod);
+        
+        // 鏌ヨ骞跺叧鑱旀鍦ㄦ墽琛岀殑浠诲姟
+        associateActiveTask(segment, vehicleId, segmentStartTime, segmentEndTime);
+        
+        return segment;
+    }
+    
+    /**
+     * 鑾峰彇杞︾墝鍙�
+     */
+    private String getVehicleNo(Long vehicleId, VehicleGps firstGps) {
+        String vehicleNo = firstGps.getVehicleNo();
+        if (vehicleNo == null || vehicleNo.trim().isEmpty()) {
+            // GPS鏁版嵁涓病鏈夎溅鐗屽彿锛屼粠杞﹁締琛ㄦ煡璇�
+            VehicleInfo vehicleInfo = vehicleInfoMapper.selectVehicleInfoById(vehicleId);
+            if (vehicleInfo != null) {
+                vehicleNo = vehicleInfo.getVehicleNo();
+            }
+        }
+        return vehicleNo;
+    }
+    
+    /**
+     * 璁板綍宸茶绠楃殑GPS鐐瑰埌鐘舵�佽〃
+     */
+    private void recordCalculatedGpsPoints(List<Long> gpsIdList, Long segmentId, Long vehicleId) {
+        for (Long gpsId : gpsIdList) {
+            try {
+                segmentMileageMapper.insertGpsCalculated(gpsId, segmentId, vehicleId);
+            } catch (Exception e) {
+                // 蹇界暐閲嶅閿紓甯革紝缁х画澶勭悊
+                logger.debug("璁板綍GPS璁$畻鐘舵�佸け璐ワ紝鍙兘宸插瓨鍦�: gpsId={}", gpsId);
+            }
+        }
+    }
+    
+    /**
+     * 瑙﹀彂姣忔棩閲岀▼缁熻姹囨��
+     */
+    private void triggerDailyMileageAggregation(Long vehicleId, Map<Date, List<VehicleGps>> segmentedData) {
+        try {
+            // 鑾峰彇娑夊強鐨勬棩鏈熻寖鍥�
+            Set<Date> affectedDates = extractAffectedDates(segmentedData);
+            
+            // 瀵规瘡涓秹鍙婄殑鏃ユ湡锛岃Е鍙戞眹鎬�
+            for (Date statDate : affectedDates) {
+                try {
+                    mileageStatsService.aggregateFromSegmentMileage(vehicleId, statDate);
+//                    logger.info("杞﹁締 {} 鏃ユ湡 {} 鐨勭粺璁℃暟鎹凡鑷姩姹囨�荤敓鎴�", vehicleId, statDate);
+                } catch (Exception e) {
+                    logger.error("杞﹁締 {} 鏃ユ湡 {} 鑷姩姹囨�荤粺璁″け璐�", vehicleId, statDate, e);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("瑙﹀彂鑷姩姹囨�诲け璐�", e);
+        }
+    }
+    
+    /**
+     * 鎻愬彇鍙楀奖鍝嶇殑鏃ユ湡鍒楄〃锛堢敤浜庢眹鎬荤粺璁★級
+     */
+    private Set<Date> extractAffectedDates(Map<Date, List<VehicleGps>> segmentedData) {
+        Set<Date> affectedDates = new HashSet<>();
+        Calendar cal = Calendar.getInstance();
+        
+        for (Map.Entry<Date, List<VehicleGps>> entry : segmentedData.entrySet()) {
+            cal.setTime(entry.getKey());
+            cal.set(Calendar.HOUR_OF_DAY, 0);
+            cal.set(Calendar.MINUTE, 0);
+            cal.set(Calendar.SECOND, 0);
+            cal.set(Calendar.MILLISECOND, 0);
+            affectedDates.add(cal.getTime());
+        }
+        
+        return affectedDates;
+    }
+    
+    /**
+     * 閲岀▼璁$畻閰嶇疆绫�
+     */
+    private static class MileageCalculationConfig {
+        int segmentMinutes;          // 鏃堕棿娈甸棿闅旓紙鍒嗛挓锛�
+        String calculateMethod;      // 璁$畻鏂瑰紡
+        boolean skipCalculated;      // 鏄惁璺宠繃宸茶绠楃殑GPS鐐�
     }
 
     /**
@@ -409,12 +647,13 @@
 
     /**
      * 璁$畻涓�涓椂闂存鍐呯殑鎬婚噷绋嬶紙鍖呮嫭涓庝笂涓�娈电殑闂撮殭璺濈锛�
-     * @param gpsList 褰撳墠鏃堕棿娈电殑GPS鐐瑰垪琛�
+     * @param gpsList 褰撳墠鏃堕棿娈电殑GPS鐐瑰垪琛紙鑷冲皯1涓偣锛�
      * @param calculateMethod 璁$畻鏂瑰紡
      * @param previousLastPoint 涓婁竴涓椂闂存鐨勬渶鍚庝竴涓偣锛堝彲涓簄ull锛�
+     * @return 鎬婚噷绋嬶紙鍏噷锛夛紝淇濈暀3浣嶅皬鏁�
      */
     private BigDecimal calculateSegmentDistanceWithGap(List<VehicleGps> gpsList, String calculateMethod, VehicleGps previousLastPoint) {
-        if (gpsList == null || gpsList.size() < 2) {
+        if (gpsList == null || gpsList.isEmpty()) {
             return BigDecimal.ZERO;
         }
         
@@ -431,18 +670,21 @@
             );
             totalDistance = totalDistance.add(BigDecimal.valueOf(gapDistance));
             
-            logger.debug("璺ㄦ闂撮殭璺濈: {}km (涓婁竴娈垫湯鐐� -> 褰撳墠娈甸鐐�)", 
-                String.format("%.3f", gapDistance));
+//            logger.debug("璺ㄦ闂撮殭璺濈: {}km (涓婁竴娈垫湯鐐� -> 褰撳墠娈甸鐐�)",
+//                String.format("%.3f", gapDistance));
         }
         
-        // 2. 鍐嶈绠楀綋鍓嶆鍐呴儴鐨勮窛绂�
-        BigDecimal segmentInternalDistance;
-        if ("tianditu".equalsIgnoreCase(calculateMethod)) {
-            segmentInternalDistance = calculateDistanceByTianditu(gpsList);
-        } else {
-            segmentInternalDistance = calculateDistanceByHaversine(gpsList);
+        // 2. 鍐嶈绠楀綋鍓嶆鍐呴儴鐨勮窛绂伙紙濡傛灉鏈�2涓垨浠ヤ笂GPS鐐癸級
+        if (gpsList.size() >= 2) {
+            BigDecimal segmentInternalDistance;
+            if ("tianditu".equalsIgnoreCase(calculateMethod)) {
+                segmentInternalDistance = calculateDistanceByTianditu(gpsList);
+            } else {
+                segmentInternalDistance = calculateDistanceByHaversine(gpsList);
+            }
+            totalDistance = totalDistance.add(segmentInternalDistance);
         }
-        totalDistance = totalDistance.add(segmentInternalDistance);
+        // 濡傛灉鍙湁1涓偣锛屾鍐呰窛绂讳负0锛屽彧璁$畻璺ㄦ璺濈
         
         return totalDistance.setScale(3, RoundingMode.HALF_UP);
     }
@@ -606,10 +848,12 @@
                                       Date segmentStartTime, Date segmentEndTime) {
         try {
             // 鏌ヨ璇ヨ溅杈嗘鍦ㄦ墽琛岀殑浠诲姟鍒楄〃
-            List<SysTask> activeTasks = sysTaskMapper.selectActiveTasksByVehicleId(vehicleId);
+          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("杞﹁締 {} 鍦ㄦ椂闂存 {} - {} 娌℃湁姝e湪鎵ц鐨勪换鍔�", vehicleId, segmentStartTime, segmentEndTime);
+                logger.info("杞﹁締 {} 鍦ㄦ椂闂存 {} - {} 娌℃湁姝e湪鎵ц鐨勪换鍔�", vehicleId, segmentStartTime, segmentEndTime);
                 return;
             }
             
@@ -625,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; // 鎵惧埌涓�涓尮閰嶇殑浠诲姟鍗冲彲
                 }
             }

--
Gitblit v1.9.1