Files
cursor/plans/渠道编号自动生成_ef6f98ea.plan.md
ray zhou 2dd9f17da9 ok
2026-06-29 14:51:55 +08:00

138 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: 渠道编号自动生成
overview: 在 slot-admin 后端创建渠道时自动生成唯一 6 位字母数字编号编辑时禁止修改slot-admin-vue 前端对应隐藏创建输入、编辑只读展示,并移除前端校验。
todos:
- id: backend-add-generate
content: GameServerLogic实现 add() + generateUniqueSource(),合并原 save() 逻辑edit() unset source
status: completed
- id: backend-validate
content: GameServerValidatesave/update 场景移除 source 校验
status: completed
- id: frontend-edit-form
content: edit.vue新增隐藏编号、编辑只读、移除校验、提交时不传 source
status: completed
- id: verify
content: Docker 内手工验证创建/编辑,跑 verify-slot-backend.sh
status: completed
isProject: false
---
# 渠道编号系统自动生成方案
## 背景与范围
渠道管理对应模块:
| 层级 | 路径 |
|------|------|
| 前端列表/表单 | [`slot-admin-vue/src/views/game/source/index.vue`](slot-admin-vue/src/views/game/source/index.vue)、[`edit.vue`](slot-admin-vue/src/views/game/source/edit.vue) |
| API | `POST /game/game-server/save``PUT /game/game-server/update` |
| 后端 | [`GameServerController`](slot-admin/app/game/controller/GameServerController.php) → [`GameServerLogic`](slot-admin/app/game/logic/GameServerLogic.php) → [`GameServerModel`](slot-admin/app/model/GameServerModel.php) |
| 校验 | [`GameServerValidate`](slot-admin/app/game/validate/GameServerValidate.php) |
当前行为:创建/编辑时前端手动填写 `source`(编号),后端 `save`/`update` 场景均校验 `source` 必填。
**额外发现(需一并修复)**[`GameServerLogic::save()`](slot-admin/app/game/logic/GameServerLogic.php) 含 `secret_key` 生成、`extend_data` 格式化、Redis 同步等逻辑,但 [`BaseController::save()`](slot-admin/plugin/saimulti/basic/BaseController.php) 实际调用的是 `logic->add()`,导致创建时这些逻辑**未执行**。本次应改为在 `add()` 中统一处理(参照 [`GGameLogic::add()`](slot-admin/app/game/logic/GGameLogic.php) 模式)。
```mermaid
sequenceDiagram
participant Vue as slot-admin-vue
participant Ctrl as GameServerController
participant Logic as GameServerLogic
participant DB as game_server
Vue->>Ctrl: POST save不含 source
Ctrl->>Logic: add(data)
Logic->>Logic: generateUniqueSource()
Logic->>Logic: prepareCreateData()
Logic->>DB: insert
Logic->>Logic: sync(redis)
Ctrl-->>Vue: success
Vue->>Ctrl: PUT updatesource 只读或不传)
Ctrl->>Logic: edit(id, data)
Logic->>Logic: unset source
Logic->>DB: update
Logic->>Logic: sync(redis)
```
---
## 编号规则(已确认)
- **格式**6 位 **大写字母 + 数字** 混合(如 `A3K9X2`
- **字符集**`A-Z` + `0-9`(统一大写,与现有 `sync()``strtoupper($source)` 行为一致)
- **唯一性**:生成后查库 [`GameServerModel::getBySource()`](slot-admin/app/model/GameServerModel.php),冲突则重试(最多 20 次),失败抛 `ApiException`
- **存量数据**:已有渠道编号不变,仅新建渠道走自动生成
---
## 后端改动slot-admin
### 1. [`GameServerLogic.php`](slot-admin/app/game/logic/GameServerLogic.php)
**新增 `add()`**(替代当前未接入的 `save()`
- 调用 `generateUniqueSource()` 写入 `$data['source']`,忽略前端传入值
- 复用现有 `save()` 内创建前处理:`secret_key``format(extend_data)``dot_type`/`fb_status`/`fb_pix`
- `parent::add($data)``sync($data['source'])`
- 删除或内联原 `save()` 方法,避免双入口
**新增私有方法**(均需中文 PHPDoc
- `generateUniqueSource(): string` — 生成唯一 6 位编号
- `prepareCreateData(array $data): array` — 从原 `save()` 提取的创建前数据整理(可选,保持方法 ≤50 行)
**修改 `edit()`**
- 在更新前 `unset($data['source'])`,防止通过 API 篡改编号
- 其余逻辑保持不变
### 2. [`GameServerValidate.php`](slot-admin/app/game/validate/GameServerValidate.php)
- `save` 场景:**移除** `source`(后端生成,不要求前端传)
- `update` 场景:**移除** `source`(不可编辑)
- 可保留 `source` 规则定义供其他场景复用,但不再出现在 save/update scene
### 3. [`GameServerModel.php`](slot-admin/app/model/GameServerModel.php)(可选小改)
- 新增 `existsBySource(string $source): bool`,供 Logic 查重,语义更清晰(非必须,可直接用 `getBySource`
---
## 前端改动slot-admin-vue
### [`edit.vue`](slot-admin-vue/src/views/game/source/edit.vue)
**模板**(约 L19-23
- **新增模式**:不展示编号输入框;可加一行提示文案「渠道编号将在创建后自动生成」
- **编辑模式**:展示 `source``disabled` 只读输入框
**校验规则**(约 L306-311
- 移除 `source``required` 规则
**提交**(约 L344-357
- 新增/编辑提交前均 `delete data.source`,避免误传
列表页 [`index.vue`](slot-admin-vue/src/views/game/source/index.vue) 已有「编号」列,创建成功后刷新即可看到生成结果,无需改动。
---
## 安全与兼容
- 后端 `edit()` 强制 `unset source` 为最终防线,不依赖前端
- 新建渠道若前端仍传 `source`,后端忽略并覆盖为系统生成值
- 不影响 [`refreshFb`](slot-admin/app/game/controller/GameServerController.php) 等按 `source` 查询的现有功能
---
## 验证步骤
1. Docker 内创建渠道:不传编号,保存成功,列表出现 6 位字母数字编号
2. 编辑渠道:编号字段只读,修改名称等其他字段保存成功,编号不变
3. 尝试通过 API 直接 PUT 修改 `source`,确认后端不更新该字段
4. 执行 `SLOT_ROOT=/Users/ray/Documents/project/www/ray ~/.cursor/hooks/verify-slot-backend.sh`