迁移婚姻通知弹窗组件

This commit is contained in:
2026-04-25 19:18:21 +08:00
parent 5b6f687db6
commit be0052119f
3 changed files with 199 additions and 156 deletions
+26 -2
View File
@@ -94,7 +94,16 @@ export {
switchMarriageTab,
tryDivorce,
} from "./chat-room/marriage-status.js";
export { appendSystemMessage, bindMarriageModalControls, marriageProposeModal, openProposeModal, openWeddingSetupModal } from "./chat-room/marriage-modals.js";
export {
appendSystemMessage,
bindMarriageModalControls,
marriageAcceptedModal,
marriageDivorcedModal,
marriageIncomingModal,
marriageProposeModal,
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";
@@ -266,7 +275,16 @@ import {
switchMarriageTab,
tryDivorce,
} from "./chat-room/marriage-status.js";
import { appendSystemMessage, bindMarriageModalControls, marriageProposeModal, openProposeModal, openWeddingSetupModal } from "./chat-room/marriage-modals.js";
import {
appendSystemMessage,
bindMarriageModalControls,
marriageAcceptedModal,
marriageDivorcedModal,
marriageIncomingModal,
marriageProposeModal,
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";
@@ -531,6 +549,9 @@ if (typeof window !== "undefined") {
bindMarriageStatusControls,
appendSystemMessage,
bindMarriageModalControls,
marriageAcceptedModal,
marriageDivorcedModal,
marriageIncomingModal,
marriageProposeModal,
closeMarriageStatusModal,
fetchMarriedList,
@@ -715,6 +736,9 @@ if (typeof window !== "undefined") {
window.marriageAction = marriageAction;
window.openMarriageStatusModal = openMarriageStatusModal;
window.appendSystemMessage = appendSystemMessage;
window.marriageAcceptedModal = marriageAcceptedModal;
window.marriageDivorcedModal = marriageDivorcedModal;
window.marriageIncomingModal = marriageIncomingModal;
window.marriageProposeModal = marriageProposeModal;
window.openProposeModal = openProposeModal;
window.openWeddingSetupModal = openWeddingSetupModal;
+173
View File
@@ -201,6 +201,176 @@ export function marriageProposeModal() {
};
}
/**
* 创建收到求婚弹窗 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 组件数据,避免直接访问 Alpine 私有字段。
*
@@ -401,6 +571,9 @@ function bindMarriageModalBootstrap() {
*/
export function bindMarriageModalControls() {
window.appendSystemMessage = appendSystemMessage;
window.marriageAcceptedModal = marriageAcceptedModal;
window.marriageDivorcedModal = marriageDivorcedModal;
window.marriageIncomingModal = marriageIncomingModal;
window.marriageProposeModal = marriageProposeModal;
window.openProposeModal = openProposeModal;
window.openWeddingSetupModal = openWeddingSetupModal;
@@ -683,160 +683,6 @@
{{-- ═══════════ Alpine.js 组件脚本 ═══════════ --}}
<script>
/**
* 收到求婚弹窗组件
*/
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 res = 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 res.json();
this.close();
if (data.status !== 'success') {
window.chatDialog?.alert(data.message || '操作失败', '提示', '#cc4444');
}
// 结婚成功后会收到 MarriageAccepted 全局广播
} catch {
window.chatDialog?.alert('网络异常', '错误', '#cc4444');
}
this.acting = false;
},
async doReject() {
if (this.acting) return;
this.acting = true;
try {
const res = 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 res.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;
}
};
}
/**
* 结婚成功弹窗组件(收到全局广播后触发)
*/
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 me = window.chatContext.username;
this.isNewlywed = (groomName === me || brideName === me);
this.show = true;
// 播放婚礼专属双倍礼花特效(全员)
if (window.EffectManager) {
window.EffectManager.play('wedding-fireworks');
}
},
close() {
this.show = false;
},
openWeddingSetup() {
window.openWeddingSetupModal?.(this.marriageId);
}
};
}
/**
* 离婚全屏公告弹窗组件(阴郁深色风格,雷雨双特效)
*/
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;
// 先播放雷电,再叠加下雨
if (window.EffectManager) {
window.EffectManager.play('lightning');
// 雷电通常持续约3秒,3.5秒后再起下雨(雨声会压住)
setTimeout(() => {
if (window.EffectManager) {
window.EffectManager.play('rain');
}
}, 3500);
}
},
close() {
this.show = false;
}
};
}
/**
* 发起离婚确认弹窗(发起方专用:展示双方结果 + 实时惩罚值)
*/