amapService.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /**
  2. * 高德地图服务模块
  3. * 提供地理编码和逆地理编码功能
  4. */
  5. /**
  6. * 使用高德地图逆地理编码API
  7. * 将经纬度坐标转换为地址信息
  8. *
  9. * @param {number} longitude - 经度
  10. * @param {number} latitude - 纬度
  11. * @returns {Promise<string>} 地址信息
  12. */
  13. export const amapReverseGeocode = async (longitude: number, latitude: number): Promise<string> => {
  14. try {
  15. const url = new URL('https://restapi.amap.com/v3/geocode/regeo')
  16. url.searchParams.append('location', `${longitude},${latitude}`)
  17. url.searchParams.append('key', '65bddc1c5df7d381507bc3ea3128b242')
  18. url.searchParams.append('radius', '1000')
  19. url.searchParams.append('extensions', 'base')
  20. url.searchParams.append('batch', 'false')
  21. const response = await fetch(url.toString())
  22. const data = await response.json()
  23. // 检查响应状态
  24. if (data.status === '1') {
  25. // 返回格式化的地址
  26. return data.regeocode?.formatted_address || '位置信息获取失败'
  27. } else {
  28. console.error('高德地图API错误:', data.info)
  29. return '位置信息获取失败'
  30. }
  31. } catch (error) {
  32. console.error('逆地理编码失败:', error)
  33. return '位置服务不可用'
  34. }
  35. }
  36. /**
  37. * 使用高德地图地理编码API
  38. * 将地址转换为经纬度坐标
  39. *
  40. * @param {string} address - 地址信息
  41. * @returns {Promise<{longitude: number, latitude: number} | null>} 坐标信息
  42. */
  43. export const amapGeocode = async (
  44. address: string
  45. ): Promise<{ longitude: number; latitude: number } | null> => {
  46. try {
  47. const url = new URL('https://restapi.amap.com/v3/geocode/geo')
  48. url.searchParams.append('address', address)
  49. url.searchParams.append('key', '65bddc1c5df7d381507bc3ea3128b242')
  50. url.searchParams.append('batch', 'false')
  51. url.searchParams.append('extensions', 'base')
  52. const response = await fetch(url.toString())
  53. const data = await response.json()
  54. if (data.status === '1' && data.geocodes && data.geocodes.length > 0) {
  55. const location = data.geocodes[0].location
  56. const [longitude, latitude] = location.split(',')
  57. return {
  58. longitude: parseFloat(longitude),
  59. latitude: parseFloat(latitude)
  60. }
  61. } else {
  62. console.error('地理编码API错误:', data.info)
  63. return null
  64. }
  65. } catch (error) {
  66. console.error('地理编码失败:', error)
  67. return null
  68. }
  69. }
  70. /**
  71. * 计算两个坐标点之间的距离(单位:米)
  72. * 使用 Haversine 公式
  73. *
  74. * @param {number} lon1 - 第一个点的经度
  75. * @param {number} lat1 - 第一个点的纬度
  76. * @param {number} lon2 - 第二个点的经度
  77. * @param {number} lat2 - 第二个点的纬度
  78. * @returns {number} 距离(米)
  79. */
  80. export const calculateDistance = (
  81. lon1: number,
  82. lat1: number,
  83. lon2: number,
  84. lat2: number
  85. ): number => {
  86. const R = 6371000 // 地球半径(米)
  87. const dLat = ((lat2 - lat1) * Math.PI) / 180
  88. const dLon = ((lon2 - lon1) * Math.PI) / 180
  89. const a =
  90. Math.sin(dLat / 2) * Math.sin(dLat / 2) +
  91. Math.cos((lat1 * Math.PI) / 180) *
  92. Math.cos((lat2 * Math.PI) / 180) *
  93. Math.sin(dLon / 2) *
  94. Math.sin(dLon / 2)
  95. const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
  96. return R * c
  97. }
  98. /**
  99. * 获取地址的详细信息
  100. * 包括省份、城市、区县等
  101. *
  102. * @param {number} longitude - 经度
  103. * @param {number} latitude - 纬度
  104. * @returns {Promise<any>} 详细地址信息
  105. */
  106. export const getAddressDetail = async (longitude: number, latitude: number): Promise<any> => {
  107. try {
  108. const url = new URL('https://restapi.amap.com/v3/geocode/regeo')
  109. url.searchParams.append('location', `${longitude},${latitude}`)
  110. url.searchParams.append('key', '65bddc1c5df7d381507bc3ea3128b242')
  111. url.searchParams.append('radius', '1000')
  112. url.searchParams.append('extensions', 'all')
  113. url.searchParams.append('batch', 'false')
  114. const response = await fetch(url.toString())
  115. const data = await response.json()
  116. if (data.status === '1') {
  117. return data.regeocode
  118. } else {
  119. console.error('获取地址详情失败:', data.info)
  120. return null
  121. }
  122. } catch (error) {
  123. console.error('获取地址详情异常:', error)
  124. return null
  125. }
  126. }