# 功能测试报告-模板配置 · 需求文档（PRD）

> **文档状态**：已定稿 · **版本**：v1.0 · **最后更新**：2026-08-13  
> **维护者**：czj · **所属模块**：报告中心-功能测试

---

## 1. 背景与目标

### 1.1 背景

功能测试报告模块目前以固定样式生成 Word 报告和 Markdown 报告，所有样式参数（字体、字号、颜色、图表尺寸、DPI 等）以及报告章节均硬编码在 `backend/app/services/functional/config.py` 中。用户无法自定义：

- 报告包含哪些章节（如不需要"测试附件"或"附录"）
- 报告默认值（如测试负责人、测试环境等）
- Word 文档的字体、字号、标题颜色
- 图表的颜色、分辨率、尺寸

随着功能测试报告模块在多个项目中使用，不同的项目有不同的报告样式需求，硬编码方式已无法满足灵活配置的要求。

### 1.2 目标

在功能测试报告模块下新增**模板配置**子功能，实现：

```
多模板管理（增删改） → 自定义章节开关 / 样式 / 默认值 → 生成报告时选择模板套用
```

具体目标：

1. **多模板管理**：支持创建多个命名模板，每个模板包含完整的样式配置
2. **默认模板**：可设置一个模板为默认模板，生成报告时自动选中
3. **章节开关**：控制 Word/Markdown 报告中包含哪些章节（10 个章节可独立开关）
4. **Word 样式自定义**：字体、字号、标题颜色、首行缩进
5. **图表样式自定义**：DPI、图表尺寸、颜色方案、中文字体
6. **报告默认值自定义**：测试负责人、测试人员、测试环境等字段
7. **模板选择**：生成报告时从下拉列表中选择模板

### 1.3 参考实现

本功能参考现有 `ErpConfig` 模型的单表配置持久化模式（`backend/app/models/erp_config.py`），将配置存储为 JSON 字段，避免频繁改表结构。

---

## 2. 功能需求

### 2.1 功能清单

| 编号 | 功能 | 说明 | 优先级 |
|------|------|------|--------|
| T1 | 模板列表 | 查看所有模板，显示名称和默认标记 | P0 |
| T2 | 创建模板 | 新建模板，填写名称和完整配置 | P0 |
| T3 | 编辑模板 | 修改模板名称或配置 | P0 |
| T4 | 删除模板 | 删除模板（不允许删除最后一个） | P0 |
| T5 | 设为默认 | 选择一个模板作为默认模板（唯一） | P0 |
| T6 | 章节开关 | 控制 10 个报告章节的启用/禁用 | P0 |
| T7 | Word 样式配置 | 自定义字体、字号、标题颜色等 | P0 |
| T8 | 图表样式配置 | 自定义 DPI、尺寸、颜色方案 | P0 |
| T9 | 报告默认值配置 | 自定义测试负责人、环境等默认字段 | P0 |
| T10 | 生成报告时选择模板 | 生成报告表单中新增模板下拉选择器 | P0 |

### 2.2 功能详细说明

#### T1-T5. 模板 CRUD

- **模板列表**：左侧面板展示所有模板，每行显示模板名称和默认标记（星标/标签），支持设为默认、编辑、删除操作
- **创建模板**：点击"新建模板"，在右侧表单中填写名称和完整配置，保存后写入数据库
- **编辑模板**：选中已有模板，右侧表单加载配置，修改后保存
- **删除模板**：确认弹窗后删除，若只剩最后一个模板则禁止删除并提示
- **设为默认**：将指定模板设为默认，原默认模板自动取消默认标记，确保全局唯一

#### T6. 章节开关

提供 10 个开关，对应 Word/Markdown 报告中的 10 个章节：

