重构:提取 calculateNewLevel() 私有方法,增加在职职务等级保护逻辑
This commit is contained in:
@@ -384,9 +384,19 @@
|
||||
* @param {number} expireSeconds 有效秒数
|
||||
* @param {'gold'|'exp'} type 货币类型
|
||||
*/
|
||||
window.showRedPacketModal = function(envelopeId, senderUsername, totalAmount, totalCount, expireSeconds,
|
||||
window.showRedPacketModal = async function(envelopeId, senderUsername, totalAmount, totalCount,
|
||||
expireSeconds,
|
||||
type) {
|
||||
try {
|
||||
// 尝试获取点击按钮附带的发包真实时间戳(兼容历史数据)
|
||||
let sentAtUnix = null;
|
||||
if (window.event && window.event.currentTarget) {
|
||||
const btn = window.event.currentTarget;
|
||||
if (btn.dataset && btn.dataset.sentAt) {
|
||||
sentAtUnix = parseInt(btn.dataset.sentAt, 10);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('showRedPacketModal 触发,当前状态:', {
|
||||
envelopeId,
|
||||
senderUsername,
|
||||
@@ -394,13 +404,87 @@
|
||||
totalCount,
|
||||
expireSeconds,
|
||||
type,
|
||||
sentAtUnix,
|
||||
oldId: _rpEnvelopeId
|
||||
});
|
||||
|
||||
// 计算真实过期时间点
|
||||
let calculatedExpireAt = Date.now() + expireSeconds * 1000;
|
||||
if (sentAtUnix && !isNaN(sentAtUnix) && sentAtUnix > 0) {
|
||||
calculatedExpireAt = (sentAtUnix + expireSeconds) * 1000;
|
||||
}
|
||||
|
||||
// 【前置拦截1】如果有时间戳并算出已过期,直接杀死不弹窗
|
||||
if (sentAtUnix && Date.now() >= calculatedExpireAt) {
|
||||
if (typeof window.chatToast === 'function') {
|
||||
window.chatToast('该红包已过期。', 'info');
|
||||
} else {
|
||||
alert('该红包已过期。');
|
||||
}
|
||||
console.log('红包已准确断定过期,拦截弹窗显示:', envelopeId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 【统一前置拦截】无论新老红包、有无时间戳,为彻底杜绝闪现,强制上云查册生死再放行!
|
||||
let currentRemaining = totalCount;
|
||||
try {
|
||||
const res = await fetch(`/red-packet/${envelopeId}/status`, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')
|
||||
.content,
|
||||
},
|
||||
});
|
||||
const initialStatusData = await res.json();
|
||||
|
||||
if (initialStatusData.status === 'success') {
|
||||
if (initialStatusData.is_expired || initialStatusData.envelope_status ===
|
||||
'expired') {
|
||||
window.chatToast?.show({
|
||||
title: '⏰ 礼包已过期',
|
||||
message: '该红包已过期,无法领取。',
|
||||
icon: '⏰',
|
||||
color: '#9ca3af',
|
||||
duration: 4000,
|
||||
});
|
||||
return; // 判定死亡,直接退出,永不渲染弹窗!
|
||||
}
|
||||
if (initialStatusData.remaining_count <= 0 || initialStatusData
|
||||
.envelope_status === 'completed') {
|
||||
window.chatToast?.show({
|
||||
title: '😅 手慢了!',
|
||||
message: '红包已被抢完,下次要快一点哦!',
|
||||
icon: '🧧',
|
||||
color: '#f59e0b',
|
||||
duration: 4000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (initialStatusData.has_claimed) {
|
||||
window.chatToast?.show({
|
||||
title: '✅ 已领取',
|
||||
message: '您已成功领取过本次礼包!',
|
||||
icon: '🧧',
|
||||
color: '#10b981',
|
||||
duration: 4000,
|
||||
});
|
||||
return; // 判定已领取,直接退出
|
||||
}
|
||||
// 记录真实的剩余倒计时以备展示
|
||||
currentRemaining = initialStatusData.remaining_count;
|
||||
totalCount = initialStatusData.total_count || totalCount;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('红包状态前置预查失败:', e);
|
||||
}
|
||||
|
||||
// --------- 到此,证实它不仅没死甚至还很活泼、也没领取过。开始安心布置并渲染弹窗 ---------
|
||||
|
||||
_rpEnvelopeId = envelopeId;
|
||||
_rpClaimed = false;
|
||||
_rpType = type || 'gold';
|
||||
_rpExpireAt = calculatedExpireAt;
|
||||
_rpTotalSeconds = expireSeconds;
|
||||
_rpExpireAt = Date.now() + expireSeconds * 1000;
|
||||
_rpType = type || 'gold'; // 保存类型供 claimRedPacket 使用
|
||||
|
||||
// 根据类型调整配色和标签
|
||||
const isExp = (type === 'exp');
|
||||
@@ -436,7 +520,7 @@
|
||||
document.getElementById('rp-sender-name').textContent = senderUsername + ' 的礼包';
|
||||
document.getElementById('rp-total-amount').textContent = totalAmount;
|
||||
document.getElementById('rp-total-count').textContent = totalCount;
|
||||
document.getElementById('rp-remaining').textContent = totalCount;
|
||||
document.getElementById('rp-remaining').textContent = currentRemaining;
|
||||
document.getElementById('rp-countdown').textContent = expireSeconds;
|
||||
document.getElementById('rp-timer-bar').style.width = '100%';
|
||||
document.getElementById('rp-status-msg').textContent = '';
|
||||
@@ -478,65 +562,6 @@
|
||||
document.getElementById('rp-status-msg').textContent = '红包已过期。';
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// 异步拉取服务端最新状态(实时刷新剩余份数)
|
||||
fetch(`/red-packet/${envelopeId}/status`, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
},
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.status !== 'success') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新剩余份数显示
|
||||
document.getElementById('rp-remaining').textContent = data.remaining_count;
|
||||
|
||||
// 若已过期 → 关闭弹窗 + Toast 提示
|
||||
if (data.is_expired || data.envelope_status === 'expired') {
|
||||
clearInterval(_rpTimer);
|
||||
closeRedPacketModal();
|
||||
window.chatToast?.show({
|
||||
title: '⏰ 礼包已过期',
|
||||
message: '该礼包已超过有效期,无法领取。',
|
||||
icon: '⏰',
|
||||
color: '#9ca3af',
|
||||
duration: 4000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 若已抢完 → 关闭弹窗 + Toast 提示
|
||||
if (data.remaining_count <= 0 || data.envelope_status === 'completed') {
|
||||
clearInterval(_rpTimer);
|
||||
closeRedPacketModal();
|
||||
window.chatToast?.show({
|
||||
title: '😅 手慢了!',
|
||||
message: '礼包已被抢完,下次要快一点哦!',
|
||||
icon: '🧧',
|
||||
color: '#f59e0b',
|
||||
duration: 4000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 若本人已领取 → 关闭弹窗 + Toast 提示
|
||||
if (data.has_claimed) {
|
||||
clearInterval(_rpTimer);
|
||||
closeRedPacketModal();
|
||||
window.chatToast?.show({
|
||||
title: '✅ 已领取',
|
||||
message: '您已成功领取过本次礼包!',
|
||||
icon: '🧧',
|
||||
color: '#10b981',
|
||||
duration: 4000,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {}); // 静默忽略网络错误,不影响弹窗展示
|
||||
};
|
||||
|
||||
// ── 抢包/关闭逻辑 ─────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user