# HANDOFF — 性能测试模块会话交接文档

> **生成时间**: 2026-08-24
> **当前分支**: `platform-auto-test`
> **最近提交**: `cf359994` feat(performance): WebSocket 批量进度订阅端点 + 项目详情实时进度条
> **会话窗口**: 性能测试 — 执行跳转闭环 + 执行历史；本次：登录压测响应验证 + 双 bug 修复部署
> **状态**: ✅ 执行跳转闭环与执行历史全链路已实现/验证/部署 5.60；本会话登录压测响应验证通过 + 修复 2 个 bug（outputs 500 / 僵尸 running 双条）已部署 5.60 + 清理 3 条僵尸记录

---

## ⚠️ 多窗口并行开发注意

参考 `Docs/多窗口并行开发指南.md`。

| 项目 | 本窗口（性能测试） | 其他窗口 |
|------|-------------------|----------|
| 后端端口 | 8001 | 视情况 |
| 前端端口 | 3000 | 视情况 |
| 开发模块 | 性能测试 | 其他模块 |
| 数据库 | 使用 `data/test_platform.db`，注意写入错开 | 同上 |

---

## ⚡ 最新会话更新（2026-08-24 晚）— 登录压测响应验证 + 双 bug 修复部署

### A. 会话背景

用户要求验证登录接口瞬时并发压测响应的正确性（是否有 response body、是否有 token），随后发现并修复了两个 bug。

### B. 登录压测响应验证结果 ✅

登录基准压测任务 `perf_0fbcb792dcc143fd80b42cb405a75176`（并发 200 Burst）执行后，通过捕获规则 `tokens ← $.data.access_token` 验证：

| 验证项 | 结果 |
|--------|------|
| 总请求数 | 4033（全部 2xx） |
| 捕获 token 数 | **4033 条唯一 JWT token**（捕获率 100%） |
| 无效格式 / 重复 | 0 / 0 |
| 结论 | 登录接口瞬时并发响应**全部正确，全部返回 token** ✅ |

### C. Bug 1：捕获输出查询 500（MySQL 排序爆内存）— 已修复部署 ✅

- **现象**：`GET /api/performance/outputs?task_id=...` 与 `GET /api/performance/tasks/{id}/outputs` 返回 500，日志 `pymysql.err.OperationalError: (1038, 'Out of sort memory, consider increasing server sort buffer size')`
- **根因**：单行 `value` 列 1.28MB（4033 个 JWT token JSON 数组），`ORDER BY` 触发 MySQL filesort 将整行载入 sort buffer，行宽超限爆 buffer；SQLite 本地不校验所以从未复现
- **修复**（`backend/app/routers/performance_output.py`）：`list_outputs()` / `get_task_outputs()` 改**两段式查询**——先只 SELECT `id` 轻量排序分页，再按 `id.in_(ids)` 回查整行还原顺序（排序成本与行宽解耦）
- **文档**：`Docs/PRD/性能测试/问题处理/_问题处理_捕获输出查询500与大JSON列排序爆内存.md` + `_执行计划_修复捕获输出查询500与大JSON列排序.md`
- **部署验证**：5.60 上传重启后两个接口均 **200**，`tokens` 4033 条完整返回

### D. Bug 2：执行记录双条（僵尸 running）— 已修复部署 ✅

- **现象**：任务执行后同一时刻产生两条执行记录——API 返回的 `executionId` 永远是 `running`/0 请求的僵尸（无人更新），真实数据落在另一条 `completed` 记录上，前端跳监控页无数据
- **根因**：`run_task_async()` 创建执行记录 A 并返回 id；后台 `_run_single_background()` 调用 `run_task()` 时未传该 id，`run_task()` 内部硬生成 `exec_xxx` 创建记录 B。A 无人更新永远 running
- **修复**（`backend/app/services/performance_service.py`）：
  - `run_task()` 新增可选参数 `execution_id: Optional[str] = None`——传入则复用已有记录（刷新 status/start_time），不传则照旧生成新记录（兼容 batch/单测调用）
  - `_run_single_background()` 透传 `execution_id=execution_id`
- **文档**：`Docs/PRD/性能测试/问题处理/_问题处理_执行记录双条僵尸running记录.md` + `_执行计划_修复执行记录双条僵尸running.md`
- **部署验证**：5.60 上传重启后重跑任务，API 返回的 `exec_54309f7e...` 执行结束后**同一条**变 `completed`（4193 请求 / TPS 29.18），无第二条记录 ✅

