json(['round' => null]); } $user = $request->user(); $myBet = BaccaratBet::query() ->where('round_id', $round->id) ->where('user_id', $user->id) ->first(); return response()->json([ 'round' => [ 'id' => $round->id, 'status' => $round->status, 'bet_closes_at' => $round->bet_closes_at->toIso8601String(), 'seconds_left' => max(0, (int) now()->diffInSeconds($round->bet_closes_at, false)), 'total_bet_big' => $round->total_bet_big, 'total_bet_small' => $round->total_bet_small, 'total_bet_triple' => $round->total_bet_triple, 'bet_count_big' => $round->bet_count_big, 'bet_count_small' => $round->bet_count_small, 'bet_count_triple' => $round->bet_count_triple, 'my_bet' => $myBet ? [ 'bet_type' => $myBet->bet_type, 'amount' => $myBet->amount, ] : null, ], ]); } /** * 用户提交下注。 * * 同一局每人限下一注(后台强制幂等)。 * 下注成功后立即扣除金币,结算时中奖者才返还本金+赔付。 */ public function bet(Request $request): JsonResponse { if (! GameConfig::isEnabled('baccarat')) { return response()->json(['ok' => false, 'message' => '百家乐游戏当前未开启。']); } $data = $request->validate([ 'round_id' => 'required|integer|exists:baccarat_rounds,id', 'bet_type' => 'required|in:big,small,triple', 'amount' => 'required|integer|min:1', ]); $config = GameConfig::forGame('baccarat')?->params ?? []; $minBet = (int) ($config['min_bet'] ?? 100); $maxBet = (int) ($config['max_bet'] ?? 50000); if ($data['amount'] < $minBet || $data['amount'] > $maxBet) { return response()->json(['ok' => false, 'message' => "押注金额须在 {$minBet}~{$maxBet} 金币之间。"]); } $round = BaccaratRound::find($data['round_id']); if (! $round || ! $round->isBettingOpen()) { return response()->json(['ok' => false, 'message' => '当前不在下注时间内。']); } $user = $request->user(); // 检查用户金币余额(金币字段为 jjb) if (($user->jjb ?? 0) < $data['amount']) { return response()->json(['ok' => false, 'message' => '金币不足,无法下注。']); } $currency = $this->currency; return DB::transaction(function () use ($user, $round, $data, $currency): JsonResponse { // 幂等:同一局只能下一注 $existing = BaccaratBet::query() ->where('round_id', $round->id) ->where('user_id', $user->id) ->lockForUpdate() ->exists(); if ($existing) { return response()->json(['ok' => false, 'message' => '本局您已下注,请等待开奖。']); } // 扣除金币 $currency->change( $user, 'gold', -$data['amount'], CurrencySource::BACCARAT_BET, "百家乐 #{$round->id} 押 ".match ($data['bet_type']) { 'big' => '大', 'small' => '小', default => '豹子' }, ); // 写入下注记录 BaccaratBet::create([ 'round_id' => $round->id, 'user_id' => $user->id, 'bet_type' => $data['bet_type'], 'amount' => $data['amount'], 'status' => 'pending', ]); // 更新局次汇总统计 $field = 'total_bet_'.$data['bet_type']; $countField = 'bet_count_'.$data['bet_type']; $round->increment($field, $data['amount']); $round->increment($countField); $round->increment('bet_count'); // 广播各选项的最新押注人数 event(new \App\Events\BaccaratPoolUpdated($round)); $betLabel = match ($data['bet_type']) { 'big' => '大', 'small' => '小', default => '豹子' }; return response()->json([ 'ok' => true, 'message' => "✅ 已押注「{$betLabel}」{$data['amount']} 金币,等待开奖!", 'amount' => $data['amount'], 'bet_type' => $data['bet_type'], ]); }); } /** * 查询最近5局的历史记录(前端展示趋势)。 */ public function history(): JsonResponse { $rounds = BaccaratRound::query() ->where('status', 'settled') ->orderByDesc('id') ->limit(10) ->get(['id', 'dice1', 'dice2', 'dice3', 'total_points', 'result', 'settled_at']); return response()->json(['history' => $rounds]); } }