bindbox-game/docs/称号系统/说明文档.md
邹方成 8141a47690
Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 39s
feat(称号系统): 新增称号管理功能与抽奖效果集成
- 新增系统称号模板与效果配置表及相关CRUD接口
- 实现用户称号分配与抽奖效果应用逻辑
- 优化抽奖接口支持用户ID参数以应用称号效果
- 新增称号管理前端页面与分配功能
- 修复Windows时区错误与JSON字段初始化问题
- 移除无用管理接口代码并更新文档说明
2025-11-16 11:37:40 +08:00

281 lines
12 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.

# 称号系统使用说明文档
> 版本v1.0
> 日期2025-11-16
> 适用范围:运营、后端、前端
---
## 一、项目规划
- 业务目标:实现“用户抽奖后获得双倍奖励(可限时)”的称号能力,运营可视化配置,后端安全可控,前端可观测。
- 范围:系统称号主数据、称号效果配置(双倍概率)、用户称号分配与时效管理、抽奖流程双倍应用。
- 时间节点:
- 2025-11-16建立说明文档完成创建流程与使用指南。
- 2025-11-17完成抽奖流程集成验证与用例测试预期
---
## 二、实施方案
### 2.1 核心模型
- SystemTitles称号主数据名称、描述、获取规则、适用范围
- SystemTitleEffects称号效果类型、参数、叠加策略、封顶值、排序、状态
- UserTitles用户称号记录生效状态、获得时间、过期时间、来源、备注
- 参考文件:
- internal/repository/mysql/model/system_titles.gen.go
- internal/repository/mysql/model/system_title_effects.gen.go
- internal/repository/mysql/model/user_titles.gen.go
### 2.2 现有预置效果
- 已内置6类效果含“双倍之王EffectType=6”。
- 参考internal/api/admin/titles_seed.go:18-37
### 2.3 后端接口
- 系统称号(管理员):
- GET/POST/PUT/DELETE `/api/admin/system_titles`
- GET/POST/PUT/DELETE `/api/admin/system_titles/:title_id/effects`
- 用户称号分配(管理员):
- POST `/api/admin/users/:user_id/titles`
- 路由参考internal/router/router.go
- 控制器参考internal/api/admin/titles_admin.go
---
## 三、创建流程(运营页面)
### 3.1 进入页面
- 管理端路径:`/operations/titles`
- 若菜单缺失,可调用 EnsureTitlesMenu参考 internal/api/admin/titles_seed.go
### 3.2 创建称号
- 基本信息:
- 名称:例如“抽奖双倍达人”
- 描述例如“抽奖奖励翻倍限时24小时”
- 状态:启用
- 获取规则ObtainRulesJSON建议
```json
{
"methods": ["lottery"],
"conditions": {"lottery_type": "normal"}
}
```
- 适用范围ScopesJSON可为空或限定具体用户等级/品类/区域/时段。
### 3.3 添加效果(双倍概率)
- 选择效果类型EffectType=6双倍概率
- 参数示例对所有奖品100%双倍周期最多1次
```json
{
"target_prize_ids": [],
"chance_x1000": 1000,
"period_cap_times": 1
}
```
- 叠加与封顶:按需设置 `StackingStrategy``CapValueX1000`,用于限制叠加与封顶行为。
### 3.4 保存与检查
- 保存称号与效果后,在列表中确认显示;可进入“效果管理”查看参数是否正确。
---
## 四、分配与时效
### 4.1 运营手动分配
- 在称号列表中点击“分配用户”:
- 有效期类型:`permanent`(永久)、`period`(开始/结束时间)、`days`(按天数)
- 建议设置:`days=1`24小时有效
- 备注:例如“抽奖获得双倍称号”
- 可选:覆盖现有相同称号、发送通知
### 4.2 抽奖后自动分配(后端集成)
- 在抽奖成功后调用用户称号分配接口或服务方法:
- 若用户未持有称号 → 写入 UserTitles设定 `expires_at`(例如当前时间+24小时
- 若已持有且未过期 → 按策略决定是否延长或保持(可由业务规则决定)
---
## 五、抽奖流程应用双倍效果
### 5.1 判定逻辑
1. 读取用户激活且未过期的 UserTitles。
2. 聚合其中类型为 EffectType=6 的 SystemTitleEffects。
3.`chance_x1000`(概率)与 `period_cap_times`(周期次数)判定是否触发。
4. 若触发:将奖品数量或价值翻倍(对指定 `target_prize_ids` 生效或全部奖品)。
5. 记录当期触发次数,避免超过 `period_cap_times`
### 5.2 参数含义
- `target_prize_ids`限定生效的奖品ID集合空数组表示对所有奖品生效。
- `chance_x1000`千分制概率1000=100%、200=20%。
- `period_cap_times`:周期内最多触发次数(建议结合自然日或活动期定义周期)。
---
## 六、配置示例集
### 6.1 获取规则(抽奖获得)
```json
{
"methods": ["lottery"],
"conditions": {"lottery_type": "normal"}
}
```
### 6.2 双倍效果100%/限1次
```json
{
"target_prize_ids": [],
"chance_x1000": 1000,
"period_cap_times": 1
}
```
### 6.3 用户分配有效期(按天)
```json
{
"expire_type": "days",
"days": 1,
"remark": "抽奖获得双倍称号",
"override_existing": true,
"send_notification": true
}
```
---
## 七、测试与验收
### 7.1 管理端用例
- 创建称号与效果 → 列表校验
- 为测试用户分配days=1→ 显示生效与过期时间
### 7.2 抽奖用例
- 用户持有称号时抽奖 → 奖励翻倍,次数受 `period_cap_times` 控制
- 称号过期后抽奖 → 不再翻倍
### 7.3 数据核查
- 检查 UserTitles`active/expires_at/remark`
- 检查效果:`SystemTitleEffects.params_json` 是否符合配置
### 7.4 验收标准
- 正常流程:在有效期内至少一次成功翻倍
- 边界:过期后不生效;超过 `period_cap_times` 不再触发
- 失败路径:接口异常可回滚或重试,日志可追踪
---
## 八、进度记录
- 2025-11-16建立说明文档完成创建流程、分配与时效、抽奖双倍应用、配置示例与验收标准。
- 2025-11-17计划完成抽奖流程集成代码的验证与单元测试。
---
## 九、常见问题
- Q为什么双倍没有触发
- A检查有效期是否过期确认 `chance_x1000` 是否为期望值;校验 `period_cap_times` 是否已用尽;确认奖品是否在 `target_prize_ids` 范围内。
- Q如何限制只对特定奖品翻倍
- A在效果参数中填入 `target_prize_ids` 指定的奖品ID数组。
- Q如何延长用户称号有效期
- A重新分配该称号并设置新的有效期覆盖现有
---
## 十、后续工作
- 如需我在抽奖服务中添加自动分配与双倍应用的具体代码,请告知周期定义(按自然日/活动期)与触发记录存储位置,我将补充实现与测试用例并更新本说明文档进度。
---
## 十一、字段级详解与代码绑定点
### 11.1 获得规则ObtainRulesJSON
- 字段结构:
- `methods: string[]` 获得方式集合(如 `register/consume/invite/activity/manual/lottery`
- `conditions: object` 按不同方式的约束条件(示例键:`lottery_type`, `min_amount`, `time_range`, `participate_times` 等)
- 用途说明:当前后端仅进行“存取”,尚未在服务层解析并自动授予头衔;需后续集成到具体事件(抽奖、消费、邀请等)的规则评估器。
- 代码绑定:
- 创建时写入默认空对象:`internal/api/admin/titles_admin.go:88`
- 创建落库:`internal/api/admin/titles_admin.go:94-96`
- 修改时更新:`internal/api/admin/titles_admin.go:125`
- 预置种子:`internal/api/admin/titles_seed.go:54`
- DAO 字段映射:`internal/repository/mysql/dao/system_titles.gen.go:34, 53, 77, 102`
- 前端规则助手来源:
- 载入与保存:`web/admin/src/views/operations/titles/components/RuleConfigDialog.vue:331-393, 395-450`
- JSON 预览构造:`web/admin/src/views/operations/titles/components/RuleConfigDialog.vue:283-322`
- 示例配置:
```json
{
"methods": ["lottery"],
"conditions": {"lottery_type": "normal", "participate_times": 1}
}
```
(说明:目前该 JSON 仅随标题存储,不会自动触发授予;若需要自动授予,需新增服务层解析器与事件钩子。)
### 11.2 使用范围ScopesJSON
- 标题层SystemTitles.ScopesJSON
- 用途:目前仅存取,并未在运行时判定中直接使用。
- 创建写入:`internal/api/admin/titles_admin.go:89, 95-96`
- 修改更新:`internal/api/admin/titles_admin.go:126`
- 效果层SystemTitleEffects.ScopesJSON
- 用途:运行时用于过滤效果的生效范围(活动/期/分类等),排除优先,包含其次,未配置则视为全局。
- 解析结构:`internal/service/title/effects_resolver.go:60-69`
- `activity_ids`, `issue_ids`, `category_ids`
- `exclude.activity_ids`, `exclude.issue_ids`, `exclude.category_ids`
- 匹配逻辑:`internal/service/title/effects_resolver.go:133-155`
- 抽奖期过滤(简化版,仅按 issue`internal/service/activity/draw_with_effects.go:85-103`
- 管理端写入:`internal/api/admin/titles_admin.go:196-206, 251`
- 示例配置:
```json
{
"activity_ids": [1001, 1002],
"issue_ids": [2001],
"category_ids": [],
"exclude": { "issue_ids": [2003] }
}
```
(说明:当事件上下文命中 `exclude` 列表则不生效;若配置了包含列表且不命中则不生效;都未配置视为全局。)
### 11.3 效果数量与叠加策略StackingStrategy/CapValueX1000
- 多效果:一个称号可挂载多个效果,列表接口返回总数(`internal/api/admin/titles_admin.go:156-170``sort` 控制同内顺序,`status` 控制启用。
- 叠加策略(`SystemTitleEffects.StackingStrategy``internal/repository/mysql/model/system_title_effects.gen.go:19`
- `0` 最大值max_only取每个目标的最大增益
- `1` 累加封顶sum_with_cap叠加并用 cap 限制
- `2` 首个匹配first_match只在当前为 0 时赋值
- 默认:累加并使用 `CapValueX1000` 统一封顶
- 统一封顶(`SystemTitleEffects.CapValueX1000`):千分比封顶值,用于限制概率/倍数累积的上限。
- 抽奖应用点:`internal/service/activity/draw_with_effects.go:104-149, 152-166, 197-233`
- `effect_type=5` 概率加成:解析 `target_prize_ids/boost_x1000/cap_x1000` 后调整权重
- `effect_type=6` 双倍奖励:合并 `target_prize_ids``chance_x1000` 后概率判定,命中则倍数 `x2`
### 11.4 规则助手(前端可视化配置)
- 入口位置:`web/admin/src/views/operations/titles/components/RuleConfigDialog.vue`
- 获得规则 UI → JSON 映射:`methods/consume/invite/activity``RuleConfigDialog.vue:225-242, 283-297`
- 使用范围 UI → JSON 映射:`user_level/category_ids/region/time``RuleConfigDialog.vue:245-257, 298-318`
- 加载现有规则:`RuleConfigDialog.vue:331-393`
- 保存规则:`RuleConfigDialog.vue:395-450`
- 注意事项:
- 效果编辑表单与后端字段对齐effect_type=5/6
- 5概率加成后端期望`target_prize_ids, boost_x1000, cap_x1000``internal/service/activity/draw_with_effects.go:104-133`
- 6双倍奖励后端期望`target_prize_ids, chance_x1000, period_cap_times``internal/service/activity/draw_with_effects.go:133-149`
- 当前前端默认参数返回与后端不一致:`web/admin/src/views/operations/titles/components/EffectEditDialog.vue:244-261`
- 建议在运营使用时,按后端字段结构填写 `params_json`,或由后续改造对齐表单字段;本文档已标注对齐需求,待前端改造确认后更新。
---
## 十二、字段参考速查表
- ObtainRulesJSON
- `methods`: string[](注册/消费/邀请/活动/抽奖/手动)
- `conditions`: object按场景扩展键`lottery_type/min_amount/time_range/participate_times` 等)
- 绑定点:创建/修改/预置/DAO 映射(见 11.1
- ScopesJSON效果层
- `activity_ids/issue_ids/category_ids`: number[]
- `exclude.activity_ids/issue_ids/category_ids`: number[]
- 绑定点:解析/匹配/抽奖过滤/写入(见 11.2
- SystemTitleEffects效果通用
- `effect_type`: 1~6见模型注释
- `params_json`: 按效果类型字段定义
- `stacking_strategy`: 0/1/2/默认
- `cap_value_x1000`: 千分封顶
- `sort/status`: 顺序与启用
- 绑定点:创建/修改/抽奖应用(见 11.3