### E. 数据清理（5.60 MySQL 存量僵尸记录）

删除 3 条后匹配的僵尸 running 记录（任务已 completed 但执行记录卡 running，total=0）：

| 僵尸执行记录 ID | 任务 |
|------------------|------|
| `exec_2f77a492d3c04648b8420ea1f8a6dad7` | perf_4fb439c7（Burst-200） |
| `exec_4e4eb234101b42a4a216df44f6705ba8` | perf_0fbcb792（登录基准） |
| `exec_bff3140c4e8c4fe98ea1abbae33d7d0a` | perf_4fb439c7（Burst-200） |

清理后 `GET /api/performance/executions?task_id=...` 每种任务仅剩 completed 记录。

### F. 本次修改文件清单

| 文件 | 修改内容 |
|------|---------|
| `backend/app/routers/performance_output.py` | `list_outputs` / `get_task_outputs` 两段式查询（Bug 1 修复） |
| `backend/app/services/performance_service.py` | `run_task()` +`execution_id` 复用参数；`_run_single_background()` 透传（Bug 2 修复） |
| `Docs/PRD/性能测试/问题处理/_问题处理_捕获输出查询500与大JSON列排序爆内存.md` | 新增问题处理文档 |
| `Docs/PRD/性能测试/问题处理/_执行计划_修复捕获输出查询500与大JSON列排序.md` | 新增执行计划文档 |
| `Docs/PRD/性能测试/问题处理/_问题处理_执行记录双条僵尸running记录.md` | 新增问题处理文档 |
| `Docs/PRD/性能测试/问题处理/_执行计划_修复执行记录双条僵尸running.md` | 新增执行计划文档 |

> ⚠️ **以上改动均未 git commit/push！** 下次窗口请先提交（可用 `/GitCommit`，建议分两个 commit：docs 文档 1 个、代码修复 1 个）。

### G. 本次会话待办（交接给下一窗口）

| # | 任务 | 说明 |
|---|------|------|
| 1 | **git commit + push** | `performance_output.py` + `performance_service.py` + 4 份问题处理/执行计划文档，用 `/GitCommit` |
| 2 | 端到端回归（可选） | 前端监控页/报告页按 API 返回 executionId 正常跳转回放，历史下拉无僵尸条目 |
| 3 | 收获新教训 | 补进 CLAUDE.md 踩坑表：①含 JSON 大列的表 ORDER BY 必须两段式（id 轻量排序 + 回查整行）；②前台建记录返回 id + 后台另起会话执行时，后台必须透传 id 复用，否则必然双条（已有独立文档，可择机提炼） |

---

## ⚡ 最新会话更新（2026-08-24）— 执行跳转闭环 + 执行历史

### A. 功能背景

PRD `_PRD_执行跳转闭环与执行历史.md`（→ 计划 `_PRD_执行跳转闭环与执行历史_计划执行.md`，9 个 Phase）解决两个痛点：
- **(问题A) 执行瞬时并发**: 启动任务 → 不自动跳转执行监控页；执行完成 → 不自动跳转报告页；
- **(问题B) 监控/报告只见最新**: 执行监控与报告模块只能选任务看最新一份，过往执行监控数据与报告无法查看。

### B. 已完成 ✅（9 阶段全部实施，2026-08-24 已部署 5.60）

| Phase | 内容 | 状态 |
|-------|------|------|
| 1 | 后端模型：新建 `performance_executions` 表（`PerformanceExecution`），`performance_snapshots` 加 `execution_id`（FK ondelete=SET NULL） | ✅ |
| 2 | Schema：`PerformanceExecutionCreate/Response`、`Snapshot` 加 execution_id | ✅ |
| 3 | 服务：`run_task_async()` 创建执行记录 + 回填快照 + `list_executions`/`get_execution_report` 聚合 | ✅ |
| 4 | 路由：`/api/performance/executions` CRUD + 快照查询 + 历史报告聚合端点 | ✅ |
| 5 | 前端类型 + API 封装（`frontend/src/api/performance.ts`、`types/performance.ts`） | ✅ |
| 6-8 | MonitorPanel/ReportPanel/ProjectDetail 三组件改造：历史执行下拉切换 + 实时/回放双模式 + 执行后自动跳报告 | ✅ |
| 9 | `database.py` 迁移 `performance_snapshots.execution_id` + `init_db()` 启动回填 `_migrate_legacy_executions()`（幂等） | ✅ |

**关键实现细节**：
- MonitorPanel 双模式：`isReplayMode`（`!!executionId && !isRunning`）/ `isLiveMode`（`!!executionId && isRunning`）；WS 无数据时走 `getExecutionSnapshots` 回放
- ReportPanel 执行记录下拉切换 `executionOptions`，`loadReport()` 按 `executionId` 分支 `getExecutionReport()` vs `getReport(taskId)`
- 前端 request util 直接返回 data（用 `res.items` 而非 `res.data.items`）
- 队列执行 `run_task_async()` 非阻塞：立即返回 `execution_id`，后台 `asyncio.create_task()`

### C. 已验证 ✅

| 验证项 | 结果 |
|--------|------|
| 本地 `init_db()` 独立运行（模型导入修复后） | ✅ 通过 |
| 前端类型检查 `npx vue-tsc --noEmit` | ✅ 通过 |
| 前端构建 `npm run build` | ✅ 通过 |
| 本地 SQLite 回填：快照 151 条关联 execution_id，6 条 legacy 执行记录 | ✅ |
| **5.60 MySQL 部署回填**：迁移 6 条 legacy 执行记录（`performance_executions`），快照 723/4/403/930/62 条关联 | ✅（启动日志确认） |

### D. 本次修改文件清单

| 文件 | 修改内容 |
|------|---------|
| `backend/app/models/performance.py` | 新增 `PerformanceExecution` 模型 |
| `backend/app/models/performance_output.py` | （含 `performance_snapshots` 模型定义） |
| `backend/app/schemas/performance.py` | execution 相关 Schema |
| `backend/app/services/performance_service.py` | `run_task_async`/`list_executions`/`get_execution_report`/`_migrate_legacy_executions`（+564 行） |
| `backend/app/routers/performance.py` | `/executions` 端点（+174 行） |
| `backend/app/executors/performance_executor.py` | 快照 execution_id 关联等 |
| `backend/app/database.py` | `_ensure_columns` 迁移 + `init_db()` 回填触发 |
| `frontend/src/types/performance.ts` | `TargetResourceData.host?` 可选字段 |
| `frontend/src/views/performance/MonitorPanel.vue` | 历史执行切换 + 实时/回放双模式 |
| `frontend/src/views/performance/ReportPanel.vue` | 执行记录下拉 + 历史报告 |
| `frontend/src/views/performance/ProjectDetail.vue` | 项目详情入口 |
| 计划文档 | `_PRD_执行跳转闭环与执行历史_计划执行.md` 各 Phase 已标 ✅ |

> ⚠️ **本次大改了 5 个后端核心文件 + 3 个前端组件，尚未 git commit/push！** 下次窗口请先提交（可用 `/GitCommit`），再继续开发。

### E. 部署记录（5.60）

- 部署路径：`/data/third_party/plat-auto-test/`（V2 合一容器 + MySQL，见内存 [[v2-deployment-complete]]、[[server-60-ssh-access]]）
- 上传：`database.py` + `services/performance_service.py` + `models/performance.py` + `routers/performance.py` + `schemas/performance.py` + `executors/performance_executor.py` + 前端 `dist/*`
- 重启：`cd /data/third_party/plat-auto-test/deploy && docker compose restart app`
- 500 排查教训：**MySQL 是持久卷，代码是 volume 挂载** — `performance_service.py` 未上传只有 `database.py` 时，数据库列已加、回填因缺方法失败，重启后正常
- ⚠️ 注意：scp 多个目标路径时**不能混用目录/文件结尾**（会把文件平铺到 app/ 根目录误成 models/performance.py），已修正并清理误放文件

### F. 本次会话待办（交接给下一窗口）

| # | 任务 | 说明 |
|---|------|------|
| 1 | **git commit + push** | 5 个后端 + 3 个前端 + 计划文档标注，用 `/GitCommit` skill（Conventional Commits + Co-Authored-By 尾缀） |
| 2 | 端到端验证（可选） | 实际压测任务跑一遍：启动跳监控 → 完成跳报告 → 历史执行下拉回放 |
| 3 | 验收门禁标记 | 计划文档"六、验收门禁"清单打勾 |

---

## ⚡ 最新会话更新（2026-08-13 晚）

### A. API 接口预设功能 — 已完成 ✅

**实现内容**（提交 `7c1c0488`，已部署至 5.60）：

| 组件 | 文件 | 说明 |
|------|------|------|
| 模型 | `backend/app/models/api_preset.py` | `ApiPreset` 表：name/method/target_url/headers/body/body_template/auth_required/sign_request/account_key/capture_rules |
| Schema | `backend/app/schemas/api_preset.py` | `CaptureRule`（`json_path` snake_case 字段，无 to_camel） |
| 路由 | `backend/app/routers/performance.py` | `POST/GET/PUT/DELETE /api/performance/presets` |
| 服务 | `backend/app/services/api_preset_service.py` | 预设 CRUD + capture_rules 嵌套更新 |
| 继承 | `backend/app/services/performance_service.py` `_inherit_from_preset()` | 任务传 `preset_id` 时合并预设字段（仅补空，不覆盖） |
| 前端 | 预设管理页 + 任务表单预设下拉 | 选预设自动继承 method/url/headers/body/bodyTemplate/captureRules/auth/sign |

**部署脚本**：`deploy_perf_preset.py`（git pull → 上传前端 dist → restart app → 校验迁移字段 `performance_tasks.preset_id`）。

> ⚠️ **数据库现状**：服务器（5.60 MySQL）当前已重置/切换，旧 HANDOFF 记录的 `perf_f27debe671d84b4fb3908af5beac67ed`（新建会议接口压测，1046 请求）**已不在服务器上**。现存仅 2 个任务（见 6.2）。

### B. 「新建会议V3」接口预设 — 已创建 ✅

| 字段 | 值 |
|------|-----|
| ID | `preset_e62140d37c29431284a2bad8fb67528c` |
| method | `PUT` |
| target_url | `https://192.168.5.44/meetingV3/api/message/book` |
| auth_required | `true` |
| sign_request | `true`（创建后补 PUT/签名） |
| account_key | `superadmin` |

### C. 「新建会议压测」任务 — 已创建（pending）⏳

| 字段 | 值 |
|------|-----|
| ID | `perf_5a1a3b4e00e04b2f96713f4108580d2b` |
| preset_id | 继承「新建会议V3」 |
| 模式 | 并发 1 · 持续 15s · ramp_up 0 |
| bodyTemplate | `messageName={__RANDOM_NAME_8__}` / `startTime={__NOW__}` / `endTime={__NOW_+2_H__}` / `topicList={__RANDOM_NAME_4__}` |
| captureRules | `message_ids` ← `$.data.messageId`（multiple=true） |
| 状态 | `pending`（**尚未执行**，待验证 bodyTemplate 是否解决重复创建会议的 4xx 问题） |

> **关键修复点**：上次压测 1045/1046 因 body 硬编码重复创建会议返回 4xx。本次用 bodyTemplate 随机化 messageName/topicName + 动态时间，且签名基于解析后的 body。**执行后需重点核对 4xx 是否归零、message_ids 是否被成功捕获**。

### D. 账号映射（已确认）

实际压测登录固定用 **admin@xty / Ubains@13579**（验证码 csba），来自 `_DEFAULT_ACCOUNTS`（superadmin/admin/user 三档全部映射到同一账号），**与预设/任务的 `account_key` 取值无关**。用户已确认此行为正常。

### E. 本次会话待办（交接给下一窗口）

| # | 任务 | 说明 |
|---|------|------|
| 1 | **执行 `perf_5a1a3b4e00e04b2f96713f4108580d2b`** | 验证 bodyTemplate 动态替换 + sign 是否解决 4xx；检查 `message_ids` 捕获 |
| 2 | 若 4xx 仍存在 | 排查 body 结构（PRD 示例 vs 实际接口字段）、签名 body 内容、token 有效性 |
| 3 | 配置断言 | 当前 `assertions=[]`，4xx 会被算"成功"（无断言），建议加 `status_code equals 200` |
| 4 | 创建「修改会议」「取消会议」压测任务 | 取消会议用 `{__REF:perf_5a1a3b4e00e04b2f96713f4108580d2b:message_ids__}` 引用 |

