完善百家乐买单补偿自动领取与聊天室播报
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:AI小班长自动领取百家乐买单活动补偿任务
|
||||
*
|
||||
* 当买单活动进入“可领取”状态后,异步为 AI小班长检查并领取
|
||||
* 本次活动中累计的补偿金币,确保金币入账和流水日志统一走正式服务。
|
||||
*/
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\BaccaratLossCoverEvent;
|
||||
use App\Models\BaccaratLossCoverRecord;
|
||||
use App\Models\User;
|
||||
use App\Services\BaccaratLossCoverService;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AiClaimBaccaratLossCoverJob implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* 最大重试次数。
|
||||
*/
|
||||
public int $tries = 3;
|
||||
|
||||
/**
|
||||
* @param int $eventId 需要自动领取补偿的活动 ID
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly int $eventId,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 执行 AI 小班长自动领取补偿逻辑。
|
||||
*/
|
||||
public function handle(BaccaratLossCoverService $lossCoverService): void
|
||||
{
|
||||
$event = BaccaratLossCoverEvent::query()->find($this->eventId);
|
||||
if (! $event) {
|
||||
Log::channel('daily')->warning('AI小班长自动领取买单补偿失败:活动不存在', [
|
||||
'event_id' => $this->eventId,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 只有活动进入可领取状态后,才允许自动发起补偿领取。
|
||||
if (! $event->isClaimable()) {
|
||||
Log::channel('daily')->info('AI小班长自动领取买单补偿跳过:活动暂不可领取', [
|
||||
'event_id' => $event->id,
|
||||
'status' => $event->status,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$aiUser = User::query()->where('username', 'AI小班长')->first();
|
||||
if (! $aiUser) {
|
||||
Log::channel('daily')->warning('AI小班长自动领取买单补偿失败:未找到 AI 用户', [
|
||||
'event_id' => $event->id,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$record = BaccaratLossCoverRecord::query()
|
||||
->where('event_id', $event->id)
|
||||
->where('user_id', $aiUser->id)
|
||||
->first();
|
||||
|
||||
// 没有补偿记录或本次没有待领取金额时,直接记日志后结束。
|
||||
if (! $record || $record->compensation_amount <= 0 || $record->claim_status !== 'pending') {
|
||||
Log::channel('daily')->info('AI小班长自动领取买单补偿跳过:暂无待领取补偿', [
|
||||
'event_id' => $event->id,
|
||||
'user_id' => $aiUser->id,
|
||||
'claim_status' => $record?->claim_status,
|
||||
'compensation_amount' => $record?->compensation_amount,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$claimResult = $lossCoverService->claim($event, $aiUser);
|
||||
|
||||
// 统一记录自动领取结果,便于后续核对 AI 补偿发放情况。
|
||||
Log::channel('daily')->info('AI小班长自动领取买单补偿结果', [
|
||||
'event_id' => $event->id,
|
||||
'user_id' => $aiUser->id,
|
||||
'ok' => $claimResult['ok'],
|
||||
'message' => $claimResult['message'],
|
||||
'amount' => $claimResult['amount'] ?? 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace App\Services;
|
||||
|
||||
use App\Enums\CurrencySource;
|
||||
use App\Events\MessageSent;
|
||||
use App\Jobs\AiClaimBaccaratLossCoverJob;
|
||||
use App\Jobs\SaveMessageJob;
|
||||
use App\Models\BaccaratBet;
|
||||
use App\Models\BaccaratLossCoverEvent;
|
||||
@@ -198,7 +199,7 @@ class BaccaratLossCoverService
|
||||
return ['ok' => false, 'message' => '当前活动暂未开放领取,或已超过领取时间。'];
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($event, $user): array {
|
||||
$result = DB::transaction(function () use ($event, $user): array {
|
||||
$record = BaccaratLossCoverRecord::query()
|
||||
->where('event_id', $event->id)
|
||||
->where('user_id', $user->id)
|
||||
@@ -247,6 +248,13 @@ class BaccaratLossCoverService
|
||||
'amount' => $amount,
|
||||
];
|
||||
});
|
||||
|
||||
// 领取成功后,需要向聊天室广播一条同款百家乐风格消息,方便其他人快速领取。
|
||||
if (($result['ok'] ?? false) === true && isset($result['amount'])) {
|
||||
$this->pushClaimMessage($event->fresh(), $user, (int) $result['amount']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,6 +404,9 @@ class BaccaratLossCoverService
|
||||
|
||||
$this->pushRoomMessage($content, '#7c3aed');
|
||||
$event->update(['ended_notice_sent_at' => now()]);
|
||||
|
||||
// 活动开放领取后,为 AI小班长补发一次自动领取任务。
|
||||
$this->dispatchAiAutoClaimJob($event->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,4 +430,66 @@ class BaccaratLossCoverService
|
||||
broadcast(new MessageSent(1, $message));
|
||||
SaveMessageJob::dispatch($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在用户领取补偿成功后,向聊天室广播领取播报。
|
||||
*/
|
||||
private function pushClaimMessage(?BaccaratLossCoverEvent $event, User $user, int $amount): void
|
||||
{
|
||||
if (! $event) {
|
||||
return;
|
||||
}
|
||||
|
||||
$formattedAmount = number_format($amount);
|
||||
$button = $event->status === 'claimable'
|
||||
? ' <button onclick="claimBaccaratLossCover('.$event->id.')" style="margin-left:8px;padding:3px 12px;background:#16a34a;color:#fff;border:none;border-radius:12px;cursor:pointer;font-size:12px;font-weight:bold;">领取补偿</button>'
|
||||
: '';
|
||||
|
||||
// 领取成功的公屏格式复用百家乐参与播报风格,保证聊天室感知一致。
|
||||
$content = "🌟 🎲 <b>{$user->username}</b> 领取了 <b>{$formattedAmount}</b> 金币补偿!✨{$button}";
|
||||
$message = [
|
||||
'id' => $this->chatState->nextMessageId(1),
|
||||
'room_id' => 1,
|
||||
'from_user' => '系统传音',
|
||||
'to_user' => '大家',
|
||||
'content' => $content,
|
||||
'is_secret' => false,
|
||||
'font_color' => '#d97706',
|
||||
'action' => '',
|
||||
'sent_at' => now()->toDateTimeString(),
|
||||
];
|
||||
|
||||
$this->chatState->pushMessage(1, $message);
|
||||
broadcast(new MessageSent(1, $message));
|
||||
SaveMessageJob::dispatch($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在活动可领取后,为 AI小班长派发自动领取补偿任务。
|
||||
*/
|
||||
private function dispatchAiAutoClaimJob(?BaccaratLossCoverEvent $event): void
|
||||
{
|
||||
if (! $event || $event->status !== 'claimable') {
|
||||
return;
|
||||
}
|
||||
|
||||
$aiUserId = User::query()->where('username', 'AI小班长')->value('id');
|
||||
if (! $aiUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hasPendingRecord = BaccaratLossCoverRecord::query()
|
||||
->where('event_id', $event->id)
|
||||
->where('user_id', $aiUserId)
|
||||
->where('claim_status', 'pending')
|
||||
->where('compensation_amount', '>', 0)
|
||||
->exists();
|
||||
|
||||
// 只有 AI小班长确实存在待领取补偿时,才派发自动领取任务。
|
||||
if (! $hasPendingRecord) {
|
||||
return;
|
||||
}
|
||||
|
||||
AiClaimBaccaratLossCoverJob::dispatch($event->id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user