| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /**
- * 地理定位工具函数模块
- * 提供浏览器定位相关的通用工具函数
- *
- * 主要功能:
- * - 浏览器定位 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
- }
|