---

## 一、历史任务与完成情况

### 1.1 核心任务：新建会议 API 性能测试

**用户需求**：对被测系统（https://192.168.5.44）的"新建会议"接口进行性能压测。

**接口信息**：
- `PUT https://192.168.5.44/meetingV3/api/message/book`
- 需要 `Authorization: Bearer {token}`
- 需要 `X-RANDOM/X-TIMESTAMP/X-SIGN` 签名头
- 请求体为 JSON **数组** `[{...}]`

**已完成**：
1. ✅ **修复 Pydantic schema body 类型**：`body: Optional[Dict[str, Any]]` → `Optional[Any]`，支持 JSON 数组（涉及 PerformanceTaskCreate、PerformanceTaskUpdate、PerformanceTaskResponse）
2. ✅ **修复执行器签名支持**：`_build_headers()` 原忽略 `sign_request` 字段，现当 `signRequest=True` 时自动调用 `_generate_sign()` 生成签名头
3. ✅ **创建并执行压测任务**：
   - 任务 ID：`perf_f27debe671d84b4fb3908af5beac67ed`
   - 并发 1 / 时长 15s / 预热 5s
   - 结果：1046 请求，1046 成功（但 1045 个 4xx，因 body 硬编码重复创建会议）

### 1.2 文档产出

| 文档 | 路径 | 说明 |
|------|------|------|
| PRD 需求文档 | `Docs/PRD/性能测试/需求文档/_PRD_bodyTemplate动态变量替换与响应捕获.md` | bodyTemplate 变量替换 + 响应捕获 + 跨任务引用 |
| 计划执行文档 | `Docs/PRD/性能测试/需求文档/_PRD_bodyTemplate动态变量替换与响应捕获_计划执行.md` | 6 个 Phase 详细执行计划 |
| 接口 Curl 记录 | `Docs/meeting_api_curls.md` | 新建/修改/取消会议三个 API 的 curl 原文 |

### 1.3 其他相关文件

| 文件 | 说明 |
|------|------|
| `backend/capture_meeting_api.py` | Playwright 脚本（已废弃，用户提供 curl 替代） |
| `backend/tmp_create_meeting_task.json` | 创建任务时使用的临时 JSON 文件 |

---

## 二、后端变更摘要

### 2.1 已修改文件（工作区未提交）

| 文件 | 修改内容 |
|------|---------|
| `backend/app/schemas/performance.py` | `body: Optional[Dict[str, Any]]` → `Optional[Any]`（3 处），增加 `description` 说明"支持 dict 或 list" |
| `backend/app/executors/performance_executor.py` | `_build_headers()` 新增 `sign_request=True` 时自动生成 X-RANDOM/X-TIMESTAMP/X-SIGN 签名头 |

### 2.2 关键代码位置

- **性能测试执行器**：`backend/app/executors/performance_executor.py`（817 行）
  - `_build_headers()` 约 470-507 行（含新加的 sign_request 逻辑）
  - `_send_request()` 约 739-790 行
  - `execute()` 入口约 509-549 行
- **性能测试 Schema**：`backend/app/schemas/performance.py`（271 行）
- **性能测试模型**：`backend/app/models/performance.py`（284 行）
- **签名算法**：`backend/app/executors/http_client.py` 约 179-230 行 `_generate_sign()`
- **性能测试路由**：`backend/app/routers/performance.py`（297 行）
- **性能测试服务**：`backend/app/services/performance_service.py`

### 2.3 服务启动信息

```bash
# 后端
cd backend && uvicorn app.main:app --reload --port 8001

# 前端
cd frontend && npm run dev
```

---

## 三、会议模块 API 信息

### 3.1 三个接口

| 接口 | 方法 | URL | 说明 |
|------|------|-----|------|
| 新建会议 | PUT | `/meetingV3/api/message/book` | 已完成压测 |
| 修改会议 | PUT | `/meetingV3/api/message/update` | 已记录 curl |
| 取消会议 | DELETE | `/meetingV3/api/message/cancel/{mid}` | 已记录 curl |

### 3.2 认证与签名要求

