# PRD — 智能定位功能执行稳定性优化

> **模块**: UI 自动化测试 — 智能元素定位
> **优先级**: P0
> **作者**: czj / Claude Code
> **创建日期**: 2026-08-05
> **最后修改**: 2026-08-05

---

## 一、需求背景

### 1.1 问题现状

2026-08-05 执行验证发现，通过脚本创建的 UI 自动化用例执行失败率较高：

| 用例 | 状态 | 失败步骤 | 失败原因 |
|------|------|----------|----------|
| 信息发布-页面访问验证 | ✅ 通过 | - | - |
| 资产管理-资产信息页面验证 | ❌ 失败 | step3 | 等待抽屉超时 |
| 集控控制-壁纸推送功能验证 | ❌ 失败 | step3 | 等待抽屉超时 |
| 通知公告-页面访问验证 | ❌ 失败 | step4 | 点击菜单失败 |
| 会议管理-会议列表查看 | ❌ 失败 | step4 | 点击菜单失败 |

**通过率：1/5 = 20%**

### 1.2 失败原因分析

#### 问题1：功能中心点击后未等待抽屉动画

**现象**：
```
步骤2: 点击功能中心图标 - 通过
步骤3: 等待抽屉打开 - 超时失败
```

**根因**：
- 功能中心点击后，抽屉有展开动画（约 300ms）
- 当前代码只等待 1 秒就开始定位下一个元素
- 动画期间 DOM 可能不稳定，导致 `.el-drawer` 选择器匹配失败

**当前选择器**：`.home_nav_left`

**正确选择器**（已验证）：`//*[@id="Home"]/div[1]/div[1]/i`

#### 问题2：抽屉内菜单点击失败

**现象**：
```
步骤3: 等待抽屉打开 - 通过
步骤4: 点击通知公告菜单 - 失败
```

**根因**：
- 抽屉内菜单可能需要滚动才能看到
- 选择器 `.el-drawer >> text='通知公告'` 匹配到元素但点击失败
- 抽屉展开动画期间元素可能被遮挡或不可交互

#### 问题3：菜单选择器不够精确

**现象**：不同菜单的点击成功率差异大

**根因**：
- 当前选择器格式 `.el-drawer >> text='{菜单名}'` 依赖文本匹配
- 某些菜单在二级分类下，需要先展开分类
- 未处理菜单在抽屉外的情况

### 1.3 已验证的正确选择器

| 元素 | 选择器 | 验证状态 |
|------|--------|----------|
| 功能中心图标 | `//*[@id="Home"]/div[1]/div[1]/i` | ✅ 已验证 |
| 抽屉容器 | `.el-drawer` | ✅ 已验证 |
| 抽屉内菜单 | `.el-drawer >> text='{菜单名}'` | ⚠️ 部分失败 |

---

## 二、需求目标

### 2.1 核心目标

**提升 UI 自动化用例执行通过率从 20% 提升到 90%+**

### 2.2 具体目标

| # | 目标 | 验收标准 |
|---|------|----------|
| 1 | 点击功能中心后正确等待抽屉 | 步骤3不再超时 |
| 2 | 抽屉内菜单可正常点击 | 菜单点击成功率 100% |
| 3 | 处理二级菜单导航 | 自动展开分类后再点击子菜单 |
| 4 | 选择器回退机制 | 主选择器失败时尝试备选方案 |

---

## 三、功能需求

### 3.1 需求1：功能中心点击后等待抽屉展开

#### 3.1.1 功能描述

点击功能中心图标后，增加等待逻辑确保抽屉完全展开。

#### 3.1.2 实现要点

1. **修正功能中心选择器**

   将 `.home_nav_left` 替换为已验证的 XPath：
   ```python
   FUNCTION_CENTER_SELECTOR = "//*[@id='Home']/div[1]/div[1]/i"
   ```

2. **增加点击后等待策略**

   点击功能中心后，执行以下等待序列：

   ```
   点击功能中心
   → 等待 .el-drawer 出现（最多 5s）
   → 等待 .el-drawer 动画完成（检查 class 不含 'el-drawer__open'）
   → 额外等待 500ms 确保稳定
   → 继续后续步骤
   ```

3. **等待状态检测**

   ```python
   # 等待抽屉出现
   page.wait_for_selector(".el-drawer", timeout=5000)
   
   # 等待抽屉动画完成（检测 drawer__open 类）
   page.wait_for_function("""
       !document.querySelector('.el-drawer')?.classList.contains('el-drawer--open') ||
       document.querySelector('.el-drawer.el-drawer--open') !== null
   """, timeout=3000)
   
   # 额外稳定等待
   page.wait_for_timeout(500)
   ```

#### 3.1.3 影响范围

- `backend/app/services/smart_locate_service.py`
- `backend/scripts/create_ui_cases_all_modules.py`（更新选择器）

---

### 3.2 需求2：抽屉内菜单点击优化

#### 3.2.1 功能描述

优化抽屉内菜单的定位和点击逻辑，处理滚动、遮挡等情况。

#### 3.2.2 实现要点

1. **菜单元素滚动到可见区域**

   点击菜单前，确保元素在可视区域：

   ```python
   menu_selector = f".el-drawer >> text='{menu_name}'"
   menu_element = page.query_selector(menu_selector)
   if menu_element:
       menu_element.scroll_into_view_if_needed()
       page.wait_for_timeout(300)  # 滚动后稳定
       menu_element.click()
   ```

