# PRD — 元素映射表定位方案：前端 Key-Value 键值提升定位稳定性

> **文档版本**: v1.0  
> **创建日期**: 2026-08-11  
> **作者**: Claude Code  
> **状态**: 待确认

---

## 一、背景与问题

### 1.1 当前定位方式的困境

当前自动化测试平台采用**关键词匹配 + 智能定位 + Claude 语义增强**的复合定位策略，在微前端架构的复杂页面中仍存在以下问题：

| 问题 | 根因 | 影响 |
|------|------|------|
| XPath / 文本定位脆弱 | 页面重构或国际化后文本变化导致定位失败 | 用例维护成本高 |
| 关键词撞车 | 多个元素包含相同关键词（如"新建会议"） | 步骤定位到错误元素 |
| 微前端 iframe 穿透 | 元素在不同微前端子应用间切换 | 定位不稳定 |
| 智能定位精度不足 | 依赖算法猜测，无法保证 100% 准确 | 约 60% 定位成功率 |

### 1.2 方案来源

前端开发人员已提供**门户首页及功能中心元素定位键值表**，源码路径：

| 来源 | 路径 |
|------|------|
| 门户首页 | `web\pc-vue2-platform\src\views\Home\index.vue` |
| 功能中心 | `web\pc-vue2-platform\src\views\Home\components\NavMenu\index.vue` |
| 跳转列表 | `web\pc-vue2-platform\src\constant\navMenu.js` |

该键值表覆盖了首页导航栏、首页功能块、功能中心置顶/常用/全部功能、筛选器、搜索框等 **100+ 个元素**，且使用 `data-key` / `data-id` / `id` 等稳定属性定位，不依赖文本内容。

### 1.3 解决思路

将前端提供的元素映射表转化为结构化的 JSON 文件，作为 Playwright 执行器的**最高优先级选择器来源**，在执行步骤时优先通过映射表获取稳定选择器，仅在映射表找不到时回退到原有定位策略。

---

## 二、目标与非目标

### 2.1 目标

1. **建立元素映射表机制**：将前端提供的键值表转化为结构化 JSON 映射文件
2. **提升定位精度**：对映射表覆盖的操作步骤，实现 100% 准确选择器命中
3. **无缝集成**：映射表作为 Playwright 执行器的最高优先级选择器来源
4. **渐进式覆盖**：先覆盖首页 + 功能中心，子页面后续由前端继续提供
5. **可回退**：映射表找不到时自动回退到原有定位策略（DB 选择器 → 关键词匹配 → 智能定位）

### 2.2 非目标

1. 不替代现有定位策略（仅作为最高优先级补充）
2. 不修改前端代码（使用前端已提供的 data 属性）
3. 不处理子页面元素定位（后续阶段由前端提供子页面映射表）
4. 不覆盖所有用例（仅覆盖映射表中已有的元素）

---

## 三、技术方案

### 3.1 架构设计

```
┌──────────────────────────────────────────────────────────────────┐
│                         Playwright 执行器                         │
│                      playwright_executor.py                       │
└────────────────────────────────┬─────────────────────────────────┘
                                 │
                    ┌────────────┴────────────┐
                    │    选择器优先级决策      │
                    └────────────┬────────────┘
                                 │
          ┌──────────────────────┼──────────────────────┐
          ▼                      ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│ 优先级1: 映射表  │  │ 优先级2: DB选择器│  │ 优先级3: 智能定位│
│ ElementMapping   │  │  DB selectors    │  │  keyword+Claude  │
│ Service          │  │                  │  │                  │
├──────────────────┤  ├──────────────────┤  ├──────────────────┤
│ 从JSON映射文件   │  │ 从用例步骤DB中   │  │ 关键词匹配→候选  │
│ 根据步骤描述匹配  │  │ 获取已保存选择器  │  │ →Claude语义排序  │
│ 返回稳定选择器    │  │                  │  │ →返回最佳选择器  │
└──────────────────┘  └──────────────────┘  └──────────────────┘
```

### 3.2 定位优先级策略

```
SELECTOR_PRIORITY = [
    "element_mapping",    # [新增] 元素映射表（最高优先级）
    "data-testid",        # 原最高优先级
    "data-key",           # data 属性
    "data-id",            # data 属性
    "id",                 # ID 选择器
    "css",                # CSS 选择器
    "xpath",              # XPath 选择器
    "keyword_match",      # 关键词匹配（降级）
    "smart_locate",       # 智能定位（最终降级）
]
```

