## 概述 - 目标:提供一个可权限控制的“活动复制”后端接口与管理端前端交互,支持深度复制期次与奖品信息,生成一个状态为“未开始”的新活动,并保证关联关系与数据一致性。 - 范围:仅管理端(/api/admin/*)可用;前端在活动管理页增加“复制”入口与对话框流程。 ## 后端设计 ### 路由与权限 - 路由:`POST /api/admin/activities/:activity_id/copy` - 鉴权:沿用管理端拦截器(JWT + 角色/动作),新增动作码如 `activity.copy`(与现有 `RequireAdminAction` 机制一致)。 - Swagger:在 `/api/admin/activities` 下新增复制接口文档(请求/响应示例与错误码)。 ### 请求/响应契约 - 请求:`activity_id`(路径参数,必填) - 响应:`{ new_activity_id: number, status: 'success' }`;错误场景返回标准错误码与消息(如未授权、找不到活动、复制失败)。 ### 复制范围与字段策略 - 活动主表(`Activities`):复制除运行态统计外的业务字段(如 `name/banner/activity_category_id/price_draw/is_boss`),`status` 固定为 “未开始”;`start_time/end_time` 可按需求重置为空或原值保留(默认重置为空)。 - 期次表(`ActivityIssues`):复制配置与时间安排(如期次名称、时间窗、规则参数等),新的 `issue` 关联新的 `activity_id`。 - 奖品表(`ActivityRewards`):复制奖品类型、数量、概率等,新的奖品关联新的 `issue_id`。 - 其他关联:不复制抽奖日志、收据、随机承诺历史等运行态数据;仅复制可配置静态数据。 ### 实现步骤(事务 + 深度复制) 1. 读取源活动(校验存在且可复制)。 2. 开启事务(`writeDB.Begin()`)。 3. 新建活动记录(`status=未开始`,重置 `start/end`),拿到 `new_activity_id`。 4. 查询源活动的全部期次(按 `activity_id`),按批次复制: - 将源期次映射为新期次(替换 `activity_id`),批量插入(`CreateInBatches`),建立 `old_issue_id -> new_issue_id` 映射表。 5. 查询源期次对应的全部奖品,按批次复制: - 使用映射替换为新的 `issue_id`,批量插入。 6. 提交事务;返回 `new_activity_id` 与状态。 - 失败回滚:任何步骤出错时回滚并返回错误码与错误信息。 ### 数据一致性与约束 - 全流程单事务保证跨表一致性。 - 外键关系通过 ID 映射正确重建(`issue_id`、`activity_id`)。 - 使用 `gorm.Session{SkipHooks:false}` 保持必要校验;如性能需要可在复制路径禁用不必要的钩子(经评估再启用)。 ### 性能优化策略 - 查询与插入采用分页/批量:`limit/offset` 读取、`CreateInBatches(batchSize=1000)` 写入。 - 仅选择必要字段,避免大 JSON/Blob 字段。 - 大数据量策略:当期次或奖品总数超阈值(如>2万),返回 `202 Accepted` 并创建异步任务(可选扩展);当前版本先同步实现并在前端加入进度提示与超时 UI。 ### 错误码与日志 - 复用项目错误码规范与上下文绑 trace(`internal/pkg/trace`)。 - 记录复制耗时、批次数与行数,便于审计与性能分析。 ### 影响文件(后端) - 路由:`internal/router/router.go`(新增 `POST /api/admin/activities/:activity_id/copy`) - 控制器:`internal/api/admin/activities_copy_admin.go`(新建,处理入参、鉴权、调用服务层) - 服务层:`internal/service/activity/activity_copy.go`(新建,封装事务与深度复制逻辑) - DAO/模型:复用 `internal/repository/mysql/dao/gen.go` 中 `Query`(`Activities/ActivityIssues/ActivityRewards`)与对应 `.gen.go` 模型 - Swagger:`docs/swagger.yaml`、`docs/docs.go`(新增接口文档) ## 前端设计(管理端) ### 交互流程 1. 用户在活动管理页点击“复制”按钮。 2. 弹出复制对话框,异步加载活动下拉(显示名称+ID,支持搜索/分页)。 3. 选择目标活动 → 点击“确认”。 4. 调用后端复制接口,显示处理中状态(loading)。 5. 成功:提示成功并跳转到新活动编辑页(`/activity/wizard?activityId=...`)或刷新列表;失败:提示错误详情。 ### 组件与页面改动 - 活动管理页:`web/admin/src/views/activity/manage/index.vue` - 在列表或操作区增加“复制”入口按钮 - 引入 `CopyActivityDialog`(新建组件或内联对话框) - 复制对话框组件:`web/admin/src/views/activity/manage/CopyActivityDialog.vue` - 下拉框(远程搜索/分页),确认/取消按钮 - 状态提示(loading、成功、失败) ### API 封装与权限 - API:`web/admin/src/api/adminActivities.ts` - 新增 `copyActivity(activityId: number)` → `POST admin/activities/${activityId}/copy` - 活动列表接口复用现有 admin 列表或新增轻量下拉接口 - 权限显示:根据用户的动作权限(如 `activity.copy`)决定是否展示“复制”按钮。 ### 错误处理与状态提示 - 统一使用项目的消息组件与错误拦截(`@/utils/http`)。 - Loading 覆盖对话框;失败显示具体原因(来自后端错误码)。 - 大数据量复制时,提示“复制时间较长”,并在超时后提供轮询或后台进度(后端异步模式可选)。 ### 影响文件(前端) - `web/admin/src/views/activity/manage/index.vue`(增加按钮、接入对话框) - `web/admin/src/views/activity/manage/CopyActivityDialog.vue`(新建组件) - `web/admin/src/api/adminActivities.ts`(新增复制接口方法) - 如需权限常量:`web/admin/src/router/guards/beforeEach.ts` 或权限配置处进行动作码接入 ## 验收标准 - 后端: - `POST /api/admin/activities/:activity_id/copy` 在合法权限下返回 200,包含 `new_activity_id`;事务复制期次与奖品,关联正确,状态为“未开始”。 - 非法权限或不存在的活动返回规范错误码。 - 大数据量下复制耗时可接受且不阻塞服务。 - 前端: - 管理页出现“复制”按钮;弹框可加载活动列表并选择;调用接口后有明显状态提示。 - 成功后刷新或跳转到新活动编辑页;错误时信息清晰。 ## 交付项 - 新接口实现(路由、控制器、服务、Swagger 文档)。 - 前端交互(按钮+对话框+API 封装)。 - 基础单元测试(服务层:期次与奖品复制的映射与事务回滚路径)。 ## 后续可选扩展 - 异步复制任务 + 进度查询(`202 Accepted` + `job_id`)。 - 复制参数增强(重命名、时间偏移、是否复制奖品池等)。 请确认以上方案后,我将开始实现并提交相应代码改动与测试。