--- name: C端 status 响应补全 overview: 完成 Free Credits 定格状态接口 C 端响应:packages 精简与 status 映射(Model 已改)、banner_image、首笔提现成功广播 broadcast(真实 Top10 + 不足补假数据),并同步单测与文档。 todos: - id: add-banner-image content: 在 buildConfigClientFields / buildStatus / buildPreEnrollmentStatus 返回 banner_image status: completed - id: add-broadcast-list content: 实现 broadcast 列表(真实首档 completed Top10 + 假数据补齐至 10 条) status: completed - id: finish-packages-docs content: 更新 FreeCreditsController PHPDoc(packages、banner_image、broadcast) status: completed - id: update-unit-tests content: 调整 FreeCreditsClientStatusTest / Harness;补充 banner_image、status 映射、broadcast 用例 status: completed - id: run-phpunit content: php82 容器跑 FreeCreditsClientStatusTest 验证 status: completed isProject: false --- # C 端定格 status 响应补全 ## 当前进度 [FreeCreditsPackageModel.php](slot_console/app/model/common/FreeCreditsPackageModel.php) **已完成**: - `mapStatusForClient()`:DB status 4/5 → 3 - `listForClient()`:仅返回 `id`、`amount`、`status` **待完成**:`banner_image`、`broadcast`、Logic/Controller 文档、单测。 ## 1. `banner_image`(活动 Banner) 配置:`ext_config.banner_image`([activity/edit.vue](backend/slot_admin_vue/src/views/game/activity/edit.vue)) 在 [FreeCreditsLogic.php](slot_console/app/api/logic/FreeCreditsLogic.php) 的 `buildConfigClientFields()` 增加 `banner_image`,`buildStatus()` / `buildPreEnrollmentStatus()` 透传;`status=-1` 仍仅 `{ status: -1 }`。 ## 2. `broadcast`(首笔提现成功最近 10 人) 对齐需求文档 [§13 广播模块](docs/requirements/首充前免费余额定格与分档释放需求文档.md):弹窗展示最近 10 条;用户本次明确要求 **仅首笔提现成功**(非后续 claim)。 ### 2.1 顶层字段 - 字段名:**`broadcast`**(`array`,固定长度 **10**) - 每项结构: ```json { "username": "U1***3", "amount": 20.0 } ``` | 子字段 | 类型 | 说明 | |--------|------|------| | `username` | string | 脱敏账号,展示用 | | `amount` | float | 该用户首笔免打码提现金额(展示大单位) | C 端文案示例:`🎉 U1***3 just cashed out $20.00`(前端拼接,接口只给结构化数据)。 ### 2.2 真实数据查询 在 [FreeCreditsPackageModel.php](slot_console/app/model/common/FreeCreditsPackageModel.php) 新增查询方法(仅查库,不做脱敏): ```php public static function listRecentFirstCashoutCompleted(int $activityId, int $limit = 10): array ``` 条件: - `activity_id = ?` - `package_type = TYPE_FIRST_CASH(1)` - `status = STATUS_COMPLETED(3)` - `ORDER BY completed_time DESC`(`completed_time` 为空则 fallback `update_time`) - `LIMIT 10` 返回行至少含:`uid`、`amount_qf`。 ### 2.3 组装与脱敏(Logic) 在 [FreeCreditsLogic.php](slot_console/app/api/logic/FreeCreditsLogic.php) 新增 `buildBroadcastList(?Model $config): array`: 1. 有 `activity_id` 时查真实记录,逐条: - `amount` = `formatClientAmount(amount_qf)` - `username` = `maskDisplayName(account)`:`UserService::getUserInfoEntity($uid)->account`,规则与 [GameLatestLogic::username()](slot_console/app/napi/logic/GameLatestLogic.php) 一致:`substr(0,2) + '***' + substr(-1)`;account 为空时用 `strval(uid)` 再脱敏 2. 若真实条数 `< 10`,用 **`buildFakeBroadcastItems($need, $config)`** 补齐: - `amount`:取当前活动 `first_cash_amount`(`configAmount` + `formatClientAmount`),可在 ±10% 内随机浮动(整数分位),避免 10 条完全相同 - `username`:随机生成 `U` + 5–8 位数字再脱敏(勿与真实 uid 重复) 3. 合并后 **截断/保证恰好 10 条**(真实在前,假数据在后) 在 `buildStatus()` / `buildPreEnrollmentStatus()` 增加: ```php 'broadcast' => $this->buildBroadcastList($config), ``` `status=-1` 不返回 `broadcast`。 ### 2.4 分层说明 - **Model**:只负责按条件查最近 N 条首档 completed - **Logic**:脱敏、金额格式化、假数据补齐(业务展示规则,不抽到 Service) ```mermaid flowchart LR pkgTable[free_credits_package] modelQuery[listRecentFirstCashoutCompleted] logicBuild[buildBroadcastList] fakePad[buildFakeBroadcastItems] statusAPI["status data.broadcast"] pkgTable --> modelQuery --> logicBuild logicBuild --> fakePad --> statusAPI ``` ## 3. packages 文档收尾 [FreeCreditsController.php](slot_console/app/api/controller/FreeCreditsController.php):`packages` 项为 `id`、`amount`、`status(0–3)`;补充 `banner_image`、`broadcast`。 ## 4. 单测 [FreeCreditsClientStatusTest.php](slot_console/tests/Unit/FreeCreditsClientStatusTest.php): | 项 | 调整 | |---|---| | `PLAYER_TOP_KEYS` | 增加 `banner_image`、`broadcast`;**移除** `first_cash_amount`(与当前 `buildStatus` 一致) | | `PACKAGE_KEYS` | `['id','amount','status']` | | 新增 | `testMapStatusForClientMapsFailedAndRejected` | | 新增 | `testBuildStatusIncludesBannerImageFromExtConfig` | | 新增 | `testBuildBroadcastAlwaysReturnsTenItems`:harness 注入空真实列表,断言 `count(broadcast)==10`、每项含 `username`/`amount` | [FreeCreditsLogicHarness.php](slot_console/tests/Support/FreeCreditsLogicHarness.php):可覆写 `buildBroadcastList` 或注入 Model 查询结果,避免单测连库。 ## 5. 验证 ```bash docker exec -w /app/www/slot/slot_console php82 ./vendor/bin/phpunit tests/Unit/FreeCreditsClientStatusTest.php ``` ## 响应示例(status≥0) ```json { "status": 2, "frozen_amount": 78.5, "win_threshold": 50.0, "recharge_unlock_amount": 50.0, "help": "...", "banner_image": "https://cdn.example.com/xxx.png", "broadcast": [ { "username": "U1***3", "amount": 20.0 }, { "username": "U9***2", "amount": 20.0 } ], "packages": [ { "id": 101, "amount": 20.0, "status": 1 } ] } ``` 注:`broadcast` 数组长度恒为 10;示例仅展示 2 条。