From 805847954dc0353803553447d4fbfed74729e8d0 Mon Sep 17 00:00:00 2001 From: kang Date: Wed, 13 May 2026 11:54:40 +0800 Subject: [PATCH] =?UTF-8?q?refactor=EF=BC=9A=E6=8B=86=E5=88=86=20API=20?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E4=B8=8E=E8=AF=B7=E6=B1=82=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=EF=BC=8C=E7=BB=9F=E4=B8=80=20final=20=E7=B1=BB=E5=92=8C?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Commands/LotteryDrawTickCommand.php | 4 +- .../Commands/LotteryHallCountdownCommand.php | 4 +- app/Events/DrawCountdownBroadcast.php | 6 +- app/Events/DrawResultPublishedBroadcast.php | 6 +- app/Events/DrawStatusChangeBroadcast.php | 6 +- .../PlayerAuthenticationException.php | 2 +- app/Exceptions/WalletOperationException.php | 2 +- .../Admin/Audit/AuditLogIndexController.php | 4 +- .../Api/V1/Admin/Auth/CaptchaController.php | 2 +- .../Api/V1/Admin/Auth/LoginController.php | 26 +- .../Config/OddsItemsReplaceController.php | 12 +- .../Config/OddsVersionIndexController.php | 10 +- .../Config/OddsVersionPublishController.php | 14 +- .../Config/OddsVersionShowController.php | 4 +- .../Config/OddsVersionStoreController.php | 8 +- .../PlayConfigItemsReplaceController.php | 14 +- .../PlayConfigVersionIndexController.php | 12 +- .../PlayConfigVersionPublishController.php | 14 +- .../PlayConfigVersionShowController.php | 6 +- .../PlayConfigVersionStoreController.php | 8 +- .../Config/RiskCapItemsReplaceController.php | 14 +- .../Config/RiskCapVersionIndexController.php | 12 +- .../RiskCapVersionPublishController.php | 14 +- .../Config/RiskCapVersionShowController.php | 6 +- .../Config/RiskCapVersionStoreController.php | 8 +- .../Dashboard/AdminDashboardController.php | 8 +- .../AdminDrawFinanceSummaryController.php | 4 +- .../Admin/Draw/AdminDrawIndexController.php | 10 +- .../AdminDrawResultBatchesIndexController.php | 6 +- .../V1/Admin/Draw/AdminDrawShowController.php | 8 +- .../Draw/DrawResultBatchPublishController.php | 14 +- .../Draw/DrawSettlementRunController.php | 10 +- ...dminJackpotContributionIndexController.php | 6 +- .../AdminJackpotPayoutLogIndexController.php | 8 +- .../AdminJackpotPoolIndexController.php | 2 +- .../AdminJackpotPoolUpdateController.php | 4 +- .../Api/V1/Admin/PingController.php | 4 +- .../Api/V1/Admin/PlayTypeIndexController.php | 4 +- .../Api/V1/Admin/PlayTypePatchController.php | 6 +- .../AdminPlayerTicketItemsIndexController.php | 24 +- .../Player/PlayerWalletShowController.php | 2 +- .../ReconcileItemIndexController.php | 6 +- .../Reconcile/ReconcileJobIndexController.php | 4 +- .../Reconcile/ReconcileJobShowController.php | 2 +- .../Reconcile/ReconcileJobStoreController.php | 23 +- .../Reports/ReportJobIndexController.php | 4 +- .../Admin/Reports/ReportJobShowController.php | 2 +- .../Reports/ReportJobStoreController.php | 14 +- .../Risk/AdminRiskPoolIndexController.php | 8 +- .../AdminRiskPoolLockLogIndexController.php | 10 +- .../Risk/AdminRiskPoolShowController.php | 14 +- .../AdminSettlementBatchDetailsController.php | 10 +- .../AdminSettlementBatchIndexController.php | 8 +- .../AdminSettlementBatchShowController.php | 4 +- .../User/AdminPermissionCatalogController.php | 2 +- .../Admin/User/AdminUserDestroyController.php | 10 +- .../Admin/User/AdminUserIndexController.php | 8 +- .../AdminUserPermissionSyncController.php | 17 +- .../User/AdminUserRoleSyncController.php | 15 +- .../V1/Admin/User/AdminUserShowController.php | 4 +- .../Admin/User/AdminUserStoreController.php | 51 +-- .../Admin/User/AdminUserUpdateController.php | 24 +- .../Wallet/TransferOrderListController.php | 29 +- .../WalletTransactionListController.php | 28 +- .../Api/V1/Draw/DrawCurrentController.php | 8 +- .../Api/V1/Draw/DrawResultShowController.php | 10 +- .../V1/Draw/DrawResultsIndexController.php | 19 +- .../Controllers/Api/V1/HealthController.php | 4 +- .../V1/Jackpot/JackpotSummaryController.php | 6 +- .../Play/PlayEffectiveCatalogController.php | 8 +- .../Api/V1/Player/MeController.php | 6 +- .../Api/V1/Player/PingController.php | 4 +- .../V1/Ticket/TicketDrawMyMatchController.php | 10 +- .../V1/Ticket/TicketItemShowController.php | 10 +- .../V1/Ticket/TicketItemsIndexController.php | 13 +- .../Api/V1/Ticket/TicketPlaceController.php | 8 +- .../Api/V1/Ticket/TicketPreviewController.php | 8 +- .../Api/V1/Wallet/WalletBalanceController.php | 20 +- .../Api/V1/Wallet/WalletLogsController.php | 19 +- .../V1/Wallet/WalletTransferInController.php | 26 +- .../V1/Wallet/WalletTransferOutController.php | 26 +- app/Http/Middleware/EnsureAdminApi.php | 8 +- app/Http/Middleware/EnsureAdminPermission.php | 8 +- app/Http/Middleware/EnsurePlayerApi.php | 12 +- .../Middleware/NegotiateLotteryLocale.php | 4 +- app/Http/Requests/Admin/AdminLoginRequest.php | 44 +++ .../Admin/AdminPlayerTicketItemsRequest.php | 30 ++ .../Admin/AdminUserPermissionSyncRequest.php | 29 ++ .../Admin/AdminUserRoleSyncRequest.php | 29 ++ .../Requests/Admin/AdminUserStoreRequest.php | 59 +++ .../Requests/Admin/AdminUserUpdateRequest.php | 41 +++ .../Admin/ReconcileJobStoreRequest.php | 30 ++ .../Requests/Admin/ReportJobStoreRequest.php | 31 ++ .../Admin/TransferOrderListRequest.php | 37 ++ .../Admin/WalletTransactionListRequest.php | 38 ++ .../Requests/Ticket/TicketPlaceRequest.php | 2 +- .../Requests/Ticket/TicketPreviewRequest.php | 2 +- .../Requests/Wallet/WalletTransferRequest.php | 2 +- app/Models/AdminMenu.php | 2 +- app/Models/AdminMenuAction.php | 2 +- app/Models/AdminRole.php | 6 +- app/Models/AdminUser.php | 12 +- app/Models/AuditLog.php | 2 +- app/Models/Currency.php | 2 +- app/Models/Draw.php | 2 +- app/Models/DrawResultBatch.php | 4 +- app/Models/DrawResultItem.php | 2 +- app/Models/JackpotContribution.php | 2 +- app/Models/JackpotPayoutLog.php | 2 +- app/Models/JackpotPool.php | 4 +- app/Models/LotterySetting.php | 2 +- app/Models/OddsItem.php | 2 +- app/Models/OddsVersion.php | 6 +- app/Models/PlayConfigItem.php | 2 +- app/Models/PlayConfigVersion.php | 6 +- app/Models/PlayType.php | 2 +- app/Models/Player.php | 2 +- app/Models/PlayerWallet.php | 2 +- app/Models/ReconcileItem.php | 2 +- app/Models/ReconcileJob.php | 4 +- app/Models/ReportJob.php | 2 +- app/Models/RiskCapItem.php | 2 +- app/Models/RiskCapVersion.php | 6 +- app/Models/RiskPool.php | 2 +- app/Models/RiskPoolLockLog.php | 2 +- app/Models/SettlementBatch.php | 4 +- app/Models/TicketCombination.php | 2 +- app/Models/TicketItem.php | 6 +- app/Models/TicketOrder.php | 4 +- app/Models/TicketSettlementDetail.php | 2 +- app/Models/TransferOrder.php | 2 +- app/Models/WalletTxn.php | 2 +- app/Providers/AppServiceProvider.php | 14 +- .../Admin/AdminDashboardSnapshotBuilder.php | 8 +- .../Admin/AdminReconcileJobService.php | 12 +- app/Services/Admin/AdminReportJobService.php | 6 +- app/Services/AdminCaptchaService.php | 4 +- app/Services/AuditLogger.php | 4 +- .../Config/EffectivePlayCatalogService.php | 8 +- app/Services/Config/OddsStreamService.php | 12 +- .../Config/PlayConfigStreamService.php | 10 +- app/Services/Config/RiskCapStreamService.php | 8 +- app/Services/Draw/DrawHallSnapshotBuilder.php | 10 +- app/Services/Draw/DrawPlannerService.php | 6 +- app/Services/Draw/DrawPublishService.php | 6 +- app/Services/Draw/DrawResultViewService.php | 8 +- app/Services/Draw/DrawRngRunner.php | 12 +- app/Services/Draw/DrawTickService.php | 4 +- .../Draw/LotteryHallRealtimeBroadcaster.php | 2 +- .../Jackpot/JackpotBurstAllocator.php | 6 +- .../Jackpot/JackpotContributionService.php | 4 +- app/Services/PlayerTokenResolver.php | 8 +- .../Contracts/SettlementPlayMatcher.php | 4 +- .../Matchers/BigSpreadSettlementMatcher.php | 6 +- .../FirstPrizeComboSettlementMatcher.php | 6 +- .../Matchers/NoopSettlementMatcher.php | 4 +- .../Matchers/Pos2AbcSettlementMatcher.php | 6 +- .../Matchers/Pos2TierSettlementMatcher.php | 6 +- .../Matchers/Pos3AbcSettlementMatcher.php | 6 +- .../Matchers/Pos3TierSettlementMatcher.php | 6 +- .../Pos4ExactTierSettlementMatcher.php | 6 +- .../Pos4ListTierSettlementMatcher.php | 6 +- .../Matchers/SmallSpreadSettlementMatcher.php | 6 +- .../StraightLikeSettlementMatcher.php | 6 +- .../Settlement/SettlementMatcherRegistry.php | 12 +- .../Settlement/SettlementOrchestrator.php | 18 +- app/Services/Ticket/NumberNormalizer.php | 2 +- app/Services/Ticket/PlayCatalogResolver.php | 12 +- app/Services/Ticket/PlayRuleEngine.php | 6 +- app/Services/Ticket/RiskPoolService.php | 6 +- .../Ticket/TicketPlacementService.php | 10 +- app/Services/Ticket/TicketPreviewService.php | 6 +- app/Services/Ticket/TicketWalletService.php | 8 +- .../Wallet/HttpMainSiteWalletGateway.php | 2 +- .../Wallet/LotteryTransferService.php | 12 +- app/Support/AdminApiList.php | 4 +- app/Support/AdminConfigPresenter.php | 6 +- app/Support/AdminMessage.php | 56 +++ app/Support/ApiResponse.php | 3 +- app/Support/CurrencyResolver.php | 68 ++++ app/Support/OddsStandardScopes.php | 2 +- app/Support/PaginationTrait.php | 51 +++ bootstrap/app.php | 18 +- config/app.php | 2 - config/auth.php | 2 - config/broadcasting.php | 4 - config/cache.php | 4 - config/database.php | 8 +- config/filesystems.php | 4 - config/logging.php | 4 - config/lottery.php | 2 - config/mail.php | 4 - config/queue.php | 4 - config/reverb.php | 6 - config/sanctum.php | 8 +- config/services.php | 2 - config/session.php | 2 - .../0001_01_01_000000_create_users_table.php | 4 +- .../0001_01_01_000001_create_cache_table.php | 4 +- .../0001_01_01_000002_create_jobs_table.php | 4 +- ...6_05_08_100000_create_currencies_table.php | 4 +- ...2026_05_08_100001_create_players_table.php | 4 +- ..._05_08_100002_create_admin_users_table.php | 4 +- ...ate_admin_roles_and_permissions_tables.php | 4 +- ..._08_100004_create_player_wallets_table.php | 4 +- ..._05_08_100005_create_wallet_txns_table.php | 4 +- ...08_100006_create_transfer_orders_table.php | 4 +- .../2026_05_08_100007_create_draws_table.php | 4 +- ...00008_create_draw_result_batches_table.php | 4 +- ..._100009_create_draw_result_items_table.php | 4 +- ...efault_users_and_password_reset_tables.php | 4 +- ...6_05_08_130000_create_play_types_table.php | 4 +- ..._play_config_versions_and_items_tables.php | 4 +- ..._create_odds_versions_and_items_tables.php | 4 +- ...ate_risk_cap_versions_and_items_tables.php | 4 +- ...5_08_130004_create_ticket_orders_table.php | 4 +- ...05_08_130005_create_ticket_items_table.php | 4 +- ...30006_create_ticket_combinations_table.php | 4 +- ...create_risk_pools_and_lock_logs_tables.php | 4 +- ...8_create_settlement_and_jackpot_tables.php | 4 +- ...9_create_report_audit_reconcile_tables.php | 4 +- ...8_140000_create_lottery_settings_table.php | 4 +- ...35_create_personal_access_tokens_table.php | 4 +- ...name_and_nullable_email_to_admin_users.php | 6 +- ...000_migrate_draw_status_to_domain_dict.php | 2 +- ..._admin_user_id_to_reconcile_jobs_table.php | 4 +- ...00_create_admin_user_permissions_table.php | 4 +- ...000_rebuild_admin_authorization_system.php | 4 +- database/seeders/AdminRbacAndUserSeeder.php | 4 +- database/seeders/CurrencySeeder.php | 2 +- .../seeders/DashboardHallFixtureSeeder.php | 12 +- .../DashboardSecondaryScenariosSeeder.php | 20 +- database/seeders/DatabaseSeeder.php | 4 +- database/seeders/DevPlayerAndWalletSeeder.php | 2 +- database/seeders/DrawDemoSeeder.php | 14 +- database/seeders/LotterySettingsSeeder.php | 4 +- .../seeders/OddsPrizeScopesBackfillSeeder.php | 4 +- .../seeders/OperationalConfigV1Seeder.php | 12 +- database/seeders/PlayTypeSeeder.php | 2 +- pint.json | 29 ++ public/index.php | 2 +- routes/api.php | 335 ++---------------- routes/api/v1/admin/auth.php | 16 + routes/api/v1/admin/config.php | 107 ++++++ routes/api/v1/admin/core.php | 21 ++ routes/api/v1/admin/draw.php | 60 ++++ routes/api/v1/admin/jackpot.php | 27 ++ routes/api/v1/admin/player.php | 16 + routes/api/v1/admin/report.php | 19 + routes/api/v1/admin/user.php | 34 ++ routes/api/v1/admin/wallet.php | 35 ++ routes/api/v1/player.php | 50 +++ routes/api/v1/public.php | 37 ++ tests/Feature/AdminAuthLoginTest.php | 4 +- tests/Feature/AdminCsFinanceApisTest.php | 4 +- tests/Feature/AdminDashboardApiTest.php | 4 +- tests/Feature/AdminDrawApiTest.php | 12 +- tests/Feature/AdminPhase15OperationsTest.php | 10 +- tests/Feature/AdminRiskPoolApiTest.php | 4 +- .../Feature/AdminSettlementJackpotApiTest.php | 2 +- tests/Feature/AdminUserPermissionApiTest.php | 6 +- tests/Feature/AdminWalletApiTest.php | 8 +- tests/Feature/AuditLoggerTest.php | 2 +- tests/Feature/DrawPipelineTest.php | 26 +- tests/Feature/DrawResultsApiTest.php | 6 +- .../JackpotPlacementSettlementTest.php | 22 +- tests/Feature/LotterySettingsTest.php | 2 +- tests/Feature/OddsStandardScopesSyncTest.php | 4 +- .../OperationalConfigAcceptanceTest.php | 18 +- tests/Feature/OperationalConfigApiTest.php | 8 +- tests/Feature/PlayerFoundationTest.php | 6 +- ...tlementMatcherRegistryCompletenessTest.php | 4 +- tests/Feature/SettlementOrchestratorTest.php | 22 +- .../SettlementPhase145AcceptanceTest.php | 32 +- tests/Feature/TicketBettingApiTest.php | 20 +- tests/Feature/TicketItemsApiTest.php | 14 +- tests/Feature/WalletBalanceTest.php | 2 +- tests/Feature/WalletLogsTest.php | 6 +- tests/Feature/WalletTransferScenariosTest.php | 10 +- tests/Feature/WalletTransferTest.php | 6 +- tests/Pest.php | 6 +- 281 files changed, 1886 insertions(+), 1308 deletions(-) create mode 100644 app/Http/Requests/Admin/AdminLoginRequest.php create mode 100644 app/Http/Requests/Admin/AdminPlayerTicketItemsRequest.php create mode 100644 app/Http/Requests/Admin/AdminUserPermissionSyncRequest.php create mode 100644 app/Http/Requests/Admin/AdminUserRoleSyncRequest.php create mode 100644 app/Http/Requests/Admin/AdminUserStoreRequest.php create mode 100644 app/Http/Requests/Admin/AdminUserUpdateRequest.php create mode 100644 app/Http/Requests/Admin/ReconcileJobStoreRequest.php create mode 100644 app/Http/Requests/Admin/ReportJobStoreRequest.php create mode 100644 app/Http/Requests/Admin/TransferOrderListRequest.php create mode 100644 app/Http/Requests/Admin/WalletTransactionListRequest.php create mode 100644 app/Support/AdminMessage.php create mode 100644 app/Support/CurrencyResolver.php create mode 100644 app/Support/PaginationTrait.php create mode 100644 pint.json create mode 100644 routes/api/v1/admin/auth.php create mode 100644 routes/api/v1/admin/config.php create mode 100644 routes/api/v1/admin/core.php create mode 100644 routes/api/v1/admin/draw.php create mode 100644 routes/api/v1/admin/jackpot.php create mode 100644 routes/api/v1/admin/player.php create mode 100644 routes/api/v1/admin/report.php create mode 100644 routes/api/v1/admin/user.php create mode 100644 routes/api/v1/admin/wallet.php create mode 100644 routes/api/v1/player.php create mode 100644 routes/api/v1/public.php diff --git a/app/Console/Commands/LotteryDrawTickCommand.php b/app/Console/Commands/LotteryDrawTickCommand.php index 218e95c..ef8e8e4 100644 --- a/app/Console/Commands/LotteryDrawTickCommand.php +++ b/app/Console/Commands/LotteryDrawTickCommand.php @@ -2,10 +2,10 @@ namespace App\Console\Commands; -use App\Services\Draw\DrawTickService; use Illuminate\Console\Command; +use App\Services\Draw\DrawTickService; -class LotteryDrawTickCommand extends Command +final class LotteryDrawTickCommand extends Command { protected $signature = 'lottery:draw-tick'; diff --git a/app/Console/Commands/LotteryHallCountdownCommand.php b/app/Console/Commands/LotteryHallCountdownCommand.php index 8ee28c4..e686c27 100644 --- a/app/Console/Commands/LotteryHallCountdownCommand.php +++ b/app/Console/Commands/LotteryHallCountdownCommand.php @@ -2,10 +2,10 @@ namespace App\Console\Commands; -use App\Services\Draw\LotteryHallRealtimeBroadcaster; use Illuminate\Console\Command; +use App\Services\Draw\LotteryHallRealtimeBroadcaster; -class LotteryHallCountdownCommand extends Command +final class LotteryHallCountdownCommand extends Command { protected $signature = 'lottery:hall-countdown'; diff --git a/app/Events/DrawCountdownBroadcast.php b/app/Events/DrawCountdownBroadcast.php index e2e9205..e273657 100644 --- a/app/Events/DrawCountdownBroadcast.php +++ b/app/Events/DrawCountdownBroadcast.php @@ -3,13 +3,13 @@ namespace App\Events; use Illuminate\Broadcasting\Channel; +use Illuminate\Queue\SerializesModels; +use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; -use Illuminate\Foundation\Events\Dispatchable; -use Illuminate\Queue\SerializesModels; /** 界面文档 §2.1:`draw.countdown` */ -class DrawCountdownBroadcast implements ShouldBroadcastNow +final class DrawCountdownBroadcast implements ShouldBroadcastNow { use Dispatchable, InteractsWithSockets, SerializesModels; diff --git a/app/Events/DrawResultPublishedBroadcast.php b/app/Events/DrawResultPublishedBroadcast.php index 5dfd000..600c427 100644 --- a/app/Events/DrawResultPublishedBroadcast.php +++ b/app/Events/DrawResultPublishedBroadcast.php @@ -3,13 +3,13 @@ namespace App\Events; use Illuminate\Broadcasting\Channel; +use Illuminate\Queue\SerializesModels; +use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; -use Illuminate\Foundation\Events\Dispatchable; -use Illuminate\Queue\SerializesModels; /** 界面文档 §2.1:`result.published` */ -class DrawResultPublishedBroadcast implements ShouldBroadcastNow +final class DrawResultPublishedBroadcast implements ShouldBroadcastNow { use Dispatchable, InteractsWithSockets, SerializesModels; diff --git a/app/Events/DrawStatusChangeBroadcast.php b/app/Events/DrawStatusChangeBroadcast.php index 9e05c0d..6f1a92a 100644 --- a/app/Events/DrawStatusChangeBroadcast.php +++ b/app/Events/DrawStatusChangeBroadcast.php @@ -3,13 +3,13 @@ namespace App\Events; use Illuminate\Broadcasting\Channel; +use Illuminate\Queue\SerializesModels; +use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; -use Illuminate\Foundation\Events\Dispatchable; -use Illuminate\Queue\SerializesModels; /** 界面文档 §2.1:`draw.status_change` */ -class DrawStatusChangeBroadcast implements ShouldBroadcastNow +final class DrawStatusChangeBroadcast implements ShouldBroadcastNow { use Dispatchable, InteractsWithSockets, SerializesModels; diff --git a/app/Exceptions/PlayerAuthenticationException.php b/app/Exceptions/PlayerAuthenticationException.php index 6483450..2297315 100644 --- a/app/Exceptions/PlayerAuthenticationException.php +++ b/app/Exceptions/PlayerAuthenticationException.php @@ -2,8 +2,8 @@ namespace App\Exceptions; -use App\Lottery\ErrorCode; use RuntimeException; +use App\Lottery\ErrorCode; /** * 玩家端 Bearer 鉴权失败时抛出,由 EnsurePlayerApi 捕获并转为 JSON。 diff --git a/app/Exceptions/WalletOperationException.php b/app/Exceptions/WalletOperationException.php index 7a442b0..5193b68 100644 --- a/app/Exceptions/WalletOperationException.php +++ b/app/Exceptions/WalletOperationException.php @@ -2,9 +2,9 @@ namespace App\Exceptions; +use RuntimeException; use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use RuntimeException; /** * 玩家钱包划转等业务失败时抛出,由控制器捕获并转为 {@see ApiResponse} JSON。 diff --git a/app/Http/Controllers/Api/V1/Admin/Audit/AuditLogIndexController.php b/app/Http/Controllers/Api/V1/Admin/Audit/AuditLogIndexController.php index e7a48ff..71f54c1 100644 --- a/app/Http/Controllers/Api/V1/Admin/Audit/AuditLogIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Audit/AuditLogIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Audit; -use App\Http\Controllers\Controller; use App\Models\AuditLog; +use Illuminate\Http\Request; use App\Support\AdminApiList; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/audit-logs — 运营/客服查询审计留痕。 diff --git a/app/Http/Controllers/Api/V1/Admin/Auth/CaptchaController.php b/app/Http/Controllers/Api/V1/Admin/Auth/CaptchaController.php index 5c32685..7b971a3 100644 --- a/app/Http/Controllers/Api/V1/Admin/Auth/CaptchaController.php +++ b/app/Http/Controllers/Api/V1/Admin/Auth/CaptchaController.php @@ -2,9 +2,9 @@ namespace App\Http\Controllers\Api\V1\Admin\Auth; -use App\Services\AdminCaptchaService; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Services\AdminCaptchaService; /** * GET /api/v1/admin/auth/captcha diff --git a/app/Http/Controllers/Api/V1/Admin/Auth/LoginController.php b/app/Http/Controllers/Api/V1/Admin/Auth/LoginController.php index 1755d96..580184d 100644 --- a/app/Http/Controllers/Api/V1/Admin/Auth/LoginController.php +++ b/app/Http/Controllers/Api/V1/Admin/Auth/LoginController.php @@ -2,38 +2,28 @@ namespace App\Http\Controllers\Api\V1\Admin\Auth; -use App\Lottery\ErrorCode; use App\Models\AdminUser; -use App\Services\AdminCaptchaService; +use App\Lottery\ErrorCode; +use Illuminate\Support\Str; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; -use Illuminate\Support\Str; +use App\Services\AdminCaptchaService; +use App\Http\Requests\Admin\AdminLoginRequest; /** * POST /api/v1/admin/auth/login * * Body: account(登录账号,与 username 对应,ASCII 仅存小写比对)、password、captcha_key、captcha_code。 */ -final class LoginController +final class LoginController extends Controller { - public function __invoke(Request $request, AdminCaptchaService $captcha): JsonResponse + public function __invoke(AdminLoginRequest $request, AdminCaptchaService $captcha): JsonResponse { $locale = $request->lotteryLocale(); - /** @var array{account:string,password:string,captcha_key:string,captcha_code:string} $data */ - $data = validator($request->all(), [ - 'account' => ['required', 'string', 'min:2', 'max:64', 'regex:/^[a-zA-Z0-9._-]+$/u'], - 'password' => ['required', 'string', 'max:256'], - 'captcha_key' => ['required', 'string', 'uuid'], - 'captcha_code' => ['required', 'string', 'max:32'], - ], [], [ - 'account' => 'account', - 'password' => 'password', - 'captcha_key' => 'captcha_key', - 'captcha_code' => 'captcha_code', - ])->validate(); + $data = $request->validated(); if (! $captcha->verify($data['captcha_key'], $data['captcha_code'])) { return ApiResponse::error( diff --git a/app/Http/Controllers/Api/V1/Admin/Config/OddsItemsReplaceController.php b/app/Http/Controllers/Api/V1/Admin/Config/OddsItemsReplaceController.php index 115f1b6..5e9684a 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/OddsItemsReplaceController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/OddsItemsReplaceController.php @@ -2,17 +2,17 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; -use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; use App\Models\AdminUser; +use App\Lottery\ErrorCode; use App\Models\OddsVersion; -use App\Services\Config\OddsStreamService; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Validation\Rule; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Lottery\ConfigVersionStatus; +use App\Support\AdminConfigPresenter; +use App\Services\Config\OddsStreamService; /** PUT /api/v1/admin/config/odds-versions/{id}/items */ final class OddsItemsReplaceController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionIndexController.php b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionIndexController.php index 1c509fe..56cba63 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionIndexController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; use App\Models\OddsVersion; -use App\Services\Config\OddsStreamService; -use App\Support\AdminApiList; -use App\Support\AdminConfigPresenter; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; +use App\Services\Config\OddsStreamService; /** GET /api/v1/admin/config/odds-versions */ final class OddsVersionIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionPublishController.php b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionPublishController.php index c4bcce3..7e14f43 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionPublishController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionPublishController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; +use App\Models\OddsVersion; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; -use App\Models\OddsVersion; -use App\Services\Config\OddsStreamService; use App\Support\AdminConfigPresenter; -use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Services\Config\OddsStreamService; /** POST /api/v1/admin/config/odds-versions/{id}/publish */ final class OddsVersionPublishController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionShowController.php b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionShowController.php index a234992..54a544e 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionShowController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; use App\Models\OddsVersion; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; /** GET /api/v1/admin/config/odds-versions/{id} */ final class OddsVersionShowController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionStoreController.php b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionStoreController.php index 3c8fbae..798ea25 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionStoreController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/OddsVersionStoreController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Services\Config\OddsStreamService; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; +use App\Services\Config\OddsStreamService; /** POST /api/v1/admin/config/odds-versions */ final class OddsVersionStoreController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigItemsReplaceController.php b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigItemsReplaceController.php index f1c1fbf..26120b3 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigItemsReplaceController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigItemsReplaceController.php @@ -2,17 +2,17 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; -use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; use App\Models\AdminUser; -use App\Models\PlayConfigVersion; -use App\Services\Config\PlayConfigStreamService; -use App\Support\AdminConfigPresenter; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Validation\Rule; +use App\Models\PlayConfigVersion; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Lottery\ConfigVersionStatus; +use App\Support\AdminConfigPresenter; +use App\Services\Config\PlayConfigStreamService; /** PUT /api/v1/admin/config/play-versions/{id}/items */ final class PlayConfigItemsReplaceController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionIndexController.php b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionIndexController.php index 67b82a0..9408099 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionIndexController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; -use App\Models\PlayConfigVersion; -use App\Services\Config\PlayConfigStreamService; -use App\Support\AdminApiList; -use App\Support\AdminConfigPresenter; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use App\Models\PlayConfigVersion; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; +use App\Services\Config\PlayConfigStreamService; /** GET /api/v1/admin/config/play-versions */ final class PlayConfigVersionIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionPublishController.php b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionPublishController.php index bdd587a..324a4d7 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionPublishController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionPublishController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use App\Models\PlayConfigVersion; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; -use App\Models\PlayConfigVersion; -use App\Services\Config\PlayConfigStreamService; use App\Support\AdminConfigPresenter; -use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Services\Config\PlayConfigStreamService; /** POST /api/v1/admin/config/play-versions/{id}/publish */ final class PlayConfigVersionPublishController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionShowController.php b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionShowController.php index 814c9a7..7757895 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionShowController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; -use App\Models\PlayConfigVersion; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; +use App\Models\PlayConfigVersion; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; /** GET /api/v1/admin/config/play-versions/{id} */ final class PlayConfigVersionShowController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionStoreController.php b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionStoreController.php index 778a349..66ae51e 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionStoreController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/PlayConfigVersionStoreController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Services\Config\PlayConfigStreamService; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; +use App\Services\Config\PlayConfigStreamService; /** POST /api/v1/admin/config/play-versions — 新建草稿(默认克隆当前 active,若无则按 play_types 生成)。 */ final class PlayConfigVersionStoreController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapItemsReplaceController.php b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapItemsReplaceController.php index 15b7b6a..883990d 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapItemsReplaceController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapItemsReplaceController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use App\Models\RiskCapVersion; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; -use App\Models\RiskCapVersion; -use App\Services\Config\RiskCapStreamService; use App\Support\AdminConfigPresenter; -use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Services\Config\RiskCapStreamService; /** PUT /api/v1/admin/config/risk-cap-versions/{id}/items */ final class RiskCapItemsReplaceController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionIndexController.php b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionIndexController.php index a32d3eb..a6acf7b 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionIndexController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; -use App\Models\RiskCapVersion; -use App\Services\Config\RiskCapStreamService; -use App\Support\AdminApiList; -use App\Support\AdminConfigPresenter; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use App\Models\RiskCapVersion; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; +use App\Services\Config\RiskCapStreamService; /** GET /api/v1/admin/config/risk-cap-versions */ final class RiskCapVersionIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionPublishController.php b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionPublishController.php index 42d2556..600f90c 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionPublishController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionPublishController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use App\Models\RiskCapVersion; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; -use App\Models\RiskCapVersion; -use App\Services\Config\RiskCapStreamService; use App\Support\AdminConfigPresenter; -use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Services\Config\RiskCapStreamService; /** POST /api/v1/admin/config/risk-cap-versions/{id}/publish */ final class RiskCapVersionPublishController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionShowController.php b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionShowController.php index a42c62d..9a92628 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionShowController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; -use App\Models\RiskCapVersion; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; +use App\Models\RiskCapVersion; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; /** GET /api/v1/admin/config/risk-cap-versions/{id} */ final class RiskCapVersionShowController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionStoreController.php b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionStoreController.php index a678c86..f569d46 100644 --- a/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionStoreController.php +++ b/app/Http/Controllers/Api/V1/Admin/Config/RiskCapVersionStoreController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Config; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Services\Config\RiskCapStreamService; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; +use App\Services\Config\RiskCapStreamService; /** POST /api/v1/admin/config/risk-cap-versions */ final class RiskCapVersionStoreController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Dashboard/AdminDashboardController.php b/app/Http/Controllers/Api/V1/Admin/Dashboard/AdminDashboardController.php index 3c6ba5f..8089e39 100644 --- a/app/Http/Controllers/Api/V1/Admin/Dashboard/AdminDashboardController.php +++ b/app/Http/Controllers/Api/V1/Admin/Dashboard/AdminDashboardController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Dashboard; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; use App\Models\AdminUser; -use App\Services\Admin\AdminDashboardSnapshotBuilder; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Admin\AdminDashboardSnapshotBuilder; /** * GET /api/v1/admin/dashboard — 首页仪表盘聚合数据(需登录;按权限返回子块)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawFinanceSummaryController.php b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawFinanceSummaryController.php index 62e3eb4..f51367e 100644 --- a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawFinanceSummaryController.php +++ b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawFinanceSummaryController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Draw; -use App\Http\Controllers\Controller; use App\Models\Draw; -use App\Models\SettlementBatch; use App\Models\TicketItem; use App\Models\TicketOrder; use App\Support\ApiResponse; +use App\Models\SettlementBatch; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/draws/{draw}/finance-summary — 单期投注/派彩汇总(客服/财务视角,PRD §15.4)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawIndexController.php b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawIndexController.php index 4cc2f05..735e4f6 100644 --- a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawIndexController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Draw; -use App\Http\Controllers\Controller; -use App\Models\Draw; -use App\Support\AdminApiList; use Carbon\Carbon; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\JsonResponse; +use App\Models\Draw; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** * GET /api/v1/admin/draws — 期号列表。 diff --git a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawResultBatchesIndexController.php b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawResultBatchesIndexController.php index 2a79142..18b479a 100644 --- a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawResultBatchesIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawResultBatchesIndexController.php @@ -2,12 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin\Draw; -use App\Http\Controllers\Controller; use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Models\DrawResultItem; use App\Support\ApiResponse; +use App\Models\DrawResultItem; +use App\Models\DrawResultBatch; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/draws/{draw}/result-batches — 开奖批次与号码(审核/结果核对)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawShowController.php b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawShowController.php index d736dc6..0846363 100644 --- a/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Draw/AdminDrawShowController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Draw; +use Carbon\Carbon; +use App\Models\Draw; +use App\Support\ApiResponse; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Lottery\DrawResultBatchStatus; -use App\Models\Draw; use App\Services\Draw\DrawHallSnapshotBuilder; -use App\Support\ApiResponse; -use Carbon\Carbon; -use Illuminate\Http\JsonResponse; /** * GET /api/v1/admin/draws/{draw} — 当期状态明细(后台查看 DB 为准 + 大厅展示态预览)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Draw/DrawResultBatchPublishController.php b/app/Http/Controllers/Api/V1/Admin/Draw/DrawResultBatchPublishController.php index bfbda26..aa4a5d5 100644 --- a/app/Http/Controllers/Api/V1/Admin/Draw/DrawResultBatchPublishController.php +++ b/app/Http/Controllers/Api/V1/Admin/Draw/DrawResultBatchPublishController.php @@ -2,20 +2,20 @@ namespace App\Http\Controllers\Api\V1\Admin\Draw; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Services\Draw\DrawPublishService; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Models\DrawResultBatch; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Draw\DrawPublishService; /** * POST /api/v1/admin/draws/{draw}/result-batches/{batch}/publish — 人工审核发布 RNG 批次。 */ -class DrawResultBatchPublishController extends Controller +final class DrawResultBatchPublishController extends Controller { public function __construct( private readonly DrawPublishService $publishService, diff --git a/app/Http/Controllers/Api/V1/Admin/Draw/DrawSettlementRunController.php b/app/Http/Controllers/Api/V1/Admin/Draw/DrawSettlementRunController.php index d854407..12fe943 100644 --- a/app/Http/Controllers/Api/V1/Admin/Draw/DrawSettlementRunController.php +++ b/app/Http/Controllers/Api/V1/Admin/Draw/DrawSettlementRunController.php @@ -2,14 +2,14 @@ namespace App\Http\Controllers\Api\V1\Admin\Draw; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; use App\Models\Draw; -use App\Services\Settlement\SettlementOrchestrator; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Settlement\SettlementOrchestrator; /** * POST /api/v1/admin/draws/{draw}/settlement/run — 对 `settling` 期号执行结算(可关自动结算时手工触发)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotContributionIndexController.php b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotContributionIndexController.php index a5ddb60..5e73ae0 100644 --- a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotContributionIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotContributionIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Jackpot; -use App\Http\Controllers\Controller; -use App\Models\JackpotContribution; +use Illuminate\Http\Request; use App\Support\AdminApiList; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Models\JackpotContribution; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/jackpot/contributions — Jackpot 蓄水流水。 diff --git a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPayoutLogIndexController.php b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPayoutLogIndexController.php index 29fb6e3..7c5b94e 100644 --- a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPayoutLogIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPayoutLogIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Jackpot; -use App\Http\Controllers\Controller; -use App\Models\JackpotPayoutLog; -use App\Support\AdminApiList; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use App\Models\JackpotPayoutLog; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/jackpot/payout-logs — Jackpot 派彩(爆池)记录。 diff --git a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolIndexController.php b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolIndexController.php index 4d904ef..33c4ee8 100644 --- a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolIndexController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Api\V1\Admin\Jackpot; -use App\Http\Controllers\Controller; use App\Models\JackpotPool; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/jackpot/pools — Jackpot 奖池配置列表。 diff --git a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolUpdateController.php b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolUpdateController.php index 02ff976..1512725 100644 --- a/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolUpdateController.php +++ b/app/Http/Controllers/Api/V1/Admin/Jackpot/AdminJackpotPoolUpdateController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Jackpot; -use App\Http\Controllers\Controller; use App\Models\JackpotPool; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * PUT /api/v1/admin/jackpot/pools/{pool} — 更新奖池运营参数(蓄水比例、阈值等)。 diff --git a/app/Http/Controllers/Api/V1/Admin/PingController.php b/app/Http/Controllers/Api/V1/Admin/PingController.php index 71febb7..ae7629c 100644 --- a/app/Http/Controllers/Api/V1/Admin/PingController.php +++ b/app/Http/Controllers/Api/V1/Admin/PingController.php @@ -2,15 +2,15 @@ namespace App\Http\Controllers\Api\V1\Admin; -use App\Http\Controllers\Controller; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * Bearer Token 必填({@see EnsureAdminApi} + Sanctum);确认 `/api/v1/admin` 鉴权链路可达。 * 路由:GET /api/v1/admin/ping */ -class PingController extends Controller +final class PingController extends Controller { public function __invoke(): JsonResponse { diff --git a/app/Http/Controllers/Api/V1/Admin/PlayTypeIndexController.php b/app/Http/Controllers/Api/V1/Admin/PlayTypeIndexController.php index ddc3344..9c6e213 100644 --- a/app/Http/Controllers/Api/V1/Admin/PlayTypeIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/PlayTypeIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin; -use App\Http\Controllers\Controller; use App\Models\PlayType; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; /** GET /api/v1/admin/play-types */ final class PlayTypeIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/PlayTypePatchController.php b/app/Http/Controllers/Api/V1/Admin/PlayTypePatchController.php index 2d6f089..559d12f 100644 --- a/app/Http/Controllers/Api/V1/Admin/PlayTypePatchController.php +++ b/app/Http/Controllers/Api/V1/Admin/PlayTypePatchController.php @@ -2,12 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin; -use App\Http\Controllers\Controller; use App\Models\PlayType; -use App\Support\AdminConfigPresenter; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminConfigPresenter; /** PATCH /api/v1/admin/play-types/{play_code} — 主目录层开关与展示名(不等同于版本化 items)。 */ final class PlayTypePatchController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Player/AdminPlayerTicketItemsIndexController.php b/app/Http/Controllers/Api/V1/Admin/Player/AdminPlayerTicketItemsIndexController.php index 6347132..92a6c33 100644 --- a/app/Http/Controllers/Api/V1/Admin/Player/AdminPlayerTicketItemsIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Player/AdminPlayerTicketItemsIndexController.php @@ -2,12 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Player; -use App\Http\Controllers\Controller; use App\Models\Player; use App\Models\TicketItem; use App\Support\ApiResponse; +use App\Support\PaginationTrait; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\AdminPlayerTicketItemsRequest; /** * GET /api/v1/admin/players/{player}/ticket-items — 客服/财务按玩家查注单(PRD §15.4)。 @@ -16,17 +17,16 @@ use Illuminate\Http\Request; */ final class AdminPlayerTicketItemsIndexController extends Controller { - public function __invoke(Request $request, Player $player): JsonResponse - { - $validated = validator($request->query(), [ - 'page' => ['sometimes', 'integer', 'min:1'], - 'per_page' => ['sometimes', 'integer', 'min:1', 'max:50'], - 'draw_no' => ['sometimes', 'nullable', 'string', 'max:32'], - ])->validate(); + use PaginationTrait; - $perPage = max(1, min(50, (int) ($validated['per_page'] ?? 20))); - $page = max(1, (int) ($validated['page'] ?? 1)); - $drawNo = isset($validated['draw_no']) ? trim((string) $validated['draw_no']) : ''; + public function __invoke(AdminPlayerTicketItemsRequest $request, Player $player): JsonResponse + { + $perPage = $this->perPage($request, 'per_page', 20, 50); + $page = $this->page($request); + $drawNo = $request->validated('draw_no'); + if (is_string($drawNo)) { + $drawNo = trim($drawNo); + } $query = TicketItem::query() ->where('ticket_items.player_id', $player->id) diff --git a/app/Http/Controllers/Api/V1/Admin/Player/PlayerWalletShowController.php b/app/Http/Controllers/Api/V1/Admin/Player/PlayerWalletShowController.php index d0deee2..bb54cb3 100644 --- a/app/Http/Controllers/Api/V1/Admin/Player/PlayerWalletShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Player/PlayerWalletShowController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Player; -use App\Http\Controllers\Controller; use App\Models\Player; use App\Models\PlayerWallet; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * 后台:按玩家查询钱包余额(`player_wallets` 全币种)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileItemIndexController.php b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileItemIndexController.php index 2f67383..dcc1f43 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileItemIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileItemIndexController.php @@ -2,12 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin\Reconcile; -use App\Http\Controllers\Controller; -use App\Models\ReconcileItem; use App\Models\ReconcileJob; +use Illuminate\Http\Request; +use App\Models\ReconcileItem; use App\Support\AdminApiList; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; /** GET /api/v1/admin/reconcile-jobs/{reconcile_job}/items */ final class ReconcileItemIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobIndexController.php b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobIndexController.php index 40fa5ea..d70f1de 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Reconcile; -use App\Http\Controllers\Controller; use App\Models\ReconcileJob; +use Illuminate\Http\Request; use App\Support\AdminApiList; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; /** GET /api/v1/admin/reconcile-jobs */ final class ReconcileJobIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobShowController.php b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobShowController.php index d88e33a..d2144ec 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobShowController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Api\V1\Admin\Reconcile; -use App\Http\Controllers\Controller; use App\Models\ReconcileJob; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** GET /api/v1/admin/reconcile-jobs/{reconcile_job} */ final class ReconcileJobShowController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobStoreController.php b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobStoreController.php index 145d076..e2a56e7 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobStoreController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reconcile/ReconcileJobStoreController.php @@ -2,32 +2,23 @@ namespace App\Http\Controllers\Api\V1\Admin\Reconcile; -use App\Http\Controllers\Controller; -use App\Models\AdminUser; -use App\Services\Admin\AdminReconcileJobService; -use App\Support\ApiResponse; use Carbon\Carbon; +use App\Models\AdminUser; +use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Services\Admin\AdminReconcileJobService; +use App\Http\Requests\Admin\ReconcileJobStoreRequest; /** POST /api/v1/admin/reconcile-jobs */ final class ReconcileJobStoreController extends Controller { - public function __invoke(Request $request, AdminReconcileJobService $service): JsonResponse + public function __invoke(ReconcileJobStoreRequest $request, AdminReconcileJobService $service): JsonResponse { /** @var AdminUser $admin */ $admin = $request->lotteryAdmin(); - $data = validator($request->all(), [ - 'reconcile_type' => ['required', 'string', 'max:32'], - 'period_start' => ['nullable', 'date'], - 'period_end' => ['nullable', 'date', 'after_or_equal:period_start'], - 'items' => ['nullable', 'array', 'max:5000'], - 'items.*.side_a_ref' => ['nullable', 'string', 'max:128'], - 'items.*.side_b_ref' => ['nullable', 'string', 'max:128'], - 'items.*.difference_amount' => ['nullable', 'integer'], - 'items.*.status' => ['nullable', 'string', 'max:32'], - ])->validate(); + $data = $request->validated(); $job = $service->createJob( $admin, diff --git a/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobIndexController.php b/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobIndexController.php index 6112c90..18b997d 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Reports; -use App\Http\Controllers\Controller; use App\Models\ReportJob; +use Illuminate\Http\Request; use App\Support\AdminApiList; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; /** GET /api/v1/admin/report-jobs */ final class ReportJobIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobShowController.php b/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobShowController.php index 370bcd8..87ec83f 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobShowController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Api\V1\Admin\Reports; -use App\Http\Controllers\Controller; use App\Models\ReportJob; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** GET /api/v1/admin/report-jobs/{report_job} */ final class ReportJobShowController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobStoreController.php b/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobStoreController.php index 3f0a064..44e74a5 100644 --- a/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobStoreController.php +++ b/app/Http/Controllers/Api/V1/Admin/Reports/ReportJobStoreController.php @@ -2,26 +2,22 @@ namespace App\Http\Controllers\Api\V1\Admin\Reports; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Services\Admin\AdminReportJobService; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Services\Admin\AdminReportJobService; +use App\Http\Requests\Admin\ReportJobStoreRequest; /** POST /api/v1/admin/report-jobs */ final class ReportJobStoreController extends Controller { - public function __invoke(Request $request, AdminReportJobService $service): JsonResponse + public function __invoke(ReportJobStoreRequest $request, AdminReportJobService $service): JsonResponse { /** @var AdminUser $admin */ $admin = $request->lotteryAdmin(); - $data = validator($request->all(), [ - 'report_type' => ['required', 'string', 'max:64'], - 'export_format' => ['sometimes', 'string', 'in:csv,xlsx'], - 'filter_json' => ['nullable', 'array'], - ])->validate(); + $data = $request->validated(); $job = $service->enqueue( $admin, diff --git a/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolIndexController.php b/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolIndexController.php index 4f71647..edd1980 100644 --- a/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolIndexController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Risk; -use App\Http\Controllers\Controller; use App\Models\Draw; use App\Models\RiskPool; -use App\Support\AdminApiList; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** * GET /api/v1/admin/draws/{draw}/risk-pools — 按期号分页查询赔付池事实(售罄筛选、排序)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolLockLogIndexController.php b/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolLockLogIndexController.php index e5c2b9c..9fa36d4 100644 --- a/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolLockLogIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolLockLogIndexController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Admin\Risk; -use App\Http\Controllers\Controller; use App\Models\Draw; -use App\Models\RiskPoolLockLog; -use App\Support\AdminApiList; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use App\Models\RiskPoolLockLog; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** * GET /api/v1/admin/draws/{draw}/risk-pool-lock-logs — 风险池占用/释放流水(审计与监控)。 diff --git a/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolShowController.php b/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolShowController.php index a7dbdab..b8ca992 100644 --- a/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Risk/AdminRiskPoolShowController.php @@ -21,7 +21,12 @@ final class AdminRiskPoolShowController extends Controller public function __invoke(Request $request, Draw $draw, string $number_4d): JsonResponse { if (preg_match('/^[0-9]{4}$/', $number_4d) !== 1) { - return ApiResponse::error('normalized_number 须为 4 位数字', ErrorCode::ValidationFailed->value, null, 422); + return ApiResponse::error( + trans('api.validation_failed', [], $request->lotteryLocale()), + ErrorCode::ValidationFailed->value, + null, + 422, + ); } $pool = RiskPool::query() @@ -30,7 +35,12 @@ final class AdminRiskPoolShowController extends Controller ->first(); if ($pool === null) { - return ApiResponse::error('该期尚无此号码的风险池记录', ErrorCode::NotFound->value, null, 404); + return ApiResponse::error( + trans('api.not_found', [], $request->lotteryLocale()), + ErrorCode::NotFound->value, + null, + 404, + ); } $p = AdminApiList::readPaging($request, 20, AdminApiList::MAX_PER_PAGE); diff --git a/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchDetailsController.php b/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchDetailsController.php index 4cdaec7..411768f 100644 --- a/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchDetailsController.php +++ b/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchDetailsController.php @@ -2,12 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin\Settlement; -use App\Http\Controllers\Controller; -use App\Models\SettlementBatch; -use App\Models\TicketSettlementDetail; -use App\Support\AdminApiList; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use App\Models\SettlementBatch; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Models\TicketSettlementDetail; /** * GET /api/v1/admin/settlement-batches/{batch}/details — 该批次下注单结算明细分页。 diff --git a/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchIndexController.php b/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchIndexController.php index 8dfd3c6..5406458 100644 --- a/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchIndexController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\Settlement; -use App\Http\Controllers\Controller; -use App\Models\SettlementBatch; -use App\Support\AdminApiList; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use App\Models\SettlementBatch; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/settlement-batches — 结算批次分页列表。 diff --git a/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchShowController.php b/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchShowController.php index 8112b23..f387fad 100644 --- a/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/Settlement/AdminSettlementBatchShowController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Api\V1\Admin\Settlement; -use App\Http\Controllers\Controller; -use App\Models\SettlementBatch; use App\Support\ApiResponse; +use App\Models\SettlementBatch; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * GET /api/v1/admin/settlement-batches/{batch} — 单批次摘要。 diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminPermissionCatalogController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminPermissionCatalogController.php index 4d34f81..7e15369 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminPermissionCatalogController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminPermissionCatalogController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminRole; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\DB; +use App\Http\Controllers\Controller; /** GET /api/v1/admin/admin-user-permission-catalog */ final class AdminPermissionCatalogController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserDestroyController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserDestroyController.php index 22b230e..ad79ba4 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserDestroyController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserDestroyController.php @@ -2,14 +2,14 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; use App\Models\AdminUser; -use App\Services\AuditLogger; -use App\Support\AdminUserApiPresenter; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Services\AuditLogger; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminUserApiPresenter; /** DELETE /api/v1/admin/admin-users/{admin_user} */ final class AdminUserDestroyController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserIndexController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserIndexController.php index 4c92503..38029dd 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserIndexController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserIndexController.php @@ -2,12 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Support\AdminApiList; -use App\Support\AdminUserApiPresenter; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\AdminApiList; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminUserApiPresenter; /** GET /api/v1/admin/admin-users */ final class AdminUserIndexController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserPermissionSyncController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserPermissionSyncController.php index 129eacc..067cb4d 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserPermissionSyncController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserPermissionSyncController.php @@ -2,27 +2,20 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Support\AdminPermissionBridge; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; -use Illuminate\Validation\Rule; +use App\Http\Controllers\Controller; +use App\Support\AdminPermissionBridge; +use App\Http\Requests\Admin\AdminUserPermissionSyncRequest; /** PUT /api/v1/admin/admin-users/{admin_user}/permissions */ final class AdminUserPermissionSyncController extends Controller { - public function __invoke(Request $request, AdminUser $admin_user): JsonResponse + public function __invoke(AdminUserPermissionSyncRequest $request, AdminUser $admin_user): JsonResponse { - /** @var array{permission_slugs:list} $data */ - $data = validator($request->all(), [ - 'permission_slugs' => ['required', 'array'], - 'permission_slugs.*' => ['string', 'max:128', 'distinct', Rule::in(AdminPermissionBridge::allLegacySlugs())], - ])->validate(); - - $slugs = array_values(array_unique($data['permission_slugs'])); + $slugs = array_values(array_unique($request->validated('permissions'))); $siteId = AdminUser::defaultAdminSiteId(); $codes = []; diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserRoleSyncController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserRoleSyncController.php index fcf2c65..bf36f7e 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserRoleSyncController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserRoleSyncController.php @@ -2,25 +2,18 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminUser; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; -use Illuminate\Validation\Rule; +use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\AdminUserRoleSyncRequest; /** PUT /api/v1/admin/admin-users/{admin_user}/roles */ final class AdminUserRoleSyncController extends Controller { - public function __invoke(Request $request, AdminUser $admin_user): JsonResponse + public function __invoke(AdminUserRoleSyncRequest $request, AdminUser $admin_user): JsonResponse { - /** @var array{role_slugs:list} $data */ - $data = validator($request->all(), [ - 'role_slugs' => ['required', 'array'], - 'role_slugs.*' => ['string', 'max:64', 'distinct', Rule::exists('admin_roles', 'slug')], - ])->validate(); - - $slugs = array_values(array_unique($data['role_slugs'])); + $slugs = array_values(array_unique($request->validated('role_slugs'))); $admin_user->syncRoleSlugsForDefaultSite($slugs); $admin_user->load('roles'); diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserShowController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserShowController.php index 3fd1949..521af32 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserShowController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserShowController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Support\AdminUserApiPresenter; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Support\AdminUserApiPresenter; /** GET /api/v1/admin/admin-users/{admin_user} */ final class AdminUserShowController extends Controller diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserStoreController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserStoreController.php index dd4a185..fb1a0b8 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserStoreController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserStoreController.php @@ -2,55 +2,40 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Services\AuditLogger; -use App\Support\AdminUserApiPresenter; use App\Support\ApiResponse; +use App\Services\AuditLogger; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Str; +use App\Http\Controllers\Controller; +use App\Support\AdminUserApiPresenter; +use App\Http\Requests\Admin\AdminUserStoreRequest; -/** POST /api/v1/admin/admin-users */ +/** + * 管理员用户创建。 + * + * POST /api/v1/admin/admin-users + */ final class AdminUserStoreController extends Controller { - public function __invoke(Request $request): JsonResponse + public function __invoke(AdminUserStoreRequest $request): JsonResponse { /** @var AdminUser $actor */ $actor = $request->lotteryAdmin(); - $payload = $request->all(); - if (isset($payload['username']) && is_string($payload['username'])) { - $payload['username'] = Str::lower(trim($payload['username'])); - } - if (array_key_exists('email', $payload) && $payload['email'] === '') { - $payload['email'] = null; - } - - $data = validator($payload, [ - 'username' => ['required', 'string', 'min:2', 'max:64', 'regex:/^[a-zA-Z0-9._-]+$/u', 'unique:admin_users,username'], - 'nickname' => ['required', 'string', 'max:128'], - 'email' => ['nullable', 'string', 'email', 'max:255'], - 'password' => ['required', 'string', 'min:8', 'max:256'], - 'status' => ['sometimes', 'integer', 'in:0,1'], - 'role_slugs' => ['required', 'array', 'min:1'], - 'role_slugs.*' => ['string', 'max:64', 'distinct', 'exists:admin_roles,slug'], - ])->validate(); - - $email = is_string($data['email'] ?? null) && trim($data['email']) !== '' - ? trim($data['email']) + $email = is_string($request->validated('email')) + ? trim($request->validated('email')) : null; - $roleSlugs = array_values(array_unique($data['role_slugs'])); + $roleSlugs = array_values(array_unique($request->validated('role_slugs'))); - $user = DB::transaction(function () use ($data, $email, $roleSlugs): AdminUser { + $user = DB::transaction(function () use ($request, $email, $roleSlugs): AdminUser { $created = AdminUser::query()->create([ - 'username' => $data['username'], - 'name' => $data['nickname'], + 'username' => $request->validated('username'), + 'name' => $request->validated('nickname'), 'email' => $email, - 'password' => $data['password'], - 'status' => array_key_exists('status', $data) ? (int) $data['status'] : 0, + 'password' => $request->validated('password'), + 'status' => $request->validated('status', 0), ]); $created->syncRoleSlugsForDefaultSite($roleSlugs); diff --git a/app/Http/Controllers/Api/V1/Admin/User/AdminUserUpdateController.php b/app/Http/Controllers/Api/V1/Admin/User/AdminUserUpdateController.php index 4924f57..387dd30 100644 --- a/app/Http/Controllers/Api/V1/Admin/User/AdminUserUpdateController.php +++ b/app/Http/Controllers/Api/V1/Admin/User/AdminUserUpdateController.php @@ -2,19 +2,18 @@ namespace App\Http\Controllers\Api\V1\Admin\User; -use App\Http\Controllers\Controller; use App\Models\AdminUser; -use App\Services\AuditLogger; -use App\Support\AdminUserApiPresenter; use App\Support\ApiResponse; +use App\Services\AuditLogger; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; -use Illuminate\Validation\Rule; +use App\Http\Controllers\Controller; +use App\Support\AdminUserApiPresenter; +use App\Http\Requests\Admin\AdminUserUpdateRequest; /** PUT /api/v1/admin/admin-users/{admin_user} */ final class AdminUserUpdateController extends Controller { - public function __invoke(Request $request, AdminUser $admin_user): JsonResponse + public function __invoke(AdminUserUpdateRequest $request, AdminUser $admin_user): JsonResponse { /** @var AdminUser $actor */ $actor = $request->lotteryAdmin(); @@ -22,18 +21,7 @@ final class AdminUserUpdateController extends Controller $admin_user->load('roles'); $before = AdminUserApiPresenter::listItem($admin_user); - $payload = $request->all(); - if (array_key_exists('email', $payload) && $payload['email'] === '') { - $payload['email'] = null; - } - - /** @var array{nickname?:string,email?:?string,password?:?string,status?:int} $data */ - $data = validator($payload, [ - 'nickname' => ['sometimes', 'string', 'max:128'], - 'email' => ['sometimes', 'nullable', 'string', 'email', 'max:255', Rule::unique('admin_users', 'email')->ignore($admin_user->id)], - 'password' => ['sometimes', 'nullable', 'string', 'min:8', 'max:256'], - 'status' => ['sometimes', 'integer', Rule::in([0, 1])], - ])->validate(); + $data = $request->validated(); $updates = []; if (array_key_exists('nickname', $data)) { diff --git a/app/Http/Controllers/Api/V1/Admin/Wallet/TransferOrderListController.php b/app/Http/Controllers/Api/V1/Admin/Wallet/TransferOrderListController.php index 904f17c..f9672e2 100644 --- a/app/Http/Controllers/Api/V1/Admin/Wallet/TransferOrderListController.php +++ b/app/Http/Controllers/Api/V1/Admin/Wallet/TransferOrderListController.php @@ -2,11 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin\Wallet; -use App\Http\Controllers\Controller; -use App\Models\TransferOrder; use App\Support\ApiResponse; +use App\Models\TransferOrder; +use App\Support\PaginationTrait; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\TransferOrderListRequest; /** * 后台:转账单列表(主站 ↔ 彩票 {@see transfer_orders})。 @@ -25,26 +26,16 @@ use Illuminate\Http\Request; */ final class TransferOrderListController extends Controller { + use PaginationTrait; + private const ALLOWED_STATUS = ['processing', 'success', 'failed', 'pending_reconcile']; - public function __invoke(Request $request): JsonResponse + public function __invoke(TransferOrderListRequest $request): JsonResponse { - $validated = validator($request->query(), [ - 'page' => ['sometimes', 'integer', 'min:1'], - 'per_page' => ['sometimes', 'integer', 'min:1', 'max:100'], - 'size' => ['sometimes', 'integer', 'min:1', 'max:100'], - 'player_id' => ['sometimes', 'nullable', 'integer', 'min:1'], - 'player_account' => ['sometimes', 'nullable', 'string', 'max:128'], - 'transfer_no' => ['sometimes', 'nullable', 'string', 'max:96'], - 'external_ref_no' => ['sometimes', 'nullable', 'string', 'max:96'], - 'created_from' => ['sometimes', 'nullable', 'date_format:Y-m-d'], - 'created_to' => ['sometimes', 'nullable', 'date_format:Y-m-d'], - 'status' => ['sometimes', 'nullable', 'string', 'max:256'], - ])->validate(); + $validated = $request->validated(); - $perPage = (int) ($validated['per_page'] ?? $validated['size'] ?? 20); - $perPage = min(100, max(1, $perPage)); - $page = max(1, (int) ($validated['page'] ?? 1)); + $perPage = $this->perPage($request, 'per_page', 20, 100); + $page = $this->page($request); $query = TransferOrder::query() ->with(['player:id,site_code,site_player_id,username,nickname']) diff --git a/app/Http/Controllers/Api/V1/Admin/Wallet/WalletTransactionListController.php b/app/Http/Controllers/Api/V1/Admin/Wallet/WalletTransactionListController.php index 7e57568..00977b4 100644 --- a/app/Http/Controllers/Api/V1/Admin/Wallet/WalletTransactionListController.php +++ b/app/Http/Controllers/Api/V1/Admin/Wallet/WalletTransactionListController.php @@ -2,11 +2,12 @@ namespace App\Http\Controllers\Api\V1\Admin\Wallet; -use App\Http\Controllers\Controller; use App\Models\WalletTxn; use App\Support\ApiResponse; +use App\Support\PaginationTrait; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Http\Requests\Admin\WalletTransactionListRequest; /** * 后台:彩票钱包流水列表 {@see wallet_txns}。 @@ -25,27 +26,16 @@ use Illuminate\Http\Request; */ final class WalletTransactionListController extends Controller { + use PaginationTrait; + private const ALLOWED_STATUS = ['posted', 'pending_reconcile']; - public function __invoke(Request $request): JsonResponse + public function __invoke(WalletTransactionListRequest $request): JsonResponse { - $validated = validator($request->query(), [ - 'page' => ['sometimes', 'integer', 'min:1'], - 'per_page' => ['sometimes', 'integer', 'min:1', 'max:100'], - 'size' => ['sometimes', 'integer', 'min:1', 'max:100'], - 'player_id' => ['sometimes', 'nullable', 'integer', 'min:1'], - 'player_account' => ['sometimes', 'nullable', 'string', 'max:128'], - 'txn_no' => ['sometimes', 'nullable', 'string', 'max:96'], - 'external_ref_no' => ['sometimes', 'nullable', 'string', 'max:96'], - 'created_from' => ['sometimes', 'nullable', 'date_format:Y-m-d'], - 'created_to' => ['sometimes', 'nullable', 'date_format:Y-m-d'], - 'biz_type' => ['sometimes', 'nullable', 'string', 'max:64'], - 'status' => ['sometimes', 'nullable', 'string', 'max:128'], - ])->validate(); + $validated = $request->validated(); - $perPage = (int) ($validated['per_page'] ?? $validated['size'] ?? 20); - $perPage = min(100, max(1, $perPage)); - $page = max(1, (int) ($validated['page'] ?? 1)); + $perPage = $this->perPage($request, 'per_page', 20, 100); + $page = $this->page($request); $query = WalletTxn::query() ->with(['player:id,site_code,site_player_id,username,nickname']) diff --git a/app/Http/Controllers/Api/V1/Draw/DrawCurrentController.php b/app/Http/Controllers/Api/V1/Draw/DrawCurrentController.php index 8f81074..b988e4c 100644 --- a/app/Http/Controllers/Api/V1/Draw/DrawCurrentController.php +++ b/app/Http/Controllers/Api/V1/Draw/DrawCurrentController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api\V1\Draw; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Services\Draw\DrawHallSnapshotBuilder; -use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; /** * 下注大厅:`GET /api/v1/draw/current`。 */ -class DrawCurrentController extends Controller +final class DrawCurrentController extends Controller { public function __construct( private readonly DrawHallSnapshotBuilder $snapshot, diff --git a/app/Http/Controllers/Api/V1/Draw/DrawResultShowController.php b/app/Http/Controllers/Api/V1/Draw/DrawResultShowController.php index c7aa058..7712e96 100644 --- a/app/Http/Controllers/Api/V1/Draw/DrawResultShowController.php +++ b/app/Http/Controllers/Api/V1/Draw/DrawResultShowController.php @@ -2,18 +2,18 @@ namespace App\Http\Controllers\Api\V1\Draw; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; use App\Models\Draw; -use App\Services\Draw\DrawResultViewService; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Draw\DrawResultViewService; /** * `GET /api/v1/draw/results/{draw_no}` — 单期详情(便于玩家端[< >]切换)。 */ -class DrawResultShowController extends Controller +final class DrawResultShowController extends Controller { public function __construct( private readonly DrawResultViewService $viewer, diff --git a/app/Http/Controllers/Api/V1/Draw/DrawResultsIndexController.php b/app/Http/Controllers/Api/V1/Draw/DrawResultsIndexController.php index 261abd4..dcf7c07 100644 --- a/app/Http/Controllers/Api/V1/Draw/DrawResultsIndexController.php +++ b/app/Http/Controllers/Api/V1/Draw/DrawResultsIndexController.php @@ -2,29 +2,32 @@ namespace App\Http\Controllers\Api\V1\Draw; +use App\Models\Draw; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use App\Models\DrawResultBatch; +use App\Support\PaginationTrait; +use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use App\Lottery\DrawResultBatchStatus; -use App\Models\Draw; -use App\Models\DrawResultBatch; use App\Services\Draw\DrawResultViewService; -use App\Support\ApiResponse; use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; /** * `GET /api/v1/draw/results` — 已发布开奖往期(公开;对齐 PRD `/api/v1/results`)。 */ -class DrawResultsIndexController extends Controller +final class DrawResultsIndexController extends Controller { + use PaginationTrait; + public function __construct( private readonly DrawResultViewService $viewer, ) {} public function __invoke(Request $request): JsonResponse { - $perPage = max(1, min(50, (int) $request->query('size', $request->query('per_page', 15)))); - $page = max(1, (int) $request->query('page', 1)); + $perPage = $this->perPage($request, 'size', 15, 50); + $page = $this->page($request); /** @var string|null $bizDate query `business_date` 或旧的 `date` */ $bizDate = $request->query('business_date') ?? $request->query('date'); diff --git a/app/Http/Controllers/Api/V1/HealthController.php b/app/Http/Controllers/Api/V1/HealthController.php index 33e4b01..d7d62e1 100644 --- a/app/Http/Controllers/Api/V1/HealthController.php +++ b/app/Http/Controllers/Api/V1/HealthController.php @@ -2,11 +2,11 @@ namespace App\Http\Controllers\Api\V1; -use App\Http\Controllers\Controller; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; -class HealthController extends Controller +final class HealthController extends Controller { /** * 健康检查(Next / 网关探活)。路径:GET /api/v1/health diff --git a/app/Http/Controllers/Api/V1/Jackpot/JackpotSummaryController.php b/app/Http/Controllers/Api/V1/Jackpot/JackpotSummaryController.php index c995642..8040daf 100644 --- a/app/Http/Controllers/Api/V1/Jackpot/JackpotSummaryController.php +++ b/app/Http/Controllers/Api/V1/Jackpot/JackpotSummaryController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api\V1\Jackpot; -use App\Http\Controllers\Controller; use App\Models\JackpotPool; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * `GET /api/v1/jackpot/summary` — 当前奖池水位(公开;玩家端开奖区展示)。 */ -class JackpotSummaryController extends Controller +final class JackpotSummaryController extends Controller { public function __invoke(Request $request): JsonResponse { diff --git a/app/Http/Controllers/Api/V1/Play/PlayEffectiveCatalogController.php b/app/Http/Controllers/Api/V1/Play/PlayEffectiveCatalogController.php index 9398337..fbb6f36 100644 --- a/app/Http/Controllers/Api/V1/Play/PlayEffectiveCatalogController.php +++ b/app/Http/Controllers/Api/V1/Play/PlayEffectiveCatalogController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Play; -use App\Http\Controllers\Controller; use App\Lottery\ErrorCode; -use App\Services\Config\EffectivePlayCatalogService; use App\Support\ApiResponse; -use Illuminate\Database\Eloquent\ModelNotFoundException; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Config\EffectivePlayCatalogService; +use Illuminate\Database\Eloquent\ModelNotFoundException; /** * GET /api/v1/play/effective — 当前生效的玩法目录 + 赔率 + 封顶(公开,无需登录)。 diff --git a/app/Http/Controllers/Api/V1/Player/MeController.php b/app/Http/Controllers/Api/V1/Player/MeController.php index a50e9f1..ef0d2f7 100644 --- a/app/Http/Controllers/Api/V1/Player/MeController.php +++ b/app/Http/Controllers/Api/V1/Player/MeController.php @@ -2,10 +2,10 @@ namespace App\Http\Controllers\Api\V1\Player; -use App\Http\Controllers\Controller; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * 鉴权自检:返回当前 Token 对应的玩家公开字段(不含密码)。 @@ -15,7 +15,7 @@ use Illuminate\Http\Request; * 补充字段与 PRD「识别玩家」及前端引导一致:`locale` 为当次 API 实际使用的语言(与 `NegotiateLotteryLocale` 一致); * 时间类为 ISO 8601 字符串,便于 H5 展示与排错。 */ -class MeController extends Controller +final class MeController extends Controller { public function __invoke(Request $request): JsonResponse { diff --git a/app/Http/Controllers/Api/V1/Player/PingController.php b/app/Http/Controllers/Api/V1/Player/PingController.php index b7d3fb6..f0e28b0 100644 --- a/app/Http/Controllers/Api/V1/Player/PingController.php +++ b/app/Http/Controllers/Api/V1/Player/PingController.php @@ -2,15 +2,15 @@ namespace App\Http\Controllers\Api\V1\Player; -use App\Http\Controllers\Controller; use App\Support\ApiResponse; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * 无需登录:仅供网关/前端确认「玩家 API 前缀」可达。 * 路由:GET /api/v1/player/ping */ -class PingController extends Controller +final class PingController extends Controller { public function __invoke(): JsonResponse { diff --git a/app/Http/Controllers/Api/V1/Ticket/TicketDrawMyMatchController.php b/app/Http/Controllers/Api/V1/Ticket/TicketDrawMyMatchController.php index 305f6e3..b92d39c 100644 --- a/app/Http/Controllers/Api/V1/Ticket/TicketDrawMyMatchController.php +++ b/app/Http/Controllers/Api/V1/Ticket/TicketDrawMyMatchController.php @@ -2,20 +2,20 @@ namespace App\Http\Controllers\Api\V1\Ticket; -use App\Http\Controllers\Controller; use App\Models\Draw; use App\Models\Player; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Draw\DrawResultViewService; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Models\TicketCombination; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Draw\DrawResultViewService; /** * `GET /api/v1/ticket/draws/{draw_no}/my-match` — 当期本人号码与已发布开奖 23 格的交集(用于开奖页高亮)。 */ -class TicketDrawMyMatchController extends Controller +final class TicketDrawMyMatchController extends Controller { public function __construct( private readonly DrawResultViewService $drawResultView, diff --git a/app/Http/Controllers/Api/V1/Ticket/TicketItemShowController.php b/app/Http/Controllers/Api/V1/Ticket/TicketItemShowController.php index 20c6c18..cfe5abe 100644 --- a/app/Http/Controllers/Api/V1/Ticket/TicketItemShowController.php +++ b/app/Http/Controllers/Api/V1/Ticket/TicketItemShowController.php @@ -2,19 +2,19 @@ namespace App\Http\Controllers\Api\V1\Ticket; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; use App\Models\Player; +use App\Lottery\ErrorCode; use App\Models\TicketItem; -use App\Services\Draw\DrawResultViewService; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Services\Draw\DrawResultViewService; /** * `GET /api/v1/ticket/items/{ticket_no}` — 注单详情(单注项 + 组合 + 结算摘要)。 */ -class TicketItemShowController extends Controller +final class TicketItemShowController extends Controller { public function __construct( private readonly DrawResultViewService $drawResultView, diff --git a/app/Http/Controllers/Api/V1/Ticket/TicketItemsIndexController.php b/app/Http/Controllers/Api/V1/Ticket/TicketItemsIndexController.php index 7a3bb91..0a8d09c 100644 --- a/app/Http/Controllers/Api/V1/Ticket/TicketItemsIndexController.php +++ b/app/Http/Controllers/Api/V1/Ticket/TicketItemsIndexController.php @@ -2,25 +2,28 @@ namespace App\Http\Controllers\Api\V1\Ticket; -use App\Http\Controllers\Controller; use App\Models\Player; use App\Models\TicketItem; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\PaginationTrait; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * `GET /api/v1/ticket/items` — 我的注单(注项列表,支持 `draw_no` 筛选)。 */ -class TicketItemsIndexController extends Controller +final class TicketItemsIndexController extends Controller { + use PaginationTrait; + public function __invoke(Request $request): JsonResponse { /** @var Player $player */ $player = $request->attributes->get('lottery_player'); - $perPage = max(1, min(50, (int) $request->query('per_page', 20))); - $page = max(1, (int) $request->query('page', 1)); + $perPage = $this->perPage($request, 'per_page', 20, 50); + $page = $this->page($request); $drawNo = $request->query('draw_no'); $query = TicketItem::query() diff --git a/app/Http/Controllers/Api/V1/Ticket/TicketPlaceController.php b/app/Http/Controllers/Api/V1/Ticket/TicketPlaceController.php index 267af70..fb73a15 100644 --- a/app/Http/Controllers/Api/V1/Ticket/TicketPlaceController.php +++ b/app/Http/Controllers/Api/V1/Ticket/TicketPlaceController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Ticket; -use App\Exceptions\TicketOperationException; -use App\Http\Controllers\Controller; -use App\Http\Requests\Ticket\TicketPlaceRequest; -use App\Services\Ticket\TicketPlacementService; use App\Support\ApiResponse; use App\Support\LotteryMessage; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Exceptions\TicketOperationException; +use App\Services\Ticket\TicketPlacementService; +use App\Http\Requests\Ticket\TicketPlaceRequest; final class TicketPlaceController extends Controller { diff --git a/app/Http/Controllers/Api/V1/Ticket/TicketPreviewController.php b/app/Http/Controllers/Api/V1/Ticket/TicketPreviewController.php index ed89cc1..7b022b6 100644 --- a/app/Http/Controllers/Api/V1/Ticket/TicketPreviewController.php +++ b/app/Http/Controllers/Api/V1/Ticket/TicketPreviewController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\Api\V1\Ticket; -use App\Exceptions\TicketOperationException; -use App\Http\Controllers\Controller; -use App\Http\Requests\Ticket\TicketPreviewRequest; -use App\Services\Ticket\TicketPreviewService; use App\Support\ApiResponse; use App\Support\LotteryMessage; use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; +use App\Exceptions\TicketOperationException; +use App\Services\Ticket\TicketPreviewService; +use App\Http\Requests\Ticket\TicketPreviewRequest; final class TicketPreviewController extends Controller { diff --git a/app/Http/Controllers/Api/V1/Wallet/WalletBalanceController.php b/app/Http/Controllers/Api/V1/Wallet/WalletBalanceController.php index 77ad56c..c476ae1 100644 --- a/app/Http/Controllers/Api/V1/Wallet/WalletBalanceController.php +++ b/app/Http/Controllers/Api/V1/Wallet/WalletBalanceController.php @@ -2,13 +2,14 @@ namespace App\Http\Controllers\Api\V1\Wallet; -use App\Http\Controllers\Controller; -use App\Lottery\ErrorCode; use App\Models\Player; +use App\Lottery\ErrorCode; use App\Models\PlayerWallet; use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Support\CurrencyResolver; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * 【玩家】查询彩票侧钱包余额。 @@ -22,7 +23,7 @@ use Illuminate\Http\Request; * - `available_balance`:`balance - frozen_balance`,表示当前可用于下注的整数最小货币单位(不为负) * - `main_balance`:主站钱包余额占位,接入主站 API 后再返回实数;当前固定 `null` */ -class WalletBalanceController extends Controller +final class WalletBalanceController extends Controller { private const WALLET_TYPE_LOTTERY = 'lottery'; @@ -68,16 +69,9 @@ class WalletBalanceController extends Controller */ private function resolveCurrencyCode(Request $request, Player $player): string|JsonResponse { - $raw = $request->query('currency'); - if (is_string($raw) && $raw !== '') { - $code = strtoupper(substr(trim($raw), 0, 16)); - } else { - $fallback = $player->default_currency ?? config('lottery.default_currency', 'NPR'); - $code = strtoupper(substr(trim((string) $fallback), 0, 16)); - } + $code = CurrencyResolver::resolve($request, $player, 'currency'); - // 币种码:字母数字,长度 1–16,与 migrations 字段一致 - if (! preg_match('/^[A-Z0-9]{1,16}$/', $code)) { + if (! CurrencyResolver::isValid($code)) { return ApiResponse::error( __('wallet.invalid_currency'), ErrorCode::WalletInvalidCurrency->value, diff --git a/app/Http/Controllers/Api/V1/Wallet/WalletLogsController.php b/app/Http/Controllers/Api/V1/Wallet/WalletLogsController.php index 72a903e..e535414 100644 --- a/app/Http/Controllers/Api/V1/Wallet/WalletLogsController.php +++ b/app/Http/Controllers/Api/V1/Wallet/WalletLogsController.php @@ -2,21 +2,24 @@ namespace App\Http\Controllers\Api\V1\Wallet; -use App\Http\Controllers\Controller; -use App\Models\TransferOrder; use App\Models\WalletTxn; -use App\Support\ApiResponse; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; use Illuminate\Support\Str; +use App\Support\ApiResponse; +use Illuminate\Http\Request; +use App\Models\TransferOrder; +use App\Support\PaginationTrait; +use Illuminate\Http\JsonResponse; +use App\Http\Controllers\Controller; /** * PRD §10.1.1:`GET /api/v1/wallet/logs` — 钱包流水。 * * Query:`page`、`size`(每页条数,默认 20)、`type`(逗号分隔:transfer_in,transfer_out,bet,prize,refund) */ -class WalletLogsController extends Controller +final class WalletLogsController extends Controller { + use PaginationTrait; + /** PRD 对外类型 → 本地 biz_type */ private const TYPE_TO_BIZ = [ 'transfer_in' => ['transfer_in'], @@ -31,8 +34,8 @@ class WalletLogsController extends Controller $player = $request->lotteryPlayer(); abort_if($player === null, 500, 'lottery_player missing'); - $perPage = min(100, max(1, (int) $request->query('size', $request->query('per_page', 20)))); - $page = max(1, (int) $request->query('page', 1)); + $perPage = $this->perPage($request, 'size', 20, 100); + $page = $this->page($request); $pendingPayload = $this->pendingReconcilePayload((int) $player->id); diff --git a/app/Http/Controllers/Api/V1/Wallet/WalletTransferInController.php b/app/Http/Controllers/Api/V1/Wallet/WalletTransferInController.php index 0068a1d..e896f45 100644 --- a/app/Http/Controllers/Api/V1/Wallet/WalletTransferInController.php +++ b/app/Http/Controllers/Api/V1/Wallet/WalletTransferInController.php @@ -2,23 +2,23 @@ namespace App\Http\Controllers\Api\V1\Wallet; -use App\Exceptions\WalletOperationException; -use App\Http\Controllers\Controller; -use App\Http\Requests\Wallet\WalletTransferRequest; -use App\Lottery\ErrorCode; use App\Models\Player; -use App\Services\Wallet\LotteryTransferService; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; use App\Support\LotteryMessage; +use App\Support\CurrencyResolver; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Exceptions\WalletOperationException; +use App\Services\Wallet\LotteryTransferService; +use App\Http\Requests\Wallet\WalletTransferRequest; /** * 转入:主站扣款 → 彩票钱包加款。 * * `POST /api/v1/wallet/transfer-in` ,body JSON:`amount`(最小货币单位整数), `idempotent_key`, `currency`(可选) */ -class WalletTransferInController extends Controller +final class WalletTransferInController extends Controller { public function __construct( private readonly LotteryTransferService $transferService, @@ -53,17 +53,11 @@ class WalletTransferInController extends Controller return ApiResponse::success($data); } - private function resolveCurrencyCode(Request $request, Player $player): string|JsonResponse + private function resolveCurrencyCode(WalletTransferRequest $request, Player $player): string|JsonResponse { - $raw = $request->input('currency'); - if (is_string($raw) && $raw !== '') { - $code = strtoupper(substr(trim($raw), 0, 16)); - } else { - $fallback = $player->default_currency ?? config('lottery.default_currency', 'NPR'); - $code = strtoupper(substr(trim((string) $fallback), 0, 16)); - } + $code = CurrencyResolver::resolve($request, $player, 'currency'); - if (! preg_match('/^[A-Z0-9]{1,16}$/', $code)) { + if (! CurrencyResolver::isValid($code)) { return ApiResponse::error( __('wallet.invalid_currency'), ErrorCode::WalletInvalidCurrency->value, diff --git a/app/Http/Controllers/Api/V1/Wallet/WalletTransferOutController.php b/app/Http/Controllers/Api/V1/Wallet/WalletTransferOutController.php index 00798ec..07c3ee1 100644 --- a/app/Http/Controllers/Api/V1/Wallet/WalletTransferOutController.php +++ b/app/Http/Controllers/Api/V1/Wallet/WalletTransferOutController.php @@ -2,23 +2,23 @@ namespace App\Http\Controllers\Api\V1\Wallet; -use App\Exceptions\WalletOperationException; -use App\Http\Controllers\Controller; -use App\Http\Requests\Wallet\WalletTransferRequest; -use App\Lottery\ErrorCode; use App\Models\Player; -use App\Services\Wallet\LotteryTransferService; +use App\Lottery\ErrorCode; use App\Support\ApiResponse; use App\Support\LotteryMessage; +use App\Support\CurrencyResolver; use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use App\Exceptions\WalletOperationException; +use App\Services\Wallet\LotteryTransferService; +use App\Http\Requests\Wallet\WalletTransferRequest; /** * 转出:彩票钱包扣款 → 主站加款;主站失败则冲正彩票余额。 * * `POST /api/v1/wallet/transfer-out` */ -class WalletTransferOutController extends Controller +final class WalletTransferOutController extends Controller { public function __construct( private readonly LotteryTransferService $transferService, @@ -53,17 +53,11 @@ class WalletTransferOutController extends Controller return ApiResponse::success($data); } - private function resolveCurrencyCode(Request $request, Player $player): string|JsonResponse + private function resolveCurrencyCode(WalletTransferRequest $request, Player $player): string|JsonResponse { - $raw = $request->input('currency'); - if (is_string($raw) && $raw !== '') { - $code = strtoupper(substr(trim($raw), 0, 16)); - } else { - $fallback = $player->default_currency ?? config('lottery.default_currency', 'NPR'); - $code = strtoupper(substr(trim((string) $fallback), 0, 16)); - } + $code = CurrencyResolver::resolve($request, $player, 'currency'); - if (! preg_match('/^[A-Z0-9]{1,16}$/', $code)) { + if (! CurrencyResolver::isValid($code)) { return ApiResponse::error( __('wallet.invalid_currency'), ErrorCode::WalletInvalidCurrency->value, diff --git a/app/Http/Middleware/EnsureAdminApi.php b/app/Http/Middleware/EnsureAdminApi.php index 71e0621..1555fe8 100644 --- a/app/Http/Middleware/EnsureAdminApi.php +++ b/app/Http/Middleware/EnsureAdminApi.php @@ -2,10 +2,10 @@ namespace App\Http\Middleware; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; -use App\Support\ApiResponse; use Closure; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; +use App\Support\ApiResponse; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; @@ -13,7 +13,7 @@ use Symfony\Component\HttpFoundation\Response; * 后台 API:`auth:sanctum` 之后执行,校验为 {@link AdminUser} 且未禁用; * 上下文可通过 `$request->lotteryAdmin()` 读取。 */ -class EnsureAdminApi +final class EnsureAdminApi { public function handle(Request $request, Closure $next): Response { diff --git a/app/Http/Middleware/EnsureAdminPermission.php b/app/Http/Middleware/EnsureAdminPermission.php index b5c84f0..edd93ec 100644 --- a/app/Http/Middleware/EnsureAdminPermission.php +++ b/app/Http/Middleware/EnsureAdminPermission.php @@ -2,10 +2,10 @@ namespace App\Http\Middleware; -use App\Lottery\ErrorCode; -use App\Models\AdminUser; -use App\Support\ApiResponse; use Closure; +use App\Models\AdminUser; +use App\Lottery\ErrorCode; +use App\Support\ApiResponse; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; @@ -13,7 +13,7 @@ use Symfony\Component\HttpFoundation\Response; * 后台 RBAC:在 {@see EnsureAdminApi} 之后校验 `prd.*` 等功能权限 slug(与 {@see AdminUser::hasAdminPermission} 一致)。 * 路由参数支持 `slug` 或 `slug1|slug2`(满足其一即可)。 */ -class EnsureAdminPermission +final class EnsureAdminPermission { public function handle(Request $request, Closure $next, string $permissionSlugs): Response { diff --git a/app/Http/Middleware/EnsurePlayerApi.php b/app/Http/Middleware/EnsurePlayerApi.php index 09fdb84..2a09975 100644 --- a/app/Http/Middleware/EnsurePlayerApi.php +++ b/app/Http/Middleware/EnsurePlayerApi.php @@ -2,14 +2,14 @@ namespace App\Http\Middleware; -use App\Exceptions\PlayerAuthenticationException; -use App\Lottery\ErrorCode; -use App\Services\PlayerTokenResolver; -use App\Support\ApiResponse; -use App\Support\LotteryMessage; use Closure; +use App\Lottery\ErrorCode; +use App\Support\ApiResponse; use Illuminate\Http\Request; +use App\Support\LotteryMessage; +use App\Services\PlayerTokenResolver; use Symfony\Component\HttpFoundation\Response; +use App\Exceptions\PlayerAuthenticationException; /** * 【玩家端 API 鉴权中间件】 @@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Response; * * PlayerAuthenticationException 的 getMessage() 仅作开发与日志用语,可与 API msg 语种不一致。 */ -class EnsurePlayerApi +final class EnsurePlayerApi { public function handle(Request $request, Closure $next): Response { diff --git a/app/Http/Middleware/NegotiateLotteryLocale.php b/app/Http/Middleware/NegotiateLotteryLocale.php index 2588243..5740ead 100644 --- a/app/Http/Middleware/NegotiateLotteryLocale.php +++ b/app/Http/Middleware/NegotiateLotteryLocale.php @@ -2,9 +2,9 @@ namespace App\Http\Middleware; -use App\Support\LotteryLocale; use Closure; use Illuminate\Http\Request; +use App\Support\LotteryLocale; use Symfony\Component\HttpFoundation\Response; /** @@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Response; * * 【与异常 JSON】{@see LotteryLocale} 与 middleware 同源,在未命中路由、`lottery_locale` 未写入时仍可从 Header 推导。 */ -class NegotiateLotteryLocale +final class NegotiateLotteryLocale { public function handle(Request $request, Closure $next): Response { diff --git a/app/Http/Requests/Admin/AdminLoginRequest.php b/app/Http/Requests/Admin/AdminLoginRequest.php new file mode 100644 index 0000000..7b87e9e --- /dev/null +++ b/app/Http/Requests/Admin/AdminLoginRequest.php @@ -0,0 +1,44 @@ +> + */ + public function rules(): array + { + return [ + 'account' => ['required', 'string', 'min:2', 'max:64', 'regex:/^[a-zA-Z0-9._-]+$/u'], + 'password' => ['required', 'string', 'max:256'], + 'captcha_key' => ['required', 'string', 'uuid'], + 'captcha_code' => ['required', 'string', 'max:32'], + ]; + } + + /** + * @return array + */ + public function attributes(): array + { + return [ + 'account' => 'account', + 'password' => 'password', + 'captcha_key' => 'captcha_key', + 'captcha_code' => 'captcha_code', + ]; + } +} diff --git a/app/Http/Requests/Admin/AdminPlayerTicketItemsRequest.php b/app/Http/Requests/Admin/AdminPlayerTicketItemsRequest.php new file mode 100644 index 0000000..714d430 --- /dev/null +++ b/app/Http/Requests/Admin/AdminPlayerTicketItemsRequest.php @@ -0,0 +1,30 @@ +> + */ + public function rules(): array + { + return [ + 'page' => ['sometimes', 'integer', 'min:1'], + 'per_page' => ['sometimes', 'integer', 'min:1', 'max:50'], + 'draw_no' => ['sometimes', 'nullable', 'string', 'max:32'], + ]; + } +} diff --git a/app/Http/Requests/Admin/AdminUserPermissionSyncRequest.php b/app/Http/Requests/Admin/AdminUserPermissionSyncRequest.php new file mode 100644 index 0000000..d67b04f --- /dev/null +++ b/app/Http/Requests/Admin/AdminUserPermissionSyncRequest.php @@ -0,0 +1,29 @@ +> + */ + public function rules(): array + { + return [ + 'permissions' => ['required', 'array'], + 'permissions.*' => ['string', 'max:128'], + ]; + } +} diff --git a/app/Http/Requests/Admin/AdminUserRoleSyncRequest.php b/app/Http/Requests/Admin/AdminUserRoleSyncRequest.php new file mode 100644 index 0000000..2485e56 --- /dev/null +++ b/app/Http/Requests/Admin/AdminUserRoleSyncRequest.php @@ -0,0 +1,29 @@ +> + */ + public function rules(): array + { + return [ + 'role_slugs' => ['required', 'array', 'min:1'], + 'role_slugs.*' => ['string', 'max:64', 'distinct', 'exists:admin_roles,slug'], + ]; + } +} diff --git a/app/Http/Requests/Admin/AdminUserStoreRequest.php b/app/Http/Requests/Admin/AdminUserStoreRequest.php new file mode 100644 index 0000000..5cab7c7 --- /dev/null +++ b/app/Http/Requests/Admin/AdminUserStoreRequest.php @@ -0,0 +1,59 @@ +input('username'); + if (is_string($username)) { + $this->merge([ + 'username' => Str::lower(trim($username)), + ]); + } + + if ($this->input('email') === '') { + $this->merge([ + 'email' => null, + ]); + } + } + + /** + * Get the validation rules that apply to the request. + * + * @return array> + */ + public function rules(): array + { + return [ + 'username' => ['required', 'string', 'min:2', 'max:64', 'regex:/^[a-zA-Z0-9._-]+$/u', 'unique:admin_users,username'], + 'nickname' => ['required', 'string', 'max:128'], + 'email' => ['nullable', 'string', 'email', 'max:255'], + 'password' => ['required', 'string', 'min:8', 'max:256'], + 'status' => ['sometimes', 'integer', 'in:0,1'], + 'role_slugs' => ['required', 'array', 'min:1'], + 'role_slugs.*' => ['string', 'max:64', 'distinct', 'exists:admin_roles,slug'], + ]; + } +} diff --git a/app/Http/Requests/Admin/AdminUserUpdateRequest.php b/app/Http/Requests/Admin/AdminUserUpdateRequest.php new file mode 100644 index 0000000..df5f258 --- /dev/null +++ b/app/Http/Requests/Admin/AdminUserUpdateRequest.php @@ -0,0 +1,41 @@ +input('email') === '') { + $this->merge(['email' => null]); + } + } + + /** + * @return array> + */ + public function rules(): array + { + $adminUser = $this->route('admin_user'); + + return [ + 'nickname' => ['sometimes', 'string', 'max:128'], + 'email' => ['sometimes', 'nullable', 'string', 'email', 'max:255', Rule::unique('admin_users', 'email')->ignore($adminUser?->id)], + 'password' => ['sometimes', 'nullable', 'string', 'min:8', 'max:256'], + 'status' => ['sometimes', 'integer', Rule::in([0, 1])], + ]; + } +} diff --git a/app/Http/Requests/Admin/ReconcileJobStoreRequest.php b/app/Http/Requests/Admin/ReconcileJobStoreRequest.php new file mode 100644 index 0000000..0fb1e6d --- /dev/null +++ b/app/Http/Requests/Admin/ReconcileJobStoreRequest.php @@ -0,0 +1,30 @@ +> + */ + public function rules(): array + { + return [ + 'date_from' => ['required', 'date_format:Y-m-d'], + 'date_to' => ['required', 'date_format:Y-m-d', 'after_or_equal:date_from'], + 'player_id' => ['sometimes', 'nullable', 'integer', 'min:1'], + ]; + } +} diff --git a/app/Http/Requests/Admin/ReportJobStoreRequest.php b/app/Http/Requests/Admin/ReportJobStoreRequest.php new file mode 100644 index 0000000..9457735 --- /dev/null +++ b/app/Http/Requests/Admin/ReportJobStoreRequest.php @@ -0,0 +1,31 @@ +> + */ + public function rules(): array + { + return [ + 'report_type' => ['required', 'string', 'max:64'], + 'parameters' => ['sometimes', 'array'], + 'parameters.date_from' => ['sometimes', 'nullable', 'date_format:Y-m-d'], + 'parameters.date_to' => ['sometimes', 'nullable', 'date_format:Y-m-d'], + ]; + } +} diff --git a/app/Http/Requests/Admin/TransferOrderListRequest.php b/app/Http/Requests/Admin/TransferOrderListRequest.php new file mode 100644 index 0000000..8a13926 --- /dev/null +++ b/app/Http/Requests/Admin/TransferOrderListRequest.php @@ -0,0 +1,37 @@ +> + */ + public function rules(): array + { + return [ + 'page' => ['sometimes', 'integer', 'min:1'], + 'per_page' => ['sometimes', 'integer', 'min:1', 'max:100'], + 'size' => ['sometimes', 'integer', 'min:1', 'max:100'], + 'player_id' => ['sometimes', 'nullable', 'integer', 'min:1'], + 'player_account' => ['sometimes', 'nullable', 'string', 'max:128'], + 'transfer_no' => ['sometimes', 'nullable', 'string', 'max:96'], + 'external_ref_no' => ['sometimes', 'nullable', 'string', 'max:96'], + 'created_from' => ['sometimes', 'nullable', 'date_format:Y-m-d'], + 'created_to' => ['sometimes', 'nullable', 'date_format:Y-m-d'], + 'status' => ['sometimes', 'nullable', 'string', 'max:256'], + ]; + } +} diff --git a/app/Http/Requests/Admin/WalletTransactionListRequest.php b/app/Http/Requests/Admin/WalletTransactionListRequest.php new file mode 100644 index 0000000..c75c227 --- /dev/null +++ b/app/Http/Requests/Admin/WalletTransactionListRequest.php @@ -0,0 +1,38 @@ +> + */ + public function rules(): array + { + return [ + 'page' => ['sometimes', 'integer', 'min:1'], + 'per_page' => ['sometimes', 'integer', 'min:1', 'max:100'], + 'size' => ['sometimes', 'integer', 'min:1', 'max:100'], + 'player_id' => ['sometimes', 'nullable', 'integer', 'min:1'], + 'player_account' => ['sometimes', 'nullable', 'string', 'max:128'], + 'txn_no' => ['sometimes', 'nullable', 'string', 'max:96'], + 'external_ref_no' => ['sometimes', 'nullable', 'string', 'max:96'], + 'created_from' => ['sometimes', 'nullable', 'date_format:Y-m-d'], + 'created_to' => ['sometimes', 'nullable', 'date_format:Y-m-d'], + 'biz_type' => ['sometimes', 'nullable', 'string', 'max:64'], + 'status' => ['sometimes', 'nullable', 'string', 'max:128'], + ]; + } +} diff --git a/app/Http/Requests/Ticket/TicketPlaceRequest.php b/app/Http/Requests/Ticket/TicketPlaceRequest.php index 531eb07..e4d9f82 100644 --- a/app/Http/Requests/Ticket/TicketPlaceRequest.php +++ b/app/Http/Requests/Ticket/TicketPlaceRequest.php @@ -2,7 +2,7 @@ namespace App\Http\Requests\Ticket; -class TicketPlaceRequest extends TicketPreviewRequest +final class TicketPlaceRequest extends TicketPreviewRequest { /** * @return array diff --git a/app/Http/Requests/Ticket/TicketPreviewRequest.php b/app/Http/Requests/Ticket/TicketPreviewRequest.php index 128293d..c6cd45a 100644 --- a/app/Http/Requests/Ticket/TicketPreviewRequest.php +++ b/app/Http/Requests/Ticket/TicketPreviewRequest.php @@ -4,7 +4,7 @@ namespace App\Http\Requests\Ticket; use Illuminate\Foundation\Http\FormRequest; -class TicketPreviewRequest extends FormRequest +final class TicketPreviewRequest extends FormRequest { public function authorize(): bool { diff --git a/app/Http/Requests/Wallet/WalletTransferRequest.php b/app/Http/Requests/Wallet/WalletTransferRequest.php index d9bec8c..a8d752d 100644 --- a/app/Http/Requests/Wallet/WalletTransferRequest.php +++ b/app/Http/Requests/Wallet/WalletTransferRequest.php @@ -7,7 +7,7 @@ use Illuminate\Foundation\Http\FormRequest; /** * 转入 / 转出共用请求体:最小货币单位金额、幂等键、可选币种。 */ -class WalletTransferRequest extends FormRequest +final class WalletTransferRequest extends FormRequest { public function authorize(): bool { diff --git a/app/Models/AdminMenu.php b/app/Models/AdminMenu.php index 6de1306..446206e 100644 --- a/app/Models/AdminMenu.php +++ b/app/Models/AdminMenu.php @@ -4,7 +4,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -class AdminMenu extends Model +final class AdminMenu extends Model { protected $table = 'admin_menus'; } diff --git a/app/Models/AdminMenuAction.php b/app/Models/AdminMenuAction.php index 35fbdfe..41a2c44 100644 --- a/app/Models/AdminMenuAction.php +++ b/app/Models/AdminMenuAction.php @@ -5,7 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; -class AdminMenuAction extends Model +final class AdminMenuAction extends Model { protected $table = 'admin_menu_actions'; diff --git a/app/Models/AdminRole.php b/app/Models/AdminRole.php index 941e89a..a1eba66 100644 --- a/app/Models/AdminRole.php +++ b/app/Models/AdminRole.php @@ -2,18 +2,18 @@ namespace App\Models; +use Illuminate\Support\Facades\DB; use App\Support\AdminPermissionBridge; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Support\Facades\DB; -class AdminRole extends Model +final class AdminRole extends Model { protected $table = 'admin_roles'; protected static function booted(): void { - static::creating(function (AdminRole $role): void { + self::creating(function (AdminRole $role): void { if (($role->code ?? '') === '' && is_string($role->slug) && $role->slug !== '') { $role->code = $role->slug; } diff --git a/app/Models/AdminUser.php b/app/Models/AdminUser.php index 7e64c92..5ada0a2 100644 --- a/app/Models/AdminUser.php +++ b/app/Models/AdminUser.php @@ -2,14 +2,14 @@ namespace App\Models; -use App\Support\AdminPermissionBridge; -use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Foundation\Auth\User as Authenticatable; -use Illuminate\Notifications\Notifiable; -use Illuminate\Support\Facades\DB; use Laravel\Sanctum\HasApiTokens; +use Illuminate\Support\Facades\DB; +use App\Support\AdminPermissionBridge; +use Illuminate\Notifications\Notifiable; +use Illuminate\Foundation\Auth\User as Authenticatable; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; -class AdminUser extends Authenticatable +final class AdminUser extends Authenticatable { use HasApiTokens; use Notifiable; diff --git a/app/Models/AuditLog.php b/app/Models/AuditLog.php index ecb0c93..3a45a8a 100644 --- a/app/Models/AuditLog.php +++ b/app/Models/AuditLog.php @@ -6,7 +6,7 @@ use App\Services\AuditLogger; use Illuminate\Database\Eloquent\Model; /** 运维/后台动作留痕表 audit_logs(写入请走 {@see AuditLogger})。 */ -class AuditLog extends Model +final class AuditLog extends Model { public const UPDATED_AT = null; diff --git a/app/Models/Currency.php b/app/Models/Currency.php index c6573be..f30cbb1 100644 --- a/app/Models/Currency.php +++ b/app/Models/Currency.php @@ -5,7 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; /** 币种枚举表 {@see currencies} */ -class Currency extends Model +final class Currency extends Model { protected $fillable = [ 'code', diff --git a/app/Models/Draw.php b/app/Models/Draw.php index 1942288..5559d49 100644 --- a/app/Models/Draw.php +++ b/app/Models/Draw.php @@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; /** 彩票期号 {@see draws} */ -class Draw extends Model +final class Draw extends Model { protected $fillable = [ 'draw_no', diff --git a/app/Models/DrawResultBatch.php b/app/Models/DrawResultBatch.php index b334880..d679d5b 100644 --- a/app/Models/DrawResultBatch.php +++ b/app/Models/DrawResultBatch.php @@ -4,11 +4,11 @@ namespace App\Models; use App\Lottery\DrawResultBatchStatus; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 开奖结果批次(含 RNG 种子摘要、审核人) {@see draw_result_batches} */ -class DrawResultBatch extends Model +final class DrawResultBatch extends Model { public $timestamps = true; diff --git a/app/Models/DrawResultItem.php b/app/Models/DrawResultItem.php index 4f060a1..6bf5f3d 100644 --- a/app/Models/DrawResultItem.php +++ b/app/Models/DrawResultItem.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 单条中奖号码行(与界面文档奖项分区对应) {@see draw_result_items} */ -class DrawResultItem extends Model +final class DrawResultItem extends Model { public const UPDATED_AT = null; diff --git a/app/Models/JackpotContribution.php b/app/Models/JackpotContribution.php index e7d9306..5a46785 100644 --- a/app/Models/JackpotContribution.php +++ b/app/Models/JackpotContribution.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 单注对 Jackpot 的蓄水 {@see jackpot_contributions} */ -class JackpotContribution extends Model +final class JackpotContribution extends Model { protected $fillable = [ 'jackpot_pool_id', diff --git a/app/Models/JackpotPayoutLog.php b/app/Models/JackpotPayoutLog.php index 3c8f59c..bb79b37 100644 --- a/app/Models/JackpotPayoutLog.php +++ b/app/Models/JackpotPayoutLog.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** Jackpot 爆池派发记录 {@see jackpot_payout_logs} */ -class JackpotPayoutLog extends Model +final class JackpotPayoutLog extends Model { public const UPDATED_AT = null; diff --git a/app/Models/JackpotPool.php b/app/Models/JackpotPool.php index d7d804f..68df260 100644 --- a/app/Models/JackpotPool.php +++ b/app/Models/JackpotPool.php @@ -3,11 +3,11 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** Jackpot 奖池配置与当前水位 {@see jackpot_pools} */ -class JackpotPool extends Model +final class JackpotPool extends Model { protected $fillable = [ 'currency_code', diff --git a/app/Models/LotterySetting.php b/app/Models/LotterySetting.php index 4c456d6..62d3787 100644 --- a/app/Models/LotterySetting.php +++ b/app/Models/LotterySetting.php @@ -6,7 +6,7 @@ use App\Services\LotterySettings; use Illuminate\Database\Eloquent\Model; /** 运行期 KV 配置行,对应表 lottery_settings(读业务请优先用 {@see LotterySettings})。 */ -class LotterySetting extends Model +final class LotterySetting extends Model { protected $fillable = [ 'setting_key', diff --git a/app/Models/OddsItem.php b/app/Models/OddsItem.php index dab996e..8a9f18d 100644 --- a/app/Models/OddsItem.php +++ b/app/Models/OddsItem.php @@ -10,7 +10,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * * `odds_value`:整数,**赔率乘数 × 10000**(例如 19500 表示 1.9500 倍)。 */ -class OddsItem extends Model +final class OddsItem extends Model { protected $fillable = [ 'version_id', diff --git a/app/Models/OddsVersion.php b/app/Models/OddsVersion.php index ef2b33a..096a93d 100644 --- a/app/Models/OddsVersion.php +++ b/app/Models/OddsVersion.php @@ -4,11 +4,11 @@ namespace App\Models; use App\Lottery\ConfigVersionStatus; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** {@see odds_versions} */ -class OddsVersion extends Model +final class OddsVersion extends Model { protected $fillable = [ 'version_no', @@ -29,7 +29,7 @@ class OddsVersion extends Model protected static function booted(): void { - static::saving(function (OddsVersion $m): void { + self::saving(function (OddsVersion $m): void { if ($m->status === null || $m->status === '') { $m->status = ConfigVersionStatus::Draft->value; } diff --git a/app/Models/PlayConfigItem.php b/app/Models/PlayConfigItem.php index 98cf91d..0a70617 100644 --- a/app/Models/PlayConfigItem.php +++ b/app/Models/PlayConfigItem.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** {@see play_config_items} — 与 {@see PlayType::play_code} 对齐。 */ -class PlayConfigItem extends Model +final class PlayConfigItem extends Model { protected $fillable = [ 'version_id', diff --git a/app/Models/PlayConfigVersion.php b/app/Models/PlayConfigVersion.php index 03e4bf8..7f27849 100644 --- a/app/Models/PlayConfigVersion.php +++ b/app/Models/PlayConfigVersion.php @@ -4,11 +4,11 @@ namespace App\Models; use App\Lottery\ConfigVersionStatus; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** {@see play_config_versions} */ -class PlayConfigVersion extends Model +final class PlayConfigVersion extends Model { protected $fillable = [ 'version_no', @@ -29,7 +29,7 @@ class PlayConfigVersion extends Model protected static function booted(): void { - static::saving(function (PlayConfigVersion $m): void { + self::saving(function (PlayConfigVersion $m): void { if ($m->status === null || $m->status === '') { $m->status = ConfigVersionStatus::Draft->value; } diff --git a/app/Models/PlayType.php b/app/Models/PlayType.php index de2d8e6..bf23ad1 100644 --- a/app/Models/PlayType.php +++ b/app/Models/PlayType.php @@ -5,7 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; /** 玩法主数据目录 {@see play_types}(与版本化配置 items 通过 play_code 关联)。 */ -class PlayType extends Model +final class PlayType extends Model { protected $fillable = [ 'play_code', diff --git a/app/Models/Player.php b/app/Models/Player.php index 7a29fb0..f686930 100644 --- a/app/Models/Player.php +++ b/app/Models/Player.php @@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; /** * 主站玩家在本地映射账号(表 players),与 SSO JWT 中 site_code + site_player_id 对应。 */ -class Player extends Model +final class Player extends Model { protected $fillable = [ 'site_code', diff --git a/app/Models/PlayerWallet.php b/app/Models/PlayerWallet.php index de73315..d1af972 100644 --- a/app/Models/PlayerWallet.php +++ b/app/Models/PlayerWallet.php @@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * 彩票侧余额(表 player_wallets),按 player + wallet_type + currency 唯一。 */ -class PlayerWallet extends Model +final class PlayerWallet extends Model { protected $fillable = [ 'player_id', diff --git a/app/Models/ReconcileItem.php b/app/Models/ReconcileItem.php index 790439d..292c192 100644 --- a/app/Models/ReconcileItem.php +++ b/app/Models/ReconcileItem.php @@ -5,7 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; -class ReconcileItem extends Model +final class ReconcileItem extends Model { protected $table = 'reconcile_items'; diff --git a/app/Models/ReconcileJob.php b/app/Models/ReconcileJob.php index 8c71ff8..6eb5c22 100644 --- a/app/Models/ReconcileJob.php +++ b/app/Models/ReconcileJob.php @@ -3,10 +3,10 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; -class ReconcileJob extends Model +final class ReconcileJob extends Model { protected $table = 'reconcile_jobs'; diff --git a/app/Models/ReportJob.php b/app/Models/ReportJob.php index 7840917..2314812 100644 --- a/app/Models/ReportJob.php +++ b/app/Models/ReportJob.php @@ -5,7 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; -class ReportJob extends Model +final class ReportJob extends Model { protected $table = 'report_jobs'; diff --git a/app/Models/RiskCapItem.php b/app/Models/RiskCapItem.php index 146a048..7d08885 100644 --- a/app/Models/RiskCapItem.php +++ b/app/Models/RiskCapItem.php @@ -10,7 +10,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * * `cap_amount`:与钱包一致的最小货币单位(整数)。 */ -class RiskCapItem extends Model +final class RiskCapItem extends Model { protected $fillable = [ 'version_id', diff --git a/app/Models/RiskCapVersion.php b/app/Models/RiskCapVersion.php index 7ee339c..632552c 100644 --- a/app/Models/RiskCapVersion.php +++ b/app/Models/RiskCapVersion.php @@ -4,11 +4,11 @@ namespace App\Models; use App\Lottery\ConfigVersionStatus; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** {@see risk_cap_versions} */ -class RiskCapVersion extends Model +final class RiskCapVersion extends Model { protected $fillable = [ 'version_no', @@ -29,7 +29,7 @@ class RiskCapVersion extends Model protected static function booted(): void { - static::saving(function (RiskCapVersion $m): void { + self::saving(function (RiskCapVersion $m): void { if ($m->status === null || $m->status === '') { $m->status = ConfigVersionStatus::Draft->value; } diff --git a/app/Models/RiskPool.php b/app/Models/RiskPool.php index 7af2bd0..f029a23 100644 --- a/app/Models/RiskPool.php +++ b/app/Models/RiskPool.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 赔付池事实表 {@see risk_pools} */ -class RiskPool extends Model +final class RiskPool extends Model { protected $fillable = [ 'draw_id', diff --git a/app/Models/RiskPoolLockLog.php b/app/Models/RiskPoolLockLog.php index 8a02090..18418a7 100644 --- a/app/Models/RiskPoolLockLog.php +++ b/app/Models/RiskPoolLockLog.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 风险池占用日志 {@see risk_pool_lock_logs} */ -class RiskPoolLockLog extends Model +final class RiskPoolLockLog extends Model { public $timestamps = false; diff --git a/app/Models/SettlementBatch.php b/app/Models/SettlementBatch.php index 0d4795c..d381945 100644 --- a/app/Models/SettlementBatch.php +++ b/app/Models/SettlementBatch.php @@ -4,11 +4,11 @@ namespace App\Models; use App\Lottery\SettlementBatchStatus; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 单期单次结算批次 {@see settlement_batches} */ -class SettlementBatch extends Model +final class SettlementBatch extends Model { protected $fillable = [ 'draw_id', diff --git a/app/Models/TicketCombination.php b/app/Models/TicketCombination.php index 29d57b9..999af69 100644 --- a/app/Models/TicketCombination.php +++ b/app/Models/TicketCombination.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 注项展开组合 {@see ticket_combinations} */ -class TicketCombination extends Model +final class TicketCombination extends Model { public $timestamps = false; diff --git a/app/Models/TicketItem.php b/app/Models/TicketItem.php index f145485..19d4541 100644 --- a/app/Models/TicketItem.php +++ b/app/Models/TicketItem.php @@ -3,12 +3,12 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 注项明细 {@see ticket_items} */ -class TicketItem extends Model +final class TicketItem extends Model { protected $fillable = [ 'ticket_no', diff --git a/app/Models/TicketOrder.php b/app/Models/TicketOrder.php index c6bba10..aec358e 100644 --- a/app/Models/TicketOrder.php +++ b/app/Models/TicketOrder.php @@ -3,11 +3,11 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 下注订单头 {@see ticket_orders} */ -class TicketOrder extends Model +final class TicketOrder extends Model { protected $fillable = [ 'order_no', diff --git a/app/Models/TicketSettlementDetail.php b/app/Models/TicketSettlementDetail.php index 5972064..28a8dee 100644 --- a/app/Models/TicketSettlementDetail.php +++ b/app/Models/TicketSettlementDetail.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 注单项结算明细 {@see ticket_settlement_details} */ -class TicketSettlementDetail extends Model +final class TicketSettlementDetail extends Model { protected $fillable = [ 'settlement_batch_id', diff --git a/app/Models/TransferOrder.php b/app/Models/TransferOrder.php index 927d5b3..54afa15 100644 --- a/app/Models/TransferOrder.php +++ b/app/Models/TransferOrder.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 主站 ↔ 彩票划转订单 {@see transfer_orders} */ -class TransferOrder extends Model +final class TransferOrder extends Model { protected $fillable = [ 'transfer_no', diff --git a/app/Models/WalletTxn.php b/app/Models/WalletTxn.php index 1233432..e73d937 100644 --- a/app/Models/WalletTxn.php +++ b/app/Models/WalletTxn.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** 彩票钱包流水 {@see wallet_txns} */ -class WalletTxn extends Model +final class WalletTxn extends Model { protected $fillable = [ 'txn_no', diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 03b5eb1..f02706f 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,17 +2,17 @@ namespace App\Providers; -use App\Models\AdminUser; use App\Models\Player; -use App\Services\Wallet\HttpMainSiteWalletGateway; -use App\Services\Wallet\MainSiteWalletGateway; -use App\Services\Wallet\StubMainSiteWalletGateway; -use Illuminate\Cache\RateLimiting\Limit; +use App\Models\AdminUser; use Illuminate\Http\Request; -use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\ServiceProvider; +use Illuminate\Cache\RateLimiting\Limit; +use Illuminate\Support\Facades\RateLimiter; +use App\Services\Wallet\MainSiteWalletGateway; +use App\Services\Wallet\HttpMainSiteWalletGateway; +use App\Services\Wallet\StubMainSiteWalletGateway; -class AppServiceProvider extends ServiceProvider +final class AppServiceProvider extends ServiceProvider { /** * Register any application services. diff --git a/app/Services/Admin/AdminDashboardSnapshotBuilder.php b/app/Services/Admin/AdminDashboardSnapshotBuilder.php index 3e3c688..bb61fbf 100644 --- a/app/Services/Admin/AdminDashboardSnapshotBuilder.php +++ b/app/Services/Admin/AdminDashboardSnapshotBuilder.php @@ -2,16 +2,16 @@ namespace App\Services\Admin; -use App\Lottery\DrawResultBatchStatus; -use App\Models\AdminUser; +use Carbon\Carbon; use App\Models\Draw; use App\Models\RiskPool; -use App\Models\SettlementBatch; +use App\Models\AdminUser; use App\Models\TicketItem; use App\Models\TicketOrder; use App\Models\TransferOrder; +use App\Models\SettlementBatch; +use App\Lottery\DrawResultBatchStatus; use App\Services\Draw\DrawHallSnapshotBuilder; -use Carbon\Carbon; /** * 后台首页仪表盘:聚合大厅快照、当期财务、期号面板、风控摘要、异常转账计数。 diff --git a/app/Services/Admin/AdminReconcileJobService.php b/app/Services/Admin/AdminReconcileJobService.php index b983bb5..ce607e3 100644 --- a/app/Services/Admin/AdminReconcileJobService.php +++ b/app/Services/Admin/AdminReconcileJobService.php @@ -2,14 +2,14 @@ namespace App\Services\Admin; -use App\Models\AdminUser; -use App\Models\ReconcileItem; -use App\Models\ReconcileJob; -use App\Services\AuditLogger; use Carbon\Carbon; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; +use App\Models\AdminUser; use Illuminate\Support\Str; +use App\Models\ReconcileJob; +use Illuminate\Http\Request; +use App\Models\ReconcileItem; +use App\Services\AuditLogger; +use Illuminate\Support\Facades\DB; /** * 对账任务:落库 `reconcile_jobs` / `reconcile_items`(阶段 7;差异引擎可后续替换)。 diff --git a/app/Services/Admin/AdminReportJobService.php b/app/Services/Admin/AdminReportJobService.php index c5bcf05..b2347ee 100644 --- a/app/Services/Admin/AdminReportJobService.php +++ b/app/Services/Admin/AdminReportJobService.php @@ -4,10 +4,10 @@ namespace App\Services\Admin; use App\Models\AdminUser; use App\Models\ReportJob; -use App\Services\AuditLogger; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; +use Illuminate\Http\Request; +use App\Services\AuditLogger; +use Illuminate\Support\Facades\DB; /** * 报表导出任务:落库 `report_jobs`(阶段 7;异步生成可后续接队列)。 diff --git a/app/Services/AdminCaptchaService.php b/app/Services/AdminCaptchaService.php index 983c6a6..73df7c0 100644 --- a/app/Services/AdminCaptchaService.php +++ b/app/Services/AdminCaptchaService.php @@ -2,13 +2,13 @@ namespace App\Services; -use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; +use Illuminate\Support\Facades\Cache; /** * 后台登录图形验证码:SVG 产出 + Cache 短时保存答案摘要(单行文本,便于前台用 img[src=data:...] 展示)。 */ -class AdminCaptchaService +final class AdminCaptchaService { private const PREFIX = 'admin_captcha:'; diff --git a/app/Services/AuditLogger.php b/app/Services/AuditLogger.php index bbdeb96..5110686 100644 --- a/app/Services/AuditLogger.php +++ b/app/Services/AuditLogger.php @@ -2,9 +2,9 @@ namespace App\Services; -use App\Models\AdminUser; -use App\Models\AuditLog; use App\Models\Player; +use App\Models\AuditLog; +use App\Models\AdminUser; use Illuminate\Http\Request; /** diff --git a/app/Services/Config/EffectivePlayCatalogService.php b/app/Services/Config/EffectivePlayCatalogService.php index 3500a8c..cb44c8b 100644 --- a/app/Services/Config/EffectivePlayCatalogService.php +++ b/app/Services/Config/EffectivePlayCatalogService.php @@ -2,16 +2,16 @@ namespace App\Services\Config; -use App\Lottery\ConfigVersionStatus; use App\Models\Currency; use App\Models\OddsItem; -use App\Models\OddsVersion; -use App\Models\PlayConfigItem; -use App\Models\PlayConfigVersion; use App\Models\PlayType; +use App\Models\OddsVersion; use App\Models\RiskCapItem; +use App\Models\PlayConfigItem; use App\Models\RiskCapVersion; +use App\Models\PlayConfigVersion; use Illuminate\Support\Collection; +use App\Lottery\ConfigVersionStatus; /** * 玩家端:当前生效的玩法目录 + 三套版本快照(只读)。 diff --git a/app/Services/Config/OddsStreamService.php b/app/Services/Config/OddsStreamService.php index 6ae62f4..e93a95a 100644 --- a/app/Services/Config/OddsStreamService.php +++ b/app/Services/Config/OddsStreamService.php @@ -2,17 +2,17 @@ namespace App\Services\Config; -use App\Lottery\ConfigVersionStatus; -use App\Models\AdminUser; use App\Models\Currency; use App\Models\OddsItem; -use App\Models\OddsVersion; use App\Models\PlayType; -use App\Services\AuditLogger; -use App\Support\OddsStandardScopes; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use App\Models\AdminUser; +use App\Models\OddsVersion; use Illuminate\Http\Request; +use App\Services\AuditLogger; use Illuminate\Support\Facades\DB; +use App\Support\OddsStandardScopes; +use App\Lottery\ConfigVersionStatus; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** 后台:赔率版本({@see odds_versions} / {@see odds_items}) */ final class OddsStreamService diff --git a/app/Services/Config/PlayConfigStreamService.php b/app/Services/Config/PlayConfigStreamService.php index aadbcfe..4ae12bd 100644 --- a/app/Services/Config/PlayConfigStreamService.php +++ b/app/Services/Config/PlayConfigStreamService.php @@ -2,15 +2,15 @@ namespace App\Services\Config; -use App\Lottery\ConfigVersionStatus; +use App\Models\PlayType; use App\Models\AdminUser; +use Illuminate\Http\Request; +use App\Services\AuditLogger; use App\Models\PlayConfigItem; use App\Models\PlayConfigVersion; -use App\Models\PlayType; -use App\Services\AuditLogger; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use App\Lottery\ConfigVersionStatus; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** 后台:玩法配置版本({@see play_config_versions} / {@see play_config_items}) */ final class PlayConfigStreamService diff --git a/app/Services/Config/RiskCapStreamService.php b/app/Services/Config/RiskCapStreamService.php index f0f0186..a90bf00 100644 --- a/app/Services/Config/RiskCapStreamService.php +++ b/app/Services/Config/RiskCapStreamService.php @@ -2,14 +2,14 @@ namespace App\Services\Config; -use App\Lottery\ConfigVersionStatus; use App\Models\AdminUser; use App\Models\RiskCapItem; -use App\Models\RiskCapVersion; -use App\Services\AuditLogger; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Http\Request; +use App\Services\AuditLogger; +use App\Models\RiskCapVersion; use Illuminate\Support\Facades\DB; +use App\Lottery\ConfigVersionStatus; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** 后台:风控封顶版本({@see risk_cap_versions} / {@see risk_cap_items}) */ final class RiskCapStreamService diff --git a/app/Services/Draw/DrawHallSnapshotBuilder.php b/app/Services/Draw/DrawHallSnapshotBuilder.php index 40c3a51..1a3af8b 100644 --- a/app/Services/Draw/DrawHallSnapshotBuilder.php +++ b/app/Services/Draw/DrawHallSnapshotBuilder.php @@ -2,12 +2,12 @@ namespace App\Services\Draw; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; -use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Models\DrawResultItem; use Carbon\Carbon; +use App\Models\Draw; +use App\Lottery\DrawStatus; +use App\Models\DrawResultItem; +use App\Models\DrawResultBatch; +use App\Lottery\DrawResultBatchStatus; /** * `GET draw/current` 与大厅 WS 快照共用数据结构。 diff --git a/app/Services/Draw/DrawPlannerService.php b/app/Services/Draw/DrawPlannerService.php index 22dc922..05f9ef2 100644 --- a/app/Services/Draw/DrawPlannerService.php +++ b/app/Services/Draw/DrawPlannerService.php @@ -2,11 +2,11 @@ namespace App\Services\Draw; -use App\Lottery\DrawStatus; -use App\Models\Draw; use Carbon\Carbon; -use Illuminate\Database\QueryException; +use App\Models\Draw; +use App\Lottery\DrawStatus; use Illuminate\Support\Facades\DB; +use Illuminate\Database\QueryException; /** * 按计划生成未来的 `draws` 行(期号、时间表)。 diff --git a/app/Services/Draw/DrawPublishService.php b/app/Services/Draw/DrawPublishService.php index afa022e..bece2c9 100644 --- a/app/Services/Draw/DrawPublishService.php +++ b/app/Services/Draw/DrawPublishService.php @@ -2,12 +2,12 @@ namespace App\Services\Draw; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; -use App\Models\AdminUser; use App\Models\Draw; +use App\Models\AdminUser; +use App\Lottery\DrawStatus; use App\Models\DrawResultBatch; use Illuminate\Support\Facades\DB; +use App\Lottery\DrawResultBatchStatus; /** * 人工审核通过后发布结果;或 RNG 自动生成路径内联调用同一事务字段更新。 diff --git a/app/Services/Draw/DrawResultViewService.php b/app/Services/Draw/DrawResultViewService.php index aa10c46..d5a1f4c 100644 --- a/app/Services/Draw/DrawResultViewService.php +++ b/app/Services/Draw/DrawResultViewService.php @@ -2,13 +2,13 @@ namespace App\Services\Draw; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; use App\Models\Draw; -use App\Models\DrawResultBatch; +use App\Lottery\DrawStatus; use App\Models\DrawResultItem; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use App\Models\DrawResultBatch; use Illuminate\Support\Collection; +use App\Lottery\DrawResultBatchStatus; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** * 将已发布的 {@see DrawResultItem} 聚合成前端/文档约定结构。 diff --git a/app/Services/Draw/DrawRngRunner.php b/app/Services/Draw/DrawRngRunner.php index 234ad72..eef75c7 100644 --- a/app/Services/Draw/DrawRngRunner.php +++ b/app/Services/Draw/DrawRngRunner.php @@ -2,14 +2,14 @@ namespace App\Services\Draw; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawResultSourceType; -use App\Lottery\DrawStatus; -use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Models\DrawResultItem; use Carbon\Carbon; +use App\Models\Draw; +use App\Lottery\DrawStatus; +use App\Models\DrawResultItem; +use App\Models\DrawResultBatch; use Illuminate\Support\Facades\DB; +use App\Lottery\DrawResultSourceType; +use App\Lottery\DrawResultBatchStatus; /** * 按配置执行 RNG,写入 {@see DrawResultBatch} / {@see DrawResultItem}。 diff --git a/app/Services/Draw/DrawTickService.php b/app/Services/Draw/DrawTickService.php index fe27726..efaea8e 100644 --- a/app/Services/Draw/DrawTickService.php +++ b/app/Services/Draw/DrawTickService.php @@ -2,11 +2,11 @@ namespace App\Services\Draw; -use App\Lottery\DrawStatus; +use Carbon\Carbon; use App\Models\Draw; +use App\Lottery\DrawStatus; use App\Services\LotterySettings; use App\Services\Settlement\SettlementOrchestrator; -use Carbon\Carbon; /** * 每分钟调度:期号状态推进 → RNG(若到期号)→ 冷静期结束时进入结算态 → 补齐未来缓冲。 diff --git a/app/Services/Draw/LotteryHallRealtimeBroadcaster.php b/app/Services/Draw/LotteryHallRealtimeBroadcaster.php index 1922ba9..f636fe3 100644 --- a/app/Services/Draw/LotteryHallRealtimeBroadcaster.php +++ b/app/Services/Draw/LotteryHallRealtimeBroadcaster.php @@ -3,8 +3,8 @@ namespace App\Services\Draw; use App\Events\DrawCountdownBroadcast; -use App\Events\DrawResultPublishedBroadcast; use App\Events\DrawStatusChangeBroadcast; +use App\Events\DrawResultPublishedBroadcast; /** * 对齐界面文档 §2.1:`draw.countdown`、`draw.status_change`、`result.published`(频道 `lottery-hall`)。 diff --git a/app/Services/Jackpot/JackpotBurstAllocator.php b/app/Services/Jackpot/JackpotBurstAllocator.php index 76db7c4..063af54 100644 --- a/app/Services/Jackpot/JackpotBurstAllocator.php +++ b/app/Services/Jackpot/JackpotBurstAllocator.php @@ -2,11 +2,11 @@ namespace App\Services\Jackpot; -use App\Lottery\DrawStatus; use App\Models\Draw; -use App\Models\JackpotPayoutLog; -use App\Models\JackpotPool; use App\Models\TicketItem; +use App\Lottery\DrawStatus; +use App\Models\JackpotPool; +use App\Models\JackpotPayoutLog; use Illuminate\Support\Collection; /** diff --git a/app/Services/Jackpot/JackpotContributionService.php b/app/Services/Jackpot/JackpotContributionService.php index 780fac9..d42efae 100644 --- a/app/Services/Jackpot/JackpotContributionService.php +++ b/app/Services/Jackpot/JackpotContributionService.php @@ -3,9 +3,9 @@ namespace App\Services\Jackpot; use App\Models\Draw; -use App\Models\JackpotContribution; -use App\Models\JackpotPool; use App\Models\TicketItem; +use App\Models\JackpotPool; +use App\Models\JackpotContribution; /** * 产品文档 §5.11.1:每笔有效注单按比例蓄水(在下注成功路径调用,非结算)。 diff --git a/app/Services/PlayerTokenResolver.php b/app/Services/PlayerTokenResolver.php index ead3ade..223a8da 100644 --- a/app/Services/PlayerTokenResolver.php +++ b/app/Services/PlayerTokenResolver.php @@ -2,13 +2,13 @@ namespace App\Services; -use App\Exceptions\PlayerAuthenticationException; -use App\Lottery\ErrorCode; -use App\Models\Player; use Firebase\JWT\JWT; use Firebase\JWT\Key; -use Illuminate\Database\QueryException; +use App\Models\Player; +use App\Lottery\ErrorCode; use Illuminate\Http\Request; +use Illuminate\Database\QueryException; +use App\Exceptions\PlayerAuthenticationException; /** * 从请求头解析玩家身份,返回已落库的 {@see Player}。 diff --git a/app/Services/Settlement/Contracts/SettlementPlayMatcher.php b/app/Services/Settlement/Contracts/SettlementPlayMatcher.php index facb1dd..aaec48b 100644 --- a/app/Services/Settlement/Contracts/SettlementPlayMatcher.php +++ b/app/Services/Settlement/Contracts/SettlementPlayMatcher.php @@ -2,10 +2,10 @@ namespace App\Services\Settlement\Contracts; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\PublishedDrawResultBoard; +use App\Models\TicketCombination; use Illuminate\Support\Collection; +use App\Services\Settlement\PublishedDrawResultBoard; interface SettlementPlayMatcher { diff --git a/app/Services/Settlement/Matchers/BigSpreadSettlementMatcher.php b/app/Services/Settlement/Matchers/BigSpreadSettlementMatcher.php index 659f2af..154034b 100644 --- a/app/Services/Settlement/Matchers/BigSpreadSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/BigSpreadSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** * Big / 包号展开类:命中 23 档中**最优档**计奖(产品文档 Big / iBox / mBox / Box)。 diff --git a/app/Services/Settlement/Matchers/FirstPrizeComboSettlementMatcher.php b/app/Services/Settlement/Matchers/FirstPrizeComboSettlementMatcher.php index dd30278..541b62e 100644 --- a/app/Services/Settlement/Matchers/FirstPrizeComboSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/FirstPrizeComboSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** * head / tail / odd / even / digit_big / digit_small:展开组合中若有与**头奖 4D** 完全一致则中奖(赔率档 first)。 diff --git a/app/Services/Settlement/Matchers/NoopSettlementMatcher.php b/app/Services/Settlement/Matchers/NoopSettlementMatcher.php index ea15d91..f4664ea 100644 --- a/app/Services/Settlement/Matchers/NoopSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/NoopSettlementMatcher.php @@ -3,9 +3,9 @@ namespace App\Services\Settlement\Matchers; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; -use App\Services\Settlement\PublishedDrawResultBoard; use Illuminate\Support\Collection; +use App\Services\Settlement\PublishedDrawResultBoard; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** * 阶段 6 首轮未实现的玩法:不派奖(后续补位置类、单双等匹配器)。 diff --git a/app/Services/Settlement/Matchers/Pos2AbcSettlementMatcher.php b/app/Services/Settlement/Matchers/Pos2AbcSettlementMatcher.php index c272a72..f153c50 100644 --- a/app/Services/Settlement/Matchers/Pos2AbcSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/Pos2AbcSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** pos_2abc:后二位命中头/二/三任意一档。 */ final class Pos2AbcSettlementMatcher implements SettlementPlayMatcher diff --git a/app/Services/Settlement/Matchers/Pos2TierSettlementMatcher.php b/app/Services/Settlement/Matchers/Pos2TierSettlementMatcher.php index 0c16a38..581dd29 100644 --- a/app/Services/Settlement/Matchers/Pos2TierSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/Pos2TierSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** pos_2a / pos_2b / pos_2c:后二位命中对应档。 */ final class Pos2TierSettlementMatcher implements SettlementPlayMatcher diff --git a/app/Services/Settlement/Matchers/Pos3AbcSettlementMatcher.php b/app/Services/Settlement/Matchers/Pos3AbcSettlementMatcher.php index 69c5c7f..8cd1a95 100644 --- a/app/Services/Settlement/Matchers/Pos3AbcSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/Pos3AbcSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** pos_3abc:后三位命中头/二/三任意一档;取最优档赔率。 */ final class Pos3AbcSettlementMatcher implements SettlementPlayMatcher diff --git a/app/Services/Settlement/Matchers/Pos3TierSettlementMatcher.php b/app/Services/Settlement/Matchers/Pos3TierSettlementMatcher.php index 0cda6d8..dd7ede7 100644 --- a/app/Services/Settlement/Matchers/Pos3TierSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/Pos3TierSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** pos_3a / pos_3b / pos_3c:后三位命中对应档。头奖命中时 `matched_prize_tier` 为 first(Jackpot 口径)。 */ final class Pos3TierSettlementMatcher implements SettlementPlayMatcher diff --git a/app/Services/Settlement/Matchers/Pos4ExactTierSettlementMatcher.php b/app/Services/Settlement/Matchers/Pos4ExactTierSettlementMatcher.php index a18a750..362c801 100644 --- a/app/Services/Settlement/Matchers/Pos4ExactTierSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/Pos4ExactTierSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** pos_4a / pos_4b / pos_4c:与对应档完整 4D 一致。 */ final class Pos4ExactTierSettlementMatcher implements SettlementPlayMatcher diff --git a/app/Services/Settlement/Matchers/Pos4ListTierSettlementMatcher.php b/app/Services/Settlement/Matchers/Pos4ListTierSettlementMatcher.php index 232ef45..90b0ec6 100644 --- a/app/Services/Settlement/Matchers/Pos4ListTierSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/Pos4ListTierSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** pos_4d(特别奖)/ pos_4e(安慰奖):命中任意一组即中奖。 */ final class Pos4ListTierSettlementMatcher implements SettlementPlayMatcher diff --git a/app/Services/Settlement/Matchers/SmallSpreadSettlementMatcher.php b/app/Services/Settlement/Matchers/SmallSpreadSettlementMatcher.php index c4fd357..9d6cfc9 100644 --- a/app/Services/Settlement/Matchers/SmallSpreadSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/SmallSpreadSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** * Small:仅头 / 二 / 三奖(产品文档 Small)。 diff --git a/app/Services/Settlement/Matchers/StraightLikeSettlementMatcher.php b/app/Services/Settlement/Matchers/StraightLikeSettlementMatcher.php index 058b001..c52f5c5 100644 --- a/app/Services/Settlement/Matchers/StraightLikeSettlementMatcher.php +++ b/app/Services/Settlement/Matchers/StraightLikeSettlementMatcher.php @@ -2,12 +2,12 @@ namespace App\Services\Settlement\Matchers; -use App\Models\TicketCombination; use App\Models\TicketItem; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; +use App\Models\TicketCombination; +use Illuminate\Support\Collection; use App\Services\Settlement\OddsSnapshotReader; use App\Services\Settlement\PublishedDrawResultBoard; -use Illuminate\Support\Collection; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; /** * 直选类:仅与**头奖**号码完全一致中奖(产品文档 Straight / 头奖口径)。 diff --git a/app/Services/Settlement/SettlementMatcherRegistry.php b/app/Services/Settlement/SettlementMatcherRegistry.php index aef31fa..171f7ef 100644 --- a/app/Services/Settlement/SettlementMatcherRegistry.php +++ b/app/Services/Settlement/SettlementMatcherRegistry.php @@ -2,18 +2,18 @@ namespace App\Services\Settlement; -use App\Services\Settlement\Contracts\SettlementPlayMatcher; -use App\Services\Settlement\Matchers\BigSpreadSettlementMatcher; -use App\Services\Settlement\Matchers\FirstPrizeComboSettlementMatcher; use App\Services\Settlement\Matchers\NoopSettlementMatcher; +use App\Services\Settlement\Contracts\SettlementPlayMatcher; use App\Services\Settlement\Matchers\Pos2AbcSettlementMatcher; -use App\Services\Settlement\Matchers\Pos2TierSettlementMatcher; use App\Services\Settlement\Matchers\Pos3AbcSettlementMatcher; +use App\Services\Settlement\Matchers\Pos2TierSettlementMatcher; use App\Services\Settlement\Matchers\Pos3TierSettlementMatcher; -use App\Services\Settlement\Matchers\Pos4ExactTierSettlementMatcher; -use App\Services\Settlement\Matchers\Pos4ListTierSettlementMatcher; +use App\Services\Settlement\Matchers\BigSpreadSettlementMatcher; use App\Services\Settlement\Matchers\SmallSpreadSettlementMatcher; +use App\Services\Settlement\Matchers\Pos4ListTierSettlementMatcher; use App\Services\Settlement\Matchers\StraightLikeSettlementMatcher; +use App\Services\Settlement\Matchers\Pos4ExactTierSettlementMatcher; +use App\Services\Settlement\Matchers\FirstPrizeComboSettlementMatcher; final class SettlementMatcherRegistry { diff --git a/app/Services/Settlement/SettlementOrchestrator.php b/app/Services/Settlement/SettlementOrchestrator.php index 9e44571..82537f0 100644 --- a/app/Services/Settlement/SettlementOrchestrator.php +++ b/app/Services/Settlement/SettlementOrchestrator.php @@ -2,22 +2,22 @@ namespace App\Services\Settlement; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; -use App\Lottery\SettlementBatchStatus; use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Models\DrawResultItem; -use App\Models\JackpotPool; use App\Models\Player; -use App\Models\SettlementBatch; use App\Models\TicketItem; +use App\Lottery\DrawStatus; +use App\Models\JackpotPool; use App\Models\TicketOrder; +use App\Models\DrawResultItem; +use App\Models\DrawResultBatch; +use App\Models\SettlementBatch; +use Illuminate\Support\Facades\DB; +use App\Lottery\DrawResultBatchStatus; +use App\Lottery\SettlementBatchStatus; use App\Models\TicketSettlementDetail; -use App\Services\Jackpot\JackpotBurstAllocator; use App\Services\Ticket\RiskPoolService; use App\Services\Ticket\TicketWalletService; -use Illuminate\Support\Facades\DB; +use App\Services\Jackpot\JackpotBurstAllocator; /** * 阶段 6:对已发布开奖、处于 `settling` 的期号执行结算(匹配 → 回水派彩调整 → Jackpot 爆池分配 → 明细 → 风险池释放 → 入账)。 diff --git a/app/Services/Ticket/NumberNormalizer.php b/app/Services/Ticket/NumberNormalizer.php index c84ae4e..72a9583 100644 --- a/app/Services/Ticket/NumberNormalizer.php +++ b/app/Services/Ticket/NumberNormalizer.php @@ -2,8 +2,8 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; use App\Lottery\ErrorCode; +use App\Exceptions\TicketOperationException; final class NumberNormalizer { diff --git a/app/Services/Ticket/PlayCatalogResolver.php b/app/Services/Ticket/PlayCatalogResolver.php index 1702a1e..807b2e4 100644 --- a/app/Services/Ticket/PlayCatalogResolver.php +++ b/app/Services/Ticket/PlayCatalogResolver.php @@ -2,17 +2,17 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; -use App\Lottery\ConfigVersionStatus; -use App\Lottery\ErrorCode; use App\Models\OddsItem; -use App\Models\OddsVersion; -use App\Models\PlayConfigItem; -use App\Models\PlayConfigVersion; use App\Models\PlayType; +use App\Lottery\ErrorCode; +use App\Models\OddsVersion; use App\Models\RiskCapItem; +use App\Models\PlayConfigItem; use App\Models\RiskCapVersion; +use App\Models\PlayConfigVersion; use Illuminate\Support\Collection; +use App\Lottery\ConfigVersionStatus; +use App\Exceptions\TicketOperationException; final class PlayCatalogResolver { diff --git a/app/Services/Ticket/PlayRuleEngine.php b/app/Services/Ticket/PlayRuleEngine.php index c5d0622..22c6cbc 100644 --- a/app/Services/Ticket/PlayRuleEngine.php +++ b/app/Services/Ticket/PlayRuleEngine.php @@ -2,12 +2,12 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; -use App\Lottery\ErrorCode; use App\Models\OddsItem; -use App\Models\PlayConfigItem; use App\Models\PlayType; +use App\Lottery\ErrorCode; +use App\Models\PlayConfigItem; use Illuminate\Support\Collection; +use App\Exceptions\TicketOperationException; final class PlayRuleEngine { diff --git a/app/Services/Ticket/RiskPoolService.php b/app/Services/Ticket/RiskPoolService.php index 791d5dd..8525d07 100644 --- a/app/Services/Ticket/RiskPoolService.php +++ b/app/Services/Ticket/RiskPoolService.php @@ -2,11 +2,11 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; -use App\Lottery\ErrorCode; use App\Models\RiskPool; -use App\Models\RiskPoolLockLog; +use App\Lottery\ErrorCode; use App\Models\TicketItem; +use App\Models\RiskPoolLockLog; +use App\Exceptions\TicketOperationException; final class RiskPoolService { diff --git a/app/Services/Ticket/TicketPlacementService.php b/app/Services/Ticket/TicketPlacementService.php index a819ef9..ae5fc9b 100644 --- a/app/Services/Ticket/TicketPlacementService.php +++ b/app/Services/Ticket/TicketPlacementService.php @@ -2,16 +2,16 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; -use App\Lottery\DrawStatus; -use App\Lottery\ErrorCode; use App\Models\Draw; use App\Models\Player; -use App\Models\TicketCombination; +use App\Lottery\ErrorCode; use App\Models\TicketItem; +use App\Lottery\DrawStatus; use App\Models\TicketOrder; -use App\Services\Jackpot\JackpotContributionService; +use App\Models\TicketCombination; use Illuminate\Support\Facades\DB; +use App\Exceptions\TicketOperationException; +use App\Services\Jackpot\JackpotContributionService; final class TicketPlacementService { diff --git a/app/Services/Ticket/TicketPreviewService.php b/app/Services/Ticket/TicketPreviewService.php index dd9c357..74e334a 100644 --- a/app/Services/Ticket/TicketPreviewService.php +++ b/app/Services/Ticket/TicketPreviewService.php @@ -2,10 +2,10 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; -use App\Lottery\DrawStatus; -use App\Lottery\ErrorCode; use App\Models\Draw; +use App\Lottery\ErrorCode; +use App\Lottery\DrawStatus; +use App\Exceptions\TicketOperationException; final class TicketPreviewService { diff --git a/app/Services/Ticket/TicketWalletService.php b/app/Services/Ticket/TicketWalletService.php index 58f5fe5..7197845 100644 --- a/app/Services/Ticket/TicketWalletService.php +++ b/app/Services/Ticket/TicketWalletService.php @@ -2,12 +2,12 @@ namespace App\Services\Ticket; -use App\Exceptions\TicketOperationException; -use App\Lottery\ErrorCode; use App\Models\Player; -use App\Models\PlayerWallet; -use App\Models\TicketOrder; use App\Models\WalletTxn; +use App\Lottery\ErrorCode; +use App\Models\TicketOrder; +use App\Models\PlayerWallet; +use App\Exceptions\TicketOperationException; final class TicketWalletService { diff --git a/app/Services/Wallet/HttpMainSiteWalletGateway.php b/app/Services/Wallet/HttpMainSiteWalletGateway.php index aa27b0e..4136ee8 100644 --- a/app/Services/Wallet/HttpMainSiteWalletGateway.php +++ b/app/Services/Wallet/HttpMainSiteWalletGateway.php @@ -3,8 +3,8 @@ namespace App\Services\Wallet; use App\Models\Player; -use GuzzleHttp\Exception\ConnectException; use Illuminate\Support\Facades\Http; +use GuzzleHttp\Exception\ConnectException; /** * 通过 HTTP 调用主站钱包 API(路径见 config lottery.main_site.wallet_*_path)。 diff --git a/app/Services/Wallet/LotteryTransferService.php b/app/Services/Wallet/LotteryTransferService.php index 7d8c56b..ce47d92 100644 --- a/app/Services/Wallet/LotteryTransferService.php +++ b/app/Services/Wallet/LotteryTransferService.php @@ -2,17 +2,17 @@ namespace App\Services\Wallet; -use App\Exceptions\WalletOperationException; -use App\Lottery\ErrorCode; -use App\Models\Currency; use App\Models\Player; +use App\Models\Currency; +use App\Models\WalletTxn; +use App\Lottery\ErrorCode; +use Illuminate\Support\Str; use App\Models\PlayerWallet; use App\Models\TransferOrder; -use App\Models\WalletTxn; use App\Services\LotterySettings; -use Illuminate\Database\QueryException; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Str; +use Illuminate\Database\QueryException; +use App\Exceptions\WalletOperationException; /** * 主站 ↔ 彩票钱包:转入 / 转出(幂等键 + 流水 + 订单)。 diff --git a/app/Support/AdminApiList.php b/app/Support/AdminApiList.php index 08bd2a4..0c019d1 100644 --- a/app/Support/AdminApiList.php +++ b/app/Support/AdminApiList.php @@ -2,9 +2,9 @@ namespace App\Support; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; /** * 后台标准列表:`items` + `meta`(current_page / per_page / total / last_page)。 diff --git a/app/Support/AdminConfigPresenter.php b/app/Support/AdminConfigPresenter.php index 203c1a3..4094944 100644 --- a/app/Support/AdminConfigPresenter.php +++ b/app/Support/AdminConfigPresenter.php @@ -3,12 +3,12 @@ namespace App\Support; use App\Models\OddsItem; -use App\Models\OddsVersion; -use App\Models\PlayConfigItem; -use App\Models\PlayConfigVersion; use App\Models\PlayType; +use App\Models\OddsVersion; use App\Models\RiskCapItem; +use App\Models\PlayConfigItem; use App\Models\RiskCapVersion; +use App\Models\PlayConfigVersion; /** 后台 API:阶段 4 运营配置序列化(与其它 Admin*Controller 手写数组风格一致)。 */ final class AdminConfigPresenter diff --git a/app/Support/AdminMessage.php b/app/Support/AdminMessage.php new file mode 100644 index 0000000..fa05a4d --- /dev/null +++ b/app/Support/AdminMessage.php @@ -0,0 +1,56 @@ +attributes->get('lottery_locale') ?? LotteryLocale::resolve($request)); + + $fullKey = 'admin.'.$key; + $msg = trans($fullKey, [], $locale); + + if ($msg !== $fullKey) { + return $msg; + } + + return trans($fullKey, [], $fallback); + } + + /** + * 取错误码对应的用户可见文案。 + * + * @param int $code {@see ErrorCode} 管理端段(8110–8114) + */ + public static function errorCode(Request $request, int $code): string + { + $fallback = (string) config('lottery.locales.fallback', 'en'); + $locale = (string) ($request->attributes->get('lottery_locale') ?? LotteryLocale::resolve($request)); + $key = 'admin.'.$code; + + $msg = trans($key, [], $locale); + if ($msg !== $key) { + return $msg; + } + + return trans($key, [], $fallback); + } +} diff --git a/app/Support/ApiResponse.php b/app/Support/ApiResponse.php index 47c7a3e..980117f 100644 --- a/app/Support/ApiResponse.php +++ b/app/Support/ApiResponse.php @@ -2,12 +2,13 @@ namespace App\Support; +use App\Lottery\ErrorCode; use Illuminate\Http\JsonResponse; /** * 对外 API 统一 JSON 结构:{ code, msg, data }。 * - * - `code=0` 即 {@see \App\Lottery\ErrorCode::Success};非 0 见 `ErrorCode` 与 docs/04 §10。 + * - `code=0` 即 {@see ErrorCode::Success};非 0 见 `ErrorCode` 与 docs/04 §10。 * - error() 的 HTTP 状态可与 code 独立(如鉴权失败 401 + code 8001)。 */ final class ApiResponse diff --git a/app/Support/CurrencyResolver.php b/app/Support/CurrencyResolver.php new file mode 100644 index 0000000..e4657a4 --- /dev/null +++ b/app/Support/CurrencyResolver.php @@ -0,0 +1,68 @@ +default_currency 或 config) + */ + public static function resolve( + Request $request, + ?Player $player = null, + string $key = 'currency', + ?string $default = null, + ): string { + $raw = $request->input($key) ?? $request->query($key); + + if (is_string($raw) && $raw !== '') { + $code = strtoupper(substr(trim($raw), 0, 16)); + } else { + $fallback = $default + ?? $player?->default_currency + ?? config('lottery.default_currency', 'NPR'); + $code = strtoupper(substr(trim((string) $fallback), 0, 16)); + } + + return $code; + } + + /** + * 验证币种码格式是否合法。 + * + * 合法格式:1-16 位字母数字,全大写。 + */ + public static function isValid(string $code): bool + { + return preg_match('/^[A-Z0-9]{1,16}$/', $code) === 1; + } + + /** + * 解析并验证币种码,无效时返回 null。 + */ + public static function resolveOrNull( + Request $request, + ?Player $player = null, + string $key = 'currency', + ?string $default = null, + ): ?string { + $code = self::resolve($request, $player, $key, $default); + + return self::isValid($code) ? $code : null; + } +} diff --git a/app/Support/OddsStandardScopes.php b/app/Support/OddsStandardScopes.php index 3d220b1..032301e 100644 --- a/app/Support/OddsStandardScopes.php +++ b/app/Support/OddsStandardScopes.php @@ -4,8 +4,8 @@ namespace App\Support; use App\Models\Currency; use App\Models\OddsItem; -use App\Models\OddsVersion; use App\Models\PlayType; +use App\Models\OddsVersion; use Illuminate\Support\Facades\DB; /** diff --git a/app/Support/PaginationTrait.php b/app/Support/PaginationTrait.php new file mode 100644 index 0000000..2e6c267 --- /dev/null +++ b/app/Support/PaginationTrait.php @@ -0,0 +1,51 @@ +query($key, $request->query('size', $default)); + + return max(1, min($max, $value)); + } + + /** + * 解析当前页码(强制至少为 1)。 + */ + protected function page(Request $request, string $key = 'page', int $default = 1): int + { + return max(1, (int) $request->query($key, $default)); + } + + /** + * 解析分页元数据数组。 + * + * @return array{page: int, per_page: int} + */ + protected function paginationMeta(Request $request, int $defaultPerPage = 20, int $maxPerPage = 50): array + { + return [ + 'page' => $this->page($request), + 'per_page' => $this->perPage($request, 'per_page', $defaultPerPage, $maxPerPage), + ]; + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index 1bf6b1c..4fd4908 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -9,21 +9,21 @@ |-------------------------------------------------------------------------- */ -use App\Http\Middleware\EnsureAdminApi; -use App\Http\Middleware\EnsureAdminPermission; -use App\Http\Middleware\EnsurePlayerApi; -use App\Http\Middleware\NegotiateLotteryLocale; use App\Lottery\ErrorCode; use App\Support\ApiResponse; +use Illuminate\Http\Request; use App\Support\LotteryLocale; -use Illuminate\Auth\AuthenticationException; -use Illuminate\Console\Scheduling\Schedule; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Foundation\Application; +use App\Http\Middleware\EnsureAdminApi; +use App\Http\Middleware\EnsurePlayerApi; +use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Auth\AuthenticationException; +use App\Http\Middleware\EnsureAdminPermission; +use Illuminate\Validation\ValidationException; +use App\Http\Middleware\NegotiateLotteryLocale; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; -use Illuminate\Http\Request; -use Illuminate\Validation\ValidationException; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; diff --git a/config/app.php b/config/app.php index 423eed5..352b893 100644 --- a/config/app.php +++ b/config/app.php @@ -1,7 +1,6 @@ env('APP_MAINTENANCE_DRIVER', 'file'), 'store' => env('APP_MAINTENANCE_STORE', 'database'), ], - ]; diff --git a/config/auth.php b/config/auth.php index 8f437a8..9090747 100644 --- a/config/auth.php +++ b/config/auth.php @@ -3,7 +3,6 @@ use App\Models\AdminUser; return [ - 'defaults' => [ 'guard' => env('AUTH_GUARD', 'web'), 'passwords' => env('AUTH_PASSWORD_BROKER', 'admin_users'), @@ -37,5 +36,4 @@ return [ ], 'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800), - ]; diff --git a/config/broadcasting.php b/config/broadcasting.php index ebc3fb9..b09556f 100644 --- a/config/broadcasting.php +++ b/config/broadcasting.php @@ -1,7 +1,6 @@ [ - 'reverb' => [ 'driver' => 'reverb', 'key' => env('REVERB_APP_KEY'), @@ -76,7 +74,5 @@ return [ 'null' => [ 'driver' => 'null', ], - ], - ]; diff --git a/config/cache.php b/config/cache.php index c68acdf..9eec385 100644 --- a/config/cache.php +++ b/config/cache.php @@ -3,7 +3,6 @@ use Illuminate\Support\Str; return [ - /* |-------------------------------------------------------------------------- | Default Cache Store @@ -33,7 +32,6 @@ return [ */ 'stores' => [ - 'array' => [ 'driver' => 'array', 'serialize' => false, @@ -98,7 +96,6 @@ return [ 'array', ], ], - ], /* @@ -126,5 +123,4 @@ return [ */ 'serializable_classes' => false, - ]; diff --git a/config/database.php b/config/database.php index 64709ce..e0dea82 100644 --- a/config/database.php +++ b/config/database.php @@ -1,10 +1,9 @@ [ - 'sqlite' => [ 'driver' => 'sqlite', 'url' => env('DB_URL'), @@ -113,7 +111,6 @@ return [ // 'encrypt' => env('DB_ENCRYPT', 'yes'), // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), ], - ], /* @@ -144,7 +141,6 @@ return [ */ 'redis' => [ - 'client' => env('REDIS_CLIENT', 'phpredis'), 'options' => [ @@ -178,7 +174,5 @@ return [ 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), ], - ], - ]; diff --git a/config/filesystems.php b/config/filesystems.php index 37d8fca..8303adb 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -1,7 +1,6 @@ [ - 'local' => [ 'driver' => 'local', 'root' => storage_path('app/private'), @@ -59,7 +57,6 @@ return [ 'throw' => false, 'report' => false, ], - ], /* @@ -76,5 +73,4 @@ return [ 'links' => [ public_path('storage') => storage_path('app/public'), ], - ]; diff --git a/config/logging.php b/config/logging.php index b09cb25..4db7195 100644 --- a/config/logging.php +++ b/config/logging.php @@ -6,7 +6,6 @@ use Monolog\Handler\SyslogUdpHandler; use Monolog\Processor\PsrLogMessageProcessor; return [ - /* |-------------------------------------------------------------------------- | Default Log Channel @@ -51,7 +50,6 @@ return [ */ 'channels' => [ - 'stack' => [ 'driver' => 'stack', 'channels' => explode(',', (string) env('LOG_STACK', 'single')), @@ -126,7 +124,5 @@ return [ 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], - ], - ]; diff --git a/config/lottery.php b/config/lottery.php index d43c19f..c61258c 100644 --- a/config/lottery.php +++ b/config/lottery.php @@ -9,7 +9,6 @@ */ return [ - 'locales' => [ 'supported' => ['zh', 'en', 'ne'], 'fallback' => 'en', @@ -80,5 +79,4 @@ return [ /** 结果发布后的冷静期(分钟),{@see draws.cooling_end_time} */ 'cooldown_minutes' => max(0, (int) env('LOTTERY_DRAW_COOLDOWN_MINUTES', 15)), ], - ]; diff --git a/config/mail.php b/config/mail.php index e32e88d..a2a8ee1 100644 --- a/config/mail.php +++ b/config/mail.php @@ -1,7 +1,6 @@ [ - 'smtp' => [ 'transport' => 'smtp', 'scheme' => env('MAIL_SCHEME'), @@ -96,7 +94,6 @@ return [ ], 'retry_after' => 60, ], - ], /* @@ -114,5 +111,4 @@ return [ 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 'name' => env('MAIL_FROM_NAME', env('APP_NAME', 'Laravel')), ], - ]; diff --git a/config/queue.php b/config/queue.php index 79c2c0a..51488e7 100644 --- a/config/queue.php +++ b/config/queue.php @@ -1,7 +1,6 @@ [ - 'sync' => [ 'driver' => 'sync', ], @@ -88,7 +86,6 @@ return [ 'deferred', ], ], - ], /* @@ -125,5 +122,4 @@ return [ 'database' => env('DB_CONNECTION', 'sqlite'), 'table' => 'failed_jobs', ], - ]; diff --git a/config/reverb.php b/config/reverb.php index 91f3880..ee447b7 100644 --- a/config/reverb.php +++ b/config/reverb.php @@ -1,7 +1,6 @@ [ - 'reverb' => [ 'host' => env('REVERB_SERVER_HOST', '0.0.0.0'), 'port' => env('REVERB_SERVER_PORT', 8080), @@ -53,7 +51,6 @@ return [ 'pulse_ingest_interval' => env('REVERB_PULSE_INGEST_INTERVAL', 15), 'telescope_ingest_interval' => env('REVERB_TELESCOPE_INGEST_INTERVAL', 15), ], - ], /* @@ -68,7 +65,6 @@ return [ */ 'apps' => [ - 'provider' => 'config', 'apps' => [ @@ -96,7 +92,5 @@ return [ ], ], ], - ], - ]; diff --git a/config/sanctum.php b/config/sanctum.php index cde73cf..656af0a 100644 --- a/config/sanctum.php +++ b/config/sanctum.php @@ -1,12 +1,11 @@ EncryptCookies::class, 'validate_csrf_token' => ValidateCsrfToken::class, ], - ]; diff --git a/config/services.php b/config/services.php index 6a90eb8..bf9e065 100644 --- a/config/services.php +++ b/config/services.php @@ -1,7 +1,6 @@ env('SLACK_BOT_USER_DEFAULT_CHANNEL'), ], ], - ]; diff --git a/config/session.php b/config/session.php index f574482..cab452a 100644 --- a/config/session.php +++ b/config/session.php @@ -3,7 +3,6 @@ use Illuminate\Support\Str; return [ - /* |-------------------------------------------------------------------------- | Default Session Driver @@ -229,5 +228,4 @@ return [ */ 'serialization' => 'json', - ]; diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 05fb5d9..2f4866a 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -1,8 +1,8 @@ $legacySlugs */ private function syncRoleMenuActions(AdminRole $role, array $legacySlugs): void diff --git a/database/seeders/CurrencySeeder.php b/database/seeders/CurrencySeeder.php index 594897a..0bb95ca 100644 --- a/database/seeders/CurrencySeeder.php +++ b/database/seeders/CurrencySeeder.php @@ -8,7 +8,7 @@ use Illuminate\Support\Facades\DB; /** * 写入 `currencies`,与 `docs/04`、`LOTTERY_DEFAULT_CURRENCY` 对齐。 */ -class CurrencySeeder extends Seeder +final class CurrencySeeder extends Seeder { public function run(): void { diff --git a/database/seeders/DashboardHallFixtureSeeder.php b/database/seeders/DashboardHallFixtureSeeder.php index 6b9880a..a4a64f2 100644 --- a/database/seeders/DashboardHallFixtureSeeder.php +++ b/database/seeders/DashboardHallFixtureSeeder.php @@ -2,19 +2,19 @@ namespace Database\Seeders; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; +use Carbon\Carbon; use App\Models\Draw; -use App\Models\DrawResultBatch; use App\Models\Player; use App\Models\RiskPool; use App\Models\TicketItem; +use App\Lottery\DrawStatus; use App\Models\TicketOrder; use App\Models\TransferOrder; -use App\Services\Draw\DrawHallSnapshotBuilder; -use Carbon\Carbon; +use App\Models\DrawResultBatch; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; +use App\Lottery\DrawResultBatchStatus; +use App\Services\Draw\DrawHallSnapshotBuilder; /** * 【仪表盘 / 大厅当期】向 **当前大厅 resolve 指向的期号** 写入丰富演示数据(财务、风控、开奖批次、异常转账)。 @@ -25,7 +25,7 @@ use Illuminate\Support\Facades\DB; * php artisan db:seed --class="Database\\Seeders\\DashboardHallFixtureSeeder" * ``` */ -class DashboardHallFixtureSeeder extends Seeder +final class DashboardHallFixtureSeeder extends Seeder { public function run(): void { diff --git a/database/seeders/DashboardSecondaryScenariosSeeder.php b/database/seeders/DashboardSecondaryScenariosSeeder.php index ced10ad..ac2f22d 100644 --- a/database/seeders/DashboardSecondaryScenariosSeeder.php +++ b/database/seeders/DashboardSecondaryScenariosSeeder.php @@ -2,18 +2,18 @@ namespace Database\Seeders; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; -use App\Lottery\SettlementBatchStatus; -use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Models\DrawResultItem; -use App\Models\RiskPool; -use App\Models\SettlementBatch; -use App\Services\Draw\DrawPrizeLayout; use Carbon\Carbon; +use App\Models\Draw; +use App\Models\RiskPool; +use App\Lottery\DrawStatus; +use App\Models\DrawResultItem; +use App\Models\DrawResultBatch; +use App\Models\SettlementBatch; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; +use App\Lottery\DrawResultBatchStatus; +use App\Lottery\SettlementBatchStatus; +use App\Services\Draw\DrawPrizeLayout; /** * 【多场景演示】额外写入几条 **非大厅当期** 的期号与数据,便于列表、开奖结果、结算摘要等联调。 @@ -25,7 +25,7 @@ use Illuminate\Support\Facades\DB; * php artisan db:seed --class="Database\\Seeders\\DashboardSecondaryScenariosSeeder" * ``` */ -class DashboardSecondaryScenariosSeeder extends Seeder +final class DashboardSecondaryScenariosSeeder extends Seeder { public function run(): void { diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 17885ce..e6f7e16 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,10 +2,10 @@ namespace Database\Seeders; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use Illuminate\Database\Console\Seeds\WithoutModelEvents; -class DatabaseSeeder extends Seeder +final class DatabaseSeeder extends Seeder { use WithoutModelEvents; diff --git a/database/seeders/DevPlayerAndWalletSeeder.php b/database/seeders/DevPlayerAndWalletSeeder.php index 59fb316..8889d30 100644 --- a/database/seeders/DevPlayerAndWalletSeeder.php +++ b/database/seeders/DevPlayerAndWalletSeeder.php @@ -12,7 +12,7 @@ use Illuminate\Database\Seeder; * * fixed site_code + site_player_id 便于之后在 JWT / 脚本里对上号(非生产数据)。 */ -class DevPlayerAndWalletSeeder extends Seeder +final class DevPlayerAndWalletSeeder extends Seeder { public function run(): void { diff --git a/database/seeders/DrawDemoSeeder.php b/database/seeders/DrawDemoSeeder.php index 6273352..766b2ce 100644 --- a/database/seeders/DrawDemoSeeder.php +++ b/database/seeders/DrawDemoSeeder.php @@ -2,14 +2,14 @@ namespace Database\Seeders; -use App\Lottery\DrawResultBatchStatus; -use App\Lottery\DrawStatus; -use App\Models\Draw; -use App\Models\DrawResultBatch; -use App\Models\DrawResultItem; -use App\Services\Draw\DrawPrizeLayout; use Carbon\Carbon; +use App\Models\Draw; +use App\Lottery\DrawStatus; +use App\Models\DrawResultItem; +use App\Models\DrawResultBatch; use Illuminate\Database\Seeder; +use App\Lottery\DrawResultBatchStatus; +use App\Services\Draw\DrawPrizeLayout; /** * 【本地演示】写入若干条 `draws` + 一条带完整 23 组开奖,便于前端大厅 / 开奖结果联调。 @@ -22,7 +22,7 @@ use Illuminate\Database\Seeder; * php artisan db:seed --class="Database\\Seeders\\DrawDemoSeeder" * ``` */ -class DrawDemoSeeder extends Seeder +final class DrawDemoSeeder extends Seeder { public function run(): void { diff --git a/database/seeders/LotterySettingsSeeder.php b/database/seeders/LotterySettingsSeeder.php index ab06c7b..32df2fb 100644 --- a/database/seeders/LotterySettingsSeeder.php +++ b/database/seeders/LotterySettingsSeeder.php @@ -2,13 +2,13 @@ namespace Database\Seeders; -use App\Services\LotterySettings; use Illuminate\Database\Seeder; +use App\Services\LotterySettings; /** * 【配置中心】示例键;后续由运营后台维护同表即可。 */ -class LotterySettingsSeeder extends Seeder +final class LotterySettingsSeeder extends Seeder { public function run(): void { diff --git a/database/seeders/OddsPrizeScopesBackfillSeeder.php b/database/seeders/OddsPrizeScopesBackfillSeeder.php index a3566ef..69c46d6 100644 --- a/database/seeders/OddsPrizeScopesBackfillSeeder.php +++ b/database/seeders/OddsPrizeScopesBackfillSeeder.php @@ -3,13 +3,13 @@ namespace Database\Seeders; use App\Models\OddsVersion; -use App\Support\OddsStandardScopes; use Illuminate\Database\Seeder; +use App\Support\OddsStandardScopes; /** * 为历史 odds_versions 补全 §5.5 五档 prize_scope(幂等,可重复执行)。 */ -class OddsPrizeScopesBackfillSeeder extends Seeder +final class OddsPrizeScopesBackfillSeeder extends Seeder { public function run(): void { diff --git a/database/seeders/OperationalConfigV1Seeder.php b/database/seeders/OperationalConfigV1Seeder.php index 4f2d0dc..bae1b91 100644 --- a/database/seeders/OperationalConfigV1Seeder.php +++ b/database/seeders/OperationalConfigV1Seeder.php @@ -2,24 +2,24 @@ namespace Database\Seeders; -use App\Lottery\ConfigVersionStatus; use App\Models\OddsItem; -use App\Models\OddsVersion; -use App\Models\PlayConfigItem; -use App\Models\PlayConfigVersion; use App\Models\PlayType; +use App\Models\OddsVersion; use App\Models\RiskCapItem; +use App\Models\PlayConfigItem; use App\Models\RiskCapVersion; -use App\Support\OddsStandardScopes; use Illuminate\Database\Seeder; +use App\Models\PlayConfigVersion; use Illuminate\Support\Facades\DB; +use App\Support\OddsStandardScopes; +use App\Lottery\ConfigVersionStatus; /** * 阶段 4:写入首套 **active** 玩法配置 / 赔率 / 风控封顶版本(依赖 {@see PlayTypeSeeder}、{@see CurrencySeeder})。 * * 幂等:仅当三套版本均已有 active 行时跳过;否则只补缺失的一类(避免「仅有 play active 时整段被跳过」导致 /play/effective 不可用)。 */ -class OperationalConfigV1Seeder extends Seeder +final class OperationalConfigV1Seeder extends Seeder { public function run(): void { diff --git a/database/seeders/PlayTypeSeeder.php b/database/seeders/PlayTypeSeeder.php index 1962c2e..cce1901 100644 --- a/database/seeders/PlayTypeSeeder.php +++ b/database/seeders/PlayTypeSeeder.php @@ -5,7 +5,7 @@ namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; -class PlayTypeSeeder extends Seeder +final class PlayTypeSeeder extends Seeder { public function run(): void { diff --git a/pint.json b/pint.json new file mode 100644 index 0000000..6bc567e --- /dev/null +++ b/pint.json @@ -0,0 +1,29 @@ +{ + "preset": "laravel", + "rules": { + "declare_strict_types": false, + "final_class": true, + "final_public_method_for_abstract_class": true, + "ordered_imports": { + "sort_algorithm": "length" + }, + "no_extra_blank_lines": { + "tokens": [ + "attribute", + "break", + "case", + "continue", + "curly_brace_block", + "default", + "extra", + "parenthesis_brace_block", + "return", + "square_brace_block", + "switch", + "throw", + "use", + "use_trait" + ] + } + } +} diff --git a/public/index.php b/public/index.php index ee8f07e..24d3a59 100644 --- a/public/index.php +++ b/public/index.php @@ -1,7 +1,7 @@ group(function (): void { - // 名称:服务健康检查 - Route::get('health', HealthController::class)->name('api.v1.health'); + // 公开路由(无需登录) + require __DIR__.'/api/v1/public.php'; - // 名称:当前期号(下注大厅倒计时;无需登录) - Route::get('draw/current', DrawCurrentController::class)->name('api.v1.draw.current'); - // 名称:已发布开奖往期 / 单期(公开) - Route::get('draw/results', DrawResultsIndexController::class)->name('api.v1.draw.results'); - Route::get('draw/results/{draw_no}', DrawResultShowController::class) - ->where('draw_no', '[0-9]{8}-[0-9]{3}') - ->name('api.v1.draw.results.show'); - - Route::get('jackpot/summary', JackpotSummaryController::class)->name('api.v1.jackpot.summary'); - - // 名称:生效玩法 / 赔率 / 封顶目录(阶段 4;公开) - Route::get('play/effective', PlayEffectiveCatalogController::class)->name('api.v1.play.effective'); - - Route::prefix('player') - ->name('api.v1.player.') - ->group(function (): void { - // 名称:玩家端连通性探测 - Route::get('ping', PlayerPingController::class)->name('ping'); - }); - - Route::middleware('lottery.player')->group(function (): void { - Route::prefix('player') - ->name('api.v1.player.') - ->group(function (): void { - // 名称:当前登录玩家信息 - Route::get('me', MeController::class)->name('me'); - }); - - Route::prefix('wallet') - ->name('api.v1.wallet.') - ->group(function (): void { - // 名称:彩票钱包余额查询 - Route::get('balance', WalletBalanceController::class)->name('balance'); - // 名称:钱包流水(PRD §10.1.1) - Route::get('logs', WalletLogsController::class)->name('logs'); - // 名称:主站 → 彩票 转入 - Route::post('transfer-in', WalletTransferInController::class)->name('transfer-in'); - // 名称:彩票 → 主站 转出 - Route::post('transfer-out', WalletTransferOutController::class)->name('transfer-out'); - }); - - Route::prefix('ticket') - ->name('api.v1.ticket.') - ->group(function (): void { - Route::post('preview', TicketPreviewController::class)->name('preview'); - Route::post('place', TicketPlaceController::class)->name('place'); - Route::get('items', TicketItemsIndexController::class)->name('items.index'); - Route::get('items/{ticket_no}', TicketItemShowController::class) - ->where('ticket_no', 'TK[0-9]+') - ->name('items.show'); - Route::get('draws/{draw_no}/my-match', TicketDrawMyMatchController::class) - ->where('draw_no', '[0-9]{8}-[0-9]{3}') - ->name('draws.my-match'); - }); - }); + // 玩家端路由(需 lottery.player) + require __DIR__.'/api/v1/player.php'; + // 管理端路由(需 auth:sanctum + lottery.admin) Route::prefix('admin') ->name('api.v1.admin.') + ->middleware(['auth:sanctum', 'lottery.admin']) ->group(function (): void { - Route::middleware('throttle:admin-auth-captcha') - ->get('auth/captcha', CaptchaController::class) - ->name('auth.captcha'); + // 认证路由(无需 Token,单独限流) + require __DIR__.'/api/v1/admin/auth.php'; - Route::middleware('throttle:admin-auth-login') - ->post('auth/login', LoginController::class) - ->name('auth.login'); + // 核心路由 + require __DIR__.'/api/v1/admin/core.php'; - Route::middleware(['auth:sanctum', 'lottery.admin'])->group(function (): void { - // 名称:后台接口连通性探测(需 Bearer Token;不校验细粒度 RBAC) - Route::get('ping', AdminPingController::class)->name('ping'); + // 钱包/对账 + require __DIR__.'/api/v1/admin/wallet.php'; - /** 首页仪表盘:聚合大厅 + 当期财务/风控/待办计数(细粒度权限在控制器内按块判断) */ - Route::get('dashboard', AdminDashboardController::class)->name('dashboard'); + // 玩家管理 + require __DIR__.'/api/v1/admin/player.php'; - /** §8 钱包对账:超管可管、风控查看、财务可管、客服单用户 */ - Route::middleware('admin.permission:prd.wallet_reconcile.manage|prd.wallet_reconcile.view|prd.wallet_reconcile.view_cs')->group(function (): void { - Route::get('wallet/transfer-orders', TransferOrderListController::class) - ->name('wallet.transfer-orders'); - Route::get('wallet/transactions', WalletTransactionListController::class) - ->name('wallet.transactions'); - }); + // 开奖/风控/结算 + require __DIR__.'/api/v1/admin/draw.php'; - /** §8 用户管理:财务查看 / 客服单用户 / 超管可管 */ - Route::middleware('admin.permission:prd.users.manage|prd.users.view_finance|prd.users.view_cs')->group(function (): void { - Route::get('players/{player}/wallets', PlayerWalletShowController::class) - ->name('players.wallets'); - /** §15.4 客服/财务:按玩家查注单 */ - Route::get('players/{player}/ticket-items', AdminPlayerTicketItemsIndexController::class) - ->name('players.ticket-items.index'); - }); + // 奖池 + require __DIR__.'/api/v1/admin/jackpot.php'; - /** §8 开奖结果·查看 + 风控占用监控(与开奖/风险域一致) */ - Route::middleware('admin.permission:prd.draw_result.manage|prd.draw_result.view')->group(function (): void { - Route::get('draws', AdminDrawIndexController::class)->name('draws.index'); - Route::get('draws/{draw}', AdminDrawShowController::class)->name('draws.show'); - /** §15.4 单期投注/派彩汇总(与结算批次对照) */ - Route::get('draws/{draw}/finance-summary', AdminDrawFinanceSummaryController::class) - ->name('draws.finance-summary'); - Route::get('draws/{draw}/result-batches', AdminDrawResultBatchesIndexController::class) - ->name('draws.result-batches.index'); - Route::get('draws/{draw}/risk-pools/{number_4d}', AdminRiskPoolShowController::class) - ->where('number_4d', '[0-9]{4}') - ->name('draws.risk-pools.show'); - Route::get('draws/{draw}/risk-pool-lock-logs', AdminRiskPoolLockLogIndexController::class) - ->name('draws.risk-pool-lock-logs.index'); - Route::get('draws/{draw}/risk-pools', AdminRiskPoolIndexController::class) - ->name('draws.risk-pools.index'); - }); + // 配置 + require __DIR__.'/api/v1/admin/config.php'; - /** §8 开奖结果录入(发布批次) */ - Route::middleware('admin.permission:prd.draw_result.manage')->group(function (): void { - Route::post( - 'draws/{draw}/result-batches/{batch}/publish', - DrawResultBatchPublishController::class, - )->name('draws.result-batches.publish'); - }); + // 报表 + require __DIR__.'/api/v1/admin/report.php'; - /** §8 派彩确认:超管执行 + 风控审核 */ - Route::middleware('admin.permission:prd.payout.manage|prd.payout.review')->group(function (): void { - Route::post('draws/{draw}/settlement/run', DrawSettlementRunController::class) - ->name('draws.settlement.run'); - }); - - Route::middleware('admin.permission:prd.payout.manage|prd.payout.review|prd.payout.view')->group(function (): void { - Route::get('settlement-batches', AdminSettlementBatchIndexController::class) - ->name('settlement-batches.index'); - Route::get('settlement-batches/{batch}', AdminSettlementBatchShowController::class) - ->name('settlement-batches.show'); - Route::get('settlement-batches/{batch}/details', AdminSettlementBatchDetailsController::class) - ->name('settlement-batches.details'); - }); - - Route::middleware('admin.permission:prd.jackpot.manage|prd.jackpot.view')->group(function (): void { - Route::get('jackpot/pools', AdminJackpotPoolIndexController::class)->name('jackpot.pools.index'); - Route::get('jackpot/payout-logs', AdminJackpotPayoutLogIndexController::class) - ->name('jackpot.payout-logs.index'); - Route::get('jackpot/contributions', AdminJackpotContributionIndexController::class) - ->name('jackpot.contributions.index'); - }); - - Route::middleware('admin.permission:prd.jackpot.manage')->group(function (): void { - Route::put('jackpot/pools/{pool}', AdminJackpotPoolUpdateController::class)->name('jackpot.pools.update'); - }); - - /** §8 玩法/玩法版本只读:财务不可(不含 rebate.view) */ - Route::middleware('admin.permission:prd.play_switch.manage|prd.odds.manage')->group(function (): void { - Route::get('play-types', PlayTypeIndexController::class)->name('play-types.index'); - Route::prefix('config')->name('config.')->group(function (): void { - Route::get('play-versions', PlayConfigVersionIndexController::class)->name('play-versions.index'); - Route::get('play-versions/{id}', PlayConfigVersionShowController::class) - ->whereNumber('id') - ->name('play-versions.show'); - }); - }); - - /** §8 赔率/回水只读:财务仅 rebate.view,不可单独看玩法版本 */ - Route::middleware('admin.permission:prd.odds.manage|prd.rebate.manage|prd.rebate.view')->group(function (): void { - Route::prefix('config')->name('config.')->group(function (): void { - Route::get('odds-versions', OddsVersionIndexController::class)->name('odds-versions.index'); - Route::get('odds-versions/{id}', OddsVersionShowController::class) - ->whereNumber('id') - ->name('odds-versions.show'); - }); - }); - - /** §8 封顶只读 */ - Route::middleware('admin.permission:prd.risk_cap.manage|prd.risk_cap.view')->group(function (): void { - Route::prefix('config')->name('config.')->group(function (): void { - Route::get('risk-cap-versions', RiskCapVersionIndexController::class)->name('risk-cap-versions.index'); - Route::get('risk-cap-versions/{id}', RiskCapVersionShowController::class) - ->whereNumber('id') - ->name('risk-cap-versions.show'); - }); - }); - - /** §8 玩法/赔率/封顶/回水/Jackpot 配置写 */ - Route::middleware('admin.permission:prd.play_switch.manage|prd.odds.manage|prd.risk_cap.manage|prd.rebate.manage|prd.jackpot.manage')->group(function (): void { - Route::patch('play-types/{play_code}', PlayTypePatchController::class) - ->where('play_code', '[a-z0-9_]+') - ->name('play-types.patch'); - Route::prefix('config')->name('config.')->group(function (): void { - Route::post('play-versions', PlayConfigVersionStoreController::class)->name('play-versions.store'); - Route::put('play-versions/{id}/items', PlayConfigItemsReplaceController::class) - ->whereNumber('id') - ->name('play-versions.items.replace'); - Route::post('play-versions/{id}/publish', PlayConfigVersionPublishController::class) - ->whereNumber('id') - ->name('play-versions.publish'); - - Route::post('odds-versions', OddsVersionStoreController::class)->name('odds-versions.store'); - Route::put('odds-versions/{id}/items', OddsItemsReplaceController::class) - ->whereNumber('id') - ->name('odds-versions.items.replace'); - Route::post('odds-versions/{id}/publish', OddsVersionPublishController::class) - ->whereNumber('id') - ->name('odds-versions.publish'); - - Route::post('risk-cap-versions', RiskCapVersionStoreController::class)->name('risk-cap-versions.store'); - Route::put('risk-cap-versions/{id}/items', RiskCapItemsReplaceController::class) - ->whereNumber('id') - ->name('risk-cap-versions.items.replace'); - Route::post('risk-cap-versions/{id}/publish', RiskCapVersionPublishController::class) - ->whereNumber('id') - ->name('risk-cap-versions.publish'); - }); - }); - - /** §8 审计日志:超管全部 / 风控自身 / 财务资金;客服无 */ - Route::middleware('admin.permission:prd.audit.all|prd.audit.self|prd.audit.finance')->group(function (): void { - Route::get('audit-logs', AuditLogIndexController::class)->name('audit-logs.index'); - }); - - /** §8 报表 */ - Route::middleware('admin.permission:prd.report.all|prd.report.risk|prd.report.finance|prd.report.player')->group(function (): void { - Route::get('report-jobs', ReportJobIndexController::class)->name('report-jobs.index'); - Route::post('report-jobs', ReportJobStoreController::class)->name('report-jobs.store'); - Route::get('report-jobs/{report_job}', ReportJobShowController::class) - ->name('report-jobs.show'); - }); - - /** §8 钱包对账任务:查看含客服单用户;创建任务仅可管理(超管/财务) */ - Route::middleware('admin.permission:prd.wallet_reconcile.manage|prd.wallet_reconcile.view|prd.wallet_reconcile.view_cs')->group(function (): void { - Route::get('reconcile-jobs', ReconcileJobIndexController::class)->name('reconcile-jobs.index'); - Route::get('reconcile-jobs/{reconcile_job}', ReconcileJobShowController::class) - ->name('reconcile-jobs.show'); - Route::get('reconcile-jobs/{reconcile_job}/items', ReconcileItemIndexController::class) - ->name('reconcile-jobs.items.index'); - }); - Route::middleware('admin.permission:prd.wallet_reconcile.manage')->group(function (): void { - Route::post('reconcile-jobs', ReconcileJobStoreController::class)->name('reconcile-jobs.store'); - }); - - /** 后台账号与权限分配:仅可管理账户执行。 */ - Route::middleware('admin.permission:prd.admin_user.manage')->group(function (): void { - Route::get('admin-users', AdminUserIndexController::class)->name('admin-users.index'); - Route::post('admin-users', AdminUserStoreController::class)->name('admin-users.store'); - Route::get('admin-users/{admin_user}', AdminUserShowController::class)->name('admin-users.show'); - Route::put('admin-users/{admin_user}', AdminUserUpdateController::class)->name('admin-users.update'); - Route::delete('admin-users/{admin_user}', AdminUserDestroyController::class)->name('admin-users.destroy'); - Route::get('admin-user-permission-catalog', AdminPermissionCatalogController::class) - ->name('admin-users.permission-catalog'); - Route::put('admin-users/{admin_user}/permissions', AdminUserPermissionSyncController::class) - ->name('admin-users.permissions.sync'); - Route::put('admin-users/{admin_user}/roles', AdminUserRoleSyncController::class) - ->name('admin-users.roles.sync'); - }); - }); + // 管理员账号 + require __DIR__.'/api/v1/admin/user.php'; }); }); diff --git a/routes/api/v1/admin/auth.php b/routes/api/v1/admin/auth.php new file mode 100644 index 0000000..10a4780 --- /dev/null +++ b/routes/api/v1/admin/auth.php @@ -0,0 +1,16 @@ +get('auth/captcha', CaptchaController::class) + ->name('api.v1.admin.auth.captcha'); + +Route::middleware('throttle:admin-auth-login') + ->post('auth/login', LoginController::class) + ->name('api.v1.admin.auth.login'); diff --git a/routes/api/v1/admin/config.php b/routes/api/v1/admin/config.php new file mode 100644 index 0000000..1bfbe0f --- /dev/null +++ b/routes/api/v1/admin/config.php @@ -0,0 +1,107 @@ +get('play-types', PlayTypeIndexController::class) + ->name('api.v1.admin.play-types.index'); + +// 玩法版本只读 +Route::middleware('admin.permission:prd.play_switch.manage|prd.odds.manage') + ->prefix('config') + ->name('api.v1.admin.config.') + ->group(function (): void { + Route::get('play-versions', PlayConfigVersionIndexController::class) + ->name('play-versions.index'); + Route::get('play-versions/{id}', PlayConfigVersionShowController::class) + ->whereNumber('id') + ->name('play-versions.show'); + }); + +// 赔率/回水只读 +Route::middleware('admin.permission:prd.odds.manage|prd.rebate.manage|prd.rebate.view') + ->prefix('config') + ->name('api.v1.admin.config.') + ->group(function (): void { + Route::get('odds-versions', OddsVersionIndexController::class) + ->name('odds-versions.index'); + Route::get('odds-versions/{id}', OddsVersionShowController::class) + ->whereNumber('id') + ->name('odds-versions.show'); + }); + +// 封顶只读 +Route::middleware('admin.permission:prd.risk_cap.manage|prd.risk_cap.view') + ->prefix('config') + ->name('api.v1.admin.config.') + ->group(function (): void { + Route::get('risk-cap-versions', RiskCapVersionIndexController::class) + ->name('risk-cap-versions.index'); + Route::get('risk-cap-versions/{id}', RiskCapVersionShowController::class) + ->whereNumber('id') + ->name('risk-cap-versions.show'); + }); + +// 玩法/赔率/封顶/Jackpot 配置写入 +Route::middleware('admin.permission:prd.play_switch.manage|prd.odds.manage|prd.risk_cap.manage|prd.rebate.manage|prd.jackpot.manage') + ->group(function (): void { + Route::patch('play-types/{play_code}', PlayTypePatchController::class) + ->where('play_code', '[a-z0-9_]+') + ->name('api.v1.admin.play-types.patch'); + + Route::prefix('config') + ->name('api.v1.admin.config.') + ->group(function (): void { + // 玩法版本写入 + Route::post('play-versions', PlayConfigVersionStoreController::class) + ->name('play-versions.store'); + Route::put('play-versions/{id}/items', PlayConfigItemsReplaceController::class) + ->whereNumber('id') + ->name('play-versions.items.replace'); + Route::post('play-versions/{id}/publish', PlayConfigVersionPublishController::class) + ->whereNumber('id') + ->name('play-versions.publish'); + + // 赔率版本写入 + Route::post('odds-versions', OddsVersionStoreController::class) + ->name('odds-versions.store'); + Route::put('odds-versions/{id}/items', OddsItemsReplaceController::class) + ->whereNumber('id') + ->name('odds-versions.items.replace'); + Route::post('odds-versions/{id}/publish', OddsVersionPublishController::class) + ->whereNumber('id') + ->name('odds-versions.publish'); + + // 封顶版本写入 + Route::post('risk-cap-versions', RiskCapVersionStoreController::class) + ->name('risk-cap-versions.store'); + Route::put('risk-cap-versions/{id}/items', RiskCapItemsReplaceController::class) + ->whereNumber('id') + ->name('risk-cap-versions.items.replace'); + Route::post('risk-cap-versions/{id}/publish', RiskCapVersionPublishController::class) + ->whereNumber('id') + ->name('risk-cap-versions.publish'); + }); + }); diff --git a/routes/api/v1/admin/core.php b/routes/api/v1/admin/core.php new file mode 100644 index 0000000..c3e3a7f --- /dev/null +++ b/routes/api/v1/admin/core.php @@ -0,0 +1,21 @@ +name('api.v1.admin.ping'); + +// 首页仪表盘 +Route::get('dashboard', AdminDashboardController::class)->name('api.v1.admin.dashboard'); + +// 审计日志 +Route::middleware('admin.permission:prd.audit.all|prd.audit.self|prd.audit.finance') + ->get('audit-logs', AuditLogIndexController::class) + ->name('api.v1.admin.audit-logs.index'); diff --git a/routes/api/v1/admin/draw.php b/routes/api/v1/admin/draw.php new file mode 100644 index 0000000..fc495f5 --- /dev/null +++ b/routes/api/v1/admin/draw.php @@ -0,0 +1,60 @@ +group(function (): void { + Route::get('draws', AdminDrawIndexController::class) + ->name('api.v1.admin.draws.index'); + Route::get('draws/{draw}', AdminDrawShowController::class) + ->name('api.v1.admin.draws.show'); + Route::get('draws/{draw}/finance-summary', AdminDrawFinanceSummaryController::class) + ->name('api.v1.admin.draws.finance-summary'); + Route::get('draws/{draw}/result-batches', AdminDrawResultBatchesIndexController::class) + ->name('api.v1.admin.draws.result-batches.index'); + Route::get('draws/{draw}/risk-pools/{number_4d}', AdminRiskPoolShowController::class) + ->where('number_4d', '[0-9]{4}') + ->name('api.v1.admin.draws.risk-pools.show'); + Route::get('draws/{draw}/risk-pool-lock-logs', AdminRiskPoolLockLogIndexController::class) + ->name('api.v1.admin.draws.risk-pool-lock-logs.index'); + Route::get('draws/{draw}/risk-pools', AdminRiskPoolIndexController::class) + ->name('api.v1.admin.draws.risk-pools.index'); + }); + +// 开奖结果录入(发布批次) +Route::middleware('admin.permission:prd.draw_result.manage') + ->post('draws/{draw}/result-batches/{batch}/publish', DrawResultBatchPublishController::class) + ->name('api.v1.admin.draws.result-batches.publish'); + +// 派彩确认 +Route::middleware('admin.permission:prd.payout.manage|prd.payout.review') + ->post('draws/{draw}/settlement/run', DrawSettlementRunController::class) + ->name('api.v1.admin.draws.settlement.run'); + +// 结算批次查看 +Route::middleware('admin.permission:prd.payout.manage|prd.payout.review|prd.payout.view') + ->group(function (): void { + Route::get('settlement-batches', AdminSettlementBatchIndexController::class) + ->name('api.v1.admin.settlement-batches.index'); + Route::get('settlement-batches/{batch}', AdminSettlementBatchShowController::class) + ->name('api.v1.admin.settlement-batches.show'); + Route::get('settlement-batches/{batch}/details', AdminSettlementBatchDetailsController::class) + ->name('api.v1.admin.settlement-batches.details'); + }); diff --git a/routes/api/v1/admin/jackpot.php b/routes/api/v1/admin/jackpot.php new file mode 100644 index 0000000..25d7357 --- /dev/null +++ b/routes/api/v1/admin/jackpot.php @@ -0,0 +1,27 @@ +group(function (): void { + Route::get('jackpot/pools', AdminJackpotPoolIndexController::class) + ->name('api.v1.admin.jackpot.pools.index'); + Route::get('jackpot/payout-logs', AdminJackpotPayoutLogIndexController::class) + ->name('api.v1.admin.jackpot.payout-logs.index'); + Route::get('jackpot/contributions', AdminJackpotContributionIndexController::class) + ->name('api.v1.admin.jackpot.contributions.index'); + }); + +// 奖池修改(仅管理权限) +Route::middleware('admin.permission:prd.jackpot.manage') + ->put('jackpot/pools/{pool}', AdminJackpotPoolUpdateController::class) + ->name('api.v1.admin.jackpot.pools.update'); diff --git a/routes/api/v1/admin/player.php b/routes/api/v1/admin/player.php new file mode 100644 index 0000000..f8d950f --- /dev/null +++ b/routes/api/v1/admin/player.php @@ -0,0 +1,16 @@ +group(function (): void { + Route::get('players/{player}/wallets', PlayerWalletShowController::class) + ->name('api.v1.admin.players.wallets'); + Route::get('players/{player}/ticket-items', AdminPlayerTicketItemsIndexController::class) + ->name('api.v1.admin.players.ticket-items.index'); + }); diff --git a/routes/api/v1/admin/report.php b/routes/api/v1/admin/report.php new file mode 100644 index 0000000..bfea15f --- /dev/null +++ b/routes/api/v1/admin/report.php @@ -0,0 +1,19 @@ +group(function (): void { + Route::get('report-jobs', ReportJobIndexController::class) + ->name('api.v1.admin.report-jobs.index'); + Route::post('report-jobs', ReportJobStoreController::class) + ->name('api.v1.admin.report-jobs.store'); + Route::get('report-jobs/{report_job}', ReportJobShowController::class) + ->name('api.v1.admin.report-jobs.show'); + }); diff --git a/routes/api/v1/admin/user.php b/routes/api/v1/admin/user.php new file mode 100644 index 0000000..5f14d9b --- /dev/null +++ b/routes/api/v1/admin/user.php @@ -0,0 +1,34 @@ +group(function (): void { + Route::get('admin-users', AdminUserIndexController::class) + ->name('api.v1.admin.admin-users.index'); + Route::post('admin-users', AdminUserStoreController::class) + ->name('api.v1.admin.admin-users.store'); + Route::get('admin-users/{admin_user}', AdminUserShowController::class) + ->name('api.v1.admin.admin-users.show'); + Route::put('admin-users/{admin_user}', AdminUserUpdateController::class) + ->name('api.v1.admin.admin-users.update'); + Route::delete('admin-users/{admin_user}', AdminUserDestroyController::class) + ->name('api.v1.admin.admin-users.destroy'); + Route::get('admin-user-permission-catalog', AdminPermissionCatalogController::class) + ->name('api.v1.admin.admin-users.permission-catalog'); + Route::put('admin-users/{admin_user}/permissions', AdminUserPermissionSyncController::class) + ->name('api.v1.admin.admin-users.permissions.sync'); + Route::put('admin-users/{admin_user}/roles', AdminUserRoleSyncController::class) + ->name('api.v1.admin.admin-users.roles.sync'); + }); diff --git a/routes/api/v1/admin/wallet.php b/routes/api/v1/admin/wallet.php new file mode 100644 index 0000000..1097586 --- /dev/null +++ b/routes/api/v1/admin/wallet.php @@ -0,0 +1,35 @@ +group(function (): void { + Route::get('wallet/transfer-orders', TransferOrderListController::class) + ->name('api.v1.admin.wallet.transfer-orders'); + Route::get('wallet/transactions', WalletTransactionListController::class) + ->name('api.v1.admin.wallet.transactions'); + + // 对账任务查看 + Route::get('reconcile-jobs', ReconcileJobIndexController::class) + ->name('api.v1.admin.reconcile-jobs.index'); + Route::get('reconcile-jobs/{reconcile_job}', ReconcileJobShowController::class) + ->name('api.v1.admin.reconcile-jobs.show'); + Route::get('reconcile-jobs/{reconcile_job}/items', ReconcileItemIndexController::class) + ->name('api.v1.admin.reconcile-jobs.items.index'); + }); + +// 对账任务创建(仅管理权限) +Route::middleware('admin.permission:prd.wallet_reconcile.manage') + ->post('reconcile-jobs', ReconcileJobStoreController::class) + ->name('api.v1.admin.reconcile-jobs.store'); diff --git a/routes/api/v1/player.php b/routes/api/v1/player.php new file mode 100644 index 0000000..729abcd --- /dev/null +++ b/routes/api/v1/player.php @@ -0,0 +1,50 @@ +group(function (): void { + // 当前登录玩家信息 + Route::prefix('player') + ->name('api.v1.player.') + ->group(function (): void { + Route::get('me', MeController::class)->name('me'); + }); + + // 钱包 + Route::prefix('wallet') + ->name('api.v1.wallet.') + ->group(function (): void { + Route::get('balance', WalletBalanceController::class)->name('balance'); + Route::get('logs', WalletLogsController::class)->name('logs'); + Route::post('transfer-in', WalletTransferInController::class)->name('transfer-in'); + Route::post('transfer-out', WalletTransferOutController::class)->name('transfer-out'); + }); + + // 注单 + Route::prefix('ticket') + ->name('api.v1.ticket.') + ->group(function (): void { + Route::post('preview', TicketPreviewController::class)->name('preview'); + Route::post('place', TicketPlaceController::class)->name('place'); + Route::get('items', TicketItemsIndexController::class)->name('items.index'); + Route::get('items/{ticket_no}', TicketItemShowController::class) + ->where('ticket_no', 'TK[0-9]+') + ->name('items.show'); + Route::get('draws/{draw_no}/my-match', TicketDrawMyMatchController::class) + ->where('draw_no', '[0-9]{8}-[0-9]{3}') + ->name('draws.my-match'); + }); +}); diff --git a/routes/api/v1/public.php b/routes/api/v1/public.php new file mode 100644 index 0000000..f295b88 --- /dev/null +++ b/routes/api/v1/public.php @@ -0,0 +1,37 @@ +name('api.v1.health'); + +// 开奖相关(公开) +Route::get('draw/current', DrawCurrentController::class)->name('api.v1.draw.current'); +Route::get('draw/results', DrawResultsIndexController::class)->name('api.v1.draw.results'); +Route::get('draw/results/{draw_no}', DrawResultShowController::class) + ->where('draw_no', '[0-9]{8}-[0-9]{3}') + ->name('api.v1.draw.results.show'); + +// 奖池水位(公开) +Route::get('jackpot/summary', JackpotSummaryController::class)->name('api.v1.jackpot.summary'); + +// 玩法目录(公开) +Route::get('play/effective', PlayEffectiveCatalogController::class)->name('api.v1.play.effective'); + +// 玩家端连通性探测 +Route::prefix('player') + ->name('api.v1.player.') + ->group(function (): void { + Route::get('ping', PlayerPingController::class)->name('ping'); + }); diff --git a/tests/Feature/AdminAuthLoginTest.php b/tests/Feature/AdminAuthLoginTest.php index ba3cd8c..49b6fdf 100644 --- a/tests/Feature/AdminAuthLoginTest.php +++ b/tests/Feature/AdminAuthLoginTest.php @@ -1,10 +1,10 @@