diff --git a/app/common/service/GameLiveService.php b/app/common/service/GameLiveService.php index 70d6262..489f1d4 100644 --- a/app/common/service/GameLiveService.php +++ b/app/common/service/GameLiveService.php @@ -25,13 +25,14 @@ final class GameLiveService private const EVT_PERIOD_PAYOUT = 'period.payout'; private const KEY_PERIOD_SECONDS = 'period_seconds'; private const KEY_BET_SECONDS = 'bet_seconds'; + private const KEY_PAYOUT_SECONDS = 'payout_seconds'; private const KEY_PICK_MAX_NUMBER_COUNT = 'pick_max_number_count'; /** 开奖结果号码池:1 至此上限(与单注可选号码个数配置无关) */ private const DRAW_NUMBER_MAX = 36; - /** 开奖后派彩展示宽限期(秒),之后再创建下一期 */ - private const PAYOUT_GRACE_SECONDS = 3; + /** 派彩展示宽限期默认值(秒),可被 game_config.payout_seconds 覆盖 */ + private const DEFAULT_PAYOUT_SECONDS = 3; /** 启动自愈:判定“异常卡局”的最小超时冗余秒数 */ private const STARTUP_RECOVER_GRACE_SECONDS = 10; @@ -64,7 +65,7 @@ final class GameLiveService return; } $periodSeconds = self::getConfigInt(self::KEY_PERIOD_SECONDS, 30); - $timeoutAt = $periodStartAt + $periodSeconds + self::PAYOUT_GRACE_SECONDS + self::STARTUP_RECOVER_GRACE_SECONDS; + $timeoutAt = $periodStartAt + $periodSeconds + self::getPayoutGraceSeconds() + self::STARTUP_RECOVER_GRACE_SECONDS; if (time() <= $timeoutAt) { return; } @@ -98,7 +99,7 @@ final class GameLiveService GameBetSettleService::settleBetsForDraw($recordId, $resultNumber); if ($status === 2) { if ($payoutUntil <= 0) { - $payoutUntil = $now + self::PAYOUT_GRACE_SECONDS; + $payoutUntil = $now + self::getPayoutGraceSeconds(); } Db::name('game_record')->where('id', $recordId)->update([ 'status' => 3, @@ -575,7 +576,7 @@ final class GameLiveService $bets = Db::name('bet_order')->where('period_id', (int) $record['id'])->select()->toArray(); $finalLoss = self::estimateLossForNumber($bets, $finalNumber); $now = time(); - $payoutUntil = $now + self::PAYOUT_GRACE_SECONDS; + $payoutUntil = $now + self::getPayoutGraceSeconds(); $settleOut = ['jackpot_hits' => []]; Db::startTrans(); @@ -1099,6 +1100,18 @@ final class GameLiveService return (int) $v; } + private static function getPayoutGraceSeconds(): int + { + $seconds = self::getConfigInt(self::KEY_PAYOUT_SECONDS, self::DEFAULT_PAYOUT_SECONDS); + if ($seconds < 1) { + return 1; + } + if ($seconds > 300) { + return 300; + } + return $seconds; + } + private static function getPickMaxNumberCount(): int { $max = self::getConfigInt(self::KEY_PICK_MAX_NUMBER_COUNT, 36); diff --git a/app/functions.php b/app/functions.php index d99306b..f266340 100644 --- a/app/functions.php +++ b/app/functions.php @@ -455,25 +455,28 @@ if (!function_exists('get_route_remark')) { function get_route_remark(): string { $controllerPath = get_controller_path() ?? ''; - $actionName = ''; - if (function_exists('request')) { - $req = request(); - if ($req) { - $path = trim($req->path(), '/'); - $parts = explode('/', $path); - $actionName = $parts[array_key_last($parts)] ?? ''; - } + if ($controllerPath === '') { + return ''; } $path = str_replace('.', '/', $controllerPath); - $names = [$path]; - if ($actionName) { - $names[] = $path . '/' . $actionName; + $menuNames = [$path]; + $parts = explode('/', $path); + foreach ($parts as &$part) { + if (str_contains($part, '_')) { + $part = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $part)))); + } + } + unset($part); + $camelPath = implode('/', $parts); + if ($camelPath !== $path) { + $menuNames[] = $camelPath; } $remark = \support\think\Db::name('admin_rule') - ->where('name', 'in', $names) + ->where('name', 'in', array_values(array_unique($menuNames))) + ->where('type', 'in', ['menu', 'menu_dir']) ->value('remark'); $remarkStr = (string) ($remark ?? ''); - if (!$remarkStr) { + if ($remarkStr === '') { return ''; } return function_exists('trans') ? trans($remarkStr, [], $controllerPath ?: null) : $remarkStr; diff --git a/web/src/lang/backend/en/game/config.ts b/web/src/lang/backend/en/game/config.ts index 8b50b65..fceee15 100644 --- a/web/src/lang/backend/en/game/config.ts +++ b/web/src/lang/backend/en/game/config.ts @@ -10,6 +10,8 @@ export default { 'field_tip period_seconds': 'Duration of each period in seconds', 'field bet_seconds': 'Betting duration (seconds)', 'field_tip bet_seconds': 'How many seconds betting stays open in each period', + 'field payout_seconds': 'Payout duration (seconds)', + 'field_tip payout_seconds': 'Grace period after draw before the next period starts; lock/calc duration = period duration − betting duration', 'field pick_max_number_count': 'Max numbers per ticket', 'field_tip pick_max_number_count': 'Maximum amount of selectable numbers per ticket', 'field bet_chips': 'Quick chip amounts', diff --git a/web/src/lang/backend/zh-cn/game/config.ts b/web/src/lang/backend/zh-cn/game/config.ts index c2ce3ac..d1eeaa2 100644 --- a/web/src/lang/backend/zh-cn/game/config.ts +++ b/web/src/lang/backend/zh-cn/game/config.ts @@ -10,6 +10,8 @@ export default { 'field_tip period_seconds': '每一局的总时长(秒)', 'field bet_seconds': '下注时长(秒)', 'field_tip bet_seconds': '每一局允许下注的时长(秒)', + 'field payout_seconds': '派彩时长(秒)', + 'field_tip payout_seconds': '开奖后派彩展示宽限期(秒),结束后自动进入下一期;封盘计算时长 = 每期时长 − 下注时长', 'field pick_max_number_count': '单注最多号码个数', 'field_tip pick_max_number_count': '单注最多可选号码数量', 'field bet_chips': '快捷筹码面额', diff --git a/web/src/views/backend/config/gameConfig/index.vue b/web/src/views/backend/config/gameConfig/index.vue index 08be171..05f341f 100644 --- a/web/src/views/backend/config/gameConfig/index.vue +++ b/web/src/views/backend/config/gameConfig/index.vue @@ -1,4 +1,4 @@ -