- **认证**：`Authorization: Bearer {token}`（通过 `authRequired=true` + `accountKey="superadmin"` 自动获取）
- **签名**：`X-RANDOM` + `X-TIMESTAMP` + `X-SIGN`（通过 `signRequest=true` 自动生成，AES-CBC 加密，密钥从 Bearer Token 派生）
- **请求体**：JSON 数组格式（已修复 Pydantic 类型限制，`body: Optional[Any]`）

### 3.3 curl 原文位置

`Docs/meeting_api_curls.md` 记录了三个接口的完整 curl 命令（含 Authorization 和签名头）。

---

## 四、已知问题与待办

### 4.1 已发现的问题

| # | 问题 | 影响 | 状态 |
|---|------|------|------|
| 1 | body 硬编码，请求数据重复 | 1045/1046 请求返回 4xx（重复创建会议） | ✅ **已解决**（bodyTemplate 动态变量，见最新会话更新 C） |
| 2 | 错误率统计依赖断言，非 HTTP 状态码 | 虽 4xx 但无断言→全部算成功 | 待配置断言后验证；或考虑改进统计逻辑 |
| 3 | `body_template` 字段已定义但执行器未使用 | 无法动态替换变量 | ✅ **已解决**（`template_resolver.py` 已实现，8 种占位符，执行器已集成） |
| 4 | 无 `capture_rules` 字段 | 无法捕获响应中的 messageId | ✅ **已解决**（模型/Schema/执行器 `_capture_response` 已实现） |

### 4.2 待办事项（按优先级）

| 优先级 | 任务 | 对应 Phase | 说明 |
|--------|------|-----------|------|
| ✅ 已完成 | 新增 PerformanceTaskOutput 模型 + capture_rules 字段 | Phase 1 | 模型/Schema 扩展 |
| ✅ 已完成 | 实现 TemplateResolver 解析器 | Phase 2 | 8 种占位符 |
| ✅ 已完成 | 执行器集成模板替换 + 响应捕获 | Phase 3 | `_send_request` + `_capture_response` |
| ✅ 已完成 | 服务/路由：输出保存 + 查询 API | Phase 4 | 跨任务引用（`{__REF:...__}`） |
| ✅ 已完成 | 前端 UI：预设管理 + 任务表单继承 | — | 接口预设功能（`7c1c0488`） |
| P0 | **执行新建会议压测任务，验证全链路** | Phase 6 | `perf_5a1a3b4e00e04b2f96713f4108580d2b`，确认 4xx 归零 + messageIds 捕获 |
| P1 | 集成验证：新建→取消会议全链路 | Phase 6 | 取消会议任务用 REF 引用 message_ids |
| P1 | 改进错误率统计（HTTP 状态码维度） | — | 当前仅依赖断言，4xx 无断言会误判成功 |

### 4.3 实施建议

**Phase 1 实现要点**：
- 新建 `models/performance_output.py`，`PerformanceTaskOutput` 表含 `(task_id, key, value, created_at)`，唯一约束 `(task_id, key)`
- 新建 `schemas/performance_output.py`，定义 `CaptureRule` Schema
- `PerformanceTaskCreate` 增加 `capture_rules: Optional[List[CaptureRule]]` 和 `body_template: Optional[Dict[str, Any]]`（后者已有）
- 注册新表到 `database.py`

**Phase 2 实现要点**：
- 新建 `executors/template_resolver.py`，`TemplateResolver` 类
- 正则 `r"\{__([A-Z_+\d:]+?)__\}"` 匹配占位符
- 支持 `NOW` / `NOW_+N_H` / `NOW_+N_M` / `RANDOM_NAME_N` / `UUID` / `RANDOM_INT_N_M` / `INDEX` / `REF:task_id:key`
- 不修改原模板，返回新容器

**Phase 3 实现要点**：
- `_send_request` 中先 `_resolve_body` 再签名
- `_build_headers` 接受 `body_for_sign` 参数
- 每次响应后按 `capture_rules` 提取字段
- `_worker` 循环传递 `request_index`

---

## 五、关键决策记录

