appDevice.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import { replaceClientId } from '@/api/admin'
  2. import permision from '@/utils/wa-permission_1.1/permission.js'
  3. function isInvalidOaid(OAID) {
  4. if (!OAID) {
  5. return true
  6. }
  7. // OAID 无效占位:只包含 0 和 -
  8. return /^[0|-]+$/.test(OAID)
  9. }
  10. function isAndroid13Plus() {
  11. // #ifdef APP-PLUS
  12. try {
  13. const Build = plus.android.importClass('android.os.Build')
  14. return Build.VERSION.SDK_INT >= 33
  15. } catch (e) {
  16. return false
  17. }
  18. // #endif
  19. return false
  20. }
  21. function areAndroidNotificationsEnabled() {
  22. // #ifdef APP-PLUS
  23. try {
  24. const main = plus.android.runtimeMainActivity()
  25. let NotificationManagerCompat = plus.android.importClass('androidx.core.app.NotificationManagerCompat')
  26. if (!NotificationManagerCompat) {
  27. NotificationManagerCompat = plus.android.importClass('android.support.v4.app.NotificationManagerCompat')
  28. }
  29. return NotificationManagerCompat.from(main).areNotificationsEnabled()
  30. } catch (e) {
  31. return false
  32. }
  33. // #endif
  34. return true
  35. }
  36. function getIosDeviceId(onComplete) {
  37. // #ifdef APP-PLUS
  38. const keychain = uni.requireNativePlugin('Univalsoft-DeviceId')
  39. keychain.getDeviceIDCallback((ret) => {
  40. const deviceId = ret ? ret : ''
  41. if (deviceId) {
  42. uni.setStorageSync('deviceId', deviceId)
  43. }
  44. if (onComplete) {
  45. onComplete()
  46. }
  47. })
  48. // #endif
  49. // #ifndef APP-PLUS
  50. if (onComplete) {
  51. onComplete()
  52. }
  53. // #endif
  54. }
  55. function androidRegister() {
  56. // #ifdef APP-PLUS
  57. const idCode = uni.requireNativePlugin('Ba-IdCode')
  58. idCode.register(res => {
  59. console.log('Ba-IdCode register', res)
  60. })
  61. // #endif
  62. }
  63. function androidGetIdCodes(onComplete) {
  64. // #ifdef APP-PLUS
  65. const idCode = uni.requireNativePlugin('Ba-IdCode')
  66. idCode.getIdCodes(res => {
  67. if (res.data && res.data.AndroidID && res.data.AndroidID !== '') {
  68. uni.setStorageSync('deviceId', res.data.AndroidID)
  69. } else if (res.data && res.data.GUID && res.data.GUID !== '') {
  70. uni.setStorageSync('deviceId', res.data.GUID)
  71. } else if (res.data && res.data.IMEI && res.data.IMEI !== '') {
  72. uni.setStorageSync('deviceId', res.data.IMEI)
  73. }
  74. if (onComplete) {
  75. onComplete()
  76. }
  77. })
  78. // #endif
  79. // #ifndef APP-PLUS
  80. if (onComplete) {
  81. onComplete()
  82. }
  83. // #endif
  84. }
  85. function androidGetOAID(onComplete) {
  86. // #ifdef APP-PLUS
  87. const idCode = uni.requireNativePlugin('Ba-IdCode')
  88. idCode.getOAID((res) => {
  89. const OAID = (res.data && res.data.OAID) ? res.data.OAID : ''
  90. if (isInvalidOaid(OAID)) {
  91. androidGetIdCodes(onComplete)
  92. return
  93. }
  94. if (OAID) {
  95. uni.setStorageSync('deviceId', OAID)
  96. }
  97. if (onComplete) {
  98. onComplete()
  99. }
  100. })
  101. // #endif
  102. // #ifndef APP-PLUS
  103. if (onComplete) {
  104. onComplete()
  105. }
  106. // #endif
  107. }
  108. /**
  109. * 登录成功后、同步推送前,由用户确认再申请通知权限(Android 13+)
  110. */
  111. export function requestAppNotificationPermission(onComplete) {
  112. // #ifdef APP-PLUS
  113. if (plus.os.name === 'iOS') {
  114. if (onComplete) {
  115. onComplete()
  116. }
  117. return
  118. }
  119. if (!isAndroid13Plus() || areAndroidNotificationsEnabled()) {
  120. if (onComplete) {
  121. onComplete()
  122. }
  123. return
  124. }
  125. uni.showModal({
  126. title: '提示',
  127. content: '开启通知权限后,可及时接收订单等重要消息',
  128. confirmText: '开启',
  129. cancelText: '暂不',
  130. success(res) {
  131. const done = () => {
  132. if (onComplete) {
  133. onComplete()
  134. }
  135. }
  136. if (!res.confirm) {
  137. done()
  138. return
  139. }
  140. permision.requestAndroidPermission('android.permission.POST_NOTIFICATIONS').then(() => {
  141. done()
  142. }).catch(() => {
  143. done()
  144. })
  145. },
  146. fail() {
  147. if (onComplete) {
  148. onComplete()
  149. }
  150. }
  151. })
  152. // #endif
  153. // #ifndef APP-PLUS
  154. if (onComplete) {
  155. onComplete()
  156. }
  157. // #endif
  158. }
  159. /**
  160. * 登录成功后获取设备标识(仅 App 端)
  161. */
  162. export function setupAppDeviceId(onComplete) {
  163. // #ifdef APP-PLUS
  164. const systemInfo = uni.getSystemInfoSync()
  165. if (systemInfo.platform === 'ios') {
  166. getIosDeviceId(onComplete)
  167. } else if (systemInfo.platform === 'android') {
  168. androidRegister()
  169. androidGetOAID(onComplete)
  170. } else if (onComplete) {
  171. onComplete()
  172. }
  173. // #endif
  174. // #ifndef APP-PLUS
  175. if (onComplete) {
  176. onComplete()
  177. }
  178. // #endif
  179. }
  180. let pushMessageListenerRegistered = false
  181. /**
  182. * 登录成功后再注册推送消息监听,避免冷启动触发推送通道初始化
  183. */
  184. export function setupAppPushMessageListener() {
  185. // #ifdef APP-PLUS
  186. if (pushMessageListenerRegistered) {
  187. return
  188. }
  189. pushMessageListenerRegistered = true
  190. uni.onPushMessage((res) => {
  191. console.log('收到推送消息:', res)
  192. const message = res.data
  193. const pagePath = message.payload && message.payload.page
  194. if (!pagePath) {
  195. return
  196. }
  197. let url = pagePath.startsWith('/') ? pagePath : `/${pagePath}`
  198. if (message.params || (message.payload && message.payload.params)) {
  199. const params = message.params || message.payload.params
  200. const queryString = Object.keys(params).map(key => `${key}=${params[key]}`).join('&')
  201. url = `${url}?${queryString}`
  202. }
  203. console.log('推送消息跳转页面:', url)
  204. uni.navigateTo({
  205. url: url,
  206. fail: (err) => {
  207. console.error('页面跳转失败:', err)
  208. }
  209. })
  210. plus.runtime.setBadgeNumber(0)
  211. })
  212. // #endif
  213. }
  214. /**
  215. * 登录成功后同步推送 clientId(仅 App 端)
  216. */
  217. export function syncAppPushClientId(auto = 0) {
  218. // #ifdef APP-PLUS
  219. try {
  220. if (plus.os.name !== 'iOS' && isAndroid13Plus() && !areAndroidNotificationsEnabled()) {
  221. return
  222. }
  223. const clientInfo = plus.push.getClientInfo()
  224. const currentClientId = clientInfo && clientInfo.clientid ? clientInfo.clientid : ''
  225. const deviceId = uni.getStorageSync('deviceId')
  226. if (currentClientId) {
  227. replaceClientId({ id: currentClientId, deviceId: deviceId, auto: auto })
  228. }
  229. } catch (e) {
  230. console.log('syncAppPushClientId error', e)
  231. }
  232. // #endif
  233. }
  234. function finishAppPushSetup(auto) {
  235. setupAppPushMessageListener()
  236. syncAppPushClientId(auto)
  237. }
  238. /**
  239. * 用户登录成功后:获取设备 ID → 用户确认后申请通知权限 → 注册推送监听 → 同步推送 clientId
  240. * @param {{ auto?: number }} options auto=1 表示静默恢复登录,auto=0 表示用户主动登录
  241. */
  242. export function afterAppLoginSuccess(options = {}) {
  243. const auto = options.auto !== undefined ? options.auto : 0
  244. setupAppDeviceId(() => {
  245. if (auto === 1) {
  246. // 冷启动自动恢复登录:不弹通知授权,仅注册监听并尝试同步 clientId
  247. finishAppPushSetup(auto)
  248. return
  249. }
  250. requestAppNotificationPermission(() => {
  251. finishAppPushSetup(auto)
  252. })
  253. })
  254. }