优化节日福利列表与领取提示展示

This commit is contained in:
2026-04-22 09:52:35 +08:00
parent b0028c515f
commit 73c6674fc4
2 changed files with 375 additions and 128 deletions
@@ -62,19 +62,20 @@
{{-- 领取按钮 --}}
<div x-show="!claimed">
<div style="background:rgba(0,0,0,.3); border-radius:16px; padding:5px;">
<button x-on:click="doClaim()" :disabled="claiming || loadingStatus || !claimable"
style="display:block; width:100%; padding:14px 0; border:none; border-radius:12px;
font-size:16px; font-weight:bold; cursor:pointer; transition:all .15s;
letter-spacing:1px; color:#fff;"
:style="claiming || loadingStatus || !claimable
?
'background:#b45309; opacity:.65; cursor:not-allowed;' :
'background:#d97706; box-shadow:0 2px 12px rgba(0,0,0,.4);'"
onmouseover="if(!this.disabled) this.style.filter='brightness(1.12)'"
onmouseout="this.style.filter=''">
<span x-text="claimButtonText()"></span>
</button>
<div style="background:rgba(0,0,0,.26); border-radius:999px; padding:10px 16px; margin-top:6px;">
<div style="display:flex; justify-content:center;">
<button x-on:click="doClaim()" :disabled="claiming || loadingStatus || !claimable"
onmouseover="if(!this.disabled)this.style.transform='translateY(-2px) scale(1.04)'"
onmouseout="this.style.transform=''"
:style="claiming || loadingStatus || !claimable
?
'min-width:220px; padding:12px 28px; border-radius:999px; border:none; cursor:not-allowed; display:inline-flex; align-items:center; justify-content:center; gap:8px; box-sizing:border-box; transition:all .25s; font-size:18px; font-weight:900; letter-spacing:1px; background:#c8b89a; color:rgba(100,50,20,.45); box-shadow:none;'
:
'min-width:220px; padding:12px 28px; border-radius:999px; border:none; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; gap:8px; box-sizing:border-box; transition:all .25s; font-size:18px; font-weight:900; letter-spacing:1px; background:#f5e6c8; color:#8b3a1a; box-shadow:0 8px 28px rgba(0,0,0,.28), inset 0 -4px 10px rgba(139,58,26,.12); animation:holiday-claim-pulse 1.8s ease-in-out infinite;'">
<span style="font-size:22px; line-height:1;">🎁</span>
<span x-text="claimButtonText()"></span>
</button>
</div>
</div>
</div>
@@ -117,6 +118,18 @@
transform: scale(1.1) rotate(5deg);
}
}
@keyframes holiday-claim-pulse {
0%,
100% {
box-shadow: 0 8px 28px rgba(0, 0, 0, .28), inset 0 -4px 10px rgba(139, 58, 26, .12);
}
50% {
box-shadow: 0 10px 34px rgba(245, 230, 200, .18), 0 12px 30px rgba(0, 0, 0, .32), inset 0 -4px 10px rgba(139, 58, 26, .16);
}
}
</style>
<script>
@@ -238,6 +251,51 @@
return detail ?? {};
}
/**
* 缓存最近广播过的节日福利批次详情,供公屏消息按钮二次打开弹窗。
*/
window.__holidayRuns = window.__holidayRuns || {};
/**
* 从公屏系统消息中打开指定节日福利批次弹窗。
*
* @param {number|string} runId
*/
window.openHolidayRunFromSystemMessage = function(runId) {
const normalizedRunId = String(runId);
const detail = window.__holidayRuns?.[normalizedRunId];
const el = document.getElementById('holiday-event-modal');
if (!el || typeof Alpine === 'undefined') {
return;
}
if (!detail) {
window.chatDialog?.alert('当前福利批次信息未缓存,请等待下一轮广播或刷新页面后重试。', '提示', '#f59e0b');
return;
}
Alpine.$data(el).open(detail);
};
/**
* 构建公屏系统消息里的领取按钮,便于多个消息场景复用一致视觉。
*
* @param {number|string|null} runId
* @param {string} label
* @returns {string}
*/
function buildHolidayClaimActionButton(runId, label = '🎁 立即领取') {
if (!runId) {
return '';
}
return ` <button type="button"
onclick="openHolidayRunFromSystemMessage(${JSON.stringify(String(runId))})"
style="display:inline-flex; align-items:center; gap:4px; margin-left:8px; padding:3px 10px; border:none; border-radius:999px; background:linear-gradient(135deg,#f59e0b,#d97706); color:#fff; font-size:12px; font-weight:bold; cursor:pointer; box-shadow:0 2px 6px rgba(0,0,0,.22); vertical-align:middle;"
title="点击领取本轮节日福利">${label}</button>`;
}
function buildHolidaySystemMessage(detail) {
const quotaText = detail.max_claimants > 0
? `前 ${detail.max_claimants} 名在线用户可领取`
@@ -247,6 +305,8 @@
: '随机金额发放';
const scheduleText = detail.scheduled_for ? `发放时间 ${formatHolidayDate(detail.scheduled_for)}` : null;
const roundText = detail.round_label ? ` ${detail.round_label}` : '';
const runId = firstHolidayDefined(detail.run_id, detail.id);
const claimButtonHtml = buildHolidayClaimActionButton(runId);
return [
`🎊 【${detail.name}】${roundText}开始啦!`,
@@ -254,7 +314,7 @@
amountText,
quotaText,
scheduleText,
].filter(Boolean).join('');
].filter(Boolean).join('') + claimButtonHtml;
}
/**
@@ -269,6 +329,7 @@
claimable: true,
claimed: false,
expiresTimer: null,
autoCloseTimer: null,
// 活动数据
runId: null,
@@ -326,6 +387,7 @@
this.loadingStatus = false;
this.claiming = false;
this.claimedAmount = 0;
this.stopAutoCloseTimer();
this.statusHint = holidayDetail.run_id
? '当前奖励按本轮福利批次发放,请在有效期内领取。'
: '兼容旧活动通道,等待主线广播升级';
@@ -341,6 +403,7 @@
close() {
this.show = false;
this.stopExpiresTimer();
this.stopAutoCloseTimer();
},
/**
@@ -361,6 +424,24 @@
}
},
/**
* 启动领取成功后的自动关闭计时器。
*/
startAutoCloseTimer() {
this.stopAutoCloseTimer();
this.autoCloseTimer = window.setTimeout(() => this.close(), 3000);
},
/**
* 停止自动关闭计时器。
*/
stopAutoCloseTimer() {
if (this.autoCloseTimer) {
window.clearTimeout(this.autoCloseTimer);
this.autoCloseTimer = null;
}
},
/**
* 更新有效期显示文字
*/
@@ -514,7 +595,17 @@
this.claimed = true;
this.claimable = false;
this.claimedAmount = claimedAmount;
this.statusHint = data.message ?? '本轮福利已入账。';
this.statusHint = `${data.message ?? '本轮福利已入账。'} 3 秒后自动关闭。`;
if (typeof appendSystemMessage === 'function') {
const username = window.chatContext?.username ?? '当前用户';
const roundText = this.roundLabel ? `【${this.roundLabel}】` : '';
appendSystemMessage(
`🌟 <b>${username}</b> 领取了【${this.eventName}】${roundText},获得 <b>${claimedAmount.toLocaleString()}</b> 金币!${buildHolidayClaimActionButton(this.runId)}`
);
}
this.startAutoCloseTimer();
if (window.__chatUser && data.balance !== undefined) {
window.__chatUser.jjb = data.balance;
@@ -550,6 +641,10 @@
window.addEventListener('chat:holiday.started', (e) => {
const detail = normalizeHolidayPayload(e.detail);
if (detail.run_id !== undefined && detail.run_id !== null) {
window.__holidayRuns[String(detail.run_id)] = detail;
}
// 公屏追加系统消息
if (typeof appendSystemMessage === 'function') {
appendSystemMessage(buildHolidaySystemMessage({