# HANDOFF — UI自动化测试交接文档

> **生成时间**: 2026-08-03
> **当前分支**: `platform-auto-test`
> **最近提交**: `待提交` feat(element-locate): 元素定位功能优化 - API增强 + 配置面板
> **状态**: ✅ 元素定位功能优化完成（Phase 1-3）
>
> **本次会话完成**：
> - ✅ Phase 1: 后端 API 增强 — 新增 5 个配置参数 + 3 个响应字段 + 重试机制
> - ✅ Phase 2: 微前端元素提取增强 — 扩展 Element UI/Vuetify/Ant Design 组件支持
> - ✅ Phase 3: 前端配置面板 — 获取定位配置弹窗 + 预览页面功能
> - ✅ 前端构建验证通过
>
> **上次会话完成**：
> - ✅ 修复步骤表格不显示定位信息问题（新增"定位类型"和"定位值"列）
> - ✅ 去掉置信度判断，始终调用 Claude CLI 进行元素匹配
> - ✅ 修复批量定位数据库更新失败问题
> - ✅ 增加批量定位超时时间到 300 秒（5 分钟）
> - ✅ 优化微前端元素提取（支持 shadow DOM + Element UI 组件）
> - ✅ 优化 Claude CLI 调用（直接传递元素列表，不再让宿主机重新访问页面）
> - ✅ 创建测试用例验证闭环（登录成功 8/8，会议列表 2/7）

---

## ⚠️ 开始工作前必读

**多窗口并行开发冲突规避**：如需开多个 Claude Code 窗口同时开发，**必须先阅读** `Docs/多窗口并行开发指南.md`，了解：
- 端口隔离（8001/8002）
- 数据库操作错开
- Playwright 执行互斥（不可同时执行用例）
- Git 提交协作

**当前多窗口状态**：本项目有多个窗口分工开发，交接文档分散在：
- `HANDOFF.md` — **平台自动化测试系统总交接**
- `HANDOFF_V2部署升级.md` — V2 部署详细交接
- `HANDOFF_UI自动化.md` — **UI 自动化测试模块（本文档）**
- `HANDOFF_安全测试.md` — 安全测试模块

---

## 一、项目概览

**平台自动化测试可视化系统 (platform-auto-test)** — Web 可视化自动化测试平台，核心创新是用例录制器。

