From f67945d53b20f6a45ae50b27d74c966eb1355bb4 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期日, 16 十一月 2025 22:53:54 +0800
Subject: [PATCH] feat: 增加分段GPS计算行程距离

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/VehicleGpsController.java |  548 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 541 insertions(+), 7 deletions(-)

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 5ae3359..48791f2 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
@@ -11,6 +11,7 @@
 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.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -63,6 +64,9 @@
     
     @Autowired
     private BaiduMapConfig baiduMapConfig;
+    
+    @Autowired
+    private TiandituMapConfig tiandituMapConfig;
 
    /**
      * 鏌ヨ杞﹁締GPS鍧愭爣鍒楄〃
@@ -575,6 +579,17 @@
             String geocodingResponse1 = HttpUtils.sendGet(geocodingUrl1, geocodingParams1);
             logger.info("璧风偣鍦扮悊缂栫爜鍝嶅簲: {}", geocodingResponse1);
             
+            // 瑙f瀽璧风偣鍧愭爣
+            com.alibaba.fastjson2.JSONObject geocodingJson1 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse1);
+            if (geocodingJson1.getInteger("status") != 0) {
+                logger.error("璧风偣鍦扮悊缂栫爜澶辫触: {}", geocodingResponse1);
+                return AjaxResult.error("璧风偣鍦板潃瑙f瀽澶辫触");
+            }
+            com.alibaba.fastjson2.JSONObject location1 = geocodingJson1.getJSONObject("result").getJSONObject("location");
+            double fromLat = location1.getDouble("lat");
+            double fromLng = location1.getDouble("lng");
+            logger.info("璧风偣鍧愭爣: lat={}, lng={}", fromLat, fromLng);
+            
             // 绗簩姝ワ細缁堢偣鍦板潃杞潗鏍�
             String geocodingUrl2 = "https://api.map.baidu.com/geocoding/v3/";
             String geocodingParams2 = "address=" + URLEncoder.encode(toAddress, StandardCharsets.UTF_8.toString()) +
@@ -586,17 +601,536 @@
             String geocodingResponse2 = HttpUtils.sendGet(geocodingUrl2, geocodingParams2);
             logger.info("缁堢偣鍦扮悊缂栫爜鍝嶅簲: {}", geocodingResponse2);
             
-            // 瑙f瀽鍧愭爣锛堣繖閲岀畝鍖栧鐞嗭紝瀹為檯搴旇瑙f瀽JSON锛�
-            // 娉ㄦ剰锛氶渶瑕佷粠鍝嶅簲涓彁鍙栧潗鏍囷紝杩欓噷杩斿洖涓棿缁撴灉渚涘墠绔鐞�
-            Map<String, Object> result = new HashMap<>();
-            result.put("fromGeocoding", geocodingResponse1);
-            result.put("toGeocoding", geocodingResponse2);
-            result.put("message", "璇疯В鏋愬潗鏍囧悗璋冪敤 /baidu/route/driving 鎺ュ彛璁$畻璺濈");
+            // 瑙f瀽缁堢偣鍧愭爣
+            com.alibaba.fastjson2.JSONObject geocodingJson2 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse2);
+            if (geocodingJson2.getInteger("status") != 0) {
+                logger.error("缁堢偣鍦扮悊缂栫爜澶辫触: {}", geocodingResponse2);
+                return AjaxResult.error("缁堢偣鍦板潃瑙f瀽澶辫触");
+            }
+            com.alibaba.fastjson2.JSONObject location2 = geocodingJson2.getJSONObject("result").getJSONObject("location");
+            double toLat = location2.getDouble("lat");
+            double toLng = location2.getDouble("lng");
+            logger.info("缁堢偣鍧愭爣: lat={}, lng={}", toLat, toLng);
             
-            return AjaxResult.success("鍦扮悊缂栫爜鎴愬姛", result);
+            // 绗笁姝ワ細璋冪敤璺嚎瑙勫垝鎺ュ彛璁$畻璺濈
+            String routeUrl = "https://api.map.baidu.com/directionlite/v1/driving";
+            String origin = fromLat + "," + fromLng;
+            String destination = toLat + "," + toLng;
+            String routeParams = "origin=" + origin +
+                                "&destination=" + destination +
+                                "&ak=" + baiduMapConfig.getAk();
+            
+            logger.info("璺嚎瑙勫垝璇锋眰: origin={}, destination={}", origin, destination);
+            String routeResponse = HttpUtils.sendGet(routeUrl, routeParams);
+            logger.info("璺嚎瑙勫垝鍝嶅簲: {}", routeResponse);
+            
+            // 瑙f瀽璺濈缁撴灉
+            com.alibaba.fastjson2.JSONObject routeJson = com.alibaba.fastjson2.JSONObject.parseObject(routeResponse);
+            if (routeJson.getInteger("status") != 0) {
+                logger.error("璺嚎瑙勫垝澶辫触: {}", routeResponse);
+                return AjaxResult.error("璺嚎瑙勫垝澶辫触");
+            }
+            
+            // 鎻愬彇璺濈淇℃伅锛堝崟浣嶏細绫筹級
+            com.alibaba.fastjson2.JSONObject result = routeJson.getJSONObject("result");
+            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);
+            int distance = route.getInteger("distance"); // 璺濈锛屽崟浣嶏細绫�
+            int duration = route.getInteger("duration"); // 鏃堕暱锛屽崟浣嶏細绉�
+            
+            logger.info("璁$畻鎴愬姛: 璺濈={}绫�, 鏃堕暱={}绉�", distance, duration);
+            
+            // 鏋勫缓杩斿洖缁撴灉
+            Map<String, Object> resultMap = new HashMap<>();
+            resultMap.put("distance", distance); // 璺濈锛堢背锛�
+            resultMap.put("duration", duration); // 鏃堕暱锛堢锛�
+            resultMap.put("distanceKm", String.format("%.1f", distance / 1000.0)); // 璺濈锛堝叕閲岋級
+            resultMap.put("durationMin", duration / 60); // 鏃堕暱锛堝垎閽燂級
+            
+            // 璧风偣鍧愭爣
+            Map<String, Object> fromLocation = new HashMap<>();
+            fromLocation.put("lat", fromLat);
+            fromLocation.put("lng", fromLng);
+            resultMap.put("fromLocation", fromLocation);
+            
+            // 缁堢偣鍧愭爣
+            Map<String, Object> toLocation = new HashMap<>();
+            toLocation.put("lat", toLat);
+            toLocation.put("lng", toLng);
+            resultMap.put("toLocation", toLocation);
+            
+            return AjaxResult.success("璁$畻鎴愬姛", resultMap);
         } catch (Exception e) {
             logger.error("璁$畻鍦板潃璺濈澶辫触", e);
             return AjaxResult.error("璁$畻璺濈澶辫触锛�" + e.getMessage());
         }
     }
+    
+    /**
+     * 鐧惧害鍦板浘鍦板潃鎼滅储鎻愮ずAPI锛堣緭鍏ヨ仈鎯筹級
+     * Place Suggestion API - 鐢ㄤ簬鍦板潃杈撳叆鏃剁殑鏅鸿兘鎻愮ず
+     */
+    @Anonymous()
+    @GetMapping("/baidu/place/suggestion")
+    public AjaxResult baiduPlaceSuggestion(String query, String region) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (query == null || query.trim().isEmpty()) {
+                return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鎼滅储鍏抽敭璇�");
+            }
+            
+            // 鏋勫缓鐧惧害鍦板浘 Place Suggestion API URL
+            String url = "https://api.map.baidu.com/place/v2/suggestion";
+            String params = "query=" + URLEncoder.encode(query, StandardCharsets.UTF_8.toString()) +
+                           (region != null && !region.trim().isEmpty() ? 
+                            "&region=" + URLEncoder.encode(region, StandardCharsets.UTF_8.toString()) : "") +
+                           "&output=json" +
+                           "&ak=" + baiduMapConfig.getAk();
+            
+            logger.info("鐧惧害鍦板浘鍦板潃鎼滅储鎻愮ず璇锋眰: query={}, region={}", query, region);
+            
+            // 鍙戦�丠TTP璇锋眰
+            String response = HttpUtils.sendGet(url, params);
+            logger.debug("鐧惧害鍦板浘鍦板潃鎼滅储鎻愮ず鍝嶅簲: {}", response);
+            
+            // 瑙f瀽鍝嶅簲
+            com.alibaba.fastjson2.JSONObject jsonResponse = com.alibaba.fastjson2.JSONObject.parseObject(response);
+            if (jsonResponse.getInteger("status") != 0) {
+                logger.error("鍦板潃鎼滅储鎻愮ず澶辫触: {}", response);
+                return AjaxResult.error("鍦板潃鎼滅储澶辫触");
+            }
+            
+            // 鎻愬彇鎻愮ず鍒楄〃
+            com.alibaba.fastjson2.JSONArray results = jsonResponse.getJSONArray("result");
+            if (results == null || results.isEmpty()) {
+                logger.info("鏈壘鍒板尮閰嶇殑鍦板潃");
+                return AjaxResult.success("鏌ヨ鎴愬姛", new ArrayList<>());
+            }
+            
+            // 鏋勫缓杩斿洖缁撴灉
+            List<Map<String, Object>> suggestions = new ArrayList<>();
+            for (int i = 0; i < results.size(); i++) {
+                com.alibaba.fastjson2.JSONObject item = results.getJSONObject(i);
+                
+                Map<String, Object> suggestion = new HashMap<>();
+                suggestion.put("name", item.getString("name")); // 鍚嶇О
+                suggestion.put("address", item.getString("address")); // 鍦板潃
+                suggestion.put("province", item.getString("province")); // 鐪�
+                suggestion.put("city", item.getString("city")); // 甯�
+                suggestion.put("district", item.getString("district")); // 鍖�
+                suggestion.put("uid", item.getString("uid")); // 鍦扮偣UID
+                
+                // 缁忕含搴︿俊鎭�
+                com.alibaba.fastjson2.JSONObject location = item.getJSONObject("location");
+                if (location != null) {
+                    Map<String, Object> locationMap = new HashMap<>();
+                    locationMap.put("lat", location.getDouble("lat"));
+                    locationMap.put("lng", location.getDouble("lng"));
+                    suggestion.put("location", locationMap);
+                }
+                
+                suggestions.add(suggestion);
+            }
+            
+            logger.info("鍦板潃鎼滅储鎻愮ず鎴愬姛: 鎵惧埌{}  鏉$粨鏋�", suggestions.size());
+            return AjaxResult.success("鏌ヨ鎴愬姛", suggestions);
+        } catch (Exception e) {
+            logger.error("鍦板潃鎼滅储鎻愮ず澶辫触", e);
+            return AjaxResult.error("鍦板潃鎼滅储澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    // ==================== 澶╁湴鍥炬帴鍙� ====================
+    
+    /**
+     * 澶╁湴鍥惧湴鐞嗙紪鐮佹帴鍙d唬鐞嗭紙鍦板潃杞潗鏍囷級
+     * 鏂囨。锛歨ttps://lbs.tianditu.gov.cn/server/geocoding.html
+     */
+    @Anonymous()
+    @GetMapping("/tianditu/geocoding")
+    public AjaxResult tiandituGeocoding(String address) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            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);
+            
+            // 杩斿洖缁撴灉
+            return AjaxResult.success("鏌ヨ鎴愬姛", response);
+        } catch (Exception e) {
+            logger.error("澶╁湴鍥惧湴鐞嗙紪鐮佸け璐�", e);
+            return AjaxResult.error("鍦扮悊缂栫爜澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佹帴鍙d唬鐞嗭紙鍧愭爣杞湴鍧�锛�
+     * 鏂囨。锛歨ttps://lbs.tianditu.gov.cn/server/geocoding.html
+     */
+    @Anonymous()
+    @GetMapping("/tianditu/reverseGeocoding")
+    public AjaxResult tiandituReverseGeocoding(Double lon, Double lat) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (lat == null || lon == null) {
+                return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯缁忕含搴﹀潗鏍�");
+            }
+            
+            // 妫�鏌ュ弬鏁版湁鏁堟��
+            if (Double.isNaN(lat) || Double.isNaN(lon) || 
+                Double.isInfinite(lat) || Double.isInfinite(lon)) {
+                return AjaxResult.error("鍙傛暟鏃犳晥锛岀粡绾害鍧愭爣鏍煎紡閿欒");
+            }
+            
+            // 鏋勫缓澶╁湴鍥鹃�嗗湴鐞嗙紪鐮丄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);
+            
+            // 杩斿洖缁撴灉
+            return AjaxResult.success("鏌ヨ鎴愬姛", response);
+        } catch (Exception e) {
+            logger.error("澶╁湴鍥鹃�嗗湴鐞嗙紪鐮佸け璐�: lon={}, lat={}", lon, lat, e);
+            return AjaxResult.error("閫嗗湴鐞嗙紪鐮佸け璐ワ細" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 澶╁湴鍥惧湴鐐规悳绱㈡帴鍙d唬鐞嗭紙POI鎼滅储锛�
+     * 鏂囨。锛歨ttps://lbs.tianditu.gov.cn/server/search.html
+     */
+    @Anonymous()
+    @GetMapping("/tianditu/place/search")
+    public AjaxResult tiandituPlaceSearch(String keyWord, String queryType, String level, 
+                                          String mapBound, Integer start, Integer count) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (keyWord == null || keyWord.trim().isEmpty()) {
+                return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鎼滅储鍏抽敭璇�");
+            }
+            
+            // 璁剧疆榛樿鍊�
+            if (queryType == null || queryType.trim().isEmpty()) {
+                queryType = "1"; // 1-鏅�氭悳绱紝7-鍛ㄨ竟鎼滅储
+            }
+            if (start == null) {
+                start = 0;
+            }
+            if (count == null) {
+                count = 10;
+            }
+            
+            // 鏋勫缓澶╁湴鍥綪OI鎼滅储API URL
+            String url = "http://api.tianditu.gov.cn/search";
+            StringBuilder paramsBuilder = new StringBuilder();
+            paramsBuilder.append("postStr={\"keyWord\":\"").append(keyWord).append("\"");
+            paramsBuilder.append(",\"queryType\":\"").append(queryType).append("\"");
+            if (level != null && !level.trim().isEmpty()) {
+                paramsBuilder.append(",\"level\":\"").append(level).append("\"");
+            }
+            if (mapBound != null && !mapBound.trim().isEmpty()) {
+                paramsBuilder.append(",\"mapBound\":\"").append(mapBound).append("\"");
+            }
+            paramsBuilder.append(",\"start\":\"").append(start).append("\"");
+            paramsBuilder.append(",\"count\":\"").append(count).append("\"");
+            paramsBuilder.append("}" );
+            paramsBuilder.append("&type=query");
+            paramsBuilder.append("&tk=").append(tiandituMapConfig.getTk());
+            
+            String params = paramsBuilder.toString();
+            
+            logger.info("澶╁湴鍥綪OI鎼滅储璇锋眰: keyWord={}, queryType={}", keyWord, queryType);
+            
+            // 鍙戦�丠TTP璇锋眰
+            String response = HttpUtils.sendGet(url, params);
+            
+            // 杩斿洖缁撴灉
+            return AjaxResult.success("鏌ヨ鎴愬姛", response);
+        } catch (Exception e) {
+            logger.error("澶╁湴鍥綪OI鎼滅储澶辫触", e);
+            return AjaxResult.error("POI鎼滅储澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 澶╁湴鍥捐矾绾胯鍒掓帴鍙d唬鐞嗭紙椹捐溅璺緞瑙勫垝锛�
+     * 鏂囨。锛歨ttps://lbs.tianditu.gov.cn/server/drive.html
+     */
+    @Anonymous()
+    @GetMapping("/tianditu/route/driving")
+    public AjaxResult tiandituRouteDriving(String orig, String dest, String mid, String style) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (orig == null || orig.trim().isEmpty() || 
+                dest == null || dest.trim().isEmpty()) {
+                return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯璧风偣鎴栫粓鐐瑰潗鏍�");
+            }
+            
+            // 楠岃瘉鍧愭爣鏍煎紡锛堢粡搴�,绾害锛�
+            String[] origParts = orig.split(",");
+            String[] destParts = dest.split(",");
+            if (origParts.length != 2 || destParts.length != 2) {
+                return AjaxResult.error("鍧愭爣鏍煎紡閿欒锛屽簲涓猴細缁忓害,绾害");
+            }
+            
+            // 璁剧疆榛樿鍊�
+            if (style == null || style.trim().isEmpty()) {
+                style = "0"; // 0-鎺ㄨ崘锛�1-閬垮紑楂橀��
+            }
+            
+            // 鏋勫缓澶╁湴鍥鹃┚杞﹁矾寰勮鍒扐PI URL
+            String url = "http://api.tianditu.gov.cn/drive";
+            StringBuilder paramsBuilder = new StringBuilder();
+            paramsBuilder.append("postStr={\"orig\":\"").append(orig).append("\"");
+            paramsBuilder.append(",\"dest\":\"").append(dest).append("\"");
+            if (mid != null && !mid.trim().isEmpty()) {
+                paramsBuilder.append(",\"mid\":\"").append(mid).append("\"");
+            }
+            paramsBuilder.append(",\"style\":\"").append(style).append("\"");
+            paramsBuilder.append("}" );
+            paramsBuilder.append("&tk=").append(tiandituMapConfig.getTk());
+            
+            String params = paramsBuilder.toString();
+            
+            logger.info("澶╁湴鍥鹃┚杞﹁矾寰勮鍒掕姹�: orig={}, dest={}", orig, dest);
+            
+            // 鍙戦�丠TTP璇锋眰
+            String response = HttpUtils.sendGet(url, params);
+            
+            // 杩斿洖缁撴灉
+            return AjaxResult.success("璁$畻鎴愬姛", response);
+        } catch (Exception e) {
+            logger.error("澶╁湴鍥鹃┚杞﹁矾寰勮鍒掑け璐�", e);
+            return AjaxResult.error("璺緞瑙勫垝澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 澶╁湴鍥捐绠椾袱涓湴鍧�涔嬮棿鐨勮窛绂伙紙缁勫悎鎺ュ彛锛氬湴鍧�杞潗鏍� + 璺緞瑙勫垝锛�
+     */
+    @Anonymous()
+    @GetMapping("/tianditu/distance/byAddress")
+    public AjaxResult tiandituDistanceByAddress(String fromAddress, String toAddress) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (fromAddress == null || fromAddress.trim().isEmpty() || 
+                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");
+            logger.info("缁堢偣鍧愭爣: lon={}, lat={}", toLon, toLat);
+            
+            // 绗笁姝ワ細璋冪敤璺緞瑙勫垝鎺ュ彛璁$畻璺濈
+            String routeUrl = "http://api.tianditu.gov.cn/drive";
+            String orig = fromLon + "," + fromLat;
+            String dest = toLon + "," + toLat;
+            String routeParams = "postStr={\"orig\":\"" + orig + "\",\"dest\":\"" + dest + "\",\"style\":\"0\"}" +
+                                "&tk=" + tiandituMapConfig.getTk();
+            
+            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("璺緞瑙勫垝澶辫触");
+            }
+            
+            // 鎻愬彇璺濈淇℃伅
+            com.alibaba.fastjson2.JSONObject result = routeJson.getJSONObject("result");
+            if (result == null) {
+                logger.error("璺緞瑙勫垝缁撴灉涓虹┖");
+                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());
+        }
+    }
+    
+    /**
+     * 澶╁湴鍥捐緭鍏ユ彁绀烘帴鍙d唬鐞嗭紙鍦板潃鑱旀兂锛�
+     * 鏂囨。锛歨ttps://lbs.tianditu.gov.cn/server/suggestion.html
+     */
+    @Anonymous()
+    @GetMapping("/tianditu/place/suggestion")
+    public AjaxResult tiandituPlaceSuggestion(String keyWord, String region, String city, Integer count) {
+        try {
+            // 妫�鏌ュ弬鏁�
+            if (keyWord == null || keyWord.trim().isEmpty()) {
+                return AjaxResult.error("鍙傛暟涓嶅畬鏁达紝缂哄皯鎼滅储鍏抽敭璇�");
+            }
+            
+            // 璁剧疆榛樿鍊�
+            if (count == null) {
+                count = 10;
+            }
+            
+            // 鏋勫缓澶╁湴鍥捐緭鍏ユ彁绀篈PI URL
+            String url = "http://api.tianditu.gov.cn/search";
+            StringBuilder paramsBuilder = new StringBuilder();
+            paramsBuilder.append("postStr={\"keyWord\":\"").append(keyWord).append("\"");
+            if (region != null && !region.trim().isEmpty()) {
+                paramsBuilder.append(",\"region\":\"").append(region).append("\"");
+            }
+            if (city != null && !city.trim().isEmpty()) {
+                paramsBuilder.append(",\"city\":\"").append(city).append("\"");
+            }
+            paramsBuilder.append(",\"count\":\"").append(count).append("\"");
+            paramsBuilder.append("}" );
+            paramsBuilder.append("&type=suggest");
+            paramsBuilder.append("&tk=").append(tiandituMapConfig.getTk());
+            
+            String params = paramsBuilder.toString();
+            
+            logger.info("澶╁湴鍥捐緭鍏ユ彁绀鸿姹�: keyWord={}, region={}", keyWord, region);
+            
+            // 鍙戦�丠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);
+                return AjaxResult.error("鍦板潃鎼滅储澶辫触");
+            }
+            
+            // 鎻愬彇鎻愮ず鍒楄〃
+            com.alibaba.fastjson2.JSONArray results = jsonResponse.getJSONArray("suggests");
+            if (results == null || results.isEmpty()) {
+                logger.info("鏈壘鍒板尮閰嶇殑鍦板潃");
+                return AjaxResult.success("鏌ヨ鎴愬姛", new ArrayList<>());
+            }
+            
+            // 鏋勫缓杩斿洖缁撴灉
+            List<Map<String, Object>> suggestions = new ArrayList<>();
+            for (int i = 0; i < results.size(); i++) {
+                com.alibaba.fastjson2.JSONObject item = results.getJSONObject(i);
+                
+                Map<String, Object> suggestion = new HashMap<>();
+                suggestion.put("name", item.getString("name")); // 鍚嶇О
+                suggestion.put("address", item.getString("address")); // 鍦板潃
+                suggestion.put("province", item.getString("province")); // 鐪�
+                suggestion.put("city", item.getString("city")); // 甯�
+                suggestion.put("district", item.getString("district")); // 鍖�
+                
+                // 缁忕含搴︿俊鎭�
+                com.alibaba.fastjson2.JSONObject location = item.getJSONObject("location");
+                if (location != null) {
+                    Map<String, Object> locationMap = new HashMap<>();
+                    locationMap.put("lon", location.getDouble("lon"));
+                    locationMap.put("lat", location.getDouble("lat"));
+                    suggestion.put("location", locationMap);
+                }
+                
+                suggestions.add(suggestion);
+            }
+            
+            logger.info("鍦板潃鎼滅储鎻愮ず鎴愬姛: 鎵惧埌{}鏉$粨鏋�", suggestions.size());
+            return AjaxResult.success("鏌ヨ鎴愬姛", suggestions);
+        } catch (Exception e) {
+            logger.error("鍦板潃鎼滅储鎻愮ず澶辫触", e);
+            return AjaxResult.error("鍦板潃鎼滅储澶辫触锛�" + e.getMessage());
+        }
+    }
 }
\ No newline at end of file

--
Gitblit v1.9.1