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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; /** * 天地图服务实现 * * @author ruoyi */ @Service("tiandituMapService") public class TiandituMapServiceImpl implements IMapService { private static final Logger logger = LoggerFactory.getLogger(TiandituMapServiceImpl.class); @Autowired private TiandituMapConfig tiandituMapConfig; /** * 地址转GPS坐标(地理编码) * * @param address 地址 * @param city 城市(可选,用于提高解析准确性) * @return GPS坐标,包含lng和lat,如果获取失败返回null */ @Override public Map geocoding(String address, String city) { // 如果地址为空,直接返回null if (address == null || address.trim().isEmpty()) { return null; } if(address.indexOf(",")>0){ String[] split = address.split(","); address=split[0]; } if(address.indexOf(",")>0){ String[] split = address.split(","); address=split[0]; } try { // 构建天地图地理编码API URL String url = "http://api.tianditu.gov.cn/geocoder"; String params = "ds=" + URLEncoder.encode("{\"keyWord\":\"" + address + "\"}", StandardCharsets.UTF_8.toString()) + "&tk=" + tiandituMapConfig.getTk(); logger.info("天地图地理编码请求: address={}, city={}", address, city); // 发送HTTP请求 String response = HttpUtils.sendGet(url, params); // 解析响应 JSONObject jsonObject = JSONObject.parseObject(response); // 检查状态 if (jsonObject.getInteger("status") == null || jsonObject.getInteger("status") != 0) { logger.warn("天地图地理编码失败: address={}, status={}, msg={}", address, jsonObject.getInteger("status"), jsonObject.getString("msg")); return null; } JSONObject location = jsonObject.getJSONObject("location"); if (location == null) { logger.warn("天地图地理编码响应无location: address={}", address); return null; } double lng = location.getDouble("lon"); double lat = location.getDouble("lat"); logger.info("天地图地理编码成功: address={}, lng={}, lat={}", address, lng, lat); Map coordinates = new HashMap<>(); coordinates.put("lng", lng); coordinates.put("lat", lat); return coordinates; } catch (Exception e) { // 捕获所有异常,避免影响主流程 logger.error("天地图地理编码异常: address=" + address, e); return null; } } /** * 直接返回地址 * @param lng 经度 * @param lat 纬度 * @return */ @Override public String reverseGeocoding(double lng, double lat) { // 构建天地图逆地理编码API 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); // 发送HTTP请求 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"); } }