--- name: 任务进度筛选对接 overview: 新增独立分页接口 `player-task/task-list`(筛选 task_type + status + page/page_size),供前端双下拉表格使用;保留现有 `player-task/task-progress` 全量快照不变。同步 slot_sdk 与 API 文档。 todos: - id: wallet-model-paginate content: WalletFundLotModel 新增 paginatePlayerTaskLots(按 lot_type/status 分页) status: completed - id: wallet-task-list-api content: 新增 taskList 全链路(Validator/DTO/Logic/Service/Controller) status: completed - id: sdk-task-list content: slot_sdk 新增 taskList 请求/响应实体与 WalletService 方法 status: completed - id: api-doc-list content: 新增 doc/player-task-list-api.md(含前端双下拉 + 分页说明) status: completed - id: feature-tests-list content: Feature 测试:筛选、分页、参数校验;task-progress 回归不变 status: completed isProject: false --- # 玩家任务进度:新增分页列表接口 ## 背景与目标 - **现有** [`player-task/task-progress`](doc/player-task-progress-api.md):只读全量快照(`bonus_tasks` + `deposit_tasks` + `summary`),**不改契约**,继续给大厅/SDK 轻量查询用。 - **新增** `player-task/task-list`:面向 **前端操作页**(双下拉 + 表格),支持 **类型筛选、状态筛选、分页**。 前端操作区: | 下拉框 | 选项 | 说明 | |--------|------|------| | 任务类型 | **Bonus** / **Deposit** | 必填,二选一 | | 状态 | **全部** + Waiting / Active / PendingConversion / PlayedOut | `status=0` 或不传 = 全部可见态 | ```mermaid flowchart TB subgraph keep [保持不变] TP["POST task-progress"] TP --> Full["bonus_tasks + deposit_tasks 全量"] end subgraph newApi [新增] TL["POST task-list"] TL --> Filter["task_type + status"] TL --> Page["page + page_size"] Page --> List["list + 分页元数据"] end UI[前端表格页] --> TL Lobby[大厅轻量展示] --> TP ``` --- ## 1. 新接口契约 ### 1.1 路由 | 项 | 值 | |----|-----| | Method | `POST` | | Path | `player-task/task-list` | | Controller | [`PlayerTaskController::taskList`](app/api/controller/PlayerTaskController.php)(新增方法) | ### 1.2 请求参数 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `uid` | int | 是 | 用户 ID | | `currency` | string | 是 | 币种,如 `TGO` | | `task_type` | string | **是** | `bonus` \| `deposit` | | `status` | int | 否 | `0` 或省略 = 全部玩家可见态;`1`/`2`/`3`/`5` = 单态 | | `page` | int | 否 | 页码,默认 `1`,最小 `1` | | `page_size` | int | 否 | 每页条数,默认 `20`,建议上限 `100` | 校验([`PlayerTaskValidator`](app/validator/PlayerTaskValidator.php) 新 scene `list`): - `uid`:`require|integer` - `currency`:`require` - `task_type`:`require|in:bonus,deposit` - `status`:`integer|in:0,1,2,3,5`(可空,默认 0) - `page`:`integer|egt:1`(可空) - `page_size`:`integer|between:1,100`(可空) **前端映射**: | UI | 请求 | |----|------| | Bonus | `"task_type": "bonus"` | | Deposit | `"task_type": "deposit"` | | 全部 | 不传 `status` 或 `"status": 0` | | Waiting / Active / … | `status` = `1` / `2` / `3` / `5` | | 翻页 | 修改 `page`(切换筛选时重置 `page=1`) | ### 1.3 成功响应 `data` 与仓库 [`SearchShardService`](app/service/search/shard/SearchShardService.php) 分页习惯对齐(`data` → `list`): ```json { "task_type": "bonus", "list": [ /* PlayerTaskItem,与 task-progress 任务项字段相同 */ ], "total": 15, "page": 1, "page_size": 20, "last_page": 1 } ``` - `list[]` 元素结构 **复用** [`PlayerTaskItemEntity::toApiArray()`](app/entity/wallet/PlayerTaskItemEntity.php)(与 `task-progress` 单条一致)。 - 排序:`consume_priority_at ASC`, `lot_id ASC`(与现 [`listPlayerTaskLots`](app/model/multi/WalletFundLotModel.php) 一致)。 - 状态范围:默认仍为 PRD §26.1 四态 `[1,2,3,5]`;**不含** Completed/Cancelled/Reversed(与 `task-progress` 一致)。 ### 1.4 与 `task-progress` 的分工 | 接口 | 场景 | 返回 | |------|------|------| | `task-progress` | 一次拿全量两类任务 + 计数汇总 | `summary` + `bonus_tasks` + `deposit_tasks` | | `task-list` | 表格页:选定类型 + 状态 + 翻页 | 单维 `list` + 分页字段 | --- ## 2. wallet 实现要点 ### 2.1 Model 在 [`WalletFundLotModel`](app/model/multi/WalletFundLotModel.php) 新增: ```php /** * 分页查询玩家任务 Lot。 * @return array{list: array, total: int, page: int, page_size: int, last_page: int} */ public function paginatePlayerTaskLots( string $currency, int $lotType, array $statuses, int $page, int $pageSize ): array ``` - `statuses` 为空时直接返回空分页(与 `listPlayerTaskLots` 一致)。 - 使用 ThinkORM `paginate($pageSize, false, ['page' => $page])`,再将 `data` 重命名为 `list`。 ### 2.2 Service 在 [`PlayerTaskQueryService`](app/service/wallet/PlayerTaskQueryService.php) 新增 `queryTaskList(...)`: - `task_type` 字符串 → `LOT_TYPE_BONUS` / `LOT_TYPE_DEPOSIT` - `status` → `PLAYER_VISIBLE_STATUSES` 或单元素数组 - 调用 Model 分页后,`buildTaskItems()` 组装 `list` ### 2.3 分层文件(新增/扩展) | 层级 | 文件 | |------|------| | DTO | `app/api/dto/request/PlayerTaskListRequestDTO.php`(新建) | | Validator | `PlayerTaskValidator` 增加 `SCENE_LIST` | | Logic | `PlayerTaskLogic::taskList()` | | Controller | `PlayerTaskController::taskList()` | **不修改** `PlayerTaskProgressRequestDTO` / `taskProgress` 逻辑。 --- ## 3. slot_sdk 新增(与 wallet 字段 snake_case 一致): | 类型 | 文件 | |------|------| | 请求 | `PlayerTaskListRequestEntity.php` | | 响应 | `PlayerTaskListResponseEntity.php`(含 `list`、`total`、`page`、`page_size`、`last_page`、`task_type`) | [`WalletService`](slot_sdk/src/service/wallet/WalletService.php) 新增: ```php public function taskList(PlayerTaskListRequestEntity $entity): ?PlayerTaskListResponseEntity // POST api/player-task/task-list ``` `taskProgress` / `PlayerTaskProgressRequestEntity` **保持不变**。 发布:slot_sdk commit → push → slot-wallet `composer update`。 --- ## 4. 文档 - **新建** [`doc/player-task-list-api.md`](doc/player-task-list-api.md):路由、入参、响应、前端双下拉 + 翻页交互、与 `task-progress` 对比、curl 示例。 - [`doc/player-task-progress-api.md`](doc/player-task-progress-api.md) 顶部增加「列表分页请用 task-list」交叉引用。 - [`doc/wallet.md`](doc/wallet.md) §26.1 补充 `task-list` 一行说明。 --- ## 5. 测试 新建 `tests/Feature/PlayerTaskListTest.php`(造数参考 [`WalletRegisterBetWinTest`](tests/Feature/WalletRegisterBetWinTest.php)): | 用例 | 断言 | |------|------| | `task_type=bonus` + 默认分页 | `list` 非空项字段完整;`total >= len(list)` | | `status=2` | `list` 内 `status` 均为 2 | | `page=2` + `page_size=1` | 第二页与总数一致 | | 缺 `task_type` | `40003` | | `page_size=101` | `40003` | | `task-progress` 仍返回双数组 | 回归,不受新接口影响 | 容器内执行:`docker compose exec -T php82` + 项目 PHPUnit 命令。 --- ## 6. 不在本次范围 - 修改 `task-progress` 入参或响应 - 任务类型「全部」合并在一个列表 - 运营后台终态(Completed 等)纳入筛选 - 前端页面实现(本仓库无前端) --- ## 7. 关键文件一览 | 仓库 | 变更 | |------|------| | slot-wallet | `PlayerTaskController`、`PlayerTaskLogic`、`PlayerTaskQueryService`、`WalletFundLotModel`、`PlayerTaskValidator`、新 DTO、`doc/player-task-list-api.md`、Feature 测试 | | slot_sdk | 新 Entity ×2、`WalletService::taskList`、`readme.md` |