bindbox-game/.trae/documents/活动创建流程重构方案.md
邹方成 2a89a1ab9d
Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 39s
feat(admin): 更新前端资源文件及修复相关功能
refactor(service): 修改banner和guild删除逻辑为软删除
fix(service): 修复删除操作使用软删除而非物理删除

build: 添加SQLite测试仓库实现
docs: 新增奖励管理字段拆分和批量抽奖UI改造文档

ci: 更新CI忽略文件
style: 清理无用资源文件
2025-11-19 01:35:55 +08:00

88 lines
6.3 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.

## 目标
- 将活动创建流程改造成“清晰、可操作、可回退”的向导式体验,显著降低填写负担、减少出错率,并确保与现有后端接口完全对齐。
- 统一字段与交互:活动、期、奖励配置的字段、校验与排序一致;消除重复输入与歧义(如奖励名称以选品自动回填)。
- 杜绝常见错误:时间格式、权限校验、表单必填项、动态模块加载等问题在交互层面被提前防护。
## 现状与痛点
- 后端接口已齐备(管理端):
- 创建活动:`POST /api/admin/activities``internal/router/router.go:78`;控制器 `internal/api/admin/activities_admin.go:41`;服务层 `internal/service/activity/activity_create.go:12-41`
- 创建期:`POST /api/admin/activities/:activity_id/issues``internal/router/router.go:83`;控制器 `internal/api/admin/issues_admin.go`;服务层 `internal/service/activity/issue_create.go:13-32`
- 创建奖励:`POST /api/admin/activities/:activity_id/issues/:issue_id/rewards`
- 前端存在两套创建入口:
- 独立向导页:`web/admin/src/views/activity/wizard/index.vue`(“下一步”仅切换步骤,提交由各步的“提交”触发)
- 管理页弹窗向导:`web/admin/src/views/activity/manage/index.vue`(“下一步”实际调用创建并推进)
- 痛点汇总:
- 两处入口的字段命名、排序不一致;奖励有的手填名称,有的选商品
- 时间未填时易触发数据库零日期错误(`TRADITIONAL SQL` 模式下)
- “下一步”与“提交”含义不统一,用户易误操作
- 表格行式编辑密度过高,填写多项参数不友好
- 动态导入失败来源于 SFC 结构不合法、重复脚本块或未声明变量导致编译失败
## 重构设计(交互与结构)
### 向导统一(单入口)
- 入口:统一从“管理页弹窗向导”打开;支持跳转到独立页,但独立页沿用同一套逻辑(避免两套逻辑分歧)
- 步骤:
1. 基本信息活动名称、分类、状态、门票价格、Boss、开始/结束时间
2. 期信息(活动期):期号、状态、排序
3. 奖励配置按商品选择与参数设置权重、数量、原始数量、等级、排序、Boss
4. 确认提交:汇总校验与最终提交
- 导航:
- “下一步”即执行当前步的提交(成功后推进),失败则停留并有明确错误提示
- “上一步”回退不丢数据;每步保存草稿状态在组件内存
### 表单布局与输入体验
- 两列栅格布局(`ElRow/ElCol`):提升可读性与并行填写效率
- 奖励配置交互:
- 改为“卡片列表 + 弹窗表单”,卡片上显示商品名称及关键参数;“新增奖励/编辑奖励”在弹窗中填写,分两列布局
- 商品选择:远程搜索 `admin/products``web/admin/src/api/product.ts`),选择后自动回填奖励名称(传递给后端以兼容)
- 支持复制卡片、删除卡片、批量导入CSV/JSON作为扩展项初版可不做批量
- 字段统一:奖励行统一字段为 `product_id、weight、quantity、original_qty、level、sort、is_boss``name`由选品自动补齐,不再手填
- 权限与提示:检测 `SessionUserInfo.IsSuper`(控制器内已做),前端在 403/400 的返回文案时专门弹出“权限不足”提示
### 校验与防错
- 实时校验规则:
- 活动:名称与分类必填;开始/结束时间支持空,但若为空则前端默认以 `ISO8601` 当前时间传入或后端统一允许 `NULL`
- 期:期号必填;排序与状态为数值校验
- 奖励:`product_id` 必填;数值项均为非负或正数;`level` 合法枚举
- 时间防错:
- 方案优先级A数据库将 `start_time/end_time` 改为可 `NULL` 且默认 `NULL`(推荐);
- 方案优先级B前端在未选择时默认传当前时间的 `toISOString()`
- 后端保留 `Omit` 逻辑(`internal/service/activity/activity_create.go:29-35`),避免强行写零日期
### 代码结构与可维护性
- 组件结构:每个步骤独立子组件(`ActivityStepBasic.vue``ActivityStepIssue.vue``ActivityStepRewards.vue`+ 容器(`ActivityWizard.vue`
- 状态管理:使用本地状态(`ref/reactive`)即可;如需跨页保持,用 `pinia` 记录向导草稿
- API层沿用 `web/admin/src/api/adminActivities.ts`,奖励提交前统一映射自动补齐 `name`
- 动态导入稳定性:
- 确保每个 SFC 仅一个 `<template>` 和一个 `<script setup>`,无重复导入、重复变量与重复函数
- 编译错误先清理其他页面的类型错误(如 `shipping-stats/index.vue``remoteLoading.orders``reconcile/diff/index.vue``formatDetail`),避免影响整体构建可用性
## 后端约束与对齐
- 保持接口不变:`CreateActivity`/`CreateIssue`/`CreateIssueRewards`
- 修改建议(可选):
- 数据库列允许 `NULL`(避免零日期);
-`CreateActivity` 中对 `StartTime/EndTime` 为空时不写入(现有已 Omit
## 验收标准
- 用户可通过统一向导完成活动创建:每步“下一步”均会发起对应请求并进入下一步;错误有明确提示
- 奖励配置以选择商品为主,不再手填名称;行字段与顺序一致
- 复杂表单两列布局,填写效率明显提升;可编辑/删除奖励卡片
- 构建通过(无 SFC 结构错误与类型错误);页面加载不再出现“动态模块导入失败”
## 实施步骤
1. 重构向导组件结构与路由入口;统一使用弹窗向导(保留独立页入口但复用组件)
2. 基本信息与期信息改为两列布局;“下一步”触发提交与推进
3. 奖励配置改为卡片 + 弹窗表单;远程选品与字段统一;提交前自动补齐名称
4. 表单校验与错误提示完善;未填时间的兜底(前端默认或后端允许 NULL
5. 清理页面内无关类型错误(`shipping-stats/index.vue``reconcile/diff/index.vue`)保证构建与动态导入稳定
6. 编写端到端测试用例:
- 正常流程:活动→期→奖励→提交 成功
- 边界:缺少必填项、非超级管理员、时间为空等
- 性能:奖励 50+ 条下的编辑与提交
## 交付物
- 统一的向导组件及子组件
- API 映射与表单校验实现
- 样式与布局更新,卡片/弹窗交互
- 测试用例与构建通过证明