2. **增加点击前等待**

   菜单元素需要等待可交互状态：

   ```python
   # 等待元素可点击
   page.wait_for_selector(menu_selector, state="visible", timeout=5000)
   page.wait_for_selector(menu_selector, state="enabled", timeout=1000)
   ```

3. **处理点击失败重试**

   ```python
   for retry in range(3):
       try:
           page.click(menu_selector, timeout=5000)
           break
       except Exception as e:
           if retry < 2:
               page.wait_for_timeout(1000)
               # 尝试滚动后重试
               page.eval_on_selector(menu_selector, "el => el.scrollIntoView()")
           else:
               raise
   ```

#### 3.2.3 影响范围

- `backend/app/services/smart_locate_service.py`
- `backend/app/executors/playwright_executor.py`

---

### 3.3 需求3：二级菜单导航支持

#### 3.3.1 功能描述

支持功能中心抽屉内的二级菜单导航（如：资产管理 → 资产信息）。

#### 3.3.2 二级菜单结构

```
功能中心抽屉
├── 集控控制 [分类]
│   ├── 壁纸推送
│   ├── 脚本命令
│   └── 应用管理
├── 资产管理 [分类]
│   ├── 资产信息
│   └── 资产设备
└── 信息发布 [直接菜单]
```

#### 3.3.3 实现要点

1. **菜单映射表**

   维护二级菜单映射：

   ```python
   MENU_HIERARCHY = {
       # 分类 → 子菜单列表
       "集控控制": ["壁纸推送", "脚本命令", "应用管理", "屏幕管理", "软件卸载", "设备网络", "门口屏发布", "播放器发布"],
       "资产管理": ["资产信息", "资产设备"],
       "会议运维": ["运维设备", "运维巡检"],
       # 直接菜单（无分类）
       "信息发布": None,
       "数据统计": None,
       "通知公告": None,
   }
   ```

2. **导航逻辑**

   ```python
   def navigate_to_menu(menu_name):
       if menu_name in MENU_HIERARCHY:
           # 直接菜单，直接点击
           click_drawer_menu(menu_name)
       else:
           # 二级菜单，先找父分类
           for category, children in MENU_HIERARCHY.items():
               if menu_name in children:
                   # 1. 点击分类展开
                   click_drawer_menu(category)
                   page.wait_for_timeout(500)
                   # 2. 点击子菜单
                   click_drawer_menu(menu_name)
                   break
   ```

#### 3.3.4 影响范围

- `backend/app/services/smart_locate_service.py`
- 新增 `backend/app/utils/menu_mapping.py`

---

### 3.4 需求4：选择器回退机制

#### 3.4.1 功能描述

主选择器失败时，自动尝试备选选择器。

#### 3.4.2 实现要点

1. **多候选选择器列表**

   ```python
   MENU_SELECTORS = {
       "信息发布": [
           ".el-drawer >> text='信息发布'",
           ".el-drawer a:has-text('信息发布')",
           ".el-drawer button:has-text('信息发布')",
           "//div[contains(@class,'el-drawer')]//a[contains(text(),'信息发布')]",
       ],
   }
   ```

2. **回退尝试逻辑**

   ```python
   def click_with_fallback(selectors, max_retry=3):
       for i, selector in enumerate(selectors):
           try:
               page.click(selector, timeout=5000)
               return True
           except Exception as e:
               if i == len(selectors) - 1:
                   raise  # 最后一个选择器也失败，抛出异常
               continue
       return False
   ```

#### 3.4.3 影响范围

- `backend/app/services/smart_locate_service.py`
- `backend/app/executors/playwright_executor.py`

---

## 四、非功能需求

### 4.1 性能要求

| 指标 | 要求 |
|------|------|
| 菜单导航耗时 | ≤ 5 秒 |
| 抽屉等待耗时 | ≤ 3 秒 |
| 重试次数上限 | 3 次 |

### 4.2 兼容性要求

- 支持现有的所有功能模块菜单
- 兼容已创建的用例（不破坏现有选择器）

### 4.3 可维护性要求

- 菜单映射表独立维护，便于扩展
- 选择器配置化，支持热更新

---

## 五、验收标准

### 5.1 功能验收

| # | 验收项 | 验收标准 |
|---|--------|----------|
| 1 | 功能中心点击 | 点击后抽屉正确展开，等待动画完成 |
| 2 | 一级菜单点击 | 信息发布等直接菜单点击成功 |
| 3 | 二级菜单点击 | 壁纸推送、资产信息等二级菜单点击成功 |
| 4 | 执行通过率 | 5 个验证用例全部通过 |

### 5.2 回归验证

- 原有通过的用例（如信息发布）仍能通过
- 新创建的用例可正常执行

---

## 六、附录

### 6.1 相关文档

- `HANDOFF_UI自动化.md` — UI 自动化模块交接文档
- `_PRD_自然语言用例智能定位功能.md` — 智能定位功能 PRD
- `_经验总结_脚本录制与元素定位.md` — 元素定位经验总结

### 6.2 验证用例清单

| 用例名称 | 模块 | 验证目的 |
|----------|------|----------|
| 集控控制-壁纸推送功能验证 | 集控控制 | 二级菜单导航 |
| 信息发布-页面访问验证 | 信息发布 | 一级菜单导航（基准） |
| 资产管理-资产信息页面验证 | 资产管理 | 二级菜单导航 |
| 通知公告-页面访问验证 | 通知公告 | 一级菜单导航 |
| 会议管理-会议列表查看 | 会议管理 | 一级菜单导航 |

---

*本文档由 Claude Code 于 2026-08-05 创建。*