184 lines
7.5 KiB
Markdown
184 lines
7.5 KiB
Markdown
---
|
||
name: 注册活动推荐游戏配置
|
||
overview: 在 slot_admin 活动管理 type=7 编辑页增加「推荐游戏」多选,写入 ext_config.game_ids;配套列表展示与保存校验,与 slot_console 已实现的领取随机进游戏逻辑对齐。
|
||
todos:
|
||
- id: admin-model-api
|
||
content: GameApiModel 查询方法 + ActivityController::publishedGames
|
||
status: completed
|
||
- id: admin-validate
|
||
content: ActivityValidate::checkRegisterRewardExt + save/update 调用
|
||
status: completed
|
||
- id: vue-edit
|
||
content: activity/edit.vue type=7 推荐游戏多选与 submit/setFormData
|
||
status: completed
|
||
- id: vue-api-index
|
||
content: activity.js API + index.vue type=7 列表展示
|
||
status: completed
|
||
- id: manual-verify
|
||
content: 后台保存后 C 端领取验证 game_id 随机返回
|
||
status: completed
|
||
isProject: false
|
||
---
|
||
|
||
# 注册活动 type=7 推荐游戏后台配置
|
||
|
||
## 背景
|
||
|
||
C 端已在 [`RegisterRewardLogic`](slot_console/app/api/logic/RegisterRewardLogic.php) 读取 `ext_config.game_ids`,领取注册活动成功后随机返回 `game_id`。本任务补齐 **后台配置入口**,范围:
|
||
|
||
- [`backend/slot_admin_vue`](backend/slot_admin_vue) 活动编辑/列表
|
||
- [`backend/slot_admin`](backend/slot_admin) 保存校验与游戏选项 API
|
||
|
||
不涉及 slot_console 改动(`updateConfig` 已原样持久化 `ext_config` JSON)。
|
||
|
||
## 配置契约(与 C 端一致)
|
||
|
||
```json
|
||
{
|
||
"game_ids": [101, 205, 308]
|
||
}
|
||
```
|
||
|
||
- 值为 `game.id`(`s_game_api.game_id`),须属于活动 `model_id` 下 **status=1** 的已发布游戏。
|
||
- 允许为空:领取仍成功,响应不含 `game_id`。
|
||
|
||
## 数据流
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
AdminVue->>ActivityController: GET publishedGames?model_id=
|
||
ActivityController->>GameApiModel: 已上架 game_id 列表
|
||
AdminVue->>ActivityController: POST save/update ext_config.game_ids
|
||
ActivityController->>ActivityValidate: checkRegisterRewardExt
|
||
ActivityController->>ConsoleInnerapi: ActivityService add/update
|
||
ConsoleInnerapi->>DB: s_recharge_gift_config.ext_config
|
||
```
|
||
|
||
## 1. slot_admin 后端
|
||
|
||
### 1.1 游戏选项 API
|
||
|
||
在 [`ActivityController`](backend/slot_admin/app/game/controller/ActivityController.php) 新增:
|
||
|
||
- **`publishedGames(Request $request)`**
|
||
- 入参:`model_id`(必填,对应活动「游戏模型」)
|
||
- 出参:`[{ game_id, name }]`,供多选下拉
|
||
|
||
查询放在 [`GameApiModel`](backend/slot_admin/app/model/GameApiModel.php)(`s_common.s_game_api`):
|
||
|
||
```php
|
||
public static function optionsByGameModelId(int $gameModelId): array
|
||
```
|
||
|
||
条件:`game_model_id`、`status = 1`,`field('game_id,name')`,按 `sort` 排序;可对 `game_id` `group` 去重(与 console 侧一致)。
|
||
|
||
### 1.2 保存校验
|
||
|
||
在 [`ActivityValidate`](backend/slot_admin/app/game/validate/ActivityValidate.php) 新增 **`checkRegisterRewardExt(array $extConfig, int $gameModelId)`**:
|
||
|
||
| 规则 | 说明 |
|
||
| --- | --- |
|
||
| `game_ids` 可选 | 缺失或 `[]` 直接通过 |
|
||
| 元素为正整数 | 非法 ID 抛 `ValidateException` |
|
||
| 与渠道一致(推荐) | 调用 `GameApiModel::publishedGameIds($gameModelId, $ids)`(与 console 同名语义),提交 ID 必须全部在已发布集合内,否则提示未上架 ID |
|
||
|
||
在 `ActivityController::save` / `update`(`updateData` 全量更新时)中,当 `type === 7` 时调用:
|
||
|
||
```php
|
||
$this->validate->checkRegisterRewardExt(
|
||
(array) input('ext_config', []),
|
||
(int) input('model_id', 0)
|
||
);
|
||
```
|
||
|
||
对齐 type=11 的 [`checkFreeCreditsExt`](backend/slot_admin/app/game/validate/ActivityValidate.php) 调用方式。
|
||
|
||
可在 `GameApiModel` 复用与 console 相同的 `publishedGameIds` 静态方法(admin 连接 `s_common`,表结构一致)。
|
||
|
||
## 2. slot_admin_vue 前端
|
||
|
||
### 2.1 API
|
||
|
||
在 [`src/api/game/activity.js`](backend/slot_admin_vue/src/api/game/activity.js) 增加:
|
||
|
||
```js
|
||
publishedGames(params) {
|
||
return request({ url: '/game/activity/publishedGames', method: 'get', params })
|
||
}
|
||
```
|
||
|
||
(路径随 Webman 路由约定:`game/activity/publishedGames`。)
|
||
|
||
### 2.2 编辑页 type=7 表单项
|
||
|
||
文件:[`src/views/game/activity/edit.vue`](backend/slot_admin_vue/src/views/game/activity/edit.vue)
|
||
|
||
在 **仅 type=7** 的 `<template>` 中增加(参考 type=11 独立区块,勿影响 type=8 下载奖励):
|
||
|
||
```vue
|
||
<template v-if="formData.type === 7">
|
||
<a-form-item label="推荐游戏" field="ext_config.game_ids"
|
||
help="用户领取注册奖励后,从此列表随机推荐一款已上架游戏">
|
||
<a-select
|
||
v-model="formData.ext_config.game_ids"
|
||
:options="publishedGameOptions"
|
||
multiple allow-search allow-clear
|
||
placeholder="请先选择游戏模型,再选择推荐游戏"
|
||
:disabled="!formData.model_id"
|
||
/>
|
||
</a-form-item>
|
||
</template>
|
||
```
|
||
|
||
脚本逻辑(对齐现有 type=10/11 的 `setFormData` / `submit` 分支):
|
||
|
||
| 时机 | 处理 |
|
||
| --- | --- |
|
||
| `open` / `model_id` 变更 | `loadPublishedGames()` → 调 `publishedGames({ model_id })`,映射 `{ value: game_id, label: name + ' (' + game_id + ')' }` |
|
||
| `setFormData` type=7 | `formData.ext_config.game_ids = (data.ext_config?.game_ids ?? []).map(Number)` |
|
||
| `submit` type=7 | `data.ext_config = { ...data.ext_config, game_ids: 去重正整数数组 }`,**不**覆盖其他 ext 字段 |
|
||
|
||
初始 `formData.ext_config` 在 type=7 时保证含 `game_ids: []`(避免 `v-model` 未定义)。
|
||
|
||
**不**复用首页导航的 cascader([`indexGameNav/edit.vue`](backend/slot_admin_vue/src/views/yyladmin/indexGameNav/edit.vue) 存的是 `nav-{id}-{brandId}`,与 `game_id` 语义不同)。
|
||
|
||
### 2.3 列表页展示
|
||
|
||
文件:[`src/views/game/activity/index.vue`](backend/slot_admin_vue/src/views/game/activity/index.vue)
|
||
|
||
在 `#ext_config` 插槽增加 type=7 分支:
|
||
|
||
- 有 `game_ids`:展示 `推荐游戏: 101, 205, ...`(或显示数量 + tooltip)
|
||
- 无配置:显示「未配置」灰色文案
|
||
|
||
## 3. 与现有编辑页结构的衔接
|
||
|
||
当前 type=7 属于 `onlyGift`,仍通过 **goods 卡片** 配置赠送金额(`goods_id: -1` 由 console 汇总),`ext_config` 此前为空。本次仅在 `ext_config` 增加 `game_ids`,与 goods 并存:
|
||
|
||
- 提交时 **不要** 像 type=11 那样 `data.goods = []`
|
||
- `submit` 中 type=7 仅 merge `game_ids` 进 `ext_config`
|
||
|
||
## 4. 验证方式
|
||
|
||
1. 后台新建/编辑 type=7 活动,选择游戏模型后多选 2+ 款已上架游戏,保存成功。
|
||
2. DB 检查:`s_recharge_gift_config.ext_config` 含 `"game_ids":[...]`。
|
||
3. C 端 `POST /api/gift/receive` 领取该活动,响应含随机 `game_id`。
|
||
4. 提交未上架 `game_id` 应被 admin 校验拦截。
|
||
5. `game_ids` 留空:保存成功,领取响应无 `game_id`。
|
||
|
||
## 文件清单
|
||
|
||
| 仓库 | 文件 | 变更 |
|
||
| --- | --- | --- |
|
||
| slot_admin | `app/model/GameApiModel.php` | `optionsByGameModelId`、`publishedGameIds` |
|
||
| slot_admin | `app/game/controller/ActivityController.php` | `publishedGames`;save/update 校验 type=7 |
|
||
| slot_admin | `app/game/validate/ActivityValidate.php` | `checkRegisterRewardExt` |
|
||
| slot_admin_vue | `src/api/game/activity.js` | `publishedGames` |
|
||
| slot_admin_vue | `src/views/game/activity/edit.vue` | type=7 多选 + 加载/读写 |
|
||
| slot_admin_vue | `src/views/game/activity/index.vue` | type=7 ext_config 展示 |
|
||
|
||
## 风险说明
|
||
|
||
- 切换「游戏模型」后已选 `game_ids` 可能与新模型不匹配:可在 `model_id` `@change` 时清空 `game_ids` 并提示重新选择(建议在实现时一并处理)。
|
||
- 游戏选项依赖 `s_game_api` 发布数据;未发布游戏不会出现在下拉,也无法通过校验提交。
|