Files
chatroom/resources/views/chat/partials/marriage-modals.blade.php
T
2026-04-25 19:20:33 +08:00

834 lines
48 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{--
文件功能:婚姻系统前端弹窗组件集合
包含:
1. 求婚弹窗(#marriage-propose-modal):选戒指→求婚
2. 求婚接收弹窗(#marriage-incoming-modal):被求婚方同意/拒绝
3. 结婚成功弹窗(#marriage-accepted-modal):恭喜UI + 婚礼设置入口
4. 婚礼设置弹窗(#wedding-setup-modal):选档位→立即/定时→支付
5. 婚礼红包弹窗(#wedding-envelope-modal):全局弹出,点击领取
6. 婚姻状态弹窗(#marriage-status-modal):查看自己的婚姻信息
7. 名片婚姻信息区(注入到 user-card JS 组件中)
@author ChatRoom Laravel
@version 1.0.0
--}}
{{-- ═══════════ 1. 求婚弹窗 ═══════════ --}}
<div id="marriage-propose-modal" x-data="marriageProposeModal()" x-show="show" x-cloak>
<div style="position:fixed; inset:0; background:rgba(15,5,25,.75); backdrop-filter:blur(4px);
z-index:9800; display:flex; align-items:center; justify-content:center; padding:16px;"
x-on:click.self="close()">
<div x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
style="width:420px; max-width:100%; border-radius:24px; overflow:hidden;
box-shadow:0 32px 80px rgba(244,63,94,.45), 0 0 0 1px rgba(244,63,94,.15);">
{{-- ───── 封面区域 ────── --}}
<div
style="background:linear-gradient(145deg,#be185d 0%,#f43f5e 45%,#fb7185 80%,#fda4af 100%);
padding:32px 24px 24px; text-align:center; position:relative;">
{{-- 关闭按钮 --}}
<button x-on:click="close()"
style="position:absolute; top:14px; right:14px; background:rgba(255,255,255,.2);
border:none; color:#fff; width:32px; height:32px; border-radius:50%;
cursor:pointer; font-size:16px; line-height:32px; transition:background .15s;"
onmouseover="this.style.background='rgba(255,255,255,.35)'"
onmouseout="this.style.background='rgba(255,255,255,.2)'"></button>
{{-- 大戒指图标 --}}
<div style="font-size:52px; margin-bottom:12px; filter:drop-shadow(0 4px 12px rgba(0,0,0,.25));">💍
</div>
{{-- 标题 --}}
<div style="color:#fff; font-size:22px; font-weight:800; letter-spacing:.5px; margin-bottom:6px;">
TA 求婚
</div>
{{-- 对象名 --}}
<div
style="display:inline-flex; align-items:center; gap:6px;
background:rgba(255,255,255,.18); border-radius:999px;
padding:4px 14px; font-size:13px; color:#fff;">
<span>💕</span>
<span x-text="targetUsername" style="font-weight:bold;"></span>
</div>
</div>
{{-- ───── 内容区域 ────── --}}
<div style="background:#fff; padding:24px;">
{{-- 错误提示 --}}
<div x-show="error" x-transition
style="display:none; background:#fef2f2; border-left:3px solid #f43f5e;
color:#dc2626; border-radius:8px; padding:10px 14px; font-size:12px; margin-bottom:16px;"
x-text="error"></div>
{{-- 加载中 --}}
<div x-show="loading" style="text-align:center; padding:28px; color:#f43f5e;">
<div style="font-size:28px; margin-bottom:8px;">💍</div>
<div style="font-size:13px; color:#9ca3af;">正在加载戒指列表…</div>
</div>
{{-- 戒指展示区 --}}
<div x-show="!loading">
{{-- 区域标题 --}}
<div style="display:flex; align-items:center; gap:8px; margin-bottom:14px;">
<div
style="width:3px; height:16px; background:linear-gradient(#f43f5e,#ec4899); border-radius:2px;">
</div>
<span style="font-size:13px; font-weight:700; color:#1f2937;">赠送的求婚戒</span>
<span style="font-size:11px; color:#d1d5db;">戒指消耗后不退,拒绝则遗失</span>
</div>
{{-- 无戒指提示 --}}
<div x-show="rings.length === 0"
style="text-align:center; padding:28px 16px; background:#fdf2f8; border-radius:14px;
border:1.5px dashed #fbcfe8; margin-bottom:16px;">
<div style="font-size:32px; margin-bottom:8px;">💔</div>
<div style="font-size:13px; color:#9ca3af; margin-bottom:10px;">背包里还没有戒指哦</div>
<button data-marriage-open-shop
style="background:linear-gradient(135deg,#f43f5e,#ec4899); color:#fff; border:none;
border-radius:8px; padding:7px 18px; font-size:12px; font-weight:bold; cursor:pointer;">
🛒 前往商店购买
</button>
</div>
{{-- 戒指展示(居中,只展示第一枚,不可选) --}}
<div x-show="rings.length > 0" style="display:flex; justify-content:center; margin-bottom:18px;">
<template x-if="rings.length > 0">
<div
style="text-align:center; padding:18px 28px; border-radius:16px;
background:linear-gradient(135deg,#fff1f2,#fdf2f8);
border:2px solid #f43f5e; box-shadow:0 4px 18px rgba(244,63,94,.15);
min-width:140px;">
<div style="font-size:42px; margin-bottom:8px;" x-text="rings[0].icon"></div>
<div style="font-weight:700; font-size:14px; color:#1f2937; margin-bottom:6px;"
x-text="rings[0].name"></div>
<div style="font-size:11px; color:#f43f5e; font-weight:600;"
x-text="'💞 亲密 +' + rings[0].intimacy_bonus"></div>
<div style="font-size:11px; color:#a855f7; margin-top:2px;"
x-text="'✨ 魅力 +' + rings[0].charm_bonus"></div>
</div>
</template>
</div>
{{-- ── 婚礼档位选择与费用提示面板 ── --}}
@php
$activeTiers = \App\Models\WeddingTier::where('is_active', true)->orderBy('amount')->get();
@endphp
<div style="margin-bottom:14px; text-align:left;">
<div style="display:flex; align-items:center; gap:8px; margin-bottom:8px;">
<div
style="width:3px; height:14px; background:linear-gradient(#f59e0b,#d97706); border-radius:2px;">
</div>
<span style="font-size:12px; font-weight:700; color:#4b5563;">预设婚礼档位</span>
</div>
<select x-model="selectedTierId" required
style="width:100%; padding:8px 10px; border-radius:8px; border:1px solid #f43f5e; background:#fff; font-size:13px; color:#1f2937; margin-bottom:10px;">
<template x-for="tier in tiers" :key="tier.id">
<option :value="tier.id" x-text="`${tier.icon} ${tier.name} (💰 ${tier.amount})`">
</option>
</template>
</select>
<div style="font-size:11px; color:#9ca3af; margin-top:-6px; margin-bottom:8px;">🎊
必须选择婚礼档位,婚礼红包会撒给在场所有人!</div>
<div x-show="selectedTier" x-transition
style="display:none; border-radius:12px; padding:12px 14px; font-size:12px; line-height:1.7; transition:all .2s;"
:style="canAfford ? 'background:#f0fdf4; border:1.5px solid #bbf7d0;' :
'background:#fef2f2; border:1.5px solid #fecaca;'">
<div style="font-weight:700; margin-bottom:4px;"
:style="canAfford ? 'color:#15803d' : 'color:#dc2626'"
x-text="canAfford ? '✅ 您的金币足以预定该婚礼' : '⚠️ 金币不足,请降低档位或准备金币'">
</div>
<div style="color:#6b7280;">
婚礼预冻结:<strong style="color:#f43f5e;"
x-text="'💰 ' + (selectedTier ? Number(selectedTier.amount).toLocaleString() : 0)"></strong>
金币
</div>
<div :style="canAfford ? 'color:#15803d' : 'color:#dc2626'">
当前余额:<strong>💰 {{ number_format($user->jjb) }}</strong> 金币
</div>
<div style="color:#9ca3af; font-size:11px; margin-top:4px;">需男方独自承担预冻结金币,对方同意后即刻举行。被拒则全额退回!
</div>
</div>
</div>
{{-- 底部按钮:样式修复并参照大卡片弹窗 --}}
<div style="display:flex; gap:12px;">
<button x-on:click="close()"
style="flex:1; padding:10px 0; border-radius:8px; font-size:13px; font-weight:bold;
cursor:pointer; border:none; background:#f1f5f9; color:#6b7280;
transition:background .15s;"
onmouseover="this.style.background='#e2e8f0'" onmouseout="this.style.background='#f1f5f9'">
取消
</button>
<button x-on:click="doPropose()"
:disabled="sending || !selectedRing || rings.length === 0 || !canAfford"
style="flex:1; padding:10px 0; border-radius:8px; font-size:13px; font-weight:bold; border:none; transition:all .2s;"
:style="(sending || !selectedRing || rings.length === 0 || !canAfford) ? {
background: '#f1f5f9',
color: '#94a3b8',
cursor: 'not-allowed',
boxShadow: 'none'
} : {
background: 'linear-gradient(135deg,#be185d,#f43f5e,#ec4899)',
color: '#fff',
cursor: 'pointer',
boxShadow: '0 4px 12px rgba(244,63,94,0.3)'
}">
<span x-text="sending ? '💌 发送中…' : '💍 确认求婚'"></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
{{-- ═══════════ 2. 收到求婚弹窗 ═══════════ --}}
<div id="marriage-incoming-modal" x-data="marriageIncomingModal()" x-show="show" x-cloak>
<div
style="position:fixed; inset:0; background:rgba(0,0,0,.65);
z-index:9850; display:flex; align-items:center; justify-content:center;">
<div
style="width:380px; max-width:95vw; background:#fff; border-radius:20px;
box-shadow:0 20px 60px rgba(244,63,94,.4); overflow:hidden; text-align:center;">
<div style="background:linear-gradient(135deg,#f43f5e,#f97316); padding:20px;">
<div style="font-size:40px; margin-bottom:6px;">💌</div>
<div style="color:#fff; font-weight:bold; font-size:18px;">收到求婚啦!</div>
</div>
<div style="padding:20px;">
<div style="font-size:14px; color:#374151; margin-bottom:6px;">
<strong x-text="proposerName" style="color:#f43f5e;"></strong>
向你送上了求婚戒指
</div>
<div x-show="ringName"
style="display:inline-flex; align-items:center; gap:6px;
background:#fff1f2; border:1px solid #fecdd3; border-radius:30px;
padding:6px 14px; font-size:13px; color:#e11d48; margin-bottom:4px;">
<span x-text="ringIcon" style="font-size:18px;"></span>
<span x-text="ringName"></span>
</div>
<div style="font-size:11px; color:#9ca3af; margin-bottom:18px;">
戒指求婚有效期 <strong>48小时</strong>,过期自动失效且戒指遗失
</div>
<div x-show="expiresAt" style="font-size:11px; color:#f59e0b; margin-bottom:14px;"
x-text="'过期时间:' + expiresAt"></div>
<div style="display:flex; gap:10px;">
<button x-on:click="doReject()" :disabled="acting"
style="flex:1; padding:11px; border-radius:10px; font-size:13px; font-weight:bold;
cursor:pointer; background:#f1f5f9; color:#374151; border:1px solid #e2e8f0;">
<span x-text="acting ? '处理中…' : '😢 婉拒'"></span>
</button>
<button x-on:click="doAccept()" :disabled="acting"
style="flex:2; padding:11px; border-radius:10px; font-size:13px; font-weight:bold;
cursor:pointer; background:linear-gradient(135deg,#f43f5e,#ec4899);
color:#fff; border:none;">
<span x-text="acting ? '处理中…' : '💑 答应啦!'"></span>
</button>
</div>
</div>
</div>
</div>
</div>
{{-- ═══════════ 3. 结婚成功全屏公告 ═══════════ --}}
<div id="marriage-accepted-modal" x-data="marriageAcceptedModal()" x-show="show" x-cloak>
<div x-transition
style="position:fixed; inset:0; background:rgba(0,0,0,.7);
z-index:9900; display:flex; align-items:center; justify-content:center;">
<div
style="width:460px; max-width:95vw; background:#fff; border-radius:24px;
box-shadow:0 24px 80px rgba(244,63,94,.5); overflow:hidden; text-align:center;">
<div style="background:linear-gradient(135deg,#f43f5e,#ec4899,#a855f7); padding:28px 20px;">
<div style="font-size:50px; margin-bottom:8px;">💑</div>
<div style="color:#fff; font-weight:bold; font-size:20px; margin-bottom:4px;">
🎊 天作之合!
</div>
<div style="color:rgba(255,255,255,.9); font-size:15px;" x-text="announcement"></div>
</div>
<div style="padding:20px 24px;">
<div style="font-size:13px; color:#6b7280; margin-bottom:16px;" x-text="subText"></div>
<button x-on:click="close()"
style="padding:10px 32px; background:#f1f5f9; border:none; border-radius:10px;
font-size:13px; color:#6b7280; cursor:pointer;">关闭</button>
</div>
</div>
</div>
</div>
{{-- ═══════════ 3.5. 离婚全屏公告(阴郁深色风格 + 雷雨特效) ═══════════ --}}
<div id="marriage-divorced-modal" x-data="marriageDivorcedModal()" x-show="show" x-cloak>
<div x-transition
style="position:fixed; inset:0; background:rgba(10,14,21,.82);
z-index:9900; display:flex; align-items:center; justify-content:center;">
<div
style="width:460px; max-width:95vw; background:linear-gradient(160deg,#1e2433,#252d3a);
border:1px solid rgba(100,116,140,.25);
border-radius:24px; box-shadow:0 24px 80px rgba(0,0,0,.7); overflow:hidden; text-align:center;">
{{-- 头部 --}}
<div
style="padding:32px 24px 20px;
background:linear-gradient(160deg,#2d3547,#1e2736);">
{{-- 断裂心形动效 --}}
<div
style="font-size:52px; margin-bottom:12px; line-height:1; position:relative; display:inline-block;">
<span style="display:inline-block; animation:divorce-shake 0.6s ease 0.3s both;">💔</span>
</div>
<div
style="color:#94a3b8; font-weight:bold; font-size:13px; letter-spacing:3px; text-transform:uppercase; margin-bottom:10px;">
缘尽于此
</div>
<div style="color:#e2e8f0; font-weight:bold; font-size:18px; margin-bottom:6px;"
x-text="announcement"></div>
<div style="color:#64748b; font-size:12px;" x-text="subText"></div>
</div>
{{-- 底部按钮 --}}
<div style="padding:18px 24px;">
<button x-on:click="close()"
style="padding:10px 40px; background:rgba(100,116,140,.15);
border:1px solid rgba(100,116,140,.3); border-radius:10px;
font-size:13px; color:#94a3b8; cursor:pointer; transition:all .2s;"
onmouseover="this.style.background='rgba(100,116,140,.25)'"
onmouseout="this.style.background='rgba(100,116,140,.15)'">
知道了
</button>
</div>
</div>
</div>
</div>
<style>
@keyframes divorce-shake {
0% {
transform: rotate(0deg) scale(1);
}
20% {
transform: rotate(-8deg) scale(1.1);
}
40% {
transform: rotate(6deg) scale(1.05);
}
60% {
transform: rotate(-4deg) scale(1.1);
}
80% {
transform: rotate(3deg) scale(1);
}
100% {
transform: rotate(0deg) scale(1);
}
}
</style>
{{-- ═══════════ 3.5. 发起离婚确认弹窗(发起方专用 + 后果说明) ═══════════ --}}
<div id="divorce-confirm-modal" x-data="divorceConfirmModal()" x-show="show" x-cloak>
<div x-transition
style="position:fixed; inset:0; background:rgba(10,14,21,.87); backdrop-filter:blur(3px);
z-index:9925; display:flex; align-items:center; justify-content:center; padding:16px;">
<div
style="width:480px; max-width:95vw; background:#1a1f2e; border:1px solid rgba(100,116,140,.3);
border-radius:24px; box-shadow:0 32px 80px rgba(0,0,0,.8); overflow:hidden;">
{{-- 头部 --}}
<div
style="padding:24px 28px 16px; background:linear-gradient(160deg,#252d3a,#1e2736); text-align:center;">
<div style="font-size:44px; margin-bottom:10px;">📄</div>
<div style="color:#f1f5f9; font-weight:bold; font-size:18px; margin-bottom:4px;">发起协议离婚申请</div>
<div style="color:#64748b; font-size:12px;">请仔细阅读以下后果,确认后再提交申请</div>
</div>
<div style="padding:16px 24px;">
{{-- 对方同意:协议离婚 --}}
<div
style="background:rgba(100,116,140,.08); border:1px solid rgba(100,116,140,.25); border-radius:12px; padding:12px 16px; margin-bottom:10px;">
<div style="color:#94a3b8; font-weight:bold; font-size:13px; margin-bottom:6px;"> 若对方同意(协议离婚)
</div>
<ul style="color:#94a3b8; font-size:12px; line-height:2; margin:0; padding-left:20px;">
<li>婚姻关系<strong style="color:#e2e8f0;">立即解除</strong>,亲密度清零</li>
<li>双方各被扣除 <strong style="color:#fca5a5;" x-text="mutualPenalty + ' 点魅力值'"></strong></li>
<li>双方进入 <strong style="color:#e2e8f0;" x-text="mutualCooldown + ' 天'"></strong>
离婚冷静期,期间无法再次结婚</li>
</ul>
</div>
{{-- 对方拒绝:强制离婚,自己赔钱 --}}
<div
style="background:rgba(239,68,68,.08); border:1px solid rgba(239,68,68,.3); border-radius:12px; padding:12px 16px; margin-bottom:16px;">
<div style="color:#fca5a5; font-weight:bold; font-size:13px; margin-bottom:6px;">⚠️
若对方拒绝(视为强制离婚,后果由你承担)</div>
<ul style="color:#94a3b8; font-size:12px; line-height:2; margin:0; padding-left:20px;">
<li>婚姻关系<strong style="color:#fca5a5;">立即强制解除</strong></li>
<li><strong style="color:#fca5a5;">你将被扣除 <span x-text="forcedPenalty"></span>
点魅力值</strong>作为惩罚</li>
<li><strong style="color:#fca5a5;">你当前一半的金币将赔偿给对方</strong></li>
<li>你进入 <strong style="color:#fca5a5;" x-text="forcedCooldown + ' 天'"></strong>
强制离婚冷静期,期间无法再次结婚</li>
</ul>
</div>
{{-- 操作按钮 --}}
<div style="display:flex; gap:10px; justify-content:center;">
<button x-on:click="doConfirm()" :disabled="acting"
style="flex:1; padding:12px 0; border-radius:12px; border:none; font-size:14px; font-weight:bold; cursor:pointer; transition:all .2s;
background:linear-gradient(135deg,#475569,#334155); color:#e2e8f0; box-shadow:0 4px 12px rgba(0,0,0,.3);"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<span x-text="acting ? '发送中…' : '📄 确认发起申请'"></span>
</button>
<button x-on:click="close()" :disabled="acting"
style="flex:0 0 auto; padding:12px 24px; border-radius:12px; font-size:13px; cursor:pointer; transition:all .2s;
background:rgba(100,116,140,.12); border:1px solid rgba(100,116,140,.3); color:#64748b;"
onmouseover="this.style.background='rgba(100,116,140,.22)'"
onmouseout="this.style.background='rgba(100,116,140,.12)'">
取消
</button>
</div>
<div x-show="error" x-transition
style="display:none; margin-top:10px; background:rgba(239,68,68,.1); border:1px solid rgba(239,68,68,.3); border-radius:8px; padding:8px 12px; font-size:12px; color:#fca5a5; text-align:center;"
x-text="error"></div>
</div>
</div>
</div>
</div>
{{-- ═══════════ 3.6. 离婚申请通知弹窗(三选按钮 + 后果说明) ═══════════ --}}
<div id="divorce-request-modal" x-data="divorceRequestModal()" x-show="show" x-cloak>
<div x-transition
style="position:fixed; inset:0; background:rgba(10,14,21,.85); backdrop-filter:blur(3px);
z-index:9920; display:flex; align-items:center; justify-content:center; padding:16px;">
<div
style="width:480px; max-width:95vw; background:#1a1f2e; border:1px solid rgba(100,116,140,.3);
border-radius:24px; box-shadow:0 32px 80px rgba(0,0,0,.8); overflow:hidden;">
{{-- 头部 --}}
<div
style="padding:28px 28px 20px; background:linear-gradient(160deg,#252d3a,#1e2736); text-align:center;">
<div style="font-size:48px; margin-bottom:12px; animation:divorce-shake 0.7s ease 0.2s both;">💔</div>
<div style="color:#f1f5f9; font-weight:bold; font-size:19px; margin-bottom:6px;">收到离婚申请</div>
<div style="color:#94a3b8; font-size:14px; line-height:1.6;" x-text="initiatorName + ' 向你提出了协议离婚申请。'">
</div>
<div style="color:#64748b; font-size:12px; margin-top:4px;">请仔细阅读以下后果说明,做出你的选择:</div>
</div>
{{-- 后果说明区 --}}
<div style="padding:16px 24px;">
{{-- 同意后果 --}}
<div
style="background:rgba(239,68,68,.08); border:1px solid rgba(239,68,68,.25); border-radius:12px; padding:12px 16px; margin-bottom:10px;">
<div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
<span
style="background:#ef4444; border-radius:50%; width:22px; height:22px; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:bold; color:#fff; flex-shrink:0;"></span>
<span style="color:#fca5a5; font-weight:bold; font-size:13px;">同意离婚</span>
</div>
<ul style="color:#94a3b8; font-size:12px; line-height:2; margin:0; padding-left:30px;">
<li>婚姻关系<strong style="color:#fca5a5;">立即解除</strong>,所有亲密度清零</li>
<li>双方各被扣除 <strong style="color:#fca5a5;" x-text="mutualPenalty + ' 点魅力值'">? 点魅力值</strong>
</li>
<li>双方都将进入<strong style="color:#fca5a5;">离婚冷静期</strong>,期间无法再次结婚</li>
</ul>
</div>
{{-- 拒绝后果 --}}
<div
style="background:rgba(234,179,8,.08); border:1px solid rgba(234,179,8,.25); border-radius:12px; padding:12px 16px; margin-bottom:10px;">
<div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
<span
style="background:#ca8a04; border-radius:50%; width:22px; height:22px; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:bold; color:#fff; flex-shrink:0;"></span>
<span style="color:#fde68a; font-weight:bold; font-size:13px;">不同意(强制离婚)</span>
</div>
<ul style="color:#94a3b8; font-size:12px; line-height:2; margin:0; padding-left:30px;">
<li>视同<strong style="color:#fde68a;">强制离婚</strong>,婚姻<strong
style="color:#fde68a;">立即解除</strong></li>
<li>申请方被扣除大量魅力值作为<strong style="color:#fde68a;">惩罚</strong></li>
<li>申请方当前<strong style="color:#fde68a;">一半金币赔偿给你</strong>(入账到你账户)</li>
<li>申请方进入<strong style="color:#fde68a;">强制离婚冷静期</strong>,期间无法再次结婚</li>
</ul>
</div>
{{-- 取消(稍后处理) --}}
<div
style="background:rgba(100,116,140,.06); border:1px solid rgba(100,116,140,.2); border-radius:12px; padding:10px 16px; margin-bottom:16px;">
<div style="display:flex; align-items:center; gap:8px; margin-bottom:4px;">
<span
style="background:#475569; border-radius:50%; width:22px; height:22px; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:bold; color:#fff; flex-shrink:0;"></span>
<span style="color:#94a3b8; font-weight:bold; font-size:13px;">稍后决定</span>
</div>
<ul style="color:#64748b; font-size:12px; line-height:2; margin:0; padding-left:30px;">
<li>关闭此弹窗,<strong style="color:#94a3b8;">暂不做决定</strong></li>
<li>下次登录或刷新页面时<strong style="color:#94a3b8;">仍会再次弹出</strong>提示</li>
<li>72 小时内若不处理,系统将<strong style="color:#94a3b8;">自动视为对方强制离婚</strong></li>
</ul>
</div>
{{-- 三个按钮 --}}
<div style="display:flex; gap:10px; justify-content:center;">
{{-- 同意 --}}
<button x-on:click="doAgree()" :disabled="acting"
style="flex:1; padding:12px 0; border-radius:12px; border:none; font-size:14px; font-weight:bold; cursor:pointer; transition:all .2s;
background:linear-gradient(135deg,#dc2626,#b91c1c); color:#fff; box-shadow:0 4px 12px rgba(220,38,38,.35);"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<span x-text="acting ? '处理中…' : '✓ 同意离婚'"></span>
</button>
{{-- 拒绝 --}}
<button x-on:click="doReject()" :disabled="acting"
style="flex:1; padding:12px 0; border-radius:12px; border:none; font-size:14px; font-weight:bold; cursor:pointer; transition:all .2s;
background:linear-gradient(135deg,#d97706,#b45309); color:#fff; box-shadow:0 4px 12px rgba(217,119,6,.3);"
onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<span x-text="acting ? '处理中…' : '✕ 拒绝离婚'"></span>
</button>
{{-- 取消 --}}
<button x-on:click="close()" :disabled="acting"
style="flex:0 0 auto; padding:12px 20px; border-radius:12px; font-size:13px; cursor:pointer; transition:all .2s;
background:rgba(100,116,140,.15); border:1px solid rgba(100,116,140,.3); color:#94a3b8;"
onmouseover="this.style.background='rgba(100,116,140,.25)'"
onmouseout="this.style.background='rgba(100,116,140,.15)'">
稍后
</button>
</div>
<div x-show="error" x-transition
style="display:none; background:rgba(239,68,68,.1); border:1px solid rgba(239,68,68,.3); border-radius:8px; padding:8px 12px; margin-top:12px; font-size:12px; color:#fca5a5; text-align:center;"
x-text="error"></div>
</div>
</div>
</div>
</div>
{{-- ═══════════ 4. 婚礼设置弹窗 ═══════════ --}}
<div id="wedding-setup-modal" x-data="weddingSetupModal()" x-show="show" x-cloak>
<div
style="position:fixed; inset:0; background:rgba(0,0,0,.65);
z-index:9820; display:flex; align-items:center; justify-content:center;">
<div
style="width:500px; max-width:95vw; background:#fff; border-radius:20px;
box-shadow:0 20px 60px rgba(245,158,11,.3); overflow:hidden;">
<div
style="background:linear-gradient(135deg,#f59e0b,#d97706); padding:16px 20px;
display:flex; align-items:center; justify-content:space-between;">
<div>
<div style="color:#fff; font-weight:bold; font-size:17px;">🎊 举办婚礼庆典</div>
<div style="color:rgba(255,255,255,.85); font-size:12px; margin-top:2px;">宴请全场,赠送红包大礼</div>
</div>
<button x-on:click="close()"
style="background:rgba(255,255,255,.25); border:none; color:#fff;
width:30px; height:30px; border-radius:50%; cursor:pointer; font-size:18px;">×</button>
</div>
<div style="padding:20px;">
<div x-show="error"
style="display:none; background:#fef2f2; border:1px solid #fecaca;
color:#dc2626; border-radius:8px; padding:10px 14px; font-size:12px; margin-bottom:14px;"
x-text="error"></div>
{{-- 档位选择 --}}
<div style="font-size:13px; font-weight:bold; color:#374151; margin-bottom:10px;">选择庆典档位</div>
<div x-show="loading" style="text-align:center; padding:16px; color:#f59e0b;">加载档位中…</div>
<div x-show="!loading"
style="display:grid; grid-template-columns:repeat(5,1fr); gap:8px; margin-bottom:16px;">
<template x-for="tier in tiers" :key="tier.id">
<div x-on:click="selectedTier = tier"
:style="selectedTier && selectedTier.id === tier.id ?
'border:2px solid #f59e0b; background:#fffbeb;' :
'border:2px solid #e2e8f0; background:#fff;'"
style="padding:10px 6px; border-radius:10px; cursor:pointer; text-align:center; transition:all .15s;">
<div style="font-size:22px;" x-text="tier.icon"></div>
<div style="font-size:11px; font-weight:bold; color:#374151; margin-top:3px;"
x-text="tier.name"></div>
<div style="font-size:11px; color:#f59e0b; font-weight:bold;"
x-text="tier.amount.toLocaleString() + ' 金'"></div>
</div>
</template>
</div>
{{-- 支付方式 --}}
<div x-show="selectedTier" style="display:none;">
<div style="font-size:13px; font-weight:bold; color:#374151; margin-bottom:10px;">金币支付方式</div>
<div style="display:flex; gap:10px; margin-bottom:16px;">
<label
style="flex:1; display:flex; align-items:center; gap:8px; padding:10px;
border-radius:10px; cursor:pointer;"
:style="payBy === 'groom' ? 'border:2px solid #f59e0b; background:#fffbeb;' :
'border:2px solid #e2e8f0;'">
<input type="radio" x-model="payBy" value="groom" style="accent-color:#f59e0b;">
<span style="font-size:12px; font-weight:bold;">由我全额支付</span>
</label>
<label
style="flex:1; display:flex; align-items:center; gap:8px; padding:10px;
border-radius:10px; cursor:pointer;"
:style="payBy === 'split' ? 'border:2px solid #f59e0b; background:#fffbeb;' :
'border:2px solid #e2e8f0;'">
<input type="radio" x-model="payBy" value="split" style="accent-color:#f59e0b;">
<span style="font-size:12px; font-weight:bold;">双方各出一半</span>
</label>
</div>
{{-- 费用摘要 --}}
<div x-show="selectedTier"
style="display:none; background:#fffbeb; border:1px solid #fde68a;
border-radius:10px; padding:12px 14px; font-size:12px; color:#92400e; margin-bottom:16px;">
<div style="display:flex; justify-content:space-between; margin-bottom:4px;">
<span>红包总额</span>
<strong x-text="selectedTier ? selectedTier.amount.toLocaleString() + ' 金' : '—'"></strong>
</div>
<div style="display:flex; justify-content:space-between; margin-bottom:4px;">
<span>你需支付</span>
<strong x-text="myCost + ' 金'"></strong>
</div>
<div x-show="payBy === 'split'" style="display:none; font-size:11px; color:#b45309;">
另一半将在婚礼触发后自动从另一方账号扣除
</div>
</div>
<button x-on:click="doSetup()" :disabled="sending || !selectedTier"
style="width:100%; padding:13px; border:none; border-radius:12px; font-size:14px;
font-weight:bold; cursor:pointer; transition:all .2s;"
:style="(sending || !selectedTier) ?
'background:#f1f5f9; color:#94a3b8; cursor:not-allowed;' :
'background:linear-gradient(135deg,#f59e0b,#d97706); color:#fff;'">
<span x-text="sending ? '设置中…' : '🎊 确认举办婚礼'"></span>
</button>
</div>
</div>
</div>
</div>
</div>
{{-- ═══════════ 5. 婚礼红包弹窗(全局触发) ═══════════ --}}
<div id="wedding-envelope-modal" x-data="weddingEnvelopeModal()" x-show="show" x-cloak>
<div x-transition
style="position:fixed; inset:0; background:rgba(0,0,0,.6);
z-index:9910; display:flex; align-items:center; justify-content:center;">
<div
style="width:380px; max-width:95vw;
background:linear-gradient(160deg,#c0392b,#e74c3c,#c0392b);
border-radius:20px; overflow:hidden; text-align:center;
box-shadow:0 24px 80px rgba(231,76,60,.65), 0 0 0 1px rgba(255,210,100,.25);
border:1px solid rgba(255,210,100,.3);">
<div style="padding:28px 20px 12px;">
<div style="font-size:56px; margin-bottom:8px; animation:pulse 1.5s infinite;">🧧</div>
<div style="color:#fff8dc; font-weight:bold; font-size:18px; margin-bottom:4px; text-shadow:0 1px 4px rgba(0,0,0,.3);"
x-text="title"></div>
<div style="color:rgba(255,248,220,.75); font-size:12px; margin-bottom:8px;" x-text="subTitle"></div>
{{-- 未领取 --}}
<div x-show="!claimed" style="display:none;">
<div style="color:rgba(255,248,220,.55); font-size:11px; margin-bottom:20px;">
红包有效期 <strong style="color:#fcd34d;">24小时</strong>,过期自动消失
</div>
{{-- 圆形领取按钮(仿「開」按钮,全样式写入 :style 避免 Alpine 覆盖) --}}
<div style="display:flex; justify-content:center; margin-bottom:20px;">
<button x-on:click="doClaim()" :disabled="claiming"
onmouseover="if(!this.disabled)this.style.transform='scale(1.08)'"
onmouseout="this.style.transform=''"
:style="claiming
?
'width:130px; height:130px; border-radius:50%; border:none; cursor:not-allowed; display:flex; align-items:center; justify-content:center; flex-shrink:0; box-sizing:border-box; transition:all .25s; font-size:28px; font-weight:900; letter-spacing:2px; background:#c8b89a; color:rgba(100,50,20,.45); box-shadow:none;' :
'width:130px; height:130px; border-radius:50%; border:none; cursor:pointer; display:flex; align-items:center; justify-content:center; flex-shrink:0; box-sizing:border-box; transition:all .25s; font-size:28px; font-weight:900; letter-spacing:2px; background:#f5e6c8; color:#8b3a1a; box-shadow:0 6px 28px rgba(0,0,0,.35), inset 0 -4px 10px rgba(139,58,26,.12); animation:grab-btn-pulse 1.8s ease-in-out infinite;'">
<span x-text="claiming ? '…' : '领取'"></span>
</button>
</div>
</div>
{{-- 已领取 --}}
<div x-show="claimed" style="display:none; padding-bottom:8px;">
<div style="font-size:40px; margin-bottom:6px; color:#fcd34d; font-weight:bold;"
x-text="'+' + claimedAmount.toLocaleString() + ' 金'"></div>
<div style="color:#fff8dc; font-size:13px;">🎉 恭喜你领取了红包!</div>
<div style="color:rgba(255,248,220,.6); font-size:11px; margin-top:4px;">金币已自动到账</div>
</div>
</div>
{{-- 关闭按钮 --}}
<div style="padding:0 20px 24px; display:flex; justify-content:center;">
<button x-on:click="close()"
style="width:200px; padding:12px 0; background:rgba(0,0,0,.3); border:none; border-radius:30px;
font-size:13px; color:rgba(255,248,220,.8); cursor:pointer; letter-spacing:1px;
transition:background .15s;"
onmouseover="this.style.background='rgba(0,0,0,.48)'"
onmouseout="this.style.background='rgba(0,0,0,.3)'">
<span x-text="claimed ? '收下啦 ✨' : '关闭'"></span>
</button>
</div>
</div>
</div>
</div>
<style>
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.08);
}
}
</style>
{{-- ═══════════ Alpine.js 组件脚本 ═══════════ --}}
<script>
function weddingSetupModal() {
return {
show: false,
marriageId: null,
tiers: [],
selectedTier: null,
payBy: 'groom',
loading: false,
sending: false,
error: '',
get myCost() {
if (!this.selectedTier) return 0;
return this.payBy === 'split' ?
Math.ceil(this.selectedTier.amount / 2) :
this.selectedTier.amount;
},
async open(marriageId) {
this.marriageId = marriageId;
this.selectedTier = null;
this.payBy = 'groom';
this.error = '';
this.loading = true;
this.show = true;
try {
const res = await fetch(window.chatContext.marriage.weddingTiersUrl, {
headers: {
'Accept': 'application/json'
}
});
const data = await res.json();
if (data.status === 'success') {
this.tiers = data.tiers;
if (this.tiers.length > 0) this.selectedTier = this.tiers[0];
}
} catch {
this.tiers = [];
}
this.loading = false;
},
close() {
this.show = false;
},
async doSetup() {
if (this.sending || !this.selectedTier) return;
this.error = '';
this.sending = true;
try {
// 固定使用立即举办,不再需要用户选择时间
const body = {
tier_id: this.selectedTier.id,
payer_type: this.payBy,
ceremony_type: 'immediate',
room_id: window.chatContext.roomId,
};
const res = await fetch(window.chatContext.marriage.weddingSetupUrl(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(body)
});
const data = await res.json();
if (data.status === 'success') {
this.close();
window.chatDialog?.alert('🎊 婚礼已开始!红包正在分发给在线用户…', '设置成功', '#f59e0b');
} else {
this.error = data.message || '设置失败';
}
} catch {
this.error = '网络异常,请稍后重试';
}
this.sending = false;
}
};
}
/**
* 婚礼红包弹窗组件
*/
function weddingEnvelopeModal() {
return {
show: false,
marriageId: null,
ceremonyId: null,
title: '',
subTitle: '',
claimed: false,
claiming: false,
claimedAmount: 0,
open(detail) {
this.marriageId = detail.marriage_id;
this.ceremonyId = detail.ceremony_id;
// 兼容两种字段命名:groom_name/bride_name 或 user.username/partner.username
const groomName = detail.groom_name ?? detail.user?.username ?? '??';
const brideName = detail.bride_name ?? detail.partner?.username ?? '??';
this.title = `${groomName} × ${brideName} 婚礼红包`;
this.subTitle = detail.tier_name ? `【${detail.tier_name}】普天同庆` : '婚礼庆典红包';
this.claimed = false;
this.claimedAmount = 0;
this.show = true;
},
close() {
this.show = false;
},
async doClaim() {
if (this.claiming || this.claimed) return;
this.claiming = true;
try {
// 正确路由:/wedding/ceremony/{ceremonyId}/claim
const res = await fetch(`/wedding/ceremony/${this.ceremonyId}/claim`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content
},
body: JSON.stringify({
ceremony_id: this.ceremonyId
})
});
const data = await res.json();
if (data.ok) {
this.claimed = true;
this.claimedAmount = data.amount || 0;
} else {
window.chatDialog?.alert(data.message || '领取失败', '提示', '#f59e0b');
if (data.message?.includes('已领取') || data.message?.includes('已过期')) {
this.claimed = true;
}
}
} catch {
window.chatDialog?.alert('网络异常', '错误', '#cc4444');
}
this.claiming = false;
}
};
}
</script>