location.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * 定位服务工具类
  3. * 提供获取当前位置、地址解析等功能
  4. */
  5. /**
  6. * 获取当前位置
  7. * @returns Promise<{latitude, longitude, address}>
  8. */
  9. export const getCurrentLocation = () => {
  10. return new Promise((resolve, reject) => {
  11. uni.showLoading({
  12. title: '正在获取位置...'
  13. });
  14. uni.getLocation({
  15. type: 'gcj02', // 使用国测局坐标系
  16. geocode: true, // 解析地址信息
  17. success: (res) => {
  18. console.log('📍 获取位置成功:', res);
  19. const locationData = {
  20. latitude: res.latitude,
  21. longitude: res.longitude,
  22. address: res.address || '位置信息获取中...'
  23. };
  24. // 如果没有地址信息,尝试逆地理编码
  25. if (!res.address) {
  26. reverseGeocode(res.latitude, res.longitude)
  27. .then(address => {
  28. locationData.address = address;
  29. resolve(locationData);
  30. })
  31. .catch(() => {
  32. locationData.address = `${res.latitude.toFixed(6)}, ${res.longitude.toFixed(6)}`;
  33. resolve(locationData);
  34. });
  35. } else {
  36. resolve(locationData);
  37. }
  38. },
  39. fail: (err) => {
  40. console.error('❌ 获取位置失败:', err);
  41. let errorMsg = '获取位置失败';
  42. if (err.errMsg) {
  43. if (err.errMsg.includes('auth deny')) {
  44. errorMsg = '位置权限被拒绝,请在设置中开启位置权限';
  45. } else if (err.errMsg.includes('locate fail')) {
  46. errorMsg = '定位失败,请检查网络连接和GPS设置';
  47. }
  48. }
  49. reject(new Error(errorMsg));
  50. },
  51. complete: () => {
  52. uni.hideLoading();
  53. }
  54. });
  55. });
  56. };
  57. /**
  58. * 逆地理编码 - 根据坐标获取地址
  59. * @param {number} latitude 纬度
  60. * @param {number} longitude 经度
  61. * @returns Promise<string>
  62. */
  63. export const reverseGeocode = (latitude, longitude) => {
  64. return new Promise((resolve, reject) => {
  65. // 这里可以调用第三方地图服务API进行逆地理编码
  66. // 暂时返回坐标信息
  67. const address = `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`;
  68. resolve(address);
  69. });
  70. };
  71. /**
  72. * 检查定位权限
  73. * @returns Promise<boolean>
  74. */
  75. export const checkLocationPermission = () => {
  76. return new Promise((resolve) => {
  77. // #ifdef APP-PLUS
  78. const permissions = ['android.permission.ACCESS_FINE_LOCATION'];
  79. plus.android.requestPermissions(permissions, (result) => {
  80. resolve(result.granted && result.granted.length > 0);
  81. }, (error) => {
  82. console.error('权限检查失败:', error);
  83. resolve(false);
  84. });
  85. // #endif
  86. // #ifndef APP-PLUS
  87. resolve(true); // 小程序和H5环境默认有权限
  88. // #endif
  89. });
  90. };
  91. /**
  92. * 打开位置权限设置
  93. */
  94. export const openLocationSettings = () => {
  95. uni.showModal({
  96. title: '位置权限',
  97. content: '需要位置权限才能进行签到,请在设置中开启位置权限',
  98. confirmText: '去设置',
  99. success: (res) => {
  100. if (res.confirm) {
  101. // #ifdef APP-PLUS
  102. plus.runtime.openURL('app-settings:');
  103. // #endif
  104. // #ifdef MP-WEIXIN
  105. wx.openSetting();
  106. // #endif
  107. }
  108. }
  109. });
  110. };
  111. /**
  112. * 计算两点间距离(米)
  113. * @param {number} lat1 纬度1
  114. * @param {number} lng1 经度1
  115. * @param {number} lat2 纬度2
  116. * @param {number} lng2 经度2
  117. * @returns {number} 距离(米)
  118. */
  119. export const calculateDistance = (lat1, lng1, lat2, lng2) => {
  120. const R = 6371000; // 地球半径(米)
  121. const dLat = (lat2 - lat1) * Math.PI / 180;
  122. const dLng = (lng2 - lng1) * Math.PI / 180;
  123. const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
  124. Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
  125. Math.sin(dLng / 2) * Math.sin(dLng / 2);
  126. const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  127. return R * c;
  128. };