MrShi
2026-06-09 3f9032e92fdd383bfefc87a0bec9b242e1223851
app/App.vue
@@ -1,10 +1,16 @@
<script>
   import { mapState } from 'vuex'
   import md5 from 'js-md5';
   import { getLocationWithNotice } from '@/utils/utils'
   export default {
      data() {
         return {
            locationTimer: null,
            jpushModule: null
            jpushModule: null,
            tts: null,
            ttsPlatform: '',
            ttsVoice: null,
            hasGrantedLocationPermission: false
         }
      },
      computed: {
@@ -13,7 +19,6 @@
      watch: {
         token(newVal) {
            if (newVal) {
               this.startLocationPolling()
               this.bindJPushAlias()
            } else {
               this.stopLocationPolling()
@@ -22,76 +27,255 @@
         }
      },
      onLaunch: function() {
         this.initJPush()
         this.checkAndStartLocationPolling()
         uni.$on('locationPermissionGranted', this.handleLocationPermissionGranted)
         uni.$on('loginSuccessStartLocationPolling', this.handleLoginSuccessStartLocationPolling)
         uni.$on('privacyAgreed', this.handlePrivacyAgreed)
         // 检查是否已经同意过隐私政策,如果是则直接初始化极光推送
         console.log('login_privacy_policy_agreed', uni.getStorageSync('login_privacy_policy_agreed'))
         if (uni.getStorageSync('login_privacy_policy_agreed')) {
            // 初始化极光推送
            this.initJPush()
            // 初始化语音播报
            this.initTTS()
            // 获取版本号
            this.checkAppUpdate()
         }
      },
      onShow: function() {
         console.log('App Show')
         this.checkAndStartLocationPolling()
      },
      onHide: function() {
         console.log('App Hide')
      },
      onUnload() {
         uni.$off('locationPermissionGranted', this.handleLocationPermissionGranted)
         uni.$off('loginSuccessStartLocationPolling', this.handleLoginSuccessStartLocationPolling)
         uni.$off('privacyAgreed', this.handlePrivacyAgreed)
         if (this.tts) {
            try {
               if (this.ttsPlatform === 'android') {
                  this.tts.stop()
                  this.tts.shutdown()
               } else if (this.ttsPlatform === 'ios') {
                  this.tts.stopSpeakingAtBoundary(0)
               }
            } catch (e) {
               console.log('释放语音播报失败', e)
            }
         }
         this.stopLocationPolling()
      },
      methods: {
         handleLoginSuccessStartLocationPolling() {
            if (this.locationTimer) return
            if (this.hasGrantedLocationPermission) {
               console.log('登录成功后开始位置轮询上报')
               this.startLocationPolling()
               return
            }
            this.checkAndStartLocationPolling()
         },
         handlePrivacyAgreed() {
            console.log('隐私政策已同意,初始化极光推送')
            this.initJPush()
         },
         handleLocationPermissionGranted() {
            this.hasGrantedLocationPermission = true
            if (!this.token || this.locationTimer) return
            console.log('定位授权成功,开始位置轮询上报')
            this.startLocationPolling()
         },
         initTTS() {
            const platform = uni.getSystemInfoSync().platform
            this.ttsPlatform = platform
            if (platform === 'android') {
               try {
                  const TextToSpeech = plus.android.importClass('android.speech.tts.TextToSpeech')
                  const Locale = plus.android.importClass('java.util.Locale')
                  this.tts = new TextToSpeech(plus.android.runtimeMainActivity(), {
                     onInit: (status) => {
                        if (status == 0) {
                           this.tts.setLanguage(Locale.CHINA)
                           console.log('安卓语音初始化成功')
                        }
                     }
                  })
               } catch (e) {
                  console.log('安卓语音初始化失败', e)
               }
               return
            }
            if (platform === 'ios') {
               try {
                  const AVSpeechSynthesizer = plus.ios.importClass('AVSpeechSynthesizer')
                  const AVSpeechSynthesisVoice = plus.ios.importClass('AVSpeechSynthesisVoice')
                  this.tts = new AVSpeechSynthesizer()
                  this.ttsVoice = AVSpeechSynthesisVoice.voiceWithLanguage('zh-CN')
                  console.log('iOS语音初始化成功')
               } catch (e) {
                  console.log('iOS语音初始化失败', e)
               }
               return
            }
            console.log('当前平台暂不支持语音播报')
         },
         speak(text) {
            if (!this.tts) {
               uni.showToast({
                  title: '语音未准备好',
                  icon: 'none'
               })
               return
            }
            try {
               if (this.ttsPlatform === 'android') {
                  this.tts.speak(text, 0, null)
                  return
               }
               if (this.ttsPlatform === 'ios') {
                  const content = String(text || '').trim()
                  if (!content) return
                  const AVSpeechUtterance = plus.ios.importClass('AVSpeechUtterance')
                  const utterance = AVSpeechUtterance.speechUtteranceWithString(content)
                  if (this.ttsVoice) {
                     utterance.setVoice(this.ttsVoice)
                  }
                  utterance.setRate(0.5)
                  utterance.setVolume(1)
                  utterance.setPitchMultiplier(1)
                  this.tts.stopSpeakingAtBoundary(0)
                  this.tts.speakUtterance(utterance)
               }
            } catch (err) {
               console.log('播报失败', err)
            }
         },
         initJPush() {
            const jpushModule = uni.requireNativePlugin('JPush')
            console.log('开始初始化极光推送...')
            // #ifdef APP-PLUS
            let jpushModule = null
            try {
               jpushModule = uni.requireNativePlugin('JG-JPush')
            } catch (e) {
               console.error('加载极光推送插件失败:', e)
               return
            }
            if (!jpushModule) {
               console.log('极光推送插件未找到,请先安装插件')
               console.error('极光推送插件未找到')
               return
            }
            this.jpushModule = jpushModule
            console.log('极光推送插件加载成功,模块:', typeof jpushModule)
            console.log('模块方法:', Object.keys(jpushModule))
            jpushModule.init()
            console.log('极光推送初始化成功')
            if (typeof jpushModule.initJPushService === 'function') {
               jpushModule.initJPushService()
               console.log('极光推送initJPushService调用成功')
            } else {
               console.error('jpushModule.initJPushService 不是函数,当前方法:', typeof jpushModule.initJPushService)
               return
            }
            jpushModule.setLoggerEnable(true)
            if (typeof jpushModule.setLoggerEnable === 'function') {
               jpushModule.setLoggerEnable(true)
            }
            console.log('极光推送初始化完成,设置监听器...')
            this.setupJPushListeners()
            this.getRegistrationID()
            // #endif
         },
            jpushModule.addReceiveNotificationListener((result) => {
         setupJPushListeners() {
            var that = this
            if (!this.jpushModule) return
            // 监听连接状态
            this.jpushModule.addConnectEventListener((result) => {
               console.log('极光连接状态:', result.connectEnable)
            })
            // 监听通知
            this.jpushModule.addNotificationListener((result) => {
               console.log('收到通知:', JSON.stringify(result))
               const extras = result.extras || {}
               if (extras.type === 'order') {
                  uni.$emit('jpush_order_notification', extras)
               that.speak(result.content || '')
               const notificationEventType = result.notificationEventType
               // notificationOpened = 点击通知
               if (notificationEventType === 'notificationOpened') {
                  console.log('通知被点击', result.extras)
                  const extras = result.extras ? result.extras : {}
                  if (extras.type === 'new_order' && extras.orderId) {
                     uni.navigateTo({
                        url: '/pages/order-detail/order-detail?id=' + extras.orderId
                     })
                  } else {
                     uni.switchTab({
                        url: '/pages/index/index'
                     })
                  }
               }
            })
         },
            jpushModule.addReceiveOpenNotificationListener((result) => {
               console.log('点击通知:', JSON.stringify(result))
               const extras = result.extras || {}
               if (extras.type === 'order') {
                  uni.navigateTo({
                     url: '/pages/order-detail/order-detail?id=' + extras.orderId
                  })
               } else if (extras.type === 'message') {
                  uni.switchTab({
                     url: '/pages/message/message'
                  })
               }
            })
            jpushModule.addReceiveMessageListener((result) => {
               console.log('收到透传消息:', JSON.stringify(result))
            })
            jpushModule.getRegistrationID((res) => {
               console.log('JPush RegistrationID:', res)
               if (res && res.registerID) {
                  uni.setStorageSync('jpush_registration_id', res.registerID)
         getRegistrationID() {
            if (!this.jpushModule) {
               console.log('JPush模块未初始化,无法获取RegistrationID')
               return
            }
            console.log('开始获取JPush RegistrationID...')
            this.jpushModule.getRegistrationID((result) => {
               console.log('JPush getRegistrationID result:', JSON.stringify(result))
               if (result && result.registerID) {
                  console.log('JPush RegistrationID获取成功:', result.registerID)
                  uni.setStorageSync('jpush_registration_id', result.registerID)
               } else {
                  console.log('JPush RegistrationID获取失败,尝试重新获取')
                  setTimeout(() => {
                     this.getRegistrationID()
                  }, 2000)
               }
            })
         },
         bindJPushAlias() {
            if (!this.jpushModule || !this.token) return
            const userId = this.$store.state.userInfo?.id || ''
            if (userId) {
               this.jpushModule.setAlias({
                  alias: String(userId),
                  sequence: Date.now()
               }, (result) => {
                  console.log('设置极光别名成功:', JSON.stringify(result))
               })
            if (!this.token) return
            if (!this.jpushModule) {
               console.log('JPush未初始化,延迟设置别名')
               setTimeout(() => {
                  this.bindJPushAlias()
               }, 1000)
               return
            }
            // 优先从store获取,如果为空则从本地存储获取
            let telephone = this.$store.state.userInfo?.telephone || ''
            if (!telephone) {
               telephone = uni.getStorageSync('userInfo')?.telephone || ''
            }
            if (!telephone) {
               console.log('用户手机号为空,延迟获取...')
               setTimeout(() => {
                  this.bindJPushAlias()
               }, 2000)
               return
            }
            const alias = md5(telephone)
            console.log('设置极光别名:', alias)
            this.jpushModule.setAlias({
               alias: alias,
               sequence: Date.now()
            }, (result) => {
               console.log('设置别名结果:', JSON.stringify(result))
               if (result && (result.code === 0 || result.errCode === 0)) {
                  console.log('设置极光别名成功')
               } else {
                  console.log('设置极光别名失败')
               }
            })
         },
         deleteJPushAlias() {
@@ -99,14 +283,26 @@
            this.jpushModule.deleteAlias({
               sequence: Date.now()
            }, (result) => {
               console.log('删除极光别名成功:', JSON.stringify(result))
               console.log('删除极光别名:', JSON.stringify(result))
            })
         },
         checkAndStartLocationPolling() {
            if (this.token) {
               this.startLocationPolling()
            }
            if (!this.token) return
            getLocationWithNotice({
               type: 'gcj02',
               success: (res) => {
                  console.log('获取定位权限成功,开始定时更新位置')
                  this.startLocationPolling()
               },
               fail: (err) => {
                  // console.log('获取定位权限失败:', err.errMsg)
                  // uni.showToast({
                  //    title: '需要定位权限才能更新位置',
                  //    icon: 'none'
                  // })
               }
            }).catch(() => {})
         },
         startLocationPolling() {
@@ -125,14 +321,72 @@
         },
         updateLocation() {
            uni.getLocation({
            if (!this.token) return
            var that = this;
            getLocationWithNotice({
               type: 'gcj02',
               success: (res) => {
                  console.log(res)
                  this.$u.api.updateLocation({
                  console.log('定时更新位置:', res.latitude, res.longitude)
                  that.$store.commit('setLocation', { latitude: res.latitude, longitude: res.longitude })
                  that.$u.api.updateLocation({
                     latitude: res.latitude,
                     longitude: res.longitude
                  }).then(res => {
                     if (res.code === 200) {
                        console.log('更新位置成功')
                     } else {
                        console.log('更新位置失败')
                     }
                  }).catch(err => {
                     console.log('更新位置请求失败:', err)
                  })
               },
               fail: (err) => {
                  console.log('获取位置失败:', err.errMsg)
               }
            }).catch(() => {})
         },
         checkAppUpdate() {
            plus.runtime.getProperty(plus.runtime.appid, (inf) => {
               const currentVersion = inf.versionCode
               this.$u.api.getApiVersion({ type: 0 }).then(res => {
                  if (res.code === 200 && res.data) {
                     const latestVersion = res.data.versionNum
                     if (latestVersion > currentVersion) {
                        if (res.data.isForce === 1) {
                           this.showForceUpdateDialog(res.data.fileUrl, res.data.versionNum)
                        } else {
                           this.showOptionalUpdateDialog(res.data.fileUrl, res.data.versionNum)
                        }
                     }
                  }
               })
            })
         },
         showForceUpdateDialog(fileUrl, version) {
            uni.showModal({
               title: '版本更新',
               content: `检测到新版本${version},请更新后继续使用`,
               showCancel: false,
               confirmText: '立即更新',
               success: () => {
                  plus.runtime.openURL(fileUrl)
               }
            })
         },
         showOptionalUpdateDialog(fileUrl, version) {
            uni.showModal({
               title: '版本更新',
               content: `检测到新版本${version},是否更新?`,
               confirmText: '更新',
               cancelText: '稍后',
               success: (res) => {
                  if (res.confirm) {
                     plus.runtime.openURL(fileUrl)
                  }
               }
            })
         }
@@ -140,6 +394,11 @@
   }
</script>
<style lang="scss">
   @import "uview-ui/index.scss";
</style>
<style>
   page {
      background-color: #f6f8fc;
   }
   uni-mp-share {
      display: none !important;
   }
</style>