重构:提取 calculateNewLevel() 私有方法,增加在职职务等级保护逻辑

This commit is contained in:
2026-03-12 06:52:40 +08:00
parent 529a59551c
commit 174ee8241d
3 changed files with 164 additions and 98 deletions
@@ -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(() => {}); // 静默忽略网络错误,不影响弹窗展示
};
// ── 抢包/关闭逻辑 ─────────────────────────────────────