congming_huose-apk/common/utils/noticeTopShared.js

95 lines
2.6 KiB
JavaScript
Raw Normal View History

/**
* 顶栏长连接通知共享状态 + 只绑定一次 appWs:notice
* 多页各挂 AppTopPushNotice 页面栈顶的实例展示 $root 与栈顶 $vm 比较
*/
import Vue from 'vue'
import { parseAppWsNoticeDisplay, formatNoticeTimeForBanner } from '@/common/utils/parseAppWsNotice.js'
const HIDE_MS = 3000
function _fingerprint(item) {
if (item && item.id) return 'id:' + item.id
return 't:' + (item.time || '') + '|' + (item.text || '')
}
function _createState() {
// 非 H5/非 Vue2 时降级为普通对象
if (typeof Vue !== 'undefined' && Vue.observable) {
return Vue.observable({
visible: false,
enterActive: false,
displayTime: '',
displayText: '',
displayPicture: '',
gnpLastKey: '',
gnpLastKeyAt: 0,
gnpNoticeSeen: {},
gnpHideTimer: null,
})
}
return {
visible: false,
enterActive: false,
displayTime: '',
displayText: '',
displayPicture: '',
gnpLastKey: '',
gnpLastKeyAt: 0,
gnpNoticeSeen: {},
gnpHideTimer: null,
}
}
export const noticeTopState = _createState()
let _bound = false
function _onMsg(msg) {
const item = parseAppWsNoticeDisplay(msg)
if (!item || !String(item.text).trim()) return
const key = _fingerprint(item)
const now = Date.now()
if (key === noticeTopState.gnpLastKey && now - (noticeTopState.gnpLastKeyAt || 0) < 2000) return
if (item.id && noticeTopState.gnpNoticeSeen[item.id]) return
if (item.id) {
noticeTopState.gnpNoticeSeen = { ...noticeTopState.gnpNoticeSeen, [item.id]: 1 }
}
noticeTopState.gnpLastKey = key
noticeTopState.gnpLastKeyAt = now
noticeTopState.displayTime = formatNoticeTimeForBanner(item.time) || '—'
noticeTopState.displayText = item.text
noticeTopState.displayPicture = item.picture || ''
if (noticeTopState.gnpHideTimer) {
clearTimeout(noticeTopState.gnpHideTimer)
noticeTopState.gnpHideTimer = null
}
noticeTopState.visible = true
noticeTopState.enterActive = false
// 与 index 内联版一致,下一帧后触发入场动画
setTimeout(() => {
noticeTopState.enterActive = true
}, 30)
noticeTopState.gnpHideTimer = setTimeout(() => {
hideTopNotice()
}, HIDE_MS)
}
export function hideTopNotice() {
if (noticeTopState.gnpHideTimer) {
clearTimeout(noticeTopState.gnpHideTimer)
noticeTopState.gnpHideTimer = null
}
noticeTopState.enterActive = false
setTimeout(() => {
noticeTopState.visible = false
noticeTopState.displayPicture = ''
}, 220)
}
/** 在 App onLaunch 或首屏调用一次 */
export function bindAppWsTopNoticeListenerOnce() {
if (_bound) return
_bound = true
uni.$off('appWs:notice', _onMsg)
uni.$on('appWs:notice', _onMsg)
}