| 章节标识 | 章节名称 | 默认值 |
|----------|----------|--------|
| `report_basic_info` | 报告基本信息 | 开启 |
| `execution_summary` | 测试执行摘要 | 开启 |
| `test_scope` | 测试范围 | 开启 |
| `case_details` | 测试用例执行详情 | 开启 |
| `bug_list` | BUG 详细列表 | 开启 |
| `chart_analysis` | 图表分析 | 开启 |
| `execution_records` | 测试执行记录 | 开启 |
| `attachments` | 测试附件 | 开启 |
| `risk_assessment` | 风险评估与建议 | 开启 |
| `appendix` | 附录 | 开启 |

关闭的章节在生成报告时跳过，不占用序号；剩余章节序号保持连续。

#### T7. Word 样式配置

| 配置项 | 说明 | 默认值 | 控件类型 |
|--------|------|--------|----------|
| 字体名称 | 正文字体 | 宋体 | 文本输入 |
| 正文字号 | 正文段落字号(pt) | 11 | 数字输入 |
| 一级标题字号 | 报告标题字号(pt) | 21 | 数字输入 |
| 二级标题字号 | 章节标题字号(pt) | 19 | 数字输入 |
| 三级标题字号 | 子章节标题字号(pt) | 17 | 数字输入 |
| 四级标题字号 | 小节标题字号(pt) | 15 | 数字输入 |
| 标题颜色 | 所有标题的字体颜色 | #000000 | 颜色选择器 |
| 首行缩进 | 段落首行缩进字符数 | 2 | 数字输入 |

#### T8. 图表样式配置

| 配置项 | 说明 | 默认值 | 控件类型 |
|--------|------|--------|----------|
| DPI | 图表分辨率 | 300 | 数字输入 |
| 图表宽度 | 图宽(英寸) | 10 | 数字输入 |
| 图表高度 | 图高(英寸) | 6 | 数字输入 |
| 中文字体 | 图表中文显示字体 | Microsoft YaHei | 文本输入 |
| 通过颜色 | 通过状态颜色 | #04AA6D | 颜色选择器 |
| 失败颜色 | 失败状态颜色 | #bb4069 | 颜色选择器 |
| 未验证颜色 | 未验证状态颜色 | #f0c040 | 颜色选择器 |
| 未开发颜色 | 未开发状态颜色 | #dcbdbd | 颜色选择器 |
| BUG 1级颜色 | 致命 BUG 颜色 | #d32f2f | 颜色选择器 |
| BUG 2级颜色 | 严重 BUG 颜色 | #f57c00 | 颜色选择器 |
| BUG 3级颜色 | 一般 BUG 颜色 | #fbc02d | 颜色选择器 |
| BUG 4级颜色 | 轻微 BUG 颜色 | #388e3c | 颜色选择器 |

#### T9. 报告默认值配置

| 配置项 | 说明 | 默认值 | 控件类型 |
|--------|------|--------|----------|
| 测试负责人 | 测试负责人姓名 | 未填写 | 文本输入 |
| 测试人员 | 测试人员姓名 | 未填写 | 文本输入 |
| 测试环境 | 测试环境描述 | 未填写 | 文本输入 |
| 系统版本 | 被测系统版本号 | 未填写 | 文本输入 |
| 服务器地址 | 服务器地址 | 未填写 | 文本输入 |
| 部署环境 | 部署环境说明 | 未填写 | 文本输入 |

#### T10. 生成报告时选择模板

- 在生成报告表单（步骤2：项目配置）中新增"报告模板"下拉选择器
- 下拉列表调用 `GET /templates` 接口加载所有模板，默认选中默认模板
- 用户选择模板后，生成请求中携带 `template_id`
- 后端根据模板配置生成报告，样式和章节动态匹配

---

## 3. 数据格式规范

### 3.1 模板配置 JSON Schema

