迁移婚姻广播弹窗脚本
This commit is contained in:
@@ -766,12 +766,12 @@ if (typeof window !== "undefined") {
|
|||||||
bindHorseRaceFabControls();
|
bindHorseRaceFabControls();
|
||||||
bindHorseRaceEvents();
|
bindHorseRaceEvents();
|
||||||
bindHolidayModalControls();
|
bindHolidayModalControls();
|
||||||
|
bindMarriageModalControls();
|
||||||
bindChatInitialStateControls();
|
bindChatInitialStateControls();
|
||||||
bindBankControls();
|
bindBankControls();
|
||||||
bindFishingControls();
|
bindFishingControls();
|
||||||
bindFortunePanelControls();
|
bindFortunePanelControls();
|
||||||
bindMarriageStatusControls();
|
bindMarriageStatusControls();
|
||||||
bindMarriageModalControls();
|
|
||||||
bindProfileControls();
|
bindProfileControls();
|
||||||
bindShopControls();
|
bindShopControls();
|
||||||
bindCompactShopPanelControls();
|
bindCompactShopPanelControls();
|
||||||
|
|||||||
@@ -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 方法和广播回调。
|
* 暴露婚姻弹窗存量入口,兼容 Blade 内 onclick、Alpine 方法和广播回调。
|
||||||
*
|
*
|
||||||
@@ -89,4 +282,7 @@ export function bindMarriageModalControls() {
|
|||||||
window.appendSystemMessage = appendSystemMessage;
|
window.appendSystemMessage = appendSystemMessage;
|
||||||
window.openProposeModal = openProposeModal;
|
window.openProposeModal = openProposeModal;
|
||||||
window.openWeddingSetupModal = openWeddingSetupModal;
|
window.openWeddingSetupModal = openWeddingSetupModal;
|
||||||
|
|
||||||
|
bindMarriageModalEvents();
|
||||||
|
bindMarriageModalBootstrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1232,175 +1232,4 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ───────── WebSocket 事件处理 ───────────────────────────
|
|
||||||
|
|
||||||
/** 收到全局结婚公告:弹出全屏通知 + 追加公屏文字 */
|
|
||||||
window.addEventListener('chat:marriage-accepted', (e) => {
|
|
||||||
const detail = e.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} 喜结连理!`);
|
|
||||||
}
|
|
||||||
// 弹出全屏公告(fireworks 效果)
|
|
||||||
const el = document.getElementById('marriage-accepted-modal');
|
|
||||||
if (el) Alpine.$data(el).open(detail);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/** 收到求婚通知(私人频道,目标方) */
|
|
||||||
window.addEventListener('chat:marriage-proposed', (e) => {
|
|
||||||
const detail = e.detail;
|
|
||||||
const el = document.getElementById('marriage-incoming-modal');
|
|
||||||
if (el) Alpine.$data(el).open(detail);
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 收到婚礼庆典(全局,显示红包 + 公屏系统消息) */
|
|
||||||
window.addEventListener('chat:wedding-celebration', (e) => {
|
|
||||||
const detail = e.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;
|
|
||||||
|
|
||||||
// 将 detail 存入全局 Map,避免 onclick 属性内嵌 JSON 被双引号破坏
|
|
||||||
if (!window._weddingEnvelopes) window._weddingEnvelopes = {};
|
|
||||||
window._weddingEnvelopes[ceremonyId] = detail;
|
|
||||||
|
|
||||||
// 公屏追加带按钮的系统消息(按钮通过 ceremonyId 引用全局 Map)
|
|
||||||
if (typeof window.appendSystemMessage === 'function') {
|
|
||||||
const claimBtn = `<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>`;
|
|
||||||
window.appendSystemMessage(
|
|
||||||
`${tierIcon} ${groomName} 与 ${brideName} 举办了【${tierName}】!总金额 💰${amount} 金币,快来抢红包!${claimBtn}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同时弹出全屏红包弹窗
|
|
||||||
const el = document.getElementById('wedding-envelope-modal');
|
|
||||||
if (el) Alpine.$data(el).open(detail);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/** 求婚被拒(私人频道,发起方) */
|
|
||||||
window.addEventListener('chat:marriage-rejected', (e) => {
|
|
||||||
const {
|
|
||||||
proposer_name,
|
|
||||||
partner_name
|
|
||||||
} = e.detail;
|
|
||||||
window.chatDialog?.alert(
|
|
||||||
`${partner_name} 婉拒了你的求婚,戒指随之遗失… 💔`,
|
|
||||||
'求婚被拒绝',
|
|
||||||
'#6b7280'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 求婚超时(私人频道,发起方) */
|
|
||||||
window.addEventListener('chat:marriage-expired', (e) => {
|
|
||||||
window.chatDialog?.alert(
|
|
||||||
'你的求婚超时未获回应,戒指已消失… ⏰',
|
|
||||||
'求婚已过期',
|
|
||||||
'#9ca3af'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 接到协议离婚申请(私人频道,对方)→ 打开专属三选弹窗 */
|
|
||||||
window.addEventListener('chat:divorce-requested', (e) => {
|
|
||||||
const detail = e.detail;
|
|
||||||
const el = document.getElementById('divorce-request-modal');
|
|
||||||
if (el) Alpine.$data(el).open(detail);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 红包领取成功通知(私人频道) */
|
|
||||||
window.addEventListener('chat:envelope-claimed', (e) => {
|
|
||||||
const {
|
|
||||||
amount
|
|
||||||
} = e.detail;
|
|
||||||
window.chatDialog?.alert(`+${amount.toLocaleString()} 金币已到账 🎉`, '红包到手!', '#f59e0b');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('chat:marriage-divorced', (e) => {
|
|
||||||
const detail = e.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} 解除了婚姻关系。`);
|
|
||||||
}
|
|
||||||
// 触发全屏离婚公告弹窗(暗色阴郁风格 + 雷雨特效)
|
|
||||||
const modal = document.getElementById('marriage-divorced-modal')?._x_dataStack?.[0];
|
|
||||||
if (modal && typeof modal.open === 'function') modal.open(detail);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/** 页面加载完成后初始化私人频道监听 */
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const userId = window.chatContext?.userId;
|
|
||||||
if (userId && typeof window.initMarriagePrivateChannel === 'function') {
|
|
||||||
// 延迟初始化,确保 Echo 已就绪
|
|
||||||
setTimeout(() => window.initMarriagePrivateChannel(userId), 1500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── 页面刷新后恢复婚礼红包领取按钮 ─────────────────────────
|
|
||||||
// 空闲时再查待领取红包,避免和聊天室首屏消息/名单初始化抢网络。
|
|
||||||
window.deferChatGameBootstrap(async () => {
|
|
||||||
try {
|
|
||||||
const res = await fetch('/wedding/pending-envelopes', {
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const data = await res.json();
|
|
||||||
if (!res.ok || !data.envelopes?.length) return;
|
|
||||||
|
|
||||||
// 初始化全局缓存
|
|
||||||
if (!window._weddingEnvelopes) window._weddingEnvelopes = {};
|
|
||||||
|
|
||||||
data.envelopes.forEach(env => {
|
|
||||||
const ceremonyId = env.ceremony_id;
|
|
||||||
|
|
||||||
// 注入 detail 到全局 Map,供领取弹窗使用
|
|
||||||
window._weddingEnvelopes[ceremonyId] = {
|
|
||||||
ceremony_id: ceremonyId,
|
|
||||||
total_amount: env.total_amount,
|
|
||||||
tier_name: env.tier_name,
|
|
||||||
tier_icon: env.tier_icon,
|
|
||||||
user: {
|
|
||||||
username: env.groom
|
|
||||||
},
|
|
||||||
partner: {
|
|
||||||
username: env.bride
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 在包厢窗口追加提示 + 领取按钮
|
|
||||||
if (typeof window.appendSystemMessage === 'function') {
|
|
||||||
const claimBtn = `<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>`;
|
|
||||||
window.appendSystemMessage(
|
|
||||||
`⚠️ 您有来自 ${env.tier_icon} ${env.groom} 与 ${env.bride}【${env.tier_name}】的婚礼红包未领取!${claimBtn}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('[婚礼红包] 恢复待领取按钮失败', e);
|
|
||||||
}
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user