# 问题处理：性能测试项目类型 Tab 过滤不生效

> 生成时间：2026-08-21
> 关联文档：`_PRD_性能测试项目管理与批量执行.md`、`HANDOFF_性能测试.md`

---

## 问题描述

在 5.60 服务器的测试管理平台上，性能测试项目管理页面的「标准版」和「项目定制」两个 Tab 页切换后，**显示的内容完全相同**，都只显示标准版的项目（或全部项目混在一起），没有按项目类型进行过滤。

## 复现步骤

1. 登录 5.60 测试管理平台
2. 进入「性能测试」→「项目管理」
3. 默认 Tab 为「标准版」，显示若干项目卡片
4. 点击「项目定制」Tab
5. 观察：页面仍然显示标准版的项目（或全部项目），与「标准版」Tab 下内容无区别

## 当前行为

两个 Tab 页显示相同内容，项目类型过滤不生效。

## 预期行为

- 切到「标准版」Tab：只显示 `project_type = 'standard'` 的项目
- 切到「项目定制」Tab：只显示 `project_type = 'custom'` 的项目

---

## 根因分析

### 调用链回溯

```
Projects.vue:172
    ↓ 发送 params = { page: 1, pageSize: 200, projectType: "standard" }
    ↓
performance.ts:187  →  request.get('/api/performance/projects', { params })
    ↓ Axios 默认序列化，参数名原样发送
    ↓
GET /api/performance/projects?page=1&pageSize=200&projectType=standard
    ↓
performance.py:408  →  project_type: Optional[str] = Query(None)
    ↓ 参数名不匹配，project_type = None
    ↓
performance_service.py:980  →  if project_type:
    ↓ project_type 为 None，条件不成立，跳过过滤
    ↓
返回全部项目（不区分类型）
```

### 根本原因

| 环节 | 文件 | 代码 | 参数名 |
|------|------|------|--------|
| 前端 Tab 切换 | `Projects.vue:140` | `projectType = ref('standard')` | `projectType`（驼峰） |
| 前端 API 调用 | `Projects.vue:172` | `listProjects({ projectType: projectType.value })` | `projectType`（驼峰） |
| API 定义 | `performance.ts:183-186` | 参数类型声明为 `projectType?` | `projectType`（驼峰） |
| Axios 序列化 | `request.ts` | 无自定义 `paramsSerializer` | 参数名原样发送 |
| 后端路由 | `performance.py:408` | Query 参数名 `project_type` | `project_type`（蛇形） |
| 后端服务 | `performance_service.py:980` | `if project_type:` | `project_type` 始终为 `None` |

**核心矛盾**：与之前修复的 `listTasks` 项目过滤问题**完全相同的根因**——前端使用 JavaScript 驼峰命名 `projectType`，后端 FastAPI 使用 Python 蛇形命名 `project_type`。Axios 默认序列化参数名时不做转换，导致后端无法匹配到参数。

### 为什么跟之前 listTasks 是同一个坑？

| 函数 | 前端参数 | 后端参数 | 当前状态 |
|------|---------|---------|---------|
| `listTasks` | `projectId` | `project_id` | ✅ 已修复（`Docs/PRD/性能测试/问题处理/_执行计划_修复项目内任务过滤不生效.md`） |
| `listProjects` | `projectType` | `project_type` | ❌ 未修复（本文档） |

---

## 修复方案

### 方案：前端 API 层映射（推荐，与 listTasks 修复模式一致）

在 `frontend/src/api/performance.ts` 的 `listProjects` 函数中，将 `projectType` 显式映射为 `project_type`：

```typescript
export function listProjects(params?: {
  page?: number
  pageSize?: number
  projectType?: string
}): Promise<PerformanceProjectListResponse> {
  const queryParams: Record<string, any> = { ...params }
  // 将 camelCase 的 projectType 映射为 snake_case 的 project_type
  if (params?.projectType !== undefined) {
    queryParams.project_type = params.projectType
    delete queryParams.projectType
  }
  return request.get(`${BASE}/projects`, { params: queryParams })
}
```

---

## 影响范围

| 影响 | 说明 |
|------|------|
| `frontend/src/api/performance.ts` | `listProjects` 函数，需增加参数映射逻辑 |
| 后端 | 无需改动 |
| 其他前端文件 | 无需改动（`Projects.vue` 的传参方式不变） |
| 其他模块 | 无影响 |

## 验证方法

修复后执行以下验证：

1. **本地验证**：启动前端 + 后端，在浏览器中进入项目管理页 → 切换「标准版」Tab → 确认只显示 standard 项目；切换「项目定制」Tab → 确认只显示 custom 项目
2. **网络请求验证**：浏览器 DevTools → Network → 查看 `GET /api/performance/projects` 请求 URL 应为 `?page=1&pageSize=200&project_type=standard` 或 `project_type=custom`
3. **边界验证**：`projectType` 不传 → 应不传 `project_type` 参数（返回全部）

---

*本文档由 Claude Code 生成*