### 3.3 映射表 JSON 结构

```json
{
  "version": "1.0",
  "updated_at": "2026-08-11",
  "source": "前端开发人员提供 - 门户首页+功能中心",
  "elements": {
    "导航栏-功能中心抽屉开关": {
      "selector": ".home_nav_left",
      "type": "css",
      "description": "打开/关闭功能中心抽屉"
    },
    "全部功能-会议预约-创建会议": {
      "selector": "[data-id=\"reserve_list.create\"]",
      "type": "css",
      "description": "创建会议按钮"
    },
    "全部功能-筛选器-会议预约": {
      "selector": "#reserve_enable",
      "type": "css",
      "description": "筛选器-会议预约"
    }
  }
}
```

### 3.4 ElementMappingService 设计

**新增文件**：`backend/app/services/element_mapping_service.py`

**核心接口**：

```python
class ElementMappingService:
    def __init__(self, mapping_file: str = "elements_mapping.json"):
        """加载映射表 JSON 文件"""
    
    def get_selector(self, step_name: str, action: str, 
                     context: Optional[Dict] = None) -> Optional[Dict]:
        """
        根据步骤描述和上下文，从映射表获取选择器
        
        Args:
            step_name: 步骤描述（如"点击创建会议按钮"）
            action: 动作类型（click / fill 等）
            context: 上下文信息（当前页面、前序步骤等）
            
        Returns:
            {"selector": "...", "type": "css", "confidence": 1.0} 或 None
        """
    
    def get_all_keys(self) -> List[str]:
        """返回所有映射键列表（用于调试）"""
    
    def reload(self) -> bool:
        """热重载映射表文件"""
```

### 3.5 集成到 PlaywrightExecutor

在 `playwright_executor.py` 的 `execute_step` 方法中，在选择器解析阶段插入映射表查询：

```python
# 步骤1: 查询元素映射表（最高优先级）
mapping_selector = element_mapping_service.get_selector(step_name, action)
if mapping_selector:
    selector = mapping_selector["selector"]
    logger.info(f"[映射表] 命中: {step_name} → {selector}")
    # 直接使用映射表选择器执行
    
# 步骤2: 映射表未命中，回落 DB 选择器
# 步骤3: DB 选择器未命中，回落关键词匹配 + 智能定位
```

### 3.6 上下文匹配策略

映射表键为中文描述（如"全部功能-会议预约-创建会议"），而步骤描述为自然语言（如"点击创建会议按钮"）。匹配策略：

1. **精确匹配**：步骤描述完全包含映射表键中的关键词（如"创建会议"）
2. **模糊匹配**：jieba 分词后计算相似度，取最高分
3. **上下文辅助**：结合当前页面 URL、前序步骤判断当前所在功能分类，缩小匹配范围

---

## 四、映射表覆盖范围

### 4.1 首页导航栏（7 个元素）

| 区域 | 示例键 | 定位方式 |
|------|--------|---------|
| 抽屉开关 | `导航栏-功能中心抽屉开关` | `.home_nav_left` |
| Logo / 系统名称 | `导航栏-Logo` | `.home_nav .logo` |
| 用户信息 | `导航栏-退出登录` | `.ub-icon-out` |

### 4.2 首页功能块（11 个元素）

| 区域 | 示例键 | 定位方式 |
|------|--------|---------|
| 常用功能 | `首页-常用功能-创建会议` | `[data-key="reserve_list.create"]` |
| 置顶功能 | `首页-置顶功能-会议室列表` | `[data-key="meetingRoomList"]` |

### 4.3 功能中心（100+ 元素）

| 区域 | 覆盖分类 | 定位方式 |
|------|---------|---------|
| 置顶功能 | 默认 5 项 | `[data-key="..."]` |
| 常用功能 | 默认 6 项 | `[data-key="..."]` |
| 全部功能 | 13 个分类 | `[data-id="..."]` |
| 筛选器 | 13 个筛选项 | `#id` |
| 搜索框 | 1 个 | CSS |

### 4.4 13 个功能分类

会议预约、运维维护、维护工单、集控控制、会议转录、信息发布、数据统计、资产管理、会务管理、信息管理、其他、预定2.0

---

## 五、验证方案

### 5.1 目标用例

| 项目 | 内容 |
|------|------|
| 用例 ID | `case_13650e0406e64779b66e6fa5de35c24a` |
| 用例名称 | 会议管理-新建会议-czj录入 |
| 所属模块 | 会议预约（`module_e80a5d08b48d4c67a16cb86156320f25`） |

