离婚流程全面升级:①发起方专属确认弹窗(含对方拒绝后果+魅力/金币惩罚实时值)②被申请方三选弹窗(同意/不同意/稍后)③不同意=强制离婚申请人赔一半金币④所有惩罚数值从后台实时查询
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');
|
$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 [
|
return [
|
||||||
'marriage_id' => $this->marriage->id,
|
'marriage_id' => $this->marriage->id,
|
||||||
@@ -66,6 +68,7 @@ class MarriageDivorceRequested implements ShouldBroadcastNow
|
|||||||
'timeout_hours' => 72,
|
'timeout_hours' => 72,
|
||||||
'requested_at' => $this->marriage->divorce_requested_at,
|
'requested_at' => $this->marriage->divorce_requested_at,
|
||||||
'mutual_charm_penalty' => $penalty, // 协议离婚双方各扣魅力
|
'mutual_charm_penalty' => $penalty, // 协议离婚双方各扣魅力
|
||||||
|
'forced_charm_penalty' => $forcedPenalty, // 不同意→强制,申请方受此惩罚
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use App\Events\MarriageProposed;
|
|||||||
use App\Events\MarriageRejected;
|
use App\Events\MarriageRejected;
|
||||||
use App\Models\Marriage;
|
use App\Models\Marriage;
|
||||||
use App\Models\UserPurchase;
|
use App\Models\UserPurchase;
|
||||||
|
use App\Services\MarriageConfigService;
|
||||||
use App\Services\MarriageService;
|
use App\Services\MarriageService;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -28,8 +29,23 @@ class MarriageController extends Controller
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly MarriageService $marriage,
|
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);
|
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' => '协议离婚已完成。'];
|
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`,
|
rejectUrl: (id) => `/marriage/${id}/reject`,
|
||||||
divorceUrl: (id) => `/marriage/${id}/divorce`,
|
divorceUrl: (id) => `/marriage/${id}/divorce`,
|
||||||
confirmDivorceUrl: (id) => `/marriage/${id}/confirm-divorce`,
|
confirmDivorceUrl: (id) => `/marriage/${id}/confirm-divorce`,
|
||||||
|
rejectDivorceUrl: (id) => `/marriage/${id}/reject-divorce`,
|
||||||
|
divorceConfigUrl: '/marriage/divorce-config',
|
||||||
weddingTiersUrl: "/wedding/tiers",
|
weddingTiersUrl: "/wedding/tiers",
|
||||||
weddingSetupUrl: (id) => `/wedding/${id}/setup`,
|
weddingSetupUrl: (id) => `/wedding/${id}/setup`,
|
||||||
claimEnvelopeUrl: (id, ceremonyId) => `/wedding/${id}/claim`,
|
claimEnvelopeUrl: (id, ceremonyId) => `/wedding/${id}/claim`,
|
||||||
|
|||||||
@@ -340,6 +340,181 @@
|
|||||||
</style>
|
</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. 婚礼设置弹窗 ═══════════ --}}
|
{{-- ═══════════ 4. 婚礼设置弹窗 ═══════════ --}}
|
||||||
<div id="wedding-setup-modal" x-data="weddingSetupModal()" x-show="show" x-cloak>
|
<div id="wedding-setup-modal" x-data="weddingSetupModal()" x-show="show" x-cloak>
|
||||||
<div
|
<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() {
|
function weddingSetupModal() {
|
||||||
return {
|
return {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -1085,38 +1400,15 @@
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 接到协议离婚申请(私人频道,对方) */
|
/** 接到协议离婚申请(私人频道,对方)→ 打开专属三选弹窗 */
|
||||||
window.addEventListener('chat:divorce-requested', (e) => {
|
window.addEventListener('chat:divorce-requested', (e) => {
|
||||||
const {
|
const detail = e.detail;
|
||||||
initiator_name,
|
const el = document.getElementById('divorce-request-modal');
|
||||||
marriage_id,
|
if (el) Alpine.$data(el).open(detail);
|
||||||
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');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 红包领取成功通知(私人频道) */
|
/** 红包领取成功通知(私人频道) */
|
||||||
window.addEventListener('chat:envelope-claimed', (e) => {
|
window.addEventListener('chat:envelope-claimed', (e) => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -172,40 +172,37 @@
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 发起协议离婚 */
|
/** 发起协议离婚(先拉惩罚配置,再弹专属全屏确认弹窗) */
|
||||||
async doDivorce(marriageId) {
|
async doDivorce(marriageId) {
|
||||||
if (!marriageId) return;
|
if (!marriageId) return;
|
||||||
this.showUserModal = false;
|
this.showUserModal = false;
|
||||||
|
|
||||||
const confirmed = await window.chatDialog?.confirm(
|
// 从后台实时拉取最新惩罚配置
|
||||||
'提出离婚后,对方将在私人频道收到通知。\n\n如果对方在 24 小时内未作决定,此申请将自动升级为“强制离婚”,并扣除发起方一定的魅力值作为单方面解除契约的惩罚。\n\n您确定要继续发起离婚申请吗?',
|
let divorceConfig = {
|
||||||
'发起离婚',
|
mutual_charm_penalty: 0,
|
||||||
'#475569'
|
forced_charm_penalty: 0,
|
||||||
);
|
mutual_cooldown_days: 0,
|
||||||
|
forced_cooldown_days: 0
|
||||||
if (!confirmed) return;
|
};
|
||||||
|
|
||||||
window.chatDialog?.alert('请稍候…', '发送申请中', '#9ca3af');
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(window.chatContext.marriage.divorceUrl(marriageId), {
|
const cfgRes = await fetch(window.chatContext.marriage.divorceConfigUrl, {
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
if (cfgRes.ok) divorceConfig = await cfgRes.json();
|
||||||
if (data.ok) {
|
|
||||||
window.chatDialog?.alert(data.message, '已发出', '#6b7280');
|
|
||||||
} else {
|
|
||||||
window.chatDialog?.alert(data.message || '操作失败', '错误', '#dc2626');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} 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) {
|
async fetchUser(username) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -87,8 +87,12 @@ Route::middleware(['chat.auth'])->group(function () {
|
|||||||
Route::post('/{marriage}/reject', [\App\Http\Controllers\MarriageController::class, 'reject'])->name('reject');
|
Route::post('/{marriage}/reject', [\App\Http\Controllers\MarriageController::class, 'reject'])->name('reject');
|
||||||
// 申请离婚(type: mutual|forced)
|
// 申请离婚(type: mutual|forced)
|
||||||
Route::post('/{marriage}/divorce', [\App\Http\Controllers\MarriageController::class, 'divorce'])->name('divorce');
|
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}/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