- **技术栈**: FastAPI + SQLAlchemy(async) + MySQL 8.0（生产）/ SQLite（本地）+ Playwright(同步API) + WebSocket / Vue 3 + Element Plus + Vite 5 + TypeScript
- **被测系统**: 统一管理平台 (https://192.168.5.44) — 微前端 micro-app 架构
- **登录凭据**: admin@xty / Ubains@13579 · 验证码固定 `csba`
- **远程仓库**: http://git.ubainsyun.com/bing/ubains-module-test.git
- **当前分支**: `platform-auto-test`（主分支：`master`）
- **服务器**: 192.168.5.60（Docker 容器化部署）

---

## 二、本次会话完成的工作

### 1. ✅ 修复步骤表格不显示定位信息

**问题**：用例详情弹窗的步骤表格只显示"步骤名称"、"动作"、"参数"三列，定位信息被隐藏在 params 的 JSON 中。

**修改内容**：
- `frontend/src/views/Cases.vue` — 新增"定位类型"和"定位值"两列
- 兼容三种命名格式：`locatorType` / `locator_type` / `params.selector`
- `formatParams` 函数排除 `selector` 字段避免重复显示
- 新增 `.locator-code` 样式让定位值用代码字体显示

**提交**: `b2854e30` fix(ui-cases): 修复步骤表格不显示定位信息问题

### 2. ✅ 始终调用 Claude CLI（去掉置信度判断）

**问题**：之前只有关键词匹配置信度 < 0.6 时才调用 Claude CLI，导致很多步骤没有真正使用 Claude 能力。

**修改内容**：
- `backend/app/routers/element_locator.py` — 去掉 `needs_claude = candidates[0]['confidence'] < 0.6` 判断
- 每次定位都调用 `call_claude_code_via_ssh` 函数
- Claude 返回结果与关键词重复时，提升置信度并标记为 Claude 确认
- 降低 Claude 结果采纳阈值为 0.3

**提交**: `fbb895f8` fix(element-locate): 始终调用 Claude CLI 进行元素定位，不再依赖置信度判断

### 3. ✅ 优化 Claude CLI 调用方式

**问题**：之前让宿主机重新访问页面提取元素，但宿主机没有登录状态，导致需要登录的页面元素提取为 0。

**修改内容**：
- 容器内已登录并提取元素，直接把元素列表传给宿主机的 Claude CLI 做匹配
- 使用 base64 编码 prompt 避免 SSH 命令行特殊字符问题
- 宿主机只负责调用 `claude -p` 进行智能匹配，不再访问页面

### 4. ✅ 修复批量定位数据库更新问题

**问题**：`'dict' object has no attribute 'module_id'`，因为 `case_service.update()` 期望接收 TestCaseUpdate schema 对象。

**修改内容**：
- 使用 SQLAlchemy 的 `update()` 语句直接更新数据库
- 绕过 schema 校验，直接更新 `steps` 字段
- 确保 `locatorType` / `locatorValue` / `params.selector` 三个字段都正确保存

**提交**: `82c6f778` fix(element-locate): 修复批量定位数据库更新问题，延长超时时间

### 5. ✅ 增加批量定位超时时间

**问题**：8 个步骤需要 8 次 SSH + Claude CLI 调用（约 15-20 秒/步骤），总时间超过 90 秒超时。

**修改内容**：
- 超时时间从 90 秒增加到 300 秒（5 分钟）
- 登录用例 8 个步骤实际耗时约 138 秒

### 6. ✅ 优化微前端元素提取

**问题**：会议列表等微前端页面元素提取为 0，因为 `micro-app-body.shadowRoot` 不一定存在。

**修改内容**：
- 支持多种 micro-app 渲染模式：shadow DOM 和普通 DOM
- 支持 Element UI 组件提取（`.el-input__inner` 等）
- 增加元素去重逻辑（避免重复提取）
- 增加页面加载后重试机制（元素为空时等待 5 秒重试）

### 7. ✅ 功能验证测试

| 用例 | 步骤数 | 定位成功 | 结论 |
|------|--------|----------|------|
| 登录成功验证 | 8 | 8/8 ✅ | 完整闭环可用 |
| 新建会议-快速预约 | 7 | 2/7 ⚠️ | 微前端页面元素提取不完整 |

### 8. ✅ 生成需求文档和计划执行文档

| 文档 | 路径 |
|------|------|
| 需求文档 | `Docs/PRD/需求文档/用例管理/_PRD_元素定位功能优化.md` |
| 计划执行文档 | `Docs/PRD/需求文档/用例管理/_执行计划_元素定位功能优化.md` |

**优化方向**：
- 支持自定义页面加载等待时间
- 支持等待特定元素出现后再提取
- 前端增加"预览页面"功能
- 元素为空时自动重试

---

## 三、关键配置信息

| 项目 | 值 |
|------|-----|
| 服务器 IP | 192.168.5.60 |
| SSH 用户 | ubains |
| SSH 密码 | Ubains@123 |
| 部署目录 | `/data/third_party/plat-auto-test/` |
| 前端地址 | http://192.168.5.60 |
| API 文档 | http://192.168.5.60/docs |
| 健康检查 | http://192.168.5.60/health |
| MySQL 外部访问 | 192.168.5.60:3307 |
| MySQL 用户/密码 | platapp / PlatApp2026 |
| 被测系统 | https://192.168.5.44/（微前端） |
| 登录凭据 | admin@xty / Ubains@13579 · 验证码 `csba` |
| 宿主机 Python | `python3`（Playwright 在 `~/.local`） |
| 宿主机 Claude Code | ✅ 已认证（office.ubainsyun.com:8400 / glm-5.2） |
| 容器 paramiko | ✅ 已安装 |

---

## 四、元素定位 API 详细说明

### 4.1 单个定位 POST /api/element/locate

**请求体**：
```json
{
  "step_description": "输入用户名",
  "page_url": "https://192.168.5.44/",
  "auto_login": true
}
```

**响应**：
```json
{
  "success": true,
  "candidates": [
    {
      "locator_type": "css",
      "locator_value": "[placeholder*='手机号/用户名/邮箱']",
      "confidence": 0.95,
      "element_info": {
        "tag": "INPUT",
        "type": "text",
        "placeholder": "手机号/用户名/邮箱",
        "text": "",
        "id": ""
      }
    }
  ],
  "message": "找到 1 个候选定位器",
  "screenshot": "base64..."
}
```

### 4.2 批量定位 POST /api/element/locate-batch

**请求体**：
```json
{
  "case_id": "case_xxx",
  "page_url": "https://192.168.5.44/",
  "auto_login": true,
  "page_load_timeout": 10000,      // 可选：页面加载超时（毫秒）
  "extra_wait_time": 5000,          // 可选：额外等待时间（毫秒）
  "wait_for_selector": "",          // 可选：等待特定元素（CSS选择器）
  "retry_on_empty": true,           // 可选：元素为空时重试
  "max_retries": 2                  // 可选：最大重试次数
}
```

**响应**：
```json
{
  "success": true,
  "case_id": "case_xxx",
  "total_steps": 6,
  "located_steps": 5,
  "results": [
    {
      "order": 1,
      "description": "输入用户名",
      "success": true,
      "locator_type": "css",
      "locator_value": "[placeholder*='手机号/用户名/邮箱']",
      "confidence": 0.95,
      "message": "置信度 95%"
    }
  ],
  "message": "成功定位 5/6 个步骤",
  "elements_extracted": 42,         // 新增：提取到的元素总数
  "retries": 0,                     // 新增：实际重试次数
  "page_load_time": 12.5            // 新增：页面加载耗时（秒）
}
```

---

## 五、Git 提交记录

| 提交哈希 | 提交信息 | 时间 |
|----------|----------|------|
| `82c6f778` | fix(element-locate): 修复批量定位数据库更新问题，延长超时时间 | 2026-08-03 |
| `fbb895f8` | fix(element-locate): 始终调用 Claude CLI 进行元素定位，不再依赖置信度判断 | 2026-08-03 |
| `b2854e30` | fix(ui-cases): 修复步骤表格不显示定位信息问题 | 2026-08-03 |
| `5848a57b` | feat: 本地元素定位功能 - 实际访问页面获取真实元素定位器 | 2026-08-03 |

---

## 六、下一步任务（优先级排序）

| 优先级 | 任务 | 说明 |
|--------|------|------|
| 🔴 **P0** | 部署到服务器 | 前端已构建，需上传到 192.168.5.60 并验证 |
| 🟡 **P1** | 设备模拟模块联调 | MQTT 环境配置与联调待验证 |
| 🟢 **P2** | 清理临时脚本 | 根目录大量探索脚本和部署脚本待清理 |
| 🟢 **P2** | Phase 5 剩余 | Pinia 状态管理、单元测试 |

---

## 七、启动与运维指南

### 本地开发

```bash
# 后端（端口 8001）
cd backend
pip install -r requirements.txt
playwright install chromium
uvicorn app.main:app --reload --port 8001

# 前端（端口 3000）
cd frontend
npm install
npm run dev
```

### 服务器更新

```bash
# 更新后端（单个文件）
scp backend/app/routers/element_locator.py ubains@192.168.5.60:/data/third_party/plat-auto-test/backend/app/routers/
ssh ubains@192.168.5.60 'cd /data/third_party/plat-auto-test/deploy && docker compose restart app'

# 更新前端
cd frontend && npm run build
# 上传 dist/ 到服务器 frontend/dist/
```

### 验证元素定位

```bash
# 单个定位
curl -X POST http://192.168.5.60/api/element/locate \
  -H "Content-Type: application/json" \
  -d '{"step_description":"输入用户名","page_url":"https://192.168.5.44/","auto_login":false}'

# 批量定位
curl -X POST http://192.168.5.60/api/element/locate-batch \
  -H "Content-Type: application/json" \
  -d '{"case_id":"case_xxx","page_url":"https://192.168.5.44/","auto_login":false}'
```

---

## 八、踩坑记录（本次新增）

| # | 现象 | 根因 | 正确做法 |
|---|------|------|---------|
| 27 | `Cannot read properties of undefined (reading 'items')` | 前端 `request.ts` 响应拦截器 `return response.data` | 改为 `return response`，所有 API 文件统一用 `response.data` |
| 28 | Playwright Sync API inside asyncio loop | `run_in_executor` 线程中 Playwright 检测到 asyncio 循环 | 使用专用 `threading.Thread` + `asyncio.set_event_loop(None)` |
| 29 | 页面加载 `Timeout 30000ms` | `networkidle` 在 SPA 页面可能永不触发 | 改用 `domcontentloaded` + 额外等待 |
| 30 | SSH 调用 `sshpass: not found` | 容器内没有安装 sshpass | 改用 `paramiko` 库建立 SSH 连接 |
| 31 | `No module named 'paramiko'` | 容器内未安装 paramiko | `pip install paramiko` |
| 32 | 关键词匹配 0 候选 | `extract_keywords` 拆分中文逻辑不对 | 改进为去除动作词 + 拆分子词 + 单字匹配 |
| 33 | 容器重启后 `ImportError` | `database.py` 导出的是 `get_db` 不是 `get_session` | 改为 `from app.database import async_session_maker` |
| 34 | 批量定位超时 | 8 步骤需 8 次 SSH + Claude CLI，超过 90s 超时 | 增加超时时间到 300s |
| 35 | 数据库更新失败 `'dict' object has no attribute 'module_id'` | `case_service.update()` 期望 schema 对象 | 使用 SQLAlchemy `update()` 语句直接更新 |
| 36 | 宿主机元素提取为 0 | `ai_locate_worker.py` 没有登录状态 | 改为容器内提取元素，宿主机只做 Claude 匹配 |
| 37 | 微前端页面元素提取不完整 | `micro-app-body.shadowRoot` 不一定存在 | 支持多种渲染模式 + Element UI 组件提取 |

---

## 九、文档索引

| 文档 | 路径 |
|------|------|
| 项目指南 | `CLAUDE.md` |
| 多窗口并行开发指南 | `Docs/多窗口并行开发指南.md` |
| 主 PRD | `Docs/PRD/需求文档/总览/_PRD_平台自动化测试可视化系统需求文档.md` |
| UI用例录入优化 PRD | `Docs/PRD/需求文档/用例管理/_PRD_UI自动化用例录入优化.md` |
| **元素定位功能优化 PRD** | `Docs/PRD/需求文档/用例管理/_PRD_元素定位功能优化.md` |
| **元素定位功能优化计划** | `Docs/PRD/需求文档/用例管理/_执行计划_元素定位功能优化.md` |
| 当前进度记录 | `Docs/PRD/需求文档/总览/当前进度记录.md` |
| V2 部署设计 | `Docs/部署方案/Linux容器化部署方案_v2.md` |
| HANDOFF 总交接 | `HANDOFF.md` |
| UI自动化交接 | `HANDOFF_UI自动化.md`（本文档） |
| V2 部署交接 | `HANDOFF_V2部署升级.md` |
| 安全测试交接 | `HANDOFF_安全测试.md` |

---

*本文档由 Claude Code 于 2026-08-03 更新，记录元素定位功能优化 + Claude CLI 始终调用 + 前端步骤表格优化 + 功能验证测试，供下次会话快速恢复上下文。*