From 8cb5d3440208a3be3e772e65f1bd0ec63031ba62 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期三, 17 十二月 2025 08:37:14 +0800
Subject: [PATCH] feat: 增加服务单派发通知
---
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