Files
chatroom/app/Http/Controllers/Admin/MarriageManagerController.php
lkddi d2797d5b59 功能:婚姻系统第9步(后台管理页面)
Admin/MarriageManagerController:
- index() 总览统计卡片
- list() 婚姻列表(筛选/强制离婚/取消求婚)
- proposals() 求婚记录
- ceremonies() 婚礼红包记录
- claimDetail() 红包领取明细
- intimacyLogs() 亲密度日志(来源筛选)
- configs/updateConfigs 参数配置(批量保存)
- tiers/updateTier 婚礼档位管理

Views(7个页面):admin/marriages/{index|list|configs|tiers|ceremonies|claim-detail|proposals|intimacy-logs}
侧边栏:superlevel 区块新增「💒 婚姻管理」入口
2026-03-01 15:15:03 +08:00

250 lines
8.0 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.
<?php
/**
* 文件功能:后台婚姻系统管理控制器
*
* 提供总览统计、婚姻/求婚明细查询、婚礼档位管理、
* 参数配置、亲密度日志审计、强制离婚等管理操作。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Marriage;
use App\Models\MarriageIntimacyLog;
use App\Models\WeddingCeremony;
use App\Models\WeddingEnvelopeClaim;
use App\Models\WeddingTier;
use App\Services\MarriageConfigService;
use App\Services\MarriageService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class MarriageManagerController extends Controller
{
public function __construct(
private readonly MarriageConfigService $config,
private readonly MarriageService $marriageService,
) {}
/**
* 婚姻管理总览(统计卡片 + 最近记录)。
*/
public function index(): View
{
$stats = [
'total_married' => Marriage::where('status', 'married')->count(),
'total_pending' => Marriage::where('status', 'pending')->count(),
'total_divorced' => Marriage::where('status', 'divorced')->count(),
'total_weddings' => WeddingCeremony::whereIn('status', ['active', 'completed'])->count(),
'total_envelopes' => WeddingEnvelopeClaim::sum('amount'),
'claimed_amount' => WeddingEnvelopeClaim::where('claimed', true)->sum('amount'),
];
$recentMarriages = Marriage::with(['user:id,username', 'partner:id,username', 'ringItem:id,name,icon'])
->where('status', 'married')
->orderByDesc('married_at')
->limit(10)
->get();
$recentDivorces = Marriage::with(['user:id,username', 'partner:id,username'])
->where('status', 'divorced')
->orderByDesc('divorced_at')
->limit(8)
->get();
return view('admin.marriages.index', compact('stats', 'recentMarriages', 'recentDivorces'));
}
/**
* 婚姻列表(支持按状态/用户名筛选)。
*/
public function list(Request $request): View
{
$query = Marriage::with(['user:id,username', 'partner:id,username', 'ringItem:id,name,icon'])
->orderByDesc('id');
if ($status = $request->get('status')) {
$query->where('status', $status);
}
if ($search = $request->get('search')) {
$query->where(function ($q) use ($search) {
$q->whereHas('user', fn ($u) => $u->where('username', 'like', "%{$search}%"))
->orWhereHas('partner', fn ($u) => $u->where('username', 'like', "%{$search}%"));
});
}
$marriages = $query->paginate(20)->withQueryString();
return view('admin.marriages.list', compact('marriages'));
}
/**
* 求婚记录列表(含 pending/expired/rejected
*/
public function proposals(Request $request): View
{
$proposals = Marriage::with(['user:id,username', 'partner:id,username', 'ringItem:id,name,icon'])
->whereIn('status', ['pending', 'expired', 'rejected'])
->orderByDesc('proposed_at')
->paginate(20)
->withQueryString();
return view('admin.marriages.proposals', compact('proposals'));
}
/**
* 婚礼红包记录。
*/
public function ceremonies(Request $request): View
{
$ceremonies = WeddingCeremony::with([
'marriage.user:id,username',
'marriage.partner:id,username',
'tier:id,name,tier,icon',
])
->orderByDesc('id')
->paginate(20)
->withQueryString();
return view('admin.marriages.ceremonies', compact('ceremonies'));
}
/**
* 红包领取明细(某场婚礼)。
*/
public function claimDetail(WeddingCeremony $ceremony): View
{
$ceremony->load(['marriage.user:id,username', 'marriage.partner:id,username', 'tier:id,name,icon']);
$claims = WeddingEnvelopeClaim::with('user:id,username,headface')
->where('ceremony_id', $ceremony->id)
->orderBy('amount', 'desc')
->paginate(30);
return view('admin.marriages.claim-detail', compact('ceremony', 'claims'));
}
/**
* 亲密度日志列表(支持按用户筛选)。
*/
public function intimacyLogs(Request $request): View
{
$query = MarriageIntimacyLog::with(['marriage.user:id,username', 'marriage.partner:id,username'])
->orderByDesc('id');
if ($search = $request->get('search')) {
$query->whereHas('marriage', function ($q) use ($search) {
$q->whereHas('user', fn ($u) => $u->where('username', 'like', "%{$search}%"))
->orWhereHas('partner', fn ($u) => $u->where('username', 'like', "%{$search}%"));
});
}
if ($source = $request->get('source')) {
$query->where('source', $source);
}
$logs = $query->paginate(30)->withQueryString();
return view('admin.marriages.intimacy-logs', compact('logs'));
}
/**
* 参数配置页面(读取所有分组配置)。
*/
public function configs(): View
{
$groups = $this->config->allGrouped();
return view('admin.marriages.configs', compact('groups'));
}
/**
* 批量保存参数配置。
*/
public function updateConfigs(Request $request): RedirectResponse
{
$data = $request->validate([
'configs' => 'required|array',
'configs.*' => 'required|integer',
]);
$this->config->batchSet($data['configs']);
return redirect()->route('admin.marriages.configs')->with('success', '婚姻参数配置已保存!');
}
/**
* 婚礼档位配置页面。
*/
public function tiers(): View
{
$tiers = WeddingTier::orderBy('tier')->get();
return view('admin.marriages.tiers', compact('tiers'));
}
/**
* 更新婚礼档位。
*/
public function updateTier(Request $request, WeddingTier $tier): RedirectResponse
{
$data = $request->validate([
'name' => 'required|string|max:30',
'icon' => 'required|string|max:20',
'amount' => 'required|integer|min:1',
'description' => 'nullable|string|max:100',
'is_active' => 'boolean',
]);
$data['is_active'] = $request->boolean('is_active', true);
$tier->update($data);
return redirect()->route('admin.marriages.tiers')->with('success', "档位【{$tier->name}】已更新!");
}
/**
* 管理员强制离婚。
*/
public function forceDissolve(Request $request, Marriage $marriage): RedirectResponse
{
$data = $request->validate([
'admin_note' => 'required|string|max:200',
]);
if ($marriage->status !== 'married') {
return back()->with('error', '该婚姻不是已婚状态,无法操作。');
}
$admin = $request->user();
$result = $this->marriageService->forceDissolve($marriage, $admin, true);
// 写入管理员备注
$marriage->update(['admin_note' => $data['admin_note']]);
$msg = $result['ok'] ? '强制离婚已完成。' : $result['message'];
$type = $result['ok'] ? 'success' : 'error';
return back()->with($type, $msg);
}
/**
* 管理员取消求婚(释放戒指 → 退还状态 active
*/
public function cancelProposal(Request $request, Marriage $marriage): RedirectResponse
{
if ($marriage->status !== 'pending') {
return back()->with('error', '该求婚不是进行中状态,无法取消。');
}
$this->marriageService->expireProposal($marriage);
$marriage->update(['admin_note' => '管理员手动取消求婚:'.($request->input('reason', ''))]);
return back()->with('success', '求婚已取消,戒指标记遗失。');
}
}