745 lines
24 KiB
JavaScript
745 lines
24 KiB
JavaScript
// 婚姻弹窗辅助入口,承接从 marriage-modals.blade.php 迁移出的全局函数。
|
|
|
|
/**
|
|
* 向聊天主窗口追加一条婚姻系统公告,允许传入受控 HTML 按钮。
|
|
*
|
|
* @param {string} html 系统模板生成的 HTML 内容
|
|
* @returns {void}
|
|
*/
|
|
export function appendSystemMessage(html) {
|
|
const container = document.getElementById("chat-messages-container");
|
|
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
const div = document.createElement("div");
|
|
div.style.cssText = "background:linear-gradient(135deg,#fdf4ff,#fce7f3); border-left:3px solid #ec4899; border-radius:6px; padding:5px 12px; margin:3px 0; font-size:13px; line-height:1.6;";
|
|
div.innerHTML = `<span style="color:#9d174d;">${html}</span>`;
|
|
container.appendChild(div);
|
|
container.scrollTop = container.scrollHeight;
|
|
}
|
|
|
|
/**
|
|
* 打开求婚弹窗入口,从用户名片按钮触发。
|
|
*
|
|
* @param {string} username 求婚对象用户名
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function openProposeModal(username) {
|
|
let rings = [];
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.myRingsUrl, {
|
|
headers: {
|
|
Accept: "application/json",
|
|
},
|
|
});
|
|
const data = await response.json();
|
|
|
|
if (data.status === "success") {
|
|
rings = data.rings || [];
|
|
}
|
|
} catch {
|
|
// 网络异常时继续交给后端兜底,避免前端误拦截真实可用的求婚流程。
|
|
}
|
|
|
|
if (rings.length === 0) {
|
|
const goShop = await window.chatDialog?.confirm(
|
|
"求婚需要一枚💍结婚戒指,你的背包里还没有。\n\n要前往商店购买吗?",
|
|
"需要结婚戒指",
|
|
);
|
|
|
|
if (goShop && typeof window.openShopModal === "function") {
|
|
window.openShopModal();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
const modal = document.getElementById("marriage-propose-modal");
|
|
const alpine = window.Alpine;
|
|
|
|
if (modal && alpine) {
|
|
alpine.$data(modal).openWithRings(username, rings);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 打开婚礼设置弹窗,供新婚公告和名片入口复用。
|
|
*
|
|
* @param {number|string} marriageId 婚姻记录 ID
|
|
* @returns {void}
|
|
*/
|
|
export function openWeddingSetupModal(marriageId) {
|
|
const modal = document.getElementById("wedding-setup-modal");
|
|
const alpine = window.Alpine;
|
|
|
|
if (modal && alpine) {
|
|
alpine.$data(modal).open(marriageId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建求婚弹窗 Alpine 数据,负责戒指选择、婚礼档位和求婚提交。
|
|
*
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
export function marriageProposeModal() {
|
|
return {
|
|
show: false,
|
|
targetUsername: "",
|
|
marriageId: null,
|
|
rings: [],
|
|
selectedRing: null,
|
|
tiers: window.chatContext?.marriage?.weddingTiers || [],
|
|
selectedTierId: window.chatContext?.marriage?.defaultWeddingTierId || "",
|
|
loading: false,
|
|
sending: false,
|
|
error: "",
|
|
|
|
get selectedTier() {
|
|
if (!this.selectedTierId) {
|
|
return null;
|
|
}
|
|
|
|
return this.tiers.find((tier) => tier.id == this.selectedTierId);
|
|
},
|
|
|
|
get canAfford() {
|
|
const amount = this.selectedTier ? Number(this.selectedTier.amount) : 0;
|
|
|
|
return window.chatContext.userJjb >= amount;
|
|
},
|
|
|
|
async open(username) {
|
|
this.targetUsername = username;
|
|
this.selectedRing = null;
|
|
this.error = "";
|
|
this.loading = true;
|
|
this.show = true;
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.myRingsUrl, {
|
|
headers: {
|
|
Accept: "application/json",
|
|
},
|
|
});
|
|
const data = await response.json();
|
|
|
|
if (data.status === "success") {
|
|
this.rings = data.rings;
|
|
|
|
if (this.rings.length > 0) {
|
|
this.selectedRing = this.rings[0].purchase_id;
|
|
}
|
|
}
|
|
} catch {
|
|
this.rings = [];
|
|
}
|
|
|
|
this.loading = false;
|
|
},
|
|
|
|
/**
|
|
* 使用预加载戒指列表打开弹窗,避免入口检查后重复请求背包。
|
|
*
|
|
* @param {string} username 求婚对象用户名
|
|
* @param {Array<Record<string, any>>} rings 已加载的戒指列表
|
|
* @returns {void}
|
|
*/
|
|
openWithRings(username, rings) {
|
|
this.targetUsername = username;
|
|
this.error = "";
|
|
this.loading = false;
|
|
this.rings = rings;
|
|
this.selectedRing = rings.length > 0 ? rings[0].purchase_id : null;
|
|
this.show = true;
|
|
},
|
|
|
|
close() {
|
|
this.show = false;
|
|
},
|
|
|
|
async doPropose() {
|
|
if (this.sending || !this.selectedRing) {
|
|
return;
|
|
}
|
|
|
|
this.sending = true;
|
|
this.error = "";
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.proposeUrl, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
"X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
|
|
},
|
|
body: JSON.stringify({
|
|
target_username: this.targetUsername,
|
|
ring_purchase_id: this.selectedRing,
|
|
wedding_tier_id: this.selectedTierId || null,
|
|
room_id: window.chatContext.roomId,
|
|
}),
|
|
});
|
|
const data = await response.json();
|
|
|
|
if (data.status === "success") {
|
|
this.close();
|
|
window.chatDialog?.alert("💍 求婚成功!等待对方回应(有效期 48 小时)", "已发出", "#f43f5e");
|
|
} else {
|
|
this.error = data.message || "求婚失败";
|
|
}
|
|
} catch {
|
|
this.error = "网络异常,请稍后重试";
|
|
}
|
|
|
|
this.sending = false;
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 创建收到求婚弹窗 Alpine 数据,处理同意和拒绝求婚。
|
|
*
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
export function marriageIncomingModal() {
|
|
return {
|
|
show: false,
|
|
proposerName: "",
|
|
marriageId: null,
|
|
ringName: "",
|
|
ringIcon: "💍",
|
|
expiresAt: "",
|
|
acting: false,
|
|
|
|
open(detail) {
|
|
this.proposerName = detail.proposer_name || detail.proposer?.username || "";
|
|
this.marriageId = detail.marriage_id;
|
|
this.ringName = detail.ring_name || "";
|
|
this.ringIcon = detail.ring_icon || "💍";
|
|
this.expiresAt = detail.expires_at || "";
|
|
this.show = true;
|
|
},
|
|
|
|
close() {
|
|
this.show = false;
|
|
},
|
|
|
|
async doAccept() {
|
|
if (this.acting) {
|
|
return;
|
|
}
|
|
|
|
this.acting = true;
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.acceptUrl(this.marriageId), {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
"X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
|
|
},
|
|
body: JSON.stringify({
|
|
room_id: window.chatContext.roomId,
|
|
}),
|
|
});
|
|
const data = await response.json();
|
|
|
|
this.close();
|
|
|
|
if (data.status !== "success") {
|
|
window.chatDialog?.alert(data.message || "操作失败", "提示", "#cc4444");
|
|
}
|
|
} catch {
|
|
window.chatDialog?.alert("网络异常", "错误", "#cc4444");
|
|
}
|
|
|
|
this.acting = false;
|
|
},
|
|
|
|
async doReject() {
|
|
if (this.acting) {
|
|
return;
|
|
}
|
|
|
|
this.acting = true;
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.rejectUrl(this.marriageId), {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
"X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
|
|
},
|
|
body: JSON.stringify({
|
|
room_id: window.chatContext.roomId,
|
|
}),
|
|
});
|
|
const data = await response.json();
|
|
|
|
this.close();
|
|
|
|
if (data.status !== "success") {
|
|
window.chatDialog?.alert(data.message || "操作失败", "提示", "#cc4444");
|
|
} else {
|
|
window.chatDialog?.alert("已婉拒对方的求婚", "操作完成", "#6b7280");
|
|
}
|
|
} catch {
|
|
window.chatDialog?.alert("网络异常", "错误", "#cc4444");
|
|
}
|
|
|
|
this.acting = false;
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 创建结婚成功公告弹窗 Alpine 数据,并触发婚礼礼花特效。
|
|
*
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
export function marriageAcceptedModal() {
|
|
return {
|
|
show: false,
|
|
announcement: "",
|
|
subText: "",
|
|
marriageId: null,
|
|
isNewlywed: false,
|
|
|
|
open(detail) {
|
|
this.marriageId = detail.marriage_id;
|
|
const groomName = detail.user?.username ?? detail.groom_name ?? "??";
|
|
const brideName = detail.partner?.username ?? detail.bride_name ?? "??";
|
|
|
|
this.announcement = `${groomName} 与 ${brideName} 喜结连理!`;
|
|
this.subText = detail.message || "愿百年好合,白头偕老!";
|
|
|
|
// 只有新婚双方本人可以继续打开婚礼设置弹窗。
|
|
const currentUsername = window.chatContext.username;
|
|
this.isNewlywed = groomName === currentUsername || brideName === currentUsername;
|
|
this.show = true;
|
|
|
|
window.EffectManager?.play("wedding-fireworks");
|
|
},
|
|
|
|
close() {
|
|
this.show = false;
|
|
},
|
|
|
|
openWeddingSetup() {
|
|
window.openWeddingSetupModal?.(this.marriageId);
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 创建离婚公告弹窗 Alpine 数据,并播放雷雨组合特效。
|
|
*
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
export function marriageDivorcedModal() {
|
|
return {
|
|
show: false,
|
|
announcement: "",
|
|
subText: "",
|
|
|
|
open(detail) {
|
|
const userName = detail.user_username ?? detail.user?.username ?? "??";
|
|
const partnerName = detail.partner_username ?? detail.partner?.username ?? "??";
|
|
|
|
this.announcement = `${userName} 与 ${partnerName} 已解除婚姻关系`;
|
|
this.subText = detail.message || "往昔已矣,各自珍重。";
|
|
this.show = true;
|
|
|
|
window.EffectManager?.play("lightning");
|
|
|
|
// 雷电结束前后再叠加雨效,保留原本的离婚公告氛围。
|
|
setTimeout(() => {
|
|
window.EffectManager?.play("rain");
|
|
}, 3500);
|
|
},
|
|
|
|
close() {
|
|
this.show = false;
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 创建发起离婚确认弹窗 Alpine 数据,展示协议/强制离婚的惩罚结果。
|
|
*
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
export function divorceConfirmModal() {
|
|
return {
|
|
show: false,
|
|
marriageId: null,
|
|
mutualPenalty: 0,
|
|
forcedPenalty: 0,
|
|
mutualCooldown: 0,
|
|
forcedCooldown: 0,
|
|
acting: false,
|
|
error: "",
|
|
|
|
open(marriageId, config) {
|
|
this.marriageId = marriageId;
|
|
this.mutualPenalty = config.mutual_charm_penalty ?? 0;
|
|
this.forcedPenalty = config.forced_charm_penalty ?? 0;
|
|
this.mutualCooldown = config.mutual_cooldown_days ?? 0;
|
|
this.forcedCooldown = config.forced_cooldown_days ?? 0;
|
|
this.acting = false;
|
|
this.error = "";
|
|
this.show = true;
|
|
},
|
|
|
|
close() {
|
|
this.show = false;
|
|
},
|
|
|
|
async doConfirm() {
|
|
if (this.acting) {
|
|
return;
|
|
}
|
|
|
|
this.acting = true;
|
|
this.error = "";
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.divorceUrl(this.marriageId), {
|
|
method: "POST",
|
|
headers: {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
"X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
|
|
},
|
|
});
|
|
const data = await response.json();
|
|
|
|
this.close();
|
|
|
|
if (data.ok) {
|
|
window.chatDialog?.alert(data.message, "申请已发出 📩", "#6b7280");
|
|
} else {
|
|
window.chatDialog?.alert(data.message || "操作失败", "错误", "#dc2626");
|
|
}
|
|
} catch {
|
|
this.error = "网络请求失败,请重试。";
|
|
} finally {
|
|
this.acting = false;
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 创建离婚申请通知弹窗 Alpine 数据,处理同意或拒绝离婚请求。
|
|
*
|
|
* @returns {Record<string, any>}
|
|
*/
|
|
export function divorceRequestModal() {
|
|
return {
|
|
show: false,
|
|
marriageId: null,
|
|
initiatorName: "",
|
|
mutualPenalty: 0,
|
|
forcedPenalty: 0,
|
|
acting: false,
|
|
error: "",
|
|
|
|
open(detail) {
|
|
this.marriageId = detail.marriage_id;
|
|
this.initiatorName = detail.initiator_name ?? detail.divorcer_username ?? "对方";
|
|
this.mutualPenalty = detail.mutual_charm_penalty ?? 0;
|
|
this.forcedPenalty = detail.forced_charm_penalty ?? 0;
|
|
this.acting = false;
|
|
this.error = "";
|
|
this.show = true;
|
|
},
|
|
|
|
close() {
|
|
this.show = false;
|
|
},
|
|
|
|
async doAgree() {
|
|
if (this.acting) {
|
|
return;
|
|
}
|
|
|
|
this.acting = true;
|
|
this.error = "";
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.confirmDivorceUrl(this.marriageId), {
|
|
method: "POST",
|
|
headers: {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
"X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
|
|
},
|
|
body: JSON.stringify({
|
|
room_id: window.chatContext.roomId,
|
|
}),
|
|
});
|
|
const data = await response.json();
|
|
|
|
this.close();
|
|
window.chatDialog?.alert(data.message, data.ok ? "操作完成" : "失败", data.ok ? "#6b7280" : "#cc4444");
|
|
} catch {
|
|
this.error = "网络请求失败,请重试。";
|
|
} finally {
|
|
this.acting = false;
|
|
}
|
|
},
|
|
|
|
async doReject() {
|
|
if (this.acting) {
|
|
return;
|
|
}
|
|
|
|
this.acting = true;
|
|
this.error = "";
|
|
|
|
try {
|
|
const response = await fetch(window.chatContext.marriage.rejectDivorceUrl(this.marriageId), {
|
|
method: "POST",
|
|
headers: {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
"X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
|
|
},
|
|
body: JSON.stringify({
|
|
room_id: window.chatContext.roomId,
|
|
}),
|
|
});
|
|
const data = await response.json();
|
|
|
|
this.close();
|
|
window.chatDialog?.alert(data.message, data.ok ? "已处理" : "失败", data.ok ? "#d97706" : "#cc4444");
|
|
} catch {
|
|
this.error = "网络请求失败,请重试。";
|
|
} finally {
|
|
this.acting = false;
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 读取 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 方法和广播回调。
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
export function bindMarriageModalControls() {
|
|
window.appendSystemMessage = appendSystemMessage;
|
|
window.divorceConfirmModal = divorceConfirmModal;
|
|
window.divorceRequestModal = divorceRequestModal;
|
|
window.marriageAcceptedModal = marriageAcceptedModal;
|
|
window.marriageDivorcedModal = marriageDivorcedModal;
|
|
window.marriageIncomingModal = marriageIncomingModal;
|
|
window.marriageProposeModal = marriageProposeModal;
|
|
window.openProposeModal = openProposeModal;
|
|
window.openWeddingSetupModal = openWeddingSetupModal;
|
|
|
|
bindMarriageModalEvents();
|
|
bindMarriageModalBootstrap();
|
|
}
|