import { type LocationSource, type LocationSourceCallbacks } from './locationSource' function hasLocationPermission(settings: WechatMiniprogram.AuthSetting): boolean { const authSettings = settings as Record return !!authSettings['scope.userLocation'] } function hasBackgroundLocationPermission(settings: WechatMiniprogram.AuthSetting): boolean { const authSettings = settings as Record return !!authSettings['scope.userLocationBackground'] } export class RealLocationSource implements LocationSource { callbacks: LocationSourceCallbacks active: boolean boundLocationHandler: ((result: WechatMiniprogram.OnLocationChangeCallbackResult) => void) | null constructor(callbacks: LocationSourceCallbacks) { this.callbacks = callbacks this.active = false this.boundLocationHandler = null } get mode(): 'real' { return 'real' } start(): void { if (this.active) { this.callbacks.onStatus('后台持续定位进行中') return } wx.getSetting({ success: (result) => { const settings = result.authSetting || {} if (hasBackgroundLocationPermission(settings)) { this.startBackgroundLocation() return } if (hasLocationPermission(settings)) { this.requestBackgroundPermissionInSettings() return } wx.authorize({ scope: 'scope.userLocation', success: () => { this.requestBackgroundPermissionInSettings() }, fail: () => { this.requestBackgroundPermissionInSettings() }, }) }, fail: (error) => { const message = error && error.errMsg ? error.errMsg : 'getSetting 失败' this.callbacks.onError(`GPS授权检查失败: ${message}`) }, }) } stop(): void { if (!this.active) { this.callbacks.onStatus('后台持续定位未启动') return } if (typeof wx.offLocationChange === 'function' && this.boundLocationHandler) { wx.offLocationChange(this.boundLocationHandler) } this.boundLocationHandler = null wx.stopLocationUpdate({ complete: () => { this.active = false this.callbacks.onStatus('后台持续定位已停止') }, }) } destroy(): void { if (typeof wx.offLocationChange === 'function' && this.boundLocationHandler) { wx.offLocationChange(this.boundLocationHandler) } this.boundLocationHandler = null if (this.active) { wx.stopLocationUpdate({ complete: () => {} }) this.active = false } } requestBackgroundPermissionInSettings(): void { this.callbacks.onStatus('请在授权面板开启后台定位') wx.openSetting({ success: (result) => { const settings = result.authSetting || {} if (hasBackgroundLocationPermission(settings)) { this.startBackgroundLocation() return } this.callbacks.onError('GPS启动失败: 未授予后台定位权限') }, fail: (error) => { const message = error && error.errMsg ? error.errMsg : 'openSetting 失败' this.callbacks.onError(`GPS启动失败: ${message}`) }, }) } startBackgroundLocation(): void { wx.startLocationUpdateBackground({ type: 'wgs84', success: () => { this.bindLocationListener() this.active = true this.callbacks.onStatus('后台持续定位已启动') }, fail: (error) => { const message = error && error.errMsg ? error.errMsg : 'startLocationUpdateBackground 失败' this.callbacks.onError(`GPS启动失败: ${message}`) }, }) } bindLocationListener(): void { if (this.boundLocationHandler) { return } this.boundLocationHandler = (result) => { this.callbacks.onLocation({ latitude: result.latitude, longitude: result.longitude, accuracy: result.accuracy, speed: result.speed, timestamp: Date.now(), sourceMode: 'real', }) } wx.onLocationChange(this.boundLocationHandler) } }