## 目标 * 移除无关的“客服组”等错误效果类型与字段,严格对齐后端模型定义(SystemTitles/SystemTitleEffects/UserTitles)。 * 统一“效果类型/参数/叠加策略/封顶/作用范围”配置为后端可用的结构,确保抽奖逻辑(effect\_type=5/6)准确生效。 * 优化前端管理界面与 API 交互,保证运营可视化配置与后端运行一致。 ## 范围 * 前端文件: * `web/admin/src/views/operations/titles/components/EffectEditDialog.vue` * `web/admin/src/views/operations/titles/components/EffectManagerDialog.vue` * `web/admin/src/views/operations/titles/components/RuleConfigDialog.vue` * `web/admin/src/views/operations/titles/index.vue` * `web/admin/src/api/titles.ts` * 后端仅对齐说明,不改动逻辑(模型/服务已正确): * `internal/service/activity/draw_with_effects.go`(抽奖应用) * `internal/service/title/effects_resolver.go`(效果范围) * `internal/api/admin/titles_admin.go`(创建/修改/分配) ## 重构设计(按模型对齐) ### 效果类型与参数(替换现有 UI 与默认值) * 1 领券(优惠券使者) * `params_json`:`{ "template_id": number, "frequency": { "period": "day|week|month", "times": number } }` * 2 抽奖折扣 * `params_json`:`{ "discount_type": "percentage|fixed", "value_x1000": number, "max_discount_x1000": number }` * 3 签到倍数 * `params_json`:`{ "multiplier_x1000": number, "daily_cap_points": number }` * 4 领道具卡 * `params_json`:`{ "template_id": number, "frequency": { "period": "week|month", "times": number } }` * 5 概率加成(抽奖) * `params_json`:`{ "target_prize_ids": number[], "boost_x1000": number, "cap_x1000": number? }` * 6 奖品双倍概率(抽奖) * `params_json`:`{ "target_prize_ids": number[], "chance_x1000": number, "period_cap_times": number? }` * 移除:`生日特权/专属客服` 效果类型与全部相关字段(UI/默认值/展示/说明)。 ### 叠加策略与封顶(严格按模型) * `stacking_strategy` 取值与文案: * 0:最大值(max\_only) * 1:累加封顶(sum\_with\_cap) * 2:首个匹配(first\_match) * `cap_value_x1000`:统一封顶,单位千分比(用于 5/6 合并时的全局封顶)。 * 统一前端控件与默认值(默认建议:1 累加封顶;`cap_value_x1000`=0 表示不封顶)。 ### 效果作用范围(效果级 scopes\_json) * 字段:`activity_ids/issue_ids/category_ids` 与 `exclude.*` * 在效果编辑对话框中新增“作用范围”折叠面板: * 多选输入上述集合;支持排除列表;空集合视为全局。 * 展示格式:在效果列表中将 `scopes_json` 可视化为“包含/排除”标签。 ### 获得规则(标题级 obtain\_rules\_json) * 保留 UI(方便运营标注),明确说明其仅存储,不参与当前自动授予;后续如接入事件评估器再使用。 * JSON 结构:`{ methods: string[], conditions: object }`;维持现有 RuleConfigDialog 保存逻辑。 ## 具体改动点(不执行,供审核) * `EffectEditDialog.vue` * 替换效果类型下拉项为 1\~6 正确枚举;删除“生日特权/专属客服”。 * 重写各类型的表单字段与 `getDefaultParams()` 返回值,改为上述模型参数结构。 * 调整 `stacking_strategy` 单选值为 0/1/2;文案与后端一致。 * 新增“作用范围”字段并在提交时携带 `scopes_json`。 * `EffectManagerDialog.vue` * 更新 `effectTypes` 名称与 Tag 映射为正确文案:`领券/抽奖折扣/签到倍数/领道具卡/概率加成/双倍概率`。 * 调整 `stackingStrategies` 文案为 0/1/2;去掉无模型项。 * 更新参数格式化 `formatParam()`,支持 `template_id/frequency/discount_type/value_x1000/...`。 * 增加对 `scopes_json` 的展示:包含/排除集合标签。 * `RuleConfigDialog.vue` * 保留现有 UI;在文档中明确“标题级范围不参与运行时判定”,避免误解。 * `titles.ts` * 校验请求参数与后端一致:`effect_type/params_json/stacking_strategy(0|1|2)/cap_value_x1000/scopes_json/sort/status`。 ## 数据迁移与兼容 * 已存在的效果记录: * 运营检查并手动改为新结构(通过管理端编辑),或提供一次性迁移脚本:按 `effect_type` 将旧 `params_json` 映射为新字段。 * 前端: * 旧页面中“生日特权/客服组”等效果无法再新建;编辑时提示需切换为模型定义效果。 ## 测试与验收 * 配置与展示:创建每一种效果,检查列表显示与 JSON 持久化。 * 抽奖逻辑: * `effect_type=5`:目标奖品权重按 `boost_x1000` 调整,叠加与封顶正确;参见 `internal/service/activity/draw_with_effects.go`。 * `effect_type=6`:双倍概率按 `chance_x1000` 合并封顶;命中后倍数 x2;名称后缀标识;参见同文件。 * 作用范围:在 issueID 不同期下验证包含/排除命中行为;参见 `effects_resolver.go` 与抽奖文件。 * 运营页面每个功能或者配置字段需要详细描述 ## 交付物 * 代码层面的重构(上述文件修改)。 * 文档更新:已在 `docs/称号系统/说明文档.md` 完成字段级详解与代码绑定点,重构后同步补充“字段校验与默认值”章节与新 UI 截图位点。 ## 风险与注意 * 现有错误效果类型的数据需运营确认是否迁移或删除。 * 前端表单字段与后端参数必须完全对齐,否则抽奖效果不会生效。 确认后我将开始实施重构并提供测试用例与验证记录。