Files
mgm-daylight-mcrm-mobile-ios/common/pushNotification.js
T
2026-09-16 10:43:59 +08:00

152 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* iOS 远程推送消息封装(原生插件:NetworkUtils-NetworkUtilsModule)
* 对应原生方法:onPushNotificationAsync、consumePendingPushNotificationsAsync
*/
// #ifdef APP-PLUS
const pushNetworkModule = uni.requireNativePlugin('NetworkUtils-NetworkUtilsModule')
// #endif
let lastPushNotification = null
const processedPushKeys = {}
function getPushDedupeKey(title, content) {
return `${title || ''}|${content || ''}`
}
function markPushProcessed(title, content) {
const key = getPushDedupeKey(title, content)
processedPushKeys[key] = true
return key
}
function isPushProcessed(title, content) {
return !!processedPushKeys[getPushDedupeKey(title, content)]
}
function dispatchPushMessage(onMessage, payload, meta = {}) {
if (!meta.userTapped && isPushProcessed(payload.title, payload.content)) {
console.log('[Push] skip duplicate push:', getPushDedupeKey(payload.title, payload.content))
return
}
markPushProcessed(payload.title, payload.content)
lastPushNotification = payload
if (typeof onMessage === 'function') {
onMessage(payload, meta)
}
}
function parseUserTappedFlag(value) {
return value === true || value === 1 || value === '1' || value === 'true'
}
function getPushConfirmNo(res = {}) {
const confirmNo = res.ConfirmNo || res.confirmNo || res.confNo || res.raw?.ConfirmNo || res.raw?.confirmNo || res.raw?.confNo
return confirmNo ? String(confirmNo) : ''
}
/**
* 将原生回调数据规范化为 { title, content, body, confirmNo, userTapped, raw }
* @param {Record<string, unknown>} res
*/
export function normalizePushPayload(res = {}) {
const title = typeof res.title === 'string' ? res.title : (res.title ? String(res.title) : '')
const body = typeof res.body === 'string' ? res.body : (res.body ? String(res.body) : '')
const confirmNo = getPushConfirmNo(res)
return {
title,
content: body,
body,
confirmNo,
userTapped: parseUserTappedFlag(res.userTapped),
raw: res
}
}
/**
* 获取最近一次收到的推送(内存缓存)
*/
export function getLastPushNotification() {
return lastPushNotification
}
/**
* 读取并清空 Native 侧缓存的待处理推送(后台/冷启动场景)
* @returns {Promise<Array<{ title: string, content: string, body: string, raw: object }>>}
*/
export function consumePendingPushNotifications() {
return new Promise((resolve) => {
// #ifdef APP-PLUS
if (!pushNetworkModule) {
console.error('[Push] NetworkUtils 原生插件不可用')
resolve([])
return
}
if (typeof pushNetworkModule.consumePendingPushNotificationsAsync !== 'function') {
console.warn('[Push] 原生暂不支持 consumePendingPushNotificationsAsync,跳过 Native pending 同步')
resolve([])
return
}
console.log('[Push] 调用 consumePendingPushNotificationsAsync ...')
pushNetworkModule.consumePendingPushNotificationsAsync({}, (ret) => {
const items = Array.isArray(ret?.items) ? ret.items : []
console.log('[Push] consumePendingPushNotificationsAsync 返回 count=', ret?.count ?? items.length)
resolve(items.map((item) => normalizePushPayload(item)))
})
// #endif
// #ifndef APP-PLUS
resolve([])
// #endif
})
}
/**
* 同步处理 Native 缓存的推送
* @param {(payload: { title: string, content: string, body: string, raw: object }, meta?: object) => void} onMessage
* @param {{ showToast?: boolean }} [options]
*/
export async function syncPendingPushNotifications(onMessage, options = {}) {
console.log('[Push] syncPendingPushNotifications start')
const pending = await consumePendingPushNotifications()
if (!pending.length) {
console.log('[Push] syncPendingPushNotifications: 队列为空')
return pending
}
console.log('[Push] syncPendingPushNotifications count=', pending.length)
for (const payload of pending) {
dispatchPushMessage(onMessage, payload, {
fromPending: true,
userTapped: payload.userTapped === true,
showToast: options.showToast !== false
})
}
return pending
}
/**
* 注册推送消息监听;每次收到远程推送时 callback 会被调用
* @param {(payload: { title: string, content: string, body: string, raw: object }, meta?: object) => void} onMessage
* @returns {() => void}
*/
export function listenPushNotification(onMessage) {
// #ifdef APP-PLUS
if (!pushNetworkModule || typeof pushNetworkModule.onPushNotificationAsync !== 'function') {
console.warn('[Push] NetworkUtils 原生插件不可用或未注册 onPushNotificationAsync')
return () => {}
}
pushNetworkModule.onPushNotificationAsync({}, (res) => {
const payload = normalizePushPayload(res)
console.log('[Push] 收到推送通知:', JSON.stringify(payload))
dispatchPushMessage(onMessage, payload, {
fromPending: !!res?.fromPending,
userTapped: payload.userTapped === true,
showToast: true
})
})
return () => {}
// #endif
// #ifndef APP-PLUS
console.warn('[Push] 非 App-PLUS 环境,跳过推送监听')
return () => {}
// #endif
}