feat: 工资查询助手首版 v1.0.105
基于 skill-template 脚手架开发,包含: - payroll_config(费率配置,可编辑)+ payslip_snapshots(解析历史,只读)2 张业务表 - 全国默认 + 北上广 4 套费率(社保/公积金/个税起征点/7 级税率表) - 5 个业务 Action:calculate-payslip-simple / calculate-payslip-full / explain-term / view-config / edit-config - 个税累计预扣法计算,支持多月历史累加 - 20 个薪资名词库(社保/公积金/个税/全勤/加班费等) - 完整市场文档(README/TUTORIAL/DEMO/CHANGELOG) - 296 测试全部通过
This commit is contained in:
189
development/RPA_DESKTOP.md
Normal file
189
development/RPA_DESKTOP.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# Windows 桌面 RPA 元素拾取与定位标准
|
||||
|
||||
> 先读 [`RPA_ELEMENT_LOCATING.md`](RPA_ELEMENT_LOCATING.md)。Windows 桌面首选 **UI Automation(UIA)**。当前已验证成功案例 `add-friend-wecom` 使用 Python `uiautomation`;`pywinauto(backend="uia")` 是兼容方案。标准约束的是 UIA 方法,不强制混用两个库。
|
||||
|
||||
## 目录
|
||||
|
||||
1. 已验证基线
|
||||
2. 拾取工具和步骤
|
||||
3. 定位优先级
|
||||
4. 窗口与控件规则
|
||||
5. 输入、点击与等待
|
||||
6. UIA 不可用时的降级
|
||||
7. 诊断和留证
|
||||
8. example 路由
|
||||
|
||||
## 1. 已验证基线
|
||||
|
||||
真实成功来源:`D:\OpenClaw\client-marketing\add-friend-wecom`(含通讯录 → 新的客户 → 添加 → 搜索 → 发送全链路)。
|
||||
|
||||
该案例验证了:
|
||||
|
||||
- 通过进程/窗口类名/标题找到企业微信顶层窗口。
|
||||
- 主窗激活后**最大化**,避免侧栏折叠导致控件不可见或坐标漂移。
|
||||
- 从 HWND 获取 UIA 根控件;在**子业务 pane**(如「企业微信-通讯录」)内缩小作用域。
|
||||
- 区分 UIA `Name` 与 `Value`:可见中文常在 Value / 子 Label,不在 Name。
|
||||
- 通用叶子名(`item` / `status_layout` / `wbtn_container`)必须绑业务父容器,并用文案校验。
|
||||
- 真实点击后校验后置状态(标题、专用容器、子窗口)。
|
||||
- 处理独立弹窗与嵌套弹窗。
|
||||
- 提供 `probe-ui` 诊断和 `dry-run / assisted / auto` 三档。
|
||||
|
||||
example 只提炼通用模式;企业微信名称、窗口类、控件名、列表顺序和业务结果不得复制到其他软件。
|
||||
|
||||
## 2. 拾取工具和步骤
|
||||
|
||||
可使用影刀元素拾取器、Microsoft Inspect/Accessibility Insights、FlaUInspect 或库自带树打印能力。
|
||||
|
||||
操作步骤:
|
||||
|
||||
1. 启动目标软件,登录并手工进入准确页面;需要完整侧栏时先**最大化**。
|
||||
2. 记录目标进程名、PID、主窗口标题和 Window Class。
|
||||
3. 用检查器点选目标元素,记录:
|
||||
- AutomationId
|
||||
- **Name**(内部 id,可能是 `org_op_new` / `status_layout`)
|
||||
- **Value**(可见中文文案常在这里,如「通讯录」「新的客户」)
|
||||
- ControlType / ClassName / FrameworkId
|
||||
- IsEnabled / IsOffscreen / BoundingRectangle
|
||||
- 父容器链(含业务子窗/pane 标题)
|
||||
4. 保存截图和原始 UIA 树/拾取器导出文件。
|
||||
5. 从长路径中找出稳定窗口、业务父容器和叶子属性。
|
||||
6. 删除仅反映当前布局的深层 index;确需 index 时写明业务依据,且优先用文案定位。
|
||||
7. 写入 element map(Name 与 Value 分开登记)。
|
||||
8. 运行 `probe-ui`(建议先激活并最大化),验证关键窗口和元素。
|
||||
9. 关闭重开软件、切换一次页面后再次验证。
|
||||
|
||||
### Name / Value(易错)
|
||||
|
||||
- 影刀/检查器里的**选择器显示名**(如「新的客户」)≠ 控件 UIA `Name`。
|
||||
- 许多国产客户端:`Name` 是内部 id,**界面中文在 `Value` 或子控件 Value**。
|
||||
- 拾取时两者都记;定位时勿把业务中文当成 `Name=` 去搜。
|
||||
|
||||
### 从拾取结果提炼定位器
|
||||
|
||||
影刀等工具可能导出很长的 UIA 路径。不要整条照抄:
|
||||
|
||||
```text
|
||||
原始:主窗口 → 通讯录 pane → wlist_view → item[2] → status_layout
|
||||
→ … → main_chattext(Value=新的客户)
|
||||
提炼:通讯录 pane → wlist_view → 行内 main_chattext.Value=新的客户 → 点击该行 status_layout
|
||||
禁止:全树第一个 Name=status_layout(常为「群聊」等其它行)
|
||||
```
|
||||
|
||||
长路径用于排障和理解结构;生产定位器使用最短、唯一、可解释的稳定组合。
|
||||
|
||||
## 3. 定位优先级
|
||||
|
||||
从高到低:
|
||||
|
||||
1. `Process/PID + WindowClass + WindowTitle`(及稳定业务子 pane)
|
||||
2. 目标窗口内 `AutomationId + ControlType`
|
||||
3. 稳定内部 `Name + ControlType`(如 `org_op_new`、`searchedit`)
|
||||
4. 业务父容器 + 稳定子元素属性
|
||||
5. **可见业务文案(优先读 Value / 子 Label)+ 相对关系**
|
||||
6. `ClassName/FrameworkId` 辅助组合
|
||||
7. 有业务依据的 index(仅兜底;须写清父容器与序号含义,禁止「过滤后的列表 [2]」与「父节点 child index=2」混用)
|
||||
8. UIA 元素实时 BoundingRectangle 派生坐标
|
||||
9. 局部截图模板/OCR
|
||||
10. 写死绝对坐标:禁止作为生产方案
|
||||
|
||||
顶层窗口或关键按钮出现多个候选时,返回 `ERROR:ELEMENT_AMBIGUOUS`,不得默认使用第一个。
|
||||
|
||||
同名叶子(如多处 `wbtn_container`)必须限制在业务父容器内(如 `search_external`),并可用子文案(如 Value=`添加`)校验;禁止点搜索旁通用「+」。
|
||||
|
||||
## 4. 窗口与控件规则
|
||||
|
||||
### 窗口
|
||||
|
||||
- 校验窗口属于预期进程和当前用户会话。
|
||||
- 主窗口、**应用内业务子 pane**、搜索窗、确认窗分别建立作用域。
|
||||
- 进入依赖完整侧栏/工具栏的页面时:**激活后最大化**;`activate` **禁止**对已最大化窗口无条件调用 `SW_RESTORE`(会还原成普通窗,导致折叠与坐标漂移)。仅最小化时才 Restore。
|
||||
- 应用可能重建窗口;页面切换后重新取 HWND 和 UIA root。
|
||||
- 自动化进程与目标进程权限级别必须兼容;不要为了绕过权限注入目标进程。
|
||||
- 多开场景必须由账号、PID或明确窗口信息选择,歧义时停止。
|
||||
|
||||
### 控件
|
||||
|
||||
- 在最小业务父容器中搜索。
|
||||
- 默认要求唯一匹配。
|
||||
- 检查可见、启用、未离屏和边界矩形有效。
|
||||
- 虚拟列表只包含当前实例化元素;滚动后重新枚举。
|
||||
- 不长期保存 Control 对象。
|
||||
|
||||
## 5. 输入、点击与等待
|
||||
|
||||
### 点击
|
||||
|
||||
1. 激活目标窗口(主窗按需最大化;子对话框不要误 Maximize)。
|
||||
2. 重新定位元素。
|
||||
3. 检查边界矩形。
|
||||
4. 使用 UIA Click/Invoke 或正常鼠标点击。
|
||||
5. 等待后置窗口/控件/业务状态(如标题文案、专用容器、子窗口 Class)。
|
||||
|
||||
关键导航建议日志:`locate`(策略/文案)→ `click` → `verify`(后置)。这与 [`LOGGING.md`](LOGGING.md)「不必每个 Click 一行」不冲突:要求的是**关键跳转可观测**,不是像素级刷屏。
|
||||
|
||||
UIA 点击失败时可以用该元素刚读取的 BoundingRectangle 中心点降级,但必须记录降级、确认窗口前台并验证后置状态;不得静默改点写死坐标。
|
||||
|
||||
### 输入
|
||||
|
||||
- 先点击聚焦。
|
||||
- 清空并逐字输入,敏感值不写日志。
|
||||
- 输入后读取 Value/Text 或通过后续业务状态验证。
|
||||
- 剪贴板可能泄露敏感信息,非必要不使用。
|
||||
|
||||
### 等待
|
||||
|
||||
优先等待:
|
||||
|
||||
- 目标窗口出现/消失。
|
||||
- 控件出现、启用或状态变化。
|
||||
- 列表产生业务结果。
|
||||
- 成功/失败提示出现。
|
||||
|
||||
固定 sleep 只作短缓冲,并使用可中断等待;不能作为成功条件。
|
||||
|
||||
## 6. UIA 不可用时的降级
|
||||
|
||||
先检查:
|
||||
|
||||
1. 权限级别和 Windows 会话是否一致。
|
||||
2. 是否选错进程或子窗口;主窗是否未最大化导致侧栏未实例化。
|
||||
3. 控件是否离屏或尚未实例化。
|
||||
4. 应用是否为 Electron(可评估 Playwright)。
|
||||
5. 是否为自绘、游戏引擎、远程桌面或安全控件。
|
||||
6. 空树/树抖动时:最大化主窗;用 Inspect/影刀附着一次后再 probe(远程桌面工具可能干扰无障碍树)。
|
||||
|
||||
只有控件树确认不可用时才使用图像:
|
||||
|
||||
- 固定或记录 DPI、缩放、分辨率和主题。
|
||||
- 限定目标窗口和搜索区域。
|
||||
- 记录模板来源、置信度阈值和多匹配处理。
|
||||
- 匹配不唯一时停止。
|
||||
- 点击后仍验证业务状态。
|
||||
|
||||
U盾、人脸、动态口令和安全键盘交给人工,不用 OCR、Hook 或坐标绕过。
|
||||
|
||||
## 7. 诊断和留证
|
||||
|
||||
桌面 `health` / `probe-ui` 至少输出:
|
||||
|
||||
- UIA 依赖是否可用。
|
||||
- 目标进程和主窗口是否存在;是否已最大化(若业务需要)。
|
||||
- 关键窗口/控件是否各唯一匹配。
|
||||
- 当前窗口标题、Class、PID。
|
||||
- DPI/缩放诊断。
|
||||
|
||||
example 里的最小 `probe`(只探主窗+个别入口)**不等于**生产 probe 完整度;业务技能应对关键跳转节点分别探测或做深探。
|
||||
|
||||
手开 PowerShell 跑 `stats` / `health` / dump 时,必须显式对齐宿主的 `CLAW_USER_ID` / 数据根,否则会读到默认用户空库,误判熔断/冷却。
|
||||
|
||||
定位失败保存:
|
||||
|
||||
- 目标窗口和全屏截图。
|
||||
- UIA 树。
|
||||
- 顶层窗口枚举。
|
||||
- element map 逻辑名、候选数量和属性。
|
||||
- 应用版本、Windows版本、DPI和会话类型。
|
||||
|
||||
## 8. example 路由
|
||||
|
||||
真实成功参考见 [`../examples/real_desktop_rpa/README.md`](../examples/real_desktop_rpa/README.md)。该 example 默认只演示 `probe`、`dry-run` 和 `assisted`;不可逆动作必须由业务技能显式实现确认策略。
|
||||
Reference in New Issue
Block a user