| | |
| | | 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.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | |
| | | |
| | | @Autowired |
| | | private TencentMapConfig tencentMapConfig; |
| | | |
| | | @Autowired |
| | | private BaiduMapConfig baiduMapConfig; |
| | | |
| | | @Autowired |
| | | private TiandituMapConfig tiandituMapConfig; |
| | | |
| | | /** |
| | | * 查询车辆GPS坐标列表 |
| | |
| | | return AjaxResult.error("距离计算失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 百度地图地理编码接口代理(地址转坐标) |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/baidu/geocoding") |
| | | public AjaxResult baiduGeocoding(String address, String city) { |
| | | try { |
| | | // 检查参数 |
| | | 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); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | |
| | | // 返回结果 |
| | | return AjaxResult.success("查询成功", response); |
| | | } catch (Exception e) { |
| | | logger.error("百度地图地理编码失败", e); |
| | | return AjaxResult.error("地理编码失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 百度地图路线规划接口代理(计算两个坐标之间的驾车距离) |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/baidu/route/driving") |
| | | public AjaxResult baiduRouteDriving(String origin, String destination) { |
| | | try { |
| | | // 检查参数 |
| | | if (origin == null || origin.trim().isEmpty() || |
| | | destination == null || destination.trim().isEmpty()) { |
| | | return AjaxResult.error("参数不完整,缺少起点或终点坐标"); |
| | | } |
| | | |
| | | // 验证坐标格式(纬度,经度) |
| | | String[] originParts = origin.split(","); |
| | | String[] destParts = destination.split(","); |
| | | if (originParts.length != 2 || destParts.length != 2) { |
| | | return AjaxResult.error("坐标格式错误,应为:纬度,经度"); |
| | | } |
| | | |
| | | // 构建百度地图路线规划API URL |
| | | String url = "https://api.map.baidu.com/directionlite/v1/driving"; |
| | | String params = "origin=" + origin + |
| | | "&destination=" + destination + |
| | | "&ak=" + baiduMapConfig.getAk(); |
| | | |
| | | logger.info("百度地图路线规划请求: origin={}, destination={}", origin, destination); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | |
| | | // 返回结果 |
| | | return AjaxResult.success("计算成功", response); |
| | | } catch (Exception e) { |
| | | logger.error("百度地图路线规划失败", e); |
| | | return AjaxResult.error("路线规划失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 百度地图计算两个地址之间的距离(组合接口:地址转坐标 + 路线规划) |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/baidu/distance/byAddress") |
| | | public AjaxResult baiduDistanceByAddress(String fromAddress, String fromCity, |
| | | String toAddress, String toCity) { |
| | | try { |
| | | // 检查参数 |
| | | if (fromAddress == null || fromAddress.trim().isEmpty() || |
| | | toAddress == null || toAddress.trim().isEmpty()) { |
| | | return AjaxResult.error("参数不完整,缺少起点或终点地址"); |
| | | } |
| | | |
| | | logger.info("开始计算地址距离: fromAddress={}, fromCity={}, toAddress={}, toCity={}", |
| | | fromAddress, fromCity, toAddress, toCity); |
| | | |
| | | // 第一步:起点地址转坐标 |
| | | String geocodingUrl1 = "https://api.map.baidu.com/geocoding/v3/"; |
| | | String geocodingParams1 = "address=" + URLEncoder.encode(fromAddress, StandardCharsets.UTF_8.toString()) + |
| | | (fromCity != null && !fromCity.trim().isEmpty() ? |
| | | "&city=" + URLEncoder.encode(fromCity, StandardCharsets.UTF_8.toString()) : "") + |
| | | "&output=json" + |
| | | "&ak=" + baiduMapConfig.getAk(); |
| | | |
| | | String geocodingResponse1 = HttpUtils.sendGet(geocodingUrl1, geocodingParams1); |
| | | logger.info("起点地理编码响应: {}", geocodingResponse1); |
| | | |
| | | // 解析起点坐标 |
| | | com.alibaba.fastjson2.JSONObject geocodingJson1 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse1); |
| | | if (geocodingJson1.getInteger("status") != 0) { |
| | | logger.error("起点地理编码失败: {}", geocodingResponse1); |
| | | return AjaxResult.error("起点地址解析失败"); |
| | | } |
| | | 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()) + |
| | | (toCity != null && !toCity.trim().isEmpty() ? |
| | | "&city=" + URLEncoder.encode(toCity, StandardCharsets.UTF_8.toString()) : "") + |
| | | "&output=json" + |
| | | "&ak=" + baiduMapConfig.getAk(); |
| | | |
| | | String geocodingResponse2 = HttpUtils.sendGet(geocodingUrl2, geocodingParams2); |
| | | logger.info("终点地理编码响应: {}", geocodingResponse2); |
| | | |
| | | // 解析终点坐标 |
| | | com.alibaba.fastjson2.JSONObject geocodingJson2 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse2); |
| | | if (geocodingJson2.getInteger("status") != 0) { |
| | | logger.error("终点地理编码失败: {}", geocodingResponse2); |
| | | return AjaxResult.error("终点地址解析失败"); |
| | | } |
| | | 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); |
| | | |
| | | // 第三步:调用路线规划接口计算距离 |
| | | 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); |
| | | |
| | | // 解析距离结果 |
| | | 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() ? |
| | | "®ion=" + URLEncoder.encode(region, StandardCharsets.UTF_8.toString()) : "") + |
| | | "&output=json" + |
| | | "&ak=" + baiduMapConfig.getAk(); |
| | | |
| | | logger.info("百度地图地址搜索提示请求: query={}, region={}", query, region); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | logger.debug("百度地图地址搜索提示响应: {}", response); |
| | | |
| | | // 解析响应 |
| | | 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()); |
| | | } |
| | | } |
| | | |
| | | // ==================== 天地图接口 ==================== |
| | | |
| | | /** |
| | | * 天地图地理编码接口代理(地址转坐标) |
| | | * 文档:https://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("参数不完整,缺少地址信息"); |
| | | } |
| | | |
| | | // 构建天地图地理编码API URL |
| | | String url = "http://api.tianditu.gov.cn/geocoder"; |
| | | String params = "ds={\"keyWord\":\"" + address + "\"}&tk=" + tiandituMapConfig.getTk(); |
| | | |
| | | logger.info("天地图地理编码请求: address={}", address); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | |
| | | // 返回结果 |
| | | return AjaxResult.success("查询成功", response); |
| | | } catch (Exception e) { |
| | | logger.error("天地图地理编码失败", e); |
| | | return AjaxResult.error("地理编码失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 天地图逆地理编码接口代理(坐标转地址) |
| | | * 文档:https://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("参数无效,经纬度坐标格式错误"); |
| | | } |
| | | |
| | | // 构建天地图逆地理编码API 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); |
| | | |
| | | // 发送HTTP请求 |
| | | 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()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 天地图地点搜索接口代理(POI搜索) |
| | | * 文档:https://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; |
| | | } |
| | | |
| | | // 构建天地图POI搜索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("天地图POI搜索请求: keyWord={}, queryType={}", keyWord, queryType); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | |
| | | // 返回结果 |
| | | return AjaxResult.success("查询成功", response); |
| | | } catch (Exception e) { |
| | | logger.error("天地图POI搜索失败", e); |
| | | return AjaxResult.error("POI搜索失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 天地图路线规划接口代理(驾车路径规划) |
| | | * 文档:https://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-避开高速 |
| | | } |
| | | |
| | | // 构建天地图驾车路径规划API 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); |
| | | |
| | | // 发送HTTP请求 |
| | | 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); |
| | | |
| | | // 解析起点坐标 |
| | | com.alibaba.fastjson2.JSONObject geocodingJson1 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse1); |
| | | if (!"0".equals(geocodingJson1.getString("status"))) { |
| | | logger.error("起点地理编码失败: {}", geocodingResponse1); |
| | | return AjaxResult.error("起点地址解析失败"); |
| | | } |
| | | 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); |
| | | |
| | | // 解析终点坐标 |
| | | com.alibaba.fastjson2.JSONObject geocodingJson2 = com.alibaba.fastjson2.JSONObject.parseObject(geocodingResponse2); |
| | | if (!"0".equals(geocodingJson2.getString("status"))) { |
| | | logger.error("终点地理编码失败: {}", geocodingResponse2); |
| | | return AjaxResult.error("终点地址解析失败"); |
| | | } |
| | | 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); |
| | | |
| | | // 解析距离结果 |
| | | 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()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 天地图输入提示接口代理(地址联想) |
| | | * 文档:https://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; |
| | | } |
| | | |
| | | // 构建天地图输入提示API 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); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | logger.debug("天地图输入提示响应: {}", response); |
| | | |
| | | // 解析响应 |
| | | 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()); |
| | | } |
| | | } |
| | | } |