| 日期 | 决策 | 理由 |
|------|------|------|
| 2026-08-13 | 使用用户提供的 curl 替代 Playwright 抓包 | 用户明确要求："或者我把请求给你 请求的curl给你" |
| 2026-08-13 | body 类型改为 `Optional[Any]` 而非新增 `ListBody` | 减少 Schema 复杂度，SQLAlchemy JSON 列和 aiohttp 原生支持 list |
| 2026-08-13 | sign_request 独立于 auth_required | 登录接口签名用空 token，业务接口签名用真实 token，两个开关独立控制 |
| 2026-08-13 | 选择 bodyTemplate 方案而非动态脚本 | 配置化，无需写代码，前端可编辑 |
| 2026-08-13 晚 | 引入「接口预设」抽象 | 重复接口配置（method/url/auth/sign/body）固化为预设，任务继承 + 增量覆盖，避免每次重填 |
| 2026-08-13 晚 | `_DEFAULT_ACCOUNTS` 三档全部映射到 admin@xty | 测试环境仅有单一管理员账号，superadmin/admin/user 统一映射，与预设 account_key 取值解耦 |
| 2026-08-13 晚 | 新建会议压测任务传 `preset_id` 继承 + 显式 `target_url` | schema 把 `target_url` 列为必填，即便 preset_id 继承也必须显式传（校验在前，继承在后） |
| 2026-08-13 晚 | `capture_rules` 用 snake_case `json_path` | 嵌套 `CaptureRule`（`performance_output.py`）未挂 `to_camel`，顶层任务 schema 虽用 camelCase 别名，但嵌套字段名必须原样 `json_path` |

---

## 六、会话资源

### 6.1 参考文档

| 文档 | 路径 |
|------|------|
| 性能测试 PRD | `Docs/PRD/性能测试/需求文档/_PRD_性能测试模块需求文档.md` |
| 性能测试计划执行 | `Docs/PRD/性能测试/需求文档/_PRD_性能测试模块_计划执行.md` |
| bodyTemplate PRD | `Docs/PRD/性能测试/需求文档/_PRD_bodyTemplate动态变量替换与响应捕获.md` |
| bodyTemplate 计划执行 | `Docs/PRD/性能测试/需求文档/_PRD_bodyTemplate动态变量替换与响应捕获_计划执行.md` |
| 会议 API Curl | `Docs/meeting_api_curls.md` |
| CLAUDE.md | `CLAUDE.md`（项目全局约束、踩坑记录） |

### 6.2 已创建的性能测试任务（5.60 服务器实际现状）

> 服务器 MySQL 库已重置/切换，旧任务 `perf_f27debe671d84b4fb3908af5beac67ed`（1046 请求）已不存在。当前现存：

| 任务 ID | 名称 | 状态 | 说明 |
|---------|------|------|------|
| `perf_5a1a3b4e00e04b2f96713f4108580d2b` | 新建会议压测 | `completed` | 已执行验证，1171 请求 / TPS 80.86 |
| `perf_0fbcb792dcc143fd80b42cb405a75176` | 登录接口性能基准测试 | completed | 4193 请求 / TPS 29.18（本会话重跑验证单执行记录） |
| `perf_4fb439c759a94f54b3c64829714564fa` | 登录接口瞬时并发压测(Burst-200用户-CSV多账号) | completed | 200 请求 / TPS 24.64 |
| `perf_ecbd92aae3b845ab9bd651ca49ca111e` | 会议模板新增 | completed | 1984 请求 / TPS 16.14 |
| `perf_82d72c5c17f94f9ebba1f899b41bc018` | 会议模板列表查询 | completed | 2776 请求 / TPS 22.54 |
| `perf_fb2bafb6ce874927861af023ec8823dd` | 会议列表查询 | completed | 15042 请求 / TPS 240.29 |

### 6.3 已创建的接口预设

| 预设 ID | 名称 | 方法/URL | 说明 |
|---------|------|----------|------|
| `preset_e62140d37c29431284a2bad8fb67528c` | 新建会议V3 | `PUT https://192.168.5.44/meetingV3/api/message/book` | auth+sign，被「新建会议压测」任务继承 |

### 6.4 用户提到的后续需求

1. ~~实现 bodyTemplate 变量替换 + 响应捕获~~ ✅ 已完成
2. 创建修改会议、取消会议的性能测试任务 ⏳ 待做
3. 取消会议引用新建会议产出的 messageId ⏳ 待做（`{__REF:perf_5a1a3b4e00e04b2f96713f4108580d2b:message_ids__}`）

---

*本 HANDOFF 文档由 Claude Code 自动生成，用于会话间交接。*