# PRD - 性能测试 API 接口预设功能

> **文档版本**: v1.0
> **创建日期**: 2026-08-13
> **关联模块**: 性能测试
> **优先级**: P0
> **关联需求**: `Docs/PRD/性能测试/需求文档/_PRD_性能测试模块需求文档.md`

---

## 一、背景与目标

### 1.1 背景

当前性能测试模块创建任务时，用户需要手动填写以下字段：

- HTTP 方法（GET/POST/PUT/DELETE）
- 目标 URL（完整路径）
- 请求头（JSON 格式）
- 请求体（JSON 格式）
- 请求体模板（bodyTemplate，带占位符）
- 响应捕获规则
- 认证配置（是否需要登录、签名）

这些字段对于同一个 API 接口是固定的，每次新建任务都重复填写既繁琐又容易出错。用户希望将"接口配置"抽象为可复用的**预设**，创建任务时只需选择预设即可自动填充，降低使用门槛。

### 1.2 目标

1. **接口预设管理**：支持用户在界面上增删改查 API 接口预设（方法、URL、请求头、请求体、模板、捕获规则等）
2. **预设选择创建任务**：创建压测任务时，通过下拉框选择预设，选定后自动填充并隐藏接口细节，用户只需配压测参数
3. **保持向后兼容**：已有任务（无预设）不受影响，仍可手动编辑

---

## 二、功能范围

### 2.1 核心功能

| 功能 | 描述 | 优先级 |
|------|------|--------|
| 接口预设 CRUD | 创建/编辑/删除/查询接口预设 | P0 |
| 预设选择创建任务 | 任务创建表单增加预设下拉框 | P0 |
| 预设继承 | 选定预设后自动填充接口字段并隐藏 | P0 |
| 预设列表页 | 独立页面管理所有预设 | P1 |
| 预设导入/导出 | 预设配置的 JSON 导入导出 | P2 |

### 2.2 预设包含的字段

| 字段 | 类型 | 说明 |
|------|------|------|
| 名称 | string | 预设名称，如"新建会议V3" |
| 描述 | string | 可选，说明用途 |
| HTTP 方法 | string | GET/POST/PUT/DELETE |
| 目标 URL | string | 接口完整 URL（含协议和域名） |
| 请求头 | JSON | 自定义请求头，如 Content-Type |
| 请求体 | JSON | 静态请求体（与 bodyTemplate 互斥） |
| 请求体模板 | JSON | 带 `{__XXX__}` 占位符的模板 |
| 响应捕获规则 | array | 捕获响应字段的规则列表 |
| 是否需要登录 | bool | 是否自动获取 Token |
| 是否需要签名 | bool | 是否生成 X-RANDOM/X-TIMESTAMP/X-SIGN |
| 使用账号 | string | 登录使用的账号 key |

---

## 三、详细需求

### 3.1 数据模型

#### 3.1.1 ApiPreset 模型

```python
class ApiPreset(Base):
    """API 接口预设"""
    __tablename__ = "api_presets"

    id: str          # 唯一标识 (preset_xxx)
    name: str        # 预设名称，如"新建会议V3"
    description: str # 描述

    # 接口配置
    method: str                    # HTTP 方法
    target_url: str                # 目标 URL
    headers: dict                  # 请求头
    body: Optional[dict|list]      # 静态请求体（与 body_template 互斥）
    body_template: Optional[dict]  # 请求体模板（支持变量替换）

    # 认证配置
    auth_required: bool            # 是否需要登录 Token
    sign_request: bool             # 是否需要签名
    account_key: Optional[str]     # 使用账号

    # 响应捕获
    capture_rules: Optional[list]  # 捕获规则列表

    created_at: datetime
    updated_at: datetime
```

#### 3.1.2 PerformanceTask 模型扩展

`PerformanceTask` 新增字段 `preset_id`，记录创建时使用的预设（可选，向后兼容）：

```python
preset_id: Optional[str]  # 关联的预设 ID，可为空
```

### 3.2 API 接口

