# PRD 计划执行：报告对比功能

> 模块：服务监测（service_monitor）
> 优先级：P1
> 创建日期：2026-07-23
> 需求文档：`PRD_需求文档_报告对比功能.md`

---

## 执行计划

### 阶段一：后端对比逻辑 + API（预估 2h）

**任务清单**：

- [ ] 1.1 新增 `compare_service.py` 对比服务
  - 文件：`skill/code/web/service_monitor/services/compare_service.py`
  - 函数：`compare_reports(report_a_id, report_b_id)`
  - 函数：`_classify_diff(item_a, item_b)` - 分类差异类型
  - 函数：`_calculate_value_change(value_a, value_b)` - 计算数值变化率
  - 函数：`_extract_numeric_value(value)` - 提取数值

- [ ] 1.2 新增对比 API 路由
  - 文件：`skill/code/web/service_monitor/routes.py`
  - 路由：`GET /reports/<report_id_a>/compare/<report_id_b>`
  - 验证：两份报告属于同一目标
  - 错误处理：报告不存在（404）、目标不匹配（400）

- [ ] 1.3 新增导出接口
  - 路由：`GET /reports/<report_id_a>/compare/<report_id_b>/export`
  - 参数：`format`（markdown/html）
  - 导出函数：`export_compare_markdown(data)` / `export_compare_html(data)`

**验收标准**：
- API 返回正确的差异分类
- 数值变化率计算准确（变化 > 20% 标记）
- 导出文件格式正确

---

### 阶段二：前端报告选择器（预估 1h）

**任务清单**：

- [ ] 2.1 修改报告详情页
  - 文件：`skill/code/web/templates/service_monitor/report.html`
  - 新增："对比历史报告"按钮（顶部操作栏）
  - 权限：仅在登录状态下显示（`{% if not token_auth %}`）

- [ ] 2.2 新增报告选择弹窗
  - 元素：弹窗组件
  - 功能：显示历史报告列表（最多 20 份）
  - 交互：选择报告后跳转到对比页

- [ ] 2.3 报告列表数据获取
  - API：`GET /api/service-monitor/reports?target_id={id}&limit=20`
  - 渲染：报告 ID + 时间 + 状态摘要

**验收标准**：
- 按钮正确显示
- 弹窗正常弹出
- 报告列表正确渲染
- 选择后正确跳转

---

### 阶段三：前端对比结果页（预估 2h）

**任务清单**：

- [ ] 3.1 新增对比结果页
  - 文件：`skill/code/web/templates/service_monitor/compare.html`
  - 布局：复用 report.html 框架
  - 路由：`GET /service-monitor/compare/<report_id_a>/<report_id_b>`

- [ ] 3.2 差异汇总卡片
  - 元素：5 个统计卡片（新增异常/恢复正常/值变化/新增项/消失项）
  - 样式：不同颜色区分

- [ ] 3.3 差异明细展示
  - 分组：按模块分组，可折叠
  - 样式：不同差异类型使用不同颜色高亮
  - 每行：KEY + 名称 + 报告A值 + 报告B值 + 变化说明

- [ ] 3.4 导出按钮
  - 位置：顶部操作栏
  - 选项：Markdown / HTML
  - 交互：点击下载文件

**验收标准**：
- 页面正常渲染
- 差异分类正确
- 高亮样式清晰
- 导出功能正常

---

### 阶段四：导出功能完善（预估 1h）

**任务清单**：

- [ ] 4.1 Markdown 导出模板
  - 内容：报告头 + 差异汇总 + 分类明细
  - 格式：标准 Markdown

- [ ] 4.2 HTML 导出模板
  - 内容：与页面布局一致
  - 样式：内联 CSS（邮件发送友好）

- [ ] 4.3 文件下载处理
  - 响应头：`Content-Type` / `Content-Disposition`
  - 文件名：`compare_{report_a_id}_{report_b_id}.{ext}`

**验收标准**：
- 导出文件格式正确
- 内容完整
- 文件名规范

---

### 阶段五：单元测试（预估 1h）

**任务清单**：

- [ ] 5.1 新增测试文件
  - 文件：`skill/code/tests/test_compare_service.py`
  - 用例：对比逻辑、差异分类、数值变化计算

- [ ] 5.2 覆盖率目标
  - 目标：`compare_service.py` > 80%

**验收标准**：
- 所有测试用例通过
- 覆盖率达标

---

### 阶段六：集成测试 + 部署（预估 1h）

**任务清单**：

- [ ] 6.1 本地集成测试
  - 测试：完整流程（选择报告 → 对比 → 导出）
  - 验证：边界情况（无差异、报告不存在、目标不匹配）

- [ ] 6.2 部署到 5.60
  - 更新：`deploy/upload_to_server.py` 文件清单
  - 执行：部署脚本
  - 验证：健康检查 + 功能测试

- [ ] 6.3 更新文档
  - 更新：`HANDOFF_服务监测.md`
  - 提交：Git commit

**验收标准**：
- 本地测试通过
- 部署成功
- 5.60 功能验证通过

---

## 关键文件清单

### 新增文件

| 文件 | 说明 |
|------|------|
| `service_monitor/services/compare_service.py` | 对比服务逻辑 |
| `templates/service_monitor/compare.html` | 对比结果页模板 |
| `tests/test_compare_service.py` | 单元测试 |

### 修改文件

| 文件 | 改动 |
|------|------|
| `service_monitor/routes.py` | 新增对比/导出 API 路由 |
| `templates/service_monitor/report.html` | 新增对比按钮 + 弹窗 |
| `deploy/upload_to_server.py` | 更新部署文件清单 |

---

## 风险与注意事项

### 风险 1：数值提取准确性

**问题**：部分检测项值包含单位（"45%"、"100MB"），数值提取可能不准确

**缓解**：
- 使用正则表达式提取数字部分
- 无法提取时标记为非数值类型，不进行值变化对比

### 风险 2：大报告对比性能

**问题**：full 套件 500+ 检测项，对比计算可能耗时

**缓解**：
- 对比逻辑使用字典索引，时间复杂度 O(n)
- 限制对比项数量（按模块分组，前端懒加载）

---

## 依赖关系

- 依赖现有报告数据结构（`report_service.py`）
- 依赖现有导出机制（`report_service.py` 中的导出函数）
- 无外部依赖新增

---

## 完成定义（DoD）

- [ ] 所有阶段任务完成
- [ ] 单元测试覆盖率 > 80%
- [ ] 本地集成测试通过
- [ ] 部署到 5.60 成功
- [ ] 功能验证通过
- [ ] 文档更新并提交