```json
{
  "chapters": {
    "report_basic_info": true,
    "execution_summary": true,
    "test_scope": true,
    "case_details": true,
    "bug_list": true,
    "chart_analysis": true,
    "execution_records": true,
    "attachments": true,
    "risk_assessment": true,
    "appendix": true
  },
  "defaults": {
    "test_lead": "未填写",
    "tester": "未填写",
    "test_env": "未填写",
    "system_version": "未填写",
    "server_address": "未填写",
    "deployment_env": "未填写"
  },
  "word_style": {
    "font_name": "宋体",
    "font_size": 11,
    "title_level_1_size": 21,
    "title_level_2_size": 19,
    "title_level_3_size": 17,
    "title_level_4_size": 15,
    "paragraph_first_line_indent": 2,
    "title_color": "#000000"
  },
  "chart_style": {
    "dpi": 300,
    "figure_width": 10,
    "figure_height": 6,
    "chinese_font": "Microsoft YaHei",
    "colors": {
      "pass": "#04AA6D",
      "fail": "#bb4069",
      "unverified": "#f0c040",
      "undeveloped": "#dcbdbd",
      "bug_1": "#d32f2f",
      "bug_2": "#f57c00",
      "bug_3": "#fbc02d",
      "bug_4": "#388e3c"
    }
  }
}
```

### 3.2 模板数据表

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | Integer PK auto | 主键 |
| `name` | String(100) | 模板名称（如"默认模板"、"精简模板"） |
| `is_default` | Boolean | 是否默认模板（全局唯一为 True） |
| `config` | Text (JSON) | 完整配置 JSON 字符串 |
| `created_at` | DateTime | 创建时间 |
| `updated_at` | DateTime | 更新时间 |

---

## 4. 非功能需求

| 需求 | 说明 |
|------|------|
| 向后兼容 | 生成报告时未传 template_id，使用默认模板配置；无任何模板时使用硬编码默认值 |
| 数据完整性 | 删除模板时检查是否最后一个，不允许删除导致模板为空 |
| 配置校验 | 创建/更新模板时校验 config JSON 的完整性，缺失字段使用默认值填充 |
| 响应性能 | 模板列表 API 响应时间 < 100ms（数据量小，预计 < 50 条） |

---

## 5. 技术方案

### 5.1 架构图

```
┌──────────────────────────────────────────────────────────────────┐
│ 前端 (TemplateConfig.vue)                                        │
│  ┌──────────────┐  ┌───────────────────────────────────────────┐ │
│  │ 模板列表      │  │ 配置表单                                  │ │
│  │  ┌──────────┐│  │  - 基本信息（名称/默认）                   │ │
│  │  │ 模板 A ★ ││  │  - 章节开关 × 10                          │ │
│  │  │ 模板 B   ││  │  - Word 样式（字体/字号/颜色等）           │ │
│  │  │ 模板 C   ││  │  - 图表样式（DPI/尺寸/颜色方案）           │ │
│  │  └──────────┘│  │  - 报告默认值 × 6                         │ │
│  │  [+ 新建]    │  │  [保存]                                   │ │
│  └──────────────┘  └───────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
       │ GET/POST/PUT/DELETE /templates
       ▼
┌──────────────────────────────────────────────────────────────────┐
│ 后端 API (routers/report_template.py)                            │
│  GET    /templates          → 列表                              │
│  GET    /templates/{id}     → 详情                              │
│  POST   /templates          → 创建                              │
│  PUT    /templates/{id}     → 更新                              │
│  DELETE /templates/{id}     → 删除                              │
│  PUT    /templates/{id}/default → 设为默认                      │
└──────────────────────────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────────────────────────┐
│ 模型 (models/report_template.py) → report_templates 表           │
│                                                                    │
│ 配置工具 (services/functional/config.py)                           │
│  - get_default_config() → 返回硬编码默认值作为字典                │
│  - merge_template_config() → 合并模板配置与默认值                 │
└──────────────────────────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────────────────────────┐
│ 生成器改造 (接收 template_config 字典)                            │
│  - word_generator.py      → 章节开关 + Word 样式 + 默认值       │
│  - chart_generator.py     → 图表样式                             │
│  - markdown_generator.py  → 章节开关 + 默认值                    │
│  - functional_report_service.py → 加载模板配置并传递             │
└──────────────────────────────────────────────────────────────────┘
```

### 5.2 复用策略

