# 模块筛选器显示安全测试模块 计划执行文档

> **文档版本**: v1.0
> **创建日期**: 2026-07-23
> **关联 PRD**: _PRD_问题处理_模块筛选器显示安全测试模块.md v1.0
> **负责人**: czj

---

## 一、执行概述

### 1.1 项目背景

用例管理页面"选择模块"筛选器显示安全测试模块（如"API1 - 对象级别授权失效"等），与 UI 自动化测试模块混在一起。需修改后端 API 和前端调用，按用例类型过滤模块。

### 1.2 执行目标

| 目标 | 描述 | 验收标准 |
|------|------|---------|
| 后端过滤 | API 新增 case_type 参数 | `case_type=ui` 只返回 UI 测试模块 |
| 前端调用 | 传递 case_type=ui | 模块筛选器不显示安全测试模块 |
| 向后兼容 | 不传 case_type 时返回全部 | 现有功能不受影响 |

### 1.3 预计工期

| 阶段 | 内容 | 预计时间 |
|------|------|---------|
| Phase 1 | 后端 API 新增 case_type 参数 | 0.5 小时 |
| Phase 2 | 前端调用传递 case_type | 0.5 小时 |
| Phase 3 | 验证 | 0.5 小时 |
| **总计** | | **1.5 小时** |

---

## 二、任务分解

### 2.1 Phase 1: 后端 API 新增 case_type 参数

#### 2.1.1 修改 `module_service.py` — 服务层过滤逻辑

**文件**: `backend/app/services/module_service.py`

**改动**: `list` 方法新增 `case_type` 参数，通过模块 ID 前缀过滤：

```python
async def list(
    self,
    skip: int = 0,
    limit: int = 100,
    order_by: str = "order",
    module_type: Optional[str] = None,
    case_type: Optional[str] = None,  # 新增: ui/security/all
) -> Tuple[List[Module], int]:
    conditions = []
    if module_type:
        conditions.append(Module.module_type == module_type)
    
    # 按 case_type 过滤模块
    if case_type == "ui":
        # UI测试模块：ID不以 sec_ 开头
        conditions.append(~Module.id.startswith("sec_"))
    elif case_type == "security":
        # 安全测试模块：ID以 sec_ 开头
        conditions.append(Module.id.startswith("sec_"))
    # case_type 为 None 或 "all" 时不过滤
```

#### 2.1.2 修改 `modules.py` — 路由层参数传递

**文件**: `backend/app/routers/modules.py`

**改动**: `list_modules` 函数新增 `case_type` 查询参数：

```python
@router.get("", response_model=ModuleListResponse)
async def list_modules(
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(100, ge=1, le=500, description="返回记录数上限"),
    module_type: Optional[str] = Query(None, description="模块类型筛选: standard/custom"),
    case_type: Optional[str] = Query(None, description="用例类型筛选: ui/security/all"),
    service: ModuleService = Depends(get_module_service)
):
    modules, total = await service.list(
        skip=skip, limit=limit, module_type=module_type, case_type=case_type
    )
```

#### 2.1.3 修改 `module.py` Schema — 无需修改

ModuleResponse 不需要新增字段，过滤逻辑在查询层完成。

### 2.2 Phase 2: 前端调用传递 case_type

#### 2.2.1 修改 `modules.ts` — API 封装

**文件**: `frontend/src/api/modules.ts`

**改动**: `list` 方法新增 `case_type` 参数：

```typescript
async list(skip = 0, limit = 100, module_type?: string, case_type?: string): Promise<ModuleListResponse> {
  const response = await request.get('/api/modules', {
    params: { skip, limit, module_type, case_type }
  })
  return response.data
}
```

#### 2.2.2 修改 `Cases.vue` — 用例管理页面

**文件**: `frontend/src/views/Cases.vue`

**改动**: `loadModules` 函数传递 `case_type=ui`：

```typescript
const loadModules = async () => {
  try {
    const response = await moduleApi.list(0, 100, undefined, 'ui')
    modules.value = response.items
  } catch (error: any) {
    console.error('加载模块列表失败:', error)
  }
}
```

#### 2.2.3 修改 `Recorder.vue` — 用例录制页面

**文件**: `frontend/src/views/Recorder.vue`

**改动**: `loadModules` 函数传递 `case_type=ui`：

```typescript
const loadModules = async () => {
  try {
    const response = await moduleApi.list(0, 100, undefined, 'ui')
    modules.value = response.items
    // ... 后续逻辑不变
  } catch (error: any) {
    ElMessage.error('加载模块列表失败: ' + error.message)
  }
}
```

#### 2.2.4 修改 `Modules.vue` — 模块管理页面（如有模块筛选器）

**文件**: `frontend/src/views/Modules.vue`

需检查是否也有同样的模块列表加载问题。如有，同样传递 `case_type=ui`。

### 2.3 Phase 3: 验证

1. 调用 `/api/modules?case_type=ui` 验证只返回 UI 测试模块
2. 调用 `/api/modules?case_type=security` 验证只返回安全测试模块
3. 调用 `/api/modules` 验证返回全部模块（向后兼容）
4. 前端用例管理页面模块筛选器验证不显示安全测试模块

---

## 三、代码变更清单

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `backend/app/services/module_service.py` | 修改 | `list` 方法新增 `case_type` 参数 |
| `backend/app/routers/modules.py` | 修改 | `list_modules` 新增 `case_type` 查询参数 |
| `frontend/src/api/modules.ts` | 修改 | `list` 方法新增 `case_type` 参数 |
| `frontend/src/views/Cases.vue` | 修改 | `loadModules` 传递 `case_type='ui'` |
| `frontend/src/views/Recorder.vue` | 修改 | `loadModules` 传递 `case_type='ui'` |

---

## 四、验证方案

### 4.1 API 验证

```bash
# 验证 UI 测试模块过滤
curl -s "http://localhost:8001/api/modules?case_type=ui" | python -c "import json,sys; d=json.load(sys.stdin); print(f'UI模块数: {d[\"total\"]}'); [print(f'  {m[\"name\"]}') for m in d['items']]"

# 验证安全测试模块过滤
curl -s "http://localhost:8001/api/modules?case_type=security" | python -c "import json,sys; d=json.load(sys.stdin); print(f'安全模块数: {d[\"total\"]}'); [print(f'  {m[\"name\"]}') for m in d['items']]"

# 验证向后兼容（无参数返回全部）
curl -s "http://localhost:8001/api/modules" | python -c "import json,sys; d=json.load(sys.stdin); print(f'全部模块数: {d[\"total\"]}')"
```

### 4.2 前端验证

- 用例管理页面模块筛选器不显示安全测试模块
- 用例录制页面模块选择器不显示安全测试模块