This commit is contained in:
Mauve
2026-09-16 10:43:59 +08:00
parent a7f2e0ca01
commit 9f2becfa67
36 changed files with 3997 additions and 264 deletions
+151
View File
@@ -0,0 +1,151 @@
/**
* 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
}