From d294abb765e4ed349907c92ce313689c6299ba7d Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期二, 02 十二月 2025 00:17:00 +0800
Subject: [PATCH] feat:地图都改为天地图的接口

---
 ruoyi-admin/src/main/resources/application-test.yml                                               |    4 
 sql/optimize_gps_query_performance.sql                                                            |   71 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java                          |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java      |   16 
 ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml                          |    6 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java                |   66 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java              |   45 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IWechatTaskNotifyService.java                 |   33 
 ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java                          |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java       |  122 +
 sql/add_legacy_service_ord_no.sql                                                                 |   17 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java   |   18 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java                          |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java                                   |   12 
 ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml                        |    3 
 sql/fix_duplicate_mileage_stats.sql                                                               |   32 
 GPS分段里程计算超时问题修复说明.md                                                                              |  315 +++
 app/pages/index.vue                                                                               | 1664 +++++++++++---------
 ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java                     |   30 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java                   |   18 
 ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml                       |   13 
 ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java                              |   22 
 sql/add_gps_collect_time_index.sql                                                                |   19 
 旧系统ServiceOrdNo字段同步功能说明.md                                                                        |  244 +++
 ruoyi-admin/src/main/resources/application.yml                                                    |    7 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java                             |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/WechatTaskNotifyServiceImpl.java         |  169 ++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java |   40 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java                            |   11 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java                             |    2 
 ruoyi-admin/src/main/resources/application-prod.yml                                               |    4 
 ruoyi-ui/src/views/task/general/index.vue                                                         |   22 
 app/pagesTask/detail.vue                                                                          |   32 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java                  |    2 
 ruoyi-admin/src/main/resources/application-dev.yml                                                |    4 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/PlateNumberExtractor.java                       |   52 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsCollectServiceImpl.java               |   12 
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                                   |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java                              |    9 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java        |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java                   |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java                          |    5 
 ruoyi-ui/src/api/task.js                                                                          |    9 
 app/api/wechat.js                                                                                 |    8 
 app/utils/subscribe.js                                                                            |  327 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java                          |   11 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java               |  530 ++++-
 ruoyi-ui/src/views/system/gps/index.vue                                                           |   14 
 app/api/map.js                                                                                    |   26 
 ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml                            |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java                                |   83 +
 ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml                                |    5 
 ruoyi-ui/src/views/task/vehicle/index.vue                                                         |  205 ++
 ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java                                  |    1 
 ruoyi-admin/pom.xml                                                                               |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java                 |   20 
 app/pagesTask/create-emergency.vue                                                                |    8 
 app/pages/message/index.vue                                                                       |   60 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java           |   66 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java                  |   11 
 ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml                                   |   10 
 sql/gps_compensation_job.sql                                                                      |   38 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java                   |   80 +
 63 files changed, 3,671 insertions(+), 1,016 deletions(-)

diff --git "a/GPS\345\210\206\346\256\265\351\207\214\347\250\213\350\256\241\347\256\227\350\266\205\346\227\266\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md" "b/GPS\345\210\206\346\256\265\351\207\214\347\250\213\350\256\241\347\256\227\350\266\205\346\227\266\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..17b39ef
--- /dev/null
+++ "b/GPS\345\210\206\346\256\265\351\207\214\347\250\213\350\256\241\347\256\227\350\266\205\346\227\266\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
@@ -0,0 +1,315 @@
+# GPS鍒嗘閲岀▼璁$畻浠诲姟瓒呮椂闂淇璇存槑
+
+## 闂鎻忚堪
+
+GPS鍒嗘閲岀▼璁$畻瀹氭椂浠诲姟鎵ц鏃跺嚭鐜版暟鎹簱杩炴帴瓒呮椂閿欒锛�
+
+```
+ERROR c.r.q.t.VehicleGpsSegmentMileageTask - GPS鍒嗘閲岀▼璁$畻浠诲姟鎵ц澶辫触
+java.lang.RuntimeException: 鎵归噺璁$畻澶辫触: 
+### Error querying database.  Cause: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
+The last packet successfully received from the server was 60,022 milliseconds ago.
+```
+
+## 闂鍘熷洜
+
+1. **鏁版嵁搴揝ocket瓒呮椂閰嶇疆杩囩煭**锛歚socketTimeout: 60000`锛�60绉掞級锛屽浜庡ぇ鏁版嵁閲廏PS鏌ヨ澶勭悊涓嶈冻
+2. **鏌ヨ鎬ц兘涓嶄匠**锛氱己灏戝繀瑕佺殑鏁版嵁搴撶储寮曪紝瀵艰嚧澶ц〃鎵弿鑰楁椂杩囬暱
+3. **閿欒澶勭悊涓嶅畬鍠�**锛氬崟涓溅杈嗚绠楀け璐ヤ細褰卞搷鏁翠釜鎵瑰鐞嗘祦绋�
+4. **缂哄皯杩涘害鏃ュ織**锛氭棤娉曚簡瑙f壒閲忓鐞嗙殑瀹炴椂杩涘害
+
+## 瑙e喅鏂规
+
+### 1. 澧炲姞鏁版嵁搴撹繛鎺ヨ秴鏃舵椂闂�
+
+**淇敼鏂囦欢**锛�
+- `ruoyi-admin/src/main/resources/application-dev.yml`
+- `ruoyi-admin/src/main/resources/application-test.yml`
+- `ruoyi-admin/src/main/resources/application-prod.yml`
+
+**淇敼鍐呭**锛�
+```yaml
+# 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛堜粠60绉掑鍔犲埌5鍒嗛挓锛�
+socketTimeout: 300000
+```
+
+**鍘熷洜**锛欸PS鍒嗘閲岀▼璁$畻闇�瑕佸鐞嗗ぇ閲忔暟鎹紝60绉掔殑瓒呮椂鏃堕棿涓嶈冻浠ュ畬鎴愭煡璇㈡搷浣溿�傚鍔犲埌5鍒嗛挓锛�300绉掞級鍙互閬垮厤姝e父鏌ヨ琚鍒や负瓒呮椂銆�
+
+### 2. 浼樺寲鏁版嵁搴撶储寮�
+
+**鎵цSQL鏂囦欢**锛歚sql/optimize_gps_query_performance.sql`
+
+**鍏抽敭绱㈠紩**锛�
+```sql
+-- 缁勫悎绱㈠紩锛歷ehicle_id + collect_time
+ALTER TABLE tb_vehicle_gps 
+ADD INDEX idx_vehicle_collect_time (vehicle_id, collect_time);
+
+-- 鍗曞垪绱㈠紩锛歝ollect_time
+ALTER TABLE tb_vehicle_gps 
+ADD INDEX idx_collect_time (collect_time);
+
+-- tb_vehicle_gps_calculated琛ㄧ储寮�
+ALTER TABLE tb_vehicle_gps_calculated 
+ADD INDEX idx_gps_id (gps_id);
+ADD INDEX idx_vehicle_id (vehicle_id);
+```
+
+**鏁堟灉**锛�
+- 澶у箙鎻愬崌鎸夎溅杈咺D鍜屾椂闂磋寖鍥存煡璇㈢殑鎬ц兘
+- 浼樺寲娲昏穬杞﹁締鏌ヨ閫熷害
+- 鏀瑰杽LEFT JOIN鏌ヨ鎬ц兘
+
+### 3. 澧炲己鎵瑰鐞嗛敊璇鐞�
+
+**淇敼鏂囦欢**锛歚VehicleGpsSegmentMileageServiceImpl.java`
+
+**鏀硅繘鐐�**锛�
+1. **鍗曡溅澶辫触涓嶅奖鍝嶅叏灞�**锛氬崟涓溅杈嗚绠楀け璐ヤ笉浼氫腑鏂暣涓壒澶勭悊
+2. **璇︾粏鐨勮繘搴︽棩蹇�**锛氭瘡澶勭悊10杈嗚溅杈撳嚭涓�娆¤繘搴�
+3. **鎴愬姛/澶辫触缁熻**锛氳褰曟垚鍔熷拰澶辫触鐨勮溅杈嗘暟閲�
+4. **鏇磋缁嗙殑閿欒淇℃伅**锛氬寘鍚爢鏍堣窡韪紝渚夸簬闂瀹氫綅
+
+**浠g爜鏀硅繘**锛�
+```java
+int successCount = 0;
+int failedCount = 0;
+
+for (int i = 0; i < vehicleIds.size(); i++) {
+    try {
+        // 澶勭悊鍗曚釜杞﹁締
+        int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime);
+        if (segmentCount > 0) {
+            successCount++;
+        }
+    } catch (Exception e) {
+        failedCount++;
+        logger.error("璁$畻杞﹁締澶辫触锛屼絾缁х画澶勭悊涓嬩竴杈�", e);
+        // 涓嶄腑鏂壒澶勭悊
+    }
+    
+    // 杩涘害鏃ュ織
+    if ((i + 1) % 10 == 0) {
+        logger.info("杩涘害: {}/{}, 鎴愬姛: {}, 澶辫触: {}", ...);
+    }
+}
+```
+
+## 閮ㄧ讲姝ラ
+
+### 1. 鏁版嵁搴撲紭鍖栵紙蹇呴』锛�
+
+```bash
+# 杩炴帴鍒癕ySQL鏁版嵁搴�
+mysql -u root -p
+
+# 鎵ц绱㈠紩浼樺寲SQL
+source sql/optimize_gps_query_performance.sql
+
+# 楠岃瘉绱㈠紩鍒涘缓鎴愬姛
+SHOW INDEX FROM tb_vehicle_gps;
+SHOW INDEX FROM tb_vehicle_gps_calculated;
+```
+
+### 2. 搴旂敤閰嶇疆鏇存柊锛堝繀椤伙級
+
+1. 澶囦唤褰撳墠閰嶇疆鏂囦欢
+2. 鏇存柊閰嶇疆鏂囦欢涓殑`socketTimeout`鍙傛暟
+3. 閲嶅惎搴旂敤鏈嶅姟
+
+```bash
+# 鍋滄鏈嶅姟
+./ry.sh stop
+
+# 鍚姩鏈嶅姟
+./ry.sh start
+
+# 鏌ョ湅鏃ュ織
+tail -f logs/sys-info.log
+```
+
+### 3. 楠岃瘉淇鏁堟灉
+
+1. **鎵嬪姩瑙﹀彂瀹氭椂浠诲姟**锛�
+   - 鐧诲綍鍚庡彴绠$悊绯荤粺
+   - 杩涘叆銆愮郴缁熺洃鎺с��->銆愬畾鏃朵换鍔°��
+   - 鎵惧埌"GPS鍒嗘閲岀▼瀹炴椂璁$畻"浠诲姟
+   - 鐐瑰嚮銆愭墽琛屼竴娆°�戞寜閽�
+
+2. **鏌ョ湅鎵ц鏃ュ織**锛�
+```bash
+# 鏌ョ湅GPS璁$畻鏃ュ織
+grep "VehicleGpsSegmentMileageTask" logs/sys-info.log
+
+# 鏌ョ湅鎴愬姛/澶辫触缁熻
+grep "鎵归噺鍒嗘閲岀▼璁$畻瀹屾垚" logs/sys-info.log
+```
+
+3. **妫�鏌ユ暟鎹簱**锛�
+```sql
+-- 鏌ョ湅鏈�鏂扮殑鍒嗘閲岀▼璁板綍
+SELECT * FROM tb_vehicle_gps_segment_mileage 
+ORDER BY create_time DESC 
+LIMIT 10;
+
+-- 缁熻浠婃棩澶勭悊鐨勮溅杈嗘暟
+SELECT COUNT(DISTINCT vehicle_id) as vehicle_count
+FROM tb_vehicle_gps_segment_mileage
+WHERE DATE(create_time) = CURDATE();
+```
+
+## 鎬ц兘鐩戞帶寤鸿
+
+### 1. 瀹氭椂浠诲姟鎵ц鏃堕棿鐩戞帶
+
+鍦ㄥ畾鏃朵换鍔$鐞嗕腑鏌ョ湅鎵ц鏃堕暱锛�
+- 姝e父鎯呭喌锛氭瘡5鍒嗛挓鎵ц涓�娆★紝澶勭悊10鍒嗛挓鏁版嵁锛屽簲鍦�1-2鍒嗛挓鍐呭畬鎴�
+- 寮傚父鎯呭喌锛氳秴杩�3鍒嗛挓闇�瑕佸叧娉紝鍙兘瀛樺湪鎬ц兘闂
+
+### 2. 鏁版嵁搴撴參鏌ヨ鏃ュ織
+
+妫�鏌ySQL鎱㈡煡璇㈡棩蹇楋細
+```sql
+-- 鏌ョ湅鎱㈡煡璇㈤厤缃�
+SHOW VARIABLES LIKE 'slow_query%';
+SHOW VARIABLES LIKE 'long_query_time';
+
+-- 鍚敤鎱㈡煡璇㈡棩蹇楋紙濡傛灉鏈惎鐢級
+SET GLOBAL slow_query_log = 'ON';
+SET GLOBAL long_query_time = 2;
+```
+
+### 3. Druid鐩戞帶
+
+璁块棶Druid鐩戞帶椤甸潰锛歚http://your-domain/druid/`
+- 鐢ㄦ埛鍚嶏細ruoyi
+- 瀵嗙爜锛�123456
+
+鍏虫敞鎸囨爣锛�
+- SQL鎵ц鏃堕棿
+- 杩炴帴姹犱娇鐢ㄦ儏鍐�
+- 鎱QL鍒楄〃
+
+## 鍚庣画浼樺寲寤鸿
+
+### 1. 瀹氭湡娓呯悊鍘嗗彶鏁版嵁
+
+GPS鏁版嵁閲忓ぇ锛屽缓璁畾鏈熸竻鐞嗗巻鍙叉暟鎹細
+
+```sql
+-- 淇濈暀鏈�杩�90澶╃殑GPS鍘熷鏁版嵁
+DELETE FROM tb_vehicle_gps 
+WHERE collect_time < DATE_SUB(NOW(), INTERVAL 90 DAY);
+
+-- 浼樺寲琛ㄧ┖闂�
+OPTIMIZE TABLE tb_vehicle_gps;
+```
+
+鍙互鍒涘缓瀹氭椂浠诲姟姣忔湀鎵ц涓�娆°��
+
+### 2. 鍒嗘壒澶勭悊澶ч噺杞﹁締
+
+濡傛灉杞﹁締鏁伴噺瓒呰繃1000杈嗭紝寤鸿淇敼鎵瑰鐞嗛�昏緫锛屽垎鎵瑰鐞嗭細
+
+```java
+// 姣忔壒澶勭悊100杈嗚溅杈�
+int batchSize = 100;
+for (int i = 0; i < vehicleIds.size(); i += batchSize) {
+    List<Long> batchIds = vehicleIds.subList(i, 
+        Math.min(i + batchSize, vehicleIds.size()));
+    processBatch(batchIds);
+}
+```
+
+### 3. 浣跨敤寮傛澶勭悊
+
+瀵逛簬鐗瑰埆鑰楁椂鐨勬搷浣滐紝鍙互鑰冭檻浣跨敤寮傛澶勭悊锛�
+
+```java
+@Async
+public CompletableFuture<Integer> calculateVehicleAsync(Long vehicleId) {
+    // 寮傛璁$畻
+}
+```
+
+### 4. 澧炲姞缂撳瓨鏈哄埗
+
+瀵逛簬棰戠箒鏌ヨ鐨勮溅杈嗕俊鎭紝鍙互浣跨敤Redis缂撳瓨锛�
+
+```java
+@Cacheable(value = "vehicleInfo", key = "#vehicleId")
+public VehicleInfo getVehicleInfo(Long vehicleId) {
+    return vehicleInfoMapper.selectVehicleInfoById(vehicleId);
+}
+```
+
+## 鐩稿叧鏂囦欢娓呭崟
+
+### 淇敼鐨勬枃浠�
+1. `ruoyi-admin/src/main/resources/application-dev.yml` - 寮�鍙戠幆澧冮厤缃�
+2. `ruoyi-admin/src/main/resources/application-test.yml` - 娴嬭瘯鐜閰嶇疆
+3. `ruoyi-admin/src/main/resources/application-prod.yml` - 鐢熶骇鐜閰嶇疆
+4. `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java` - 鎵瑰鐞嗛�昏緫浼樺寲
+5. `ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml` - 娣诲姞SQL娉ㄩ噴
+
+### 鏂板鐨勬枃浠�
+1. `sql/optimize_gps_query_performance.sql` - 鏁版嵁搴撴�ц兘浼樺寲SQL
+
+## 鏁呴殰鎺掓煡
+
+### 闂1锛氭墽琛孲QL鏃舵姤閿�"绱㈠紩宸插瓨鍦�"
+
+**瑙e喅鏂规**锛�
+```sql
+-- 鍒犻櫎宸插瓨鍦ㄧ殑绱㈠紩
+DROP INDEX idx_vehicle_collect_time ON tb_vehicle_gps;
+DROP INDEX idx_collect_time ON tb_vehicle_gps;
+
+-- 閲嶆柊鍒涘缓绱㈠紩
+-- 鐒跺悗鎵цoptimize_gps_query_performance.sql
+```
+
+### 闂2锛氫慨鏀归厤缃悗浠嶇劧瓒呮椂
+
+**妫�鏌ユ楠�**锛�
+1. 纭閰嶇疆鏂囦欢淇敼鐢熸晥锛氭鏌ュ綋鍓嶆縺娲荤殑profile锛坉ev/test/prod锛�
+2. 纭搴旂敤宸查噸鍚細`ps -ef | grep java`
+3. 鏌ョ湅Druid杩炴帴姹犻厤缃細璁块棶 `/druid/` 妫�鏌ocketTimeout鍊�
+4. 妫�鏌ユ暟鎹簱鏈嶅姟鍣ㄩ厤缃細`SHOW VARIABLES LIKE 'wait_timeout';`
+
+### 闂3锛氱储寮曞垱寤哄悗鎬ц兘鏈敼鍠�
+
+**妫�鏌ユ楠�**锛�
+```sql
+-- 1. 楠岃瘉绱㈠紩鏄惁琚娇鐢�
+EXPLAIN SELECT DISTINCT vehicle_id
+FROM tb_vehicle_gps
+WHERE collect_time >= DATE_SUB(NOW(), INTERVAL 7 DAY);
+
+-- 2. 鏇存柊琛ㄧ粺璁′俊鎭�
+ANALYZE TABLE tb_vehicle_gps;
+
+-- 3. 妫�鏌ヨ〃鏁版嵁閲�
+SELECT COUNT(*) FROM tb_vehicle_gps;
+```
+
+## 鎬荤粨
+
+鏈淇涓昏瑙e喅浜咷PS鍒嗘閲岀▼璁$畻浠诲姟鐨勮秴鏃堕棶棰橈紝閫氳繃浠ヤ笅鎺柦锛�
+
+1. 鉁� 澧炲姞鏁版嵁搴撹繛鎺ヨ秴鏃舵椂闂达紙60绉� -> 300绉掞級
+2. 鉁� 娣诲姞鏁版嵁搴撶储寮曚紭鍖栨煡璇㈡�ц兘
+3. 鉁� 鏀硅繘鎵瑰鐞嗛敊璇鐞嗘満鍒�
+4. 鉁� 澧炲己鏃ュ織杈撳嚭锛屼究浜庣洃鎺у拰闂瀹氫綅
+
+**棰勬湡鏁堟灉**锛�
+- 浠诲姟鎵ц涓嶅啀瓒呮椂
+- 鏌ヨ鎬ц兘鎻愬崌50%浠ヤ笂
+- 鍗曚釜杞﹁締澶辫触涓嶅奖鍝嶆暣浣撳鐞�
+- 瀹炴椂浜嗚В澶勭悊杩涘害
+
+**娉ㄦ剰浜嬮」**锛�
+- 蹇呴』鎵ц鏁版嵁搴撶储寮曚紭鍖朣QL
+- 蹇呴』閲嶅惎搴旂敤浣块厤缃敓鏁�
+- 寤鸿瀹氭湡娓呯悊鍘嗗彶GPS鏁版嵁
+- 鎸佺画鐩戞帶浠诲姟鎵ц鎯呭喌
diff --git a/app/api/map.js b/app/api/map.js
index 03b2060..bbd122c 100644
--- a/app/api/map.js
+++ b/app/api/map.js
@@ -8,7 +8,8 @@
   }
   
   return request({
-    url: '/system/gps/address/search',
+//    url: '/system/gps/address/search',
+    url: '/system/gps/tianditu/place/suggestion',
     method: 'get',
     params: {
       keyword: keyword,
@@ -28,9 +29,12 @@
   if (isNaN(lat) || isNaN(lng)) {
     return Promise.reject(new Error('鍙傛暟鏃犳晥锛岀粡绾害鍧愭爣鏍煎紡閿欒'))
   }
-  
+  /**
+   * 杩欓噷鐢ㄥ埌澶╁湴鍥�
+   */
   return request({
-    url: '/system/gps/address/geocoder',
+    // url: '/system/gps/address/geocoder',
+    url: '/system/gps/tianditu/reverseGeocoding',
     method: 'get',
     params: {
       lat: lat,
@@ -39,6 +43,21 @@
   })
 }
 
+export function calculateTianDiTuDistance(fromAddress, toAddress) {
+  // 鍙傛暟楠岃瘉
+  if (!fromAddress || !toAddress) {
+    return Promise.reject(new Error('鍙傛暟涓嶅畬鏁达紝缂哄皯鍦板潃'))
+  }
+
+  return request({
+    url: '/system/gps/tianditu/distance/byAddress',
+    method: 'get',
+    params: {
+      fromAddress: fromAddress,
+      toAddress: toAddress
+    }
+  })
+}
 // 鍦板浘璺嚎瑙勫垝API锛堣绠椾袱鐐归棿璺濈锛�
 export function calculateDistance(fromLat, fromLng, toLat, toLng) {
   // 鍙傛暟楠岃瘉
@@ -56,6 +75,7 @@
   
   return request({
     url: '/system/gps/route/distance',
+    // url: '/system/gps/tianditu/byAddress',
     method: 'get',
     params: {
       fromLat: fromLat,
diff --git a/app/api/wechat.js b/app/api/wechat.js
index 4f1e3e1..6ad84ea 100644
--- a/app/api/wechat.js
+++ b/app/api/wechat.js
@@ -33,4 +33,12 @@
     method: 'post',
     data: data
   })
+}
+
+// 鑾峰彇寰俊閰嶇疆锛堝寘鎷闃呮秷鎭ā鏉縄D绛夛級
+export function getWechatConfig() {
+  return request({
+    url: '/wechat/config',
+    method: 'get'
+  })
 }
\ No newline at end of file
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 4df32d4..c5c90fe 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -5,25 +5,45 @@
       <view class="user-info-content">
         <view class="user-details">
           <view class="user-info-row">
-            <text class="user-name">{{ userName || '鏈櫥褰�' }}</text>
-            <text class="separator" v-if="currentUser.branchCompanyName">|</text>
+            <text class="user-name">{{ userName || "鏈櫥褰�" }}</text>
+            <text class="separator" v-if="currentUser.branchCompanyName"
+              >|</text
+            >
             <view class="branch-company" v-if="currentUser.branchCompanyName">
-              <uni-icons type="location" size="16" color="#666" style="margin-right: 4rpx;"></uni-icons>
+              <uni-icons
+                type="location"
+                size="16"
+                color="#666"
+                style="margin-right: 4rpx"
+              ></uni-icons>
               <text>{{ currentUser.branchCompanyName }}</text>
             </view>
             <text class="separator" v-if="boundVehicle">|</text>
-            <view class="vehicle-info" @click.stop="goToBindVehicle" v-if="boundVehicle">
+            <view
+              class="vehicle-info"
+              @click.stop="goToBindVehicle"
+              v-if="boundVehicle"
+            >
               <text>{{ boundVehicle }}</text>
-              <uni-icons 
-                type="loop" 
-                size="16" 
+              <uni-icons
+                type="loop"
+                size="16"
                 color="#007AFF"
-                style="margin-left: 4rpx;"
+                style="margin-left: 4rpx"
               ></uni-icons>
             </view>
           </view>
-          <view class="bind-vehicle-btn" v-if="!boundVehicle" @click="goToBindVehicle">
-            <uni-icons type="plus-filled" size="16" color="#007AFF" style="margin-right: 4rpx;"></uni-icons>
+          <view
+            class="bind-vehicle-btn"
+            v-if="!boundVehicle"
+            @click="goToBindVehicle"
+          >
+            <uni-icons
+              type="plus-filled"
+              size="16"
+              color="#007AFF"
+              style="margin-right: 4rpx"
+            ></uni-icons>
             <text>缁戝畾杞︾墝</text>
           </view>
         </view>
@@ -36,9 +56,30 @@
         <uni-icons type="chat" size="24" color="#007AFF"></uni-icons>
       </view>
       <view class="message-text">娑堟伅涓績</view>
-      <view class="unread-dot" v-if="unreadMessageCount > 0">{{ unreadMessageCount }}</view>
+      <view class="unread-dot" v-if="unreadMessageCount > 0">{{
+        unreadMessageCount
+      }}</view>
       <view class="arrow">
         <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+      </view>
+    </view>
+
+    <!-- 璁㈤槄閫氱煡鎻愮ず鍗$墖锛堟湭璁㈤槄鏃舵樉绀猴級 -->
+    <view
+      class="subscribe-banner"
+      v-if="!hasSubscribed"
+      @click="clickConfirmsubscribeTaskNotify"
+    >
+      <view class="banner-icon">
+        <uni-icons type="bell" size="28" color="#ff9500"></uni-icons>
+      </view>
+      <view class="banner-content">
+        <view class="banner-title">寮�鍚换鍔¢�氱煡</view>
+        <view class="banner-desc">鍙婃椂鎺ユ敹浠诲姟鍒嗛厤鍜岀姸鎬佹洿鏂版彁閱�</view>
+      </view>
+      <view class="banner-action">
+        <text>绔嬪嵆寮�鍚�</text>
+        <uni-icons type="arrowright" size="16" color="#007AFF"></uni-icons>
       </view>
     </view>
 
@@ -54,17 +95,38 @@
           <view class="task-main" @click="viewTaskDetail(task)">
             <!-- 浠诲姟澶撮儴锛氭爣棰樺拰鐘舵�佹爣绛� -->
             <view class="task-header">
-              <view class="task-title">{{ getTaskTypeText(task.type) }} - {{ task.vehicle }}</view>
-              <view class="task-status" :class="task.taskStatus === 'PENDING' ? 'status-pending' : task.taskStatus === 'DEPARTING' ? 'status-departing' : task.taskStatus === 'ARRIVED' ? 'status-arrived' : task.taskStatus === 'RETURNING' ? 'status-returning' : task.taskStatus === 'COMPLETED' ? 'status-completed' : task.taskStatus === 'CANCELLED' ? 'status-cancelled' : task.taskStatus === 'IN_PROGRESS' ? 'status-in-progress' : 'status-default'">
+              <view class="task-title"
+                >{{ getTaskTypeText(task.type) }} - {{ task.vehicle }}</view
+              >
+              <view
+                class="task-status"
+                :class="
+                  task.taskStatus === 'PENDING'
+                    ? 'status-pending'
+                    : task.taskStatus === 'DEPARTING'
+                    ? 'status-departing'
+                    : task.taskStatus === 'ARRIVED'
+                    ? 'status-arrived'
+                    : task.taskStatus === 'RETURNING'
+                    ? 'status-returning'
+                    : task.taskStatus === 'COMPLETED'
+                    ? 'status-completed'
+                    : task.taskStatus === 'CANCELLED'
+                    ? 'status-cancelled'
+                    : task.taskStatus === 'IN_PROGRESS'
+                    ? 'status-in-progress'
+                    : 'status-default'
+                "
+              >
                 {{ getStatusText(task.status) }}
               </view>
             </view>
-            
+
             <!-- 浠诲姟缂栧彿鍗曠嫭涓�琛� -->
             <view class="task-code-row">
               <text class="task-code">{{ task.taskNo }}</text>
             </view>
-            
+
             <!-- 浠诲姟璇︾粏淇℃伅 -->
             <view class="task-info">
               <view class="info-row">
@@ -89,65 +151,65 @@
               </view>
             </view>
           </view>
-          
+
           <!-- 鎿嶄綔鎸夐挳 -->
           <view class="task-actions">
             <!-- 寰呭鐞嗙姸鎬�: 鏄剧ず鍑哄彂銆佸彇娑� -->
             <template v-if="task.taskStatus === 'PENDING'">
-              <button 
-                class="action-btn primary" 
+              <button
+                class="action-btn primary"
                 @click="handleTaskAction(task, 'depart')"
               >
                 鍑哄彂
               </button>
-              <button 
-                class="action-btn cancel" 
+              <button
+                class="action-btn cancel"
                 @click="handleTaskAction(task, 'cancel')"
               >
                 鍙栨秷
               </button>
             </template>
-            
+
             <!-- 鍑哄彂涓姸鎬�: 鏄剧ず宸插埌杈俱�佸己鍒剁粨鏉� -->
             <template v-else-if="task.taskStatus === 'DEPARTING'">
-              <button 
-                class="action-btn primary" 
+              <button
+                class="action-btn primary"
                 @click="handleTaskAction(task, 'arrive')"
               >
                 宸插埌杈�
               </button>
-              <button 
-                class="action-btn cancel" 
+              <button
+                class="action-btn cancel"
                 @click="handleTaskAction(task, 'forceCancel')"
               >
                 寮哄埗缁撴潫
               </button>
             </template>
-            
+
             <!-- 宸插埌杈剧姸鎬�: 鏄剧ず宸茶繑绋� -->
             <template v-else-if="task.taskStatus === 'ARRIVED'">
-              <button 
-                class="action-btn primary" 
+              <button
+                class="action-btn primary"
                 @click="handleTaskAction(task, 'return')"
               >
                 宸茶繑绋�
               </button>
             </template>
-            
+
             <!-- 杩旂▼涓姸鎬�: 鏄剧ず宸插畬鎴� -->
             <template v-else-if="task.taskStatus === 'RETURNING'">
-              <button 
-                class="action-btn primary" 
+              <button
+                class="action-btn primary"
                 @click="handleTaskAction(task, 'complete')"
               >
                 宸插畬鎴�
               </button>
             </template>
-            
+
             <!-- 宸插畬鎴�/宸插彇娑�: 涓嶆樉绀烘寜閽� -->
           </view>
         </view>
-        
+
         <view class="no-data" v-if="runningTasks.length === 0">
           <uni-icons type="info" size="40" color="#ccc"></uni-icons>
           <text>鏆傛棤姝e湪杩愯鐨勪换鍔�</text>
@@ -158,192 +220,244 @@
 </template>
 
 <script>
-  import { mapState } from 'vuex'
-  import { getMyTasks, changeTaskStatus } from '@/api/task'
-  import { getUserProfile } from '@/api/system/user'
-  import { getUserBoundVehicle } from '@/api/vehicle'
-  import { getUnreadCount } from '@/api/message'
-  import { formatDateTime } from '@/utils/common'
-  
-  export default {
-    data() {
-      return {
-        // 鐢ㄦ埛缁戝畾鐨勮溅杈嗕俊鎭�
-        boundVehicle: '',
-        boundVehicleId: null,
-        
-        // 娑堟伅鏁版嵁
-        messages: [],
-        unreadMessageCount: 0,
-        
-        // 姝e湪杩愯鐨勪换鍔″垪琛�
-        taskList: [],
-        loading: false
-      }
+import { mapState } from "vuex";
+import { getMyTasks, changeTaskStatus } from "@/api/task";
+import { getUserProfile } from "@/api/system/user";
+import { getUserBoundVehicle } from "@/api/vehicle";
+import { getUnreadCount } from "@/api/message";
+import { formatDateTime } from "@/utils/common";
+import subscribeManager from "@/utils/subscribe";
+
+export default {
+  data() {
+    return {
+      // 鐢ㄦ埛缁戝畾鐨勮溅杈嗕俊鎭�
+      boundVehicle: "",
+      boundVehicleId: null,
+
+      // 娑堟伅鏁版嵁
+      messages: [],
+      unreadMessageCount: 0,
+
+      // 姝e湪杩愯鐨勪换鍔″垪琛�
+      taskList: [],
+      loading: false,
+
+      // 璁㈤槄鐘舵��
+      hasSubscribed: true,
+    };
+  },
+  computed: {
+    ...mapState({
+      userName: (state) => state.user.nickName,
+      currentUser: (state) => state.user,
+    }),
+
+    // 姝e湪杩愯鐨勪换鍔★紙寰呭鐞嗗拰鍚勭澶勭悊涓殑浠诲姟锛�
+    runningTasks() {
+      return this.taskList.filter((task) => {
+        // 鍖呭惈寰呭鐞嗐�佸嚭鍙戜腑銆佸凡鍒拌揪銆佽繑绋嬩腑绛夋墍鏈夋湭瀹屾垚鐨勭姸鎬�
+        return [
+          "PENDING",
+          "DEPARTING",
+          "ARRIVED",
+          "RETURNING",
+          "IN_PROGRESS",
+        ].includes(task.taskStatus);
+      });
     },
-    computed: {
-      ...mapState({
-        userName: state => state.user.nickName,
-        currentUser: state => state.user
-      }),
-      
-      // 姝e湪杩愯鐨勪换鍔★紙寰呭鐞嗗拰鍚勭澶勭悊涓殑浠诲姟锛�
-      runningTasks() {
-        return this.taskList.filter(task => {
-          // 鍖呭惈寰呭鐞嗐�佸嚭鍙戜腑銆佸凡鍒拌揪銆佽繑绋嬩腑绛夋墍鏈夋湭瀹屾垚鐨勭姸鎬�
-          return ['PENDING', 'DEPARTING', 'ARRIVED', 'RETURNING', 'IN_PROGRESS'].includes(task.taskStatus)
+  },
+  onLoad() {
+    // 妫�鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍
+    const userId = this.currentUser.userId;
+    if (!userId) {
+      console.log("鐢ㄦ埛鏈櫥褰曪紝璺宠繃鍔犺浇鏁版嵁");
+      return;
+    }
+
+    // 妫�鏌ヨ闃呯姸鎬侊紙鍏堟鏌ユ湰鍦帮紝鍚庨潰浼氭鏌ュ井淇″畼鏂圭姸鎬侊級
+    this.hasSubscribed = subscribeManager.checkLocalSubscribeStatus();
+
+    // 鑷姩璁㈤槄锛堝鏋滄湭璁㈤槄鍒欐樉绀虹‘璁ゅ脊绐楋級
+    // this.autoSubscribeOnLaunch();
+
+    // 鍔犺浇鐢ㄦ埛缁戝畾杞﹁締淇℃伅
+    this.loadUserVehicle();
+    // 鍔犺浇姝e湪杩愯鐨勪换鍔�
+    this.loadRunningTasks();
+    // 鍔犺浇鏈娑堟伅鏁伴噺
+    this.loadUnreadMessageCount();
+  },
+  onShow() {
+    // 妫�鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍
+    const userId = this.currentUser.userId;
+    if (!userId) {
+      console.log("鐢ㄦ埛鏈櫥褰曪紝璺宠繃鍔犺浇鏁版嵁");
+      return;
+    }
+
+    // 姣忔鏄剧ず椤甸潰鏃跺埛鏂颁换鍔″垪琛ㄣ�佺粦瀹氳溅杈嗗拰娑堟伅鏁伴噺
+    this.loadUserVehicle();
+    this.loadRunningTasks();
+    this.loadUnreadMessageCount();
+  },
+  onPullDownRefresh() {
+    // 涓嬫媺鍒锋柊
+    this.loadRunningTasks();
+    setTimeout(() => {
+      uni.stopPullDownRefresh();
+    }, 1000);
+  },
+  methods: {
+    // 鑷姩璁㈤槄锛堝皬绋嬪簭鍚姩鏃惰皟鐢級
+    autoSubscribeOnLaunch() {
+      subscribeManager.autoSubscribe()
+        .then((result) => {
+          if (result.skipped) {
+            console.log('鐢ㄦ埛宸茶闃咃紝鏃犻渶閲嶅璁㈤槄');
+            this.hasSubscribed = true;
+          } else if (result.success) {
+            this.hasSubscribed = true;
+            console.log('鑷姩璁㈤槄鎴愬姛');
+          } else {
+            // 璁㈤槄澶辫触鎴栬鎷掔粷锛屾洿鏂扮姸鎬�
+            this.hasSubscribed = false;
+          }
+          
+          // 濡傛灉杩斿洖浜嗙姸鎬佷俊鎭紝杈撳嚭璇︾粏鐘舵��
+          if (result.status) {
+            console.log('璇︾粏璁㈤槄鐘舵�侊細', result.status);
+          }
+        })
+        .catch((error) => {
+          console.log('鑷姩璁㈤槄鍙栨秷鎴栧け璐ワ細', error);
+          this.hasSubscribed = false;
+        });
+    },
+
+    // 鍔犺浇鐢ㄦ埛缁戝畾鐨勮溅杈嗕俊鎭�
+    loadUserVehicle() {
+      const userId = this.currentUser.userId;
+      if (!userId) {
+        console.error("鐢ㄦ埛鏈櫥褰曪紝鏃犳硶鑾峰彇缁戝畾杞﹁締淇℃伅");
+        this.boundVehicle = "";
+        this.boundVehicleId = null;
+        return;
+      }
+
+      getUserBoundVehicle(userId)
+        .then((response) => {
+          if (response.code === 200 && response.data) {
+            const vehicle = response.data;
+            this.boundVehicle = vehicle.vehicleNumber || "鏈煡杞︾墝";
+            this.boundVehicleId = vehicle.vehicleId;
+            console.log("鐢ㄦ埛缁戝畾杞﹁締:", this.boundVehicle);
+          } else {
+            this.boundVehicle = "";
+            this.boundVehicleId = null;
+          }
+        })
+        .catch((error) => {
+          console.error("鑾峰彇缁戝畾杞﹁締淇℃伅澶辫触:", error);
+          this.boundVehicle = "";
+          this.boundVehicleId = null;
+        });
+    },
+
+    // 鍔犺浇鏈娑堟伅鏁伴噺
+    loadUnreadMessageCount() {
+      // 妫�鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍
+      const userId = this.currentUser.userId;
+      if (!userId) {
+        console.log("鐢ㄦ埛鏈櫥褰曪紝璺宠繃鑾峰彇鏈娑堟伅鏁伴噺");
+        return;
+      }
+
+      getUnreadCount()
+        .then((response) => {
+          if (response.code === 200) {
+            this.unreadMessageCount = response.data || 0;
+            // 鏇存柊TabBar寰芥爣
+            this.updateTabBarBadge(this.unreadMessageCount);
+          }
+        })
+        .catch((error) => {
+          console.error("鑾峰彇鏈娑堟伅鏁伴噺澶辫触:", error);
+        });
+    },
+
+    // 鏇存柊TabBar寰芥爣
+    updateTabBarBadge(count) {
+      if (count > 0) {
+        uni.setTabBarBadge({
+          index: 3, // 娑堟伅椤甸潰鍦╰abBar涓殑绱㈠紩
+          text: count > 99 ? "99+" : count.toString(),
+        });
+      } else {
+        uni.removeTabBarBadge({
+          index: 3,
         });
       }
     },
-    onLoad() {
-      // 妫�鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍
-      const userId = this.currentUser.userId
+
+    // 鍔犺浇鐢ㄦ埛淇℃伅锛堜繚鐣欎互鍏煎涔嬪墠鐨勪唬鐮侊級
+    loadUserProfile() {
+      const userId = this.currentUser.userId;
       if (!userId) {
-        console.log('鐢ㄦ埛鏈櫥褰曪紝璺宠繃鍔犺浇鏁版嵁')
-        return
+        console.error("鐢ㄦ埛鏈櫥褰曪紝鏃犳硶鑾峰彇鐢ㄦ埛淇℃伅");
+        return;
       }
-      
-      // 鍔犺浇鐢ㄦ埛缁戝畾杞﹁締淇℃伅
-      this.loadUserVehicle()
-      // 鍔犺浇姝e湪杩愯鐨勪换鍔�
-      this.loadRunningTasks()
-      // 鍔犺浇鏈娑堟伅鏁伴噺
-      this.loadUnreadMessageCount()
-    },
-    onShow() {
-      // 妫�鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍
-      const userId = this.currentUser.userId
-      if (!userId) {
-        console.log('鐢ㄦ埛鏈櫥褰曪紝璺宠繃鍔犺浇鏁版嵁')
-        return
-      }
-      
-      // 姣忔鏄剧ず椤甸潰鏃跺埛鏂颁换鍔″垪琛ㄣ�佺粦瀹氳溅杈嗗拰娑堟伅鏁伴噺
-      this.loadUserVehicle()
-      this.loadRunningTasks()
-      this.loadUnreadMessageCount()
-    },
-    onPullDownRefresh() {
-      // 涓嬫媺鍒锋柊
-      this.loadRunningTasks()
-      setTimeout(() => {
-        uni.stopPullDownRefresh()
-      }, 1000)
-    },
-    methods: {
-      // 鍔犺浇鐢ㄦ埛缁戝畾鐨勮溅杈嗕俊鎭�
-      loadUserVehicle() {
-        const userId = this.currentUser.userId
-        if (!userId) {
-          console.error('鐢ㄦ埛鏈櫥褰曪紝鏃犳硶鑾峰彇缁戝畾杞﹁締淇℃伅')
-          this.boundVehicle = ''
-          this.boundVehicleId = null
-          return
-        }
-        
-        getUserBoundVehicle(userId).then(response => {
-          if (response.code === 200 && response.data) {
-            const vehicle = response.data
-            this.boundVehicle = vehicle.vehicleNumber || '鏈煡杞︾墝'
-            this.boundVehicleId = vehicle.vehicleId
-            console.log('鐢ㄦ埛缁戝畾杞﹁締:', this.boundVehicle)
-          } else {
-            this.boundVehicle = ''
-            this.boundVehicleId = null
-          }
-        }).catch(error => {
-          console.error('鑾峰彇缁戝畾杞﹁締淇℃伅澶辫触:', error)
-          this.boundVehicle = ''
-          this.boundVehicleId = null
-        })
-      },
-      
-      // 鍔犺浇鏈娑堟伅鏁伴噺
-      loadUnreadMessageCount() {
-        // 妫�鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍
-        const userId = this.currentUser.userId
-        if (!userId) {
-          console.log('鐢ㄦ埛鏈櫥褰曪紝璺宠繃鑾峰彇鏈娑堟伅鏁伴噺')
-          return
-        }
-        
-        getUnreadCount().then(response => {
-          if (response.code === 200) {
-            this.unreadMessageCount = response.data || 0
-            // 鏇存柊TabBar寰芥爣
-            this.updateTabBarBadge(this.unreadMessageCount)
-          }
-        }).catch(error => {
-          console.error('鑾峰彇鏈娑堟伅鏁伴噺澶辫触:', error)
-        })
-      },
-      
-      // 鏇存柊TabBar寰芥爣
-      updateTabBarBadge(count) {
-        if (count > 0) {
-          uni.setTabBarBadge({
-            index: 3, // 娑堟伅椤甸潰鍦╰abBar涓殑绱㈠紩
-            text: count > 99 ? '99+' : count.toString()
-          })
-        } else {
-          uni.removeTabBarBadge({
-            index: 3
-          })
-        }
-      },
-      
-      // 鍔犺浇鐢ㄦ埛淇℃伅锛堜繚鐣欎互鍏煎涔嬪墠鐨勪唬鐮侊級
-      loadUserProfile() {
-        const userId = this.currentUser.userId
-        if (!userId) {
-          console.error('鐢ㄦ埛鏈櫥褰曪紝鏃犳硶鑾峰彇鐢ㄦ埛淇℃伅')
-          return
-        }
-        
-        getUserProfile().then(response => {
-          const userInfo = response.data || response
+
+      getUserProfile()
+        .then((response) => {
+          const userInfo = response.data || response;
           // 鑾峰彇鐢ㄦ埛缁戝畾鐨勮溅杈嗕俊鎭�
           if (userInfo.boundVehicle) {
-            this.boundVehicle = userInfo.boundVehicle.vehicleNumber
-            this.boundVehicleId = userInfo.boundVehicle.vehicleId
+            this.boundVehicle = userInfo.boundVehicle.vehicleNumber;
+            this.boundVehicleId = userInfo.boundVehicle.vehicleId;
           }
-        }).catch(error => {
-          console.error('鑾峰彇鐢ㄦ埛淇℃伅澶辫触:', error)
         })
-      },
-      
-      // 鍔犺浇姝e湪杩愯鐨勪换鍔�
-      loadRunningTasks() {
-        const userId = this.currentUser.userId
-        if (!userId) {
-          console.error('鐢ㄦ埛鏈櫥褰曪紝鏃犳硶鍔犺浇浠诲姟鍒楄〃')
-          return
-        }
-        
-        this.loading = true
-        // 浣跨敤 /task/my 鎺ュ彛鑾峰彇褰撳墠鐢ㄦ埛鐩稿叧鐨勬墍鏈変换鍔★紙鐢ㄦ埛鍒涘缓銆佸垎閰嶇粰鐢ㄦ埛銆佹墽琛屼汉鏄敤鎴凤級
-        getMyTasks().then(response => {
-          this.loading = false
+        .catch((error) => {
+          console.error("鑾峰彇鐢ㄦ埛淇℃伅澶辫触:", error);
+        });
+    },
+
+    // 鍔犺浇姝e湪杩愯鐨勪换鍔�
+    loadRunningTasks() {
+      const userId = this.currentUser.userId;
+      if (!userId) {
+        console.error("鐢ㄦ埛鏈櫥褰曪紝鏃犳硶鍔犺浇浠诲姟鍒楄〃");
+        return;
+      }
+
+      this.loading = true;
+      // 浣跨敤 /task/my 鎺ュ彛鑾峰彇褰撳墠鐢ㄦ埛鐩稿叧鐨勬墍鏈変换鍔★紙鐢ㄦ埛鍒涘缓銆佸垎閰嶇粰鐢ㄦ埛銆佹墽琛屼汉鏄敤鎴凤級
+      getMyTasks()
+        .then((response) => {
+          this.loading = false;
           // 鏍规嵁鍚庣杩斿洖鐨勬暟鎹粨鏋勮繘琛岃В鏋�
-          const data = response.data || response.rows || response || []
+          const data = response.data || response.rows || response || [];
           // 杩囨护鍑烘湭瀹屾垚鐨勪换鍔�
-          const allTasks = Array.isArray(data) ? data : []
+          const allTasks = Array.isArray(data) ? data : [];
           this.taskList = allTasks
-            .filter(task => {
+            .filter((task) => {
               // 鍙樉绀烘湭瀹屾垚鍜屾湭鍙栨秷鐨勪换鍔�
-              return task.taskStatus !== 'COMPLETED' && task.taskStatus !== 'CANCELLED'
+              return (
+                task.taskStatus !== "COMPLETED" &&
+                task.taskStatus !== "CANCELLED"
+              );
             })
-            .map(task => {
+            .map((task) => {
               // 浠巃ssignedVehicles鏁扮粍涓幏鍙栬溅杈嗕俊鎭�
-              let vehicleInfo = '鏈垎閰嶈溅杈�'
+              let vehicleInfo = "鏈垎閰嶈溅杈�";
               if (task.assignedVehicles && task.assignedVehicles.length > 0) {
-                const firstVehicle = task.assignedVehicles[0]
-                vehicleInfo = firstVehicle.vehicleNo || '鏈煡杞︾墝'
+                const firstVehicle = task.assignedVehicles[0];
+                vehicleInfo = firstVehicle.vehicleNo || "鏈煡杞︾墝";
                 if (task.assignedVehicles.length > 1) {
-                  vehicleInfo += ` 绛�${task.assignedVehicles.length}杈哷
+                  vehicleInfo += ` 绛�${task.assignedVehicles.length}杈哷;
                 }
               }
-              
+
               return {
                 ...task,
                 // 鏍煎紡鍖栨樉绀哄瓧娈�
@@ -351,566 +465,678 @@
                 type: task.taskType,
                 vehicle: vehicleInfo,
                 vehicleList: task.assignedVehicles || [],
-                startLocation: this.formatAddress(task.departureAddress || task.startLocation || '鏈缃�'),
-                endLocation: this.formatAddress(task.destinationAddress || task.endLocation || '鏈缃�'),
-                startTime: task.plannedStartTime ? formatDateTime(task.plannedStartTime, 'YYYY-MM-DD HH:mm') : '鏈缃�',
-                assignee: task.assigneeName || '鏈垎閰�',
-                taskNo: task.taskCode || '鏈煡缂栧彿',
-                status: this.convertStatus(task.taskStatus) // 杞崲鐘舵�佹牸寮忎互鍏煎鏃I
-              }
-            })
-        }).catch(error => {
-          this.loading = false
-          console.error('鍔犺浇浠诲姟鍒楄〃澶辫触:', error)
+                startLocation: this.formatAddress(
+                  task.departureAddress || task.startLocation || "鏈缃�"
+                ),
+                endLocation: this.formatAddress(
+                  task.destinationAddress || task.endLocation || "鏈缃�"
+                ),
+                startTime: task.plannedStartTime
+                  ? formatDateTime(task.plannedStartTime, "YYYY-MM-DD HH:mm")
+                  : "鏈缃�",
+                assignee: task.assigneeName || "鏈垎閰�",
+                taskNo: task.taskCode || "鏈煡缂栧彿",
+                status: this.convertStatus(task.taskStatus), // 杞崲鐘舵�佹牸寮忎互鍏煎鏃I
+              };
+            });
         })
-      },
-      
-      // 鏍煎紡鍖栧湴鍧� - 鍙樉绀�-鍓嶉潰鐨勯儴鍒�
-      formatAddress(address) {
-        if (!address) return '鏈缃�'
-        const dashIndex = address.indexOf('-')
-        if (dashIndex > 0) {
-          return address.substring(0, dashIndex)
-        }
-        return address
-      },
-      
-      // 杞崲鐘舵�佹牸寮忥紙灏嗘暟鎹簱鐘舵�佽浆鎹负UI浣跨敤鐨勭姸鎬侊級
-      convertStatus(dbStatus) {
-        const statusMap = {
-          'PENDING': 'pending',
-          'DEPARTING': 'processing',
-          'ARRIVED': 'processing',
-          'RETURNING': 'processing',
-          'IN_PROGRESS': 'processing',
-          'COMPLETED': 'completed',
-          'CANCELLED': 'cancelled'
-        }
-        return statusMap[dbStatus] || 'pending'
-      },
-      // 璺宠浆鍒扮粦瀹氳溅杈嗛〉闈�
-      goToBindVehicle() {
-        // 璺宠浆鍒扮粦瀹氳溅杈嗙殑椤甸潰
-        this.$tab.navigateTo('/pages/bind-vehicle');
-      },
-      
-      // 璺宠浆鍒版秷鎭〉闈�
-      goToMessages() {
-        this.$tab.switchTab('/pages/message/index');
-      },
-      
-      // 鏌ョ湅浠诲姟璇︽儏
-      viewTaskDetail(task) {
-        // 璺宠浆鍒颁换鍔¤鎯呴〉闈� - 浣跨敤taskId
-        this.$tab.navigateTo(`/pagesTask/detail?id=${task.taskId || task.id}`);
-      },
-      
-      // 澶勭悊浠诲姟鎿嶄綔
-      handleTaskAction(task, action) {
-        switch (action) {
-          case 'depart':
-            // 鍑哄彂 -> 鐘舵�佸彉涓哄嚭鍙戜腑
-            this.$modal.confirm('纭畾瑕佸嚭鍙戝悧锛�').then(() => {
-              this.updateTaskStatus(task.taskId, 'DEPARTING', '浠诲姟宸插嚭鍙�')
-            }).catch(() => {});
-            break;
-            
-          case 'cancel':
-            // 鍙栨秷 -> 浜屾纭鍚庣姸鎬佸彉涓哄凡鍙栨秷
-            this.$modal.confirm('纭畾瑕佸彇娑堟浠诲姟鍚楋紵').then(() => {
-              this.updateTaskStatus(task.taskId, 'CANCELLED', '浠诲姟宸插彇娑�')
-            }).catch(() => {});
-            break;
-            
-          case 'arrive':
-            // 宸插埌杈� -> 鐘舵�佸彉涓哄凡鍒拌揪
-            this.$modal.confirm('纭宸插埌杈剧洰鐨勫湴锛�').then(() => {
-              this.updateTaskStatus(task.taskId, 'ARRIVED', '宸插埌杈剧洰鐨勫湴')
-            }).catch(() => {});
-            break;
-            
-          case 'forceCancel':
-            // 寮哄埗缁撴潫 -> 鐘舵�佸彉涓哄凡鍙栨秷
-            this.$modal.confirm('纭畾瑕佸己鍒剁粨鏉熸浠诲姟鍚楋紵').then(() => {
-              this.updateTaskStatus(task.taskId, 'CANCELLED', '浠诲姟宸插己鍒剁粨鏉�')
-            }).catch(() => {});
-            break;
-            
-          case 'return':
-            // 宸茶繑绋� -> 鐘舵�佸彉涓鸿繑绋嬩腑
-            this.$modal.confirm('纭寮�濮嬭繑绋嬶紵').then(() => {
-              this.updateTaskStatus(task.taskId, 'RETURNING', '宸插紑濮嬭繑绋�')
-            }).catch(() => {});
-            break;
-            
-          case 'complete':
-            // 宸插畬鎴� -> 鐘舵�佸彉涓哄凡瀹屾垚
-            this.$modal.confirm('纭浠诲姟宸插畬鎴愶紵').then(() => {
-              this.updateTaskStatus(task.taskId, 'COMPLETED', '浠诲姟宸插畬鎴�')
-            }).catch(() => {});
-            break;
-        }
-      },
-      
-      // 鏇存柊浠诲姟鐘舵��
-      updateTaskStatus(taskId, status, remark) {
-        // 鑾峰彇GPS浣嶇疆淇℃伅
-        this.getLocationAndUpdateStatus(taskId, status, remark)
-      },
-      
-      // 鑾峰彇浣嶇疆淇℃伅骞舵洿鏂扮姸鎬�
-      getLocationAndUpdateStatus(taskId, status, remark) {
-        const that = this
-        
-        // 浣跨敤uni.getLocation鑾峰彇GPS浣嶇疆
-        uni.getLocation({
-          type: 'gcj02',
-          geocode: true,
-          altitude: true,
-          success: function(res) {
-            console.log('GPS瀹氫綅鎴愬姛:', res)
-            
-            const statusData = {
-              taskStatus: status,
-              remark: remark,
-              latitude: res.latitude,
-              longitude: res.longitude,
-              locationAddress: res.address ? res.address.street || res.address.poiName || '' : '',
-              locationProvince: res.address ? res.address.province || '' : '',
-              locationCity: res.address ? res.address.city || '' : '',
-              locationDistrict: res.address ? res.address.district || '' : '',
-              gpsAccuracy: res.accuracy,
-              altitude: res.altitude,
-              speed: res.speed,
-              heading: res.direction || res.heading
-            }
-            
-            changeTaskStatus(taskId, statusData).then(response => {
-              that.$modal.showToast('鐘舵�佹洿鏂版垚鍔�')
-              that.loadRunningTasks()
-            }).catch(error => {
-              console.error('鏇存柊浠诲姟鐘舵�佸け璐�:', error)
-              that.$modal.showToast('鐘舵�佹洿鏂板け璐ワ紝璇烽噸璇�')
+        .catch((error) => {
+          this.loading = false;
+          console.error("鍔犺浇浠诲姟鍒楄〃澶辫触:", error);
+        });
+    },
+
+    // 鏍煎紡鍖栧湴鍧� - 鍙樉绀�-鍓嶉潰鐨勯儴鍒�
+    formatAddress(address) {
+      if (!address) return "鏈缃�";
+      const dashIndex = address.indexOf("-");
+      if (dashIndex > 0) {
+        return address.substring(0, dashIndex);
+      }
+      return address;
+    },
+
+    // 杞崲鐘舵�佹牸寮忥紙灏嗘暟鎹簱鐘舵�佽浆鎹负UI浣跨敤鐨勭姸鎬侊級
+    convertStatus(dbStatus) {
+      const statusMap = {
+        PENDING: "pending",
+        DEPARTING: "processing",
+        ARRIVED: "processing",
+        RETURNING: "processing",
+        IN_PROGRESS: "processing",
+        COMPLETED: "completed",
+        CANCELLED: "cancelled",
+      };
+      return statusMap[dbStatus] || "pending";
+    },
+    // 璺宠浆鍒扮粦瀹氳溅杈嗛〉闈�
+    goToBindVehicle() {
+      // 璺宠浆鍒扮粦瀹氳溅杈嗙殑椤甸潰
+      this.$tab.navigateTo("/pages/bind-vehicle");
+    },
+
+    // 璺宠浆鍒版秷鎭〉闈�
+    goToMessages() {
+      this.$tab.switchTab("/pages/message/index");
+    },
+
+    // 鏌ョ湅浠诲姟璇︽儏
+    viewTaskDetail(task) {
+      // 璺宠浆鍒颁换鍔¤鎯呴〉闈� - 浣跨敤taskId
+      this.$tab.navigateTo(`/pagesTask/detail?id=${task.taskId || task.id}`);
+    },
+
+    // 澶勭悊浠诲姟鎿嶄綔
+    handleTaskAction(task, action) {
+      switch (action) {
+        case "depart":
+          // 鍑哄彂 -> 鐘舵�佸彉涓哄嚭鍙戜腑
+          this.$modal
+            .confirm("纭畾瑕佸嚭鍙戝悧锛�")
+            .then(() => {
+              this.updateTaskStatus(task.taskId, "DEPARTING", "浠诲姟宸插嚭鍙�");
             })
-          },
-          fail: function(err) {
-            console.error('GPS瀹氫綅澶辫触:', err)
-            
-            that.$modal.confirm('GPS瀹氫綅澶辫触锛屾槸鍚︾户缁洿鏂扮姸鎬侊紵').then(() => {
+            .catch(() => {});
+          break;
+
+        case "cancel":
+          // 鍙栨秷 -> 浜屾纭鍚庣姸鎬佸彉涓哄凡鍙栨秷
+          this.$modal
+            .confirm("纭畾瑕佸彇娑堟浠诲姟鍚楋紵")
+            .then(() => {
+              this.updateTaskStatus(task.taskId, "CANCELLED", "浠诲姟宸插彇娑�");
+            })
+            .catch(() => {});
+          break;
+
+        case "arrive":
+          // 宸插埌杈� -> 鐘舵�佸彉涓哄凡鍒拌揪
+          this.$modal
+            .confirm("纭宸插埌杈剧洰鐨勫湴锛�")
+            .then(() => {
+              this.updateTaskStatus(task.taskId, "ARRIVED", "宸插埌杈剧洰鐨勫湴");
+            })
+            .catch(() => {});
+          break;
+
+        case "forceCancel":
+          // 寮哄埗缁撴潫 -> 鐘舵�佸彉涓哄凡鍙栨秷
+          this.$modal
+            .confirm("纭畾瑕佸己鍒剁粨鏉熸浠诲姟鍚楋紵")
+            .then(() => {
+              this.updateTaskStatus(task.taskId, "CANCELLED", "浠诲姟宸插己鍒剁粨鏉�");
+            })
+            .catch(() => {});
+          break;
+
+        case "return":
+          // 宸茶繑绋� -> 鐘舵�佸彉涓鸿繑绋嬩腑
+          this.$modal
+            .confirm("纭寮�濮嬭繑绋嬶紵")
+            .then(() => {
+              this.updateTaskStatus(task.taskId, "RETURNING", "宸插紑濮嬭繑绋�");
+            })
+            .catch(() => {});
+          break;
+
+        case "complete":
+          // 宸插畬鎴� -> 鐘舵�佸彉涓哄凡瀹屾垚
+          this.$modal
+            .confirm("纭浠诲姟宸插畬鎴愶紵")
+            .then(() => {
+              this.updateTaskStatus(task.taskId, "COMPLETED", "浠诲姟宸插畬鎴�");
+            })
+            .catch(() => {});
+          break;
+      }
+    },
+
+    // 鏇存柊浠诲姟鐘舵��
+    updateTaskStatus(taskId, status, remark) {
+      // 鑾峰彇GPS浣嶇疆淇℃伅
+      this.getLocationAndUpdateStatus(taskId, status, remark);
+    },
+
+    // 鑾峰彇浣嶇疆淇℃伅骞舵洿鏂扮姸鎬�
+    getLocationAndUpdateStatus(taskId, status, remark) {
+      const that = this;
+
+      // 浣跨敤uni.getLocation鑾峰彇GPS浣嶇疆
+      uni.getLocation({
+        type: "gcj02",
+        geocode: true,
+        altitude: true,
+        success: function (res) {
+          console.log("GPS瀹氫綅鎴愬姛:", res);
+
+          const statusData = {
+            taskStatus: status,
+            remark: remark,
+            latitude: res.latitude,
+            longitude: res.longitude,
+            locationAddress: res.address
+              ? res.address.street || res.address.poiName || ""
+              : "",
+            locationProvince: res.address ? res.address.province || "" : "",
+            locationCity: res.address ? res.address.city || "" : "",
+            locationDistrict: res.address ? res.address.district || "" : "",
+            gpsAccuracy: res.accuracy,
+            altitude: res.altitude,
+            speed: res.speed,
+            heading: res.direction || res.heading,
+          };
+
+          changeTaskStatus(taskId, statusData)
+            .then((response) => {
+              that.$modal.showToast("鐘舵�佹洿鏂版垚鍔�");
+              that.loadRunningTasks();
+            })
+            .catch((error) => {
+              console.error("鏇存柊浠诲姟鐘舵�佸け璐�:", error);
+              that.$modal.showToast("鐘舵�佹洿鏂板け璐ワ紝璇烽噸璇�");
+            });
+        },
+        fail: function (err) {
+          console.error("GPS瀹氫綅澶辫触:", err);
+
+          that.$modal
+            .confirm("GPS瀹氫綅澶辫触锛屾槸鍚︾户缁洿鏂扮姸鎬侊紵")
+            .then(() => {
               const statusData = {
                 taskStatus: status,
-                remark: remark
-              }
-              
-              changeTaskStatus(taskId, statusData).then(response => {
-                that.$modal.showToast('鐘舵�佹洿鏂版垚鍔�')
-                that.loadRunningTasks()
-              }).catch(error => {
-                console.error('鏇存柊浠诲姟鐘舵�佸け璐�:', error)
-                that.$modal.showToast('鐘舵�佹洿鏂板け璐ワ紝璇烽噸璇�')
-              })
-            }).catch(() => {})
+                remark: remark,
+              };
+
+              changeTaskStatus(taskId, statusData)
+                .then((response) => {
+                  that.$modal.showToast("鐘舵�佹洿鏂版垚鍔�");
+                  that.loadRunningTasks();
+                })
+                .catch((error) => {
+                  console.error("鏇存柊浠诲姟鐘舵�佸け璐�:", error);
+                  that.$modal.showToast("鐘舵�佹洿鏂板け璐ワ紝璇烽噸璇�");
+                });
+            })
+            .catch(() => {});
+        },
+      });
+    },
+
+    // 鑾峰彇鐘舵�佹牱寮忕被
+    getStatusClass(status) {
+      const statusClassMap = {
+        PENDING: "status-pending",
+        DEPARTING: "status-departing",
+        ARRIVED: "status-arrived",
+        RETURNING: "status-returning",
+        COMPLETED: "status-completed",
+        CANCELLED: "status-cancelled",
+        IN_PROGRESS: "status-in-progress",
+      };
+      return statusClassMap[status] || "status-default";
+    },
+
+    getStatusText(status) {
+      // 鏀寔鏂版棫涓ょ鐘舵�佹牸寮�
+      const statusMap = {
+        // 鏂版牸寮忥紙鏁版嵁搴撶姸鎬侊級
+        PENDING: "寰呭鐞�",
+        DEPARTING: "鍑哄彂涓�",
+        ARRIVED: "宸插埌杈�",
+        RETURNING: "杩旂▼涓�",
+        COMPLETED: "宸插畬鎴�",
+        CANCELLED: "宸插彇娑�",
+        IN_PROGRESS: "澶勭悊涓�",
+        // 鏃ф牸寮忥紙UI鐘舵�侊級
+        pending: "寰呭鐞�",
+        processing: "澶勭悊涓�",
+        completed: "宸插畬鎴�",
+      };
+      return statusMap[status] || "鏈煡";
+    },
+
+    getTaskTypeText(type) {
+      const typeMap = {
+        // 鏂版牸寮忥紙鏁版嵁搴撶被鍨嬶級
+        MAINTENANCE: "缁翠慨淇濆吇",
+        FUEL: "鍔犳补",
+        OTHER: "鍏朵粬",
+        EMERGENCY_TRANSFER: "杞繍浠诲姟",
+        WELFARE: "绂忕杞�",
+        // 鏃ф牸寮忥紙UI绫诲瀷锛�
+        maintenance: "缁翠慨淇濆吇",
+        refuel: "鍔犳补",
+        inspection: "宸℃",
+        emergency: "杞繍浠诲姟",
+        welfare: "绂忕杞�",
+      };
+      return typeMap[type] || "鏈煡绫诲瀷";
+    },
+
+    clickConfirmsubscribeTaskNotify() {
+      subscribeManager.subscribeWithConfirm()
+        .then((result) => {
+          if (result.success) {
+            this.hasSubscribed = true;
           }
         })
-      },
-      
-      // 鑾峰彇鐘舵�佹牱寮忕被
-      getStatusClass(status) {
-        const statusClassMap = {
-          'PENDING': 'status-pending',
-          'DEPARTING': 'status-departing',
-          'ARRIVED': 'status-arrived',
-          'RETURNING': 'status-returning',
-          'COMPLETED': 'status-completed',
-          'CANCELLED': 'status-cancelled',
-          'IN_PROGRESS': 'status-in-progress'
-        }
-        return statusClassMap[status] || 'status-default'
-      },
-      
-      getStatusText(status) {
-        // 鏀寔鏂版棫涓ょ鐘舵�佹牸寮�
-        const statusMap = {
-          // 鏂版牸寮忥紙鏁版嵁搴撶姸鎬侊級
-          'PENDING': '寰呭鐞�',
-          'DEPARTING': '鍑哄彂涓�',
-          'ARRIVED': '宸插埌杈�',
-          'RETURNING': '杩旂▼涓�',
-          'COMPLETED': '宸插畬鎴�',
-          'CANCELLED': '宸插彇娑�',
-          'IN_PROGRESS': '澶勭悊涓�',
-          // 鏃ф牸寮忥紙UI鐘舵�侊級
-          'pending': '寰呭鐞�',
-          'processing': '澶勭悊涓�',
-          'completed': '宸插畬鎴�'
-        }
-        return statusMap[status] || '鏈煡'
-      },
-      
-      getTaskTypeText(type) {
-        const typeMap = {
-          // 鏂版牸寮忥紙鏁版嵁搴撶被鍨嬶級
-          'MAINTENANCE': '缁翠慨淇濆吇',
-          'FUEL': '鍔犳补',
-          'OTHER': '鍏朵粬',
-          'EMERGENCY_TRANSFER': '杞繍浠诲姟',
-          'WELFARE': '绂忕杞�',
-          // 鏃ф牸寮忥紙UI绫诲瀷锛�
-          'maintenance': '缁翠慨淇濆吇',
-          'refuel': '鍔犳补',
-          'inspection': '宸℃',
-          'emergency': '杞繍浠诲姟',
-          'welfare': '绂忕杞�'
-        }
-        return typeMap[type] || '鏈煡绫诲瀷'
-      }
-    }
-  }
+        .catch((error) => {
+          console.log('璁㈤槄鍙栨秷鎴栧け璐ワ細', error);
+        });
+    },
+
+    // 璁㈤槄浠诲姟閫氱煡锛堢洿鎺ヨ皟鐢紝涓嶆樉绀虹‘璁ゅ脊绐楋級
+    subscribeTaskNotify() {
+      subscribeManager.subscribeDirect()
+        .then((result) => {
+          if (result.success) {
+            this.hasSubscribed = true;
+          }
+        })
+        .catch((error) => {
+          console.log('璁㈤槄澶辫触锛�', error);
+        });
+    },
+  },
+};
 </script>
 
 <style lang="scss">
-  .home-container {
-    padding: 20rpx;
-    background-color: #f5f5f5;
-    height: 100vh;
-    display: flex;
-    flex-direction: column;
-    // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘
-    ::-webkit-scrollbar {
-      display: none;
-      width: 0 !important;
-      height: 0 !important;
-      background: transparent;
-    }
-    
-    // Firefox婊氬姩鏉¢殣钘�
-    * {
-      scrollbar-width: none; /* Firefox */
-    }
-    
-    // IE/Edge婊氬姩鏉¢殣钘�
-    * {
-      -ms-overflow-style: none; /* IE 10+ */
-    }
+.home-container {
+  padding: 20rpx;
+  background-color: #f5f5f5;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘
+  ::-webkit-scrollbar {
+    display: none;
+    width: 0 !important;
+    height: 0 !important;
+    background: transparent;
   }
-  
-  // 鐢ㄦ埛淇℃伅鍖哄煙
-  .user-info-section {
-    background-color: white;
-    border-radius: 15rpx;
-    padding: 30rpx;
-    margin-bottom: 20rpx;
-    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
-    flex-shrink: 0; // 闃叉鏀剁缉
-    
-    .user-info-content {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      
-      .user-details {
-        flex: 1;
-        
-        .user-info-row {
-          display: flex;
-          align-items: center;
-          flex-wrap: wrap;
-          margin-bottom: 12rpx;
-          
-          .user-name {
-            font-size: 32rpx;
-            font-weight: bold;
-            color: #333;
-          }
-          
-          .separator {
-            margin: 0 12rpx;
-            color: #ddd;
-            font-size: 28rpx;
-          }
-          
-          .branch-company {
-            font-size: 26rpx;
-            color: #666;
-            display: flex;
-            align-items: center;
-          }
-          
-          .vehicle-info {
-            font-size: 26rpx;
-            color: #007AFF;
-            display: flex;
-            align-items: center;
-          }
+
+  // Firefox婊氬姩鏉¢殣钘�
+  * {
+    scrollbar-width: none; /* Firefox */
+  }
+
+  // IE/Edge婊氬姩鏉¢殣钘�
+  * {
+    -ms-overflow-style: none; /* IE 10+ */
+  }
+}
+
+// 鐢ㄦ埛淇℃伅鍖哄煙
+.user-info-section {
+  background-color: white;
+  border-radius: 15rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+  flex-shrink: 0; // 闃叉鏀剁缉
+
+  .user-info-content {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .user-details {
+      flex: 1;
+
+      .user-info-row {
+        display: flex;
+        align-items: center;
+        flex-wrap: wrap;
+        margin-bottom: 12rpx;
+
+        .user-name {
+          font-size: 32rpx;
+          font-weight: bold;
+          color: #333;
         }
-        
-        .bind-vehicle-btn {
+
+        .separator {
+          margin: 0 12rpx;
+          color: #ddd;
+          font-size: 28rpx;
+        }
+
+        .branch-company {
           font-size: 26rpx;
-          color: #007AFF;
+          color: #666;
           display: flex;
           align-items: center;
-          
-          &:active {
-            opacity: 0.7;
-          }
+        }
+
+        .vehicle-info {
+          font-size: 26rpx;
+          color: #007aff;
+          display: flex;
+          align-items: center;
+        }
+      }
+
+      .bind-vehicle-btn {
+        font-size: 26rpx;
+        color: #007aff;
+        display: flex;
+        align-items: center;
+
+        &:active {
+          opacity: 0.7;
         }
       }
     }
   }
-  
-  // 娑堟伅鍏ュ彛
-  .message-entry {
+}
+
+// 娑堟伅鍏ュ彛
+.message-entry {
+  display: flex;
+  align-items: center;
+  background-color: white;
+  border-radius: 15rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+  position: relative;
+
+  .message-icon {
+    margin-right: 20rpx;
+  }
+
+  .message-text {
+    flex: 1;
+    font-size: 32rpx;
+    color: #333;
+  }
+
+  .unread-dot {
+    position: absolute;
+    top: 15rpx;
+    right: 60rpx;
+    background-color: #ff4d4f;
+    color: white;
+    border-radius: 50%;
+    width: 32rpx;
+    height: 32rpx;
     display: flex;
     align-items: center;
-    background-color: white;
-    border-radius: 15rpx;
-    padding: 30rpx;
-    margin-bottom: 20rpx;
-    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
-    position: relative;
-    
-    .message-icon {
-      margin-right: 20rpx;
-    }
-    
-    .message-text {
-      flex: 1;
-      font-size: 32rpx;
-      color: #333;
-    }
-    
-    .unread-dot {
-      position: absolute;
-      top: 15rpx;
-      right: 60rpx;
-      background-color: #ff4d4f;
-      color: white;
-      border-radius: 50%;
-      width: 32rpx;
-      height: 32rpx;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-size: 20rpx;
-    }
-    
-    .arrow {
-      margin-left: 20rpx;
-    }
+    justify-content: center;
+    font-size: 20rpx;
   }
-  
-  // 姝e湪杩愯鐨勪换鍔℃爣棰�
-  .running-tasks-header {
-    margin-bottom: 20rpx;
-    flex-shrink: 0; // 闃叉鏀剁缉
-    
-    .header-title {
-      font-size: 36rpx;
+
+  .arrow {
+    margin-left: 20rpx;
+  }
+}
+
+// 璁㈤槄閫氱煡妯箙
+.subscribe-banner {
+  display: flex;
+  align-items: center;
+  background: linear-gradient(135deg, #fff9e6 0%, #fff3e0 100%);
+  border-radius: 15rpx;
+  padding: 30rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 10rpx rgba(255, 149, 0, 0.1);
+  border: 1rpx solid #ffe0b2;
+
+  .banner-icon {
+    margin-right: 20rpx;
+    flex-shrink: 0;
+  }
+
+  .banner-content {
+    flex: 1;
+
+    .banner-title {
+      font-size: 30rpx;
       font-weight: bold;
       color: #333;
+      margin-bottom: 8rpx;
+    }
+
+    .banner-desc {
+      font-size: 24rpx;
+      color: #666;
+      line-height: 1.4;
     }
   }
-  
-  // 姝e湪杩愯鐨勪换鍔″垪琛�
-  .running-tasks-section {
-    flex: 1;
+
+  .banner-action {
+    display: flex;
+    align-items: center;
+    padding: 12rpx 24rpx;
     background-color: white;
-    border-radius: 15rpx;
-    padding: 30rpx;
-    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
-    // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘
-    ::-webkit-scrollbar {
-      display: none;
-      width: 0 !important;
-      height: 0 !important;
-      background: transparent;
+    border-radius: 30rpx;
+    flex-shrink: 0;
+
+    text {
+      font-size: 26rpx;
+      color: #007aff;
+      margin-right: 4rpx;
     }
-    
-    // Firefox婊氬姩鏉¢殣钘�
-    * {
-      scrollbar-width: none; /* Firefox */
-    }
-    
-    // IE/Edge婊氬姩鏉¢殣钘�
-    * {
-      -ms-overflow-style: none; /* IE 10+ */
-    }
-    
-    .task-list {
-      .task-item {
-        background-color: #fafafa;
-        border-radius: 15rpx;
-        margin-bottom: 30rpx;
-        overflow: hidden;
-        
-        .task-main {
-          padding: 30rpx;
-          border-bottom: 1rpx solid #f0f0f0;
-          
-          // 浠诲姟澶撮儴锛氭爣棰樺拰鐘舵��
-          .task-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: flex-start;
-            margin-bottom: 15rpx;
-            
-            .task-title {
-              flex: 1;
-              font-size: 32rpx;
-              font-weight: bold;
-              padding-right: 20rpx;
-              line-height: 1.4;
-            }
-            
-            .task-status {
-              padding: 8rpx 20rpx;
-              border-radius: 30rpx;
-              font-size: 24rpx;
-              white-space: nowrap;
-              flex-shrink: 0;
-              
-              // 寰呭鐞� - 姗欒壊
-              &.status-pending {
-                background-color: #fff3e0;
-                color: #ff9500;
-              }
-              
-              // 鍑哄彂涓� - 钃濊壊
-              &.status-departing {
-                background-color: #e3f2fd;
-                color: #007AFF;
-              }
-              
-              // 宸插埌杈� - 绱壊
-              &.status-arrived {
-                background-color: #f3e5f5;
-                color: #9c27b0;
-              }
-              
-              // 杩旂▼涓� - 闈掕壊
-              &.status-returning {
-                background-color: #e0f2f1;
-                color: #009688;
-              }
-              
-              // 宸插畬鎴� - 缁胯壊
-              &.status-completed {
-                background-color: #e8f5e9;
-                color: #34C759;
-              }
-              
-              // 宸插彇娑� - 鐏拌壊
-              &.status-cancelled {
-                background-color: #f5f5f5;
-                color: #999;
-              }
-              
-              // 澶勭悊涓� (鍏煎鏃ф暟鎹�) - 钃濊壊
-              &.status-in-progress {
-                background-color: #e3f2fd;
-                color: #007AFF;
-              }
-              
-              // 榛樿鏍峰紡
-              &.status-default {
-                background-color: #f5f5f5;
-                color: #666;
-              }
-            }
+  }
+
+  &:active {
+    opacity: 0.9;
+  }
+}
+
+// 姝e湪杩愯鐨勪换鍔℃爣棰�
+.running-tasks-header {
+  margin-bottom: 20rpx;
+  flex-shrink: 0; // 闃叉鏀剁缉
+
+  .header-title {
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #333;
+  }
+}
+
+// 姝e湪杩愯鐨勪换鍔″垪琛�
+.running-tasks-section {
+  flex: 1;
+  background-color: white;
+  border-radius: 15rpx;
+  padding: 30rpx;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+  // 闅愯棌婊氬姩鏉′絾淇濇寔婊氬姩鍔熻兘
+  ::-webkit-scrollbar {
+    display: none;
+    width: 0 !important;
+    height: 0 !important;
+    background: transparent;
+  }
+
+  // Firefox婊氬姩鏉¢殣钘�
+  * {
+    scrollbar-width: none; /* Firefox */
+  }
+
+  // IE/Edge婊氬姩鏉¢殣钘�
+  * {
+    -ms-overflow-style: none; /* IE 10+ */
+  }
+
+  .task-list {
+    .task-item {
+      background-color: #fafafa;
+      border-radius: 15rpx;
+      margin-bottom: 30rpx;
+      overflow: hidden;
+
+      .task-main {
+        padding: 30rpx;
+        border-bottom: 1rpx solid #f0f0f0;
+
+        // 浠诲姟澶撮儴锛氭爣棰樺拰鐘舵��
+        .task-header {
+          display: flex;
+          justify-content: space-between;
+          align-items: flex-start;
+          margin-bottom: 15rpx;
+
+          .task-title {
+            flex: 1;
+            font-size: 32rpx;
+            font-weight: bold;
+            padding-right: 20rpx;
+            line-height: 1.4;
           }
-          
-          // 浠诲姟缂栧彿鍗曠嫭涓�琛�
-          .task-code-row {
-            margin-bottom: 15rpx;
-            padding: 10rpx 0;
-            border-bottom: 1rpx dashed #e0e0e0;
-            
-            .task-code {
-              font-size: 28rpx;
-              color: #333;
-              font-weight: 500;
-              font-family: monospace;
+
+          .task-status {
+            padding: 8rpx 20rpx;
+            border-radius: 30rpx;
+            font-size: 24rpx;
+            white-space: nowrap;
+            flex-shrink: 0;
+
+            // 寰呭鐞� - 姗欒壊
+            &.status-pending {
+              background-color: #fff3e0;
+              color: #ff9500;
             }
-          }
-          
-          .task-info {
-            .info-row {
-              display: flex;
-              margin-bottom: 15rpx;
-              
-              &:last-child {
-                margin-bottom: 0;
-              }
-              
-              .info-item {
-                flex: 1;
-                display: flex;
-                
-                .label {
-                  font-size: 26rpx;
-                  color: #666;
-                  margin-right: 10rpx;
-                  white-space: nowrap;
-                }
-                
-                .value {
-                  font-size: 26rpx;
-                  flex: 1;
-                  word-break: break-all;
-                }
-              }
+
+            // 鍑哄彂涓� - 钃濊壊
+            &.status-departing {
+              background-color: #e3f2fd;
+              color: #007aff;
+            }
+
+            // 宸插埌杈� - 绱壊
+            &.status-arrived {
+              background-color: #f3e5f5;
+              color: #9c27b0;
+            }
+
+            // 杩旂▼涓� - 闈掕壊
+            &.status-returning {
+              background-color: #e0f2f1;
+              color: #009688;
+            }
+
+            // 宸插畬鎴� - 缁胯壊
+            &.status-completed {
+              background-color: #e8f5e9;
+              color: #34c759;
+            }
+
+            // 宸插彇娑� - 鐏拌壊
+            &.status-cancelled {
+              background-color: #f5f5f5;
+              color: #999;
+            }
+
+            // 澶勭悊涓� (鍏煎鏃ф暟鎹�) - 钃濊壊
+            &.status-in-progress {
+              background-color: #e3f2fd;
+              color: #007aff;
+            }
+
+            // 榛樿鏍峰紡
+            &.status-default {
+              background-color: #f5f5f5;
+              color: #666;
             }
           }
         }
-        
-        .task-actions {
-          display: flex;
-          padding: 20rpx;
-          
-          .action-btn {
-            flex: 1;
-            height: 70rpx;
-            border-radius: 10rpx;
-            font-size: 26rpx;
-            margin: 0 5rpx;
-            background-color: #f0f0f0;
+
+        // 浠诲姟缂栧彿鍗曠嫭涓�琛�
+        .task-code-row {
+          margin-bottom: 15rpx;
+          padding: 10rpx 0;
+          border-bottom: 1rpx dashed #e0e0e0;
+
+          .task-code {
+            font-size: 28rpx;
             color: #333;
-            
-            &.primary {
-              background-color: #007AFF;
-              color: white;
-            }
-            
-            &.cancel {
-              background-color: #ff3b30;
-              color: white;
-            }
-            
-            &.disabled {
-              opacity: 0.5;
-            }
-            
-            &:first-child {
-              margin-left: 0;
-            }
-            
+            font-weight: 500;
+            font-family: monospace;
+          }
+        }
+
+        .task-info {
+          .info-row {
+            display: flex;
+            margin-bottom: 15rpx;
+
             &:last-child {
-              margin-right: 0;
+              margin-bottom: 0;
+            }
+
+            .info-item {
+              flex: 1;
+              display: flex;
+
+              .label {
+                font-size: 26rpx;
+                color: #666;
+                margin-right: 10rpx;
+                white-space: nowrap;
+              }
+
+              .value {
+                font-size: 26rpx;
+                flex: 1;
+                word-break: break-all;
+              }
             }
           }
         }
       }
-      
-      .no-data {
-        text-align: center;
-        padding: 100rpx 0;
-        color: #999;
-        
-        text {
-          display: block;
-          margin-top: 20rpx;
+
+      .task-actions {
+        display: flex;
+        padding: 20rpx;
+
+        .action-btn {
+          flex: 1;
+          height: 70rpx;
+          border-radius: 10rpx;
+          font-size: 26rpx;
+          margin: 0 5rpx;
+          background-color: #f0f0f0;
+          color: #333;
+
+          &.primary {
+            background-color: #007aff;
+            color: white;
+          }
+
+          &.cancel {
+            background-color: #ff3b30;
+            color: white;
+          }
+
+          &.disabled {
+            opacity: 0.5;
+          }
+
+          &:first-child {
+            margin-left: 0;
+          }
+
+          &:last-child {
+            margin-right: 0;
+          }
         }
+      }
+    }
+
+    .no-data {
+      text-align: center;
+      padding: 100rpx 0;
+      color: #999;
+
+      text {
+        display: block;
+        margin-top: 20rpx;
       }
     }
   }
+}
 </style>
\ No newline at end of file
diff --git a/app/pages/message/index.vue b/app/pages/message/index.vue
index dd713e4..fd682d0 100644
--- a/app/pages/message/index.vue
+++ b/app/pages/message/index.vue
@@ -2,6 +2,10 @@
   <view class="message-container">
     <view class="message-header">
       <view class="header-title">娑堟伅涓績</view>
+      <view class="subscribe-btn" v-if="!subscribed" @click="subscribeMessage">
+        <uni-icons type="bell" size="20" color="#007AFF"></uni-icons>
+        <text>璁㈤槄閫氱煡</text>
+      </view>
     </view>
     
     <scroll-view class="message-list-scroll" scroll-y="true">
@@ -35,13 +39,15 @@
 <script>
   import { getMyMessages, markAsRead } from '@/api/message'
   import { formatDateTime } from '@/utils/common'
+  import subscribeManager from '@/utils/subscribe'
   
   export default {
     data() {
       return {
         // 娑堟伅鍒楄〃
         messages: [],
-        loading: false
+        loading: false,
+        subscribed: true,
       }
     },
     computed: {
@@ -61,6 +67,8 @@
     },
     onLoad() {
       this.loadMessages()
+      // 鑷姩璁㈤槄锛堝鏋滄湭璁㈤槄鍒欐樉绀虹‘璁ゅ脊绐楋級
+      // this.autoSubscribeOnLaunch()
     },
     onShow() {
       // 姣忔鏄剧ず椤甸潰鏃跺埛鏂版秷鎭�
@@ -74,6 +82,21 @@
       })
     },
     methods: {
+      // 鑷姩璁㈤槄锛堥〉闈㈠姞杞芥椂璋冪敤锛�
+      autoSubscribeOnLaunch() {
+        subscribeManager.autoSubscribe()
+          .then((result) => {
+            if (result.skipped) {
+              console.log('鐢ㄦ埛宸茶闃咃紝鏃犻渶閲嶅璁㈤槄')
+            } else if (result.success) {
+              console.log('鑷姩璁㈤槄鎴愬姛')
+            }
+          })
+          .catch((error) => {
+            console.log('鑷姩璁㈤槄鍙栨秷鎴栧け璐ワ細', error)
+          })
+      },
+
       // 鍔犺浇娑堟伅鍒楄〃
       async loadMessages() {
         try {
@@ -157,6 +180,23 @@
       formatMessageTime(dateTime) {
         if (!dateTime) return ''
         return formatDateTime(dateTime, 'MM-DD HH:mm')
+      },
+      
+      // 璁㈤槄浠诲姟閫氱煡
+      subscribeMessage() {
+        subscribeManager.subscribeWithConfirm()
+          .then((result) => {
+            if (result.success) {
+              uni.showToast({
+                title: '璁㈤槄鎴愬姛锛屾偍灏嗘敹鍒颁换鍔¢�氱煡',
+                icon: 'success',
+                duration: 2000
+              })
+            }
+          })
+          .catch((error) => {
+            console.log('璁㈤槄澶辫触锛�', error)
+          })
       }
     }
   }
@@ -199,6 +239,24 @@
       font-size: 36rpx;
       font-weight: bold;
     }
+    
+    .subscribe-btn {
+      display: flex;
+      align-items: center;
+      padding: 10rpx 20rpx;
+      background-color: #f0f9ff;
+      border-radius: 30rpx;
+      
+      text {
+        margin-left: 8rpx;
+        font-size: 26rpx;
+        color: #007AFF;
+      }
+      
+      &:active {
+        opacity: 0.7;
+      }
+    }
   }
   
   .message-list-scroll {
diff --git a/app/pagesTask/create-emergency.vue b/app/pagesTask/create-emergency.vue
index a6fde13..a0f819e 100644
--- a/app/pagesTask/create-emergency.vue
+++ b/app/pagesTask/create-emergency.vue
@@ -332,7 +332,7 @@
 import { listAvailableVehicles, getUserBoundVehicle } from "@/api/vehicle"
 import { searchHospitals, searchHospitalsByDeptRegion } from "@/api/hospital"
 import DepartureSelector from './components/DepartureSelector.vue'
-import { calculateDistance, baiduDistanceByAddress, baiduPlaceSuggestion } from "@/api/map"
+import { calculateTianDiTuDistance } from "@/api/map"
 import { listBranchUsers } from "@/api/system/user"
 import { searchIcd10 } from "@/api/icd10"
 import { calculateTransferPrice } from "@/api/price"
@@ -878,7 +878,7 @@
       
       // 璋冪敤鐧惧害鍦板浘API璁$畻璺濈
       const region = this.selectedRegion || '骞垮窞'
-      baiduDistanceByAddress(fromAddress, region, toAddress, region)
+      calculateTianDiTuDistance(fromAddress,  toAddress)
         .then(response => {
           uni.hideLoading()
           
@@ -1160,7 +1160,7 @@
       
       // 浣跨敤uni-app鐨凣PS瀹氫綅鍔熻兘
       uni.getLocation({
-        type: 'gcj02', // 杩斿洖鍥芥祴灞�鍧愭爣锛岄�傜敤浜庡浗鍐呭湴鍥�
+        type: 'gcj02', // 杩斿洖鍥芥祴灞�鍧愭爣锛岄�傜敤浜庡浗鍐呭湴鍥� 鐏槦鍧愭爣
         success: (res) => {
           console.log('鑾峰彇鍒癎PS鍧愭爣:', res)
           const latitude = res.latitude
@@ -1626,7 +1626,7 @@
       })
       
       // 璋冪敤鐧惧害鍦板浘API璁$畻璺濈
-      baiduDistanceByAddress(fromAddress, fromCity, toAddress, toCity)
+      calculateTianDiTuDistance(fromAddress, toAddress)
         .then(response => {
           uni.hideLoading()
           
diff --git a/app/pagesTask/detail.vue b/app/pagesTask/detail.vue
index 781b0d4..214bb7b 100644
--- a/app/pagesTask/detail.vue
+++ b/app/pagesTask/detail.vue
@@ -37,10 +37,10 @@
       <view class="detail-section">
         <view class="section-title">鏃堕棿淇℃伅</view>
         <view class="info-item">
-          <view class="label">璁″垝寮�濮嬫椂闂�</view>
+          <view class="label">棰勭害鏃堕棿</view>
           <view class="value">{{ displayPlannedStartTime }}</view>
         </view>
-        <view class="info-item">
+        <view class="info-item" v-if="taskDetail.plannedEndTime">
           <view class="label">璁″垝缁撴潫鏃堕棿</view>
           <view class="value">{{ displayPlannedEndTime }}</view>
         </view>
@@ -466,28 +466,48 @@
         if (!this.taskDetail || !this.taskDetail.plannedStartTime) {
           return '鏈缃�'
         }
-        return formatDateTime(this.taskDetail.plannedStartTime, 'YYYY-MM-DD HH:mm')
+        const formatted = formatDateTime(this.taskDetail.plannedStartTime, 'YYYY-MM-DD HH:mm')
+        // 濡傛灉骞翠唤鏄�1900,琛ㄧず鏃犳晥鏃ユ湡,鏄剧ず涓烘湭璁剧疆
+        if (formatted && formatted.startsWith('1900')) {
+          return '鏈缃�'
+        }
+        return formatted
       },
       // 鏄剧ず璁″垝缁撴潫鏃堕棿
       displayPlannedEndTime() {
         if (!this.taskDetail || !this.taskDetail.plannedEndTime) {
           return '鏈缃�'
         }
-        return formatDateTime(this.taskDetail.plannedEndTime, 'YYYY-MM-DD HH:mm')
+        const formatted = formatDateTime(this.taskDetail.plannedEndTime, 'YYYY-MM-DD HH:mm')
+        // 濡傛灉骞翠唤鏄�1900,琛ㄧず鏃犳晥鏃ユ湡,鏄剧ず涓烘湭璁剧疆
+        if (formatted && formatted.startsWith('1900')) {
+          return '鏈缃�'
+        }
+        return formatted
       },
       // 鏄剧ず瀹為檯寮�濮嬫椂闂�
       displayActualStartTime() {
         if (!this.taskDetail || !this.taskDetail.actualStartTime) {
           return '鏈缃�'
         }
-        return formatDateTime(this.taskDetail.actualStartTime, 'YYYY-MM-DD HH:mm')
+        const formatted = formatDateTime(this.taskDetail.actualStartTime, 'YYYY-MM-DD HH:mm')
+        // 濡傛灉骞翠唤鏄�1900,琛ㄧず鏃犳晥鏃ユ湡,鏄剧ず涓烘湭璁剧疆
+        if (formatted && formatted.startsWith('1900')) {
+          return '鏈缃�'
+        }
+        return formatted
       },
       // 鏄剧ず瀹為檯缁撴潫鏃堕棿
       displayActualEndTime() {
         if (!this.taskDetail || !this.taskDetail.actualEndTime) {
           return '鏈缃�'
         }
-        return formatDateTime(this.taskDetail.actualEndTime, 'YYYY-MM-DD HH:mm')
+        const formatted = formatDateTime(this.taskDetail.actualEndTime, 'YYYY-MM-DD HH:mm')
+        // 濡傛灉骞翠唤鏄�1900,琛ㄧず鏃犳晥鏃ユ湡,鏄剧ず涓烘湭璁剧疆
+        if (formatted && formatted.startsWith('1900')) {
+          return '鏈缃�'
+        }
+        return formatted
       }
     },
     onLoad(options) {
diff --git a/app/utils/subscribe.js b/app/utils/subscribe.js
new file mode 100644
index 0000000..8066c8a
--- /dev/null
+++ b/app/utils/subscribe.js
@@ -0,0 +1,327 @@
+import { getWechatConfig } from '@/api/wechat'
+
+/**
+ * 寰俊璁㈤槄娑堟伅宸ュ叿绫�
+ * 缁熶竴绠$悊璁㈤槄娑堟伅鐩稿叧鍔熻兘
+ */
+class SubscribeManager {
+  constructor() {
+    this.wechatConfig = {
+      taskNotifyTemplateId: ''
+    }
+    this.configLoaded = false
+  }
+
+  /**
+   * 鍔犺浇寰俊閰嶇疆
+   * @returns {Promise}
+   */
+  loadWechatConfig() {
+    return new Promise((resolve, reject) => {
+      if (this.configLoaded && this.wechatConfig.taskNotifyTemplateId) {
+        resolve(this.wechatConfig)
+        return
+      }
+
+      getWechatConfig()
+        .then((response) => {
+          if (response.code === 200 && response.data) {
+            this.wechatConfig = response.data
+            this.configLoaded = true
+            console.log('寰俊閰嶇疆鍔犺浇鎴愬姛锛�', this.wechatConfig)
+            resolve(this.wechatConfig)
+          } else {
+            console.warn('鍔犺浇寰俊閰嶇疆澶辫触锛屼娇鐢ㄩ粯璁ら厤缃�')
+            reject(new Error('鍔犺浇寰俊閰嶇疆澶辫触'))
+          }
+        })
+        .catch((error) => {
+          console.error('鍔犺浇寰俊閰嶇疆澶辫触锛�', error)
+          reject(error)
+        })
+    })
+  }
+
+  /**
+   * 妫�鏌ユ湰鍦拌闃呯姸鎬侊紙浠庣紦瀛樿鍙栵級
+   * @returns {boolean}
+   */
+  checkLocalSubscribeStatus() {
+    return true;// uni.getStorageSync('hasSubscribedTaskNotify') || false
+  }
+
+  /**
+   * 妫�鏌ュ井淇″畼鏂硅闃呯姸鎬侊紙鐪熷疄鐘舵�侊級
+   * @returns {Promise<boolean>}
+   */
+  checkWechatSubscribeStatus() {
+    return new Promise((resolve) => {
+      // #ifdef MP-WEIXIN
+      // 闇�瑕佸厛鍔犺浇閰嶇疆鑾峰彇妯℃澘ID
+      this.loadWechatConfig()
+        .then(() => {
+          const templateId = this.wechatConfig.taskNotifyTemplateId
+          if (!templateId) {
+            console.warn('妯℃澘ID鏈厤缃紝鏃犳硶妫�鏌ヨ闃呯姸鎬�')
+            resolve(false)
+            return
+          }
+
+          wx.getSetting({
+            withSubscriptions: true,
+            success: (res) => {
+              console.log('寰俊璁㈤槄鐘舵�佹煡璇㈢粨鏋滐細', res)
+              
+              // 妫�鏌ubscriptionsSetting涓槸鍚︽湁璇ユā鏉縄D鐨勮褰�
+              if (res.subscriptionsSetting && res.subscriptionsSetting.mainSwitch) {
+                const subscribeStatus = res.subscriptionsSetting.mainSwitch;
+                resolve(subscribeStatus)
+                // 'accept' 琛ㄧず鐢ㄦ埛鍚屾剰璁㈤槄锛�'reject' 琛ㄧず鎷掔粷锛�'ban' 琛ㄧず琚皝绂�
+                // const isSubscribed = subscribeStatus === 'accept'
+                // console.log(`妯℃澘ID ${templateId} 璁㈤槄鐘舵�侊細`, subscribeStatus, '鏄惁宸茶闃咃細', isSubscribed)
+                // resolve(isSubscribed)
+              } else {
+                console.log('鏈壘鍒拌闃呰缃俊鎭紝瑙嗕负鏈闃�')
+                resolve(false)
+              }
+            },
+            fail: (err) => {
+              console.error('鑾峰彇寰俊璁剧疆澶辫触锛�', err)
+              resolve(false)
+            }
+          })
+        })
+        .catch((error) => {
+          console.error('鍔犺浇閰嶇疆澶辫触锛屾棤娉曟鏌ヨ闃呯姸鎬侊細', error)
+          resolve(false)
+        })
+      // #endif
+
+      // #ifndef MP-WEIXIN
+      console.log('闈炲井淇″皬绋嬪簭鐜锛屾棤娉曟鏌ヨ闃呯姸鎬�')
+      resolve(false)
+      // #endif
+    })
+  }
+
+  /**
+   * 妫�鏌ヨ闃呯姸鎬侊紙缁煎悎妫�鏌ワ級
+   * 鍏堟鏌ユ湰鍦扮姸鎬侊紝鍐嶆鏌ュ井淇″畼鏂圭姸鎬�
+   * @returns {Promise<{local: boolean, wechat: boolean, needResubscribe: boolean}>}
+   */
+  async checkSubscribeStatus() {
+    const localStatus = this.checkLocalSubscribeStatus()
+    const wechatStatus = await this.checkWechatSubscribeStatus()
+    
+    // 濡傛灉鏈湴鏄剧ず宸茶闃咃紝浣嗗井淇″畼鏂规樉绀烘湭璁㈤槄锛岄渶瑕侀噸鏂拌闃�
+    const needResubscribe =  wechatStatus
+    
+    if (needResubscribe) {
+      console.warn('鏈湴鐘舵�佷笌寰俊瀹樻柟鐘舵�佷笉涓�鑷达紝闇�瑕侀噸鏂拌闃�')
+      // 娓呴櫎鏈湴璁板綍
+      uni.removeStorageSync('hasSubscribedTaskNotify')
+    }
+    
+    return {
+      local: localStatus,
+      wechat: wechatStatus,
+      needResubscribe: needResubscribe,
+      isSubscribed: wechatStatus // 浠ュ井淇″畼鏂圭姸鎬佷负鍑�
+    }
+  }
+
+  /**
+   * 鏄剧ず璁㈤槄纭寮圭獥
+   * @returns {Promise}
+   */
+  showSubscribeConfirm() {
+    return new Promise((resolve, reject) => {
+      // #ifdef MP-WEIXIN
+      wx.showModal({
+        title: '寮�鍚换鍔¢�氱煡',
+        content: '鍕鹃�夈�屾�绘槸淇濇寔浠ヤ笂閫夋嫨銆嶏紝鍚庣画鏂颁换鍔″皢鑷姩鎺ㄩ�亊',
+        confirmText: '鍘诲紑鍚�',
+        cancelText: '鏆備笉寮�鍚�',
+        success(res) {
+          if (res.confirm) {
+            resolve()
+          } else {
+            reject(new Error('鐢ㄦ埛鍙栨秷'))
+          }
+        },
+        fail() {
+          reject(new Error('寮圭獥澶辫触'))
+        }
+      })
+      // #endif
+
+      // #ifndef MP-WEIXIN
+      uni.showToast({
+        title: '浠呮敮鎸佸井淇″皬绋嬪簭',
+        icon: 'none'
+      })
+      reject(new Error('浠呮敮鎸佸井淇″皬绋嬪簭'))
+      // #endif
+    })
+  }
+
+  /**
+   * 璁㈤槄浠诲姟閫氱煡
+   * @param {Object} options 閰嶇疆閫夐」
+   * @param {boolean} options.showConfirm 鏄惁鏄剧ず纭寮圭獥锛岄粯璁rue
+   * @param {Function} options.onSuccess 鎴愬姛鍥炶皟
+   * @param {Function} options.onReject 鎷掔粷鍥炶皟
+   * @param {Function} options.onFail 澶辫触鍥炶皟
+   * @returns {Promise}
+   */
+  async subscribeTaskNotify(options = {}) {
+    const { 
+      showConfirm = true,
+      onSuccess,
+      onReject,
+      onFail
+    } = options
+
+    try {
+      // 鍔犺浇閰嶇疆
+      await this.loadWechatConfig()
+
+      // 妫�鏌ラ厤缃槸鍚﹀姞杞�
+      if (!this.wechatConfig.taskNotifyTemplateId) {
+        uni.showToast({
+          title: '閰嶇疆鍔犺浇涓紝璇风◢鍚庨噸璇�',
+          icon: 'none'
+        })
+        throw new Error('閰嶇疆鏈姞杞�')
+      }
+
+      // 鏄剧ず纭寮圭獥锛堝鏋滈渶瑕侊級
+      if (showConfirm) {
+        await this.showSubscribeConfirm()
+      }
+
+      // 鍙戣捣璁㈤槄
+      return new Promise((resolve, reject) => {
+        // #ifdef MP-WEIXIN
+        wx.requestSubscribeMessage({
+          tmplIds: [this.wechatConfig.taskNotifyTemplateId],
+          success: (res) => {
+            console.log('璁㈤槄娑堟伅鎺堟潈缁撴灉锛�', res)
+            const templateId = this.wechatConfig.taskNotifyTemplateId
+            
+            if (res[templateId] === 'accept') {
+              // 璁板綍宸茶闃�
+              uni.setStorageSync('hasSubscribedTaskNotify', true)
+              uni.showToast({
+                title: '璁㈤槄鎴愬姛',
+                icon: 'success'
+              })
+              
+              if (onSuccess) onSuccess()
+              resolve({ success: true, action: 'accept' })
+            } else if (res[templateId] === 'reject') {
+              uni.showToast({
+                title: '鎮ㄦ嫆缁濅簡璁㈤槄',
+                icon: 'none'
+              })
+              
+              if (onReject) onReject()
+              resolve({ success: false, action: 'reject' })
+            } else {
+              // 鍏朵粬鎯呭喌锛坆an绛夛級
+              resolve({ success: false, action: res[templateId] })
+            }
+          },
+          fail: (err) => {
+            console.error('璁㈤槄娑堟伅澶辫触锛�', err)
+            uni.showToast({
+              title: '璁㈤槄澶辫触',
+              icon: 'none'
+            })
+            
+            if (onFail) onFail(err)
+            reject(err)
+          }
+        })
+        // #endif
+
+        // #ifndef MP-WEIXIN
+        uni.showToast({
+          title: '浠呮敮鎸佸井淇″皬绋嬪簭',
+          icon: 'none'
+        })
+        reject(new Error('浠呮敮鎸佸井淇″皬绋嬪簭'))
+        // #endif
+      })
+    } catch (error) {
+      console.error('璁㈤槄娴佺▼寮傚父锛�', error)
+      throw error
+    }
+  }
+
+  /**
+   * 蹇�熻闃咃紙甯︾‘璁ゅ脊绐楋級
+   * @returns {Promise}
+   */
+  subscribeWithConfirm() {
+    return this.subscribeTaskNotify({ showConfirm: true })
+  }
+
+  /**
+   * 鐩存帴璁㈤槄锛堜笉鏄剧ず纭寮圭獥锛�
+   * @returns {Promise}
+   */
+  subscribeDirect() {
+    return this.subscribeTaskNotify({ showConfirm: false })
+  }
+
+  /**
+   * 鑷姩璁㈤槄锛堟櫤鑳芥鏌ワ級
+   * 濡傛灉宸茶闃呭垯璺宠繃锛屾湭璁㈤槄鍒欐樉绀虹‘璁ゅ脊绐�
+   * @param {Object} options 閰嶇疆閫夐」
+   * @param {boolean} options.force 鏄惁寮哄埗鏄剧ず璁㈤槄寮圭獥锛岄粯璁alse
+   * @returns {Promise}
+   */
+  async autoSubscribe(options = {}) {
+    const { force = false } = options
+    
+    try {
+      // 缁煎悎妫�鏌ヨ闃呯姸鎬侊紙鏈湴 + 寰俊瀹樻柟锛�
+      const status = await this.checkSubscribeStatus()
+      
+      console.log('璁㈤槄鐘舵�佹鏌ョ粨鏋滐細', status)
+      
+      // 濡傛灉寰俊瀹樻柟鐘舵�佹樉绀哄凡璁㈤槄锛屼笖涓嶅己鍒惰闃�
+      if (status.isSubscribed && !force) {
+        console.log('鐢ㄦ埛宸茶闃呰繃锛堝井淇″畼鏂圭姸鎬侊級锛岃烦杩囪嚜鍔ㄨ闃�')
+        return { success: true, action: 'already_subscribed', skipped: true, status }
+      }
+
+      // 濡傛灉闇�瑕侀噸鏂拌闃呮垨鏈闃�
+      if (status.needResubscribe) {
+        console.log('妫�娴嬪埌璁㈤槄鐘舵�佸け鏁堬紝瑙﹀彂閲嶆柊璁㈤槄娴佺▼')
+      } else {
+        console.log('鐢ㄦ埛鏈闃咃紝瑙﹀彂鑷姩璁㈤槄娴佺▼')
+      }
+      
+      // 鏄剧ず纭寮圭獥骞惰闃� 鐩存帴榛樿璁㈤槄
+      const result = await this.subscribeWithConfirm();
+      return { ...result, status }
+    } catch (error) {
+      console.log('鑷姩璁㈤槄娴佺▼寮傚父锛�', error)
+      return { success: false, action: 'error', error }
+    }
+  }
+
+  /**
+   * 閲嶇疆璁㈤槄鐘舵��
+   */
+  resetSubscribeStatus() {
+    uni.removeStorageSync('hasSubscribedTaskNotify')
+  }
+}
+
+// 鍒涘缓鍗曚緥
+const subscribeManager = new SubscribeManager()
+
+export default subscribeManager
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index a77a0d9..d9c5fc8 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -57,13 +57,17 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>ruoyi-quartz</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>2.1.4</version>
+        </dependency>
         <!-- 浠g爜鐢熸垚-->
         <dependency>
             <groupId>com.ruoyi</groupId>
             <artifactId>ruoyi-generator</artifactId>
         </dependency>
-        
+
         <!-- 鏀粯妯″潡 -->
         <dependency>
             <groupId>com.ruoyi</groupId>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
index 188657d..5d64960 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java
@@ -1,5 +1,6 @@
 package com.ruoyi.web.controller.system;
 
+import java.io.ByteArrayInputStream;
 import java.util.*;
 import java.text.SimpleDateFormat;
 import java.text.ParseException;
@@ -7,11 +8,16 @@
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.system.domain.*;
 import com.ruoyi.system.service.*;
 import com.ruoyi.common.config.TencentMapConfig;
 import com.ruoyi.common.config.BaiduMapConfig;
 import com.ruoyi.common.config.TiandituMapConfig;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -31,6 +37,10 @@
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.utils.http.HttpUtils;
+
+
+import javax.annotation.Resource;
+
 
 /**
  * 杞﹁締GPS鍧愭爣Controller
@@ -67,6 +77,13 @@
     
     @Autowired
     private TiandituMapConfig tiandituMapConfig;
+
+
+    @Resource(name = "tiandituMapService")
+    private IMapService tiandituMapService;
+
+    @Resource(name = "baiduMapService")
+    private IMapService baiduMapService;
 
    /**
      * 鏌ヨ杞﹁締GPS鍧愭爣鍒楄〃
@@ -478,7 +495,29 @@
             return AjaxResult.error("璺濈璁$畻澶辫触锛�" + e.getMessage());
         }
     }
-    
+
+    /**
+     * 鐧惧害鍦板浘閫嗗湴鍧�瑙f瀽鎺ュ彛浠g悊
+     */
+    @Anonymous()
+    @GetMapping("/baidu/reverseGeocoding")
+    public AjaxResult baiduResolveAddress(Double lng, Double lat) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (lat == null || lng == null) {
+                return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯缁忕含搴﹀潗鏍�");
+            }
+
+           String response= baiduMapService.reverseGeocoding(lng, lat);
+            // 鍙戦�丠TTP璇锋眰
+            Map<String,String> objResult=new HashMap<>();
+            objResult.put("address",response);
+            return AjaxResult.success("鏌ヨ鎴愬姛", objResult);
+        }catch (Exception e){
+            logger.error("鐧惧害閫嗗湴鍧�瑙f瀽澶辫触: lat={}, lng={}", lat, lng, e);
+            return AjaxResult.error("鐧惧害閫嗗湴鍧�瑙f瀽澶辫触锛�" + e.getMessage());
+        }
+    }
     /**
      * 鐧惧害鍦板浘鍦扮悊缂栫爜鎺ュ彛浠g悊锛堝湴鍧�杞潗鏍囷級
      */
@@ -490,22 +529,11 @@
             if (address == null || address.trim().isEmpty()) {
                 return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鍦板潃淇℃伅");
             }
-            
-            // 鏋勫缓鐧惧害鍦板浘鍦扮悊缂栫爜API URL
-            String url = "https://api.map.baidu.com/geocoding/v3/";
-            String params = "address=" + URLEncoder.encode(address, StandardCharsets.UTF_8.toString()) +
-                           (city != null && !city.trim().isEmpty() ? 
-                            "&city=" + URLEncoder.encode(city, StandardCharsets.UTF_8.toString()) : "") +
-                           "&output=json" +
-                           "&ak=" + baiduMapConfig.getAk();
-            
-            logger.info("鐧惧害鍦板浘鍦扮悊缂栫爜璇锋眰: address={}, city={}", address, city);
-            
-            // 鍙戦�丠TTP璇锋眰
-            String response = HttpUtils.sendGet(url, params);
+            Map<String,Double> objResult=baiduMapService.geocoding(address, city);
+
             
             // 杩斿洖缁撴灉
-            return AjaxResult.success("鏌ヨ鎴愬姛", response);
+            return AjaxResult.success("鏌ヨ鎴愬姛", objResult);
         } catch (Exception e) {
             logger.error("鐧惧害鍦板浘鍦扮悊缂栫爜澶辫触", e);
             return AjaxResult.error("鍦扮悊缂栫爜澶辫触锛�" + e.getMessage());
@@ -759,18 +787,11 @@
             if (address == null || address.trim().isEmpty()) {
                 return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鍦板潃淇℃伅");
             }
-            
-            // 鏋勫缓澶╁湴鍥惧湴鐞嗙紪鐮丄PI URL
-            String url = "http://api.tianditu.gov.cn/geocoder";
-            String params = "ds={\"keyWord\":\"" + address + "\"}&tk=" + tiandituMapConfig.getTk();
-            
-            logger.info("澶╁湴鍥惧湴鐞嗙紪鐮佽姹�: address={}", address);
-            
-            // 鍙戦�丠TTP璇锋眰
-            String response = HttpUtils.sendGet(url, params);
-            
+            Map<String,Double> resultMap =tiandituMapService.geocoding(address,"");
+
+
             // 杩斿洖缁撴灉
-            return AjaxResult.success("鏌ヨ鎴愬姛", response);
+            return AjaxResult.success("鏌ヨ鎴愬姛", resultMap);
         } catch (Exception e) {
             logger.error("澶╁湴鍥惧湴鐞嗙紪鐮佸け璐�", e);
             return AjaxResult.error("鍦扮悊缂栫爜澶辫触锛�" + e.getMessage());
@@ -795,20 +816,13 @@
                 Double.isInfinite(lat) || Double.isInfinite(lon)) {
                 return AjaxResult.error("鍙傛暟鏃犳晥锛岀粡绾害鍧愭爣鏍煎紡閿欒");
             }
+            String address=this.tiandituMapService.reverseGeocoding(lon, lat);
+
             
-            // 鏋勫缓澶╁湴鍥鹃�嗗湴鐞嗙紪鐮丄PI URL
-            String url = "http://api.tianditu.gov.cn/geocoder";
-            String params = "postStr={\"lon\":" + lon + ",\"lat\":" + lat + ",\"ver\":1}" +
-                           "&type=geocode" +
-                           "&tk=" + tiandituMapConfig.getTk();
-            
-            logger.info("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佽姹�: lon={}, lat={}", lon, lat);
-            
-            // 鍙戦�丠TTP璇锋眰
-            String response = HttpUtils.sendGet(url, params);
-            
+            Map<String,String> resultMap = new HashMap<>();
+            resultMap.put("address",address);
             // 杩斿洖缁撴灉
-            return AjaxResult.success("鏌ヨ鎴愬姛", response);
+            return AjaxResult.success("鏌ヨ鎴愬姛",resultMap);
         } catch (Exception e) {
             logger.error("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佸け璐�: lon={}, lat={}", lon, lat, e);
             return AjaxResult.error("閫嗗湴鐞嗙紪鐮佸け璐ワ細" + e.getMessage());
@@ -937,56 +951,21 @@
                 toAddress == null || toAddress.trim().isEmpty()) {
                 return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯璧风偣鎴栫粓鐐瑰湴鍧�");
             }
-            
-            logger.info("寮�濮嬭绠楀湴鍧�璺濈: fromAddress={}, toAddress={}", fromAddress, toAddress);
-            
-            // 绗竴姝ワ細璧风偣鍦板潃杞潗鏍�
-            String geocodingUrl1 = "http://api.tianditu.gov.cn/geocoder";
-            String geocodingParams1 = "ds={\"keyWord\":\"" + fromAddress + "\"}" +
-                                     "&tk=" + tiandituMapConfig.getTk();
-            
-            String geocodingResponse1 = HttpUtils.sendGet(geocodingUrl1, geocodingParams1);
-            logger.info("璧风偣鍦扮悊缂栫爜鍝嶅簲: {}", geocodingResponse1);
-            
-            // 瑙f瀽璧风偣鍧愭爣
-            com.alibaba.fastjson2.JSONObject geocodingJson1 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse1);
-            if (!"0".equals(geocodingJson1.getString("status"))) {
-                logger.error("璧风偣鍦扮悊缂栫爜澶辫触: {}", geocodingResponse1);
-                return AjaxResult.error("璧风偣鍦板潃瑙f瀽澶辫触");
-            }
-            com.alibaba.fastjson2.JSONObject location1 = geocodingJson1.getJSONObject("location");
-            if (location1 == null) {
-                return AjaxResult.error("璧风偣鍦板潃鏈壘鍒板搴斿潗鏍�");
-            }
-            double fromLon = location1.getDouble("lon");
-            double fromLat = location1.getDouble("lat");
-            logger.info("璧风偣鍧愭爣: lon={}, lat={}", fromLon, fromLat);
-            
-            // 绗簩姝ワ細缁堢偣鍦板潃杞潗鏍�
-            String geocodingUrl2 = "http://api.tianditu.gov.cn/geocoder";
-            String geocodingParams2 = "ds={\"keyWord\":\"" + toAddress + "\"}" +
-                                     "&tk=" + tiandituMapConfig.getTk();
-            
-            String geocodingResponse2 = HttpUtils.sendGet(geocodingUrl2, geocodingParams2);
-            logger.info("缁堢偣鍦扮悊缂栫爜鍝嶅簲: {}", geocodingResponse2);
-            
-            // 瑙f瀽缁堢偣鍧愭爣
-            com.alibaba.fastjson2.JSONObject geocodingJson2 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse2);
-            if (!"0".equals(geocodingJson2.getString("status"))) {
-                logger.error("缁堢偣鍦扮悊缂栫爜澶辫触: {}", geocodingResponse2);
-                return AjaxResult.error("缁堢偣鍦板潃瑙f瀽澶辫触");
-            }
-            com.alibaba.fastjson2.JSONObject location2 = geocodingJson2.getJSONObject("location");
-            if (location2 == null) {
-                return AjaxResult.error("缁堢偣鍦板潃鏈壘鍒板搴斿潗鏍�");
-            }
-            double toLon = location2.getDouble("lon");
-            double toLat = location2.getDouble("lat");
+
+            Map<String,Double> fromLngLat= tiandituMapService.geocoding(fromAddress, null);
+
+            double fromLng = fromLngLat.get("lng");
+            double fromLat = fromLngLat.get("lat");
+            logger.info("璧风偣鍧愭爣: lon={}, lat={}", fromLng, fromLat);
+
+            Map<String,Double> toLngLat = tiandituMapService.geocoding(toAddress, null);
+            double toLon = toLngLat.get("lng");
+            double toLat = toLngLat.get("lat");
             logger.info("缁堢偣鍧愭爣: lon={}, lat={}", toLon, toLat);
             
             // 绗笁姝ワ細璋冪敤璺緞瑙勫垝鎺ュ彛璁$畻璺濈
             String routeUrl = "http://api.tianditu.gov.cn/drive";
-            String orig = fromLon + "," + fromLat;
+            String orig = fromLng + "," + fromLat;
             String dest = toLon + "," + toLat;
             String routeParams = "postStr={\"orig\":\"" + orig + "\",\"dest\":\"" + dest + "\",\"style\":\"0\"}" +
                                 "&tk=" + tiandituMapConfig.getTk();
@@ -994,53 +973,314 @@
             logger.info("璺緞瑙勫垝璇锋眰: orig={}, dest={}", orig, dest);
             String routeResponse = HttpUtils.sendGet(routeUrl, routeParams);
             logger.info("璺緞瑙勫垝鍝嶅簲: {}", routeResponse);
-            
-            // 瑙f瀽璺濈缁撴灉
-            com.alibaba.fastjson2.JSONObject routeJson = com.alibaba.fastjson2.JSONObject.parseObject(routeResponse);
-            if (!"0".equals(routeJson.getString("status"))) {
-                logger.error("璺緞瑙勫垝澶辫触: {}", routeResponse);
-                return AjaxResult.error("璺緞瑙勫垝澶辫触");
+            //<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+            //<result dest="113.3472,23.16957" mid="" orig="113.373308,23.136699">
+            //
+            //    <parameters>
+            //
+            //        <orig>113.373308,23.136699</orig>
+            //
+            //        <dest>113.3472,23.16957</dest>
+            //
+            //        <mid/>
+            //
+            //        <key/>
+            //
+            //        <width>600</width>
+            //
+            //        <height>400</height>
+            //
+            //        <style>0</style>
+            //
+            //        <version/>
+            //
+            //        <sort/>
+            //
+            //    </parameters>
+            //
+            //    <routes count="9" time="0.0">
+            //
+            //        <item id="0">
+            //
+            //            <strguide>浠庢瀹夎矾鍚戣タ鍑哄彂,娌挎瀹夎矾璧�100绫冲苟宸﹁浆,</strguide>
+            //
+            //            <signage/>
+            //
+            //            <streetName>妫犲畨璺�</streetName>
+            //
+            //            <nextStreetName/>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.37323,23.13677</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="1">
+            //
+            //            <strguide>璧�100绫冲苟鍚戝箍鍥揩閫�/鐪侀亾303/鍗庡崡蹇��/鐪侀亾81/鐜煄楂橀��/鍗庤璺�/宀戞潙/鐪侀亾3/骞挎繁娌挎睙鏂瑰悜杩涘叆绉戦煹涓矾,</strguide>
+            //
+            //            <signage>骞垮洯蹇��/鐪侀亾303/鍗庡崡蹇��/鐪侀亾81/鐜煄楂橀��/鍗庤璺�/宀戞潙/鐪侀亾3/骞挎繁娌挎睙</signage>
+            //
+            //            <streetName/>
+            //
+            //            <nextStreetName>绉戦煹涓矾</nextStreetName>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.37185,23.13699</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="2">
+            //
+            //            <strguide>娌跨闊典腑璺蛋0.6鍏噷骞跺悜骞垮洯蹇��(瑗胯)/鐪侀亾303/鍗庡崡蹇�熸柟鍚戣繘鍏ュ箍鍥揩閫熻矾,</strguide>
+            //
+            //            <signage>骞垮洯蹇��(瑗胯)/鐪侀亾303/鍗庡崡蹇��</signage>
+            //
+            //            <streetName>绉戦煹涓矾</streetName>
+            //
+            //            <nextStreetName>骞垮洯蹇�熻矾</nextStreetName>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.37107,23.13648</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="3">
+            //
+            //            <strguide>娌垮箍鍥揩閫熻矾璧�1.9鍏噷骞朵粠鍗庡崡蹇��/骞垮窞鍗楃珯/骞垮窞鍖楃珯/鐜煄楂橀��(鍖楃幆)/骞垮窞闀块殕/甯藉嘲灞�/鍗庡崡蹇��(鍖楄)/鍥介亾4/骞垮窞鐜煄楂橀��/鍗庡崡蹇��(瑗�)/浜腐婢抽珮閫�/骞垮窞鏈哄満楂橀��/骞挎渤楂橀��/闊跺叧/鐪侀亾81/鐪侀亾8鏂瑰悜鍖濋亾杩涘叆鍗庡崡绔嬩氦妗�,</strguide>
+            //
+            //            <signage>鍗庡崡蹇��/骞垮窞鍗楃珯/骞垮窞鍖楃珯/鐜煄楂橀��(鍖楃幆)/骞垮窞闀块殕/甯藉嘲灞�/鍗庡崡蹇��(鍖楄)/鍥介亾4/骞垮窞鐜煄楂橀��/鍗庡崡蹇��(瑗�)/浜腐婢抽珮閫�/骞垮窞鏈哄満楂橀��/骞挎渤楂橀��/闊跺叧/鐪侀亾81/鐪侀亾8鏂瑰悜鍖濋亾</signage>
+            //
+            //            <streetName>骞垮洯蹇�熻矾</streetName>
+            //
+            //            <nextStreetName>鍗庡崡绔嬩氦妗�</nextStreetName>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.37139,23.14206</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="4">
+            //
+            //            <strguide>娌垮崕鍗楃珛浜ゆˉ鐩樻ˉ鍚戝寳璧�0.6鍏噷骞剁洿琛屽埌鐪侀亾4/鍗庡崡蹇��,</strguide>
+            //
+            //            <signage/>
+            //
+            //            <streetName>鍗庡崡绔嬩氦妗�</streetName>
+            //
+            //            <nextStreetName>鐪侀亾4/鍗庡崡蹇��</nextStreetName>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.35685,23.14669</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="5">
+            //
+            //            <strguide>娌跨渷閬�4/鍗庡崡蹇�熻蛋0.6鍏噷骞朵粠澶╂渤瀹㈣繍绔�/鐪侀亾15/鍏冨矖/浣涘北/娣卞湷/骞垮窞鐜煄楂橀��/娌堟捣楂橀�熸敮绾�/鍗庡崡蹇�熺鐞嗕腑蹇�/宀戞潙绔嬩氦/鐪侀亾81鏂瑰悜鍖濋亾杩涘叆宀戞潙绔嬩氦,</strguide>
+            //
+            //            <signage>澶╂渤瀹㈣繍绔�/鐪侀亾15/鍏冨矖/浣涘北/娣卞湷/骞垮窞鐜煄楂橀��/娌堟捣楂橀�熸敮绾�/鍗庡崡蹇�熺鐞嗕腑蹇�/宀戞潙绔嬩氦/鐪侀亾81鏂瑰悜鍖濋亾</signage>
+            //
+            //            <streetName>鐪侀亾4/鍗庡崡蹇��</streetName>
+            //
+            //            <nextStreetName>宀戞潙绔嬩氦</nextStreetName>
+            //
+            //            <tollStatus>1</tollStatus>
+            //
+            //            <turnlatlon>113.35518,23.15157</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="6">
+            //
+            //            <strguide>娌垮矐鏉戠珛浜ょ洏妗ュ悜瑗垮寳璧�0.5鍏噷骞朵粠澶╂渤瀹㈣繍绔�/鍏冨矖/骞挎睍璺�/宀戞潙璺�/甯備氦璀︽敮闃熷嚭鍙i┒绂诲苟杩涘叆闀垮叴璺�,</strguide>
+            //
+            //            <signage>澶╂渤瀹㈣繍绔�/鍏冨矖/骞挎睍璺�/宀戞潙璺�/甯備氦璀︽敮闃熷嚭鍙�</signage>
+            //
+            //            <streetName>宀戞潙绔嬩氦</streetName>
+            //
+            //            <nextStreetName>闀垮叴璺�</nextStreetName>
+            //
+            //            <tollStatus>1</tollStatus>
+            //
+            //            <turnlatlon>113.35731,23.15636</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="7">
+            //
+            //            <strguide>娌块暱鍏磋矾璧�2.8鍏噷骞跺彸杞埌闀挎勾涓矾,</strguide>
+            //
+            //            <signage/>
+            //
+            //            <streetName>闀垮叴璺�</streetName>
+            //
+            //            <nextStreetName>闀挎勾涓矾</nextStreetName>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.35829,23.16086</turnlatlon>
+            //
+            //        </item>
+            //
+            //        <item id="8">
+            //
+            //            <strguide>娌块暱婀翠腑璺蛋100绫冲埌杈剧洰鐨勫湴銆�</strguide>
+            //
+            //            <signage/>
+            //
+            //            <streetName>闀挎勾涓矾</streetName>
+            //
+            //            <nextStreetName/>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.34714,23.17047</turnlatlon>
+            //
+            //        </item>
+            //
+            //    </routes>
+            //
+            //    <simple>
+            //
+            //        <item id="0">
+            //
+            //            <strguide>浠庢瀹夎矾鍑哄彂,杩涘叆绉戦煹涓矾銆�</strguide>
+            //
+            //            <streetNames>妫犲畨璺�</streetNames>
+            //
+            //            <lastStreetName/>
+            //
+            //            <linkStreetName>绉戦煹涓矾</linkStreetName>
+            //
+            //            <signage/>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.37323,23.13677</turnlatlon>
+            //
+            //            <streetLatLon>113.37323,23.13677;113.37291,23.13683;113.37272,23.13687;113.37272,23.13687;113.37265,23.13688;113.37265,23.13688;113.37227,23.13696;113.37227,23.13696;113.37209,23.13699;113.37201,23.13696;113.37201,23.13696;113.37185,23.13699;</streetLatLon>
+            //
+            //            <streetDistance>144.0</streetDistance>
+            //
+            //            <segmentNumber>0</segmentNumber>
+            //
+            //        </item>
+            //
+            //        <item id="1">
+            //
+            //            <strguide>娌跨闊典腑璺椹�,鍚戝箍鍥揩閫�(瑗胯)/鐪侀亾303/鍗庡崡蹇�熸柟鍚�,杩涘叆鐪侀亾4/鍗庡崡蹇�熴��</strguide>
+            //
+            //            <streetNames/>
+            //
+            //            <lastStreetName>绉戦煹涓矾</lastStreetName>
+            //
+            //            <linkStreetName>鐪侀亾4/鍗庡崡蹇��</linkStreetName>
+            //
+            //            <signage>骞垮洯蹇��(瑗胯)/鐪侀亾303/鍗庡崡蹇��</signage>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.37107,23.13648</turnlatlon>
+            //
+            //            <streetLatLon>113.37185,23.13699;113.37174,23.13683;113.3714,23.13649;113.37134,23.13645;113.37126,23.13643;113.37116,23.13644;113.37107,23.13648;113.37107,23.13648;113.37103,23.13657;113.37091,23.13683;113.37091,23.13683;113.37086,23.13693;113.3708,23.13705;113.3708,23.13705;113.37075,23.13717;113.37075,23.13717;113.37069,23.1373;113.37069,23.1373;113.37067,23.13735;113.37067,23.13735;113.3706,23.13755;113.37057,23.13765;113.37055,23.13779;113.37054,23.13794;113.37054,23.13804;113.37054,23.13814;113.37054,23.13831;113.37055,23.13844;113.37055,23.13844;113.37056,23.13855;113.37058,23.13865;113.3706,23.13878;113.37062,23.13884;113.37068,23.13911;113.37073,23.13935;113.37075,23.13944;113.37079,23.1396;113.3708,23.13964;113.37083,23.13975;113.37083,23.13975;113.37084,23.1398;113.37084,23.1398;113.37087,23.13998;113.3709,23.1401;113.37097,23.14039;113.371,23.14051;113.371,23.14051;113.3711,23.1409;113.37114,23.14105;113.37116,23.14115;113.3712,23.14127;113.37121,23.14135;113.37124,23.14146;113.37125,23.14153;113.37126,23.14155;113.37129,23.14167;113.37129,23.14167;113.37134,23.14187;113.37136,23.14194;113.37139,23.14206;</streetLatLon>
+            //
+            //            <streetDistance>748.0</streetDistance>
+            //
+            //            <segmentNumber>1-2</segmentNumber>
+            //
+            //        </item>
+            //
+            //        <item id="2">
+            //
+            //            <strguide>娌跨渷閬�4/鍗庡崡蹇��,宀戞潙绔嬩氦,琛岄┒鍒板箍鍥揩閫熻矾,鍦ㄥぉ娌冲杩愮珯/鍏冨矖/骞挎睍璺�/宀戞潙璺�/甯備氦璀︽敮闃熷嚭鍙i┒绂�,杩涘叆闀挎勾涓矾銆�</strguide>
+            //
+            //            <streetNames>鐪侀亾4/鍗庡崡蹇��,宀戞潙绔嬩氦,</streetNames>
+            //
+            //            <lastStreetName>骞垮洯蹇�熻矾</lastStreetName>
+            //
+            //            <linkStreetName>闀挎勾涓矾</linkStreetName>
+            //
+            //            <signage>澶╂渤瀹㈣繍绔�/鍏冨矖/骞挎睍璺�/宀戞潙璺�/甯備氦璀︽敮闃熷嚭鍙�</signage>
+            //
+            //            <tollStatus>2</tollStatus>
+            //
+            //            <turnlatlon>113.35731,23.15636</turnlatlon>
+            //
+            //            <streetLatLon>113.37139,23.14206;113.37145,23.14219;113.37151,23.1423;113.37157,23.14241;113.37164,23.14249;113.37171,23.14256;113.37175,23.1426;113.37179,23.14263;113.37182,23.14265;113.37186,23.14267;113.37192,23.14269;113.37196,23.1427;113.37206,23.14271;113.37216,23.14269;113.37222,23.14267;113.37229,23.14264;113.37234,23.14261;113.37239,23.14257;113.37243,23.14251;113.37247,23.14246;113.3725,23.14237;113.37251,23.14231;113.37251,23.14226;113.37251,23.14222;113.37249,23.14215;113.37248,23.14212;113.37247,23.14208;113.37245,23.14203;113.37242,23.14198;113.37235,23.14191;113.37226,23.14182;113.37215,23.14174;113.37206,23.14169;113.37202,23.14167;113.37183,23.1416;113.37169,23.14157;113.37157,23.14155;113.37145,23.14153;113.37131,23.14151;113.37131,23.14151;113.37125,23.14153;113.37115,23.14156;113.37049,23.14178;113.37036,23.14183;113.37022,23.14188;113.37006,23.14194;113.36995,23.14197;113.36995,23.14197;113.36986,23.14199;113.36979,23.142;113.36956,23.14203;113.36956,23.14203;113.36949,23.14205;113.36949,23.14205;113.3693,23.14213;113.3693,23.14213;113.3692,23.14218;113.3692,23.14218;113.3691,23.14223;113.3691,23.14223;113.36837,23.1425;113.36837,23.1425;113.36735,23.14293;113.36735,23.14293;113.36683,23.14314;113.36683,23.14314;113.36454,23.14409;113.36454,23.14409;113.36432,23.14418;113.36413,23.14426;113.3637,23.14444;113.3637,23.14444;113.36214,23.14505;113.36138,23.14532;113.36138,23.14532;113.36131,23.14535;113.36131,23.14535;113.36113,23.14541;113.36113,23.14541;113.36101,23.14545;113.36089,23.1455;113.36071,23.14556;113.36071,23.14556;113.36062,23.14559;113.36052,23.14562;113.36052,23.14562;113.36024,23.1457;113.36015,23.14573;113.36015,23.14573;113.35987,23.14581;113.35969,23.14587;113.35818,23.1463;113.35818,23.1463;113.35777,23.14642;113.35777,23.14642;113.35766,23.14645;113.35766,23.14645;113.35762,23.14647;113.35762,23.14647;113.35736,23.14655;113.35736,23.14655;113.35685,23.14669;113.35685,23.14669;113.35657,23.14695;113.35642,23.14713;113.35642,23.14713;113.35637,23.14718;113.3562,23.14738;113.35586,23.14787;113.35582,23.14793;113.35572,23.14812;113.35572,23.14812;113.35557,23.14838;113.35554,23.14844;113.35554,23.14844;113.35545,23.14854;113.35533,23.14872;113.35533,23.14872;113.35529,23.14878;113.35529,23.14878;113.355,23.14912;113.35492,23.14923;113.35486,23.1493;113.35483,23.14936;113.3548,23.14942;113.3548,23.14942;113.35473,23.14964;113.35472,23.14973;113.35472,23.14973;113.35471,23.14981;113.35473,23.15003;113.35485,23.15044;113.35509,23.1512;113.35517,23.15145;113.35518,23.15151;113.35518,23.15157;113.35518,23.15157;113.35523,23.15169;113.35523,23.15169;113.35526,23.15178;113.35526,23.15178;113.35531,23.15192;113.35531,23.15192;113.35534,23.15199;113.35541,23.15216;113.35547,23.15233;113.35554,23.1525;113.35568,23.15287;113.35584,23.15323;113.35591,23.15342;113.35598,23.15358;113.35609,23.15379;113.35617,23.15394;113.35629,23.15421;113.35646,23.15457;113.35648,23.15461;113.35652,23.15471;113.35654,23.15475;113.35673,23.15515;113.35677,23.15524;113.35677,23.15524;113.35693,23.15556;113.35697,23.15564;113.35709,23.1559;113.35709,23.1559;113.35731,23.15636;113.35731,23.15636;113.35756,23.15669;113.35775,23.15697;113.3579,23.15725;113.35805,23.15752;113.35805,23.15752;113.35841,23.15824;113.35865,23.15872;113.3587,23.15889;113.3587,23.15889;113.35879,23.15912;113.35883,23.15927;113.35885,23.15938;113.35886,23.15948;113.35884,23.1596;113.35882,23.15978;113.35878,23.15994;113.35868,23.16016;113.35859,23.16034;113.35855,23.16041;113.35849,23.1605;113.35843,23.16062;113.35829,23.16086;</streetLatLon>
+            //
+            //            <streetDistance>3669.0</streetDistance>
+            //
+            //            <segmentNumber>3-6</segmentNumber>
+            //
+            //        </item>
+            //
+            //        <item id="3">
+            //
+            //            <strguide>娌块暱婀翠腑璺椹跺埌鐩殑鍦般��</strguide>
+            //
+            //            <streetNames>闀挎勾涓矾</streetNames>
+            //
+            //            <lastStreetName/>
+            //
+            //            <linkStreetName/>
+            //
+            //            <signage/>
+            //
+            //            <tollStatus>0</tollStatus>
+            //
+            //            <turnlatlon>113.34714,23.17047</turnlatlon>
+            //
+            //            <streetLatLon>113.34714,23.17047;113.34711,23.1703;113.34708,23.16988;113.34708,23.16988;113.34705,23.16957;</streetLatLon>
+            //
+            //            <streetDistance>101.0</streetDistance>
+            //
+            //            <segmentNumber>7-8</segmentNumber>
+            //
+            //        </item>
+            //
+            //    </simple>
+            //
+            //    <distance>7.48</distance>
+            //
+            //    <duration>548.0</duration>
+            //
+            //    <routelatlon>113.373308,23.136699;113.37323,23.13677;113.37272,23.13687;113.37265,23.13688;113.37227,23.13696;113.37209,23.13699;113.37201,23.13696;113.37185,23.13699;113.37185,23.13699;113.3714,23.13649;113.37126,23.13643;113.37116,23.13644;113.37107,23.13648;113.37107,23.13648;113.37091,23.13683;113.37075,23.13717;113.37057,23.13765;113.37054,23.13794;113.37055,23.13844;113.3706,23.13878;113.3708,23.13964;113.37083,23.13975;113.371,23.14051;113.37125,23.14153;113.37129,23.14167;113.37139,23.14206;113.37139,23.14206;113.37164,23.14249;113.37182,23.14265;113.37206,23.14271;113.37222,23.14267;113.37234,23.14261;113.3725,23.14237;113.37249,23.14215;113.37242,23.14198;113.37206,23.14169;113.37183,23.1416;113.37131,23.14151;113.37049,23.14178;113.36995,23.14197;113.36956,23.14203;113.36949,23.14205;113.3693,23.14213;113.3692,23.14218;113.3691,23.14223;113.36837,23.1425;113.36735,23.14293;113.36683,23.14314;113.36454,23.14409;113.3637,23.14444;113.36138,23.14532;113.36113,23.14541;113.36052,23.14562;113.35818,23.1463;113.35766,23.14645;113.35762,23.14647;113.35685,23.14669;113.35685,23.14669;113.35642,23.14713;113.35637,23.14718;113.35572,23.14812;113.35554,23.14844;113.35533,23.14872;113.35529,23.14878;113.35486,23.1493;113.3548,23.14942;113.35473,23.14964;113.35473,23.15003;113.35518,23.15151;113.35518,23.15157;113.35518,23.15157;113.35526,23.15178;113.35554,23.1525;113.35598,23.15358;113.35652,23.15471;113.35731,23.15636;113.35731,23.15636;113.35805,23.15752;113.3587,23.15889;113.35885,23.15938;113.35878,23.15994;113.35855,23.16041;113.35829,23.16086;113.35829,23.16086;113.35774,23.16199;113.35695,23.16368;113.35625,23.1651;113.35567,23.16616;113.35546,23.16638;113.35484,23.1669;113.3547,23.16697;113.35444,23.1671;113.35392,23.16726;113.35328,23.16732;113.35126,23.16726;113.35046,23.16736;113.34949,23.16765;113.34651,23.16884;113.34571,23.16921;113.34393,23.17017;113.34387,23.17021;113.34252,23.17092;113.34213,23.17112;113.34192,23.17139;113.34177,23.17169;113.34261,23.17145;113.34427,23.17102;113.34559,23.17069;113.34714,23.17047;113.34714,23.17047;113.34708,23.16988;113.34708,23.16988;113.34705,23.16957;113.3472,23.16957;</routelatlon>
+            //
+            //    <mapinfo>
+            //
+            //        <center>113.35754,23.15406</center>
+            //
+            //        <scale>10</scale>
+            //
+            //    </mapinfo>
+            //</result>
+            //瑙f瀽杩欎釜xml 鎷垮埌distance鍜宒uration
+            if(routeResponse!=null) {
+                org.dom4j.Document doc = DocumentHelper.parseText(routeResponse);
+
+                // 2. 鑾峰彇鏍硅妭鐐� <result>
+                Element rootElement = doc.getRootElement();
+
+                // 3. 鐩存帴鑾峰彇鏍硅妭鐐逛笅鐨� <distance> 瀛愯妭鐐规枃鏈��
+                String distance = rootElement.elementText("distance");
+
+                // 鍙�夛細杞负Double绫诲瀷锛堣嫢闇�鏁板�艰绠楋級
+                Double distanceValue = Double.parseDouble(distance);
+                Map<String, Double> resultMap = new HashMap<>();
+                resultMap.put("distance", distanceValue*1000);
+
+                // 4. 鐩存帴鑾峰彇鏍硅妭鐐逛笅鐨� <duration> 瀛愯妭鐐规枃鏈��
+                return AjaxResult.success("璁$畻鎴愬姛", resultMap);
             }
-            
-            // 鎻愬彇璺濈淇℃伅
-            com.alibaba.fastjson2.JSONObject result = routeJson.getJSONObject("result");
-            if (result == null) {
-                logger.error("璺緞瑙勫垝缁撴灉涓虹┖");
-                return AjaxResult.error("璺緞瑙勫垝澶辫触");
+            else{
+                return AjaxResult.error("璁$畻璺濈澶辫触锛氭棤杩斿洖缁撴灉");
             }
-            
-            com.alibaba.fastjson2.JSONArray routes = result.getJSONArray("routes");
-            if (routes == null || routes.isEmpty()) {
-                logger.error("鏈壘鍒拌矾绾夸俊鎭�");
-                return AjaxResult.error("鏈壘鍒拌矾绾夸俊鎭�");
-            }
-            
-            com.alibaba.fastjson2.JSONObject route = routes.getJSONObject(0);
-            double distance = route.getDoubleValue("distance"); // 璺濈锛屽崟浣嶏細绫�
-            double duration = route.getDoubleValue("duration"); // 鏃堕暱锛屽崟浣嶏細绉�
-            
-            logger.info("璁$畻鎴愬姛: 璺濈={}绫�, 鏃堕暱={}绉�", distance, duration);
-            
-            // 鏋勫缓杩斿洖缁撴灉
-            Map<String, Object> resultMap = new HashMap<>();
-            resultMap.put("distance", (int)distance); // 璺濈锛堢背锛�
-            resultMap.put("duration", (int)duration); // 鏃堕暱锛堢锛�
-            resultMap.put("distanceKm", String.format("%.1f", distance / 1000.0)); // 璺濈锛堝叕閲岋級
-            resultMap.put("durationMin", (int)(duration / 60)); // 鏃堕暱锛堝垎閽燂級
-            
-            // 璧风偣鍧愭爣
-            Map<String, Object> fromLocation = new HashMap<>();
-            fromLocation.put("lon", fromLon);
-            fromLocation.put("lat", fromLat);
-            resultMap.put("fromLocation", fromLocation);
-            
-            // 缁堢偣鍧愭爣
-            Map<String, Object> toLocation = new HashMap<>();
-            toLocation.put("lon", toLon);
-            toLocation.put("lat", toLat);
-            resultMap.put("toLocation", toLocation);
-            
-            return AjaxResult.success("璁$畻鎴愬姛", resultMap);
         } catch (Exception e) {
             logger.error("璁$畻鍦板潃璺濈澶辫触", e);
             return AjaxResult.error("璁$畻璺濈澶辫触锛�" + e.getMessage());
@@ -1099,29 +1339,26 @@
             // 鍙戦�丠TTP璇锋眰
             String response = HttpUtils.sendGet(url, params);
             logger.debug("澶╁湴鍥炬櫘閫氭悳绱㈠搷搴�: {}", response);
-            
-            // 瑙f瀽鍝嶅簲
-            com.alibaba.fastjson2.JSONObject jsonResponse = com.alibaba.fastjson2.JSONObject.parseObject(response);
-            if (!"0".equals(jsonResponse.getString("status"))) {
-                logger.error("鏅�氭悳绱㈠け璐�: {}", response);
+            // {"count":27,"resultType":1,"prompt":[{"type":4,"admins":[{"adminName":"骞垮窞甯�","adminCode":156440100}]}],
+            //"pois":[{"address":"骞夸笢鐪佸箍宸炲競澶╂渤鍖烘涓嬭閬撳瓙鍗堥澶╂渤妫犱笅搴�","phone":"","poiType":"101","name":"瀛愬崍棣�(澶╂渤妫犱笅搴�)","source":"0","hotPointID":"17163AD907B29F24","lonlat":"113.36952,23.134056"},{"address":"鍗氭眹琛�6鍙�","phone":"","poiType":"101","name":"澶╂渤妫犱笅路鏅烘眹park","source":"0","hotPointID":"C2635A7054C1EBB7","lonlat":"113.37003,23.14308"},{"address":"绉戞柊璺�143~147鍙�","phone":"020-88524715","poiType":"101","name":"閲嶅簡寰峰簞鐏攨(澶╂渤妫犱笅搴�)","source":"0","hotPointID":"6919E1CFA6F6EF20","lonlat":"113.37627,23.127416"},{"address":"鍗氭眹琛�6鍙�","phone":"020-87085713","poiType":"101","name":"澶╂渤妫犱笅路鏅烘眹PAPK鍋滆溅鍦�","source":"0","hotPointID":"4AC84F8E1CB34C4E","lonlat":"113.36925,23.14256"},{"address":"骞垮洯涓滆矾鍗氭眹琛�6鍙峰ぉ娌虫涓嬄锋櫤姹嘝APK鍦颁笅鍋滆溅鍦�","phone":"020-87085713","poiType":"101","name":"澶╂渤妫犱笅路鏅烘眹PAPK鐗规柉鎷夎秴绾у厖鐢电珯","source":"0","hotPointID":"70FC2D0A2D061E4B","lonlat":"113.3705,23.14359"},{"address":"妫犲痉鍗楄矾321","phone":"","poiType":"101","name":"绯栧洯澶╂渤妫犱笅搴�","source":"0","hotPointID":"B97F4B20719EEBD1","lonlat":"113.38009,23.13434"},{"address":"涓北澶ч亾妫犱笅璺笢闂稿ぇ琛楄嚜缂�98鍙�2鍙峰簵","phone":"13590139682","poiType":"101","name":"鑺辩敳鐜嬪ぉ娌虫涓嬪簵","source":"0","hotPointID":"174C40E7FBAE1187","lonlat":"113.37556,23.12844"},{"address":"妫犱笅浜岀ぞ娑岃竟璺�69鍙峰厜杈夊ぇ鍘�","phone":"020-66351119","poiType":"101","name":"绱㈢壒鏉ユ枃鑹洪厭搴楀ぉ娌虫涓嬪簵","source":"0","hotPointID":"362052A27B9A1AC8","lonlat":"113.37161,23.12794"},{"address":"涓北澶ч亾瑗�493鍙�","phone":"020-38288788","poiType":"101","name":"涓浗鐢典俊澶╂渤妫犱笅绂忓杽钀ヤ笟鍘�","source":"0","hotPointID":"D50C7774CFC6AA09","lonlat":"113.37455,23.12855"},{"address":"骞夸笢鐪佸箍宸炲競澶╂渤鍖烘涓嬭閬撴効杈捐瑷�鍩硅涓績澶╂渤妫犱笅鏍″尯","phone":"","poiType":"101","name":"鎰胯揪璇█鍩硅涓績澶╂渤妫犱笅鏍″尯","source":"0","hotPointID":"3CEE80F76558BDE4","lonlat":"113.373743,23.128796"}],"lineData":[],"status":{"cndesc":"鏈嶅姟姝e父","infocode":1000},"keyWord":"骞垮窞澶╂渤妫犱笅"}
+            com.alibaba.fastjson.JSONObject jsonResponse = com.alibaba.fastjson.JSONObject.parseObject(response);
+            JSONObject objStatus=jsonResponse.getJSONObject("status");
+            if (objStatus == null || objStatus.getInteger("infocode") != 1000) {
+                logger.error("澶╁湴鍥炬櫘閫氭悳绱㈠け璐�: {}", response);
                 return AjaxResult.error("鍦板潃鎼滅储澶辫触");
             }
-            
-            // 鎻愬彇鎼滅储缁撴灉
-            com.alibaba.fastjson2.JSONArray results = jsonResponse.getJSONArray("pois");
-            if (results == null || results.isEmpty()) {
-                logger.info("鏈壘鍒板尮閰嶇殑鍦板潃");
-                return AjaxResult.success("鏌ヨ鎴愬姛", new ArrayList<>());
-            }
+
+            JSONArray results = jsonResponse.getJSONArray("pois");
+
             
             // 鏋勫缓杩斿洖缁撴灉
             List<Map<String, Object>> suggestions = new ArrayList<>();
             for (int i = 0; i < results.size(); i++) {
-                com.alibaba.fastjson2.JSONObject item = results.getJSONObject(i);
+                JSONObject item = results.getJSONObject(i);
                 
                 Map<String, Object> suggestion = new HashMap<>();
                 suggestion.put("name", item.getString("name")); // 鍚嶇О
-                suggestion.put("address", item.getString("addr")); // 鍦板潃
+                suggestion.put("address", item.getString("address")); // 鍦板潃
                 suggestion.put("province", item.getString("prov")); // 鐪�
                 suggestion.put("city", item.getString("city")); // 甯�
                 suggestion.put("district", item.getString("county")); // 鍖哄幙
@@ -1130,11 +1367,12 @@
                 suggestion.put("type", item.getString("type")); // 绫诲瀷
                 
                 // 缁忕含搴︿俊鎭�
-                com.alibaba.fastjson2.JSONObject location = item.getJSONObject("lonlat");
+                String location = item.getString("lonlat");
                 if (location != null) {
                     Map<String, Object> locationMap = new HashMap<>();
-                    locationMap.put("lon", location.getDouble("lon"));
-                    locationMap.put("lat", location.getDouble("lat"));
+                    String[] locationArray = location.split(",");
+                    locationMap.put("lng",Double.parseDouble(locationArray[0]));
+                    locationMap.put("lat",Double.parseDouble(locationArray[1]));
                     suggestion.put("location", locationMap);
                 }
                 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
index 9d47562..cc7dd4d 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
@@ -199,7 +199,7 @@
     @PutMapping("/status/{id}")
     public AjaxResult updateStatus(@PathVariable("id") Long id, @RequestParam String status) {
         try {
-            int result = sysTaskVehicleService.updateTaskVehicleStatus(id, status);
+            int result = sysTaskVehicleService.updateSysTaskVehicleStatus(id, status);
             if (result > 0) {
                 return success("鐘舵�佹洿鏂版垚鍔�");
             } else {
@@ -211,6 +211,22 @@
     }
 
     /**
+     * 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
+     * 浼樺寲鎺ュ彛锛氬噺灏慔TTP璇锋眰娆℃暟
+     */
+    @PreAuthorize("@ss.hasPermi('task:vehicle:query')")
+    @PostMapping("/currentStatus")
+    public AjaxResult batchGetCurrentTaskStatus(@RequestBody List<Long> vehicleIds) {
+        try {
+            java.util.Map<Long, java.util.Map<String, Object>> statusMap = sysTaskVehicleService.batchGetVehicleCurrentTaskStatus(vehicleIds);
+            return success(statusMap);
+        } catch (Exception e) {
+            logger.error("鎵归噺鑾峰彇杞﹁締浠诲姟鐘舵�佸け璐�", e);
+            return error("鑾峰彇鐘舵�佸け璐ワ細" + e.getMessage());
+        }
+    }
+
+    /**
      * 鍒嗛厤杞﹁締璇锋眰瀵硅薄
      */
     public static class AssignVehicleRequest {
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java
index d5b8c99..82258c3 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java
@@ -2,12 +2,29 @@
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.config.WechatConfig;
 import com.ruoyi.common.utils.WechatUtils;
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.service.IWechatTaskNotifyService;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 寰俊鎺ュ彛Controller
@@ -20,6 +37,18 @@
     
     @Autowired
     private WechatConfig wechatConfig;
+
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private IWechatTaskNotifyService wechatTaskNotifyService;
     
     /**
      * 鑾峰彇寰俊AccessToken
@@ -39,4 +68,55 @@
             return error("鑾峰彇寰俊AccessToken寮傚父锛�" + e.getMessage());
         }
     }
+
+    /**
+     * 鑾峰彇寰俊閰嶇疆淇℃伅锛堝尶鍚嶈闂級
+     * 杩斿洖鍓嶇闇�瑕佺殑閰嶇疆淇℃伅锛屽璁㈤槄娑堟伅妯℃澘ID绛�
+     */
+    @Anonymous
+    @GetMapping("/config")
+    public AjaxResult getConfig() {
+        Map<String, String> config = new HashMap<>();
+        config.put("taskNotifyTemplateId", wechatConfig.getTaskNotifyTemplateId());
+        config.put("taskDetailPage", wechatConfig.getTaskDetailPage());
+        return success(config);
+    }
+
+    /**
+     * 鍖垮悕鎺ュ彛锛氭牴鎹换鍔D鎵嬪姩瑙﹀彂涓�娆′换鍔″井淇¢�氱煡
+     * 鏂逛究閫氳繃Postman璋冭瘯锛屽墠鎻愭槸浠诲姟宸叉湁鎵ц浜�/鍒涘缓浜哄苟缁戝畾浜唎penId
+     */
+    @Anonymous
+    @PostMapping("/task/notify")
+    public AjaxResult notifyTaskByWechat(@RequestParam("taskId") Long taskId) {
+        if (taskId == null) {
+            return error("浠诲姟ID涓嶈兘涓虹┖");
+        }
+
+        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+        if (task == null) {
+            return error("浠诲姟涓嶅瓨鍦�");
+        }
+
+        // 绠�鍖栵細缁欎换鍔″垱寤轰汉鍙戜竴鏉★紙濡傛灉缁戝畾浜唎penId锛夛紝鏂逛究蹇�熼獙璇佹ā鏉垮拰璺宠浆
+        if (task.getCreatorId() == null) {
+            return error("浠诲姟鏈寚瀹氬垱寤轰汉");
+        }
+
+        SysUser creator = sysUserMapper.selectUserById(task.getCreatorId());
+        if (creator == null || StringUtils.isEmpty(creator.getOpenId())) {
+            return error("鍒涘缓浜烘湭缁戝畾寰俊openId");
+        }
+
+        // 璋冪敤缁熶竴鐨勫井淇¢�氱煡鏈嶅姟
+        List<Long> userIds = new ArrayList<>();
+        userIds.add(task.getCreatorId());
+        int successCount = wechatTaskNotifyService.sendTaskNotifyMessage(taskId, userIds);
+
+        if (successCount == 0) {
+            return error("寰俊閫氱煡鍙戦�佸け璐�");
+        }
+
+        return success("宸茶Е鍙戝井淇¢�氱煡锛屾垚鍔熷彂閫佹潯鏁帮細" + successCount);
+    }
 }
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index e4c6e54..be0ae20 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -34,8 +34,8 @@
             maxWait: 60000
             # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
             connectTimeout: 30000
-            # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
-            socketTimeout: 60000
+            # 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛堝鍔犲埌5鍒嗛挓锛岄伩鍏嶅ぇ鏁版嵁閲忔煡璇㈣秴鏃讹級
+            socketTimeout: 300000
             # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
             timeBetweenEvictionRunsMillis: 60000
             # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml
index 464c528..cf4900c 100644
--- a/ruoyi-admin/src/main/resources/application-prod.yml
+++ b/ruoyi-admin/src/main/resources/application-prod.yml
@@ -34,8 +34,8 @@
       maxWait: 60000
       # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
       connectTimeout: 30000
-      # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
-      socketTimeout: 60000
+      # 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛堝鍔犲埌5鍒嗛挓锛岄伩鍏嶅ぇ鏁版嵁閲忔煡璇㈣秴鏃讹級
+      socketTimeout: 300000
       # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
       timeBetweenEvictionRunsMillis: 60000
       # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml
index b3184cc..94c03ac 100644
--- a/ruoyi-admin/src/main/resources/application-test.yml
+++ b/ruoyi-admin/src/main/resources/application-test.yml
@@ -34,8 +34,8 @@
             maxWait: 60000
             # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
             connectTimeout: 30000
-            # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
-            socketTimeout: 60000
+            # 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛堝鍔犲埌5鍒嗛挓锛岄伩鍏嶅ぇ鏁版嵁閲忔煡璇㈣秴鏃讹級
+            socketTimeout: 300000
             # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
             timeBetweenEvictionRunsMillis: 60000
             # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 121ba1d..21b8d9b 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -168,6 +168,11 @@
 transferConfigWeixin:
   appId: wx40692cc44953a8cb
   appSecret: 9638b7d8bb988e4daaac7ac35457f296
+  # 浠诲姟閫氱煡妯℃澘ID锛堜綘缁欑殑閭d釜妯″瀷ID锛�
+  taskNotifyTemplateId: 4mJGnvzjPpQednzNwVgghN5CZ_jSirZToisISOpLfMU
+  # 浠诲姟璇︽儏椤甸潰璺緞锛堢敤浜庢嫾鎺� ?id=taskId锛�
+  # 鍒嗗寘椤甸潰璺緞鏍煎紡锛氬垎鍖呮牴鐩綍/椤甸潰璺緞锛堜笉瑕佸墠瀵兼枩鏉狅級
+  taskDetailPage: pagesTask/detail
 # 鑵捐鍦板浘閰嶇疆
 tencent:
   map:
@@ -187,7 +192,7 @@
 # provider: 鍦板浘鏈嶅姟鎻愪緵鍟嗭紝鍙�夊�硷細baidu锛堢櫨搴﹀湴鍥撅級銆乼ianditu锛堝ぉ鍦板浘锛�
 map:
   service:
-    provider: baidu  # 榛樿浣跨敤鐧惧害鍦板浘
+    provider: tianditu  # 榛樿浣跨敤鐧惧害鍦板浘 tianditu /baidu
 
 # 鏀粯閰嶇疆
 payment:
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java
index fa094a8..8a1cee9 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java
@@ -16,7 +16,7 @@
      * 鍙�夊��: baidu, tianditu
      * 榛樿: baidu
      */
-    private String provider = "baidu";
+    private String provider = "tianditu";
 
     public String getProvider() {
         return provider;
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java
index b60bb7a..77f61e8 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java
@@ -19,6 +19,12 @@
     /** 寰俊灏忕▼搴廇ppSecret */
     private String appSecret;
 
+    /** 浠诲姟閫氱煡妯℃澘ID */
+    private String taskNotifyTemplateId;
+
+    /** 浠诲姟璇︽儏椤甸潰璺緞 */
+    private String taskDetailPage;
+
     public String getAppId() {
         return appId;
     }
@@ -34,4 +40,20 @@
     public void setAppSecret(String appSecret) {
         this.appSecret = appSecret;
     }
+
+    public String getTaskNotifyTemplateId() {
+        return taskNotifyTemplateId;
+    }
+
+    public void setTaskNotifyTemplateId(String taskNotifyTemplateId) {
+        this.taskNotifyTemplateId = taskNotifyTemplateId;
+    }
+
+    public String getTaskDetailPage() {
+        return taskDetailPage;
+    }
+
+    public void setTaskDetailPage(String taskDetailPage) {
+        this.taskDetailPage = taskDetailPage;
+    }
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
index fb2ae21..434d1e1 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -21,6 +21,7 @@
     public static String YYYY = "yyyy";
 
     public static String YYYY_MM = "yyyy-MM";
+    public static String YYYYMMDD="yyyyMMdd";
 
     public static String YYYY_MM_DD = "yyyy-MM-dd";
 
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PlateNumberExtractor.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PlateNumberExtractor.java
new file mode 100644
index 0000000..13352a8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PlateNumberExtractor.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.utils;
+
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PlateNumberExtractor {
+    // 鐪佷唤绠�绉版鍒欑墖娈�
+    private static final String PROVINCE_ABBRS = "浜瑋娲娌獆娓潀鍐�|鏅媩杈絴鍚墊榛憒鑻弢娴檤鐨東闂絴璧椴亅璞珅閯倈婀榺绮鐞紎宸潀璐祙浜憒闄晐鐢榺闈抾钂檤妗倈瀹亅鏂皘钘弢娓瘄婢硘鍙�";
+    // 杞︾墝鍙锋鍒欙細鐪佷唤绠�绉� + A-Z瀛楁瘝 + 5-6浣嶅瓧姣�/鏁板瓧锛堝惈鏂拌兘婧愯溅鐗岋級
+    private static final String PLATE_REGEX = "([" + PROVINCE_ABBRS + "][A-Z][A-Z0-9]{5,6})";
+    private static final Pattern PLATE_PATTERN = Pattern.compile(PLATE_REGEX);
+
+    /**
+     * 鎻愬彇瀛楃涓蹭腑鎵�鏈夌鍚堣鍒欑殑杞︾墝鍙�
+     * @param input 杈撳叆瀛楃涓�
+     * @return 杞︾墝鍙峰垪琛紙鏃犲尮閰嶅垯杩斿洖绌哄垪琛級
+     */
+    public static List<String> extractPlateNumbers(String input) {
+        List<String> plateNumbers = new ArrayList<>();
+        if (input == null || input.isEmpty()) {
+            return plateNumbers;
+        }
+
+        Matcher matcher = PLATE_PATTERN.matcher(input);
+        while (matcher.find()) {
+            System.out.println(matcher.group(1));
+            plateNumbers.add(matcher.group(1));
+        }
+        return plateNumbers;
+    }
+
+    public static String extractPlateNumber(String input) {
+
+
+        Matcher matcher = PLATE_PATTERN.matcher(input);
+        if (matcher.find()) {
+
+            return matcher.group(1);
+        }
+        return "";
+    }
+
+//    public static void main(String[] args) {
+//        String input = "xxx绮SX120锛屾祴璇曚含A88888锛屾勃B123456锛堟柊鑳芥簮锛�";
+//        String plates = extractPlateNumber(input);
+//        System.out.println("鎻愬彇鐨勮溅鐗屽彿锛�" + plates);
+//        // 杈撳嚭锛歔绮SX120, 浜珹88888, 娌狟123456]
+//    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java
index 53ff3a3..9a34103 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/WechatUtils.java
@@ -200,4 +200,87 @@
         }
         return userAgent.toLowerCase().contains("micromessenger");
     }
+
+    /**
+     * 鎴柇thing绫诲瀷瀛楁锛屽井淇¤闃呮秷鎭痶hing绫诲瀷鏈�闀�20涓瓧绗�
+     * 
+     * @param value 鍘熷瀛楃涓�
+     * @return 鎴柇鍚庣殑瀛楃涓诧紙鏈�闀�20瀛楃锛�
+     */
+    public static String truncateThingValue(String value) {
+        if (StringUtils.isEmpty(value)) {
+            return value;
+        }
+        
+        // 寰俊thing绫诲瀷鏈�闀�20涓瓧绗�
+        final int MAX_THING_LENGTH = 20;
+        
+        if (value.length() <= MAX_THING_LENGTH) {
+            return value;
+        }
+        
+        // 鎴柇骞舵坊鍔犵渷鐣ュ彿锛岀‘淇濇�婚暱搴︿笉瓒呰繃20
+        return value.substring(0, MAX_THING_LENGTH - 1) + "鈥�";
+    }
+
+    /**
+     * 鍙戦�佸皬绋嬪簭璁㈤槄娑堟伅
+     *
+     * @param accessToken 寰俊鎺ュ彛璋冪敤鍑瘉
+     * @param touser 鎺ユ敹浜簅penId
+     * @param templateId 妯℃澘ID
+     * @param page 灏忕▼搴忚烦杞〉闈�
+     * @param data 妯℃澘鏁版嵁锛宬ey涓哄瓧娈靛悕(濡倀hing1銆乼ime27)锛寁alue涓哄瓧娈靛��
+     * @return 寰俊杩斿洖缁撴灉JSON
+     */
+    public static JSONObject sendSubscribeMessage(String accessToken,
+                                                  String touser,
+                                                  String templateId,
+                                                  String page,
+                                                  Map<String, String> data) {
+        try {
+            if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(touser) || StringUtils.isEmpty(templateId)) {
+                log.error("鍙戦�佽闃呮秷鎭弬鏁颁笉瀹屾暣锛宎ccessToken={}, touser={}, templateId={}", accessToken, touser, templateId);
+                return null;
+            }
+
+            String url = WECHAT_API_BASE_URL_SERVER + "/cgi-bin/message/subscribe/send?access_token=" + accessToken;
+
+            Map<String, Object> body = new HashMap<>();
+            body.put("touser", touser);
+            body.put("template_id", templateId);
+            if (StringUtils.isNotEmpty(page)) {
+                body.put("page", page);
+            }
+             body.put("miniprogram_state", "formal");
+
+            Map<String, Object> dataNode = new HashMap<>();
+            if (data != null && !data.isEmpty()) {
+                for (Map.Entry<String, String> entry : data.entrySet()) {
+                    Map<String, String> valueNode = new HashMap<>();
+                    valueNode.put("value", entry.getValue());
+                    dataNode.put(entry.getKey(), valueNode);
+                }
+            }
+            body.put("data", dataNode);
+
+            String jsonBody = JSON.toJSONString(body);
+            String response = HttpUtils.sendPost(url, jsonBody);
+
+            JSONObject jsonObject = JSON.parseObject(response);
+            if (jsonObject == null) {
+                log.error("鍙戦�佽闃呮秷鎭繑鍥炰负绌�");
+                return null;
+            }
+            if (jsonObject.getIntValue("errcode") != 0) {
+                log.error("鍙戦�佽闃呮秷鎭け璐�: {}", jsonObject.toJSONString());
+            } else {
+                log.info("鍙戦�佽闃呮秷鎭垚鍔燂紝touser={}, templateId={}", touser, templateId);
+            }
+            return jsonObject;
+        } catch (Exception e) {
+            log.error("鍙戦�佽闃呮秷鎭紓甯�: {}", e.getMessage(), e);
+            return null;
+        }
+    }
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
index 492b569..3cc8d9f 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -108,7 +108,7 @@
             URLConnection connection = realUrl.openConnection();
             connection.setRequestProperty("accept", "*/*");
             connection.setRequestProperty("connection", "Keep-Alive");
-            connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
+//            connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
             connection.connect();
             in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
             String line;
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java
index b55780a..1694256 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java
@@ -6,6 +6,7 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
+import com.ruoyi.common.utils.PlateNumberExtractor;
 import com.ruoyi.system.domain.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -135,6 +136,7 @@
 
     //瀵硅溅鐗屽鐞嗙殑閫氱敤鏂规硶
     private String getPlateNo(String plateNo){
+
         if (StringUtils.isNotEmpty(plateNo)) {
                 // 浠庤溅杈嗗悕绉颁腑鎻愬彇杞︾墝鍙凤紙鍋囪鏍煎紡涓�"鈽呰溅鐗屽彿锛堝湴鍖猴級"锛�
             if(plateNo.contains("(")) {
@@ -143,7 +145,9 @@
                 plateNo = plateNo.replace("鈽�", "").replace("鈽�", "").split("锛�")[0];
             }
             }
-            return plateNo;
+        //xxx绮SX120
+        plateNo = plateNo.replaceAll("[^a-zA-Z0-9]", "");
+        return PlateNumberExtractor.extractPlateNumber(plateNo);
     }
 
     /**
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java
index 371896a..a317652 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java
@@ -2,7 +2,6 @@
 
 import java.util.Calendar;
 import java.util.Date;
-import javax.annotation.PostConstruct;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -25,42 +24,41 @@
     private ISysConfigService configService;
     
     /**
-     * 鏈嶅姟鍚姩鏃舵墽琛岃ˉ鍋胯绠�
-     * 妫�鏌ユ渶杩�7澶╁唴鏈澶勭悊鐨凣PS鍧愭爣骞惰繘琛岃ˉ鍋胯绠�
+     * 鎵цGPS鍒嗘閲岀▼琛ュ伩璁$畻
+     * 妫�鏌ユ渶杩慛澶╁唴鏈澶勭悊鐨凣PS鍧愭爣骞惰繘琛岃ˉ鍋胯绠�
+     * 寤鸿閰嶇疆涓烘瘡澶╂墽琛屼竴娆�,渚嬪鍑屾櫒2鐐�
      */
-    @PostConstruct
-    public void init() {
-        // 鍚姩鍚庡欢杩熸墽琛岋紝閬垮厤褰卞搷鏈嶅姟鍚姩閫熷害
-        new Thread(() -> {
-            try {
-                // 寤惰繜30绉掑惎鍔紝纭繚鎵�鏈夋湇鍔″凡灏辩华
-                Thread.sleep(30000);
-                
-                logger.info("========== 寮�濮嬫墽琛孏PS鍒嗘閲岀▼琛ュ伩璁$畻 ==========");
-                
-                // 鑾峰彇閰嶇疆鐨勫洖婧ぉ鏁帮紝榛樿7澶�
-                int lookbackDays = 7;
-                String lookbackConfig = configService.selectConfigByKey("gps.mileage.compensation.days");
-                if (lookbackConfig != null && !lookbackConfig.isEmpty()) {
-                    try {
-                        lookbackDays = Integer.parseInt(lookbackConfig);
-                    } catch (NumberFormatException e) {
-                        logger.warn("琛ュ伩鍥炴函澶╂暟閰嶇疆閿欒锛屼娇鐢ㄩ粯璁ゅ��7澶�");
-                    }
+    public void executeCompensationCalculation() {
+        executeCompensationCalculation("7");
+    }
+    
+    /**
+     * 鎵цGPS鍒嗘閲岀▼琛ュ伩璁$畻(甯﹀弬鏁�)
+     * 
+     * @param params 鍙傛暟瀛楃涓�,鏍煎紡:鍥炴函澶╂暟(濡�:7琛ㄧず鍥炴函7澶�)
+     */
+    public void executeCompensationCalculation(String params) {
+        try {
+            // 瑙f瀽鍙傛暟:鍥炴函澶╂暟
+            int lookbackDays = 7; // 榛樿7澶�
+            if (params != null && !params.trim().isEmpty()) {
+                try {
+                    lookbackDays = Integer.parseInt(params.trim());
+                } catch (NumberFormatException e) {
+                    logger.warn("鍙傛暟鏍煎紡閿欒,浣跨敤榛樿鍊�7澶�: {}", params);
                 }
-                
-                // 鎵ц琛ュ伩璁$畻
-                int successCount = segmentMileageService.compensateCalculation(lookbackDays);
-                
-                logger.info("========== GPS鍒嗘閲岀▼琛ュ伩璁$畻瀹屾垚 - 鎴愬姛澶勭悊 {} 杈嗚溅 ==========", successCount);
-                
-            } catch (InterruptedException e) {
-                logger.error("琛ュ伩璁$畻绾跨▼琚腑鏂�", e);
-                Thread.currentThread().interrupt();
-            } catch (Exception e) {
-                logger.error("GPS鍒嗘閲岀▼琛ュ伩璁$畻澶辫触", e);
             }
-        }, "GPS-Compensation-Thread").start();
+            
+            logger.info("========== 寮�濮嬫墽琛孏PS鍒嗘閲岀▼琛ュ伩璁$畻 - 鍥炴函{}澶� ==========", lookbackDays);
+            
+            // 鎵ц琛ュ伩璁$畻
+            int successCount = segmentMileageService.compensateCalculation(lookbackDays);
+            
+            logger.info("========== GPS鍒嗘閲岀▼琛ュ伩璁$畻瀹屾垚 - 鎴愬姛澶勭悊 {} 杈嗚溅 ==========", successCount);
+            
+        } catch (Exception e) {
+            logger.error("GPS鍒嗘閲岀▼琛ュ伩璁$畻澶辫触", e);
+        }
     }
 
     /**
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java
index e969f5f..6d80602 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java
@@ -1,5 +1,6 @@
 package com.ruoyi.quartz.task;
 
+import com.ruoyi.common.utils.PlateNumberExtractor;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -86,9 +87,13 @@
      */
     private String extractPlateNumber(String deviceName, String remark) {
         if (StringUtils.isNotEmpty(deviceName)) {
+            String plateNumber =PlateNumberExtractor.extractPlateNumber(deviceName);
+            if(StringUtils.isNotEmpty(plateNumber))return plateNumber;
             return deviceName;
         }
         if (StringUtils.isNotEmpty(remark)) {
+            String plateNumber =PlateNumberExtractor.extractPlateNumber(remark);
+            if(StringUtils.isNotEmpty(plateNumber))return plateNumber;
             return remark;
         }
         return null;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java b/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java
index 66c619a..25558f8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java
@@ -41,7 +41,7 @@
     @Primary
     public IMapService mapService() {
         String provider = mapServiceConfig.getProvider();
-        
+        logger.info("浣跨敤鐨勫湴鍥炬湇鍔¤繘琛屽湴鐞嗙紪鐮�:{}",provider);
         if ("tianditu".equalsIgnoreCase(provider)) {
             logger.info("浣跨敤澶╁湴鍥炬湇鍔¤繘琛屽湴鐞嗙紪鐮�");
             return tiandituMapService;
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 377d933..5e549d6 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
@@ -108,6 +108,10 @@
     @Excel(name = "閮ㄩ棬鍚嶇О")
     private String deptName;
 
+    /** 杞︾墝鍙�(鍒楄〃鏄剧ず绗竴杈嗚溅) */
+    @Excel(name = "杞︾墝鍙�")
+    private String vehicleNo;
+
     /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
     private String delFlag;
 
@@ -308,6 +312,14 @@
         return deptName;
     }
 
+    public void setVehicleNo(String vehicleNo) {
+        this.vehicleNo = vehicleNo;
+    }
+
+    public String getVehicleNo() {
+        return vehicleNo;
+    }
+
     public void setDelFlag(String delFlag) {
         this.delFlag = delFlag;
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
index d4522e8..4d960ad 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
@@ -132,6 +132,9 @@
     /** 鏄惁闇�瑕侀噸鏂板悓姝ワ細0-涓嶉渶瑕侊紝1-闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鎴栦汉鍛樺彉鏇达級 */
     private Integer needResync;
 
+    /** 鏃х郴缁烻erviceOrdNo锛堣浆杩愬崟缂栧彿锛� */
+    private String legacyServiceOrdNo;
+
 
 
     public Long getId() {
@@ -454,6 +457,14 @@
         this.needResync = needResync;
     }
 
+    public String getLegacyServiceOrdNo() {
+        return legacyServiceOrdNo;
+    }
+
+    public void setLegacyServiceOrdNo(String legacyServiceOrdNo) {
+        this.legacyServiceOrdNo = legacyServiceOrdNo;
+    }
+
     @Override
     public String toString() {
         return "SysTaskEmergency{" +
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
index d300330..6736fee 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
@@ -22,6 +22,9 @@
     /** 浠诲姟鐘舵�� */
     private String taskStatus;
 
+    /** 杞︾墝鍙� */
+    private String vehicleNo;
+
     /** 鍒涘缓浜篒D */
     private Long creatorId;
 
@@ -74,6 +77,14 @@
         this.taskStatus = taskStatus;
     }
 
+    public String getVehicleNo() {
+        return vehicleNo;
+    }
+
+    public void setVehicleNo(String vehicleNo) {
+        this.vehicleNo = vehicleNo;
+    }
+
     public Long getCreatorId() {
         return creatorId;
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
index 8a14ec2..87a04f4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
@@ -7,13 +7,21 @@
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysMessage;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
 import com.ruoyi.system.event.TaskCreatedEvent;
 import com.ruoyi.system.event.TaskAssignedEvent;
 import com.ruoyi.system.event.TaskStatusChangedEvent;
 import com.ruoyi.system.mapper.SysMessageMapper;
 import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.system.service.IWechatTaskNotifyService;
+
+import java.util.HashMap;
 
 /**
  * 浠诲姟娑堟伅鐩戝惉鍣�
@@ -32,6 +40,15 @@
     
     @Autowired
     private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+
+    @Autowired
+    private IWechatTaskNotifyService wechatTaskNotifyService;
 
     /**
      * 鐩戝惉浠诲姟鍒涘缓浜嬩欢
@@ -93,7 +110,7 @@
                 return;
             }
             
-            // 缁欐瘡涓墽琛屼汉鍙戦�佹秷鎭�
+            // 缁欐瘡涓墽琛屼汉鍙戦�佺珯鍐呮秷鎭�
             for (int i = 0; i < event.getAssigneeIds().size(); i++) {
                 Long assigneeId = event.getAssigneeIds().get(i);
                 
@@ -104,7 +121,7 @@
                     continue;
                 }
                 
-                // 鍒涘缓娑堟伅
+                // 鍒涘缓绔欏唴娑堟伅
                 SysMessage message = new SysMessage();
                 message.setMessageType("PUSH");
                 message.setMessageTitle("浠诲姟鎺ㄩ��");
@@ -123,6 +140,15 @@
                 sysMessageMapper.insertSysMessage(message);
                 log.info("浠诲姟鍒嗛厤娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛歿}锛屾帴鏀朵汉锛歿}", message.getMessageId(), assignee.getNickName());
             }
+
+            // 鍙戦�佸井淇¤闃呮秷鎭紙鎺掗櫎鍒涘缓浜猴級
+            try {
+                SysTask task = sysTaskMapper.selectSysTaskByTaskId(event.getTaskId());
+                Long creatorId = task != null ? task.getCreatorId() : null;
+                wechatTaskNotifyService.sendTaskNotifyMessage(event.getTaskId(), event.getAssigneeIds(), creatorId);
+            } catch (Exception e) {
+                log.error("澶勭悊浠诲姟鍒嗛厤浜嬩欢鏃跺彂閫佸井淇¤闃呮秷鎭け璐�", e);
+            }
             
         } catch (Exception e) {
             log.error("澶勭悊浠诲姟鍒嗛厤浜嬩欢澶辫触", e);
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 423fe75..4112657 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
@@ -25,7 +25,7 @@
      */
     List<Map<String, Object>> selectTransferOrders(@Param("startDate") String startDate);
     
-    /**
+    /**ServiceOrdNo
      * 鏍规嵁鏈嶅姟鍗旾D鍜岃皟搴﹀崟ID鏌ヨ杞繍鍗曟暟鎹�
      * 
      * @param serviceOrdID 鏈嶅姟鍗旾D
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java
index 4f7ba6b..da0f917 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleGpsMapper.java
@@ -64,11 +64,12 @@
                                                        @Param("endTime") Date endTime);
 
     /**
-     * 鏌ヨ鎵�鏈夋椿璺冭溅杈咺D鍒楄〃
+     * 鏌ヨ娲昏穬杞﹁締ID鍒楄〃
      * 
+     * @param startTime 璧峰鏃堕棿
      * @return 杞﹁締ID鍒楄〃
      */
-    public List<Long> selectActiveVehicleIds();
+    public List<Long> selectActiveVehicleIds(@Param("startTime") Date startTime);
     
     /**
      * 鏌ヨ鏈璁$畻鐨凣PS鍧愭爣锛堜笉鍦╰b_vehicle_gps_calculated琛ㄤ腑鐨勮褰曪級
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java
index 8866f86..b39b87c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java
@@ -18,4 +18,13 @@
      * @return GPS鍧愭爣锛屽寘鍚玪ng鍜宭at锛屽鏋滆幏鍙栧け璐ヨ繑鍥瀗ull
      */
     Map<String, Double> geocoding(String address, String city);
+
+    /**
+     * GPS鍧愭爣杞湴鍧�锛堥�嗗悜鍦扮悊缂栫爜锛�
+     *
+     * @param lng 缁忓害
+     * @param lat 绾害
+     * @return 鍦板潃锛屽鏋滆幏鍙栧け璐ヨ繑鍥瀗ull
+     */
+    String reverseGeocoding(double lng, double lat);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
index 7b3cab6..a4c900b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
@@ -55,7 +55,7 @@
      * @param updateTime 鏇存柊鏃堕棿
      * @return 缁撴灉
      */
-    public int insertTask(TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, Long userId,String userName, Long deptId, Date createTime, Date updateTime);
+    public int insertTask(TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, String serviceOrdNo, Long userId,String userName, Long deptId, Date createTime, Date updateTime);
 
     /**
      * 淇敼浠诲姟绠$悊
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
index 75ab50f..0e1ec8b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import java.util.List;
+import java.util.Map;
 import com.ruoyi.system.domain.SysTaskVehicle;
 
 /**
@@ -147,4 +148,21 @@
      * @return 缁撴灉
      */
     public int updateTaskVehicleStatus(Long id, String status);
+
+    /**
+     * 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
+     * 
+     * @param vehicleIds 杞﹁締ID鍒楄〃
+     * @return Map<杞﹁締ID, Map<"taskCode": 浠诲姟缂栧彿, "taskStatus": 浠诲姟鐘舵��>>
+     */
+    public Map<Long, Map<String, Object>> batchGetVehicleCurrentTaskStatus(List<Long> vehicleIds);
+
+    /**
+     * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵�侊紙鏂版柟娉曪級
+     * 
+     * @param id 鍏宠仈ID
+     * @param status 鏂扮姸鎬�
+     * @return 缁撴灉
+     */
+    public int updateSysTaskVehicleStatus(Long id, String status);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IWechatTaskNotifyService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IWechatTaskNotifyService.java
new file mode 100644
index 0000000..659be54
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IWechatTaskNotifyService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysTask;
+
+import java.util.List;
+
+/**
+ * 寰俊浠诲姟閫氱煡鏈嶅姟鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-11-30
+ */
+public interface IWechatTaskNotifyService {
+    
+    /**
+     * 鍙戦�佷换鍔¢�氱煡娑堟伅缁欐寚瀹氱敤鎴峰垪琛�
+     * 
+     * @param taskId 浠诲姟ID
+     * @param userIds 鎺ユ敹鐢ㄦ埛ID鍒楄〃
+     * @param excludeUserId 鎺掗櫎鐨勭敤鎴稩D锛堝彲閫夛紝濡傚垱寤轰汉锛�
+     * @return 鎴愬姛鍙戦�佺殑娑堟伅鏁伴噺
+     */
+    int sendTaskNotifyMessage(Long taskId, List<Long> userIds, Long excludeUserId);
+    
+    /**
+     * 鍙戦�佷换鍔¢�氱煡娑堟伅缁欐寚瀹氱敤鎴峰垪琛紙涓嶆帓闄や换浣曠敤鎴凤級
+     * 
+     * @param taskId 浠诲姟ID
+     * @param userIds 鎺ユ敹鐢ㄦ埛ID鍒楄〃
+     * @return 鎴愬姛鍙戦�佺殑娑堟伅鏁伴噺
+     */
+    int sendTaskNotifyMessage(Long taskId, List<Long> userIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java
index 63f2f31..01a593a 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java
@@ -101,7 +101,7 @@
                 .orElse(null);
             
             if (fee == null) {
-                log.error("鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曚笉瀛樺湪锛宖eeId: {}", feeId);
+                log.info("鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曚笉瀛樺湪锛宖eeId: {}", feeId);
                 return false;
             }
             
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java
index f44748a..e6c330e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java
@@ -82,4 +82,24 @@
             return null;
         }
     }
+
+    @Override
+    public String reverseGeocoding(double lng, double lat) {
+        //璋冪敤鐧惧害鍦板潃鍙嶅悜瑙f瀽鎺ュ彛
+        String url = "https://api.map.baidu.com/reverse_geocoding/v3/";
+        String params = "location=" + lat + "," + lng +
+                "&output=json" +
+                "&ak=" + baiduMapConfig.getAk();
+        String response = HttpUtils.sendGet(url, params);
+        //"{\"status\":0,\"result\":{\"location\":{\"lng\":113.25330399999999,\"lat\":23.04668300960378},\"formatted_address\":\"骞夸笢鐪佷經灞卞競鍗楁捣鍖烘鍩庤閬揬",\"edz\":{\"name\":\"\"},\"business\":\"\",\"business_info\":[],\"addressComponent\":{\"country\":\"涓浗\",\"country_code\":0,\"region_code_iso\":\"CHN\",\"country_code_iso\":\"CHN\",\"country_code_iso2\":\"CN\",\"province\":\"骞夸笢鐪乗",\"city\":\"浣涘北甯俓",\"city_level\":2,\"district\":\"鍗楁捣鍖篭",\"town\":\"妗傚煄琛楅亾\",\"town_code\":\"440605011\",\"distance\":\"\",\"direction\":\"\",\"adcode\":\"440605\",\"street\":\"\",\"street_number\":\"\"},\"pois\":[],\"roads\":[],\"poiRegions\":[],\"sematic_description\":\"\",\"formatted_address_poi\":\"\",\"cityCode\":138}}"
+        JSONObject jsonObject = JSONObject.parseObject(response);
+        if (jsonObject.getInteger("status") != 0) {
+            logger.warn("鐧惧害鍦板浘鍦板潃鍙嶅悜瑙f瀽澶辫触: lng={}, lat={}, status={}, message={}",
+                    lng, lat, jsonObject.getInteger("status"), jsonObject.getString("message"));
+            return null;
+        }
+        String address = jsonObject.getJSONObject("result").getString("formatted_address");
+        logger.info("鐧惧害鍦板浘鍦板潃鍙嶅悜瑙f瀽鎴愬姛: lng={}, lat={}, address={}", lng, lat, address);
+        return address;
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsCollectServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsCollectServiceImpl.java
index a936fc2..541ea56 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsCollectServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/GpsCollectServiceImpl.java
@@ -1,5 +1,6 @@
 package com.ruoyi.system.service.impl;
 
+import com.ruoyi.common.utils.PlateNumberExtractor;
 import com.ruoyi.common.utils.http.HttpUtils;
 import com.ruoyi.system.domain.*;
 import com.ruoyi.system.service.IGpsCollectService;
@@ -258,10 +259,21 @@
     private String extractPlateNumber(String deviceName, String remark) {
         // 杩欓噷鍙互鏍规嵁瀹為檯鎯呭喌瀹炵幇杞︾墝鍙锋彁鍙栭�昏緫
         // 渚嬪锛氫粠瀛楃涓蹭腑鍖归厤杞︾墝鍙锋牸寮�
+        //aaxx绮SX120
+        //鍦ㄨ繖閲屾彁鍙� 绮SX120
+
         if (StringUtils.isNotEmpty(deviceName)) {
+            String plateNo =PlateNumberExtractor.extractPlateNumber(deviceName);
+            if (plateNo != null) {
+                return plateNo;
+            }
             return deviceName;
         }
         if (StringUtils.isNotEmpty(remark)) {
+            String plateNo =PlateNumberExtractor.extractPlateNumber(remark);
+            if (plateNo != null) {
+                return plateNo;
+            }
             return remark;
         }
         return null;
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 abc7e5c..be0888b 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
@@ -18,6 +18,8 @@
 import com.ruoyi.system.mapper.LegacyTransferSyncMapper;
 import com.ruoyi.system.mapper.VehicleInfoMapper;
 import com.ruoyi.system.service.ISysUserService;
+import com.ruoyi.system.service.IWechatTaskNotifyService;
+import org.apache.poi.ss.usermodel.DateUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +31,7 @@
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 /**
  * 鏃х郴缁熻浆杩愬崟鍚屾Service涓氬姟灞傚鐞�
@@ -61,6 +64,9 @@
 
     @Autowired
     private ISysUserService sysUserService;
+
+    @Autowired
+    private IWechatTaskNotifyService wechatTaskNotifyService;
     
     /**
      * 鍚屾鎸囧畾鏃ユ湡鑼冨洿鐨勬棫绯荤粺杞繍鍗曞埌鏂扮郴缁�
@@ -199,11 +205,11 @@
      */
     private boolean syncSingleTransferOrder(String serviceOrdID, String dispatchOrdID, Map<String, Object> order) {
         log.info("寮�濮嬪悓姝ュ崟涓浆杩愬崟: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
-        
+        String sysTaskCode="";
         try {
             // 鏋勯�燭askCreateVO瀵硅薄
             TaskCreateVO createTaskVo = buildCreateTaskVo(serviceOrdID, dispatchOrdID, order);
-            
+            sysTaskCode = createTaskVo.getTaskCode();
             if (createTaskVo == null) {
                 log.error("鏋勯�燭askCreateVO澶辫触: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
                 return false;
@@ -215,10 +221,13 @@
                      createTaskVo.getPatient() != null ? createTaskVo.getPatient().getName() : "鏈煡",
                      createTaskVo.getHospitalOut() != null ? createTaskVo.getHospitalOut().getName() : "鏈煡",
                      createTaskVo.getHospitalIn() != null ? createTaskVo.getHospitalIn().getName() : "鏈煡");
-
+            /**
+             * 寮�鍗曟椂闂�
+             */
             Date ServiceOrd_CC_Time= getDateValue(order, "ServiceOrd_CC_Time");
             // 璋冪敤sysTaskService鍒涘缓浠诲姟
             String serviceOrdClass = getStringValue(order,"ServiceOrdClass");
+            String serviceOrdNo = getStringValue(order,"ServiceOrdNo");
 
             Integer oauserId=getIntegerValue(order,"ServiceOrd_NS_ID");
             SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId);
@@ -227,10 +236,17 @@
             SysDept dept=sysDeptService.selectDeptByServiceClass(serviceOrdClass);
             Long deptId=dept==null?null:dept.getDeptId();
 
-            int result = sysTaskService.insertTask(createTaskVo,serviceOrdID,dispatchOrdID, taskCreatorId,createUserName, deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time);
+            int result = sysTaskService.insertTask(createTaskVo,serviceOrdID,dispatchOrdID, serviceOrdNo, taskCreatorId,createUserName, deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time);
 
             if (result > 0) {
                 log.info("杞繍鍗曞悓姝ユ垚鍔�: ServiceOrdID={}, DispatchOrdID={}, 鍒涘缓鐨勪换鍔D={}", serviceOrdID, dispatchOrdID, result);
+
+                try {
+                    notifyTransferOrderByWechat((long) result, serviceOrdID, dispatchOrdID, serviceOrdNo, ServiceOrd_CC_Time, dept, order);
+                } catch (Exception e) {
+                    log.error("杞繍鍗曞悓姝ユ垚鍔熷悗鍙戦�佸井淇¢�氱煡澶辫触: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID, e);
+                }
+
                 return true;
             } else {
                 log.error("杞繍鍗曞悓姝ュけ璐�: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
@@ -238,7 +254,7 @@
             }
             
         } catch (Exception e) {
-            log.error("鍚屾鍗曚釜杞繍鍗曞紓甯�: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID, e);
+            log.error("鍚屾鍗曚釜杞繍鍗曞紓甯�: ServiceOrdID={}, DispatchOrdID={},sysTaskCode:{}", serviceOrdID, dispatchOrdID,sysTaskCode, e);
             return false;
         }
     }
@@ -288,7 +304,16 @@
             return false;
         }
     }
-    
+
+    private String getServiceOrdCode(Date ServiceOrd_CC_Time,String serviceOrdClass,String serviceOrdNo){
+        //BF20251101-serviceOrdNo;
+        //灏� ServiceOrd_CC_Time 杞负 yyyyMMdd 鏍煎紡
+        String ServiceOrd_CC_Time_Str= DateUtils.parseDateToStr(DateUtils.YYYYMMDD,ServiceOrd_CC_Time);
+        //serviceOrdNo 杩欎釜鏄暟瀛楋紝鍥哄畾3浣嶆暟 锛屽皢32锛岃浆鎴�032锛涘皢1杞垚001
+        Integer intServiceNo=Integer.valueOf(serviceOrdNo);
+        String ServiceOrdNo_Str=String.format("%03d", intServiceNo);
+        return serviceOrdClass+ServiceOrd_CC_Time_Str+"-"+ServiceOrdNo_Str;
+    }
     /**
      * 鏋勯�燭askCreateVO瀵硅薄鐢ㄤ簬鍒涘缓浠诲姟
      * 
@@ -312,18 +337,17 @@
                 log.error("鏈嶅姟鍗旾D涓嶈兘涓虹┖");
                 return null;
             }
-            
+            String serviceOrdClass = getStringValue(order, "ServiceOrdClass");
+            //TODO
             TaskCreateVO createTaskVo = new TaskCreateVO();
-            String Old_ServiceOrdID_TXT=getStringValue(order,"Old_ServiceOrdID_TXT");
-            if(Old_ServiceOrdID_TXT!=null){
-                createTaskVo.setTaskCode(Old_ServiceOrdID_TXT);
-            }
-            
+            String serviceOrdCode=this.getServiceOrdCode(getDateValue(order, "ServiceOrd_CC_Time"),serviceOrdClass,getStringValue(order, "ServiceOrdNo"));
+            createTaskVo.setTaskCode(serviceOrdCode);
+            log.info("鏋勯�燭askCreateVO: ServiceOrdID={}, DispatchOrdID={},taskCode:{}", serviceOrdID, dispatchOrdID,serviceOrdCode);
             // 璁剧疆鍩烘湰淇℃伅
             createTaskVo.setTaskType("EMERGENCY_TRANSFER"); // 鎬ユ晳杞繍浠诲姟
             
             // 璁剧疆鍗曟嵁绫诲瀷鍜屼换鍔$被鍨婭D锛堜粠鏃х郴缁熷瓧娈垫槧灏勶級
-            String serviceOrdClass = getStringValue(order, "ServiceOrdClass");
+
             if (StringUtils.isNotEmpty(serviceOrdClass)) {
                 createTaskVo.setDocumentTypeId(serviceOrdClass);
             }
@@ -526,7 +550,7 @@
 
 
             
-            // 璁剧疆鍒涘缓鏃堕棿
+            // 璁剧疆鍒涘缓鏃堕棿 寮�鍗曟棩鏈�
             Date createTime = getDateValue(order, "ServiceOrd_CC_Time");
             if (createTime != null) {
                 createTaskVo.setCreateTime(createTime);
@@ -767,4 +791,72 @@
             return false;
         }
     }
-}
\ No newline at end of file
+
+    private void notifyTransferOrderByWechat(Long taskId,
+                                             String serviceOrdID,
+                                             String dispatchOrdID,
+                                             String serviceOrdNo,
+                                             Date serviceOrdCcTime,
+                                             SysDept dept,
+                                             Map<String, Object> order) {
+        try {
+            // 鑾峰彇閫氱煡鎺ユ敹浜哄垪琛�
+            List<SysUser> receivers = getWechatNotifyUsers(dispatchOrdID, dept);
+            if (receivers == null || receivers.isEmpty()) {
+                log.info("鏃х郴缁熷悓姝ヨ浆杩愬崟鏃犲彲鐢ㄥ井淇℃帴鏀朵汉锛宼askId={}", taskId);
+                return;
+            }
+
+            // 鎻愬彇鎺ユ敹浜� ID 鍒楄〃
+            List<Long> userIds = new ArrayList<>();
+            for (SysUser user : receivers) {
+                if (user != null && user.getUserId() != null) {
+                    userIds.add(user.getUserId());
+                }
+            }
+
+            // 璋冪敤缁熶竴鐨勫井淇¢�氱煡鏈嶅姟
+            int successCount = wechatTaskNotifyService.sendTaskNotifyMessage(taskId, userIds);
+            log.info("鏃х郴缁熷悓姝ヨ浆杩愬崟寰俊閫氱煡鍙戦�佸畬鎴愶紝taskId={}, 鎴愬姛={}", taskId, successCount);
+        } catch (Exception e) {
+            log.error("notifyTransferOrderByWechat鍙戠敓寮傚父, serviceOrdID={}, dispatchOrdID={}", serviceOrdID, dispatchOrdID, e);
+        }
+    }
+
+    private List<SysUser> getWechatNotifyUsers(String dispatchOrdID, SysDept dept) {
+        try {
+            List<SysUser> result = new ArrayList<>();
+
+            List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID);
+            if (assignees != null && !assignees.isEmpty()) {
+                for (TaskCreateVO.AssigneeInfo assigneeInfo : assignees) {
+                    if (assigneeInfo == null || assigneeInfo.getUserId() == null) {
+                        continue;
+                    }
+                    SysUser user = sysUserService.selectUserById(assigneeInfo.getUserId());
+                    if (user != null && StringUtils.isNotEmpty(user.getOpenId())) {
+                        result.add(user);
+                    }
+                }
+            }
+
+            if (!result.isEmpty()) {
+                return result;
+            }
+
+            if (dept == null || StringUtils.isEmpty(dept.getPhone())) {
+                return result;
+            }
+
+            SysUser leader = sysUserService.selectUserByPhonenumber(dept.getPhone());
+            if (leader != null && StringUtils.isNotEmpty(leader.getOpenId())) {
+                result.add(leader);
+            }
+
+            return result;
+        } catch (Exception e) {
+            log.error("鑾峰彇鏃х郴缁熷悓姝ヨ浆杩愬崟寰俊閫氱煡鎺ユ敹浜哄け璐�, dispatchOrdID={}", dispatchOrdID, e);
+            return new ArrayList<>();
+        }
+    }
+}
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 ccff010..afde674 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
@@ -277,7 +277,7 @@
         
         // 淇濆瓨鎬ユ晳杞繍鎵╁睍淇℃伅
         if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType())) {
-            saveEmergencyInfo(task.getTaskId(),username, createVO,null,null);
+            saveEmergencyInfo(task.getTaskId(),username, createVO,null,null,null);
         }
         
         // 淇濆瓨绂忕杞︽墿灞曚俊鎭�
@@ -351,7 +351,7 @@
      */
     @Override
     @Transactional
-    public int insertTask(TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, Long userId,String userName, Long deptId, Date createTime, Date updateTime) {
+    public int insertTask(TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, String serviceOrdNo, Long userId,String userName, Long deptId, Date createTime, Date updateTime) {
         SysTask task = new SysTask();
         if(createVO.getTaskCode()!=null){
             task.setTaskCode(createVO.getTaskCode());
@@ -490,7 +490,7 @@
         
         // 淇濆瓨鎬ユ晳杞繍鎵╁睍淇℃伅
         if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType())) {
-            saveEmergencyInfo(task.getTaskId(),userName, createVO, serviceOrderId, dispatchOrderId);
+            saveEmergencyInfo(task.getTaskId(),userName, createVO, serviceOrderId, dispatchOrderId, serviceOrdNo);
         }
         
         // 淇濆瓨绂忕杞︽墿灞曚俊鎭�
@@ -1649,7 +1649,7 @@
      * @param taskId 浠诲姟ID
      * @param createVO 浠诲姟鍒涘缓瀵硅薄
      */
-    private void saveEmergencyInfo(Long taskId,String createUserName, TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId) {
+    private void saveEmergencyInfo(Long taskId,String createUserName, TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, String serviceOrdNo) {
         SysTaskEmergency emergencyInfo = new SysTaskEmergency();
         emergencyInfo.setTaskId(taskId);
         
@@ -1755,6 +1755,9 @@
             emergencyInfo.setDispatchSyncTime(new Date());
             emergencyInfo.setDispatchSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
         }
+        if(serviceOrdNo!=null){
+            emergencyInfo.setLegacyServiceOrdNo(serviceOrdNo);
+        }
         // 绯荤粺瀛楁
         emergencyInfo.setCreateTime(DateUtils.getNowDate());
         emergencyInfo.setUpdateTime(DateUtils.getNowDate());
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 9cbaeb1..feab794 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
@@ -2,7 +2,9 @@
 
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -11,7 +13,9 @@
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.system.mapper.SysTaskVehicleMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
 import com.ruoyi.system.mapper.VehicleInfoMapper;
+import com.ruoyi.system.domain.SysTask;
 import com.ruoyi.system.domain.SysTaskVehicle;
 import com.ruoyi.system.domain.VehicleInfo;
 import com.ruoyi.system.service.ISysTaskVehicleService;
@@ -32,6 +36,9 @@
     
     @Autowired
     private VehicleInfoMapper vehicleInfoMapper;
+    
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
 
     /**
      * 鏌ヨ浠诲姟杞﹁締鍏宠仈
@@ -308,4 +315,63 @@
         taskVehicle.setUpdateTime(DateUtils.getNowDate());
         return sysTaskVehicleMapper.updateSysTaskVehicle(taskVehicle);
     }
+
+    /**
+     * 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
+     * 
+     * @param vehicleIds 杞﹁締ID鍒楄〃
+     * @return Map<杞﹁締ID, Map<"taskCode": 浠诲姟缂栧彿, "taskStatus": 浠诲姟鐘舵��>>
+     */
+    @Override
+    public Map<Long, Map<String, Object>> batchGetVehicleCurrentTaskStatus(List<Long> vehicleIds) {
+        Map<Long, Map<String, Object>> resultMap = new HashMap<>();
+        
+        if (vehicleIds == null || vehicleIds.isEmpty()) {
+            return resultMap;
+        }
+        
+        try {
+            // 瀵规瘡涓溅杈嗘煡璇㈠叾褰撳墠姝e湪杩涜鐨勪换鍔�
+            for (Long vehicleId : vehicleIds) {
+                if (vehicleId == null) {
+                    continue;
+                }
+                
+                // 鏌ヨ杞﹁締鐨勬椿璺冧换鍔★紙鏈畬鎴愩�佹湭鍙栨秷鐨勪换鍔★級
+                List<SysTask> activeTasks = sysTaskMapper.selectActiveTasksByVehicleId(vehicleId);
+                
+                if (activeTasks != null && !activeTasks.isEmpty()) {
+                    // 鍙栫涓�涓椿璺冧换鍔★紙鏈�鏂扮殑锛�
+                    SysTask currentTask = activeTasks.get(0);
+                    
+                    Map<String, Object> taskInfo = new HashMap<>();
+                    taskInfo.put("taskCode", currentTask.getTaskCode());
+                    taskInfo.put("taskStatus", currentTask.getTaskStatus());
+                    taskInfo.put("taskId", currentTask.getTaskId());
+                    
+                    resultMap.put(vehicleId, taskInfo);
+                } else {
+                    // 娌℃湁娲昏穬浠诲姟
+                    resultMap.put(vehicleId, null);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("鎵归噺鏌ヨ杞﹁締浠诲姟鐘舵�佸け璐�", e);
+        }
+        
+        return resultMap;
+    }
+
+    /**
+     * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵�侊紙鏂版柟娉曪級
+     * 
+     * @param id 鍏宠仈ID
+     * @param status 鏂扮姸鎬�
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional
+    public int updateSysTaskVehicleStatus(Long id, String status) {
+        return updateTaskVehicleStatus(id, status);
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
index 996bf70..a5c7675 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service.impl;
 
 import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.http.HttpUtils;
 import com.ruoyi.common.config.TiandituMapConfig;
 import com.ruoyi.system.service.IMapService;
@@ -62,14 +63,9 @@
                 return null;
             }
             
-            // 鎻愬彇鍧愭爣
-            JSONObject result = jsonObject.getJSONObject("result");
-            if (result == null) {
-                logger.warn("澶╁湴鍥惧湴鐞嗙紪鐮佸搷搴旀棤result: address={}", address);
-                return null;
-            }
+
             
-            JSONObject location = result.getJSONObject("location");
+            JSONObject location = jsonObject.getJSONObject("location");
             if (location == null) {
                 logger.warn("澶╁湴鍥惧湴鐞嗙紪鐮佸搷搴旀棤location: address={}", address);
                 return null;
@@ -91,4 +87,39 @@
             return null;
         }
     }
+
+    /**
+     * 鐩存帴杩斿洖鍦板潃
+     * @param lng 缁忓害
+     * @param lat 绾害
+     * @return
+     */
+    @Override
+    public String reverseGeocoding(double lng, double lat) {
+        // 鏋勫缓澶╁湴鍥鹃�嗗湴鐞嗙紪鐮丄PI URL
+        String url = "http://api.tianditu.gov.cn/geocoder";
+        String params = "postStr={\"lon\":" + lng + ",\"lat\":" + lat + ",\"ver\":1}" +
+                "&type=geocode" +
+                "&tk=" + tiandituMapConfig.getTk();
+
+        logger.info("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佽姹�: lon={}, lat={}", lng, lat);
+
+        // 鍙戦�丠TTP璇锋眰
+        String response = HttpUtils.sendGet(url, params);
+
+        // "{\"msg\":\"ok\",\"location\":{\"score\":100,\"level\":\"闂ㄥ潃\",\"lon\":\"116.290158\",\"lat\":\"39.894696\",\"keyWord\":\"鍖椾含甯傛捣娣�鍖鸿幉鑺辨睜瑗胯矾28鍙穃"},\"searchVersion\":\"7.4.3V\",\"status\":\"0\"}"
+        logger.info("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佸搷搴�: {}", response);
+        com.alibaba.fastjson.JSONObject obj= com.alibaba.fastjson.JSONObject.parseObject(response);
+        if (obj.getInteger("status") !=0) {
+            logger.error("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佸け璐�: {}", response);
+            return null;
+        }
+        com.alibaba.fastjson.JSONObject location = obj.getJSONObject("result");
+        if (location == null) {
+            logger.error("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佸搷搴旀棤location: {}", response);
+            return null;
+        }
+        return location.getString("formatted_address");
+
+    }
 }
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 08beb40..fbeede2 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
@@ -96,33 +96,55 @@
     @Override
     public int batchCalculateSegmentMileage(Date startTime, Date endTime) {
         try {
-            // 鏌ヨ鎵�鏈夋椿璺冭溅杈�
-            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
+            logger.info("寮�濮嬫壒閲忚绠桮PS鍒嗘閲岀▼ - 鏃堕棿鑼冨洿: {} 鍒� {}", startTime, endTime);
+            
+            // 鏌ヨ鍦ㄦ寚瀹氭椂闂磋寖鍥村唴鏈塆PS鏁版嵁鐨勬墍鏈夎溅杈�
+            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
             
             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);
         }
     }
 
@@ -138,7 +160,7 @@
             logger.info("寮�濮嬭ˉ鍋胯绠� - 鍥炴函澶╂暟: {}, 鏃堕棿鑼冨洿: {} 鍒� {}", lookbackDays, startTime, endTime);
             
             // 鏌ヨ鎵�鏈夋椿璺冭溅杈�
-            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
+            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
             
             if (vehicleIds == null || vehicleIds.isEmpty()) {
                 logger.info("娌℃湁鎵惧埌娲昏穬杞﹁締");
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
index 1cda18e..e61b9f6 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
@@ -181,8 +181,14 @@
     @Override
     public int batchCalculateMileageStats(Date statDate) {
         try {
+            // 璁$畻鏌ヨ寮�濮嬫椂闂达紙7澶╁墠锛�
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(statDate);
+            calendar.add(Calendar.DAY_OF_MONTH, -7);
+            Date startTime = calendar.getTime();
+            
             // 鏌ヨ鎵�鏈夋椿璺冭溅杈�
-            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
+            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
             
             if (vehicleIds == null || vehicleIds.isEmpty()) {
                 logger.info("娌℃湁鎵惧埌娲昏穬杞﹁締");
@@ -485,8 +491,14 @@
     @Override
     public int batchAggregateFromSegmentMileage(Date statDate) {
         try {
+            // 璁$畻鏌ヨ寮�濮嬫椂闂达紙7澶╁墠锛�
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(statDate);
+            calendar.add(Calendar.DAY_OF_MONTH, -7);
+            Date startTime = calendar.getTime();
+            
             // 鏌ヨ鎵�鏈夋椿璺冭溅杈�
-            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds();
+            List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
             
             if (vehicleIds == null || vehicleIds.isEmpty()) {
                 logger.info("娌℃湁鎵惧埌娲昏穬杞﹁締");
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/WechatTaskNotifyServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/WechatTaskNotifyServiceImpl.java
new file mode 100644
index 0000000..48833d3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/WechatTaskNotifyServiceImpl.java
@@ -0,0 +1,169 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.config.WechatConfig;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.WechatUtils;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.service.IWechatTaskNotifyService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 寰俊浠诲姟閫氱煡鏈嶅姟瀹炵幇
+ * 缁熶竴绠$悊鎵�鏈変换鍔$浉鍏崇殑寰俊璁㈤槄娑堟伅鍙戦�侀�昏緫
+ * 
+ * @author ruoyi
+ * @date 2025-11-30
+ */
+@Service
+public class WechatTaskNotifyServiceImpl implements IWechatTaskNotifyService {
+    
+    private static final Logger log = LoggerFactory.getLogger(WechatTaskNotifyServiceImpl.class);
+    
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+    
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+    
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    
+    @Autowired
+    private WechatConfig wechatConfig;
+    
+    /**
+     * 鍙戦�佷换鍔¢�氱煡娑堟伅缁欐寚瀹氱敤鎴峰垪琛�
+     * 
+     * @param taskId 浠诲姟ID
+     * @param userIds 鎺ユ敹鐢ㄦ埛ID鍒楄〃
+     * @param excludeUserId 鎺掗櫎鐨勭敤鎴稩D锛堝彲閫夛紝濡傚垱寤轰汉锛�
+     * @return 鎴愬姛鍙戦�佺殑娑堟伅鏁伴噺
+     */
+    @Override
+    public int sendTaskNotifyMessage(Long taskId, List<Long> userIds, Long excludeUserId) {
+        if (taskId == null || userIds == null || userIds.isEmpty()) {
+            log.warn("鍙戦�佸井淇′换鍔¢�氱煡鍙傛暟涓嶅畬鏁达紝taskId={}, userIds={}", taskId, userIds);
+            return 0;
+        }
+        
+        // 鏌ヨ浠诲姟淇℃伅
+        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+        if (task == null) {
+            log.warn("寰俊閫氱煡澶辫触锛屼换鍔′笉瀛樺湪锛宼askId={}", taskId);
+            return 0;
+        }
+        
+        // 鏌ヨ鎬ユ晳淇℃伅
+        SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+        
+        // 鑾峰彇寰俊AccessToken
+        String accessToken = WechatUtils.getAccessToken(wechatConfig.getAppId(), wechatConfig.getAppSecret());
+        if (StringUtils.isEmpty(accessToken)) {
+            log.error("鑾峰彇寰俊AccessToken澶辫触锛屾棤娉曞彂閫佷换鍔¢�氱煡");
+            return 0;
+        }
+        
+        // 鏋勯�犳秷鎭暟鎹�
+        Map<String, String> data = buildTaskNotifyData(task, emergency);
+        
+        // 鑾峰彇妯℃澘閰嶇疆
+        String page = wechatConfig.getTaskDetailPage() + "?id=" + taskId;
+        String templateId = wechatConfig.getTaskNotifyTemplateId();
+        
+        // 鍙戦�佹秷鎭粰姣忎釜鐢ㄦ埛
+        int successCount = 0;
+        for (Long userId : userIds) {
+            // 鎺掗櫎鎸囧畾鐢ㄦ埛
+            if (excludeUserId != null && excludeUserId.equals(userId)) {
+                log.debug("璺宠繃鎺掗櫎鐢ㄦ埛锛寀serId={}", userId);
+                continue;
+            }
+            
+            // 鏌ヨ鐢ㄦ埛淇℃伅
+            SysUser user = sysUserMapper.selectUserById(userId);
+            if (user == null || StringUtils.isEmpty(user.getOpenId())) {
+                log.debug("鐢ㄦ埛鏈粦瀹氬井淇penId锛岃烦杩囧彂閫侊紝userId={}", userId);
+                continue;
+            }
+            
+            // 鍙戦�佽闃呮秷鎭�
+            try {
+                WechatUtils.sendSubscribeMessage(accessToken, user.getOpenId(), templateId, page, data);
+                successCount++;
+                log.info("寰俊浠诲姟閫氱煡鍙戦�佹垚鍔燂紝taskId={}, userId={}, userName={}", taskId, userId, user.getUserName());
+            } catch (Exception e) {
+                log.error("寰俊浠诲姟閫氱煡鍙戦�佸け璐ワ紝taskId={}, userId={}", taskId, userId, e);
+            }
+        }
+        
+        log.info("寰俊浠诲姟閫氱煡鎵归噺鍙戦�佸畬鎴愶紝taskId={}, 鎬绘暟={}, 鎴愬姛={}", taskId, userIds.size(), successCount);
+        return successCount;
+    }
+    
+    /**
+     * 鍙戦�佷换鍔¢�氱煡娑堟伅缁欐寚瀹氱敤鎴峰垪琛紙涓嶆帓闄や换浣曠敤鎴凤級
+     * 
+     * @param taskId 浠诲姟ID
+     * @param userIds 鎺ユ敹鐢ㄦ埛ID鍒楄〃
+     * @return 鎴愬姛鍙戦�佺殑娑堟伅鏁伴噺
+     */
+    @Override
+    public int sendTaskNotifyMessage(Long taskId, List<Long> userIds) {
+        return sendTaskNotifyMessage(taskId, userIds, null);
+    }
+    
+    /**
+     * 鏋勯�犱换鍔¢�氱煡鐨勬秷鎭暟鎹�
+     * 
+     * @param task 浠诲姟淇℃伅
+     * @param emergency 鎬ユ晳淇℃伅锛堝彲閫夛級
+     * @return 娑堟伅鏁版嵁Map
+     */
+    private Map<String, String> buildTaskNotifyData(SysTask task, SysTaskEmergency emergency) {
+        // 浜嬮」鎻忚堪
+        String problemDesc = "鎮ㄦ湁鏂扮殑杞繍浠诲姟锛岃鍙婃椂澶勭悊";
+        
+        // 鍦扮偣淇℃伅
+        String location;
+        if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalOutName()) && StringUtils.isNotEmpty(emergency.getHospitalInName())) {
+            location = emergency.getHospitalOutName() + " 鈫� " + emergency.getHospitalInName();
+        } else if (StringUtils.isNotEmpty(task.getDepartureAddress()) && StringUtils.isNotEmpty(task.getDestinationAddress())) {
+            location = task.getDepartureAddress() + " 鈫� " + task.getDestinationAddress();
+        } else {
+            location = "鏈煡鍦扮偣";
+        }
+        
+        // 鏃堕棿淇℃伅
+        String startTimeStr;
+        if (task.getPlannedStartTime() != null) {
+            startTimeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", task.getPlannedStartTime());
+        } else {
+            startTimeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", new java.util.Date());
+        }
+        
+        // 杩愬崟鍙�
+        String waybillNo = StringUtils.isNotEmpty(task.getTaskCode()) ? task.getTaskCode() : String.valueOf(task.getTaskId());
+        
+        // 缁勮鏁版嵁锛堝簲鐢╰hing绫诲瀷瀛楁鐨勯暱搴﹂檺鍒讹級
+        Map<String, String> data = new HashMap<>();
+        // data.put("thing1", WechatUtils.truncateThingValue(problemDesc));  // 鎴柇thing绫诲瀷瀛楁
+        // data.put("thing10", WechatUtils.truncateThingValue(location));  // 鎴柇thing绫诲瀷瀛楁
+        data.put("time8", startTimeStr);
+        data.put("character_string1", waybillNo);
+        
+        return data;
+    }
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml b/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
index 7905aa7..f3aad10 100644
--- a/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
@@ -10,6 +10,7 @@
         <result property="ServiceOrdUserID" column="ServiceOrdUserID" />
         <result property="ServiceOrdAreaType" column="ServiceOrdAreaType" />
         <result property="ServiceOrdType" column="ServiceOrdType" />
+        <result property="ServiceOrdNo" column="ServiceOrdNo" />
         <result property="ServiceOrdTraTxnPrice" column="ServiceOrdTraTxnPrice" />
         <result property="ServiceOrdPtOutHospID" column="ServiceOrdPtOutHospID" />
         <result property="ServiceOrdPtServicesID" column="ServiceOrdPtServicesID" />
@@ -55,6 +56,7 @@
         SELECT 
             a.ServiceOrdID,
             a.Old_ServiceOrdID_TXT,
+            a.ServiceOrdNo,
             a.ServiceOrdTraVia,
             a.ServiceOrdApptDate,
             a.ServiceOrd_NS_ID,
@@ -102,6 +104,7 @@
             a.ServiceOrdID,
             a.Old_ServiceOrdID_TXT,
             a.ServiceOrdTraVia,
+            a.ServiceOrdNo,
             a.ServiceOrdApptDate,
             a.ServiceOrdUserID,
             a.ServiceOrd_NS_ID,
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
index 05675ce..a7f2760 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
@@ -45,6 +45,7 @@
         <result property="dispatchSyncTime"        column="dispatch_sync_time"      />
         <result property="dispatchSyncErrorMsg"    column="dispatch_sync_error_msg" />
         <result property="needResync"              column="need_resync"             />
+        <result property="legacyServiceOrdNo"      column="legacy_service_ord_no"   />
         <result property="createTime"              column="create_time"             />
         <result property="updateTime"              column="update_time"             />
         <result property="createBy"                column="create_by"               />
@@ -59,7 +60,7 @@
                hospital_in_department_id, hospital_in_bed_number, hospital_in_address, hospital_in_longitude, 
                hospital_in_latitude, transfer_distance, transfer_price, passenger_contact, 
                passenger_phone, disease_ids, document_type_id, task_type_id, legacy_service_ord_id, legacy_dispatch_ord_id, 
-               sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync,
+               sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync, legacy_service_ord_no,
                create_time, update_time, create_by, update_by
         from sys_task_emergency
     </sql>
@@ -116,6 +117,7 @@
             <if test="dispatchSyncTime != null">dispatch_sync_time,</if>
             <if test="dispatchSyncErrorMsg != null">dispatch_sync_error_msg,</if>
             <if test="needResync != null">need_resync,</if>
+            <if test="legacyServiceOrdNo != null">legacy_service_ord_no,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="createBy != null">create_by,</if>
@@ -161,6 +163,7 @@
             <if test="dispatchSyncTime != null">#{dispatchSyncTime},</if>
             <if test="dispatchSyncErrorMsg != null">#{dispatchSyncErrorMsg},</if>
             <if test="needResync != null">#{needResync},</if>
+            <if test="legacyServiceOrdNo != null">#{legacyServiceOrdNo},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="createBy != null">#{createBy},</if>
@@ -209,6 +212,7 @@
             <if test="dispatchSyncTime != null">dispatch_sync_time = #{dispatchSyncTime},</if>
             <if test="dispatchSyncErrorMsg != null">dispatch_sync_error_msg = #{dispatchSyncErrorMsg},</if>
             <if test="needResync != null">need_resync = #{needResync},</if>
+            <if test="legacyServiceOrdNo != null">legacy_service_ord_no = #{legacyServiceOrdNo},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
         </trim>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
index 338d8e2..18f75f9 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -34,6 +34,7 @@
         <result property="creatorName"      column="creator_name"      />
         <result property="assigneeName"     column="assignee_name"     />
         <result property="deptName"         column="dept_name"         />
+        <result property="vehicleNo"        column="vehicle_no"        />
         <collection property="assignedVehicles" ofType="SysTaskVehicle">
             <result property="id"            column="tv_id"             />
             <result property="taskId"        column="tv_task_id"        />
@@ -57,6 +58,14 @@
                t.actual_start_time, t.actual_end_time, t.creator_id, t.assignee_id, t.dept_id,
                t.create_time, t.update_time, t.create_by, t.update_by, t.remark, t.del_flag, t.legacy_synced,
                u1.nick_name as creator_name, u2.nick_name as assignee_name, d.dept_name,
+               (
+                   select v2.vehicle_no 
+                   from sys_task_vehicle tv2 
+                   left join tb_vehicle_info v2 on tv2.vehicle_id = v2.vehicle_id 
+                   where tv2.task_id = t.task_id 
+                   order by tv2.assign_time asc 
+                   limit 1
+               ) as vehicle_no,
                tv.id as tv_id, tv.task_id as tv_task_id, tv.vehicle_id as tv_vehicle_id,
                v.vehicle_no as tv_vehicle_no, v.vehicle_type as tv_vehicle_type,
                v.vehicle_brand as tv_vehicle_brand, v.vehicle_model as tv_vehicle_model,
@@ -77,6 +86,7 @@
             <if test="taskCode != null  and taskCode != ''"> and t.task_code like concat('%', #{taskCode}, '%')</if>
             <if test="taskType != null  and taskType != ''"> and t.task_type = #{taskType}</if>
             <if test="taskStatus != null  and taskStatus != ''"> and t.task_status = #{taskStatus}</if>
+            <if test="vehicleNo != null  and vehicleNo != ''"> and v.vehicle_no like concat('%', #{vehicleNo}, '%')</if>
             <!-- 缁煎悎鏌ヨ锛氬綋鍓嶇敤鎴锋墍鍦ㄦ満鏋� OR 褰撳墠鐢ㄦ埛鍒涘缓 OR 鍒嗛厤缁欏綋鍓嶇敤鎴� -->
             <if test="(creatorId != null and creatorId != 0) or (assigneeId != null and assigneeId != 0) or (deptId != null and deptId != 0)">
                 and (
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml
index 392434d..fc52b17 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml
@@ -36,7 +36,9 @@
         <include refid="selectSysTaskVehicleVo"/>
         <where>  
             <if test="taskId != null "> and tv.task_id = #{taskId}</if>
+            <if test="taskCode != null and taskCode != ''"> and t.task_code like concat('%', #{taskCode}, '%')</if>
             <if test="vehicleId != null "> and tv.vehicle_id = #{vehicleId}</if>
+            <if test="vehicleNo != null  and vehicleNo != ''"> and v.vehicle_no like concat('%', #{vehicleNo}, '%')</if>
             <if test="status != null  and status != ''"> and tv.status = #{status}</if>
             <if test="assignBy != null  and assignBy != ''"> and tv.assign_by like concat('%', #{assignBy}, '%')</if>
         </where>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 3f59bac..ffc09a9 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -25,6 +25,9 @@
         <result property="updateBy"     column="update_by"    />
         <result property="updateTime"   column="update_time"  />
         <result property="remark"       column="remark"       />
+        <result property="openId"       column="open_id"       />
+        <result property="unionId"     column="union_id"     />
+        <result property="wechatNickname" column="wechat_nickname" />
         <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
         <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
     </resultMap>
@@ -49,7 +52,7 @@
     </resultMap>
 	
 	<sql id="selectUserVo">
-        select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,
+        select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname,
         d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
         from sys_user u
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml
index 3abe287..2c78bdf 100644
--- a/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml
@@ -30,7 +30,7 @@
     <select id="selectVehicleGpsList" parameterType="VehicleGps" resultMap="VehicleGpsResult">
         <include refid="selectVehicleGpsVo"/>
         <where>  
-            <if test="vehicleNo != null  and vehicleNo != ''"> and vehicle_no = #{vehicleNo}</if>
+            <if test="vehicleNo != null  and vehicleNo != ''"> and v.vehicle_no like concat('%', #{vehicleNo}, '%')</if>
             <if test="longitude != null "> and longitude = #{longitude}</if>
             <if test="latitude != null "> and latitude = #{latitude}</if>
             <if test="speed != null "> and speed = #{speed}</if>
@@ -130,10 +130,11 @@
         order by collect_time
     </select>
 
+    <!-- 鏌ヨ娲昏穬杞﹁締ID锛堜紭鍖栵細娣诲姞LIMIT闄愬埗锛岄伩鍏嶅ぇ琛ㄦ壂鎻忥級 -->
     <select id="selectActiveVehicleIds" resultType="Long">
         select distinct vehicle_id
         from tb_vehicle_gps
-        where collect_time &gt;= DATE_SUB(NOW(), INTERVAL 7 DAY)
+        where collect_time &gt;= #{startTime}
         order by vehicle_id
     </select>
     
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
index 4179acf..aee4324 100644
--- a/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
@@ -83,7 +83,7 @@
                s.non_task_mileage, s.task_ratio, s.gps_point_count, s.task_count, s.segment_count, 
                s.data_source, s.create_time, s.update_time
         from tb_vehicle_mileage_stats s
-        where s.vehicle_id = #{vehicleId} and s.stat_date = #{statDate}
+        where s.vehicle_id = #{vehicleId} and DATE(s.stat_date) = DATE(#{statDate})
         limit 1
     </select>
 
@@ -130,6 +130,17 @@
             <if test="dataSource != null">#{dataSource},</if>
             NOW()
          </trim>
+        ON DUPLICATE KEY UPDATE
+            vehicle_no = VALUES(vehicle_no),
+            total_mileage = VALUES(total_mileage),
+            task_mileage = VALUES(task_mileage),
+            non_task_mileage = VALUES(non_task_mileage),
+            task_ratio = VALUES(task_ratio),
+            gps_point_count = VALUES(gps_point_count),
+            task_count = VALUES(task_count),
+            segment_count = VALUES(segment_count),
+            data_source = VALUES(data_source),
+            update_time = NOW()
     </insert>
 
     <update id="updateVehicleMileageStats" parameterType="VehicleMileageStats">
diff --git a/ruoyi-ui/src/api/task.js b/ruoyi-ui/src/api/task.js
index ce09668..8a1ae69 100644
--- a/ruoyi-ui/src/api/task.js
+++ b/ruoyi-ui/src/api/task.js
@@ -248,6 +248,15 @@
   })
 }
 
+// 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
+export function batchGetVehicleCurrentTaskStatus(vehicleIds) {
+  return request({
+    url: '/task/vehicle/management/currentStatus',
+    method: 'post',
+    data: vehicleIds
+  })
+}
+
 // ========== 浠诲姟鏀粯鐩稿叧API ==========
 
 // 鑾峰彇浠诲姟鏀粯淇℃伅
diff --git a/ruoyi-ui/src/views/system/gps/index.vue b/ruoyi-ui/src/views/system/gps/index.vue
index c92678e..6166b06 100644
--- a/ruoyi-ui/src/views/system/gps/index.vue
+++ b/ruoyi-ui/src/views/system/gps/index.vue
@@ -2,14 +2,12 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
-        <el-select v-model="queryParams.vehicleNo" placeholder="璇烽�夋嫨杞︾墝鍙�" clearable size="small">
-          <el-option
-            v-for="item in vehicleOptions"
-            :key="item.vehicleId"
-            :label="item.vehicleNo"
-            :value="item.vehicleNo"
-          />
-        </el-select>
+        <el-input
+          v-model="queryParams.vehicleNo"
+          placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+          clearable
+          size="small"
+        />
       </el-form-item>
       <el-form-item label="閲囬泦鏃堕棿" prop="collectTime">
         <el-date-picker
diff --git a/ruoyi-ui/src/views/task/general/index.vue b/ruoyi-ui/src/views/task/general/index.vue
index 8087b32..63da244 100644
--- a/ruoyi-ui/src/views/task/general/index.vue
+++ b/ruoyi-ui/src/views/task/general/index.vue
@@ -29,6 +29,14 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
+        <el-input
+          v-model="queryParams.vehicleNo"
+          placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
       <el-form-item label="璁″垝寮�濮嬫椂闂�">
         <el-date-picker
           v-model="dateRange"
@@ -118,6 +126,12 @@
           <dict-tag :options="dict.type.sys_task_status" :value="scope.row.taskStatus"/>
         </template>
       </el-table-column>
+      <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" width="120">
+        <template slot-scope="scope">
+          <span v-if="scope.row.vehicleNo">{{ scope.row.vehicleNo }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </template>
+      </el-table-column>
       <el-table-column label="鍑哄彂鍦板潃" align="center" prop="departureAddress" show-overflow-tooltip />
       <el-table-column label="鐩殑鍦板潃" align="center" prop="destinationAddress" show-overflow-tooltip />
       <el-table-column label="棰勮鍏噷鏁�" align="center" prop="estimatedDistance" width="120">
@@ -126,12 +140,7 @@
           <span v-else style="color: #C0C4CC;">--</span>
         </template>
       </el-table-column>
-      <el-table-column label="璁″垝寮�濮嬫椂闂�" align="center" prop="plannedStartTime" width="180">
-        <template slot-scope="scope">
-          <span v-if="scope.row.plannedStartTime">{{ parseTime(scope.row.plannedStartTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
-          <span v-else style="color: #C0C4CC;">--</span>
-        </template>
-      </el-table-column>
+ 
      
       <el-table-column label="鍒涘缓浜�" align="center" prop="creatorName" />
       <el-table-column label="鎵ц浜�" align="center" prop="assigneeName" />
@@ -418,6 +427,7 @@
         taskCode: null,
         taskType: null,
         taskStatus: null,
+        vehicleNo: null,
         plannedStartTimeBegin: null,
         plannedStartTimeEnd: null,
       },
diff --git a/ruoyi-ui/src/views/task/vehicle/index.vue b/ruoyi-ui/src/views/task/vehicle/index.vue
index bebb9f3..76c5ca6 100644
--- a/ruoyi-ui/src/views/task/vehicle/index.vue
+++ b/ruoyi-ui/src/views/task/vehicle/index.vue
@@ -1,25 +1,14 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="浠诲姟" prop="taskId">
-        <el-select v-model="queryParams.taskId" placeholder="璇烽�夋嫨浠诲姟" clearable filterable style="width: 200px">
-          <el-option
-            v-for="task in taskList"
-            :key="task.taskId"
-            :label="task.taskCode + ' - ' + getTaskTypeName(task.taskType)"
-            :value="task.taskId"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="杞﹁締" prop="vehicleId">
-        <el-select v-model="queryParams.vehicleId" placeholder="璇烽�夋嫨杞﹁締" clearable filterable style="width: 200px">
-          <el-option
-            v-for="vehicle in vehicleList"
-            :key="vehicle.vehicleId"
-            :label="vehicle.vehicleNo + ' - ' + vehicle.deptName"
-            :value="vehicle.vehicleId"
-          />
-        </el-select>
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
+      <el-form-item label="浠诲姟缂栧彿" prop="taskCode">
+        <el-input
+          v-model="queryParams.taskCode"
+          placeholder="璇疯緭鍏ヤ换鍔$紪鍙�"
+          clearable
+          @keyup.enter.native="handleQuery"
+          style="width: 200px"
+        />
       </el-form-item>
       <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
         <el-input
@@ -27,6 +16,7 @@
           placeholder="璇疯緭鍏ヨ溅鐗屽彿"
           clearable
           @keyup.enter.native="handleQuery"
+          style="width: 200px"
         />
       </el-form-item>
       <el-form-item label="鍏宠仈鐘舵��" prop="status">
@@ -108,9 +98,20 @@
         </template>
       </el-table-column>
       <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
-      <el-table-column label="杞﹁締绫诲瀷" align="center" prop="vehicleType">
+      
+      <el-table-column label="褰撳墠浠诲姟鐘舵��" align="center" prop="currentTaskStatus" width="180">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.sys_vehicle_type" :value="scope.row.vehicleType"/>
+          <div v-if="scope.row.currentTaskCode">
+            <el-tag type="success" size="mini">
+              <i class="el-icon-loading"></i> 浠诲姟涓�
+            </el-tag>
+            <div style="font-size: 12px; color: #409EFF; margin-top: 5px;">
+              {{ scope.row.currentTaskCode }}
+            </div>
+          </div>
+          <el-tag v-else type="info" size="mini">
+            <i class="el-icon-circle-check"></i> 绌洪棽
+          </el-tag>
         </template>
       </el-table-column>
       
@@ -149,6 +150,12 @@
             @click="handleStatusChange(scope.row)"
             v-hasPermi="['task:vehicle:edit']"
           >鐘舵�佸彉鏇�</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-tickets"
+            @click="handleViewTaskList(scope.row)"
+          >浠诲姟娓呭崟</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -248,16 +255,68 @@
         <el-button @click="cancelStatusChange">鍙� 娑�</el-button>
       </div>
     </el-dialog>
+
+    <!-- 杞﹁締浠诲姟娓呭崟瀵硅瘽妗� -->
+    <el-dialog :title="'杞﹁締浠诲姟娓呭崟 - ' + currentVehicleNo" :visible.sync="taskListOpen" width="1200px" append-to-body>
+      <el-table v-loading="taskListLoading" :data="vehicleTaskList" max-height="500">
+        <el-table-column label="浠诲姟缂栧彿" align="center" prop="taskCode" width="180">
+          <template slot-scope="scope">
+            <el-button
+              type="text"
+              @click="handleViewTaskDetail(scope.row.taskId)"
+              style="font-family: 'Courier New', monospace; font-size: 13px;"
+            >{{ scope.row.taskCode }}</el-button>
+          </template>
+        </el-table-column>
+        <el-table-column label="浠诲姟绫诲瀷" align="center" prop="taskType" width="120">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="璁″垝寮�濮嬫椂闂�" align="center" prop="plannedStartTime" width="160">
+          <template slot-scope="scope">
+            <span v-if="scope.row.plannedStartTime">{{ parseTime(scope.row.plannedStartTime, '{y}-{m}-{d} {h}:{i}') }}</span>
+            <span v-else style="color: #C0C4CC;">--</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍑哄彂鍦板潃" align="center" prop="departureAddress" show-overflow-tooltip min-width="150" />
+        <el-table-column label="鐩爣鍦板潃" align="center" prop="destinationAddress" show-overflow-tooltip min-width="150" />
+        <el-table-column label="棰勮鍏噷鏁�" align="center" prop="estimatedDistance" width="110">
+          <template slot-scope="scope">
+            <span v-if="scope.row.estimatedDistance">{{ scope.row.estimatedDistance }} km</span>
+            <span v-else style="color: #C0C4CC;">--</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="浠诲姟鐘舵��" align="center" prop="taskStatus" width="100">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_task_status" :value="scope.row.taskStatus"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" align="center" width="100">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-view"
+              @click="handleViewTaskDetail(scope.row.taskId)"
+            >鏌ョ湅</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="taskListOpen = false">鍏� 闂�</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { listTaskVehicle, getTaskVehicle, delTaskVehicle, addTaskVehicle, updateTaskVehicle, updateTaskVehicleStatus, listTask } from "@/api/task";
+import { listTaskVehicle, getTaskVehicle, delTaskVehicle, addTaskVehicle, updateTaskVehicle, updateTaskVehicleStatus, listTask, getTask, batchGetVehicleCurrentTaskStatus } from "@/api/task";
 import { listVehicle } from "@/api/system/vehicle";
 
 export default {
   name: "TaskVehicle",
-  dicts: ['sys_task_vehicle_status', 'sys_vehicle_type', 'sys_task_type'],
+  dicts: ['sys_task_vehicle_status', 'sys_vehicle_type', 'sys_task_type', 'sys_task_status'],
   data() {
     return {
       // 閬僵灞�
@@ -288,12 +347,19 @@
       open: false,
       // 鏄惁鏄剧ず鐘舵�佸彉鏇村脊鍑哄眰
       statusOpen: false,
+      // 鏄惁鏄剧ず浠诲姟娓呭崟寮瑰嚭灞�
+      taskListOpen: false,
+      // 杞﹁締浠诲姟鍒楄〃
+      vehicleTaskList: [],
+      // 杞﹁締浠诲姟鍒楄〃鍔犺浇鐘舵��
+      taskListLoading: false,
+      // 褰撳墠鏌ョ湅鐨勮溅鐗屽彿
+      currentVehicleNo: '',
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        taskId: null,
-        vehicleId: null,
+        taskCode: null,
         vehicleNo: null,
         status: null,
         assignBy: null,
@@ -334,7 +400,39 @@
       listTaskVehicle(this.queryParams).then(response => {
         this.taskVehicleList = response.rows;
         this.total = response.total;
+        // 涓烘瘡涓溅杈嗗姞杞藉綋鍓嶄换鍔$姸鎬�
+        this.loadCurrentTaskStatus();
         this.loading = false;
+      });
+    },
+    /** 鍔犺浇杞﹁締褰撳墠浠诲姟鐘舵�侊紙浼樺寲锛氭壒閲忔煡璇級 */
+    loadCurrentTaskStatus() {
+      // 鎻愬彇鎵�鏈夎溅杈咺D
+      const vehicleIds = this.taskVehicleList
+        .map(item => item.vehicleId)
+        .filter(id => id != null);
+      
+      if (vehicleIds.length === 0) {
+        return;
+      }
+      
+      // 鎵归噺鏌ヨ杞﹁締褰撳墠浠诲姟鐘舵��
+      batchGetVehicleCurrentTaskStatus(vehicleIds).then(response => {
+        const statusMap = response.data || {};
+        
+        // 鏇存柊姣忎釜杞﹁締鐨勪换鍔$姸鎬�
+        this.taskVehicleList.forEach(item => {
+          if (item.vehicleId && statusMap[item.vehicleId]) {
+            const taskInfo = statusMap[item.vehicleId];
+            this.$set(item, 'currentTaskCode', taskInfo.taskCode);
+            this.$set(item, 'currentTaskStatus', taskInfo.taskStatus);
+          } else {
+            this.$set(item, 'currentTaskCode', null);
+            this.$set(item, 'currentTaskStatus', null);
+          }
+        });
+      }).catch(error => {
+        console.error('鍔犺浇杞﹁締浠诲姟鐘舵�佸け璐�:', error);
       });
     },
     /** 鑾峰彇浠诲姟鍒楄〃 */
@@ -484,6 +582,61 @@
       this.statusOpen = false;
       this.statusForm = {};
     },
+    /** 鏌ョ湅杞﹁締浠诲姟娓呭崟 */
+    handleViewTaskList(row) {
+      this.currentVehicleNo = row.vehicleNo;
+      this.taskListOpen = true;
+      this.taskListLoading = true;
+      
+      // 鏌ヨ璇ヨ溅杈嗙殑鎵�鏈変换鍔″叧鑱�
+      listTaskVehicle({ 
+        vehicleId: row.vehicleId,
+        pageNum: 1, 
+        pageSize: 1000 
+      }).then(response => {
+        const taskVehicles = response.rows || [];
+        
+        // 鑾峰彇鎵�鏈変换鍔D
+        const taskIds = [...new Set(taskVehicles.map(item => item.taskId).filter(id => id))];
+        
+        if (taskIds.length === 0) {
+          this.vehicleTaskList = [];
+          this.taskListLoading = false;
+          return;
+        }
+        
+        // 鎵归噺鏌ヨ浠诲姟璇︽儏
+        const taskPromises = taskIds.map(taskId => 
+          getTask(taskId).then(res => res.data).catch(() => null)
+        );
+        
+        Promise.all(taskPromises).then(tasks => {
+          // 杩囨护鎺夌┖鍊煎苟鎸夋椂闂存帓搴�
+          this.vehicleTaskList = tasks
+            .filter(task => task !== null)
+            .sort((a, b) => {
+              const timeA = new Date(a.plannedStartTime || a.createTime).getTime();
+              const timeB = new Date(b.plannedStartTime || b.createTime).getTime();
+              return timeB - timeA; // 闄嶅簭鎺掑垪
+            });
+          
+          this.taskListLoading = false;
+        }).catch(error => {
+          console.error('鏌ヨ浠诲姟璇︽儏澶辫触:', error);
+          this.$modal.msgError('鍔犺浇浠诲姟娓呭崟澶辫触');
+          this.taskListLoading = false;
+        });
+      }).catch(error => {
+        console.error('鏌ヨ杞﹁締浠诲姟鍏宠仈澶辫触:', error);
+        this.$modal.msgError('鍔犺浇浠诲姟娓呭崟澶辫触');
+        this.taskListLoading = false;
+      });
+    },
+    /** 鏌ョ湅浠诲姟璇︽儏 */
+    handleViewTaskDetail(taskId) {
+      // 璺宠浆鍒颁换鍔¤鎯呴〉闈�
+      this.$router.push('/task/general-detail/index/' + taskId);
+    },
     /** 浠诲姟閫夋嫨鍙樺寲 */
     handleTaskChange(taskId) {
       if (taskId) {
diff --git a/sql/add_gps_collect_time_index.sql b/sql/add_gps_collect_time_index.sql
new file mode 100644
index 0000000..02b9a8e
--- /dev/null
+++ b/sql/add_gps_collect_time_index.sql
@@ -0,0 +1,19 @@
+-- 涓簍b_vehicle_gps琛ㄧ殑collect_time瀛楁娣诲姞绱㈠紩
+-- 鐢ㄤ簬浼樺寲GPS鍒嗘閲岀▼璁$畻鏃剁殑鏌ヨ鎬ц兘,閬垮厤鍏ㄨ〃鎵弿瀵艰嚧瓒呮椂
+
+-- 妫�鏌ョ储寮曟槸鍚﹀凡瀛樺湪(MySQL 5.5鍏煎璇硶)
+-- 濡傛灉绱㈠紩宸插瓨鍦�,璇峰拷鐣ヤ笅闈㈢殑CREATE INDEX璇彞
+
+-- 娣诲姞collect_time绱㈠紩(鐢ㄤ簬鏃堕棿鑼冨洿鏌ヨ)
+CREATE INDEX idx_collect_time ON tb_vehicle_gps(collect_time);
+
+-- 娣诲姞vehicle_id鍜宑ollect_time鐨勫鍚堢储寮�(鐢ㄤ簬鍗曡溅杈嗘椂闂磋寖鍥存煡璇�)
+CREATE INDEX idx_vehicle_collect_time ON tb_vehicle_gps(vehicle_id, collect_time);
+
+-- 绱㈠紩璇存槑:
+-- 1. idx_collect_time: 鐢ㄤ簬selectActiveVehicleIds鏌ヨ,鍔犻�熸寜鏃堕棿杩囨护
+-- 2. idx_vehicle_collect_time: 鐢ㄤ簬selectGpsDataByTimeRange鍜宻electUncalculatedGps鏌ヨ
+--    鎸夎溅杈咺D+鏃堕棿鑼冨洿鏌ヨ鏃跺彲鏄捐憲鎻愬崌鎬ц兘
+
+-- 楠岃瘉绱㈠紩鍒涘缓鎴愬姛
+SHOW INDEX FROM tb_vehicle_gps WHERE Key_name IN ('idx_collect_time', 'idx_vehicle_collect_time');
diff --git a/sql/add_legacy_service_ord_no.sql b/sql/add_legacy_service_ord_no.sql
new file mode 100644
index 0000000..b089690
--- /dev/null
+++ b/sql/add_legacy_service_ord_no.sql
@@ -0,0 +1,17 @@
+-- ----------------------------
+-- 娣诲姞鏃х郴缁烻erviceOrdNo瀛楁锛岀敤浜庝繚瀛樹粠鏃х郴缁熷悓姝ョ殑杞繍鍗曠紪鍙�
+-- ----------------------------
+
+-- 鍦ㄦ�ユ晳杞繍鎵╁睍琛ㄤ腑娣诲姞legacy_service_ord_no瀛楁
+ALTER TABLE sys_task_emergency 
+ADD COLUMN legacy_service_ord_no VARCHAR(50) NULL COMMENT '鏃х郴缁烻erviceOrdNo锛堣浆杩愬崟缂栧彿锛�' AFTER need_resync;
+
+-- 涓鸿瀛楁娣诲姞绱㈠紩浠ヤ究蹇�熸煡璇�
+ALTER TABLE sys_task_emergency 
+ADD INDEX idx_legacy_service_ord_no (legacy_service_ord_no);
+
+-- 鏌ヨ绀轰緥锛�
+-- SELECT task_id, legacy_service_ord_id, legacy_service_ord_no, legacy_dispatch_ord_id
+-- FROM sys_task_emergency
+-- WHERE legacy_service_ord_no IS NOT NULL
+-- ORDER BY id DESC;
diff --git a/sql/fix_duplicate_mileage_stats.sql b/sql/fix_duplicate_mileage_stats.sql
new file mode 100644
index 0000000..7d6bd65
--- /dev/null
+++ b/sql/fix_duplicate_mileage_stats.sql
@@ -0,0 +1,32 @@
+-- 淇杞﹁締閲岀▼缁熻琛ㄤ腑鐨勯噸澶嶆暟鎹�
+-- 鎵ц鍓嶈鍏堝浠芥暟鎹紒
+
+-- 1. 鏌ョ湅閲嶅鏁版嵁
+SELECT vehicle_id, stat_date, COUNT(*) as count
+FROM tb_vehicle_mileage_stats
+GROUP BY vehicle_id, stat_date
+HAVING COUNT(*) > 1;
+
+-- 2. 鍒犻櫎閲嶅璁板綍锛屼繚鐣欐渶鏂扮殑涓�鏉★紙鏍规嵁stats_id鏈�澶х殑淇濈暀锛�
+DELETE t1 FROM tb_vehicle_mileage_stats t1
+INNER JOIN (
+    SELECT vehicle_id, stat_date, MAX(stats_id) as max_id
+    FROM tb_vehicle_mileage_stats
+    GROUP BY vehicle_id, stat_date
+    HAVING COUNT(*) > 1
+) t2 ON t1.vehicle_id = t2.vehicle_id 
+    AND t1.stat_date = t2.stat_date 
+    AND t1.stats_id < t2.max_id;
+
+-- 3. 楠岃瘉鏄惁杩樻湁閲嶅鏁版嵁
+SELECT vehicle_id, stat_date, COUNT(*) as count
+FROM tb_vehicle_mileage_stats
+GROUP BY vehicle_id, stat_date
+HAVING COUNT(*) > 1;
+
+-- 4. 纭鍞竴绱㈠紩鏄惁瀛樺湪
+SHOW INDEX FROM tb_vehicle_mileage_stats WHERE Key_name = 'uk_vehicle_date';
+
+-- 濡傛灉鍞竴绱㈠紩涓嶅瓨鍦紝閲嶆柊鍒涘缓
+-- ALTER TABLE tb_vehicle_mileage_stats 
+-- ADD UNIQUE KEY `uk_vehicle_date` (`vehicle_id`, `stat_date`);
diff --git a/sql/gps_compensation_job.sql b/sql/gps_compensation_job.sql
new file mode 100644
index 0000000..7cb6364
--- /dev/null
+++ b/sql/gps_compensation_job.sql
@@ -0,0 +1,38 @@
+-- GPS鍒嗘閲岀▼琛ュ伩璁$畻瀹氭椂浠诲姟閰嶇疆
+-- 鐢ㄤ簬琛ュ伩鍥犳湇鍔℃晠闅溿�侀噸鍚瓑鍘熷洜瀵艰嚧閬楁紡鐨凣PS鏁版嵁璁$畻
+
+-- GPS鍒嗘閲岀▼琛ュ伩璁$畻浠诲姟锛堟瘡澶╁噷鏅�2鐐规墽琛岋紝鍥炴函7澶╂暟鎹級
+INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark)
+VALUES (
+  'GPS鍒嗘閲岀▼琛ュ伩璁$畻',
+  'DEFAULT',
+  'vehicleGpsSegmentMileageTask.executeCompensationCalculation(''7'')',
+  '0 0 2 * * ?',
+  '2',
+  '0',
+  '1',
+  'admin',
+  NOW(),
+  '姣忓ぉ鍑屾櫒2鐐规墽琛岋紝妫�鏌ユ渶杩�7澶╁唴鏈澶勭悊鐨凣PS鍧愭爣骞惰繘琛岃ˉ鍋胯绠椼�傚弬鏁�7琛ㄧず鍥炴函7澶╋紝鍙牴鎹渶瑕佽皟鏁�'
+);
+
+-- 閰嶇疆璇存槑
+-- 1. 浠诲姟榛樿鐘舵�佷负'1'锛堟殏鍋滐級锛岄渶瑕佸湪鍚庡彴绠$悊绯荤粺涓墜鍔ㄥ惎鍔�
+-- 2. 寤鸿鍦ㄥ噷鏅ㄦ墽琛岋紝閬垮厤褰卞搷鐧藉ぉ涓氬姟楂樺嘲
+-- 3. 鍥炴函澶╂暟鍙�氳繃鍙傛暟璋冩暣锛屽缓璁笉瓒呰繃30澶╋紝閬垮厤鏁版嵁閲忚繃澶у奖鍝嶆�ц兘
+-- 4. 琛ュ伩璁$畻閫昏緫锛�
+--    - 鏌ヨ鎸囧畾鏃堕棿鑼冨洿鍐呮墍鏈夎溅杈�
+--    - 妫�鏌ユ瘡杈嗚溅鐨凣PS鍧愭爣鏄惁宸茶鍒嗘澶勭悊锛堥�氳繃segment_id鍒ゆ柇锛�
+--    - 瀵规湭澶勭悊鐨凣PS鍧愭爣鎵ц鍒嗘閲岀▼璁$畻
+--    - 鑷姩鍏宠仈浠诲姟ID鍜屼换鍔$紪鍙�
+-- 5. 涓庡疄鏃惰绠椾换鍔$殑鍖哄埆锛�
+--    - 瀹炴椂璁$畻锛氬鐞嗘渶杩戠殑GPS鏁版嵁锛堝鏈�杩�10鍒嗛挓锛�
+--    - 琛ュ伩璁$畻锛氬洖婧鏌ュ巻鍙叉暟鎹紝琛ュ厖閬楁紡鐨勮绠�
+-- 6. cron琛ㄨ揪寮忚鏄庯細
+--    - '0 0 2 * * ?' : 姣忓ぉ鍑屾櫒2鐐规墽琛�
+--    - 鍙牴鎹疄闄呮儏鍐佃皟鏁存墽琛屾椂闂�
+
+-- 浣跨敤绀轰緥
+-- 1. 榛樿鍥炴函7澶╋細executeCompensationCalculation() 鎴� executeCompensationCalculation('7')
+-- 2. 鍥炴函3澶╋細executeCompensationCalculation('3')
+-- 3. 鍥炴函30澶╋細executeCompensationCalculation('30')
diff --git a/sql/optimize_gps_query_performance.sql b/sql/optimize_gps_query_performance.sql
new file mode 100644
index 0000000..1eb3bcc
--- /dev/null
+++ b/sql/optimize_gps_query_performance.sql
@@ -0,0 +1,71 @@
+-- GPS鏌ヨ鎬ц兘浼樺寲SQL
+-- 鐢ㄤ簬瑙e喅GPS鍒嗘閲岀▼璁$畻浠诲姟鏌ヨ瓒呮椂闂
+
+-- 1. 妫�鏌b_vehicle_gps琛ㄧ殑绱㈠紩
+SHOW INDEX FROM tb_vehicle_gps;
+
+-- 2. 娣诲姞缁勫悎绱㈠紩锛歷ehicle_id + collect_time锛堝鏋滀笉瀛樺湪锛�
+-- 杩欎釜绱㈠紩鍙互澶у箙鎻愬崌鎸夎溅杈咺D鍜屾椂闂磋寖鍥存煡璇㈢殑鎬ц兘
+ALTER TABLE tb_vehicle_gps 
+ADD INDEX idx_vehicle_collect_time (vehicle_id, collect_time);
+
+-- 3. 娣诲姞鍗曞垪绱㈠紩锛歝ollect_time锛堝鏋滀笉瀛樺湪锛�
+-- 杩欎釜绱㈠紩鐢ㄤ簬浼樺寲鏌ヨ娲昏穬杞﹁締ID鐨勬煡璇�
+ALTER TABLE tb_vehicle_gps 
+ADD INDEX idx_collect_time (collect_time);
+
+-- 4. 妫�鏌b_vehicle_gps_calculated琛ㄧ殑绱㈠紩
+SHOW INDEX FROM tb_vehicle_gps_calculated;
+
+-- 5. 浼樺寲tb_vehicle_gps_calculated琛ㄧ储寮�
+-- 娣诲姞gps_id绱㈠紩锛堝鏋滀笉瀛樺湪锛夛紝鐢ㄤ簬LEFT JOIN鏌ヨ浼樺寲
+ALTER TABLE tb_vehicle_gps_calculated 
+ADD INDEX idx_gps_id (gps_id);
+
+-- 6. 娣诲姞vehicle_id绱㈠紩锛岀敤浜庢寜杞﹁締鏌ヨ宸茶绠楄褰�
+ALTER TABLE tb_vehicle_gps_calculated 
+ADD INDEX idx_vehicle_id (vehicle_id);
+
+-- 7. 鏌ョ湅琛ㄧ殑缁熻淇℃伅
+ANALYZE TABLE tb_vehicle_gps;
+ANALYZE TABLE tb_vehicle_gps_calculated;
+
+-- 8. 鏌ョ湅绱㈠紩浣跨敤鎯呭喌
+-- 鎵ц浠ヤ笅鏌ヨ鏉ラ獙璇佺储寮曟槸鍚﹁姝g‘浣跨敤
+EXPLAIN SELECT DISTINCT vehicle_id
+FROM tb_vehicle_gps
+WHERE collect_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
+ORDER BY vehicle_id;
+
+EXPLAIN SELECT g.gps_id, g.vehicle_id, g.device_id, g.longitude, g.latitude, 
+       g.altitude, g.speed, g.direction, g.collect_time
+FROM tb_vehicle_gps g
+LEFT JOIN tb_vehicle_gps_calculated c ON g.gps_id = c.gps_id
+WHERE g.vehicle_id = 1
+  AND g.collect_time >= DATE_SUB(NOW(), INTERVAL 1 DAY)
+  AND g.collect_time <= NOW()
+  AND c.gps_id IS NULL
+ORDER BY g.collect_time;
+
+-- 9. 鎬ц兘浼樺寲寤鸿
+/*
+鎵ц缁撴灉璇存槑锛�
+- type搴旇鏄痳ef鎴杛ange锛屼笉搴旇鏄疉LL锛堝叏琛ㄦ壂鎻忥級
+- key搴旇鏄剧ず浣跨敤浜嗙浉搴旂殑绱㈠紩
+- rows搴旇灏藉彲鑳藉皯
+
+濡傛灉鍙戠幇绱㈠紩鏈浣跨敤锛屽彲鑳介渶瑕侊細
+1. 鏇存柊琛ㄧ粺璁′俊鎭細ANALYZE TABLE
+2. 妫�鏌ySQL鐗堟湰鏄惁鏀寔绱㈠紩浼樺寲
+3. 鑰冭檻澧炲姞MySQL鐨刬nnodb_buffer_pool_size閰嶇疆
+*/
+
+-- 10. 娓呯悊鍘嗗彶GPS鏁版嵁锛堝彲閫夛紝瀹氭湡鎵ц锛�
+-- 寤鸿淇濈暀鏈�杩�30-90澶╃殑鏁版嵁锛岄伩鍏嶈〃杩囧ぇ褰卞搷鏌ヨ鎬ц兘
+/*
+DELETE FROM tb_vehicle_gps 
+WHERE collect_time < DATE_SUB(NOW(), INTERVAL 90 DAY);
+
+-- 浼樺寲琛ㄧ┖闂�
+OPTIMIZE TABLE tb_vehicle_gps;
+*/
diff --git "a/\346\227\247\347\263\273\347\273\237ServiceOrdNo\345\255\227\346\256\265\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/\346\227\247\347\263\273\347\273\237ServiceOrdNo\345\255\227\346\256\265\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..a34f026
--- /dev/null
+++ "b/\346\227\247\347\263\273\347\273\237ServiceOrdNo\345\255\227\346\256\265\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,244 @@
+# 鏃х郴缁烻erviceOrdNo瀛楁鍚屾鍔熻兘璇存槑
+
+## 涓�銆佸姛鑳芥杩�
+
+鍦ㄤ粠鏃х郴缁熷悓姝ヨ浆杩愬崟锛圫erviceOrder锛夊埌鏂扮郴缁熸椂锛岄櫎浜嗗凡鏈夌殑`ServiceOrdID`锛堟湇鍔″崟ID锛夊拰`DispatchOrdID`锛堣皟搴﹀崟ID锛夛紝鐜板湪杩樹細鍚屾`ServiceOrdNo`锛堣浆杩愬崟缂栧彿锛夊瓧娈碉紝骞朵繚瀛樺埌`sys_task_emergency`琛ㄤ腑銆�
+
+## 浜屻�佹暟鎹簱鍙樻洿
+
+### 鏂板瀛楁
+
+鍦╜sys_task_emergency`琛ㄤ腑娣诲姞浠ヤ笅瀛楁锛�
+
+```sql
+-- 鏃х郴缁烻erviceOrdNo锛堣浆杩愬崟缂栧彿锛�
+ALTER TABLE sys_task_emergency 
+ADD COLUMN legacy_service_ord_no VARCHAR(50) NULL COMMENT '鏃х郴缁烻erviceOrdNo锛堣浆杩愬崟缂栧彿锛�' AFTER need_resync;
+
+-- 娣诲姞绱㈠紩
+ALTER TABLE sys_task_emergency 
+ADD INDEX idx_legacy_service_ord_no (legacy_service_ord_no);
+```
+
+### 瀛楁璇存槑
+
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 | 绀轰緥 |
+|--------|------|------|------|
+| legacy_service_ord_no | VARCHAR(50) | 鏃х郴缁熻浆杩愬崟缂栧彿 | "123"銆�"045"绛� |
+
+**娉ㄦ剰**锛歚ServiceOrdNo`瀛楁鍦ㄦ棫绯荤粺涓槸鏁板瓧绫诲瀷锛屽湪鐢熸垚浠诲姟缂栧彿鏃朵細琚牸寮忓寲涓�3浣嶆暟瀛楀瓧绗︿覆锛堝 32 鈫� "032"锛�1 鈫� "001"锛夈��
+
+## 涓夈�佷唬鐮佸彉鏇�
+
+### 1. 瀹炰綋绫讳慨鏀�
+
+**鏂囦欢**: `SysTaskEmergency.java`
+
+鏂板灞炴�э細
+```java
+/** 鏃х郴缁烻erviceOrdNo锛堣浆杩愬崟缂栧彿锛� */
+private String legacyServiceOrdNo;
+```
+
+鏂板getter/setter鏂规硶銆�
+
+### 2. Mapper XML淇敼
+
+**鏂囦欢**: `SysTaskEmergencyMapper.xml`
+
+- 鍦╜resultMap`涓坊鍔犲瓧娈垫槧灏�
+- 鍦╜selectSysTaskEmergencyVo`涓坊鍔犳煡璇㈠瓧娈�
+- 鍦╜insertSysTaskEmergency`涓坊鍔犳彃鍏ラ�昏緫
+- 鍦╜updateSysTaskEmergency`涓坊鍔犳洿鏂伴�昏緫
+
+### 3. Service鎺ュ彛淇敼
+
+**鏂囦欢**: `ISysTaskService.java`
+
+淇敼鏂规硶绛惧悕锛屾坊鍔燻serviceOrdNo`鍙傛暟锛�
+```java
+public int insertTask(TaskCreateVO createVO, String serviceOrderId, 
+                     String dispatchOrderId, String serviceOrdNo, 
+                     Long userId, String userName, Long deptId, 
+                     Date createTime, Date updateTime);
+```
+
+### 4. Service瀹炵幇淇敼
+
+**鏂囦欢**: `SysTaskServiceImpl.java`
+
+1. 淇敼`insertTask`鏂规硶绛惧悕锛屾坊鍔燻serviceOrdNo`鍙傛暟
+2. 淇敼`saveEmergencyInfo`鏂规硶绛惧悕锛屾坊鍔燻serviceOrdNo`鍙傛暟
+3. 鍦╜saveEmergencyInfo`鏂规硶涓繚瀛榒serviceOrdNo`锛�
+
+```java
+if(serviceOrdNo!=null){
+    emergencyInfo.setLegacyServiceOrdNo(serviceOrdNo);
+}
+```
+
+### 5. 鍚屾鏈嶅姟淇敼
+
+**鏂囦欢**: `LegacyTransferSyncServiceImpl.java`
+
+鍦╜syncSingleTransferOrder`鏂规硶涓細
+
+1. 浠庢棫绯荤粺鏌ヨ缁撴灉涓彁鍙朻ServiceOrdNo`锛�
+```java
+String serviceOrdNo = getStringValue(order, "ServiceOrdNo");
+```
+
+2. 璋冪敤`insertTask`鏂规硶鏃朵紶閫抈serviceOrdNo`鍙傛暟锛�
+```java
+int result = sysTaskService.insertTask(createTaskVo, serviceOrdID, 
+                                      dispatchOrdID, serviceOrdNo, 
+                                      taskCreatorId, createUserName, 
+                                      deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time);
+```
+
+## 鍥涖�佹暟鎹祦杞�
+
+```
+鏃х郴缁� ServiceOrder 琛�
+    鈫� (鏌ヨ)
+LegacyTransferSyncServiceImpl
+    鈫� (鎻愬彇)
+ServiceOrdNo 瀛楁
+    鈫� (浼犻��)
+SysTaskService.insertTask()
+    鈫� (淇濆瓨)
+SysTaskEmergency.legacy_service_ord_no
+```
+
+## 浜斻�佷娇鐢ㄥ満鏅�
+
+### 1. 鏁版嵁杩芥函
+閫氳繃`legacy_service_ord_no`瀛楁鍙互蹇�熷湪鏃х郴缁熶腑瀹氫綅鍘熷杞繍鍗曟暟鎹��
+
+### 2. 浠诲姟缂栧彿鐢熸垚
+`ServiceOrdNo`瀛楁鐢ㄤ簬鐢熸垚鏂扮郴缁熺殑浠诲姟缂栧彿锛坄task_code`锛夛紝鏍煎紡涓猴細
+```
+{ServiceOrdClass}{YYYYMMDD}-{ServiceOrdNo(3浣�)}
+```
+渚嬪锛歚BF20251101-032`
+
+### 3. 鏁版嵁鏌ヨ
+
+鏌ヨ宸插悓姝ョ殑杞繍鍗曞強鍏剁紪鍙凤細
+```sql
+SELECT 
+    t.task_id,
+    t.task_code,
+    e.legacy_service_ord_id,
+    e.legacy_service_ord_no,
+    e.legacy_dispatch_ord_id,
+    e.sync_status
+FROM sys_task t
+JOIN sys_task_emergency e ON t.task_id = e.task_id
+WHERE e.legacy_service_ord_no IS NOT NULL
+ORDER BY t.create_time DESC;
+```
+
+鎸塦ServiceOrdNo`鏌ヨ鐗瑰畾杞繍鍗曪細
+```sql
+SELECT 
+    t.task_id,
+    t.task_code,
+    t.task_status,
+    e.patient_name,
+    e.hospital_out_name,
+    e.hospital_in_name
+FROM sys_task t
+JOIN sys_task_emergency e ON t.task_id = e.task_id
+WHERE e.legacy_service_ord_no = '032';
+```
+
+## 鍏�佹祴璇曢獙璇�
+
+### 娴嬭瘯姝ラ
+
+1. **鎵ц鏁版嵁搴撹剼鏈�**
+   ```bash
+   mysql -u鐢ㄦ埛鍚� -p鏁版嵁搴撳悕 < sql/add_legacy_service_ord_no.sql
+   ```
+
+2. **閲嶅惎搴旂敤**
+   纭繚鏂颁唬鐮佺敓鏁堛��
+
+3. **瑙﹀彂鍚屾浠诲姟**
+   - 鏂瑰紡1锛氭墜鍔ㄨ皟鐢ㄥ畾鏃朵换鍔�
+   - 鏂瑰紡2锛氱瓑寰呰嚜鍔ㄥ畾鏃朵换鍔℃墽琛�
+
+4. **楠岃瘉鏁版嵁**
+   ```sql
+   SELECT task_id, legacy_service_ord_id, legacy_service_ord_no
+   FROM sys_task_emergency
+   WHERE sync_status = 2
+   ORDER BY id DESC
+   LIMIT 10;
+   ```
+
+### 棰勬湡缁撴灉
+
+- `legacy_service_ord_no`瀛楁搴斿寘鍚粠鏃х郴缁熷悓姝ョ殑`ServiceOrdNo`鍊�
+- 璇ュ瓧娈典笉涓虹┖涓旀牸寮忔纭紙閫氬父涓�1-3浣嶆暟瀛楋級
+- 涓巂legacy_service_ord_id`涓�涓�瀵瑰簲
+
+## 涓冦�佹敞鎰忎簨椤�
+
+1. **瀛楁鍙┖鎬�**锛歚legacy_service_ord_no`瀛楁鍏佽涓篘ULL锛屽洜涓猴細
+   - 鏃т换鍔″彲鑳芥病鏈夎瀛楁
+   - 浠庢柊绯荤粺鍒涘缓鐨勪换鍔′笉浼氭湁姝ゅ瓧娈�
+
+2. **鏁版嵁绫诲瀷**锛氳櫧鐒禶ServiceOrdNo`鍦ㄦ棫绯荤粺涓槸鏁板瓧锛屼絾鍦ㄦ柊绯荤粺涓娇鐢╒ARCHAR绫诲瀷瀛樺偍锛屼互淇濇寔鍘熷鏍煎紡銆�
+
+3. **鍚戝悗鍏煎**锛氭淇敼涓嶅奖鍝嶅凡瀛樺湪鐨勬暟鎹拰鍔熻兘锛屽彧瀵规柊鍚屾鐨勮浆杩愬崟鏈夋晥銆�
+
+4. **浠诲姟缂栧彿鐢熸垚**锛歚ServiceOrdNo`鐢ㄤ簬鐢熸垚浠诲姟缂栧彿锛屼絾濡傛灉璇ュ瓧娈典负绌猴紝绯荤粺浼氳嚜鍔ㄧ敓鎴愭柊鐨勪换鍔$紪鍙枫��
+
+## 鍏�佺浉鍏虫枃浠舵竻鍗�
+
+### 鏁版嵁搴撹剼鏈�
+- `sql/add_legacy_service_ord_no.sql` - 娣诲姞瀛楁鐨凷QL鑴氭湰
+
+### Java鏂囦欢
+- `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java`
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java`
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java`
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java`
+
+### Mapper鏂囦欢
+- `ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml`
+
+### 鏂囨。
+- `鏃х郴缁烻erviceOrdNo瀛楁鍚屾鍔熻兘璇存槑.md` - 鏈枃妗�
+
+## 涔濄�佸父瑙侀棶棰�
+
+### Q1: ServiceOrdNo瀛楁涓轰粈涔堟槸VARCHAR绫诲瀷锛�
+**A**: 铏界劧鍦ㄦ棫绯荤粺涓槸鏁板瓧绫诲瀷锛屼絾浣跨敤VARCHAR鍙互锛�
+- 淇濈暀鍘熷鏍煎紡锛堝鍓嶅闆讹級
+- 閬垮厤绫诲瀷杞崲閿欒
+- 鏇寸伒娲诲湴澶勭悊鐗规畩鎯呭喌
+
+### Q2: 濡傛灉鏃х郴缁熶腑ServiceOrdNo涓虹┖鎬庝箞鍔烇紵
+**A**: 浠g爜涓湁NULL妫�鏌ワ紝濡傛灉`ServiceOrdNo`涓虹┖锛岃瀛楁鍦ㄦ柊绯荤粺涓篃涓篘ULL锛屼笉褰卞搷鍏朵粬涓氬姟銆�
+
+### Q3: 宸插悓姝ョ殑鍘嗗彶鏁版嵁浼氭洿鏂拌繖涓瓧娈靛悧锛�
+**A**: 涓嶄細銆傛鍔熻兘鍙鏂板悓姝ョ殑杞繍鍗曟湁鏁堛�傚闇�鏇存柊鍘嗗彶鏁版嵁锛岄渶瑕佺紪鍐欎笓闂ㄧ殑鏁版嵁杩佺Щ鑴氭湰銆�
+
+### Q4: 杩欎釜瀛楁浼氬奖鍝嶇幇鏈夊姛鑳藉悧锛�
+**A**: 涓嶄細銆傝繖鏄竴涓柊澧炲瓧娈碉紝涓嶅奖鍝嶄换浣曠幇鏈変笟鍔¢�昏緫锛屽畬鍏ㄥ悜鍚庡吋瀹广��
+
+## 鍗併�佸悗缁紭鍖栧缓璁�
+
+1. **鍘嗗彶鏁版嵁鍥炲~**锛氬彲浠ョ紪鍐欒剼鏈负宸插悓姝ョ殑鍘嗗彶浠诲姟鍥炲~`legacy_service_ord_no`瀛楁銆�
+
+2. **鍓嶇灞曠ず**锛氬彲浠ュ湪浠诲姟璇︽儏椤甸潰灞曠ず璇ュ瓧娈碉紝鏂逛究鐢ㄦ埛鏌ョ湅鍘熷杞繍鍗曠紪鍙枫��
+
+3. **鏁版嵁鏍¢獙**锛氬彲浠ユ坊鍔犳暟鎹竴鑷存�ф牎楠岋紝纭繚`legacy_service_ord_id`鍜宍legacy_service_ord_no`鐨勫搴斿叧绯绘纭��
+
+---
+
+**鏇存柊鏃ユ湡**: 2024-11-30  
+**鐗堟湰**: v1.0

--
Gitblit v1.9.1