"""脱敏 UIA element specs;复制到新技能后必须用真实拾取结果替换。""" from __future__ import annotations from dataclasses import dataclass from typing import Optional @dataclass(frozen=True) class WindowSpec: logical_name: str process_name: str class_name: str title: Optional[str] = None @dataclass(frozen=True) class ElementSpec: logical_name: str name: Optional[str] = None """UIA Name(内部 id,未必是界面中文)。""" value: Optional[str] = None """UIA Value(可见中文文案常在此)。""" automation_id: Optional[str] = None control_type: Optional[str] = None class_name: Optional[str] = None ancestor_name: Optional[str] = None """先定位到该 Name 的祖先,再在其下搜索。""" child_value_name: Optional[str] = None """在候选控件子树中查找该 Name 的子控件,并用 value 匹配其 Value。""" expected_count: int = 1 MAIN_WINDOW = WindowSpec("main_window", "WXWork", "WeWorkWindow", "企业微信") ADD_CUSTOMER_WINDOW = WindowSpec( "add_customer_window", "WXWork", "SearchExternalsWnd", "添加客户", ) CONTACTS_ENTRY = ElementSpec( "contacts_entry", name="org_op_new", control_type="TreeItem", ) # 示意:用子控件 main_chattext 的 Value 定位「新的客户」行(禁止全树第一个 status_layout) NEW_CUSTOMER_ROW = ElementSpec( "new_customer_row", name="status_layout", ancestor_name="wlist_view", child_value_name="main_chattext", value="新的客户", ) ADD_BUTTON = ElementSpec( "add_customer_button", name="wbtn_container", ancestor_name="search_external", ) SEARCH_INPUT = ElementSpec( "search_input", name="searchedit", ancestor_name="search_layout", )