/** * 地理定位工具函数模块 * 提供浏览器定位相关的通用工具函数 * * 主要功能: * - 浏览器定位 API 封装 * - 定位错误处理 * - HTTPS 环境检测 */ /** * 检查是否为安全上下文(HTTPS) * @returns {boolean} 是否为安全上下文 */ export function isSecureContext() { // #ifdef H5 if (typeof window !== 'undefined' && window.location) { return window.isSecureContext || window.location.protocol === 'https:' } // #endif return false } /** * 检查浏览器是否支持定位 * @returns {boolean} 是否支持定位 */ export function isGeolocationSupported() { // #ifdef H5 return typeof navigator !== 'undefined' && 'geolocation' in navigator // #endif // #ifndef H5 return false // #endif } /** * 获取当前位置 * 使用浏览器 Geolocation API * @param {Object} options 定位选项 * @returns {Promise<{longitude: number, latitude: number}>} 定位结果 */ export function getCurrentPosition(options = {}) { return new Promise((resolve, reject) => { // #ifdef H5 if (!isGeolocationSupported()) { reject(new Error('浏览器不支持定位功能')) return } const defaultOptions = { enableHighAccuracy: true, timeout: 10000, maximumAge: 0, ...options } navigator.geolocation.getCurrentPosition( (position) => { resolve({ longitude: position.coords.longitude, latitude: position.coords.latitude, accuracy: position.coords.accuracy, timestamp: position.timestamp }) }, (error) => { reject(error) }, defaultOptions ) // #endif // #ifndef H5 reject(new Error('当前平台不支持浏览器定位 API')) // #endif }) } /** * 解析定位错误 * @param {GeolocationPositionError} error 定位错误对象 * @returns {Object} 包含 message 和 detail 的错误信息对象 */ export function parseGeolocationError(error) { let errorMsg = '定位失败' let errorDetail = '' // #ifdef H5 if (error && typeof error.code === 'number') { switch(error.code) { case 1: // PERMISSION_DENIED errorMsg = '定位权限被拒绝' errorDetail = '请在浏览器设置中允许定位权限。' // 检查 HTTPS 环境 if (!isSecureContext()) { errorDetail += ' 注意:HTTP 环境下浏览器可能会直接拒绝定位请求,建议使用 HTTPS 访问。' } break case 2: // POSITION_UNAVAILABLE errorMsg = '位置信息不可用' errorDetail = '请检查 GPS 或网络连接,确保设备定位服务已开启。' break case 3: // TIMEOUT errorMsg = '定位请求超时' errorDetail = '定位请求超过设定时间未响应,请重试或检查网络连接。' break default: errorMsg = '定位失败' errorDetail = error.message || '未知错误' } } else if (error && error.message) { errorMsg = '定位失败' errorDetail = error.message } // #endif return { message: errorMsg, detail: errorDetail, code: error?.code } } /** * 监听位置变化 * @param {Function} successCallback 成功回调 * @param {Function} errorCallback 错误回调 * @param {Object} options 定位选项 * @returns {number|null} watchId,用于停止监听 */ export function watchPosition(successCallback, errorCallback, options = {}) { // #ifdef H5 if (!isGeolocationSupported()) { if (errorCallback) { errorCallback(new Error('浏览器不支持定位功能')) } return null } const defaultOptions = { enableHighAccuracy: true, timeout: 10000, maximumAge: 0, ...options } return navigator.geolocation.watchPosition( (position) => { if (successCallback) { successCallback({ longitude: position.coords.longitude, latitude: position.coords.latitude, accuracy: position.coords.accuracy, timestamp: position.timestamp }) } }, (error) => { if (errorCallback) { errorCallback(error) } }, defaultOptions ) // #endif // #ifndef H5 if (errorCallback) { errorCallback(new Error('当前平台不支持浏览器定位 API')) } return null // #endif } /** * 停止监听位置变化 * @param {number} watchId watchPosition 返回的 ID */ export function clearWatch(watchId) { // #ifdef H5 if (watchId !== null && watchId !== undefined && isGeolocationSupported()) { navigator.geolocation.clearWatch(watchId) } // #endif }