locationController.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. export interface LocationUpdate {
  2. latitude: number
  3. longitude: number
  4. accuracy?: number
  5. speed?: number
  6. }
  7. export interface LocationControllerCallbacks {
  8. onLocation: (update: LocationUpdate) => void
  9. onStatus: (message: string) => void
  10. onError: (message: string) => void
  11. }
  12. function hasLocationPermission(settings: WechatMiniprogram.AuthSetting): boolean {
  13. const authSettings = settings as Record<string, boolean | undefined>
  14. return !!authSettings['scope.userLocation']
  15. }
  16. function hasBackgroundLocationPermission(settings: WechatMiniprogram.AuthSetting): boolean {
  17. const authSettings = settings as Record<string, boolean | undefined>
  18. return !!authSettings['scope.userLocationBackground']
  19. }
  20. export class LocationController {
  21. callbacks: LocationControllerCallbacks
  22. listening: boolean
  23. boundLocationHandler: ((result: WechatMiniprogram.OnLocationChangeCallbackResult) => void) | null
  24. constructor(callbacks: LocationControllerCallbacks) {
  25. this.callbacks = callbacks
  26. this.listening = false
  27. this.boundLocationHandler = null
  28. }
  29. start(): void {
  30. if (this.listening) {
  31. this.callbacks.onStatus('后台持续定位进行中')
  32. return
  33. }
  34. wx.getSetting({
  35. success: (result) => {
  36. const settings = result.authSetting || {}
  37. if (hasBackgroundLocationPermission(settings)) {
  38. this.startBackgroundLocation()
  39. return
  40. }
  41. if (hasLocationPermission(settings)) {
  42. this.requestBackgroundPermissionInSettings()
  43. return
  44. }
  45. wx.authorize({
  46. scope: 'scope.userLocation',
  47. success: () => {
  48. this.requestBackgroundPermissionInSettings()
  49. },
  50. fail: () => {
  51. this.requestBackgroundPermissionInSettings()
  52. },
  53. })
  54. },
  55. fail: (error) => {
  56. const message = error && error.errMsg ? error.errMsg : 'getSetting 失败'
  57. this.callbacks.onError(`GPS授权检查失败: ${message}`)
  58. },
  59. })
  60. }
  61. requestBackgroundPermissionInSettings(): void {
  62. this.callbacks.onStatus('请在授权面板开启后台定位')
  63. wx.openSetting({
  64. success: (result) => {
  65. const settings = result.authSetting || {}
  66. if (hasBackgroundLocationPermission(settings)) {
  67. this.startBackgroundLocation()
  68. return
  69. }
  70. this.callbacks.onError('GPS启动失败: 未授予后台定位权限')
  71. },
  72. fail: (error) => {
  73. const message = error && error.errMsg ? error.errMsg : 'openSetting 失败'
  74. this.callbacks.onError(`GPS启动失败: ${message}`)
  75. },
  76. })
  77. }
  78. startBackgroundLocation(): void {
  79. wx.startLocationUpdateBackground({
  80. type: 'wgs84',
  81. success: () => {
  82. this.bindLocationListener()
  83. this.listening = true
  84. this.callbacks.onStatus('后台持续定位已启动')
  85. },
  86. fail: (error) => {
  87. const message = error && error.errMsg ? error.errMsg : 'startLocationUpdateBackground 失败'
  88. this.callbacks.onError(`GPS启动失败: ${message}`)
  89. },
  90. })
  91. }
  92. stop(): void {
  93. if (!this.listening) {
  94. this.callbacks.onStatus('后台持续定位未启动')
  95. return
  96. }
  97. if (typeof wx.offLocationChange === 'function' && this.boundLocationHandler) {
  98. wx.offLocationChange(this.boundLocationHandler)
  99. }
  100. this.boundLocationHandler = null
  101. wx.stopLocationUpdate({
  102. complete: () => {
  103. this.listening = false
  104. this.callbacks.onStatus('后台持续定位已停止')
  105. },
  106. })
  107. }
  108. destroy(): void {
  109. if (typeof wx.offLocationChange === 'function' && this.boundLocationHandler) {
  110. wx.offLocationChange(this.boundLocationHandler)
  111. }
  112. this.boundLocationHandler = null
  113. if (this.listening) {
  114. wx.stopLocationUpdate({ complete: () => {} })
  115. this.listening = false
  116. }
  117. }
  118. bindLocationListener(): void {
  119. if (this.boundLocationHandler) {
  120. return
  121. }
  122. this.boundLocationHandler = (result) => {
  123. this.callbacks.onLocation({
  124. latitude: result.latitude,
  125. longitude: result.longitude,
  126. accuracy: result.accuracy,
  127. speed: result.speed,
  128. })
  129. }
  130. wx.onLocationChange(this.boundLocationHandler)
  131. }
  132. }