## 总览
- 覆盖 5 个问题：商品列表批量操作、活动创建奖品价格与总价、仪表盘图表重叠修复、活动创建性能、弹窗点击关闭问题。
- 技术栈：管理端前端 Vue3 + Element Plus（路径 `web/admin`），后端 Go（路径 `internal/*`）。
- 目标：补齐商品批量接口、完善前端交互与缓存、修正布局与加载时序、增强性能与统一弹窗行为。

## 关键位置
- 商品前端：`web/admin/src/views/product/list/index.vue`，API：`web/admin/src/api/product.ts`
- 商品后端：`internal/api/admin/product_create.go`、Service：`internal/service/product/product.go`
- 活动向导：`web/admin/src/views/activity/wizard/index.vue`
- 奖励管理：`web/admin/src/views/activity/rewards/index.vue`
- 仪表盘容器：`web/admin/src/views/dashboard/console/index.vue`
- 抽奖量图表：`web/admin/src/views/dashboard/console/modules/sales-overview.vue` + `components/core/charts/art-line-chart`
- 中奖率分析：`web/admin/src/views/dashboard/console/modules/activity-prize-analysis.vue`
- 弹窗示例：`web/admin/src/views/player-manage/modules/*Dialog.vue`、`components/core/layouts/*`

## 1. 商品列表功能优化
- 后端批量接口
  - 新增 `PUT /api/admin/products/batch`：请求体 `{ ids: number[], stock?: number, status?: 1|2 }`，返回 `{ updated_count, failed: [ {id, reason} ] }`。
  - Controller：在 `internal/api/admin/product_create.go` 或新文件 `product_batch.go` 增加路由与校验（限制 `ids` 1–1000，`stock >= 0`）。
  - Service：`internal/service/product/product.go` 增加 `BatchUpdate(ctx, ids, stock?, status?)`，事务更新；支持“仅库存”“仅状态”“二者皆有”。
  - DAO：使用批量更新（`UPDATE products SET stock=?, status=? WHERE id IN (...)`），对无权限/不存在的 `id` 记录失败原因。
  - 文档：更新 swagger（`docs/swagger.yaml`）。
- 前端批量操作
  - 列表顶部添加“全选本页”复选框：基于 `ElTable` 的选择事件维护 `selectedIds: number[]`，`checkAll` 同步当页数据。
  - 批量工具栏：按钮“批量改库存”“批量上架”“批量下架”。每次操作弹出确认框（库存输入/操作确认）。
  - API：在 `web/admin/src/api/product.ts` 新增 `batchUpdateProducts(payload)` 调用上游接口；失败项以通知/表格高亮反馈。
  - 交互：操作成功后刷新当页并清空选中；支持 loading 与禁用态；无选中时禁用按钮。

## 2. 活动创建流程优化（奖品价格与总价）
- 单价展示
  - 远程商品搜索返回 `price` 字段（已有），选择时在 `ElSelect` 的 `option` 右侧显示“¥单价”。
  - 在奖励编辑卡片/表格中追加“单价”列（从缓存读取）。
- 总价计算
  - 公式：`总价 = Σ(price(product_id) * quantity)`；监听 `product_id/quantity` 变更实时更新。
  - 缓存：在 `wizard/index.vue` 与 `rewards/index.vue` 维护 `priceCache: Map<product_id, price>`，首次选择命中即用，未命中时调用 `fetchProducts` 补齐并写入。
  - 同步：商品价格变更时（重新打开或重新拉取），更新缓存并触发总价重算；保留两位小数。
  - 展示：步骤3顶部显示“选中奖品总成本：¥xxx.xx”。

## 3. 仪表盘数据展示修复（重叠问题）
- 布局与间距
  - 在 `console/index.vue` 的 `ElRow` 增加统一 `gutter`（如 `20`），保证模块间距。
  - 调整 `ElCol` 断点：避免同一行 `ActivityPrizeAnalysis` 与其他模块在窄屏并排压缩；在 `md/sm` 断点落到 `24` 独占一行。
- 组件容器
  - 为 `sales-overview.vue` 与 `activity-prize-analysis.vue` 外层卡片设置 `position: relative; z-index: 0`；图表内部设 `z-index: 1`，避免 canvas/svg 溢出覆盖。
  - 统一卡片最小高度，防止加载时高度为 0 导致重叠。
- 加载时序
  - 图表组件在 `dataReady` 后再渲染；`v-if="dataReady"` 避免空容器渲染。
  - 保留/增加骨架或加载态，防止内容突变挤压。

## 4. 活动创建性能优化（步骤1）
- 加载指示
  - `wizard/index.vue` 步骤1添加 `v-loading` 与骨架；按钮禁用在加载中。
- 请求超时
  - 前端 axios 层设置接口超时 `30s`，在 `web/admin/src/api/_http.ts`（或全局实例）设置，并对超时给出 Toast 提示与重试入口。
- 慢请求日志
  - Axios 响应拦截记录 `duration > 2000ms` 的接口，打印到控制台并上报（如有日志上报端点）。
- 初始化优化
  - 并行拉取必要数据（活动分类、默认配置、组织信息），减少串行等待；命中表格缓存的接口优先读缓存（已有 `tableCache`）。
- 错误恢复
  - 失败时保留已填写表单，显示错误提示与“重试/刷新数据”按钮；网络恢复后自动重载。

## 5. 弹窗点击关闭没有反应（统一与修复）
- 审核现状
  - 业务型对话框普遍设置 `:close-on-click-modal="false"`（避免误关）；全局搜索/锁屏等未禁用遮罩关闭且部分隐藏关闭按钮。
- 统一策略
  - 业务表单：保留 `close-on-click-modal=false`，确保“关闭按钮/取消按钮/ESC”都能关闭；统一通过 `@update:model-value` 与 `@closed` 重置。
  - 全局弹窗：明确设置 `:close-on-click-modal="false"` 并显示关闭按钮或提供显式关闭入口（避免遮罩点击不生效引起困惑）。
- 修复点
  - 核查所有 `ElDialog/ElDrawer`：确保存在 `@update:model-value` 或 `v-model` 双向绑定；为关闭图标绑定 `emit('update:visible', false)`；在有 `before-close` 时正确调用 `done()`。
  - 统一 ESC 关闭（可选）：在布局层面监听 ESC 并广播关闭事件。

## 验收标准
- 商品批量：
  - 在商品列表勾选 N 个，批量改库存/上下架成功，返回计数与失败明细；刷新后状态一致。
- 奖品选择：
  - 选择奖品即显示单价，总价随数量/选择实时更新；切换商品价格后总价同步。
- 仪表盘：
  - “活动抽奖量”与“活动中奖率分析”在所有断点无重叠，布局稳定；数据加载时不挤压。
- 性能与超时：
  - 步骤1加载显示进度，超时 30s 有提示与重试；>2s 请求有日志可见。
- 弹窗关闭：
  - 所有弹窗可通过关闭按钮/取消按钮/ESC 关闭；遮罩行为与设计一致，不出现“点击关闭没有反应”。

## 交付变更清单
- 后端：新增批量接口（Controller+Service+DAO+Swagger）。
- 前端：
  - 商品列表批量选择与工具栏；新增批量 API 调用与确认反馈。
  - 向导步骤3与奖励管理页显示单价与总价；缓存价格。
  - 仪表盘栅格与 z-index 调整；图表渲染时序保护。
  - Axios 超时与慢请求日志；向导加载骨架与错误恢复。
  - 弹窗双向绑定与关闭逻辑统一。

如确认本方案，我将按上述清单依次实现并提交改动，过程中为关键函数添加函数级注释与必要单元/交互测试。