diff --git a/app/api/controller/Game.php b/app/api/controller/Game.php index 734004e..f889b67 100644 --- a/app/api/controller/Game.php +++ b/app/api/controller/Game.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace app\api\controller; use app\common\library\game\BetChips; +use app\common\library\game\GamePeriodNo; use app\common\library\game\StreakWinReward; use app\common\library\game\ZiHuaDictionary; use app\common\model\BetOrder; @@ -21,7 +22,7 @@ use support\Response; class Game extends MobileBase { - protected array $noNeedLogin = ['dictionaryList']; + protected array $noNeedLogin = ['dictionaryList', 'periodHistory']; public function lobbyInit(Request $request): Response { @@ -58,7 +59,10 @@ class Game extends MobileBase 'runtime_enabled' => GameRecordService::getConfigBool(GameRecordService::KEY_AUTO_CREATE), 'period' => [ 'period_id' => $periodRow ? $this->intValue($periodRow['id'] ?? 0) : 0, - 'period_no' => (string) ($periodRow['period_no'] ?? ''), + 'period_no' => GamePeriodNo::toDisplay( + (string) ($periodRow['period_no'] ?? ''), + $periodRow ? $this->intValue($periodRow['id'] ?? 0) : 0 + ), 'status' => $this->mapPeriodStatus($periodRow['status'] ?? null), 'countdown' => $countdown, 'lock_at' => $lockAt, @@ -105,6 +109,36 @@ class Game extends MobileBase ]); } + /** + * 获取最近开奖记录(默认最新 30 条),期号为纯数字。 + */ + public function periodHistory(Request $request): Response + { + $response = $this->initializeMobile($request); + if ($response !== null) { + return $response; + } + $limit = $this->intValue($request->input('limit', 30)); + if ($limit < 1) { + $limit = 30; + } + if ($limit > 100) { + $limit = 100; + } + $list = GameRecord::whereNotNull('result_number')->order('id', 'desc')->limit($limit)->select(); + $rows = []; + foreach ($list as $item) { + $periodId = $this->intValue($item->id ?? 0); + $rows[] = [ + 'period_no' => GamePeriodNo::toDisplay((string) ($item->period_no ?? ''), $periodId), + 'result_number' => $item->result_number, + 'open_time' => $item->update_time, + ]; + } + + return $this->mobileSuccess(['list' => $rows]); + } + public function periodCurrent(Request $request): Response { $response = $this->initializeMobile($request); @@ -120,7 +154,10 @@ class Game extends MobileBase return $this->mobileSuccess([ 'runtime_enabled' => GameRecordService::getConfigBool(GameRecordService::KEY_AUTO_CREATE), 'period_id' => $this->intValue($periodRow['id'] ?? 0), - 'period_no' => $periodRow['period_no'], + 'period_no' => GamePeriodNo::toDisplay( + (string) ($periodRow['period_no'] ?? ''), + $this->intValue($periodRow['id'] ?? 0) + ), 'status' => $this->mapPeriodStatus($periodRow['status'] ?? null), 'countdown' => max(0, ($startAt + 30) - $now), 'bet_close_in' => max(0, ($startAt + 20) - $now), @@ -188,6 +225,12 @@ class Game extends MobileBase return $this->mobileError(3001, 'Game is paused'); } $period = GameRecord::where('period_no', $periodNo)->find(); + if (!$period && ctype_digit($periodNo)) { + $periodIdLookup = filter_var($periodNo, FILTER_VALIDATE_INT); + if ($periodIdLookup !== false && $periodIdLookup > 0) { + $period = GameRecord::find($periodIdLookup); + } + } if (!$period) { return $this->mobileError(2002, 'Game period does not exist'); } @@ -311,9 +354,13 @@ class Game extends MobileBase 'biz_type' => 'bet', 'changed_at' => time(), ], $userId, $streakAtBet)); + $periodIdForDisplay = filter_var($period->id ?? null, FILTER_VALIDATE_INT); + if ($periodIdForDisplay === false) { + $periodIdForDisplay = 0; + } return $this->mobileSuccess([ 'order_no' => $orderNo, - 'period_no' => $period->period_no, + 'period_no' => GamePeriodNo::toDisplay((string) ($period->period_no ?? ''), $periodIdForDisplay), 'status' => 'accepted', 'bet_id' => $betChipId, 'single_bet_amount' => $singleAmount, @@ -437,7 +484,7 @@ class Game extends MobileBase } $rows[] = [ 'order_no' => (string) $item->id, - 'period_no' => $item->period_no, + 'period_no' => GamePeriodNo::toDisplay((string) ($item->period_no ?? ''), $periodIdValue), 'numbers' => $item->pick_numbers ?? [], // 整笔压注金额(本笔总扣款) 'bet_amount' => $item->total_amount, diff --git a/app/common/library/game/GamePeriodNo.php b/app/common/library/game/GamePeriodNo.php new file mode 100644 index 0000000..84147f4 --- /dev/null +++ b/app/common/library/game/GamePeriodNo.php @@ -0,0 +1,55 @@ +max('id'); + $maxId = filter_var($maxIdRaw, FILTER_VALIDATE_INT); + if ($maxId === false) { + $maxId = 0; + } + + $maxNumericRow = Db::name('game_record') + ->whereRaw("period_no REGEXP '^[0-9]+$'") + ->fieldRaw('MAX(CAST(period_no AS UNSIGNED)) AS max_no') + ->find(); + $maxNumericRaw = is_array($maxNumericRow) ? ($maxNumericRow['max_no'] ?? null) : null; + $maxNumeric = filter_var($maxNumericRaw, FILTER_VALIDATE_INT); + if ($maxNumeric === false) { + $maxNumeric = 0; + } + + $next = max($maxId, $maxNumeric) + 1; + + return (string) $next; + } + + /** + * 对外 API / 列表展示的纯数字期号;历史非数字期号回退为 period_id。 + */ + public static function toDisplay(string $periodNo, int $periodId = 0): string + { + $trimmed = trim($periodNo); + if ($trimmed !== '' && ctype_digit($trimmed)) { + return $trimmed; + } + if ($periodId > 0) { + return (string) $periodId; + } + + return $trimmed; + } +} diff --git a/app/common/service/GameRecordService.php b/app/common/service/GameRecordService.php index c83eabc..a1714eb 100644 --- a/app/common/service/GameRecordService.php +++ b/app/common/service/GameRecordService.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace app\common\service; +use app\common\library\game\GamePeriodNo; use support\think\Db; use Throwable; @@ -192,7 +193,7 @@ final class GameRecordService private static function generatePeriodNo(): string { - return date('Ymd-His') . '-' . substr(bin2hex(random_bytes(4)), 0, 8); + return GamePeriodNo::generateNext(); } private static function truthyConfigInput(mixed $v): bool diff --git a/web/src/lang/backend/en/game/record.ts b/web/src/lang/backend/en/game/record.ts index f860ff7..2541421 100644 --- a/web/src/lang/backend/en/game/record.ts +++ b/web/src/lang/backend/en/game/record.ts @@ -1,7 +1,7 @@ export default { - 'quick Search Fields': 'Round No. / ID', + 'quick Search Fields': 'Period No. / ID', id: 'ID', - period_no: 'Round No.', + period_no: 'Period No.', period_start_at: 'Start time', status: 'Status', 'status 0': 'Betting open', diff --git a/web/src/lang/backend/zh-cn/game/record.ts b/web/src/lang/backend/zh-cn/game/record.ts index b962946..e7607a6 100644 --- a/web/src/lang/backend/zh-cn/game/record.ts +++ b/web/src/lang/backend/zh-cn/game/record.ts @@ -1,7 +1,7 @@ export default { - 'quick Search Fields': '局号/ID', + 'quick Search Fields': '期数/ID', id: 'ID', - period_no: '局号', + period_no: '期数', period_start_at: '开始时间', status: '状态', 'status 0': '下注开放',