## 目标
- 将活动创建流程改造成“清晰、可操作、可回退”的向导式体验，显著降低填写负担、减少出错率，并确保与现有后端接口完全对齐。
- 统一字段与交互：活动、期、奖励配置的字段、校验与排序一致；消除重复输入与歧义（如奖励名称以选品自动回填）。
- 杜绝常见错误：时间格式、权限校验、表单必填项、动态模块加载等问题在交互层面被提前防护。

## 现状与痛点
- 后端接口已齐备（管理端）：
  - 创建活动：`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 映射与表单校验实现
- 样式与布局更新，卡片/弹窗交互
- 测试用例与构建通过证明
