# 百度地图距离计算接口说明 ## 功能概述 实现了百度地图的两个核心距离计算功能: 1. **计算两个坐标之间的距离** - 直接使用经纬度坐标计算驾车距离 2. **计算两个地址之间的距离** - 先将地址转换为坐标,再计算距离 ## 技术架构 - **后端**: Spring Boot + 百度地图API - **前端**: Uniapp + 封装的API调用方法 - **配置**: 支持动态配置百度地图API Key ## 配置说明 ### 1. 配置百度地图API Key 在 `ruoyi-admin/src/main/resources/application.yml` 中配置: ```yaml # 百度地图配置 baidu: map: ak: YOUR_BAIDU_MAP_AK_HERE # 请替换为您的百度地图API Key ``` **获取API Key步骤**: 1. 访问百度地图开放平台: https://lbsyun.baidu.com/ 2. 注册/登录账号 3. 进入控制台 -> 应用管理 -> 我的应用 4. 创建应用,选择"服务端"类型 5. 获取 AK (Access Key) ### 2. 配置文件说明 - **配置类**: `com.ruoyi.common.config.BaiduMapConfig` - **Controller**: `com.ruoyi.web.controller.system.VehicleGpsController` - **前端API**: `app/api/map.js` ## 接口详情 ### 接口一: 计算两个坐标之间的距离 #### 后端接口 **接口地址**: `/system/gps/baidu/route/driving` **请求方式**: GET **请求参数**: | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | origin | String | 是 | 起点坐标(纬度,经度) | 40.056878,116.30815 | | destination | String | 是 | 终点坐标(纬度,经度) | 31.222965,121.505821 | **请求示例**: ``` GET /system/gps/baidu/route/driving?origin=40.056878,116.30815&destination=31.222965,121.505821 ``` **响应示例**: ```json { "code": 200, "msg": "计算成功", "data": { "status": 0, "message": "ok", "result": { "routes": [{ "distance": 1213000, // 距离(米) "duration": 43920, // 时间(秒) "steps": [...] }] } } } ``` #### 前端调用 ```javascript import { baiduRouteDriving } from '@/api/map' // 调用示例 baiduRouteDriving('40.056878,116.30815', '31.222965,121.505821') .then(response => { console.log('距离计算结果:', response) // 解析返回数据 const result = JSON.parse(response.data) if (result.status === 0) { const distance = result.result.routes[0].distance // 距离(米) const distanceKm = (distance / 1000).toFixed(2) // 转换为公里 console.log('行驶距离:', distanceKm + ' 公里') } }) .catch(error => { console.error('距离计算失败:', error) }) ``` ### 接口二: 地理编码 (地址转坐标) #### 后端接口 **接口地址**: `/system/gps/baidu/geocoding` **请求方式**: GET **请求参数**: | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | address | String | 是 | 待解析的地址 | 广州市天河区天河路 | | city | String | 否 | 地址所在城市 | 广州市 | **请求示例**: ``` GET /system/gps/baidu/geocoding?address=广州市天河区天河路&city=广州市 ``` **响应示例**: ```json { "code": 200, "msg": "查询成功", "data": { "status": 0, "result": { "location": { "lng": 113.331053, // 经度 "lat": 23.137883 // 纬度 }, "precise": 1, "confidence": 80, "comprehension": 100, "level": "道路" } } } ``` #### 前端调用 ```javascript import { baiduGeocoding } from '@/api/map' // 调用示例 baiduGeocoding('广州市天河区天河路', '广州市') .then(response => { console.log('地理编码结果:', response) const result = JSON.parse(response.data) if (result.status === 0) { const lng = result.result.location.lng // 经度 const lat = result.result.location.lat // 纬度 console.log('坐标:', lat + ',' + lng) } }) .catch(error => { console.error('地理编码失败:', error) }) ``` ### 接口三: 计算两个地址之间的距离 (组合接口) #### 后端接口 **接口地址**: `/system/gps/baidu/distance/byAddress` **请求方式**: GET **请求参数**: | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | fromAddress | String | 是 | 起点地址 | 广州市天河区天河路 | | fromCity | String | 否 | 起点所在城市 | 广州市 | | toAddress | String | 是 | 终点地址 | 广州市越秀区中山路 | | toCity | String | 否 | 终点所在城市 | 广州市 | **请求示例**: ``` GET /system/gps/baidu/distance/byAddress?fromAddress=广州市天河区天河路&fromCity=广州市&toAddress=广州市越秀区中山路&toCity=广州市 ``` **响应示例**: ```json { "code": 200, "msg": "地理编码成功", "data": { "fromGeocoding": "{...}", // 起点地理编码结果 "toGeocoding": "{...}", // 终点地理编码结果 "message": "请解析坐标后调用 /baidu/route/driving 接口计算距离" } } ``` #### 前端调用 (完整流程) ```javascript import { baiduDistanceByAddress, baiduRouteDriving } from '@/api/map' /** * 计算两个地址之间的驾车距离 */ async function calculateAddressDistance(fromAddr, fromCity, toAddr, toCity) { try { // 第一步: 获取两个地址的坐标 const geocodingResult = await baiduDistanceByAddress(fromAddr, fromCity, toAddr, toCity) // 解析起点坐标 const fromGeo = JSON.parse(geocodingResult.data.fromGeocoding) if (fromGeo.status !== 0) { throw new Error('起点地址解析失败') } const fromLat = fromGeo.result.location.lat const fromLng = fromGeo.result.location.lng // 解析终点坐标 const toGeo = JSON.parse(geocodingResult.data.toGeocoding) if (toGeo.status !== 0) { throw new Error('终点地址解析失败') } const toLat = toGeo.result.location.lat const toLng = toGeo.result.location.lng // 第二步: 计算两点间距离 const origin = fromLat + ',' + fromLng const destination = toLat + ',' + toLng const routeResult = await baiduRouteDriving(origin, destination) // 解析距离 const route = JSON.parse(routeResult.data) if (route.status === 0) { const distance = route.result.routes[0].distance // 距离(米) const distanceKm = (distance / 1000).toFixed(2) // 转换为公里 console.log('行驶距离:', distanceKm + ' 公里') return distanceKm } else { throw new Error('距离计算失败') } } catch (error) { console.error('计算地址距离失败:', error) throw error } } // 使用示例 calculateAddressDistance( '广州市天河区天河路', '广州市', '广州市越秀区中山路', '广州市' ).then(distance => { console.log('最终距离:', distance + ' 公里') }) ``` ## 使用场景 ### 场景一: 任务创建时自动计算距离 在创建急救转运任务时,根据起点和终点地址自动计算行驶距离: ```javascript // 在任务表单中监听地址变化 watch(['startAddress', 'endAddress'], async () => { if (startAddress && endAddress) { try { const distance = await calculateAddressDistance( startAddress, startCity, endAddress, endCity ) // 自动填充距离字段 form.distance = distance } catch (error) { console.error('自动计算距离失败', error) } } }) ``` ### 场景二: 地图选点后计算距离 用户在地图上选择起点和终点后,自动计算距离: ```javascript // 地图选点回调 onMapPointSelected(point) { if (point.type === 'start') { this.startLat = point.lat this.startLng = point.lng } else { this.endLat = point.lat this.endLng = point.lng } // 两个点都选择后计算距离 if (this.startLat && this.endLat) { const origin = this.startLat + ',' + this.startLng const destination = this.endLat + ',' + this.endLng baiduRouteDriving(origin, destination).then(res => { const result = JSON.parse(res.data) if (result.status === 0) { const distance = (result.result.routes[0].distance / 1000).toFixed(2) this.form.distance = distance } }) } } ``` ## 注意事项 ### 1. 坐标系统 - 百度地图使用 **BD-09 坐标系** (百度坐标) - 如果您的数据是其他坐标系(如 GPS、高德),需要进行坐标转换 - 腾讯地图使用 GCJ-02 坐标系(火星坐标) ### 2. 坐标格式 - **百度地图**: 纬度在前,经度在后 (lat,lng) - **腾讯地图**: 纬度在前,经度在后 (lat,lng) - 请求时注意顺序: `"纬度,经度"` ### 3. 错误处理 百度地图API返回的状态码说明: - `status: 0` - 成功 - `status: 1` - 服务器内部错误 - `status: 2` - 请求参数非法 - `status: 3` - 权限校验失败 - `status: 4` - 配额校验失败 - `status: 5` - AK不存在或非法 ### 4. API配额限制 - 百度地图API有每日调用次数限制 - 免费版通常为 10万次/天 - 建议做好缓存,避免重复计算相同路线 ### 5. 距离单位 - API返回的距离单位是 **米(m)** - 前端显示时建议转换为 **公里(km)** - 转换公式: `distanceKm = distance / 1000` ## 对比: 百度地图 vs 腾讯地图 | 功能 | 百度地图 | 腾讯地图 | |------|----------|----------| | 坐标系 | BD-09 | GCJ-02 | | 地理编码 | /geocoding/v3/ | /geocoder/v1/ | | 路线规划 | /directionlite/v1/driving | /distance/v1/ | | 参数格式 | origin=lat,lng | from=lat,lng | | 免费配额 | 10万次/天 | 10万次/天 | ## 测试建议 ### 1. 单元测试 建议创建测试用例验证接口功能: ```java @Test public void testBaiduRouteDriving() { // 北京到上海的距离 String origin = "40.056878,116.30815"; String destination = "31.222965,121.505821"; AjaxResult result = controller.baiduRouteDriving(origin, destination); assertEquals(200, result.get("code")); } ``` ### 2. 接口测试 使用 Postman 或浏览器测试: ``` GET http://localhost:8080/system/gps/baidu/route/driving?origin=40.056878,116.30815&destination=31.222965,121.505821 ``` ### 3. 前端测试 在浏览器控制台测试: ```javascript import { baiduRouteDriving } from '@/api/map' baiduRouteDriving('40.056878,116.30815', '31.222965,121.505821') .then(res => console.log(res)) .catch(err => console.error(err)) ``` ## 常见问题 ### Q1: API返回 status: 3 (权限校验失败) **原因**: API Key 配置错误或未授权该接口 **解决方案**: 1. 检查 application.yml 中的 AK 是否正确 2. 登录百度地图控制台,检查应用是否启用了对应服务 3. 确认IP白名单设置(如有) ### Q2: 计算的距离与实际不符 **原因**: 可能是坐标系不匹配 **解决方案**: 1. 确认输入坐标是百度坐标系(BD-09) 2. 如是其他坐标系,需先进行坐标转换 3. 检查坐标顺序是否正确(纬度,经度) ### Q3: 地址解析失败 **原因**: 地址不够准确或格式不规范 **解决方案**: 1. 提供更详细的地址信息 2. 指定所在城市参数 3. 使用标准地址格式 ## 扩展功能 ### 1. 支持多种出行方式 可以扩展接口支持步行、骑行、公交等: ```java @GetMapping("/baidu/route/{mode}") public AjaxResult baiduRoute(@PathVariable String mode, String origin, String destination) { // mode: driving(驾车), walking(步行), riding(骑行), transit(公交) String url = "https://api.map.baidu.com/directionlite/v1/" + mode; // ... } ``` ### 2. 返回详细路径信息 除了距离,还可以返回路径详情、途经点等: ```javascript // 解析完整路线信息 const route = result.result.routes[0] console.log('距离:', route.distance, '米') console.log('预计时间:', route.duration, '秒') console.log('路线详情:', route.steps) ``` ### 3. 批量计算距离 如需计算多个地点间的距离,可以使用批量接口: ```java @PostMapping("/baidu/route/batch") public AjaxResult baiduRouteBatch(@RequestBody List requests) { // 批量计算多个路线的距离 } ``` ## 相关文档 - [百度地图开放平台](https://lbsyun.baidu.com/) - [百度地图Web服务API](https://lbsyun.baidu.com/index.php?title=webapi) - [路线规划API文档](https://lbsyun.baidu.com/index.php?title=webapi/direction-api-v2) - [地理编码API文档](https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding) ## 更新日志 ### v1.0 (2025-10-21) - ✅ 实现百度地图地理编码接口(地址转坐标) - ✅ 实现百度地图路线规划接口(坐标计算距离) - ✅ 实现组合接口(地址计算距离) - ✅ 添加前端API封装 - ✅ 添加配置文件支持 - ✅ 完善参数验证和错误处理 --- **开发者**: AI Assistant **文档创建时间**: 2025-10-21 **最后更新时间**: 2025-10-21