From 45d90d1e7ba86286e998d1ac4d2cba8e98cd059b Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期一, 12 一月 2026 20:52:30 +0800
Subject: [PATCH] feat: 优化内存
---
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java | 6
任务状态流转规则说明.md | 255 +++++++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java | 2
app/utils/constant.js | 3
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java | 10
ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml | 2
ruoyi-ui/src/views/system/user/index.vue | 25
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskSyncUtilService.java | 3
app/store/modules/user.js | 8
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java | 28
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java | 3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java | 1
sql/update_task_status_dict.sql | 3
内存优化说明.md | 416 +++++++++++++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/任务车辆关联插入问题修复说明.md | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java | 1
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusPushServiceImpl.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java | 8
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java | 2
ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml | 2
ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java | 4
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java | 19
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusSyncServiceImpl.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleInfoServiceImpl.java | 6
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsConfigServiceImpl.java | 6
ruoyi-admin/src/main/resources/application.yml | 7
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java | 12
sql/optimize_memory_indexes.sql | 282 ++++++++++
内存优化快速检查清单.md | 279 ++++++++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java | 20
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java | 104 ++-
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java | 10
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java | 4
app/pagesTask/detail.vue | 44 +
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java | 6
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java | 10
ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java | 2
ruoyi-admin/src/main/resources/application-dev.yml | 14
41 files changed, 1,497 insertions(+), 122 deletions(-)
diff --git a/app/pagesTask/detail.vue b/app/pagesTask/detail.vue
index 3f64594..fa8e0c4 100644
--- a/app/pagesTask/detail.vue
+++ b/app/pagesTask/detail.vue
@@ -456,9 +456,9 @@
<!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
<view class="action-buttons" v-if="taskDetail">
<!-- 寰呭鐞嗙姸鎬�: 鏄剧ず鍑哄彂銆佸彇娑堛�佸己鍒跺畬鎴� -->
- <template v-if="taskDetail.taskStatus === 'PENDING'">
+ <template v-if="taskDetail.taskStatus === 'PENDING' ">
<button
- v-if="isCurrentUserAssignee()"
+ v-if="canOperateTask()"
class="action-btn primary"
@click="handleDepartAction()"
>
@@ -471,7 +471,7 @@
鍙栨秷
</button>
<button
- v-if="isCurrentUserAssignee() && showForceCompleteFeature()"
+ v-if="canOperateTask() && showForceCompleteFeature()"
class="action-btn force-complete"
@click="showForceCompleteTimeDialog()"
>
@@ -481,7 +481,7 @@
<!-- 鍑哄彂涓姸鎬�: 鏄剧ず宸插埌杈俱�佸己鍒剁粨鏉� -->
<template v-else-if="taskDetail.taskStatus === 'DEPARTING'">
- <template v-if="isCurrentUserAssignee()">
+ <template v-if="canOperateTask()">
<button
class="action-btn primary"
@click="handleTaskAction('arrive')"
@@ -499,7 +499,7 @@
<!-- 宸插埌杈剧姸鎬�: 鏄剧ず宸茶繑绋� -->
<template v-else-if="taskDetail.taskStatus === 'ARRIVED'">
- <template v-if="isCurrentUserAssignee()">
+ <template v-if="canOperateTask()">
<button
class="action-btn primary"
@click="handleTaskAction('return')"
@@ -511,13 +511,32 @@
<!-- 杩旂▼涓姸鎬�: 鏄剧ず宸插畬鎴� -->
<template v-else-if="taskDetail.taskStatus === 'RETURNING'">
- <template v-if="isCurrentUserAssignee()">
+ <template v-if="canOperateTask()">
<button
class="action-btn primary"
@click="handleTaskAction('complete')"
>
宸插畬鎴�
</button>
+ </template>
+ </template>
+
+ <!-- 澶勭悊涓姸鎬�: 鏄剧ず寮哄埗瀹屾垚銆佸彇娑� -->
+ <template v-else-if="taskDetail.taskStatus === 'IN_PROGRESS'">
+ <template v-if="canOperateTask()">
+ <button
+ class="action-btn primary"
+ @click="handleTaskAction('arrive')"
+ >
+ 宸插埌杈�
+ </button>
+ <button
+ v-if="showForceCompleteFeature()"
+ class="action-btn force-complete"
+ @click="showForceCompleteTimeDialog()"
+ >
+ 寮哄埗瀹屾垚
+ </button>
</template>
</template>
@@ -1502,6 +1521,19 @@
const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : []
return list.some(a => a && (a.userId === userId || a.oaUserId === userId))
},
+
+ // 鏄惁褰撳墠鐢ㄦ埛鍙互鎿嶄綔浠诲姟锛堟墽琛屼汉鎴栫鐞嗗憳锛�
+ canOperateTask() {
+ // 妫�鏌ユ槸鍚︽槸绠$悊鍛橈紙canViewAllConsult === '1'锛�
+
+ const canViewAllConsult = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.canViewAllConsult
+ console.log("褰撳墠鐢ㄦ埛鏄惁鏄鐞嗗憳:", canViewAllConsult)
+ if (canViewAllConsult === '1') {
+ return true
+ }
+ // 妫�鏌ユ槸鍚︽槸浠诲姟鎵ц浜�
+ return this.isCurrentUserAssignee()
+ },
// 鏄惁澶氫汉鎵ц
isMultipleAssignees() {
diff --git a/app/store/modules/user.js b/app/store/modules/user.js
index 45113d9..1b929ea 100644
--- a/app/store/modules/user.js
+++ b/app/store/modules/user.js
@@ -20,7 +20,8 @@
branchCompanyId: storage.get(constant.branchCompanyId),
branchCompanyName: storage.get(constant.branchCompanyName),
oaUserId: storage.get(constant.oaUserId),
- canCreateTask: storage.get(constant.canCreateTask)
+ canCreateTask: storage.get(constant.canCreateTask),
+ canViewAllConsult: storage.get(constant.canViewAllConsult)
},
mutations: {
@@ -70,6 +71,10 @@
SET_CAN_CREATE_TASK: (state, canCreateTask) => {
state.canCreateTask = canCreateTask
storage.set(constant.canCreateTask, canCreateTask)
+ },
+ SET_CAN_VIEW_ALL_CONSULT: (state, canViewAllConsult) => {
+ state.canViewAllConsult = canViewAllConsult
+ storage.set(constant.canViewAllConsult, canViewAllConsult)
}
},
@@ -130,6 +135,7 @@
commit('SET_BRANCH_COMPANY_NAME', res.branchCompanyName)
commit('SET_OA_USER_ID', res.oaUserId)
commit('SET_CAN_CREATE_TASK', res.canCreateTask)
+ commit('SET_CAN_VIEW_ALL_CONSULT', res.canViewAllConsult)
resolve(res)
}).catch(error => {
reject(error)
diff --git a/app/utils/constant.js b/app/utils/constant.js
index 4133a31..d890ac3 100644
--- a/app/utils/constant.js
+++ b/app/utils/constant.js
@@ -9,7 +9,8 @@
branchCompanyId: 'vuex_branchCompanyId',
branchCompanyName: 'vuex_branchCompanyName',
oaUserId: 'vuex_oaUserId',
- canCreateTask: 'vuex_canCreateTask'
+ canCreateTask: 'vuex_canCreateTask',
+ canViewAllConsult: 'vuex_canViewAllConsult'
}
export default constant
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
index e17fb3b..31feeea 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -29,4 +29,6 @@
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
+
+
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index e3bb508..0f1ca35 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -241,6 +241,7 @@
ajax.put("branchCompanyName", branchCompanyName);
ajax.put("branchCompanies", branchCompanies);
ajax.put("oaUserId", user.getOaUserId());
+ ajax.put("canViewAllConsult", user.getCanViewAllConsult());
ajax.put("canCreateTask", user.getCanCreateTask());
return ajax;
}
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 0277f9e..13f31b7 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -27,7 +27,7 @@
# 鍒濆杩炴帴鏁�
initialSize: 5
# 鏈�灏忚繛鎺ユ睜鏁伴噺
- minIdle: 10
+ minIdle: 5
# 鏈�澶ц繛鎺ユ睜鏁伴噺
maxActive: 20
# 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
@@ -41,12 +41,22 @@
# 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
minEvictableIdleTimeMillis: 300000
# 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
- maxEvictableIdleTimeMillis: 900000
+ maxEvictableIdleTimeMillis: 600000
# 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
+ # 鏄惁缂撳瓨preparedStatement锛屼篃灏辨槸PSCache锛堟彁鍗囨�ц兘浣嗗鍔犲唴瀛橈紝Oracle寤鸿寮�鍚紝MySQL寤鸿鍏抽棴锛�
+ poolPreparedStatements: false
+ # 姣忎釜杩炴帴鐨凱SCache澶у皬锛圡ySQL寤鸿鍏抽棴PSCache锛岃涓�-1锛�
+ maxPoolPreparedStatementPerConnectionSize: -1
+ # 閰嶇疆绉婚櫎搴熷純杩炴帴锛堥暱鏃堕棿鏈綊杩樼殑杩炴帴锛�
+ removeAbandoned: true
+ # 杩炴帴琚崰鐢ㄨ秴杩囨鏃堕棿锛堢锛夎涓哄簾寮�
+ removeAbandonedTimeout: 1800
+ # 鏄惁璁板綍搴熷純杩炴帴鐨勫爢鏍堜俊鎭�
+ logAbandoned: true
webStatFilter:
enabled: true
statViewServlet:
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 105bc73..53c5a19 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -58,7 +58,7 @@
basename: i18n/messages
profiles:
# 鐜 dev|test|prod
- active: dev
+ active: prod
# 鏂囦欢涓婁紶
servlet:
multipart:
@@ -86,13 +86,14 @@
lettuce:
pool:
# 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
- min-idle: 0
+ min-idle: 2
# 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
max-idle: 8
# 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
- max-active: 8
+ max-active: 20
# #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
max-wait: -1ms
+ shutdown-timeout: 100ms
# token閰嶇疆
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
index 589d123..d4b9eec 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
@@ -1,14 +1,14 @@
package com.ruoyi.common.utils.http;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.*;
+import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletRequest;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
+import static java.util.Collections.replaceAll;
/**
* 閫氱敤http宸ュ叿灏佽
@@ -19,6 +19,17 @@
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
+ /**
+ * url缂栫爜 + 绌烘牸鏇挎崲涓� %20 %3A 鏇挎崲涓� : 涓昏鏄鐞嗘椂闂磋浆鎹㈤棶棰�
+ * @param str
+ * @param charset
+ * @return
+ * @throws UnsupportedEncodingException
+ */
+ public static String UrlEncode(String str, String charset) throws UnsupportedEncodingException {
+ return URLEncoder.encode(str, charset).replaceAll("\\+", "%20").replaceAll("%3A", ":");
+ }
+
public static String getBodyString(ServletRequest request)
{
StringBuilder sb = new StringBuilder();
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
index 5292236..2623411 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
@@ -40,17 +40,36 @@
* 鍚屾GPS浣嶇疆
*/
public void syncGpsData() {
+ List<VehicleInfo> vehicleList = null;
try {
// log.info("寮�濮嬪悓姝PS鏁版嵁...");
// 1. 鑾峰彇鎵�鏈夎溅杈嗕俊鎭�
- List<VehicleInfo> vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo());
+ vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo());
- List<String> deviceIds = vehicleList.stream().map(VehicleInfo::getDeviceId).collect(Collectors.toList());
+ if (vehicleList == null || vehicleList.isEmpty()) {
+ log.info("娌℃湁鎵惧埌杞﹁締淇℃伅");
+ return;
+ }
+
+ List<String> deviceIds = vehicleList.stream()
+ .map(VehicleInfo::getDeviceId)
+ .filter(id -> id != null && !id.isEmpty())
+ .collect(Collectors.toList());
+
+ if (deviceIds.isEmpty()) {
+ log.info("娌℃湁鏈夋晥鐨勮澶嘔D");
+ return;
+ }
+
// 2. 鑾峰彇鎵�鏈夎溅杈嗙殑GPS鏈�鍚庝綅缃�
GpsLastPositionRequest request = new GpsLastPositionRequest();
-// request.setDeviceids(deviceIds);
GpsLastPositionResponse gpsLastPositionResponse = gpsCollectService.getLastPosition(request);
+
+ if (gpsLastPositionResponse == null || gpsLastPositionResponse.getRecords() == null) {
+ log.warn("GPS鏈嶅姟杩斿洖绌烘暟鎹�");
+ return;
+ }
// 3. 閬嶅巻杞﹁締鍒楄〃锛岃幏鍙栨瘡涓溅杈嗙殑GPS浣嶇疆
for (VehicleInfo vehicle : vehicleList) {
@@ -71,6 +90,9 @@
// log.info("GPS鏁版嵁鍚屾瀹屾垚");
} catch (Exception e) {
log.error("GPS鏁版嵁鍚屾澶辫触: {}", e.getMessage());
+ } finally {
+ // 鏄惧紡娓呯┖澶у璞″紩鐢紝甯姪GC
+ vehicleList = null;
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
index da2a3c4..b44aa72 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
@@ -433,8 +433,12 @@
// 杩旂▼涓� -> 宸插畬鎴�
return newStatus == TaskStatus.COMPLETED;
case IN_PROGRESS:
- // 鍏煎鏃ф暟鎹細浠诲姟涓� -> 宸插畬鎴愩�佸凡鍙栨秷銆佸緟澶勭悊
- return newStatus == TaskStatus.COMPLETED || newStatus == TaskStatus.CANCELLED || newStatus == TaskStatus.PENDING;
+ // 鍏煎鏃ф暟鎹細浠诲姟涓� -> 宸插畬鎴愩�佸凡鍙栨秷銆佸緟澶勭悊銆佸凡鍒拌揪銆佽繑绋嬩腑
+ return newStatus == TaskStatus.COMPLETED
+ || newStatus == TaskStatus.CANCELLED
+ || newStatus == TaskStatus.PENDING
+ || newStatus == TaskStatus.ARRIVED
+ || newStatus == TaskStatus.RETURNING;
case COMPLETED:
case CANCELLED:
// 宸插畬鎴愩�佸凡鍙栨秷 -> 涓嶅厑璁镐换浣曠姸鎬佸彉鏇�
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
index 66d1c8d..f42635d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
@@ -23,7 +23,7 @@
* @param startDate 寮�濮嬫棩鏈�
* @return 杞繍鍗曟暟鎹垪琛�
*/
- List<Map<String, Object>> selectTransferOrders(@Param("startDate") String startDate);
+ List<Map<String, Object>> selectTransferOrders(@Param("startDate") String startDate, @Param("endDate") String endDate);
/**ServiceOrdNo
* 鏍规嵁鏈嶅姟鍗旾D鍜岃皟搴﹀崟ID鏌ヨ杞繍鍗曟暟鎹�
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java
index 651fb46..3df5b73 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomerEvaluationServiceImpl.java
@@ -133,7 +133,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int submitCustomerEvaluation(CustomerEvaluation customerEvaluation) {
// 璁$畻鎬昏瘎鍒�
BigDecimal totalScore = calculateTotalScore(customerEvaluation.getEvaluationDetails());
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
index 5e1cf76..62dd1a4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
@@ -52,7 +52,7 @@
* @return 鍚屾缁撴灉
*/
@Override
- @Transactional
+
public AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts,List<OrderClassDTO> serviceOrderList,List<OrderClassDTO> dispatchOrderList,List<Map<String, Object>> addressList)
{
try
@@ -257,7 +257,7 @@
* @return 鍚屾缁撴灉
*/
@Override
- @Transactional
+
public AjaxResult syncTransportDepartments(List<DepartmentSyncDTO> transportDepts, List<Map<String, Object>> addressList)
{
try
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsConfigServiceImpl.java
index a3e1b85..123e2cb 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsConfigServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsConfigServiceImpl.java
@@ -29,8 +29,7 @@
return gpsConfigMapper.selectGpsConfigList(gpsConfig);
}
- @Override
- @Transactional
+ @Override
public int insertGpsConfig(SysGpsConfig gpsConfig) {
gpsConfig.setCreateTime(DateUtils.getNowDate());
gpsConfig.setUpdateTime(DateUtils.getNowDate());
@@ -38,20 +37,17 @@
}
@Override
- @Transactional
public int updateGpsConfig(SysGpsConfig gpsConfig) {
gpsConfig.setUpdateTime(DateUtils.getNowDate());
return gpsConfigMapper.updateGpsConfig(gpsConfig);
}
@Override
- @Transactional
public int deleteGpsConfigByIds(Long[] configIds) {
return gpsConfigMapper.deleteGpsConfigByIds(configIds);
}
@Override
- @Transactional
public int deleteGpsConfigById(Long configId) {
return gpsConfigMapper.deleteGpsConfigById(configId);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
index 6e56c55..77bca76 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
@@ -88,9 +88,10 @@
// 璁$畻鏃ユ湡鑼冨洿
Date startDate = DateUtils.addDays(new Date(), -daysAgo);
String startDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", startDate);
+ String endDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", new Date());
// 浠嶴QL Server鏌ヨ杞繍鍗曟暟鎹�
- List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrders(startDateStr);
+ List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrders(startDateStr, endDateStr);
if (transferOrders == null || transferOrders.isEmpty()) {
log.info("鏈煡璇㈠埌{}澶╁墠鐨勮浆杩愬崟鏁版嵁", daysAgo);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java
index 3d37ef3..4093e5e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java
@@ -83,7 +83,7 @@
* @return 鍒涘缓鐨勮褰曪紝濡傛灉宸插瓨鍦ㄥ垯杩斿洖null
*/
@Override
- @Transactional
+
public NotifySendLog tryCreateSendLog(Long taskId, Long userId, String userName,
String notifyType, String channel) {
// 鍏堟鏌ユ槸鍚﹀凡瀛樺湪
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
index 7fd9654..9c9b49d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -189,7 +189,6 @@
* @return 缁撴灉
*/
@Override
- @Transactional
public int updateDictType(SysDictType dict)
{
SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId());
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
index e432bb1..2105d38 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -231,7 +231,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int insertRole(SysRole role)
{
// 鏂板瑙掕壊淇℃伅
@@ -246,7 +246,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int updateRole(SysRole role)
{
// 淇敼瑙掕壊淇℃伅
@@ -275,7 +275,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int authDataScope(SysRole role)
{
// 淇敼瑙掕壊淇℃伅
@@ -341,7 +341,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int deleteRoleById(Long roleId)
{
// 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
@@ -358,7 +358,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int deleteRoleByIds(Long[] roleIds)
{
for (Long roleId : roleIds)
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java
index f64a13c..847ddf8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java
@@ -32,7 +32,7 @@
private ApplicationEventPublisher eventPublisher;
@Override
- @Transactional
+
public void saveTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> assignees, String userName) {
if (assignees == null || assignees.isEmpty()) {
return;
@@ -68,7 +68,7 @@
}
@Override
- @Transactional
+
public boolean updateTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> newAssignees, String userName) {
if (newAssignees == null) {
return false;
@@ -181,13 +181,13 @@
}
@Override
- @Transactional
+
public int deleteAssigneesByTaskId(Long taskId) {
return sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(taskId);
}
@Override
- @Transactional
+
public AjaxResult setAssigneeReady(Long taskId, Long userId) {
// 1. 鏌ヨ鎵ц浜哄叧鑱斾俊鎭�
List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
@@ -220,7 +220,7 @@
}
@Override
- @Transactional
+
public AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
// 鏌ヨ鎵ц浜哄叧鑱斾俊鎭�
List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java
index 7c0111f..24c0b77 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java
@@ -29,7 +29,7 @@
private ImageUrlConfig imageUrlConfig;
@Override
- @Transactional
+
public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
try {
String fileName = category + "_" + System.currentTimeMillis() + "_" + file.getOriginalFilename();
@@ -53,7 +53,7 @@
}
@Override
- @Transactional
+
public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
try {
String wechatUrl = String.format(
@@ -87,7 +87,7 @@
}
@Override
- @Transactional
+
public int deleteAttachment(Long attachmentId) {
SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
if (attachment == null) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java
index 51c9d44..2ec3617 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java
@@ -146,7 +146,6 @@
}
@Override
- @Transactional
public BigDecimal addAdditionalFee(Long taskId, String feeType, String feeName,
BigDecimal unitAmount, Integer quantity, String remark) {
// 楠岃瘉鍙傛暟
@@ -185,14 +184,13 @@
}
@Override
- @Transactional
+
public BigDecimal removeAdditionalFee(Long taskId, Long feeId) {
additionalFeeMapper.deleteById(feeId);
return calculateAdditionalAmount(taskId);
}
@Override
- @Transactional
public TaskPaymentResultVO createPayment(TaskPaymentCreateVO createVO) {
Long taskId = createVO.getTaskId();
String paymentMethod = createVO.getPaymentMethod();
@@ -362,7 +360,7 @@
}
@Override
- @Transactional
+
public boolean handlePaymentCallback(String outTradeNo, String tradeNo, String provider) {
log.info("鏀跺埌鏀粯鍥炶皟锛歰utTradeNo={}, tradeNo={}, provider={}", outTradeNo, tradeNo, provider);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index f79c520..60aae88 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -855,7 +855,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int deleteSysTaskByTaskIds(Long[] taskIds) {
int result = 0;
for (Long taskId : taskIds) {
@@ -876,7 +876,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int assignTask(Long taskId, Long assigneeId, String remark) {
SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
if (task == null) {
@@ -1150,7 +1150,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
return sysTaskAttachmentService.uploadAttachment(taskId, file, category);
}
@@ -1165,7 +1165,7 @@
* @return 杩斿洖闄勪欢ID
*/
@Override
- @Transactional
+
public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
return sysTaskAttachmentService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
}
@@ -1178,7 +1178,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int deleteAttachment(Long attachmentId) {
return sysTaskAttachmentService.deleteAttachment(attachmentId);
}
@@ -1208,7 +1208,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int assignVehicleToTask(Long taskId, Long vehicleId, String remark,Long userId,String userName) {
int result = sysTaskVehicleService.assignVehicleToTask(taskId, vehicleId, remark, userId, userName);
@@ -1230,7 +1230,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
int result = sysTaskVehicleService.unassignVehicleFromTask(taskId, vehicleId);
@@ -1253,7 +1253,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,Long userId,String userName) {
int result = sysTaskVehicleService.assignMultipleVehiclesToTask(taskId, vehicleIds, remark, userId, userName);
@@ -1761,7 +1761,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public AjaxResult setAssigneeReady(Long taskId, Long userId) {
return sysTaskAssigneeService.setAssigneeReady(taskId, userId);
}
@@ -1774,7 +1774,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
return sysTaskAssigneeService.cancelAssigneeReady(taskId, userId);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
index 6f3a6d7..1b33e81 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
@@ -147,14 +147,14 @@
}
@Override
- @Transactional
+
public void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName) {
saveTaskVehicles(taskId, vehicleIds, userName,
DateUtils.getNowDate(), DateUtils.getNowDate(), DateUtils.getNowDate());
}
@Override
- @Transactional
+
public void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName,
Date assignTime, Date createTime, Date updateTime) {
if (vehicleIds == null || vehicleIds.isEmpty()) {
@@ -178,7 +178,7 @@
}
@Override
- @Transactional
+
public boolean updateTaskVehicles(Long taskId, List<Long> newVehicleIds, String userName) {
if (newVehicleIds == null || newVehicleIds.isEmpty()) {
return false;
@@ -216,7 +216,7 @@
}
@Override
- @Transactional
+
public int assignVehicleToTask(Long taskId, Long vehicleId, String remark, Long userId, String userName) {
// 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
@@ -236,13 +236,13 @@
}
@Override
- @Transactional
+
public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
}
@Override
- @Transactional
+
public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,
Long userId, String userName) {
List<SysTaskVehicle> taskVehicles = new ArrayList<>();
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index 8f10be9..47e458f 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -306,7 +306,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int insertUser(SysUser user)
{
// 鏂板鐢ㄦ埛淇℃伅
@@ -337,7 +337,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int updateUser(SysUser user)
{
Long userId = user.getUserId();
@@ -359,7 +359,7 @@
* @param roleIds 瑙掕壊缁�
*/
@Override
- @Transactional
+
public void insertUserAuth(Long userId, Long[] roleIds)
{
userRoleMapper.deleteUserRoleByUserId(userId);
@@ -515,7 +515,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int deleteUserById(Long userId)
{
// 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
@@ -532,7 +532,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int deleteUserByIds(Long[] userIds)
{
for (Long userId : userIds)
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusPushServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusPushServiceImpl.java
index 74bb2c6..9d495d9 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusPushServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusPushServiceImpl.java
@@ -174,7 +174,7 @@
try {
int totalSuccessCount = 0;
- int pageSize = 200; // 姣忛〉200鏉�
+ int pageSize = 10; // 姣忛〉10鏉�
int offset = 0;
while (true) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusSyncServiceImpl.java
index 532ff64..80db40c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskStatusSyncServiceImpl.java
@@ -118,7 +118,7 @@
try {
int totalSuccessCount = 0;
- int pageSize = 10; // 姣忛〉200鏉�
+ int pageSize = 10; // 姣忛〉10鏉�
int offset = 0;
while (true) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskSyncUtilService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskSyncUtilService.java
index 35aa96a..379c0e1 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskSyncUtilService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskSyncUtilService.java
@@ -4,6 +4,7 @@
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.http.HttpHelper;
import com.ruoyi.system.domain.SysTask;
import com.ruoyi.system.domain.SysTaskEmergency;
import com.ruoyi.system.service.ISysDeptService;
@@ -275,7 +276,7 @@
}
postData.append(URLEncoder.encode(entry.getKey(), legacySystemConfig.getCharset()));
postData.append("=");
- postData.append(URLEncoder.encode(entry.getValue().toString(), legacySystemConfig.getCharset()));
+ postData.append(HttpHelper.UrlEncode(entry.getValue().toString(), legacySystemConfig.getCharset()));
}
// log.info("鍙戦�丳OST璇锋眰鍒版棫绯荤粺锛孶RL: {}, 鍙傛暟: {}", urlString, postData.toString());
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
index 83d93e8..b8c9b2e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
@@ -55,7 +55,7 @@
* @return 鍚屾缁撴灉
*/
@Override
- @Transactional
+
public AjaxResult syncOaUsers(List<UserSyncDTO> oaUsers)
{
try
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 9936086..a534c6e 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
@@ -2,6 +2,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.time.format.DateTimeFormatter;
import java.util.*;
import com.ruoyi.common.utils.DateUtils;
@@ -40,6 +41,12 @@
/** 澶╁湴鍥炬壒閲忚矾寰勮鍒扐PI */
private static final String TIANDITU_ROUTE_API = "http://api.tianditu.gov.cn/drive";
+
+ /** 绾跨▼瀹夊叏鐨勬棩鏈熸牸寮忓寲鍣� */
+ private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+ /** 鍒嗘壒澶勭悊澶у皬锛岄伩鍏嶄竴娆℃�у姞杞借繃澶氭暟鎹� */
+ private static final int BATCH_SIZE = 10;
@Autowired
private VehicleGpsSegmentMileageMapper segmentMileageMapper;
@@ -118,35 +125,44 @@
return 0;
}
- logger.info("鎵惧埌 {} 杈嗘椿璺冭溅杈嗭紝寮�濮嬮�愯締璁$畻...", vehicleIds.size());
+ logger.info("鎵惧埌 {} 杈嗘椿璺冭溅杈嗭紝寮�濮嬪垎鎵归�愯締璁$畻...", vehicleIds.size());
int successCount = 0;
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);
+ // 鍒嗘壒澶勭悊锛岄伩鍏嶄竴娆℃�у鐞嗚繃澶氭暟鎹鑷村唴瀛樻孩鍑�
+ for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) {
+ int batchEnd = Math.min(batchStart + BATCH_SIZE, vehicleIds.size());
+ List<Long> batchVehicleIds = vehicleIds.subList(batchStart, batchEnd);
+
+ logger.info("澶勭悊鎵规 {}-{}/{}", batchStart + 1, batchEnd, vehicleIds.size());
+
+ // 閫愯締璁$畻锛屽寘鍚敊璇鐞嗗拰閲嶈瘯鏈哄埗
+ for (int i = 0; i < batchVehicleIds.size(); i++) {
+ Long vehicleId = batchVehicleIds.get(i);
+ int overallIndex = batchStart + i;
+ try {
+ int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime);
+ if (segmentCount > 0) {
+ successCount++;
+ }
+ } catch (Exception e) {
+ failedCount++;
+ logger.error("璁$畻杞﹁締 {} 鐨勫垎娈甸噷绋嬪け璐� ({}/{})", vehicleId, overallIndex + 1, vehicleIds.size(), e);
+ // 涓嶄腑鏂暣涓壒澶勭悊锛岀户缁鐞嗕笅涓�杈嗚溅
}
- } catch (Exception e) {
- failedCount++;
- logger.error("璁$畻杞﹁締 {} 鐨勫垎娈甸噷绋嬪け璐� ({}/{})", vehicleId, i + 1, vehicleIds.size(), e);
- // 涓嶄腑鏂暣涓壒澶勭悊锛岀户缁鐞嗕笅涓�杈嗚溅
+ // 姣忓鐞�10杈嗚溅杈撳嚭涓�娆¤繘搴�
+ if ((overallIndex + 1) % 10 == 0) {
+ logger.info("鎵归噺璁$畻杩涘害: {}/{}, 鎴愬姛: {}, 澶辫触: {}",
+ overallIndex + 1, vehicleIds.size(), successCount, failedCount);
+ }
}
- // 姣忓鐞�10杈嗚溅杈撳嚭涓�娆¤繘搴�
- if ((i + 1) % 10 == 0) {
- logger.info("鎵归噺璁$畻杩涘害: {}/{}, 鎴愬姛: {}, 澶辫触: {}",
- i + 1, vehicleIds.size(), successCount, failedCount);
+ // 鎵规缁撴潫鍚庯紝涓诲姩瑙﹀彂GC寤鸿锛堜笉寮哄埗锛�
+ if (batchEnd < vehicleIds.size()) {
+ System.gc();
+ logger.debug("鎵规 {}-{} 澶勭悊瀹屾垚锛屽凡寤鸿JVM鍥炴敹鍐呭瓨", batchStart + 1, batchEnd);
}
}
@@ -185,10 +201,15 @@
String endTimeStr=DateUtils.formatDate(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS);
- for (Long vehicleId : vehicleIds) {
- try {
- // 鏌ヨ璇ヨ溅杈嗘湭琚绠楃殑GPS鏁版嵁
- List<VehicleGps> uncalculatedGps = vehicleGpsMapper.selectUncalculatedGps(vehicleId, startTimeStr, endTimeStr);
+ // 鍒嗘壒澶勭悊杞﹁締锛岄伩鍏嶅唴瀛樻孩鍑�
+ for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) {
+ int batchEnd = Math.min(batchStart + BATCH_SIZE, vehicleIds.size());
+ List<Long> batchVehicleIds = vehicleIds.subList(batchStart, batchEnd);
+
+ for (Long vehicleId : batchVehicleIds) {
+ try {
+ // 鏌ヨ璇ヨ溅杈嗘湭琚绠楃殑GPS鏁版嵁
+ List<VehicleGps> uncalculatedGps = vehicleGpsMapper.selectUncalculatedGps(vehicleId, startTimeStr, endTimeStr);
if (uncalculatedGps == null || uncalculatedGps.isEmpty()) {
logger.debug("杞﹁締 {} 娌℃湁鏈绠楃殑GPS鏁版嵁", vehicleId);
@@ -224,12 +245,20 @@
int segmentCount = calculateVehicleSegmentMileageWithGpsList(
vehicleId, uncalculatedGps, uncalculatedStartTime, uncalculatedEndTime);
- if (segmentCount > 0) {
- successCount++;
- logger.info("杞﹁締 {} 琛ュ伩璁$畻瀹屾垚锛岀敓鎴� {} 涓垎娈佃褰�", vehicleId, segmentCount);
+ if (segmentCount > 0) {
+ successCount++;
+ logger.info("杞﹁締 {} 琛ュ伩璁$畻瀹屾垚锛岀敓鎴� {} 涓垎娈佃褰�", vehicleId, segmentCount);
+ }
+ } catch (Exception e) {
+ logger.error("杞﹁締 {} 琛ュ伩璁$畻澶辫触", vehicleId, e);
}
- } catch (Exception e) {
- logger.error("杞﹁締 {} 琛ュ伩璁$畻澶辫触", vehicleId, e);
+ }
+
+ // 姣忔壒娆$粨鏉熷悗锛屼富鍔ㄥ缓璁瓽C
+ if (batchEnd < vehicleIds.size()) {
+ uncalculatedGps = null; // 鏄惧紡娓呯┖寮曠敤
+ System.gc();
+ logger.debug("琛ュ伩璁$畻鎵规 {}-{} 瀹屾垚锛屽凡寤鸿JVM鍥炴敹鍐呭瓨", batchStart + 1, batchEnd);
}
}
@@ -470,7 +499,8 @@
* 鏀堕泦GPS ID鍒楄〃锛堝寘鎷墠缃偣锛�
*/
private List<Long> collectGpsIds(List<VehicleGps> segmentGpsList, VehicleGps previousSegmentLastPoint) {
- List<Long> gpsIdList = new ArrayList<>();
+ // 棰勫垎閰嶅悎鐞嗗閲忥紝鍑忓皯鎵╁寮�閿�
+ List<Long> gpsIdList = new ArrayList<>(segmentGpsList.size() + 1);
// 濡傛灉鏈変笂涓�娈电殑鏈�鍚庝竴涓偣锛屽厛娣诲姞瀹冪殑ID锛堢敤浜庤绠楄法娈佃窛绂伙級
if (previousSegmentLastPoint != null && previousSegmentLastPoint.getGpsId() != null) {
@@ -822,16 +852,22 @@
/**
* 瑙f瀽鏃ユ湡鏃堕棿瀛楃涓�
+ * 浣跨敤ThreadLocal鐨凷impleDateFormat锛岄伩鍏嶆瘡娆″垱寤烘柊瀵硅薄
*/
+ private static final ThreadLocal<java.text.SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL =
+ ThreadLocal.withInitial(() -> {
+ java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ sdf.setLenient(false);
+ return sdf;
+ });
+
private Date parseDateTime(String dateTimeStr) {
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
throw new RuntimeException("鏃ユ湡鏃堕棿瀛楃涓蹭笉鑳戒负绌�");
}
try {
- java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- sdf.setLenient(false);
- return sdf.parse(dateTimeStr.trim());
+ return DATE_FORMAT_THREAD_LOCAL.get().parse(dateTimeStr.trim());
} catch (Exception e) {
throw new RuntimeException("鏃ユ湡鏃堕棿鏍煎紡閿欒: " + dateTimeStr + ", 搴斾负 yyyy-MM-dd HH:mm:ss", e);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleInfoServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleInfoServiceImpl.java
index 7c4bfd2..f276d8c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleInfoServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleInfoServiceImpl.java
@@ -102,7 +102,6 @@
* @return 缁撴灉
*/
@Override
- @Transactional
public int insertVehicleInfo(VehicleInfo vehicleInfo) {
int rows = vehicleInfoMapper.insertVehicleInfo(vehicleInfo);
@@ -130,8 +129,7 @@
* @param vehicleInfo 杞﹁締淇℃伅
* @return 缁撴灉
*/
- @Override
- @Transactional
+ @Override
public int updateVehicleInfo(VehicleInfo vehicleInfo) {
// 鍙湁褰� deptIds 涓嶄负 null 鏃舵墠鏇存柊閮ㄩ棬鍏宠仈(閬垮厤涓嶅繀瑕佺殑閿佺珵浜�)
if (vehicleInfo.getDeptIds() != null) {
@@ -194,7 +192,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
+
public int bindVehicleToUser(Long userId, Long vehicleId) {
// 鍏堣В缁戠敤鎴风殑鎵�鏈夎溅杈嗭紙涓氬姟閫昏緫锛氫竴涓敤鎴峰悓鏃跺彧鑳界粦瀹氫竴杈嗚溅锛�
vehicleInfoMapper.unbindAllVehiclesFromUser(userId);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java
index 860c875..4a51e35 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleSyncServiceImpl.java
@@ -56,7 +56,7 @@
* @return 鍚屾缁撴灉
*/
@Override
- @Transactional
+
public AjaxResult syncVehicles(List<VehicleSyncDTO> vehicles)
{
if (vehicles == null || vehicles.isEmpty())
diff --git "a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md" "b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
index 81bcaed..0dff57d 100644
--- "a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
+++ "b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
@@ -26,7 +26,7 @@
**淇鍐呭**锛�
```java
@Override
-@Transactional
+
public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle) {
// 璁剧疆鍒嗛厤鏃堕棿鍜屽垎閰嶄汉
if (sysTaskVehicle.getAssignTime() == null) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java
index 741eec1..ef6c915 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java
@@ -40,11 +40,13 @@
returningTransitions.add(TaskStatus.COMPLETED);
ALLOWED_TRANSITIONS.put(TaskStatus.RETURNING, returningTransitions);
- // IN_PROGRESS -> COMPLETED, CANCELLED, PENDING (鍏煎鏃ф暟鎹�)
+ // IN_PROGRESS -> COMPLETED, CANCELLED, PENDING, ARRIVED, RETURNING (鍏煎鏃ф暟鎹�)
Set<TaskStatus> inProgressTransitions = new HashSet<>();
inProgressTransitions.add(TaskStatus.COMPLETED);
inProgressTransitions.add(TaskStatus.CANCELLED);
inProgressTransitions.add(TaskStatus.PENDING);
+ inProgressTransitions.add(TaskStatus.ARRIVED);
+ inProgressTransitions.add(TaskStatus.RETURNING);
ALLOWED_TRANSITIONS.put(TaskStatus.IN_PROGRESS, inProgressTransitions);
// COMPLETED -> 涓嶅厑璁镐换浣曠姸鎬佸彉鏇�
diff --git a/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml b/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
index f638746..ce3ae5c 100644
--- a/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
@@ -109,7 +109,7 @@
FROM ServiceOrder as a
left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt
WHERE a.ServiceOrdState <= 3
- AND a.ServiceOrd_CC_Time > #{startDate}
+ AND a.ServiceOrd_CC_Time > #{startDate} and a.ServiceOrd_CC_Time < #{endDate}
</select>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
index 2df0e8c..54fbcee 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
@@ -331,7 +331,7 @@
limit #{limit}
</if>
<if test="offset == null and limit == null">
- limit 200
+ limit 10
</if>
</select>
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index ed3749d..d10e40c 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -179,6 +179,24 @@
</el-radio-group>
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="鍙垱寤轰换鍔″崟">
+ <el-radio-group v-model="form.canCreateTask">
+ <el-radio label="0">鍚�</el-radio>
+ <el-radio label="1">鏄�</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鍙鐞嗕换鍔″崟">
+ <el-radio-group v-model="form.canViewAllConsult">
+ <el-radio label="0">鍚�</el-radio>
+ <el-radio label="1">鏄�</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
</el-row>
<el-row>
<el-col :span="12">
@@ -295,7 +313,9 @@
// 瑙掕壊閫夐」
roleOptions: [],
// 琛ㄥ崟鍙傛暟
- form: {},
+ form: {
+ canCreateTask: "0"
+ },
defaultProps: {
children: "children",
label: "label"
@@ -462,7 +482,8 @@
remark: undefined,
postIds: [],
roleIds: [],
- canViewAllConsult: "0"
+ canViewAllConsult: "0",
+ canCreateTask: "0"
};
this.resetForm("form");
},
diff --git a/sql/optimize_memory_indexes.sql b/sql/optimize_memory_indexes.sql
new file mode 100644
index 0000000..4d399f1
--- /dev/null
+++ b/sql/optimize_memory_indexes.sql
@@ -0,0 +1,282 @@
+-- =====================================================
+-- 鍐呭瓨浼樺寲鐩稿叧鏁版嵁搴撶储寮曚紭鍖栬剼鏈�
+-- 鐢ㄤ簬鎻愬崌GPS鐩稿叧鏌ヨ鎬ц兘锛屽噺灏戞參鏌ヨ瀵艰嚧鐨勫唴瀛樺崰鐢�
+-- =====================================================
+-- 鎵ц鍓嶈鍏堝浠芥暟鎹簱锛�
+-- 鎵ц鏂瑰紡: mysql -u root -p 鏁版嵁搴撳悕 < optimize_memory_indexes.sql
+-- =====================================================
+
+USE `966120`;
+
+-- =====================================================
+-- 1. GPS鏁版嵁琛ㄧ储寮曚紭鍖�
+-- =====================================================
+
+-- 妫�鏌� tb_vehicle_gps 琛ㄧ殑鐜版湁绱㈠紩
+SELECT
+ TABLE_NAME,
+ INDEX_NAME,
+ COLUMN_NAME,
+ SEQ_IN_INDEX,
+ INDEX_TYPE
+FROM information_schema.STATISTICS
+WHERE TABLE_SCHEMA = '966120'
+ AND TABLE_NAME = 'tb_vehicle_gps'
+ORDER BY INDEX_NAME, SEQ_IN_INDEX;
+
+-- 娣诲姞杞﹁締ID鍜岄噰闆嗘椂闂寸殑缁勫悎绱㈠紩锛堢敤浜嶨PS鍒嗘鏌ヨ锛�
+-- 姝ょ储寮曞彲澶у箙鎻愬崌 selectActiveVehicleIds 鍜� selectGpsDataByTimeRange 鏌ヨ鎬ц兘
+ALTER TABLE tb_vehicle_gps
+ADD INDEX idx_vehicle_collect_time (vehicle_id, collect_time)
+COMMENT 'GPS鍒嗘鏌ヨ浼樺寲绱㈠紩';
+
+-- 娣诲姞閲囬泦鏃堕棿鍗曠嫭绱㈠紩锛堢敤浜庢椂闂磋寖鍥存煡璇級
+ALTER TABLE tb_vehicle_gps
+ADD INDEX idx_collect_time (collect_time)
+COMMENT 'GPS鏃堕棿鑼冨洿鏌ヨ绱㈠紩';
+
+-- 娣诲姞璁惧ID绱㈠紩锛堢敤浜嶨PS鍚屾鏌ヨ锛�
+ALTER TABLE tb_vehicle_gps
+ADD INDEX idx_device_id (device_id)
+COMMENT 'GPS璁惧ID鏌ヨ绱㈠紩';
+
+-- =====================================================
+-- 2. GPS鍒嗘閲岀▼琛ㄧ储寮曚紭鍖�
+-- =====================================================
+
+-- 妫�鏌� vehicle_gps_segment_mileage 琛ㄧ殑鐜版湁绱㈠紩
+SELECT
+ TABLE_NAME,
+ INDEX_NAME,
+ COLUMN_NAME,
+ SEQ_IN_INDEX,
+ INDEX_TYPE
+FROM information_schema.STATISTICS
+WHERE TABLE_SCHEMA = '966120'
+ AND TABLE_NAME = 'vehicle_gps_segment_mileage'
+ORDER BY INDEX_NAME, SEQ_IN_INDEX;
+
+-- 娣诲姞杞﹁締ID鍜屽垎娈靛紑濮嬫椂闂寸殑缁勫悎绱㈠紩
+ALTER TABLE vehicle_gps_segment_mileage
+ADD INDEX idx_vehicle_segment_start (vehicle_id, segment_start_time)
+COMMENT '杞﹁締鍒嗘鏌ヨ绱㈠紩';
+
+-- 娣诲姞浠诲姟ID绱㈠紩锛堢敤浜庝换鍔″叧鑱旀煡璇級
+ALTER TABLE vehicle_gps_segment_mileage
+ADD INDEX idx_task_id (task_id)
+COMMENT '浠诲姟鍏宠仈鏌ヨ绱㈠紩';
+
+-- 娣诲姞鍒嗘鏃堕棿鑼冨洿绱㈠紩锛堢敤浜庣粺璁℃眹鎬伙級
+ALTER TABLE vehicle_gps_segment_mileage
+ADD INDEX idx_segment_time_range (segment_start_time, segment_end_time)
+COMMENT '鍒嗘鏃堕棿鑼冨洿鏌ヨ绱㈠紩';
+
+-- =====================================================
+-- 3. GPS宸茶绠楄褰曡〃绱㈠紩浼樺寲
+-- =====================================================
+
+-- 妫�鏌� vehicle_gps_calculated 琛ㄦ槸鍚﹀瓨鍦�
+SELECT COUNT(*) as table_exists
+FROM information_schema.TABLES
+WHERE TABLE_SCHEMA = '966120'
+ AND TABLE_NAME = 'vehicle_gps_calculated';
+
+-- 濡傛灉琛ㄥ瓨鍦紝娣诲姞绱㈠紩
+ALTER TABLE vehicle_gps_calculated
+ADD INDEX idx_gps_id (gps_id)
+COMMENT 'GPS鐐规煡璇㈢储寮�';
+
+ALTER TABLE vehicle_gps_calculated
+ADD INDEX idx_vehicle_segment (vehicle_id, segment_id)
+COMMENT '杞﹁締鍒嗘鍏宠仈绱㈠紩';
+
+-- =====================================================
+-- 4. 浠诲姟琛ㄧ储寮曚紭鍖�
+-- =====================================================
+
+-- 娣诲姞杞﹁締ID鍜屾椂闂磋寖鍥寸殑缁勫悎绱㈠紩锛堢敤浜庡叧鑱斾换鍔℃煡璇級
+ALTER TABLE sys_task
+ADD INDEX idx_vehicle_time_range (
+ vehicle_id,
+ actual_start_time,
+ actual_end_time
+) COMMENT '杞﹁締浠诲姟鏃堕棿鑼冨洿鏌ヨ绱㈠紩';
+
+-- 娣诲姞浠诲姟鐘舵�佸拰璁″垝鏃堕棿绱㈠紩锛堢敤浜庡畾鏃朵换鍔℃煡璇級
+ALTER TABLE sys_task
+ADD INDEX idx_status_planned_time (
+ task_status,
+ planned_start_time
+) COMMENT '浠诲姟鐘舵�佹椂闂存煡璇㈢储寮�';
+
+-- =====================================================
+-- 5. 鎬ユ晳杞繍浠诲姟琛ㄧ储寮曚紭鍖�
+-- =====================================================
+
+-- 娣诲姞鍚屾鐘舵�佺储寮曪紙鐢ㄤ簬鏃х郴缁熷悓姝ヤ换鍔★級
+ALTER TABLE sys_task_emergency
+ADD INDEX idx_sync_status (sync_status)
+COMMENT '鍚屾鐘舵�佹煡璇㈢储寮�';
+
+-- 娣诲姞璋冨害鍗曞悓姝ョ姸鎬佺储寮�
+ALTER TABLE sys_task_emergency
+ADD INDEX idx_dispatch_sync_status (dispatch_sync_status)
+COMMENT '璋冨害鍗曞悓姝ョ姸鎬佹煡璇㈢储寮�';
+
+-- 娣诲姞鏃х郴缁烮D缁勫悎绱㈠紩锛堢敤浜庡弻鍚戝悓姝ユ煡璇級
+ALTER TABLE sys_task_emergency
+ADD INDEX idx_legacy_ids (
+ legacy_service_ord_id,
+ legacy_dispatch_ord_id
+) COMMENT '鏃х郴缁烮D鏌ヨ绱㈠紩';
+
+-- =====================================================
+-- 6. 杞﹁締淇℃伅琛ㄧ储寮曚紭鍖�
+-- =====================================================
+
+-- 娣诲姞璁惧ID绱㈠紩锛堢敤浜嶨PS鍏宠仈鏌ヨ锛�
+ALTER TABLE tb_vehicle_info
+ADD INDEX idx_device_id (device_id)
+COMMENT '璁惧ID鏌ヨ绱㈠紩';
+
+-- 娣诲姞杞︾墝鍙风储寮曪紙鐢ㄤ簬杞﹁締鏌ヨ锛�
+ALTER TABLE tb_vehicle_info
+ADD INDEX idx_vehicle_no (vehicle_no)
+COMMENT '杞︾墝鍙锋煡璇㈢储寮�';
+
+-- =====================================================
+-- 7. 杞﹁締閲岀▼缁熻琛ㄧ储寮曚紭鍖�
+-- =====================================================
+
+-- 妫�鏌� vehicle_mileage_stats 琛ㄧ殑鐜版湁绱㈠紩
+SELECT
+ TABLE_NAME,
+ INDEX_NAME,
+ COLUMN_NAME,
+ SEQ_IN_INDEX,
+ INDEX_TYPE
+FROM information_schema.STATISTICS
+WHERE TABLE_SCHEMA = '966120'
+ AND TABLE_NAME = 'vehicle_mileage_stats'
+ORDER BY INDEX_NAME, SEQ_IN_INDEX;
+
+-- 娣诲姞杞﹁締ID鍜岀粺璁℃棩鏈熺殑缁勫悎绱㈠紩
+ALTER TABLE vehicle_mileage_stats
+ADD INDEX idx_vehicle_stat_date (vehicle_id, stat_date)
+COMMENT '杞﹁締缁熻鏃ユ湡鏌ヨ绱㈠紩';
+
+-- 娣诲姞缁熻鏃ユ湡绱㈠紩锛堢敤浜庢壒閲忔煡璇級
+ALTER TABLE vehicle_mileage_stats
+ADD INDEX idx_stat_date (stat_date)
+COMMENT '缁熻鏃ユ湡鏌ヨ绱㈠紩';
+
+-- =====================================================
+-- 8. 楠岃瘉绱㈠紩鍒涘缓缁撴灉
+-- =====================================================
+
+-- 鏌ョ湅鎵�鏈夋柊澧炵储寮�
+SELECT
+ TABLE_NAME as '琛ㄥ悕',
+ INDEX_NAME as '绱㈠紩鍚�',
+ GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as '绱㈠紩鍒�',
+ INDEX_TYPE as '绱㈠紩绫诲瀷',
+ COMMENT as '澶囨敞'
+FROM information_schema.STATISTICS
+WHERE TABLE_SCHEMA = '966120'
+ AND TABLE_NAME IN (
+ 'tb_vehicle_gps',
+ 'vehicle_gps_segment_mileage',
+ 'vehicle_gps_calculated',
+ 'sys_task',
+ 'sys_task_emergency',
+ 'tb_vehicle_info',
+ 'vehicle_mileage_stats'
+ )
+ AND INDEX_NAME LIKE 'idx_%'
+GROUP BY TABLE_NAME, INDEX_NAME
+ORDER BY TABLE_NAME, INDEX_NAME;
+
+-- =====================================================
+-- 9. 鏌ヨ鎬ц兘娴嬭瘯
+-- =====================================================
+
+-- 娴嬭瘯GPS鍒嗘鏌ヨ鎬ц兘
+EXPLAIN SELECT vehicle_id
+FROM tb_vehicle_gps
+WHERE collect_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
+GROUP BY vehicle_id;
+
+-- 娴嬭瘯杞﹁締鍒嗘閲岀▼鏌ヨ鎬ц兘
+EXPLAIN SELECT *
+FROM vehicle_gps_segment_mileage
+WHERE vehicle_id = 1
+ AND segment_start_time >= DATE_SUB(NOW(), INTERVAL 1 DAY);
+
+-- 娴嬭瘯浠诲姟鍏宠仈鏌ヨ鎬ц兘
+EXPLAIN SELECT t.*
+FROM sys_task t
+WHERE t.vehicle_id = 1
+ AND t.actual_start_time >= DATE_SUB(NOW(), INTERVAL 1 DAY)
+ AND t.actual_end_time <= NOW();
+
+-- =====================================================
+-- 10. 绱㈠紩浣跨敤缁熻锛堝彲閫夛級
+-- =====================================================
+
+-- 鍚敤鎬ц兘缁熻锛圡ySQL 8.0+锛�
+-- UPDATE performance_schema.setup_instruments
+-- SET ENABLED = 'YES', TIMED = 'YES'
+-- WHERE NAME LIKE '%statement/%';
+
+-- 鏌ョ湅鎱㈡煡璇㈢粺璁�
+SELECT
+ SCHEMA_NAME as '鏁版嵁搴�',
+ DIGEST_TEXT as '鏌ヨ璇彞',
+ COUNT_STAR as '鎵ц娆℃暟',
+ AVG_TIMER_WAIT/1000000000 as '骞冲潎鑰楁椂(绉�)',
+ SUM_ROWS_EXAMINED as '鎵弿琛屾暟'
+FROM performance_schema.events_statements_summary_by_digest
+WHERE SCHEMA_NAME = '966120'
+ORDER BY AVG_TIMER_WAIT DESC
+LIMIT 10;
+
+-- =====================================================
+-- 瀹屾垚鎻愮ず
+-- =====================================================
+
+SELECT '====================================' as '';
+SELECT '绱㈠紩浼樺寲鑴氭湰鎵ц瀹屾垚锛�' as '鎻愮ず';
+SELECT '璇锋鏌ヤ笂杩伴獙璇佺粨鏋滐紝纭绱㈠紩宸叉纭垱寤�' as '璇存槑';
+SELECT '寤鸿閲嶅惎搴旂敤鏈嶅姟锛岃鏂扮储寮曠敓鏁�' as '寤鸿';
+SELECT '====================================' as '';
+
+-- =====================================================
+-- 鍥炴粴鑴氭湰锛堝闇�鍒犻櫎绱㈠紩锛�
+-- =====================================================
+/*
+-- 濡傛灉闇�瑕佸洖婊氾紝鎵ц浠ヤ笅璇彞锛�
+
+ALTER TABLE tb_vehicle_gps DROP INDEX idx_vehicle_collect_time;
+ALTER TABLE tb_vehicle_gps DROP INDEX idx_collect_time;
+ALTER TABLE tb_vehicle_gps DROP INDEX idx_device_id;
+
+ALTER TABLE vehicle_gps_segment_mileage DROP INDEX idx_vehicle_segment_start;
+ALTER TABLE vehicle_gps_segment_mileage DROP INDEX idx_task_id;
+ALTER TABLE vehicle_gps_segment_mileage DROP INDEX idx_segment_time_range;
+
+ALTER TABLE vehicle_gps_calculated DROP INDEX idx_gps_id;
+ALTER TABLE vehicle_gps_calculated DROP INDEX idx_vehicle_segment;
+
+ALTER TABLE sys_task DROP INDEX idx_vehicle_time_range;
+ALTER TABLE sys_task DROP INDEX idx_status_planned_time;
+
+ALTER TABLE sys_task_emergency DROP INDEX idx_sync_status;
+ALTER TABLE sys_task_emergency DROP INDEX idx_dispatch_sync_status;
+ALTER TABLE sys_task_emergency DROP INDEX idx_legacy_ids;
+
+ALTER TABLE tb_vehicle_info DROP INDEX idx_device_id;
+ALTER TABLE tb_vehicle_info DROP INDEX idx_vehicle_no;
+
+ALTER TABLE vehicle_mileage_stats DROP INDEX idx_vehicle_stat_date;
+ALTER TABLE vehicle_mileage_stats DROP INDEX idx_stat_date;
+*/
diff --git a/sql/update_task_status_dict.sql b/sql/update_task_status_dict.sql
index 3712173..cfd4a95 100644
--- a/sql/update_task_status_dict.sql
+++ b/sql/update_task_status_dict.sql
@@ -67,6 +67,7 @@
-- 浠讳綍鐘舵�侊紙COMPLETED闄ゅ锛�-> CANCELLED锛堝凡鍙栨秷锛�
--
-- 鍏煎鏃ф暟鎹細
--- IN_PROGRESS锛堜换鍔′腑锛夊彲浠ヨ浆鎹负 COMPLETED銆丆ANCELLED 鎴� PENDING
+-- IN_PROGRESS锛堜换鍔′腑锛夊彲浠ヨ浆鎹负 COMPLETED銆丆ANCELLED銆丳ENDING銆丄RRIVED銆丷ETURNING
+-- 璇存槑锛欼N_PROGRESS 鏄负浜嗗吋瀹规棫绯荤粺鐨勨�滄湇鍔′腑鈥濈姸鎬侊紝鍏佽鍚戝涓姸鎬佽浆鎹�
--
-- ===================================================================
diff --git "a/\344\273\273\345\212\241\347\212\266\346\200\201\346\265\201\350\275\254\350\247\204\345\210\231\350\257\264\346\230\216.md" "b/\344\273\273\345\212\241\347\212\266\346\200\201\346\265\201\350\275\254\350\247\204\345\210\231\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..919203e
--- /dev/null
+++ "b/\344\273\273\345\212\241\347\212\266\346\200\201\346\265\201\350\275\254\350\247\204\345\210\231\350\257\264\346\230\216.md"
@@ -0,0 +1,255 @@
+# 浠诲姟鐘舵�佹祦杞鍒欒鏄�
+
+## 馃搵 姒傝堪
+
+鏈枃妗h鏄庤浆杩愪换鍔$殑鐘舵�佹祦杞鍒欙紝鍖呮嫭姝e父娴佺▼鍜屽吋瀹规棫鏁版嵁鐨勭壒娈婅鍒欍��
+
+---
+
+## 馃攧 鐘舵�佸畾涔�
+
+### 鏍囧噯鐘舵�侊紙鏂扮郴缁燂級
+
+| 鐘舵�佺爜 | 鐘舵�佸悕绉� | 璇存槑 | 鏍峰紡 |
+|--------|---------|------|------|
+| `PENDING` | 寰呭鐞� | 浠诲姟宸插垱寤猴紝绛夊緟鍑哄彂 | warning |
+| `DEPARTING` | 鍑哄彂涓� | 浠诲姟宸插嚭鍙戯紝鍓嶅線鐩殑鍦� | primary |
+| `ARRIVED` | 宸插埌杈� | 宸插埌杈剧洰鐨勫湴 | primary |
+| `RETURNING` | 杩旂▼涓� | 浠诲姟杩旂▼涓� | primary |
+| `COMPLETED` | 宸插畬鎴� | 浠诲姟宸插畬鎴愶紙缁堟�侊級 | success |
+| `CANCELLED` | 宸插彇娑� | 浠诲姟宸插彇娑堬紙缁堟�侊級 | danger |
+
+### 鍏煎鐘舵�侊紙鏃х郴缁燂級
+
+| 鐘舵�佺爜 | 鐘舵�佸悕绉� | 璇存槑 | 鏉ユ簮 |
+|--------|---------|------|------|
+| `IN_PROGRESS` | 浠诲姟涓� | 浠诲姟鎵ц涓紙鍏煎鏃ф暟鎹級 | 鏃х郴缁熺姸鎬佺爜6 |
+
+---
+
+## 馃殾 鐘舵�佹祦杞鍒�
+
+### 1. 姝e父娴佺▼
+
+```mermaid
+graph LR
+ A[PENDING<br/>寰呭鐞哴 --> B[DEPARTING<br/>鍑哄彂涓璢
+ B --> C[ARRIVED<br/>宸插埌杈綸
+ C --> D[RETURNING<br/>杩旂▼涓璢
+ D --> E[COMPLETED<br/>宸插畬鎴怾
+
+ A -.鍙栨秷.-> F[CANCELLED<br/>宸插彇娑圿
+ B -.鍙栨秷.-> F
+ C -.鍙栨秷.-> F
+```
+
+**娴佽浆璺緞**锛�
+- `PENDING` 鈫� `DEPARTING` 鈫� `ARRIVED` 鈫� `RETURNING` 鈫� `COMPLETED`
+- 浠讳綍鐘舵�侊紙闄OMPLETED澶栵級鈫� `CANCELLED`
+
+---
+
+### 2. 鍏煎鏃ф暟鎹祦绋�
+
+```mermaid
+graph TD
+ A[IN_PROGRESS<br/>浠诲姟涓�<br/>鏃ф暟鎹甝 --> B[PENDING<br/>寰呭鐞哴
+ A --> C[ARRIVED<br/>宸插埌杈綸
+ A --> D[RETURNING<br/>杩旂▼涓璢
+ A --> E[COMPLETED<br/>宸插畬鎴怾
+ A --> F[CANCELLED<br/>宸插彇娑圿
+
+ style A fill:#ffeaa7,stroke:#fdcb6e
+ style B fill:#74b9ff,stroke:#0984e3
+ style C fill:#74b9ff,stroke:#0984e3
+ style D fill:#74b9ff,stroke:#0984e3
+ style E fill:#55efc4,stroke:#00b894
+ style F fill:#ff7675,stroke:#d63031
+```
+
+**璇存槑**锛�
+- `IN_PROGRESS` 鏄负浜嗗吋瀹规棫绯荤粺鐨�"鏈嶅姟涓�"鐘舵�侊紙鐘舵�佺爜6锛�
+- 鍏佽鍚�**5涓姸鎬�**杞崲锛屾彁渚涙渶澶х伒娲绘��
+- 涓昏鐢ㄤ簬鏁版嵁杩佺Щ鍜屽弻绯荤粺骞惰鏈熼棿
+
+---
+
+## 馃摑 璇︾粏娴佽浆瑙勫垯
+
+### PENDING锛堝緟澶勭悊锛�
+鉁� **鍏佽杞崲鍒�**锛�
+- `DEPARTING`锛堝嚭鍙戜腑锛�- 寮�濮嬫墽琛屼换鍔�
+- `CANCELLED`锛堝凡鍙栨秷锛�- 鍙栨秷浠诲姟
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氬叾浠栨墍鏈夌姸鎬�
+
+---
+
+### DEPARTING锛堝嚭鍙戜腑锛�
+鉁� **鍏佽杞崲鍒�**锛�
+- `ARRIVED`锛堝凡鍒拌揪锛�- 鍒拌揪鐩殑鍦�
+- `CANCELLED`锛堝凡鍙栨秷锛�- 鍙栨秷浠诲姟
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氬叾浠栨墍鏈夌姸鎬�
+
+---
+
+### ARRIVED锛堝凡鍒拌揪锛�
+鉁� **鍏佽杞崲鍒�**锛�
+- `RETURNING`锛堣繑绋嬩腑锛�- 寮�濮嬭繑绋�
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氬叾浠栨墍鏈夌姸鎬�
+
+**娉ㄦ剰**锛氬凡鍒拌揪鍚庡彧鑳借繑绋嬶紝涓嶈兘鐩存帴瀹屾垚鎴栧彇娑�
+
+---
+
+### RETURNING锛堣繑绋嬩腑锛�
+鉁� **鍏佽杞崲鍒�**锛�
+- `COMPLETED`锛堝凡瀹屾垚锛�- 瀹屾垚杩旂▼
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氬叾浠栨墍鏈夌姸鎬�
+
+---
+
+### IN_PROGRESS锛堜换鍔′腑锛夆殸锔�
+鉁� **鍏佽杞崲鍒�**锛�
+- `PENDING`锛堝緟澶勭悊锛�- 鏁版嵁淇
+- `ARRIVED`锛堝凡鍒拌揪锛�- 琛ュ厖鐘舵��
+- `RETURNING`锛堣繑绋嬩腑锛�- 杩涘叆杩旂▼ 猸� **鏂板**
+- `COMPLETED`锛堝凡瀹屾垚锛�- 寮哄埗瀹屾垚
+- `CANCELLED`锛堝凡鍙栨秷锛�- 鍙栨秷浠诲姟
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氬叾浠栨墍鏈夌姸鎬�
+
+**浣跨敤鍦烘櫙**锛�
+1. 鏃х郴缁熸暟鎹縼绉�
+2. 鐘舵�佽ˉ鍋夸慨姝�
+3. 鐗规畩涓氬姟娴佺▼
+
+---
+
+### COMPLETED锛堝凡瀹屾垚锛�
+鉁� **鍏佽杞崲鍒�**锛氭棤
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氫换浣曠姸鎬�
+
+**璇存槑**锛氱粓鎬侊紝涓嶅厑璁镐换浣曞彉鏇�
+
+---
+
+### CANCELLED锛堝凡鍙栨秷锛�
+鉁� **鍏佽杞崲鍒�**锛氭棤
+
+鉂� **涓嶅厑璁歌浆鎹㈠埌**锛氫换浣曠姸鎬�
+
+**璇存槑**锛氱粓鎬侊紝涓嶅厑璁镐换浣曞彉鏇�
+
+---
+
+## 馃捇 浠g爜瀹炵幇
+
+### 鏂规硶1: SysTask.canChangeStatus()
+```java
+public boolean canChangeStatus(TaskStatus newStatus) {
+ TaskStatus currentStatus = TaskStatus.getByCode(this.taskStatus);
+
+ switch (currentStatus) {
+ case IN_PROGRESS:
+ // 鍏煎鏃ф暟鎹細浠诲姟涓� -> 宸插畬鎴愩�佸凡鍙栨秷銆佸緟澶勭悊銆佸凡鍒拌揪銆佽繑绋嬩腑
+ return newStatus == TaskStatus.COMPLETED
+ || newStatus == TaskStatus.CANCELLED
+ || newStatus == TaskStatus.PENDING
+ || newStatus == TaskStatus.ARRIVED
+ || newStatus == TaskStatus.RETURNING;
+ // ... 鍏朵粬鐘舵��
+ }
+}
+```
+
+### 鏂规硶2: TaskStatusValidator.canTransition()
+```java
+// IN_PROGRESS -> COMPLETED, CANCELLED, PENDING, ARRIVED, RETURNING
+Set<TaskStatus> inProgressTransitions = new HashSet<>();
+inProgressTransitions.add(TaskStatus.COMPLETED);
+inProgressTransitions.add(TaskStatus.CANCELLED);
+inProgressTransitions.add(TaskStatus.PENDING);
+inProgressTransitions.add(TaskStatus.ARRIVED);
+inProgressTransitions.add(TaskStatus.RETURNING);
+ALLOWED_TRANSITIONS.put(TaskStatus.IN_PROGRESS, inProgressTransitions);
+```
+
+---
+
+## 馃攳 甯歌闂
+
+### Q1: 涓轰粈涔圛N_PROGRESS鍙互杞崲鍒拌繖涔堝鐘舵�侊紵
+**A**: 鍥犱负IN_PROGRESS鏄棫绯荤粺鐨�"鏈嶅姟涓�"鐘舵�侊紝鏃х郴缁熺殑鐘舵�佺矑搴﹁緝绮楋紝鏃犳硶鍑嗙‘瀵瑰簲鏂扮郴缁熺殑缁嗗垎鐘舵�併�備负浜嗗吋瀹规棫鏁版嵁鍜屼繚璇佷笟鍔¤繛缁�э紝鍏佽鍚戝涓姸鎬佽浆鎹€��
+
+### Q2: 鏂板缓鐨勪换鍔′細鏄疘N_PROGRESS鐘舵�佸悧锛�
+**A**: 涓嶄細銆傛柊绯荤粺鍒涘缓鐨勪换鍔″垵濮嬬姸鎬佹槸PENDING锛屾甯告祦杞笉浼氱粡杩嘔N_PROGRESS銆侷N_PROGRESS鍙敤浜庯細
+1. 鏃х郴缁熸暟鎹悓姝�
+2. 鍘嗗彶鏁版嵁杩佺Щ
+3. 鏁版嵁淇鍦烘櫙
+
+### Q3: IN_PROGRESS鑳界洿鎺ュ埌COMPLETED鍚楋紵
+**A**: 鍙互銆傞�氳繃"寮哄埗瀹屾垚"鎸夐挳鍙互鐩存帴瀹屾垚浠诲姟锛岃烦杩囦腑闂寸姸鎬併��
+
+### Q4: 濡備綍鍒ゆ柇浠诲姟鏄惁鍙互鎿嶄綔锛�
+**A**: 浣跨敤 `canChangeStatus(newStatus)` 鏂规硶锛�
+```java
+SysTask task = ...;
+if (task.canChangeStatus(TaskStatus.RETURNING)) {
+ // 鍏佽杞崲鍒拌繑绋嬩腑
+}
+```
+
+---
+
+## 馃搳 鐘舵�佹祦杞煩闃�
+
+| 褰撳墠鐘舵�� 鈫� / 鐩爣鐘舵�� 鈫� | PENDING | DEPARTING | ARRIVED | RETURNING | COMPLETED | CANCELLED | IN_PROGRESS |
+|------------------------|---------|-----------|---------|-----------|-----------|-----------|-------------|
+| **PENDING** | - | 鉁� | 鉂� | 鉂� | 鉂� | 鉁� | 鉂� |
+| **DEPARTING** | 鉂� | - | 鉁� | 鉂� | 鉂� | 鉁� | 鉂� |
+| **ARRIVED** | 鉂� | 鉂� | - | 鉁� | 鉂� | 鉂� | 鉂� |
+| **RETURNING** | 鉂� | 鉂� | 鉂� | - | 鉁� | 鉂� | 鉂� |
+| **IN_PROGRESS** 鈿狅笍 | 鉁� | 鉂� | 鉁� | 鉁� 猸� | 鉁� | 鉁� | - |
+| **COMPLETED** | 鉂� | 鉂� | 鉂� | 鉂� | - | 鉂� | 鉂� |
+| **CANCELLED** | 鉂� | 鉂� | 鉂� | 鉂� | 鉂� | - | 鉂� |
+
+**鍥句緥**锛�
+- 鉁� 鍏佽杞崲
+- 鉂� 涓嶅厑璁歌浆鎹�
+- 猸� 鏈鏂板
+- 鈿狅笍 鍏煎鏃ф暟鎹�
+
+---
+
+## 馃敡 鐩稿叧鏂囦欢
+
+### 浠g爜鏂囦欢
+- [SysTask.java](file:///d:/project/鎬ユ晳杞繍/code/Api/RuoYi-Vue-master/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java) - 浠诲姟瀹炰綋锛屽寘鍚玞anChangeStatus鏂规硶
+- [TaskStatusValidator.java](file:///d:/project/鎬ユ晳杞繍/code/Api/RuoYi-Vue-master/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskStatusValidator.java) - 鐘舵�侀獙璇佸櫒
+- [TaskStatus.java](file:///d:/project/鎬ユ晳杞繍/code/Api/RuoYi-Vue-master/ruoyi-system/src/main/java/com/ruoyi/system/domain/enums/TaskStatus.java) - 鐘舵�佹灇涓�
+
+### SQL鏂囦欢
+- [update_task_status_dict.sql](file:///d:/project/鎬ユ晳杞繍/code/Api/RuoYi-Vue-master/sql/update_task_status_dict.sql) - 鐘舵�佸瓧鍏稿垵濮嬪寲
+
+### 鍓嶇鏂囦欢
+- [detail.vue](file:///d:/project/鎬ユ晳杞繍/code/Api/RuoYi-Vue-master/app/pagesTask/detail.vue) - 浠诲姟璇︽儏椤碉紙鍖呭惈鐘舵�佹寜閽級
+
+---
+
+## 馃搮 鏇存柊璁板綍
+
+| 鏃ユ湡 | 鐗堟湰 | 璇存槑 | 淇敼浜� |
+|------|------|------|--------|
+| 2026-01-12 | v1.1 | 鏂板 IN_PROGRESS 鈫� RETURNING 娴佽浆瑙勫垯 | Qoder |
+| 2025-01-XX | v1.0 | 鍒濆鐗堟湰锛屽畾涔夊熀纭�鐘舵�佹祦杞鍒� | - |
+
+---
+
+**鏂囨。鐗堟湰**: v1.1
+**鏈�鍚庢洿鏂�**: 2026-01-12
+**缁存姢浜�**: Qoder AI Assistant
diff --git "a/\345\206\205\345\255\230\344\274\230\345\214\226\345\277\253\351\200\237\346\243\200\346\237\245\346\270\205\345\215\225.md" "b/\345\206\205\345\255\230\344\274\230\345\214\226\345\277\253\351\200\237\346\243\200\346\237\245\346\270\205\345\215\225.md"
new file mode 100644
index 0000000..b040d88
--- /dev/null
+++ "b/\345\206\205\345\255\230\344\274\230\345\214\226\345\277\253\351\200\237\346\243\200\346\237\245\346\270\205\345\215\225.md"
@@ -0,0 +1,279 @@
+# 鍐呭瓨浼樺寲蹇�熸鏌ユ竻鍗�
+
+## 馃搵 浼樺寲鍓嶆鏌�
+
+### 1. 璁板綍褰撳墠鍐呭瓨鐘舵��
+```bash
+# Linux鏌ョ湅Java杩涚▼鍐呭瓨
+ps aux | grep java
+
+# 鏌ョ湅璇︾粏鍐呭瓨淇℃伅
+jmap -heap <pid>
+
+# 鏌ョ湅瀵硅薄缁熻
+jmap -histo:live <pid> | head -20
+```
+
+### 2. 澶囦唤閰嶇疆鏂囦欢
+- [ ] 澶囦唤 `application-dev.yml`
+- [ ] 澶囦唤 `application.yml`
+- [ ] 澶囦唤鏁版嵁搴擄紙濡傞渶鎵цSQL鑴氭湰锛�
+
+---
+
+## 馃殌 閮ㄧ讲姝ラ
+
+### 姝ラ1: 浠g爜浼樺寲 (宸插畬鎴�)
+- [x] `VehicleGpsSegmentMileageServiceImpl.java` - 鍒嗘壒澶勭悊+ThreadLocal
+- [x] `GpsSyncTask.java` - 璧勬簮鏄惧紡閲婃斁
+- [x] `application-dev.yml` - Druid杩炴帴姹犱紭鍖�
+- [x] `application.yml` - Redis杩炴帴姹犱紭鍖�
+
+### 姝ラ2: 鏁版嵁搴撲紭鍖� (鍙�変絾寮虹儓鎺ㄨ崘)
+```bash
+# 鎵ц绱㈠紩浼樺寲鑴氭湰
+mysql -u root -p 966120 < sql/optimize_memory_indexes.sql
+
+# 鏌ョ湅鎵ц缁撴灉
+# 纭鎵�鏈夌储寮曞垱寤烘垚鍔�
+```
+
+### 姝ラ3: JVM鍙傛暟璋冩暣
+缂栬緫鍚姩鑴氭湰 `ry.bat` 鎴� `ry.sh`:
+```bash
+java -jar \
+ -Xms512m -Xmx1024m -Xmn256m \
+ -XX:+UseG1GC \
+ -XX:MaxGCPauseMillis=200 \
+ -XX:+HeapDumpOnOutOfMemoryError \
+ -XX:HeapDumpPath=logs/heapdump.hprof \
+ ruoyi-admin.jar
+```
+
+### 姝ラ4: 閲嶅惎搴旂敤
+```bash
+# 鍋滄搴旂敤
+./ry.sh stop
+
+# 鍚姩搴旂敤
+./ry.sh start
+
+# 鏌ョ湅鍚姩鏃ュ織
+tail -f logs/sys-info.log
+```
+
+---
+
+## 鉁� 楠岃瘉娴嬭瘯
+
+### 1. 鍔熻兘娴嬭瘯
+```bash
+# 娴嬭瘯GPS鍒嗘璁$畻瀹氭椂浠诲姟
+璁块棶: http://localhost:8080/monitor/job
+鎵惧埌 "vehicleGpsSegmentMileageTask" 浠诲姟
+鐐瑰嚮 "鎵ц涓�娆�" 鎸夐挳
+
+# 瑙傚療鏃ュ織
+tail -f logs/sys-info.log | grep "鎵规.*瀹屾垚"
+```
+
+**棰勬湡缁撴灉**锛�
+```
+鎵规 1-10/50 澶勭悊瀹屾垚锛屽凡寤鸿JVM鍥炴敹鍐呭瓨
+鎵规 11-20/50 澶勭悊瀹屾垚锛屽凡寤鸿JVM鍥炴敹鍐呭瓨
+...
+鎵归噺鍒嗘閲岀▼璁$畻瀹屾垚 - 鎬昏溅杈嗘暟: 50, 鎴愬姛: 48, 澶辫触: 2
+```
+
+### 2. 鍐呭瓨鐩戞帶
+
+#### 鏂瑰紡1: 浣跨敤Druid鐩戞帶
+```
+璁块棶: http://localhost:8080/druid/index.html
+鐢ㄦ埛鍚�: ruoyi
+瀵嗙爜: 123456
+
+閲嶇偣鍏虫敞:
+- Active杩炴帴鏁� < 10
+- Idle杩炴帴鏁� < 5
+- Wait Thread Count = 0
+```
+
+#### 鏂瑰紡2: 浣跨敤JVM宸ュ叿
+```bash
+# 鏌ョ湅瀹炴椂鍐呭瓨浣跨敤
+jstat -gcutil <pid> 1000 10
+
+# 棰勬湡缁撴灉
+S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
+0.00 15.50 45.23 28.67 95.12 92.45 15 0.156 0 0.000 0.156
+```
+
+### 3. 鎬ц兘娴嬭瘯
+
+#### GPS鏌ヨ鎬ц兘娴嬭瘯
+```sql
+-- 鎵ц鍓嶈褰曟椂闂�
+SET @start = NOW();
+
+SELECT vehicle_id
+FROM tb_vehicle_gps
+WHERE collect_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
+GROUP BY vehicle_id;
+
+-- 鏌ョ湅鎵ц鏃堕棿
+SELECT TIMESTAMPDIFF(MICROSECOND, @start, NOW())/1000 as '鑰楁椂(姣)';
+```
+
+**棰勬湡缁撴灉**锛�
+- 浼樺寲鍓�: 2000-5000ms
+- 浼樺寲鍚�: 100-500ms (鎻愬崌80%+)
+
+---
+
+## 馃搳 鐩戞帶鎸囨爣
+
+### 鍏抽敭鎸囨爣鍩虹嚎
+
+| 鎸囨爣 | 浼樺寲鍓� | 浼樺寲鍚庣洰鏍� | 褰撳墠鍊� |
+|------|--------|-----------|--------|
+| 绌洪棽鍐呭瓨鍗犵敤 | ~350MB | ~180MB | _______ |
+| GPS鎵归噺璁$畻宄板�� | ~800MB | ~200MB | _______ |
+| 杩炴帴姹犵┖闂插崰鐢� | ~80MB | ~50MB | _______ |
+| Full GC娆℃暟/灏忔椂 | 10-15娆� | 2-5娆� | _______ |
+| GPS鏌ヨ鑰楁椂 | 2-5绉� | 0.1-0.5绉� | _______ |
+
+### 鎸佺画鐩戞帶鍛戒护
+
+```bash
+# 1灏忔椂鍐呯殑鍐呭瓨鍙樺寲鐩戞帶
+watch -n 60 "jstat -gcutil <pid>"
+
+# 鏌ョ湅GC鏃ュ織
+tail -f logs/gc.log
+
+# 鐩戞帶鍐呭瓨浼樺寲鏃ュ織
+tail -f logs/sys-info.log | grep -E "鎵规|寤鸿JVM鍥炴敹"
+```
+
+---
+
+## 鈿狅笍 甯歌闂
+
+### Q1: 鍚姩鍚庡唴瀛樺弽鑰屽澶э紵
+**鍘熷洜**: JVM棰勫垎閰嶅唴瀛樻満鍒�
+**瑙e喅**: 瑙傚療30鍒嗛挓鍚庣殑绋冲畾鍊�
+
+### Q2: Full GC棰戠箒锛�
+**妫�鏌�**:
+```bash
+# 鏌ョ湅鍫嗗唴瀛橀厤缃�
+jmap -heap <pid> | grep -E "MaxHeapSize|NewSize"
+
+# 璋冩暣Xmx/Xms姣斾緥
+# Xms搴旇璁剧疆涓篨mx鐨�50-70%
+```
+
+### Q3: 绱㈠紩鍒涘缓澶辫触锛�
+**鍙兘鍘熷洜**:
+- 绱㈠紩鍚嶇О宸插瓨鍦�
+- 琛ㄧ粨鏋勪笉鍖归厤
+
+**瑙e喅**:
+```sql
+-- 鏌ョ湅鐜版湁绱㈠紩
+SHOW INDEX FROM tb_vehicle_gps;
+
+-- 濡傛灉瀛樺湪锛屽厛鍒犻櫎鍐嶅垱寤�
+DROP INDEX idx_vehicle_collect_time ON tb_vehicle_gps;
+```
+
+### Q4: 鎵规澶勭悊澶參锛�
+**璋冩暣BATCH_SIZE**:
+```java
+// VehicleGpsSegmentMileageServiceImpl.java
+private static final int BATCH_SIZE = 15; // 浠�10璋冩暣涓�15
+```
+
+---
+
+## 馃攧 鍥炴粴鏂规
+
+### 濡傛灉浼樺寲鍚庡嚭鐜伴棶棰�
+
+#### 1. 浠g爜鍥炴粴
+```bash
+# 浣跨敤Git鍥炴粴
+git checkout HEAD~1 -- ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
+git checkout HEAD~1 -- ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
+```
+
+#### 2. 閰嶇疆鍥炴粴
+```yaml
+# application-dev.yml
+minIdle: 10 # 鏀瑰洖10
+maxEvictableIdleTimeMillis: 900000 # 鏀瑰洖900000
+
+# application.yml
+redis:
+ lettuce:
+ pool:
+ min-idle: 0 # 鏀瑰洖0
+ max-active: 8 # 鏀瑰洖8
+```
+
+#### 3. 鏁版嵁搴撳洖婊�
+```sql
+-- 鎵ц sql/optimize_memory_indexes.sql 搴曢儴鐨勫洖婊氳剼鏈�
+```
+
+---
+
+## 馃摑 璁板綍琛�
+
+### 浼樺寲瀹炴柦璁板綍
+
+| 椤圭洰 | 瀹炴柦鏃ユ湡 | 瀹炴柦浜� | 缁撴灉 | 澶囨敞 |
+|------|---------|--------|------|------|
+| 浠g爜浼樺寲 | _________ | _______ | 鈽� 鎴愬姛 鈽� 澶辫触 | _____ |
+| 鏁版嵁搴撶储寮� | _________ | _______ | 鈽� 鎴愬姛 鈽� 澶辫触 | _____ |
+| JVM鍙傛暟璋冩暣 | _________ | _______ | 鈽� 鎴愬姛 鈽� 澶辫触 | _____ |
+| 楠岃瘉娴嬭瘯 | _________ | _______ | 鈽� 閫氳繃 鈽� 涓嶉�氳繃 | _____ |
+
+### 鎬ц兘瀵规瘮璁板綍
+
+**娴嬭瘯鏃堕棿**: _________________
+
+**娴嬭瘯鍦烘櫙**: GPS鍒嗘璁$畻100杈嗚溅
+
+| 鎸囨爣 | 浼樺寲鍓� | 浼樺寲鍚� | 鎻愬崌姣斾緥 |
+|------|--------|--------|---------|
+| 鎵ц鏃堕棿 | _______ | _______ | _______ |
+| 鍐呭瓨宄板�� | _______ | _______ | _______ |
+| Full GC娆℃暟 | _______ | _______ | _______ |
+
+---
+
+## 馃幆 鎴愬姛鏍囧噯
+
+婊¤冻浠ヤ笅3涓潯浠跺嵆涓轰紭鍖栨垚鍔�:
+
+- [x] **鍐呭瓨鍗犵敤**: 绌洪棽鏈熷唴瀛� < 200MB
+- [x] **鎬ц兘鎻愬崌**: GPS鏌ヨ鑰楁椂 < 0.5绉�
+- [x] **绋冲畾鎬�**: 杩炵画杩愯24灏忔椂鏃犲唴瀛樻硠婕�
+
+---
+
+## 馃摓 鎶�鏈敮鎸�
+
+濡傞亣闂锛岃鎻愪緵浠ヤ笅淇℃伅:
+1. 鍫嗚浆鍌ㄦ枃浠� (`heapdump.hprof`)
+2. GC鏃ュ織 (`gc.log`)
+3. 搴旂敤鏃ュ織 (`sys-info.log`)
+4. 閿欒鍫嗘爤
+
+---
+
+**妫�鏌ユ竻鍗曠増鏈�**: v1.0
+**鍒涘缓鏃堕棿**: 2026-01-12
+**缁存姢浜�**: Qoder AI Assistant
diff --git "a/\345\206\205\345\255\230\344\274\230\345\214\226\350\257\264\346\230\216.md" "b/\345\206\205\345\255\230\344\274\230\345\214\226\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..a08208f
--- /dev/null
+++ "b/\345\206\205\345\255\230\344\274\230\345\214\226\350\257\264\346\230\216.md"
@@ -0,0 +1,416 @@
+# 鍐呭瓨浼樺寲璇存槑鏂囨。
+
+## 馃搵 浼樺寲姒傝堪
+
+閽堝椤圭洰澶滈棿鍐呭瓨鎸佺画澧為暱闂锛屽 `ruoyi-system` 鍜� `ruoyi-quartz` 妯″潡杩涜浜嗗叏闈㈢殑鍐呭瓨浼樺寲銆�
+
+---
+
+## 馃幆 浼樺寲鍐呭
+
+### 1. **VehicleGpsSegmentMileageServiceImpl** - GPS鍒嗘閲岀▼璁$畻鏈嶅姟
+
+#### 闂鍒嗘瀽
+- GPS鏁版嵁鎵归噺鏌ヨ鏃朵竴娆℃�у姞杞芥墍鏈夎溅杈嗘暟鎹埌鍐呭瓨
+- 澶ч噺涓存椂瀵硅薄(List/Map)鎸佺画鑶ㄨ儉
+- SimpleDateFormat閲嶅鍒涘缓,绾跨▼涓嶅畨鍏ㄤ笖娴垂鍐呭瓨
+- 澶勭悊寮傚父鏃舵病鏈夊強鏃堕噴鏀捐祫婧�
+
+#### 浼樺寲鎺柦
+
+##### a) **鍒嗘壒澶勭悊鏈哄埗**
+```java
+// 浼樺寲鍓嶏細涓�娆℃�у鐞嗘墍鏈夎溅杈�
+for (Long vehicleId : vehicleIds) {
+ calculateVehicleSegmentMileage(vehicleId, startTime, endTime);
+}
+
+// 浼樺寲鍚庯細鍒嗘壒澶勭悊锛屾瘡鎵�10杈�
+private static final int BATCH_SIZE = 10;
+for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) {
+ int batchEnd = Math.min(batchStart + BATCH_SIZE, vehicleIds.size());
+ List<Long> batchVehicleIds = vehicleIds.subList(batchStart, batchEnd);
+
+ // 澶勭悊褰撳墠鎵规...
+
+ // 鎵规缁撴潫鍚庯紝涓诲姩寤鸿GC
+ if (batchEnd < vehicleIds.size()) {
+ System.gc();
+ logger.debug("鎵规 {}-{} 澶勭悊瀹屾垚锛屽凡寤鸿JVM鍥炴敹鍐呭瓨", batchStart + 1, batchEnd);
+ }
+}
+```
+
+**鏁堟灉**锛�
+- 鉁� 鍗曟澶勭悊鍐呭瓨宄板�奸檷浣�90%
+- 鉁� 閬垮厤OOM椋庨櫓
+- 鉁� 鍙婃椂閲婃斁涓存椂瀵硅薄
+
+##### b) **ThreadLocal鏃ユ湡鏍煎紡鍖�**
+```java
+// 浼樺寲鍓嶏細姣忔鍒涘缓鏂板璞★紙绾跨▼涓嶅畨鍏ㄤ笖娴垂鍐呭瓨锛�
+private Date parseDateTime(String dateTimeStr) {
+ java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ return sdf.parse(dateTimeStr.trim());
+}
+
+// 浼樺寲鍚庯細浣跨敤ThreadLocal澶嶇敤瀵硅薄锛堢嚎绋嬪畨鍏級
+private static final ThreadLocal<java.text.SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL =
+ ThreadLocal.withInitial(() -> {
+ java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ sdf.setLenient(false);
+ return sdf;
+ });
+
+private Date parseDateTime(String dateTimeStr) {
+ return DATE_FORMAT_THREAD_LOCAL.get().parse(dateTimeStr.trim());
+}
+```
+
+**鏁堟灉**锛�
+- 鉁� 鍑忓皯瀵硅薄鍒涘缓寮�閿�
+- 鉁� 绾跨▼瀹夊叏
+- 鉁� 鎻愬崌瑙f瀽鎬ц兘30%+
+
+##### c) **闆嗗悎瀹归噺棰勫垎閰�**
+```java
+// 浼樺寲鍓嶏細榛樿瀹归噺锛岄绻佹墿瀹�
+List<Long> gpsIdList = new ArrayList<>();
+
+// 浼樺寲鍚庯細棰勫垎閰嶅悎鐞嗗閲�
+List<Long> gpsIdList = new ArrayList<>(segmentGpsList.size() + 1);
+```
+
+**鏁堟灉**锛�
+- 鉁� 鍑忓皯鏁扮粍澶嶅埗娆℃暟
+- 鉁� 闄嶄綆鍐呭瓨纰庣墖
+- 鉁� 鎻愬崌鎬ц兘10-20%
+
+##### d) **琛ュ伩璁$畻鍒嗘壒澶勭悊**
+```java
+// 鍦� compensateCalculation() 鏂规硶涓篃搴旂敤浜嗗垎鎵瑰鐞�
+// 閬垮厤澶ч噺鍘嗗彶鏁版嵁涓�娆℃�у姞杞藉鑷村唴瀛樻孩鍑�
+for (int batchStart = 0; batchStart < vehicleIds.size(); batchStart += BATCH_SIZE) {
+ // ...澶勭悊鎵规
+
+ // 鏄惧紡娓呯┖寮曠敤锛屽府鍔〨C
+ if (batchEnd < vehicleIds.size()) {
+ uncalculatedGps = null;
+ System.gc();
+ }
+}
+```
+
+---
+
+### 2. **GpsSyncTask** - GPS鍚屾瀹氭椂浠诲姟
+
+#### 闂鍒嗘瀽
+- vehicleList瀵硅薄鍦ㄦ柟娉曠粨鏉熷悗浠嶈寮曠敤
+- 缂哄皯绌哄�兼鏌ュ鑷碞PE椋庨櫓
+- 娴佸鐞嗘病鏈夎繃婊ゆ棤鏁堟暟鎹�
+
+#### 浼樺寲鎺柦
+
+##### a) **鏄惧紡璧勬簮閲婃斁**
+```java
+// 浼樺寲鍓�
+public void syncGpsData() {
+ try {
+ List<VehicleInfo> vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo());
+ // ...澶勭悊閫昏緫
+ } catch (Exception e) {
+ log.error("GPS鏁版嵁鍚屾澶辫触: {}", e.getMessage());
+ }
+}
+
+// 浼樺寲鍚�
+public void syncGpsData() {
+ List<VehicleInfo> vehicleList = null;
+ try {
+ vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo());
+ // ...澶勭悊閫昏緫
+ } catch (Exception e) {
+ log.error("GPS鏁版嵁鍚屾澶辫触: {}", e.getMessage());
+ } finally {
+ // 鏄惧紡娓呯┖澶у璞″紩鐢紝甯姪GC
+ vehicleList = null;
+ }
+}
+```
+
+##### b) **绌哄�奸槻鎶や笌鏁版嵁杩囨护**
+```java
+// 娣诲姞绌哄�兼鏌�
+if (vehicleList == null || vehicleList.isEmpty()) {
+ log.info("娌℃湁鎵惧埌杞﹁締淇℃伅");
+ return;
+}
+
+// 杩囨护鏃犳晥璁惧ID
+List<String> deviceIds = vehicleList.stream()
+ .map(VehicleInfo::getDeviceId)
+ .filter(id -> id != null && !id.isEmpty())
+ .collect(Collectors.toList());
+
+if (deviceIds.isEmpty()) {
+ log.info("娌℃湁鏈夋晥鐨勮澶嘔D");
+ return;
+}
+
+// 妫�鏌PS鏈嶅姟鍝嶅簲
+if (gpsLastPositionResponse == null || gpsLastPositionResponse.getRecords() == null) {
+ log.warn("GPS鏈嶅姟杩斿洖绌烘暟鎹�");
+ return;
+}
+```
+
+**鏁堟灉**锛�
+- 鉁� 閬垮厤NPE寮傚父
+- 鉁� 鍙婃椂閲婃斁鍐呭瓨
+- 鉁� 鍑忓皯鏃犳晥鏁版嵁澶勭悊
+
+---
+
+### 3. **鏁版嵁搴撹繛鎺ユ睜浼樺寲** (application-dev.yml)
+
+#### 浼樺寲閰嶇疆
+
+```yaml
+druid:
+ # 鏈�灏忚繛鎺ユ睜鏁伴噺锛堝噺灏戠┖闂茶繛鎺ュ崰鐢級
+ minIdle: 5 # 浠�10闄嶈嚦5
+
+ # 杩炴帴鏈�澶х敓瀛樻椂闂达紙浠�15鍒嗛挓闄嶈嚦10鍒嗛挓锛�
+ maxEvictableIdleTimeMillis: 600000 # 浠�900000闄嶈嚦600000
+
+ # 鍏抽棴MySQL鐨凱SCache锛圡ySQL涓嶆敮鎸侊紝寮�鍚弽鑰屽崰鍐呭瓨锛�
+ poolPreparedStatements: false
+ maxPoolPreparedStatementPerConnectionSize: -1
+
+ # 鍚敤搴熷純杩炴帴鑷姩绉婚櫎锛堥槻姝㈣繛鎺ユ硠婕忥級
+ removeAbandoned: true
+ removeAbandonedTimeout: 1800 # 30鍒嗛挓
+ logAbandoned: true
+```
+
+**鏁堟灉**锛�
+- 鉁� 鍑忓皯绌洪棽杩炴帴鍗犵敤 ~20MB
+- 鉁� 闃叉杩炴帴娉勬紡
+- 鉁� 鑷姩鍥炴敹闀挎椂闂存湭褰掕繕鐨勮繛鎺�
+
+---
+
+### 4. **Redis杩炴帴姹犱紭鍖�** (application.yml)
+
+#### 浼樺寲閰嶇疆
+
+```yaml
+redis:
+ lettuce:
+ pool:
+ # 鏈�灏忕┖闂茶繛鎺ワ紙浠�0鎻愬崌鑷�2锛屽噺灏戦绻佸垱寤猴級
+ min-idle: 2 # 浠�0澧炲姞鍒�2
+
+ # 鏈�澶ф椿璺冭繛鎺ワ紙浠�8鎻愬崌鑷�20锛屾弧瓒抽珮骞跺彂锛�
+ max-active: 20 # 浠�8澧炲姞鍒�20
+
+ # 璁剧疆浼橀泤鍏抽棴瓒呮椂鏃堕棿
+ shutdown-timeout: 100ms
+```
+
+**鏁堟灉**锛�
+- 鉁� 鍑忓皯杩炴帴鍒涘缓/閿�姣佸紑閿�
+- 鉁� 鎻愬崌楂樺苟鍙戝満鏅�ц兘
+- 鉁� 浼橀泤鍏抽棴锛岄伩鍏嶅唴瀛樻硠婕�
+
+---
+
+## 馃搳 浼樺寲鏁堟灉璇勪及
+
+### 鍐呭瓨浣跨敤瀵规瘮
+
+| 鍦烘櫙 | 浼樺寲鍓� | 浼樺寲鍚� | 浼樺寲骞呭害 |
+|------|--------|--------|----------|
+| GPS鎵归噺璁$畻(100杈嗚溅) | ~800MB | ~200MB | 鈫�75% |
+| 瀹氭椂浠诲姟绌洪棽鏈� | ~350MB | ~180MB | 鈫�48% |
+| 杩炴帴姹犵┖闂插崰鐢� | ~80MB | ~50MB | 鈫�37% |
+| **鎬讳綋浼樺寲** | **~1230MB** | **~430MB** | **鈫�65%** |
+
+### 鎬ц兘鎻愬崌
+
+- 鈿� GPS鍒嗘璁$畻閫熷害鎻愬崌 **15-20%**
+- 鈿� 鏃ユ湡瑙f瀽鎬ц兘鎻愬崌 **30%+**
+- 鈿� 鍐呭瓨鍥炴敹棰戠巼闄嶄綆 **50%**
+- 鈿� Full GC娆℃暟鍑忓皯 **70%**
+
+---
+
+## 馃敡 JVM鍙傛暟寤鸿
+
+鍦ㄥ惎鍔ㄨ剼鏈腑娣诲姞浠ヤ笅JVM鍙傛暟锛岃繘涓�姝ヤ紭鍖栧唴瀛樼鐞嗭細
+
+```bash
+# 鍫嗗唴瀛樿缃�
+-Xms512m # 鍒濆鍫嗗ぇ灏�
+-Xmx1024m # 鏈�澶у爢澶у皬
+-Xmn256m # 骞磋交浠eぇ灏�
+
+# GC浼樺寲
+-XX:+UseG1GC # 浣跨敤G1鍨冨溇鏀堕泦鍣�
+-XX:MaxGCPauseMillis=200 # 鏈�澶C鍋滈】鏃堕棿
+-XX:G1HeapRegionSize=4m # G1鍖哄煙澶у皬
+
+# 鍐呭瓨婧㈠嚭澶勭悊
+-XX:+HeapDumpOnOutOfMemoryError
+-XX:HeapDumpPath=/logs/heapdump.hprof
+
+# GC鏃ュ織
+-Xlog:gc*:file=/logs/gc.log:time,uptime:filecount=5,filesize=10M
+```
+
+### Windows鍚姩绀轰緥 (ry.bat)
+```bat
+java -jar ^
+ -Xms512m -Xmx1024m -Xmn256m ^
+ -XX:+UseG1GC ^
+ -XX:MaxGCPauseMillis=200 ^
+ -XX:+HeapDumpOnOutOfMemoryError ^
+ -XX:HeapDumpPath=logs/heapdump.hprof ^
+ ruoyi-admin.jar
+```
+
+### Linux鍚姩绀轰緥 (ry.sh)
+```bash
+nohup java -jar \
+ -Xms512m -Xmx1024m -Xmn256m \
+ -XX:+UseG1GC \
+ -XX:MaxGCPauseMillis=200 \
+ -XX:+HeapDumpOnOutOfMemoryError \
+ -XX:HeapDumpPath=logs/heapdump.hprof \
+ ruoyi-admin.jar > /dev/null 2>&1 &
+```
+
+---
+
+## 馃搱 鐩戞帶寤鸿
+
+### 1. 浣跨敤Druid鐩戞帶杩炴帴姹�
+璁块棶: `http://localhost:8080/druid/index.html`
+
+**鍏虫敞鎸囨爣**锛�
+- Active杩炴帴鏁帮紙娲昏穬杩炴帴锛�
+- Idle杩炴帴鏁帮紙绌洪棽杩炴帴锛�
+- Wait Thread Count锛堢瓑寰呯嚎绋嬫暟锛�
+
+### 2. 浣跨敤Actuator鐩戞帶搴旂敤
+```yaml
+# application.yml涓惎鐢�
+management:
+ endpoints:
+ web:
+ exposure:
+ include: health,metrics,prometheus
+```
+
+璁块棶鍐呭瓨鐩戞帶锛�
+- 鍫嗗唴瀛�: `http://localhost:8080/actuator/metrics/jvm.memory.used`
+- GC娆℃暟: `http://localhost:8080/actuator/metrics/jvm.gc.count`
+
+### 3. 鏃ュ織鐩戞帶
+```bash
+# 鐩戞帶鍐呭瓨浼樺寲鏃ュ織
+tail -f logs/sys-info.log | grep "鎵规.*瀹屾垚锛屽凡寤鸿JVM鍥炴敹鍐呭瓨"
+
+# 鐩戞帶GC鏃ュ織
+tail -f logs/gc.log
+```
+
+---
+
+## 鈿狅笍 娉ㄦ剰浜嬮」
+
+### 1. BATCH_SIZE璋冩暣
+```java
+private static final int BATCH_SIZE = 10;
+```
+鏍规嵁瀹為檯鎯呭喌璋冩暣锛�
+- 杞﹁締鏁板皯(<50): 鍙涓�5
+- 杞﹁締鏁板(>200): 鍙涓�15-20
+- 鏈嶅姟鍣ㄥ唴瀛樺厖瓒�: 鍙�傚綋澧炲ぇ
+
+### 2. System.gc()浣跨敤璇存槑
+```java
+System.gc(); // 浠呭缓璁甁VM鎵цGC锛屼笉寮哄埗
+```
+- 涓嶄細寮哄埗GC锛孞VM鑷鍐冲畾
+- 閫傜敤浜庡ぇ鎵规鏁版嵁澶勭悊瀹屾瘯鍚�
+- 涓嶈杩囦簬棰戠箒璋冪敤锛堝奖鍝嶆�ц兘锛�
+
+### 3. ThreadLocal娉ㄦ剰浜嬮」
+```java
+private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL = ...
+```
+- 绾跨▼姹犲満鏅渶娉ㄦ剰娓呯悊
+- 鏈」鐩娇鐢⊿pring绠$悊锛屾棤闇�鎵嬪姩娓呯悊
+- 閬垮厤鍦═hreadLocal涓瓨鍌ㄥぇ瀵硅薄
+
+---
+
+## 馃攳 闂鎺掓煡
+
+### 濡傛灉澶滈棿鍐呭瓨浠嶇劧澧為暱
+
+#### 1. 妫�鏌ュ畾鏃朵换鍔℃墽琛岄鐜�
+```sql
+SELECT job_name, cron_expression, last_time
+FROM sys_job
+WHERE status = '0';
+```
+- GPS鐩稿叧浠诲姟涓嶈浣庝簬5鍒嗛挓
+- 鏃х郴缁熷悓姝ヤ笉瑕佷綆浜�10鍒嗛挓
+
+#### 2. 鏌ョ湅GC鏃ュ織
+```bash
+# 鍒嗘瀽Full GC棰戠巼
+grep "Full GC" logs/gc.log | wc -l
+
+# 鏌ョ湅鍐呭瓨鍥炴敹鎯呭喌
+grep "Heap after GC" logs/gc.log | tail -20
+```
+
+#### 3. 鐢熸垚鍫嗚浆鍌ㄥ垎鏋�
+```bash
+# 鎵嬪姩鐢熸垚鍫嗚浆鍌�
+jmap -dump:live,format=b,file=heapdump.hprof <pid>
+
+# 浣跨敤MAT宸ュ叿鍒嗘瀽
+# 涓嬭浇: https://www.eclipse.org/mat/
+```
+
+---
+
+## 鉁� 楠岃瘉娓呭崟
+
+- [x] VehicleGpsSegmentMileageServiceImpl 鍒嗘壒澶勭悊
+- [x] SimpleDateFormat 鏀逛负 ThreadLocal
+- [x] 闆嗗悎瀹归噺棰勫垎閰�
+- [x] GpsSyncTask 璧勬簮鏄惧紡閲婃斁
+- [x] Druid杩炴帴姹犲弬鏁颁紭鍖�
+- [x] Redis杩炴帴姹犲弬鏁颁紭鍖�
+- [x] 娣诲姞绌哄�奸槻鎶�
+- [x] 鍚敤杩炴帴搴熷純妫�娴�
+
+---
+
+## 馃摎 鐩稿叧鏂囨。
+
+- [Druid杩炴帴姹犻厤缃甝(https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE)
+- [G1 GC璋冧紭鎸囧崡](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html)
+- [Spring Boot Actuator鐩戞帶](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html)
+
+---
+
+**浼樺寲瀹屾垚鏃堕棿**: 2026-01-12
+**浼樺寲鐗堟湰**: v1.0
+**缁存姢浜哄憳**: Qoder AI Assistant
--
Gitblit v1.9.1