From 025cce3e3e05eb07847bf8202bb86510102186f5 Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Mon, 20 Apr 2026 10:27:01 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E5=92=8C=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=BF=94=E5=9B=9E=E5=AF=B9=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/lang/en/admin_rule_title.php | 103 ++++++++++++++++++++++++ app/common/lang/en/game_live.php | 24 ++++++ app/common/lang/zh-cn/game_live.php | 24 ++++++ app/common/service/GameLiveService.php | 54 +++++++------ config/game_hot_cache.php | 28 +++++++ 5 files changed, 209 insertions(+), 24 deletions(-) create mode 100644 app/common/lang/en/admin_rule_title.php create mode 100644 app/common/lang/en/game_live.php create mode 100644 app/common/lang/zh-cn/game_live.php create mode 100644 config/game_hot_cache.php diff --git a/app/common/lang/en/admin_rule_title.php b/app/common/lang/en/admin_rule_title.php new file mode 100644 index 0000000..8a6ce27 --- /dev/null +++ b/app/common/lang/en/admin_rule_title.php @@ -0,0 +1,103 @@ + 'View', + '添加' => 'Add', + '编辑' => 'Edit', + '删除' => 'Delete', + '保存' => 'Save', + '快速排序' => 'Quick sort', + '还原' => 'Restore', + '回滚' => 'Rollback', + '查看详情' => 'View details', + '生成' => 'Generate', + '安装' => 'Install', + '调整状态' => 'Change state', + '卸载' => 'Uninstall', + '更新' => 'Update', + '审核通过' => 'Approve', + '审核驳回' => 'Reject', + + // 安装包默认菜单 + '控制台' => 'Dashboard', + '权限管理' => 'Permission management', + '角色组管理' => 'Role groups', + '管理员管理' => 'Administrators', + '菜单规则管理' => 'Menu rules', + '管理员日志管理' => 'Admin logs', + '常规管理' => 'Routine', + '系统配置' => 'System configuration', + '附件管理' => 'Attachments', + '个人资料' => 'Profile', + '数据安全管理' => 'Data security', + '数据回收站' => 'Data recycle bin', + '敏感数据修改记录' => 'Sensitive data change log', + '数据回收规则管理' => 'Data recycle rules', + '敏感字段规则管理' => 'Sensitive field rules', + '模块市场' => 'Module store', + 'CRUD代码生成' => 'CRUD generator', + + // 会员端 user_rule(若出现在后台接口中) + '我的账户' => 'My account', + '账户概览' => 'Overview', + '积分记录' => 'Score log', + '余额记录' => 'Balance log', + + // 业务扩展菜单 + '用户管理' => 'User management', + '用户列表' => 'User list', + '订单管理' => 'Order management', + '游戏管理' => 'Game management', + '配置管理' => 'Configuration', + '游戏配置' => 'Game configuration', + '常规配置' => 'General settings', + '记录管理' => 'Records', + '游戏对局' => 'Game rounds', + '游戏对局记录' => 'Game records', + '游戏实时对局' => 'Game live', + '压注订单' => 'Bet orders', + '充值订单' => 'Deposit orders', + '提现订单' => 'Withdraw orders', + '用户钱包流水' => 'User wallet transactions', + '36字花字典' => '36 Zihua dictionary', + '代理与结算' => 'Agents & settlement', + '代理结算周期' => 'Agent settlement periods', + '代理佣金记录' => 'Agent commission records', + '运营' => 'Operations', + '运营公告' => 'Operation notices', + '用户阅读记录' => 'User read log', + '充值档位' => 'Deposit tiers', + '连胜奖励' => 'Win streak rewards', + '连胜降低档位' => 'Streak reduction tiers', + '钱包加减点' => 'Wallet adjust', + '测试' => 'Test', + '推送-对局公共频道' => 'Push: public game period', + '推送-公告广播频道' => 'Push: operation notices', + '推送-用户私有频道' => 'Push: user private', + '渠道管理' => 'Channel management', + + // 演示/运营公告标题(若入库为菜单展示) + '系统维护通知(演示)' => 'Maintenance notice (demo)', + '提现风控升级提醒(演示)' => 'Withdraw risk notice (demo)', + '活动奖励发放说明(演示)' => 'Promotion notice (demo)', + + // 部分按钮 title 为动作名(game/live 等迁移写入) + 'index' => 'View', + 'snapshot' => 'Snapshot', + 'pushConfig' => 'Push config', + 'recordSettings' => 'Period settings', + 'createNextManual' => 'Create next period manually', + 'periodSettings' => 'Period settings', + 'manualSettle' => 'Manual settle', + + // 其它中文按钮文案 + '期号开关' => 'Period toggle', + '手动创建下一期' => 'Create next period manually', +]; diff --git a/app/common/lang/en/game_live.php b/app/common/lang/en/game_live.php new file mode 100644 index 0000000..8d6fdda --- /dev/null +++ b/app/common/lang/en/game_live.php @@ -0,0 +1,24 @@ + 'No active game in progress', + 'Current game status does not allow calculation' => 'Current game status does not allow calculation', + 'Betting period has not ended; calculation is not available yet' => 'Betting period has not ended; calculation is not available yet', + 'Manual draw number is out of the allowed range' => 'Manual draw number is out of the allowed range', + 'Calculation completed' => 'Calculation completed', + 'Draw number is out of the allowed range' => 'Draw number is out of the allowed range', + 'Current game status does not allow scheduling the draw' => 'Current game status does not allow scheduling the draw', + 'Betting has not ended; cannot schedule the draw' => 'Betting has not ended; cannot schedule the draw', + 'This period has ended; please refresh the page' => 'This period has ended; please refresh the page', + 'Draw number scheduled; it will be used when the countdown ends' => 'Draw number scheduled; it will be used when the countdown ends', + 'Current game status does not allow drawing' => 'Current game status does not allow drawing', + 'Betting period has not ended; drawing is not available yet' => 'Betting period has not ended; drawing is not available yet', + 'Period countdown has not ended; cannot draw yet' => 'Period countdown has not ended; cannot draw yet', + 'Draw completed; paying out' => 'Draw completed; paying out', + 'Game live: settlement error' => 'Game live: settlement error', + 'Calculation failed' => 'Calculation failed', + 'Please enter the draw number' => 'Please enter the draw number', + 'Schedule failed' => 'Schedule failed', +]; diff --git a/app/common/lang/zh-cn/game_live.php b/app/common/lang/zh-cn/game_live.php new file mode 100644 index 0000000..7757c99 --- /dev/null +++ b/app/common/lang/zh-cn/game_live.php @@ -0,0 +1,24 @@ + '未找到进行中的对局', + 'Current game status does not allow calculation' => '当前对局状态不可计算', + 'Betting period has not ended; calculation is not available yet' => '下注开放时长未结束,暂不可计算', + 'Manual draw number is out of the allowed range' => '手动开奖号码超出允许范围', + 'Calculation completed' => '计算完成', + 'Draw number is out of the allowed range' => '开奖号码超出允许范围', + 'Current game status does not allow scheduling the draw' => '当前对局状态不可预约开奖', + 'Betting has not ended; cannot schedule the draw' => '下注尚未结束,无法预约开奖', + 'This period has ended; please refresh the page' => '本期倒计时已结束,请刷新页面', + 'Draw number scheduled; it will be used when the countdown ends' => '已预约本期开奖号码,倒计时结束后将使用该号码开奖', + 'Current game status does not allow drawing' => '当前对局状态不可开奖', + 'Betting period has not ended; drawing is not available yet' => '下注开放时长未结束,不可开奖', + 'Period countdown has not ended; cannot draw yet' => '本期倒计时未结束,无法开奖', + 'Draw completed; paying out' => '开奖完成,派彩中', + 'Game live: settlement error' => '对局结算出错', + 'Calculation failed' => '计算失败', + 'Please enter the draw number' => '请填写开奖号码', + 'Schedule failed' => '预约失败', +]; diff --git a/app/common/service/GameLiveService.php b/app/common/service/GameLiveService.php index 494672f..4ad0482 100644 --- a/app/common/service/GameLiveService.php +++ b/app/common/service/GameLiveService.php @@ -159,27 +159,27 @@ final class GameLiveService { $record = self::resolveRecord($recordId); if (!$record) { - return ['ok' => false, 'msg' => '未找到进行中的对局']; + return ['ok' => false, 'msg' => __('No active game in progress')]; } if (!in_array((int) $record['status'], [0, 1], true)) { - return ['ok' => false, 'msg' => '当前对局状态不可计算']; + return ['ok' => false, 'msg' => __('Current game status does not allow calculation')]; } $periodSeconds = self::getConfigInt(self::KEY_PERIOD_SECONDS, 30); $betSeconds = self::getConfigInt(self::KEY_BET_SECONDS, 20); $elapsed = max(0, time() - (int) $record['period_start_at']); if ($elapsed < $betSeconds) { - return ['ok' => false, 'msg' => '下注开放时长未结束,暂不可计算']; + return ['ok' => false, 'msg' => __('Betting period has not ended; calculation is not available yet')]; } self::ensureAiLocked((int) $record['id']); $record = self::reloadRecord((int) $record['id']); if (!$record) { - return ['ok' => false, 'msg' => '未找到进行中的对局']; + return ['ok' => false, 'msg' => __('No active game in progress')]; } $pickMax = self::getPickMaxNumberCount(); if ($manualNumber !== null && ($manualNumber < 1 || $manualNumber > self::DRAW_NUMBER_MAX)) { - return ['ok' => false, 'msg' => '手动开奖号码超出允许范围']; + return ['ok' => false, 'msg' => __('Manual draw number is out of the allowed range')]; } $bets = Db::name('bet_order')->where('period_id', (int) $record['id'])->select()->toArray(); @@ -215,7 +215,7 @@ final class GameLiveService return [ 'ok' => true, - 'msg' => '计算完成', + 'msg' => __('Calculation completed'), 'record' => $record, 'period_seconds' => $periodSeconds, 'bet_seconds' => $betSeconds, @@ -234,23 +234,23 @@ final class GameLiveService public static function scheduleDraw(?int $recordId, int $manualNumber): array { if ($manualNumber < 1 || $manualNumber > self::DRAW_NUMBER_MAX) { - return ['ok' => false, 'msg' => '开奖号码超出允许范围']; + return ['ok' => false, 'msg' => __('Draw number is out of the allowed range')]; } $record = self::resolveRecord($recordId); if (!$record) { - return ['ok' => false, 'msg' => '未找到进行中的对局']; + return ['ok' => false, 'msg' => __('No active game in progress')]; } if (!in_array((int) $record['status'], [0, 1], true)) { - return ['ok' => false, 'msg' => '当前对局状态不可预约开奖']; + return ['ok' => false, 'msg' => __('Current game status does not allow scheduling the draw')]; } $periodSeconds = self::getConfigInt(self::KEY_PERIOD_SECONDS, 30); $betSeconds = self::getConfigInt(self::KEY_BET_SECONDS, 20); $elapsed = max(0, time() - (int) $record['period_start_at']); if ($elapsed < $betSeconds) { - return ['ok' => false, 'msg' => '下注尚未结束,无法预约开奖']; + return ['ok' => false, 'msg' => __('Betting has not ended; cannot schedule the draw')]; } if ($elapsed >= $periodSeconds) { - return ['ok' => false, 'msg' => '本期倒计时已结束,请刷新页面']; + return ['ok' => false, 'msg' => __('This period has ended; please refresh the page')]; } self::ensureAiLocked((int) $record['id']); @@ -258,11 +258,12 @@ final class GameLiveService 'pending_draw_number' => $manualNumber, 'update_time' => time(), ]); + GameHotDataRedis::gameRecordForget((int) $record['id']); self::publishSnapshot(null); return [ 'ok' => true, - 'msg' => '已预约本期开奖号码,倒计时结束后将使用该号码开奖', + 'msg' => __('Draw number scheduled; it will be used when the countdown ends'), ]; } @@ -273,25 +274,25 @@ final class GameLiveService { $record = self::resolveRecord($recordId); if (!$record) { - return ['ok' => false, 'msg' => '未找到进行中的对局']; + return ['ok' => false, 'msg' => __('No active game in progress')]; } if (!in_array((int) $record['status'], [0, 1], true)) { - return ['ok' => false, 'msg' => '当前对局状态不可开奖']; + return ['ok' => false, 'msg' => __('Current game status does not allow drawing')]; } $periodSeconds = self::getConfigInt(self::KEY_PERIOD_SECONDS, 30); $betSeconds = self::getConfigInt(self::KEY_BET_SECONDS, 20); $elapsed = max(0, time() - (int) $record['period_start_at']); if ($elapsed < $betSeconds) { - return ['ok' => false, 'msg' => '下注开放时长未结束,不可开奖']; + return ['ok' => false, 'msg' => __('Betting period has not ended; drawing is not available yet')]; } if ($elapsed < $periodSeconds) { - return ['ok' => false, 'msg' => '本期倒计时未结束,无法开奖']; + return ['ok' => false, 'msg' => __('Period countdown has not ended; cannot draw yet')]; } self::ensureAiLocked((int) $record['id']); $record = self::reloadRecord((int) $record['id']); if (!$record) { - return ['ok' => false, 'msg' => '未找到进行中的对局']; + return ['ok' => false, 'msg' => __('No active game in progress')]; } $useManual = $manualNumber; @@ -342,9 +343,11 @@ final class GameLiveService Db::commit(); } catch (Throwable $e) { Db::rollback(); - return ['ok' => false, 'msg' => $e->getMessage()]; + return ['ok' => false, 'msg' => __('Game live: settlement error') . ': ' . $e->getMessage()]; } + GameHotDataRedis::gameRecordForget((int) $record['id']); + try { GameRecordStatService::refreshForRecordId((int) $record['id']); } catch (Throwable) { @@ -357,7 +360,7 @@ final class GameLiveService return [ 'ok' => true, - 'msg' => '开奖完成,派彩中', + 'msg' => __('Draw completed; paying out'), 'result_number' => $finalNumber, 'estimated_loss' => $finalLoss, 'payout_until' => $payoutUntil, @@ -392,6 +395,7 @@ final class GameLiveService Db::rollback(); return; } + GameHotDataRedis::gameRecordForget($id); GameRecordStatService::refreshForRecordId($id); self::publishSnapshot(null); } @@ -565,17 +569,17 @@ final class GameLiveService private static function resolveRecord(?int $recordId): ?array { if ($recordId !== null && $recordId > 0) { - $row = Db::name('game_record')->where('id', $recordId)->find(); + $row = GameHotDataRedis::gameRecordById($recordId); if ($row) { return $row; } } - return Db::name('game_record')->whereIn('status', [0, 1, 2, 3])->order('id', 'desc')->find(); + return GameHotDataRedis::gameRecordActive(); } private static function reloadRecord(int $id): ?array { - $row = Db::name('game_record')->where('id', $id)->find(); + $row = GameHotDataRedis::gameRecordById($id); return $row ?: null; } @@ -584,7 +588,7 @@ final class GameLiveService */ private static function ensureAiLocked(int $recordId): void { - $record = Db::name('game_record')->where('id', $recordId)->find(); + $record = GameHotDataRedis::gameRecordById($recordId); if (!$record) { return; } @@ -605,6 +609,7 @@ final class GameLiveService 'status' => 1, 'update_time' => time(), ]); + GameHotDataRedis::gameRecordForget($recordId); $record['status'] = 1; self::publishPublicPeriodLocked($record); } @@ -624,6 +629,7 @@ final class GameLiveService $update['status'] = 1; } Db::name('game_record')->where('id', $recordId)->update($update); + GameHotDataRedis::gameRecordForget($recordId); $record = array_merge($record, $update); if ($st === 0) { self::publishPublicPeriodLocked($record); @@ -653,7 +659,7 @@ final class GameLiveService private static function getConfigInt(string $key, int $default): int { - $row = Db::name('game_config')->where('config_key', $key)->find(); + $row = GameHotDataRedis::gameConfigRow($key); if (!$row) { return $default; } diff --git a/config/game_hot_cache.php b/config/game_hot_cache.php new file mode 100644 index 0000000..37b22b1 --- /dev/null +++ b/config/game_hot_cache.php @@ -0,0 +1,28 @@ + filter_var(env('GAME_HOT_CACHE_ENABLED', true), FILTER_VALIDATE_BOOLEAN), + /** game_config 行缓存(秒),后台修改会主动删除 */ + 'ttl_game_config' => $envInt('GAME_HOT_CACHE_TTL_GAME_CONFIG', 86400), + /** game_record 行缓存(秒) */ + 'ttl_game_record' => $envInt('GAME_HOT_CACHE_TTL_GAME_RECORD', 60), + /** user 行缓存(秒),余额/连胜变更会主动删除 */ + 'ttl_user' => $envInt('GAME_HOT_CACHE_TTL_USER', 90), +];