### 5.2 验证范围

| 步骤 | 描述 | 映射表预期命中 | 映射表选择器 |
|------|------|---------------|-------------|
| 1-6 | 登录操作 | ❌ 登录页不在映射表范围 | 使用原有登录模板 |
| 7 | 点击【功能中心】展开 | ✅ | `.home_nav_left` |
| 8 | 点击【会议预约】分类 | ✅ | `#reserve_enable`（筛选器） |
| 9 | 点击【新建会议】按钮 | ✅ | `[data-key="reserve_list.create"]` |

### 5.3 验证指标

| 指标 | 目标 |
|------|------|
| 映射表覆盖步骤命中率 | 100%（步骤 7-9） |
| 定位准确率 | 100%（命中即准确） |
| 执行成功率 | 100%（选择器正确即可执行） |
| 执行时间 | 与原有策略持平或更优 |

---

## 六、实现范围

### 6.1 本次实现（Phase 1）

| 模块 | 内容 | 优先级 |
|------|------|--------|
| 映射表 JSON 文件 | 将前端文档转化为结构化 JSON | P0 |
| ElementMappingService | 映射表加载 + 匹配 + 查询 | P0 |
| PlaywrightExecutor 集成 | 插入映射表为最高优先级选择器 | P0 |
| 实验验证 | 对目标用例执行验证 | P0 |
| 选择器映射器更新 | SelectorMapper 增加映射表优先级 | P1 |

### 6.2 后续迭代（Phase 2+）

| 模块 | 内容 | 优先级 |
|------|------|--------|
| 子页面映射表 | 前端提供子页面元素映射表后补充 | P1 |
| 映射表管理 API | 可视化查看/编辑映射表 | P2 |
| 自动映射表生成 | 通过录制自动生成元素映射 | P3 |
| 映射表版本管理 | 多版本映射表 + 环境适配 | P3 |

---

## 七、验收标准

### 7.1 功能验收

| 测试场景 | 预期结果 |
|---------|---------|
| 映射表命中（步骤 7-9） | 使用映射表选择器，执行成功 |
| 映射表未命中（步骤 1-6） | 自动回退到原有策略，不影响执行 |
| 映射表 JSON 格式错误 | 服务加载失败时自动禁用映射表，日志告警 |
| 热重载映射表 | 更新 JSON 文件后无需重启服务 |

### 7.2 精度验收

| 指标 | 当前（关键词匹配） | 目标（映射表） |
|------|-------------------|---------------|
| 步骤 7 定位准确率 | 不稳定（XPath 文本） | 100% |
| 步骤 8 定位准确率 | 不稳定（文本匹配） | 100% |
| 步骤 9 定位准确率 | 不稳定（撞车风险） | 100% |

### 7.3 回退验证

| 场景 | 预期行为 |
|------|---------|
| 映射表 JSON 文件不存在 | 静默跳过，使用原有策略 |
| 映射表 JSON 解析失败 | 日志告警，使用原有策略 |
| 映射表查询无匹配 | 返回 None，继续下一优先级 |

---

## 八、风险评估

| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| 前端页面重构导致 data-key 变化 | 映射表无效 | 与前端约定 data-key 为稳定 ID，变化时同步更新映射表 |
| 映射表覆盖不全 | 部分步骤仍需原有策略 | 渐进式补充，前端持续提供子页面映射表 |
| 个性化菜单动态变化 | 映射表与实际渲染不一致 | 映射表仅覆盖默认配置，实际以渲染为准 |
| 权限过滤导致元素不渲染 | 定位失败 | 确认测试账号权限，日志记录权限缺失 |

---

## 九、参考资料

- `Docs/Doc_门户首页_首页元素获取键值_功能总结-新.md` — 前端提供的元素定位键值表
- `HANDOFF_UI自动化.md` — UI 自动化模块交接文档
- `backend/app/services/keyword_matcher.py` — 当前关键词匹配实现
- `backend/app/services/smart_locate_service.py` — 智能定位服务
- `backend/app/executors/playwright_executor.py` — Playwright 执行引擎
- `backend/app/utils/selector_mapper.py` — 选择器映射器
- `_PRD_智能定位Claude语义增强.md` — 原智能定位 PRD
- `_PRD_自然语言用例智能定位功能.md` — 原自然语言定位 PRD

---

*本文档待用户确认后进入执行计划阶段。*