编辑 | blame | 历史 | 原始文档

百度地图距离计算接口说明

功能概述

实现了百度地图的两个核心距离计算功能:
1. 计算两个坐标之间的距离 - 直接使用经纬度坐标计算驾车距离
2. 计算两个地址之间的距离 - 先将地址转换为坐标,再计算距离

技术架构

  • 后端: Spring Boot + 百度地图API
  • 前端: Uniapp + 封装的API调用方法
  • 配置: 支持动态配置百度地图API Key

配置说明

1. 配置百度地图API Key

ruoyi-admin/src/main/resources/application.yml 中配置:

# 百度地图配置
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": [...] }] } } }

前端调用

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": "道路" } } }

前端调用

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 接口计算距离" } }

前端调用 (完整流程)

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 + ' 公里')
})

使用场景

场景一: 任务创建时自动计算距离

在创建急救转运任务时,根据起点和终点地址自动计算行驶距离:

// 在任务表单中监听地址变化
watch(['startAddress', 'endAddress'], async () => {
  if (startAddress && endAddress) {
    try {
      const distance = await calculateAddressDistance(
        startAddress, startCity,
        endAddress, endCity
      )
      // 自动填充距离字段
      form.distance = distance
    } catch (error) {
      console.error('自动计算距离失败', error)
    }
  }
})

场景二: 地图选点后计算距离

用户在地图上选择起点和终点后,自动计算距离:

// 地图选点回调
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. 单元测试

建议创建测试用例验证接口功能:

@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. 前端测试

在浏览器控制台测试:

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. 支持多种出行方式

可以扩展接口支持步行、骑行、公交等:

@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. 返回详细路径信息

除了距离,还可以返回路径详情、途经点等:

// 解析完整路线信息
const route = result.result.routes[0]
console.log('距离:', route.distance, '米')
console.log('预计时间:', route.duration, '秒')
console.log('路线详情:', route.steps)

3. 批量计算距离

如需计算多个地点间的距离,可以使用批量接口:

@PostMapping("/baidu/route/batch")
public AjaxResult baiduRouteBatch(@RequestBody List<RouteRequest> requests) {
    // 批量计算多个路线的距离
}

相关文档

更新日志

v1.0 (2025-10-21)

  • ✅ 实现百度地图地理编码接口(地址转坐标)
  • ✅ 实现百度地图路线规划接口(坐标计算距离)
  • ✅ 实现组合接口(地址计算距离)
  • ✅ 添加前端API封装
  • ✅ 添加配置文件支持
  • ✅ 完善参数验证和错误处理

开发者: AI Assistant
文档创建时间: 2025-10-21
最后更新时间: 2025-10-21