离婚流程全面升级:①发起方专属确认弹窗(含对方拒绝后果+魅力/金币惩罚实时值)②被申请方三选弹窗(同意/不同意/稍后)③不同意=强制离婚申请人赔一半金币④所有惩罚数值从后台实时查询
This commit is contained in:
@@ -58,6 +58,8 @@ class MarriageDivorceRequested implements ShouldBroadcastNow
|
||||
|
||||
// 读取协议离婚魅力惩罚供前端展示
|
||||
$penalty = (int) \App\Models\MarriageConfig::where('key', 'divorce_mutual_charm')->value('value');
|
||||
// 读取强制离婚魅力惩罚(被拒=强制离婚时申请方受此惩罚)
|
||||
$forcedPenalty = (int) \App\Models\MarriageConfig::where('key', 'divorce_forced_charm')->value('value');
|
||||
|
||||
return [
|
||||
'marriage_id' => $this->marriage->id,
|
||||
@@ -66,6 +68,7 @@ class MarriageDivorceRequested implements ShouldBroadcastNow
|
||||
'timeout_hours' => 72,
|
||||
'requested_at' => $this->marriage->divorce_requested_at,
|
||||
'mutual_charm_penalty' => $penalty, // 协议离婚双方各扣魅力
|
||||
'forced_charm_penalty' => $forcedPenalty, // 不同意→强制,申请方受此惩罚
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ use App\Events\MarriageProposed;
|
||||
use App\Events\MarriageRejected;
|
||||
use App\Models\Marriage;
|
||||
use App\Models\UserPurchase;
|
||||
use App\Services\MarriageConfigService;
|
||||
use App\Services\MarriageService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -28,8 +29,23 @@ class MarriageController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MarriageService $marriage,
|
||||
private readonly MarriageConfigService $config,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 获取离婚相关惩罚配置(供前端展示风险提示)。
|
||||
* 返回协议离婚魅力惩罚、强制离婚魅力惩罚及各冷静期天数。
|
||||
*/
|
||||
public function divorceConfig(): JsonResponse
|
||||
{
|
||||
return response()->json([
|
||||
'mutual_charm_penalty' => (int) $this->config->get('divorce_mutual_charm', 100),
|
||||
'forced_charm_penalty' => (int) $this->config->get('divorce_forced_charm', 300),
|
||||
'mutual_cooldown_days' => (int) $this->config->get('divorce_mutual_cooldown', 70),
|
||||
'forced_cooldown_days' => (int) $this->config->get('divorce_forced_cooldown', 90),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的婚姻状态(名片/用户列表用)。
|
||||
*/
|
||||
@@ -221,4 +237,20 @@ class MarriageController extends Controller
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝协议离婚申请(被申请方选择不同意 = 视为强制离婚)。
|
||||
* 申请人赔偿一半金币给对方,婚姻以 forced 类型解除。
|
||||
*/
|
||||
public function rejectDivorce(Request $request, Marriage $marriage): JsonResponse
|
||||
{
|
||||
$result = $this->marriage->rejectDivorce($marriage, $request->user());
|
||||
|
||||
if ($result['ok']) {
|
||||
$marriage->refresh();
|
||||
broadcast(new MarriageDivorced($marriage, 'forced'));
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +304,69 @@ class MarriageService
|
||||
return ['ok' => true, 'message' => '协议离婚已完成。'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 被申请方拒绝协议离婚申请(等同于强制离婚)。
|
||||
*
|
||||
* 规则:
|
||||
* - 婚姻立即以 forced 类型解除
|
||||
* - 申请人(divorcer)被扣除 divorce_forced_charm 点魅力作为惩罚
|
||||
* - 申请人一半金币赔偿给被申请方
|
||||
* - 申请人进入强制离婚冷静期
|
||||
*
|
||||
* @param Marriage $marriage 婚姻记录
|
||||
* @param User $respondent 被申请方(拒绝者)
|
||||
* @return array{ok: bool, message: string}
|
||||
*/
|
||||
public function rejectDivorce(Marriage $marriage, User $respondent): array
|
||||
{
|
||||
if ($marriage->status !== 'married' || $marriage->divorce_type !== 'mutual') {
|
||||
return ['ok' => false, 'message' => '没有待处理的离婚申请。'];
|
||||
}
|
||||
if ($marriage->divorcer_id === $respondent->id) {
|
||||
return ['ok' => false, 'message' => '不能拒绝自己发起的离婚申请。'];
|
||||
}
|
||||
if (! $marriage->involves($respondent->id)) {
|
||||
return ['ok' => false, 'message' => '无权操作此婚姻。'];
|
||||
}
|
||||
|
||||
// 申请方(被拒的一方)
|
||||
$divorcer = $marriage->user_id === $marriage->divorcer_id
|
||||
? $marriage->user
|
||||
: $marriage->partner;
|
||||
|
||||
DB::transaction(function () use ($marriage, $divorcer, $respondent) {
|
||||
$charmPenalty = $this->config->get('divorce_forced_charm', 300);
|
||||
|
||||
// 申请人扣魅力
|
||||
$this->currency->change($divorcer, 'charm', -$charmPenalty, CurrencySource::DIVORCE_CHARM, '拒绝离婚时视为强制离婚,扣除魅力惩罚');
|
||||
|
||||
// 申请人一半金币赔偿给对方
|
||||
$divorcerJjb = $divorcer->fresh()->jjb ?? 0;
|
||||
if ($divorcerJjb > 0) {
|
||||
$half = (int) floor($divorcerJjb / 2);
|
||||
if ($half > 0) {
|
||||
$this->currency->change($divorcer, 'gold', -$half, CurrencySource::FORCED_DIVORCE_TRANSFER, "协议离婚被拒,赔偿一半金币给 {$respondent->username}");
|
||||
$this->currency->change($respondent, 'gold', $half, CurrencySource::FORCED_DIVORCE_TRANSFER, "对方协议离婚被拒,获得 {$divorcer->username} 一半金币赔偿");
|
||||
}
|
||||
}
|
||||
|
||||
// 更新婚姻为强制离婚
|
||||
$marriage->update([
|
||||
'status' => 'divorced',
|
||||
'divorce_type' => 'forced',
|
||||
'divorcer_id' => $divorcer->id,
|
||||
'divorced_at' => now(),
|
||||
'intimacy' => 0,
|
||||
'level' => 1,
|
||||
]);
|
||||
});
|
||||
|
||||
$divorcerJjb = $divorcer->fresh()->jjb ?? 0;
|
||||
$half = (int) floor(($divorcer->jjb ?? 0) / 2);
|
||||
|
||||
return ['ok' => true, 'message' => "你已拒绝离婚申请,视为强制离婚,{$divorcer->username} 赔偿了 {$half} 枚金币给你,婚姻已解除。"];
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制离婚(单方立即生效,发起方金币全转对方)。
|
||||
*
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
rejectUrl: (id) => `/marriage/${id}/reject`,
|
||||
divorceUrl: (id) => `/marriage/${id}/divorce`,
|
||||
confirmDivorceUrl: (id) => `/marriage/${id}/confirm-divorce`,
|
||||
rejectDivorceUrl: (id) => `/marriage/${id}/reject-divorce`,
|
||||
divorceConfigUrl: '/marriage/divorce-config',
|
||||
weddingTiersUrl: "/wedding/tiers",
|
||||
weddingSetupUrl: (id) => `/wedding/${id}/setup`,
|
||||
claimEnvelopeUrl: (id, ceremonyId) => `/wedding/${id}/claim`,
|
||||
|
||||
@@ -340,6 +340,181 @@
|
||||
</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
|
||||
@@ -809,10 +984,150 @@
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起离婚确认弹窗(发起方专用:展示双方结果 + 实时惩罚值)
|
||||
*/
|
||||
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 res = 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 res.json();
|
||||
this.close();
|
||||
if (data.ok) {
|
||||
window.chatDialog?.alert(data.message, '申请已发出 📩', '#6b7280');
|
||||
} else {
|
||||
window.chatDialog?.alert(data.message || '操作失败', '错误', '#dc2626');
|
||||
}
|
||||
} catch (e) {
|
||||
this.error = '网络请求失败,请重试。';
|
||||
} finally {
|
||||
this.acting = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 婚礼设置弹窗组件
|
||||
* 离婚申请通知弹窗(被申请方专用:三选 + 真实惩罚值)
|
||||
*/
|
||||
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;
|
||||
},
|
||||
|
||||
/** 同意:协议离婚,双方各扣 mutualPenalty 魅力 */
|
||||
async doAgree() {
|
||||
if (this.acting) return;
|
||||
this.acting = true;
|
||||
this.error = '';
|
||||
try {
|
||||
const res = 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 res.json();
|
||||
this.close();
|
||||
window.chatDialog?.alert(data.message, data.ok ? '操作完成' : '失败', data.ok ? '#6b7280' :
|
||||
'#cc4444');
|
||||
} catch (e) {
|
||||
this.error = '网络请求失败,请重试。';
|
||||
} finally {
|
||||
this.acting = false;
|
||||
}
|
||||
},
|
||||
|
||||
/** 不同意:视为强制离婚,申请方扣魅力 + 赔一半金币 */
|
||||
async doReject() {
|
||||
if (this.acting) return;
|
||||
this.acting = true;
|
||||
this.error = '';
|
||||
try {
|
||||
const res = 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 res.json();
|
||||
this.close();
|
||||
window.chatDialog?.alert(data.message, data.ok ? '已处理' : '失败', data.ok ? '#d97706' : '#cc4444');
|
||||
} catch (e) {
|
||||
this.error = '网络请求失败,请重试。';
|
||||
} finally {
|
||||
this.acting = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function weddingSetupModal() {
|
||||
return {
|
||||
show: false,
|
||||
@@ -1085,38 +1400,15 @@
|
||||
);
|
||||
});
|
||||
|
||||
/** 接到协议离婚申请(私人频道,对方) */
|
||||
/** 接到协议离婚申请(私人频道,对方)→ 打开专属三选弹窗 */
|
||||
window.addEventListener('chat:divorce-requested', (e) => {
|
||||
const {
|
||||
initiator_name,
|
||||
marriage_id,
|
||||
mutual_charm_penalty
|
||||
} = e.detail;
|
||||
const penaltyTip = mutual_charm_penalty > 0 ?
|
||||
`\n\n⚠️ 双方各将被扣除 ${mutual_charm_penalty} 点魅力值作为惩罚。` :
|
||||
'';
|
||||
window.chatDialog?.confirm(
|
||||
`${initiator_name} 申请与你协议离婚,是否同意?${penaltyTip}`,
|
||||
'离婚申请 💔'
|
||||
).then(ok => {
|
||||
if (!ok) return;
|
||||
fetch(window.chatContext.marriage.confirmDivorceUrl(marriage_id), {
|
||||
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
|
||||
})
|
||||
}).then(r => r.json()).then(data => {
|
||||
window.chatDialog?.alert(data.message, data.status === 'success' ? '操作完成' :
|
||||
'失败', data.status === 'success' ? '#6b7280' : '#cc4444');
|
||||
});
|
||||
});
|
||||
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 {
|
||||
|
||||
@@ -172,40 +172,37 @@
|
||||
return;
|
||||
},
|
||||
|
||||
/** 发起协议离婚 */
|
||||
/** 发起协议离婚(先拉惩罚配置,再弹专属全屏确认弹窗) */
|
||||
async doDivorce(marriageId) {
|
||||
if (!marriageId) return;
|
||||
this.showUserModal = false;
|
||||
|
||||
const confirmed = await window.chatDialog?.confirm(
|
||||
'提出离婚后,对方将在私人频道收到通知。\n\n如果对方在 24 小时内未作决定,此申请将自动升级为“强制离婚”,并扣除发起方一定的魅力值作为单方面解除契约的惩罚。\n\n您确定要继续发起离婚申请吗?',
|
||||
'发起离婚',
|
||||
'#475569'
|
||||
);
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
window.chatDialog?.alert('请稍候…', '发送申请中', '#9ca3af');
|
||||
// 从后台实时拉取最新惩罚配置
|
||||
let divorceConfig = {
|
||||
mutual_charm_penalty: 0,
|
||||
forced_charm_penalty: 0,
|
||||
mutual_cooldown_days: 0,
|
||||
forced_cooldown_days: 0
|
||||
};
|
||||
try {
|
||||
const res = await fetch(window.chatContext.marriage.divorceUrl(marriageId), {
|
||||
method: 'POST',
|
||||
const cfgRes = await fetch(window.chatContext.marriage.divorceConfigUrl, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
}
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.ok) {
|
||||
window.chatDialog?.alert(data.message, '已发出', '#6b7280');
|
||||
} else {
|
||||
window.chatDialog?.alert(data.message || '操作失败', '错误', '#dc2626');
|
||||
}
|
||||
if (cfgRes.ok) divorceConfig = await cfgRes.json();
|
||||
} catch (e) {
|
||||
window.chatDialog?.alert('网络请求失败', '错误', '#dc2626');
|
||||
/* 网络异常则使用默认值 */ }
|
||||
|
||||
// 打开专属离婚确认弹窗
|
||||
const modal = document.getElementById('divorce-confirm-modal');
|
||||
if (modal && window.Alpine) {
|
||||
Alpine.$data(modal).open(marriageId, divorceConfig);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/** 获取用户资料 */
|
||||
async fetchUser(username) {
|
||||
try {
|
||||
|
||||
@@ -87,8 +87,12 @@ Route::middleware(['chat.auth'])->group(function () {
|
||||
Route::post('/{marriage}/reject', [\App\Http\Controllers\MarriageController::class, 'reject'])->name('reject');
|
||||
// 申请离婚(type: mutual|forced)
|
||||
Route::post('/{marriage}/divorce', [\App\Http\Controllers\MarriageController::class, 'divorce'])->name('divorce');
|
||||
// 离婚惩罚配置查询(前端展示风险提示用)
|
||||
Route::get('/divorce-config', [\App\Http\Controllers\MarriageController::class, 'divorceConfig'])->name('divorce-config');
|
||||
// 确认协议离婚
|
||||
Route::post('/{marriage}/confirm-divorce', [\App\Http\Controllers\MarriageController::class, 'confirmDivorce'])->name('confirm-divorce');
|
||||
// 拒绝离婚申请(被申请方选择不同意→弹强制离婚)
|
||||
Route::post('/{marriage}/reject-divorce', [\App\Http\Controllers\MarriageController::class, 'rejectDivorce'])->name('reject-divorce');
|
||||
});
|
||||
|
||||
// ── 婚礼系统(前台)──────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user