#### 3.2.1 预设管理 API

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/performance/presets` | 获取预设列表（分页） |
| POST | `/api/performance/presets` | 创建预设 |
| GET | `/api/performance/presets/{id}` | 获取预设详情 |
| PUT | `/api/performance/presets/{id}` | 更新预设 |
| DELETE | `/api/performance/presets/{id}` | 删除预设 |

#### 3.2.2 任务创建 API 扩展

`POST /api/performance/tasks` 新增可选字段 `preset_id`。

当 `preset_id` 传入时，后端自动从预设继承接口配置（method、target_url、headers、body、body_template、capture_rules、auth_required、sign_request、account_key），前端传的对应字段可覆盖预设值。

### 3.3 前端变更

#### 3.3.1 预设管理页面

- 独立页面 `/performance/presets`，列表展示所有预设
- 每行显示：名称、方法、URL 摘要、更新时间
- 操作：编辑、删除
- 新建/编辑对话框：
  - 名称（必填）
  - 描述（可选）
  - HTTP 方法（下拉选择 GET/POST/PUT/DELETE）
  - 目标 URL（必填）
  - 请求头（JSON 文本域）
  - 请求体 / 请求体模板（互斥，radio 切换，JSON 文本域）
  - 响应捕获规则（表格增删改，同 bodyTemplate PRD 设计）
  - 认证开关（是否需要登录 + 签名 + 账号选择）

#### 3.3.2 任务创建表单改造

**当前表单**：直接展示 HTTP 方法、目标 URL、请求头、请求体等字段

**改造后表单**：

1. 第一行：**预设下拉框**（可选，新增）
   - 选项：无预设 + 所有已定义的预设
   - 选择预设后，自动填充接口字段并**隐藏**这些字段
   - 切换预设自动更新

2. 常规压测参数保持不变：
   - 任务名称
   - 压测模式（并发/QPS/阶梯）
   - 并发数 / QPS / 阶梯配置
   - 时长、预热时间
   - 断言配置

3. 当选择"无预设"时，展示原有的全部接口字段（完全向后兼容）

#### 3.3.3 预设选择后的只读摘要

选择预设后，在表单中预设下拉框下方显示**只读摘要**，让用户看到当前使用的接口信息：

```
┌─ 接口预设: 新建会议V3 ─────────────────────┐
│ PUT https://192.168.5.44/meetingV3/api/message/book │
│ 需要登录 · 需要签名 · 响应捕获: message_ids     │
└──────────────────────────────────────────────┘
```

### 3.4 后端处理逻辑

#### 3.4.1 创建任务时的预设继承

```python
# performance_service.py
async def create_task(self, task_data: PerformanceTaskCreate):
    # 如果传入了 preset_id，从预设继承字段
    if task_data.preset_id:
        preset = await self.db.get(ApiPreset, task_data.preset_id)
        if not preset:
            raise HTTPException(404, "预设不存在")
        
        # 预设字段作为默认值，任务显式传入的字段覆盖
        resolved = {
            "method": task_data.method or preset.method,
            "target_url": task_data.target_url or preset.target_url,
            "headers": task_data.headers or preset.headers,
            "body": task_data.body if task_data.body is not None else preset.body,
            "body_template": task_data.body_template or preset.body_template,
            "capture_rules": task_data.capture_rules or preset.capture_rules,
            "auth_required": task_data.auth_required if task_data.auth_required is not None else preset.auth_required,
            "sign_request": task_data.sign_request if task_data.sign_request is not None else preset.sign_request,
            "account_key": task_data.account_key or preset.account_key,
        }
    else:
        resolved = task_data.dict(exclude={"preset_id"})
    
    # 创建任务...
```

#### 3.4.2 预设更新不影响已有任务

预设更新后，已创建的任务不受影响（任务存储的是当时的值，不是引用）。这是有意为之——历史压测任务的配置不应该被预设变更影响。

---

## 四、非功能需求

### 4.1 兼容性

- 已有任务（无 preset_id）完全不受影响，创建/编辑/执行逻辑不变
- 预设变更不影响已有历史任务

### 4.2 约束

- 预设名称唯一（同一用户不能有两个同名预设）
- 删除预设不影响已有任务（仅关联字段 `preset_id` 置空或保留引用）
- 预设删除时应有二次确认

---

## 五、应用场景示例

### 5.1 场景一：新建会议压测

1. 运维同学在预设管理页面创建"新建会议V3"预设：
   - 方法：PUT
   - URL：`https://192.168.5.44/meetingV3/api/message/book`
   - 请求体模板：`{"messageName": "{__RANDOM_NAME_8__}", ...}`
   - 捕获规则：`message_ids → $.data.messageId`
   - 需要登录 + 需要签名

2. 测试同学创建压测任务：
   - 选择预设："新建会议V3" → 自动填充，接口字段隐藏
   - 设置并发数：50，时长：60s
   - 点击执行 → 成功运行

### 5.2 场景二：已有预设更新

1. 接口发生变化（如 URL 路径调整），运维同学更新预设
2. 新建任务时使用更新后的预设，获取最新配置
3. 历史任务保持不变，不受影响

---

## 六、影响范围

### 6.1 新增文件

| 文件 | 说明 |
|------|------|
| `backend/app/models/api_preset.py` | API 预设数据库模型 |
| `backend/app/schemas/api_preset.py` | API 预设 Pydantic Schema |
| `backend/app/routers/api_preset.py` | API 预设 CRUD 路由 |
| `backend/app/services/api_preset_service.py` | API 预设业务逻辑 |
| `frontend/src/views/performance/ApiPresetList.vue` | 预设管理页面 |
| `frontend/src/views/performance/ApiPresetDialog.vue` | 预设编辑对话框 |

### 6.2 修改文件

| 文件 | 变更 |
|------|------|
| `backend/app/models/performance.py` | 新增 `preset_id` 字段 |
| `backend/app/schemas/performance.py` | 新增 `preset_id` 字段 |
| `backend/app/services/performance_service.py` | 创建任务时继承预设字段 |
| `backend/app/database.py` | 注册新表 + 补齐字段 |
| `backend/app/main.py` | 注册新路由 |
| `backend/app/models/__init__.py` | 导出新模型 |
| `frontend/src/views/performance/TaskList.vue` | 任务表单增加预设下拉框 |
| `frontend/src/api/performance.ts` | 新增预设 API 封装 |
| `frontend/src/types/performance.ts` | 新增预设类型 |
| `frontend/src/router/index.ts` | 新增预设管理路由 |

---

## 七、验收标准

| # | 验收项 | 验证方式 |
|---|--------|---------|
| 1 | 创建预设（方法/URL/请求头/请求体模板/认证配置） | 预设列表看到新条目 |
| 2 | 编辑预设 | 修改后保存，内容更新 |
| 3 | 删除预设 | 二次确认后删除，列表消失 |
| 4 | 创建任务时选择预设 | 接口字段自动填充，表单简洁 |
| 5 | 选择预设后隐藏接口字段 | 只显示摘要卡片 |
| 6 | 选择"无预设" | 显示全部接口字段（向后兼容） |
| 7 | 使用预设创建的任务正常执行 | 执行成功，结果正确 |
| 8 | 预设更新不影响历史任务 | 旧任务执行时仍用原配置 |

---

*本文档为接口预设功能的需求定义，后续将输出计划执行文档用于指导开发。*