# 称号系统使用说明文档 > 版本: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)