Files
gmTouringMiniApp/src/services/location/current-location.ts
T

75 lines
2.3 KiB
TypeScript
Raw Normal View History

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<CheckInLocationSnapshot> {
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<typeof setTimeout> | 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)
})
}