import type { CheckInLocationSnapshot } from '@/domain/check-in' interface CurrentLocationOptions { highAccuracyExpireTime?: number timeoutMs?: number } function locationOptionsSupported(): boolean { try { return typeof uni.canIUse !== 'function' || uni.canIUse('getLocation.object.isHighAccuracy') } catch { return false } } export function isLocationPermissionDenied(error: unknown): boolean { if (!error || typeof error !== 'object') return false const message = String((error as { errMsg?: unknown }).errMsg ?? '') return !/privacy/i.test(message) && /auth deny|auth denied|authorize:fail|permission/i.test(message) } export function getCurrentGcj02Location(options: CurrentLocationOptions = {}): Promise { return new Promise((resolve, reject) => { const highAccuracyExpireTime = Math.max(3000, options.highAccuracyExpireTime ?? 8000) const timeoutMs = Math.max(3000, options.timeoutMs ?? 15000) let settled = false let timeout: ReturnType | null = null const finish = (callback: () => void) => { if (settled) return settled = true if (timeout) clearTimeout(timeout) callback() } timeout = setTimeout(() => { finish(() => reject(new Error('定位超时,请到开阔处重试'))) }, timeoutMs) const commonOptions = { type: 'gcj02' as const, success: (result: UniNamespace.GetLocationSuccess) => { const longitude = Number(result.longitude) const latitude = Number(result.latitude) const accuracy = Number(result.accuracy ?? result.horizontalAccuracy) if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) { finish(() => reject(new Error('定位结果无效,请稍后重试'))) return } finish(() => resolve({ longitude, latitude, accuracy: Number.isFinite(accuracy) && accuracy >= 0 ? accuracy : null, receivedAt: new Date().toISOString(), coordinateSystem: 'GCJ02', })) }, fail: (error: unknown) => finish(() => reject(error)), } if (locationOptionsSupported()) { uni.getLocation({ ...commonOptions, isHighAccuracy: true, highAccuracyExpireTime, }) return } uni.getLocation(commonOptions) }) }