140 lines
4.5 KiB
JavaScript
140 lines
4.5 KiB
JavaScript
/**
|
|
* 定位服务工具类
|
|
* 提供获取当前位置、地址解析等功能
|
|
*/
|
|
|
|
/**
|
|
* 获取当前位置
|
|
* @returns Promise<{latitude, longitude, address}>
|
|
*/
|
|
export const getCurrentLocation = () => {
|
|
return new Promise((resolve, reject) => {
|
|
uni.showLoading({
|
|
title: '正在获取位置...'
|
|
});
|
|
|
|
uni.getLocation({
|
|
type: 'gcj02', // 使用国测局坐标系
|
|
geocode: true, // 解析地址信息
|
|
success: (res) => {
|
|
console.log('📍 获取位置成功:', res);
|
|
|
|
const locationData = {
|
|
latitude: res.latitude,
|
|
longitude: res.longitude,
|
|
address: res.address || '位置信息获取中...'
|
|
};
|
|
|
|
// 如果没有地址信息,尝试逆地理编码
|
|
if (!res.address) {
|
|
reverseGeocode(res.latitude, res.longitude)
|
|
.then(address => {
|
|
locationData.address = address;
|
|
resolve(locationData);
|
|
})
|
|
.catch(() => {
|
|
locationData.address = `${res.latitude.toFixed(6)}, ${res.longitude.toFixed(6)}`;
|
|
resolve(locationData);
|
|
});
|
|
} else {
|
|
resolve(locationData);
|
|
}
|
|
},
|
|
fail: (err) => {
|
|
console.error('❌ 获取位置失败:', err);
|
|
|
|
let errorMsg = '获取位置失败';
|
|
if (err.errMsg) {
|
|
if (err.errMsg.includes('auth deny')) {
|
|
errorMsg = '位置权限被拒绝,请在设置中开启位置权限';
|
|
} else if (err.errMsg.includes('locate fail')) {
|
|
errorMsg = '定位失败,请检查网络连接和GPS设置';
|
|
}
|
|
}
|
|
|
|
reject(new Error(errorMsg));
|
|
},
|
|
complete: () => {
|
|
uni.hideLoading();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 逆地理编码 - 根据坐标获取地址
|
|
* @param {number} latitude 纬度
|
|
* @param {number} longitude 经度
|
|
* @returns Promise<string>
|
|
*/
|
|
export const reverseGeocode = (latitude, longitude) => {
|
|
return new Promise((resolve, reject) => {
|
|
// 这里可以调用第三方地图服务API进行逆地理编码
|
|
// 暂时返回坐标信息
|
|
const address = `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`;
|
|
resolve(address);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 检查定位权限
|
|
* @returns Promise<boolean>
|
|
*/
|
|
export const checkLocationPermission = () => {
|
|
return new Promise((resolve) => {
|
|
// #ifdef APP-PLUS
|
|
const permissions = ['android.permission.ACCESS_FINE_LOCATION'];
|
|
plus.android.requestPermissions(permissions, (result) => {
|
|
resolve(result.granted && result.granted.length > 0);
|
|
}, (error) => {
|
|
console.error('权限检查失败:', error);
|
|
resolve(false);
|
|
});
|
|
// #endif
|
|
|
|
// #ifndef APP-PLUS
|
|
resolve(true); // 小程序和H5环境默认有权限
|
|
// #endif
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 打开位置权限设置
|
|
*/
|
|
export const openLocationSettings = () => {
|
|
uni.showModal({
|
|
title: '位置权限',
|
|
content: '需要位置权限才能进行签到,请在设置中开启位置权限',
|
|
confirmText: '去设置',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
// #ifdef APP-PLUS
|
|
plus.runtime.openURL('app-settings:');
|
|
// #endif
|
|
|
|
// #ifdef MP-WEIXIN
|
|
wx.openSetting();
|
|
// #endif
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 计算两点间距离(米)
|
|
* @param {number} lat1 纬度1
|
|
* @param {number} lng1 经度1
|
|
* @param {number} lat2 纬度2
|
|
* @param {number} lng2 经度2
|
|
* @returns {number} 距离(米)
|
|
*/
|
|
export const calculateDistance = (lat1, lng1, lat2, lng2) => {
|
|
const R = 6371000; // 地球半径(米)
|
|
const dLat = (lat2 - lat1) * Math.PI / 180;
|
|
const dLng = (lng2 - lng1) * Math.PI / 180;
|
|
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
|
Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
return R * c;
|
|
};
|