- **配置持久化模式**：参考 `ErpConfig` 模型（单行表，JSON 字段存储完整配置）
- **生成器改造**：各生成器函数新增 `template_config: Optional[Dict]` 参数，非侵入式，不传则行为不变
- **章节跳过**：在每个章节生成前加 `if not chapters.get("xxx", True): continue`，序号根据已启用章节动态生成

---

## 6. 接口设计

### 6.1 API 接口

**前缀**：`/api/functional-report/templates`

| 方法 | 路径 | 请求体 | 响应 | 说明 |
|------|------|--------|------|------|
| GET | `/templates` | — | `[{id, name, is_default, updated_at}]` | 获取模板列表（不含 config 详情） |
| GET | `/templates/{id}` | — | `{id, name, is_default, config, created_at, updated_at}` | 获取单个模板完整信息 |
| POST | `/templates` | `{name, config}` | `{id, name, is_default, config, ...}` | 创建模板 |
| PUT | `/templates/{id}` | `{name?, config?, is_default?}` | `{id, name, is_default, config, ...}` | 更新模板 |
| DELETE | `/templates/{id}` | — | `{success: true}` | 删除模板（最后一个禁止删除） |
| PUT | `/templates/{id}/default` | — | `{id, name, is_default, config, ...}` | 设为默认模板（原默认自动取消） |

**生成报告请求扩展**：

| 方法 | 路径 | 新增字段 | 说明 |
|------|------|----------|------|
| POST | `/api/functional-report/generate` | `template_id: Optional[int]` | 选择模板 ID，为空则使用默认模板或硬编码默认值 |

### 6.2 前端路由

| 路径 | 组件 | 说明 |
|------|------|------|
| `/reports/functional/template-config` | `TemplateConfig.vue` | 模板配置管理页面 |

---

## 7. 依赖清单

| 依赖 | 说明 | 类型 |
|------|------|------|
| `backend/app/models/report_template.py` | 新增 ORM 模型 | 新增 |
| `backend/app/schemas/report_template.py` | 新增 Pydantic 校验 | 新增 |
| `backend/app/routers/report_template.py` | 新增 API 路由 | 新增 |
| `backend/app/services/functional/config.py` | 修改：新增配置工具函数 | 修改 |
| `backend/app/services/functional/word_generator.py` | 修改：支持 template_config | 修改 |
| `backend/app/services/functional/chart_generator.py` | 修改：支持 chart_style 配置 | 修改 |
| `backend/app/services/functional/markdown_generator.py` | 修改：支持 template_config | 修改 |
| `backend/app/services/functional_report_service.py` | 修改：加载模板配置并传递 | 修改 |
| `backend/app/routers/functional_report.py` | 修改：generate 端点传入 template_id | 修改 |
| `backend/app/schemas/functional_report.py` | 修改：GenerateRequest 新增 template_id | 修改 |
| `backend/app/main.py` | 修改：注册 report_template 路由 | 修改 |
| `backend/app/models/__init__.py` | 修改：导入 ReportTemplate | 修改 |
| `frontend/src/api/reportTemplate.ts` | 新增 API 封装 | 新增 |
| `frontend/src/views/functional-report/TemplateConfig.vue` | 新增页面组件 | 新增 |
| `frontend/src/views/functional-report/FunctionalReport.vue` | 修改：新增模板下拉选择 | 修改 |
| `frontend/src/router/index.ts` | 修改：新增 template-config 子路由 | 修改 |
| `frontend/src/App.vue` | 修改：新增菜单项 + 标签映射 | 修改 |

---

## 8. 风险与应对

| 风险 | 影响 | 概率 | 应对 |
|------|------|------|------|
| 模板配置与生成器耦合紧密 | 改造成本高 | 中 | 采用非侵入式参数设计，不传参则行为不变 |
| 章节开关导致序号不连续 | 报告可读性降低 | 低 | 动态编号，只对启用章节分配序号 |
| 图表颜色配置与现有颜色不兼容 | 图表风格不一致 | 低 | 用户可自定义，默认值与现有硬编码一致 |
| 删除模板导致数据丢失 | 用户误操作 | 低 | 确认弹窗 + 禁止删除最后一条 |