迁移婚姻广播弹窗脚本

This commit is contained in:
2026-04-25 19:13:40 +08:00
parent ee4abdff85
commit e53f2f5d9d
3 changed files with 197 additions and 172 deletions
+1 -1
View File
@@ -766,12 +766,12 @@ if (typeof window !== "undefined") {
bindHorseRaceFabControls();
bindHorseRaceEvents();
bindHolidayModalControls();
bindMarriageModalControls();
bindChatInitialStateControls();
bindBankControls();
bindFishingControls();
bindFortunePanelControls();
bindMarriageStatusControls();
bindMarriageModalControls();
bindProfileControls();
bindShopControls();
bindCompactShopPanelControls();
+196
View File
@@ -80,6 +80,199 @@ export function openWeddingSetupModal(marriageId) {
}
}
/**
* 读取 Alpine 组件数据,避免直接访问 Alpine 私有字段。
*
* @param {string} modalId 弹窗节点 ID
* @returns {Record<string, any>|null}
*/
function getAlpineModalData(modalId) {
const modal = document.getElementById(modalId);
const alpine = window.Alpine;
if (!modal || !alpine) {
return null;
}
return alpine.$data(modal);
}
/**
* 构建婚礼红包领取按钮 HTML,按钮通过 ceremonyId 读取全局缓存。
*
* @param {number|string} ceremonyId 婚礼场次 ID
* @returns {string}
*/
function buildWeddingClaimButton(ceremonyId) {
return `<button data-wedding-envelope-claim="${Number(ceremonyId)}"
style="display:inline-block; margin-left:10px; padding:4px 14px; border-radius:20px;
background:#d97706; color:#fff;
border:none; font-size:12px; font-weight:bold; cursor:pointer;
vertical-align:middle; line-height:1.8; box-shadow:0 2px 8px rgba(0,0,0,.3);"
title="点击领取婚礼红包">🧧 点击领取红包</button>`;
}
/**
* 将红包详情写入全局缓存,供领取按钮和状态面板复用。
*
* @param {number|string} ceremonyId 婚礼场次 ID
* @param {Record<string, any>} detail 红包详情
* @returns {void}
*/
function cacheWeddingEnvelope(ceremonyId, detail) {
if (!window._weddingEnvelopes) {
window._weddingEnvelopes = {};
}
window._weddingEnvelopes[ceremonyId] = detail;
}
/**
* 绑定婚姻系统广播事件,处理弹窗、公告和红包到账提示。
*
* @returns {void}
*/
function bindMarriageModalEvents() {
if (window.__marriageModalEventsBound) {
return;
}
window.__marriageModalEventsBound = true;
window.addEventListener("chat:marriage-accepted", (event) => {
const detail = event.detail;
const groomName = detail.user?.username ?? detail.groom_name ?? "??";
const brideName = detail.partner?.username ?? detail.bride_name ?? "??";
if (typeof window.appendSystemMessage === "function") {
window.appendSystemMessage(`💑 ${groomName}${brideName} 喜结连理!`);
}
getAlpineModalData("marriage-accepted-modal")?.open(detail);
});
window.addEventListener("chat:marriage-proposed", (event) => {
getAlpineModalData("marriage-incoming-modal")?.open(event.detail);
});
window.addEventListener("chat:wedding-celebration", (event) => {
const detail = event.detail;
const groomName = detail.user?.username ?? "??";
const brideName = detail.partner?.username ?? "??";
const tierIcon = detail.tier_icon ?? "🎊";
const tierName = detail.tier_name ?? "婚礼";
const amount = detail.total_amount ? Number(detail.total_amount).toLocaleString() : "?";
const ceremonyId = detail.ceremony_id;
cacheWeddingEnvelope(ceremonyId, detail);
if (typeof window.appendSystemMessage === "function") {
window.appendSystemMessage(
`${tierIcon} ${groomName}${brideName} 举办了【${tierName}】!总金额 💰${amount} 金币,快来抢红包!${buildWeddingClaimButton(ceremonyId)}`,
);
}
getAlpineModalData("wedding-envelope-modal")?.open(detail);
});
window.addEventListener("chat:marriage-rejected", (event) => {
const { partner_name: partnerName } = event.detail;
window.chatDialog?.alert(`${partnerName} 婉拒了你的求婚,戒指随之遗失… 💔`, "求婚被拒绝", "#6b7280");
});
window.addEventListener("chat:marriage-expired", () => {
window.chatDialog?.alert("你的求婚超时未获回应,戒指已消失… ⏰", "求婚已过期", "#9ca3af");
});
window.addEventListener("chat:divorce-requested", (event) => {
getAlpineModalData("divorce-request-modal")?.open(event.detail);
});
window.addEventListener("chat:envelope-claimed", (event) => {
const { amount } = event.detail;
window.chatDialog?.alert(`+${amount.toLocaleString()} 金币已到账 🎉`, "红包到手!", "#f59e0b");
});
window.addEventListener("chat:marriage-divorced", (event) => {
const detail = event.detail;
const userName = detail.user_username ?? detail.user?.username ?? "??";
const partnerName = detail.partner_username ?? detail.partner?.username ?? "??";
if (typeof window.appendSystemMessage === "function") {
window.appendSystemMessage(`💔 ${userName}${partnerName} 解除了婚姻关系。`);
}
getAlpineModalData("marriage-divorced-modal")?.open(detail);
});
}
/**
* 页面恢复时查询未领取婚礼红包,并补回公屏领取入口。
*
* @returns {void}
*/
function restorePendingWeddingEnvelopes() {
const deferBootstrap = window.deferChatGameBootstrap || ((callback, delay = 0) => setTimeout(callback, delay));
deferBootstrap(async () => {
try {
const response = await fetch("/wedding/pending-envelopes", {
headers: {
Accept: "application/json",
},
});
const data = await response.json();
if (!response.ok || !data.envelopes?.length) {
return;
}
data.envelopes.forEach((envelope) => {
const ceremonyId = envelope.ceremony_id;
cacheWeddingEnvelope(ceremonyId, {
ceremony_id: ceremonyId,
total_amount: envelope.total_amount,
tier_name: envelope.tier_name,
tier_icon: envelope.tier_icon,
user: {
username: envelope.groom,
},
partner: {
username: envelope.bride,
},
});
if (typeof window.appendSystemMessage === "function") {
window.appendSystemMessage(
`⚠️ 您有来自 ${envelope.tier_icon} ${envelope.groom}${envelope.bride}${envelope.tier_name}】的婚礼红包未领取!${buildWeddingClaimButton(ceremonyId)}`,
);
}
});
} catch (error) {
console.warn("[婚礼红包] 恢复待领取按钮失败", error);
}
}, 3000);
}
/**
* 页面就绪后初始化婚姻私人频道和待领取红包恢复。
*
* @returns {void}
*/
function bindMarriageModalBootstrap() {
document.addEventListener("DOMContentLoaded", () => {
const userId = window.chatContext?.userId;
if (userId && typeof window.initMarriagePrivateChannel === "function") {
// Echo 初始化可能晚于 DOM 就绪,保留短延迟避免私人频道注册失败。
setTimeout(() => window.initMarriagePrivateChannel(userId), 1500);
}
restorePendingWeddingEnvelopes();
});
}
/**
* 暴露婚姻弹窗存量入口,兼容 Blade 内 onclick、Alpine 方法和广播回调。
*
@@ -89,4 +282,7 @@ export function bindMarriageModalControls() {
window.appendSystemMessage = appendSystemMessage;
window.openProposeModal = openProposeModal;
window.openWeddingSetupModal = openWeddingSetupModal;
bindMarriageModalEvents();
bindMarriageModalBootstrap();
}