diff --git a/resources/js/chat-room.js b/resources/js/chat-room.js
index e4a453a..e3786d5 100644
--- a/resources/js/chat-room.js
+++ b/resources/js/chat-room.js
@@ -19,6 +19,7 @@
* - lottery-panel.js:提供双色球彩票 lotteryPanel Alpine 组件和全局开关入口。
* - mobile-drawer.js:处理移动端抽屉、房间列表和在线名单。
* - marriage-status.js:处理婚姻状态弹窗、已婚列表、接受拒绝和离婚申请。
+ * - marriage-modals.js:处理婚姻弹窗的系统消息、求婚和婚礼设置全局入口。
* - toolbar.js:处理工具栏按钮和功能快捷入口。
* - user-card.js:提供用户名片弹窗 Alpine 组件和管理/礼物操作。
* - user-target-actions.js:处理点击用户名切换私聊目标和打开名片。
@@ -93,6 +94,7 @@ export {
switchMarriageTab,
tryDivorce,
} from "./chat-room/marriage-status.js";
+export { appendSystemMessage, bindMarriageModalControls, openProposeModal, openWeddingSetupModal } from "./chat-room/marriage-modals.js";
export { bindToolbarControls, runFeatureShortcut, runToolbarAction } from "./chat-room/toolbar.js";
export { bindUserCardControls, userCardComponent } from "./chat-room/user-card.js";
export { bindUserTargetActions, openUserCard, switchTarget } from "./chat-room/user-target-actions.js";
@@ -264,6 +266,7 @@ import {
switchMarriageTab,
tryDivorce,
} from "./chat-room/marriage-status.js";
+import { appendSystemMessage, bindMarriageModalControls, openProposeModal, openWeddingSetupModal } from "./chat-room/marriage-modals.js";
import { bindToolbarControls, runFeatureShortcut, runToolbarAction } from "./chat-room/toolbar.js";
import { bindUserCardControls, userCardComponent } from "./chat-room/user-card.js";
import { bindUserTargetActions, openUserCard, switchTarget } from "./chat-room/user-target-actions.js";
@@ -526,11 +529,15 @@ if (typeof window !== "undefined") {
showInlineMsg,
unbindWechat,
bindMarriageStatusControls,
+ appendSystemMessage,
+ bindMarriageModalControls,
closeMarriageStatusModal,
fetchMarriedList,
fetchMyMarriageStatus,
marriageAction,
openMarriageStatusModal,
+ openProposeModal,
+ openWeddingSetupModal,
renderMarriedList,
renderMarriageStatus,
switchMarriageTab,
@@ -706,6 +713,9 @@ if (typeof window !== "undefined") {
window.fetchMyMarriageStatus = fetchMyMarriageStatus;
window.marriageAction = marriageAction;
window.openMarriageStatusModal = openMarriageStatusModal;
+ window.appendSystemMessage = appendSystemMessage;
+ window.openProposeModal = openProposeModal;
+ window.openWeddingSetupModal = openWeddingSetupModal;
window.renderMarriedList = renderMarriedList;
window.renderMarriageStatus = renderMarriageStatus;
window.switchMarriageTab = switchMarriageTab;
@@ -761,6 +771,7 @@ if (typeof window !== "undefined") {
bindFishingControls();
bindFortunePanelControls();
bindMarriageStatusControls();
+ bindMarriageModalControls();
bindProfileControls();
bindShopControls();
bindCompactShopPanelControls();
diff --git a/resources/js/chat-room/marriage-modals.js b/resources/js/chat-room/marriage-modals.js
new file mode 100644
index 0000000..d49aaf7
--- /dev/null
+++ b/resources/js/chat-room/marriage-modals.js
@@ -0,0 +1,92 @@
+// 婚姻弹窗辅助入口,承接从 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 = `${html}`;
+ container.appendChild(div);
+ container.scrollTop = container.scrollHeight;
+}
+
+/**
+ * 打开求婚弹窗入口,从用户名片按钮触发。
+ *
+ * @param {string} username 求婚对象用户名
+ * @returns {Promise}
+ */
+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);
+ }
+}
+
+/**
+ * 暴露婚姻弹窗存量入口,兼容 Blade 内 onclick、Alpine 方法和广播回调。
+ *
+ * @returns {void}
+ */
+export function bindMarriageModalControls() {
+ window.appendSystemMessage = appendSystemMessage;
+ window.openProposeModal = openProposeModal;
+ window.openWeddingSetupModal = openWeddingSetupModal;
+}
diff --git a/resources/views/chat/partials/marriage-modals.blade.php b/resources/views/chat/partials/marriage-modals.blade.php
index 6018cdb..debe7a2 100644
--- a/resources/views/chat/partials/marriage-modals.blade.php
+++ b/resources/views/chat/partials/marriage-modals.blade.php
@@ -683,21 +683,6 @@
{{-- ═══════════ Alpine.js 组件脚本 ═══════════ --}}