Add baccarat loss cover activity

This commit is contained in:
2026-04-11 23:27:29 +08:00
parent dd9a8c5db8
commit e43dceab2c
22 changed files with 1898 additions and 5 deletions
@@ -0,0 +1,62 @@
<?php
/**
* 文件功能:百家乐买单活动后台控制器
*
* 提供聊天室管理员在输入框上方快捷创建活动、
* 查看当前活动并手动结束活动的 JSON 接口。
*/
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreBaccaratLossCoverEventRequest;
use App\Models\BaccaratLossCoverEvent;
use App\Services\BaccaratLossCoverService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class BaccaratLossCoverEventController extends Controller
{
/**
* 注入百家乐买单活动服务。
*/
public function __construct(
private readonly BaccaratLossCoverService $lossCoverService,
) {}
/**
* 创建新的百家乐买单活动。
*/
public function store(StoreBaccaratLossCoverEventRequest $request): JsonResponse
{
try {
$event = $this->lossCoverService->createEvent($request->user(), $request->validated());
} catch (\RuntimeException $exception) {
return response()->json([
'ok' => false,
'message' => $exception->getMessage(),
], 422);
}
return response()->json([
'ok' => true,
'message' => "活动「{$event->title}」已创建成功。",
'event_id' => $event->id,
]);
}
/**
* 手动结束或取消一场百家乐买单活动。
*/
public function close(Request $request, BaccaratLossCoverEvent $event): JsonResponse
{
$event = $this->lossCoverService->forceCloseEvent($event, $request->user());
return response()->json([
'ok' => true,
'message' => '活动状态已更新。',
'status' => $event->status,
]);
}
}
+12 -2
View File
@@ -19,6 +19,7 @@ use App\Enums\CurrencySource;
use App\Models\BaccaratBet;
use App\Models\BaccaratRound;
use App\Models\GameConfig;
use App\Services\BaccaratLossCoverService;
use App\Services\UserCurrencyService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -28,6 +29,7 @@ class BaccaratController extends Controller
{
public function __construct(
private readonly UserCurrencyService $currency,
private readonly BaccaratLossCoverService $lossCoverService,
) {}
/**
@@ -107,8 +109,9 @@ class BaccaratController extends Controller
}
$currency = $this->currency;
$lossCoverService = $this->lossCoverService;
return DB::transaction(function () use ($user, $round, $data, $currency): JsonResponse {
return DB::transaction(function () use ($user, $round, $data, $currency, $lossCoverService): JsonResponse {
// 幂等:同一局只能下一注
$existing = BaccaratBet::query()
->where('round_id', $round->id)
@@ -131,15 +134,22 @@ class BaccaratController extends Controller
},
);
// 下注时间命中活动窗口时,将本次下注挂到对应的买单活动下。
$lossCoverEvent = $lossCoverService->findEventForBetTime(now());
// 写入下注记录
BaccaratBet::create([
$bet = BaccaratBet::create([
'round_id' => $round->id,
'user_id' => $user->id,
'loss_cover_event_id' => $lossCoverEvent?->id,
'bet_type' => $data['bet_type'],
'amount' => $data['amount'],
'status' => 'pending',
]);
// 命中活动的下注要同步累计到用户活动记录中,便于后续前台查看。
$lossCoverService->registerBet($bet);
// 更新局次汇总统计
$field = 'total_bet_'.$data['bet_type'];
$countField = 'bet_count_'.$data['bet_type'];
@@ -0,0 +1,112 @@
<?php
/**
* 文件功能:百家乐买单活动前台控制器
*
* 提供活动摘要、历史记录以及用户领取补偿的接口,
* 供娱乐大厅弹窗与聊天室系统消息按钮调用。
*/
namespace App\Http\Controllers;
use App\Models\BaccaratLossCoverEvent;
use App\Services\BaccaratLossCoverService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class BaccaratLossCoverController extends Controller
{
/**
* 注入百家乐买单活动服务。
*/
public function __construct(
private readonly BaccaratLossCoverService $lossCoverService,
) {}
/**
* 返回当前最值得关注的一次活动摘要。
*/
public function summary(Request $request): JsonResponse
{
$event = BaccaratLossCoverEvent::query()
->with(['creator:id,username'])
->whereIn('status', ['active', 'settlement_pending', 'claimable', 'scheduled'])
->orderByRaw("CASE status WHEN 'active' THEN 0 WHEN 'settlement_pending' THEN 1 WHEN 'claimable' THEN 2 WHEN 'scheduled' THEN 3 ELSE 4 END")
->orderByDesc('starts_at')
->first();
$record = null;
if ($event) {
$record = $event->records()->where('user_id', $request->user()->id)->first();
}
return response()->json([
'event' => $event ? $this->transformEvent($event, $record) : null,
]);
}
/**
* 返回最近的活动列表以及当前用户的领取记录。
*/
public function history(Request $request): JsonResponse
{
$events = BaccaratLossCoverEvent::query()
->with(['creator:id,username', 'records' => function ($query) use ($request) {
$query->where('user_id', $request->user()->id);
}])
->latest('starts_at')
->limit(20)
->get()
->map(function (BaccaratLossCoverEvent $event) {
$record = $event->records->first();
return $this->transformEvent($event, $record);
});
return response()->json([
'events' => $events,
]);
}
/**
* 领取指定活动的补偿金币。
*/
public function claim(Request $request, BaccaratLossCoverEvent $event): JsonResponse
{
$result = $this->lossCoverService->claim($event, $request->user());
return response()->json($result);
}
/**
* 将活动与个人记录整理为前端更容易消费的结构。
*/
private function transformEvent(BaccaratLossCoverEvent $event, mixed $record): array
{
return [
'id' => $event->id,
'title' => $event->title,
'description' => $event->description,
'status' => $event->status,
'status_label' => $event->statusLabel(),
'starts_at' => $event->starts_at?->toIso8601String(),
'ends_at' => $event->ends_at?->toIso8601String(),
'claim_deadline_at' => $event->claim_deadline_at?->toIso8601String(),
'participant_count' => $event->participant_count,
'compensable_user_count' => $event->compensable_user_count,
'total_loss_amount' => $event->total_loss_amount,
'total_claimed_amount' => $event->total_claimed_amount,
'creator_username' => $event->creator?->username ?? '管理员',
'my_record' => $record ? [
'total_bet_amount' => $record->total_bet_amount,
'total_win_payout' => $record->total_win_payout,
'total_loss_amount' => $record->total_loss_amount,
'compensation_amount' => $record->compensation_amount,
'claim_status' => $record->claim_status,
'claim_status_label' => $record->claimStatusLabel(),
'claimed_amount' => $record->claimed_amount,
'claimed_at' => $record->claimed_at?->toIso8601String(),
] : null,
];
}
}