| | |
| | | import java.util.*; |
| | | import java.text.SimpleDateFormat; |
| | | import java.text.ParseException; |
| | | import java.io.IOException; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | |
| | | import com.ruoyi.system.domain.*; |
| | | import com.ruoyi.system.service.*; |
| | | import com.ruoyi.common.config.TencentMapConfig; |
| | | import com.ruoyi.common.config.BaiduMapConfig; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | |
| | | import com.ruoyi.common.enums.BusinessType; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.common.core.page.TableDataInfo; |
| | | import com.ruoyi.common.utils.http.HttpUtils; |
| | | |
| | | /** |
| | | * 车辆GPS坐标Controller |
| | |
| | | |
| | | @Autowired |
| | | private ICmsGpsCollectService cmsGpsCollectService; |
| | | |
| | | @Autowired |
| | | private TencentMapConfig tencentMapConfig; |
| | | |
| | | @Autowired |
| | | private BaiduMapConfig baiduMapConfig; |
| | | |
| | | /** |
| | | * 查询车辆GPS坐标列表 |
| | |
| | | throw new Error("查询车辆轨迹失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 腾讯地图地址搜索接口代理 |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/address/search") |
| | | public AjaxResult searchAddress(String keyword, String region) { |
| | | try { |
| | | // 构建腾讯地图搜索API URL |
| | | String url = "https://apis.map.qq.com/ws/place/v1/search"; |
| | | String params = "keyword=" + URLEncoder.encode(keyword, StandardCharsets.UTF_8.toString()) + |
| | | "&boundary=region(" + (region != null ? region : "广州") + ")" + |
| | | "&key=" + tencentMapConfig.getKey(); |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | |
| | | // 返回结果 |
| | | return AjaxResult.success("查询成功", response); |
| | | } catch (Exception e) { |
| | | logger.error("地址搜索失败", e); |
| | | return AjaxResult.error("地址搜索失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 腾讯地图逆地址解析接口代理 |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/address/geocoder") |
| | | public AjaxResult reverseGeocoder(Double lat, Double lng) { |
| | | try { |
| | | // 检查参数 |
| | | logger.info("逆地址解析请求参数: lat={}, lng={}", lat, lng); |
| | | |
| | | if (lat == null || lng == null) { |
| | | logger.warn("参数不完整,缺少经纬度坐标: lat={}, lng={}", lat, lng); |
| | | return AjaxResult.error("参数不完整,缺少经纬度坐标"); |
| | | } |
| | | |
| | | // 检查参数有效性 |
| | | if (Double.isNaN(lat) || Double.isNaN(lng) || |
| | | Double.isInfinite(lat) || Double.isInfinite(lng)) { |
| | | logger.warn("参数无效,经纬度坐标包含非法值: lat={}, lng={}", lat, lng); |
| | | return AjaxResult.error("参数无效,经纬度坐标格式错误"); |
| | | } |
| | | |
| | | // 构建腾讯地图逆地址解析API URL |
| | | String url = "https://apis.map.qq.com/ws/geocoder/v1/"; |
| | | String params = "location=" + lat + "," + lng + |
| | | "&key=" + tencentMapConfig.getKey() + |
| | | "&get_poi=1"; |
| | | |
| | | // 发送HTTP请求 |
| | | String response = HttpUtils.sendGet(url, params); |
| | | |
| | | // 返回结果 |
| | | return AjaxResult.success("查询成功", response); |
| | | } catch (Exception e) { |
| | | logger.error("逆地址解析失败: lat={}, lng={}", lat, lng, e); |
| | | return AjaxResult.error("逆地址解析失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 腾讯地图路线规划接口代理(计算两点间距离) |
| | | */ |
| | | @Anonymous() |
| | | @GetMapping("/route/distance") |
| | | public AjaxResult calculateDistance(Double fromLat, Double fromLng, Double toLat, Double toLng) { |
| | | try { |
| | | // 检查参数 |
| | | if (fromLat == null || fromLng == null || toLat == null || toLng == null) { |
| | | return AjaxResult.error("参数不完整,缺少起点或终点坐标"); |
| | | } |
| | | |
| | | // 构建腾讯地图路线规划API URL |
| | | String url = "https://apis.map.qq.com/ws/distance/v1/"; |
| | | String params = "mode=driving" + |
| | | "&from=" + fromLat + "," + fromLng + |
| | | "&to=" + toLat + "," + toLng + |
| | | "&key=" + tencentMapConfig.getKey(); |
| | | |
| | | // 发送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/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); |
| | | |
| | | // 第二步:终点地址转坐标 |
| | | 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); |
| | | |
| | | // 解析坐标(这里简化处理,实际应该解析JSON) |
| | | // 注意:需要从响应中提取坐标,这里返回中间结果供前端处理 |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("fromGeocoding", geocodingResponse1); |
| | | result.put("toGeocoding", geocodingResponse2); |
| | | result.put("message", "请解析坐标后调用 /baidu/route/driving 接口计算距离"); |
| | | |
| | | return AjaxResult.success("地理编码成功", result); |
| | | } catch (Exception e) { |
| | | logger.error("计算地址距离失败", e); |
| | | return AjaxResult.error("计算距离失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | } |