realLocationSource.ts 4.1 KB

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