第一次提交:小程序前端最新版本
This commit is contained in:
203
services/popupService.js
Normal file
203
services/popupService.js
Normal file
@@ -0,0 +1,203 @@
|
||||
import request from '../utils/request.js'
|
||||
|
||||
const STORAGE_RECORDS = 'popup_records'
|
||||
const STORAGE_MUTE_TODAY = 'popup_mute_today'
|
||||
|
||||
class PopupService {
|
||||
constructor() {
|
||||
this.records = this.loadRecords()
|
||||
this.muteToday = this.loadMuteToday()
|
||||
this.currentPageKey = null
|
||||
this.isShowing = false // 是否正在展示弹窗队列
|
||||
this.isFetching = false // 是否正在请求弹窗数据
|
||||
}
|
||||
|
||||
loadRecords() {
|
||||
try {
|
||||
return wx.getStorageSync(STORAGE_RECORDS) || {}
|
||||
} catch (e) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
saveRecords() {
|
||||
try {
|
||||
wx.setStorageSync(STORAGE_RECORDS, this.records)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
loadMuteToday() {
|
||||
try {
|
||||
return wx.getStorageSync(STORAGE_MUTE_TODAY) || {}
|
||||
} catch (e) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
saveMuteToday() {
|
||||
try {
|
||||
wx.setStorageSync(STORAGE_MUTE_TODAY, this.muteToday)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
isSamePeriod(date1, date2, interval) {
|
||||
const d1 = new Date(date1)
|
||||
const d2 = new Date(date2)
|
||||
if (interval === 'day') {
|
||||
return d1.toDateString() === d2.toDateString()
|
||||
} else if (interval === 'week') {
|
||||
const getWeek = (d) => {
|
||||
const year = d.getFullYear()
|
||||
const firstDay = new Date(year, 0, 1)
|
||||
const week = Math.ceil((((d - firstDay) / 86400000) + firstDay.getDay() + 1) / 7)
|
||||
return `${year}-${week}`
|
||||
}
|
||||
return getWeek(d1) === getWeek(d2)
|
||||
} else if (interval === 'month') {
|
||||
return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth()
|
||||
} else if (interval === 'year') {
|
||||
return d1.getFullYear() === d2.getFullYear()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
shouldShow(popup, pageKey, serverDate, pageIgnoreUserMute) {
|
||||
const popupId = popup.popup_id
|
||||
const strategy = popup.strategy
|
||||
const force_even_muted = popup.force_even_muted || false
|
||||
|
||||
const todayStr = serverDate.split('T')[0]
|
||||
const now = new Date(serverDate)
|
||||
|
||||
const skipMuteCheck = pageIgnoreUserMute || force_even_muted
|
||||
if (!skipMuteCheck) {
|
||||
const mutedDate = this.muteToday[pageKey]
|
||||
if (mutedDate === todayStr) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const key = `${pageKey}_${popupId}`
|
||||
const record = this.records[key]
|
||||
const { type, maxCount = 1, resetInterval = 'day' } = strategy
|
||||
|
||||
if (type === 'once') return !record
|
||||
if (type === 'always') return true
|
||||
if (type === 'daily' || type === 'weekly' || type === 'monthly' || type === 'yearly') {
|
||||
const interval = type
|
||||
if (!record) return true
|
||||
const lastTime = record.lastShowTime
|
||||
if (!lastTime) return true
|
||||
const same = this.isSamePeriod(lastTime, now, interval)
|
||||
if (!same) return true
|
||||
const currentCount = record.showCount || 1
|
||||
return currentCount < maxCount
|
||||
}
|
||||
if (type === 'count') {
|
||||
if (!record) return true
|
||||
const lastTime = record.lastShowTime
|
||||
if (!lastTime) return true
|
||||
const same = this.isSamePeriod(lastTime, now, resetInterval)
|
||||
if (!same) return true
|
||||
const currentCount = record.showCount || 1
|
||||
return currentCount < maxCount
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
recordShow(popupId, pageKey, serverDate) {
|
||||
const key = `${pageKey}_${popupId}`
|
||||
const now = new Date(serverDate)
|
||||
const record = this.records[key] || { showCount: 0, lastShowTime: 0, lastShowDate: '' }
|
||||
record.showCount = (record.showCount || 0) + 1
|
||||
record.lastShowTime = now.getTime()
|
||||
record.lastShowDate = serverDate.split('T')[0]
|
||||
this.records[key] = record
|
||||
this.saveRecords()
|
||||
}
|
||||
|
||||
setMuteToday(pageKey, serverDate) {
|
||||
const todayStr = serverDate.split('T')[0]
|
||||
this.muteToday[pageKey] = todayStr
|
||||
this.saveMuteToday()
|
||||
}
|
||||
|
||||
async checkAndShow(pageInstance, pageKey) {
|
||||
if (this.isShowing || this.isFetching) return
|
||||
|
||||
this.isFetching = true
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/peizhi/tanchuang',
|
||||
method: 'POST',
|
||||
data: { pageKey }
|
||||
})
|
||||
if (res.statusCode !== 200 || res.data.code !== 0) return
|
||||
const { serverTime, popups = [], ignore_user_mute = false } = res.data.data
|
||||
if (!popups.length) return
|
||||
|
||||
const queue = []
|
||||
for (const popup of popups) {
|
||||
if (this.shouldShow(popup, pageKey, serverTime, ignore_user_mute)) {
|
||||
queue.push(popup)
|
||||
}
|
||||
}
|
||||
if (!queue.length) return
|
||||
|
||||
this.isShowing = true
|
||||
this.currentPageKey = pageKey
|
||||
await this.showQueue(pageInstance, queue, 0, serverTime, ignore_user_mute)
|
||||
} catch (error) {
|
||||
console.error('[弹窗] 服务错误:', error)
|
||||
} finally {
|
||||
this.isFetching = false
|
||||
this.isShowing = false
|
||||
}
|
||||
}
|
||||
|
||||
showQueue(pageInstance, queue, index, serverTime, pageIgnoreUserMute) {
|
||||
if (index >= queue.length) return Promise.resolve()
|
||||
const popup = queue[index]
|
||||
const isLast = index === queue.length - 1
|
||||
|
||||
const popupComp = pageInstance.selectComponent('#popupNotice')
|
||||
if (!popupComp) {
|
||||
console.error('[弹窗] 未找到组件 #popupNotice')
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const showCheckbox = isLast && !pageIgnoreUserMute && !popup.force_even_muted
|
||||
const showData = {
|
||||
popupId: popup.popup_id,
|
||||
title: popup.title || '',
|
||||
duration: popup.duration || 0,
|
||||
images: popup.images || [],
|
||||
showMuteCheckbox: showCheckbox,
|
||||
serverTime: serverTime
|
||||
}
|
||||
const onClose = (result) => {
|
||||
this.recordShow(popup.popup_id, this.currentPageKey, serverTime)
|
||||
if (result.muteToday && showCheckbox) {
|
||||
this.setMuteToday(this.currentPageKey, serverTime)
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
this.showQueue(pageInstance, queue, index + 1, serverTime, pageIgnoreUserMute).then(resolve)
|
||||
}
|
||||
popupComp.show(showData, onClose)
|
||||
})
|
||||
}
|
||||
|
||||
// ========== 🆕 新增:强制重置锁状态 ==========
|
||||
/**
|
||||
* 当页面被隐藏(onHide)时调用,用于释放全局锁,避免影响其他页面的弹窗
|
||||
*/
|
||||
reset() {
|
||||
this.isShowing = false;
|
||||
this.isFetching = false;
|
||||
this.currentPageKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
export default new PopupService()
|
||||
Reference in New Issue
Block a user