## 概述
- 目标：提供一个可权限控制的“活动复制”后端接口与管理端前端交互，支持深度复制期次与奖品信息，生成一个状态为“未开始”的新活动，并保证关联关系与数据一致性。
- 范围：仅管理端（/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`）。
- 复制参数增强（重命名、时间偏移、是否复制奖品池等）。

请确认以上方案后，我将开始实现并提交相应代码改动与测试。