ms-vite-plugin 1.4.40 → 1.4.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/api/dotocr.md +4 -4
- package/docs/api/node.md +242 -266
- package/docs/api/opencv.md +46 -356
- package/docs/apicn/dotocr.md +2 -2
- package/docs/apicn/node.md +245 -284
- package/docs/apipython/dotocr.md +2 -2
- package/docs/apipython/node.md +193 -215
- package/package.json +1 -1
package/docs/api/dotocr.md
CHANGED
|
@@ -75,7 +75,7 @@ function recognizeAbs(
|
|
|
75
75
|
y?: number,
|
|
76
76
|
ex?: number,
|
|
77
77
|
ey?: number,
|
|
78
|
-
confidenceThreshold?: number
|
|
78
|
+
confidenceThreshold?: number
|
|
79
79
|
): OCRChar[];
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -85,7 +85,7 @@ function recognizeAbs(
|
|
|
85
85
|
| `input` | string | 是 | | 输入源,支持 `"screen"`、图片文件路径、URL 或 imageId |
|
|
86
86
|
| `x`, `y` | number | 否 | 0 | 裁剪区域左上角坐标 |
|
|
87
87
|
| `ex`, `ey` | number | 否 | 0 | 裁剪区域右下角坐标;`ex` 或 `ey` 为 0 时分别使用图像宽度或高度 |
|
|
88
|
-
| `confidenceThreshold` | number
|
|
88
|
+
| `confidenceThreshold` | number | 否 | 0.8 | 相似度下限;`<=0` 时按 `0.8`;低于阈值的字符会被过滤;`>0.95` 时要求像素完全一致 |
|
|
89
89
|
|
|
90
90
|
**返回值:**`OCRChar[]`。按行从上到下、同一行从左到右排列。颜色按字库各字自带的前景色/偏色匹配,无需额外传色。
|
|
91
91
|
|
|
@@ -108,7 +108,7 @@ function findTextAbs(
|
|
|
108
108
|
ex?: number,
|
|
109
109
|
ey?: number,
|
|
110
110
|
confidenceThreshold?: number,
|
|
111
|
-
exactMatch?: boolean
|
|
111
|
+
exactMatch?: boolean
|
|
112
112
|
): OCRChar[];
|
|
113
113
|
```
|
|
114
114
|
|
|
@@ -120,7 +120,7 @@ function findTextAbs(
|
|
|
120
120
|
| `x`, `y` | number | 否 | 0 | 裁剪区域左上角坐标 |
|
|
121
121
|
| `ex`, `ey` | number | 否 | 0 | 裁剪区域右下角坐标;`ex` 或 `ey` 为 0 时分别使用图像宽度或高度 |
|
|
122
122
|
| `confidenceThreshold` | number | 否 | 0.8 | 单字符识别相似度下限;语义同 `recognizeAbs` |
|
|
123
|
-
| `exactMatch` | boolean | 否 | false
|
|
123
|
+
| `exactMatch` | boolean | 否 | false | `false` 为行内子串包含匹配;`true` 要求某一整行文本完全等于目标字符串 |
|
|
124
124
|
|
|
125
125
|
**返回值:**命中结果数组。每个目标最多返回一次命中(最先匹配到的行);每项的 `text` 是目标字符串。
|
|
126
126
|
|
package/docs/api/node.md
CHANGED
|
@@ -1,352 +1,328 @@
|
|
|
1
1
|
# 节点模块 (Node)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
用于查找和操作当前界面上的控件节点。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**注意**
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- 仅支持快点 Agent 模式
|
|
8
|
+
- 用完调用 `releaseNode()` 释放;找完节点即可释放,不必等点击结束
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**基本流程**
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
```text
|
|
13
|
+
createNodeSelector → 设置筛选条件 → getOneNodeInfo / getNodeInfo
|
|
14
|
+
→ 点击 / 输入 / 设值等 → releaseNode
|
|
15
|
+
```
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
---
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
## 创建选择器
|
|
19
20
|
|
|
20
21
|
```typescript
|
|
21
22
|
function createNodeSelector(params?: {
|
|
22
|
-
maxDepth?: number; //
|
|
23
|
-
mode?: number; //
|
|
23
|
+
maxDepth?: number; // 最大层级,默认 50;越小通常越快
|
|
24
|
+
mode?: number; // 抓取模式 1 | 2 | 3,默认 1
|
|
24
25
|
}): NodeSelector;
|
|
25
26
|
```
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
| `maxDepth` | number | 否 | 50 | 遍历的最大层级深度,默认 50 |
|
|
32
|
-
| `mode` | number | 否 | 1 | 抓取模式。支持模式 1、模式 2、模式 3,默认模式 1 |
|
|
33
|
-
|
|
34
|
-
**返回值:**
|
|
35
|
-
|
|
36
|
-
| 类型 | 描述 |
|
|
37
|
-
| -------------- | ---------------------- |
|
|
38
|
-
| `NodeSelector` | 新创建的节点选择器实例 |
|
|
39
|
-
|
|
40
|
-
**示例:**
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
// 创建选择器
|
|
44
|
-
const selector = createNodeSelector({
|
|
45
|
-
maxDepth: 20, // 最大20层深度
|
|
46
|
-
mode: 1, // 默认模式 1
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 节点信息接口
|
|
51
|
-
|
|
52
|
-
#### NodeBoundsInfo - 节点边界信息。
|
|
28
|
+
| 参数 | 默认 | 说明 |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `maxDepth` | `50` | 抓取深度,深层控件抓不到时可调大 |
|
|
31
|
+
| `mode` | `1` | 抓取模式,可选 `1` / `2` / `3`,默认 `1` |
|
|
53
32
|
|
|
54
33
|
```typescript
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
width: number; // 宽度
|
|
59
|
-
height: number; // 高度
|
|
60
|
-
centerX: number; // 中心点x坐标
|
|
61
|
-
centerY: number; // 中心点y坐标
|
|
62
|
-
}
|
|
34
|
+
const selector = createNodeSelector();
|
|
35
|
+
const shallow = createNodeSelector({ maxDepth: 15 });
|
|
36
|
+
const listPage = createNodeSelector({ mode: 2 });
|
|
63
37
|
```
|
|
64
38
|
|
|
65
|
-
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 节点信息
|
|
42
|
+
|
|
43
|
+
### 位置 `NodeBoundsInfo`
|
|
44
|
+
|
|
45
|
+
| 字段 | 说明 |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `x` / `y` | 左上角 |
|
|
48
|
+
| `width` / `height` | 宽高 |
|
|
49
|
+
| `centerX` / `centerY` | 中心点 |
|
|
50
|
+
|
|
51
|
+
### 节点 `NodeInfo`
|
|
52
|
+
|
|
53
|
+
**属性**
|
|
54
|
+
|
|
55
|
+
| 字段 | 说明 |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `id` | 节点 ID(内部定位用,不要改) |
|
|
58
|
+
| `identifier` | 控件标识符 |
|
|
59
|
+
| `label` | 标签文案 |
|
|
60
|
+
| `type` | 类型,如 `XCUIElementTypeButton` |
|
|
61
|
+
| `value` | 当前值 |
|
|
62
|
+
| `placeholderValue` | 输入框占位文字 |
|
|
63
|
+
| `title` | 标题 |
|
|
64
|
+
| `enabled` | 是否启用 |
|
|
65
|
+
| `bounds` | 位置大小 |
|
|
66
|
+
| `depth` | 层级 |
|
|
67
|
+
| `index` | 在父节点下的序号 |
|
|
68
|
+
| `parentId` | 父节点 ID |
|
|
69
|
+
| `childCount` | 子节点数量 |
|
|
70
|
+
|
|
71
|
+
**方法**
|
|
72
|
+
|
|
73
|
+
| 方法 | 说明 |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `hittable()` | 当前是否可点击(可见且未被挡住) |
|
|
76
|
+
| `scrollToVisible()` | 滚动到可见区域 |
|
|
77
|
+
| `tap()` | 单击(不可见时会先尝试滚到可见) |
|
|
78
|
+
| `doubleTap()` | 双击 |
|
|
79
|
+
| `press(duration?)` | 长按,`duration` 单位毫秒,默认 500 |
|
|
80
|
+
| `clickCenter()` | 点击中心坐标 |
|
|
81
|
+
| `clickRandom()` | 在节点范围内随机点击 |
|
|
82
|
+
| `clearInput()` | 清空输入内容 |
|
|
83
|
+
| `input(text)` | 追加输入(不先清空) |
|
|
84
|
+
| `setValue(text)` | 设置值(见下方) |
|
|
85
|
+
| `parent()` | 父节点 |
|
|
86
|
+
| `child(index)` | 第 `index` 个子节点 |
|
|
87
|
+
| `allChildren()` | 全部子节点 |
|
|
88
|
+
| `siblings()` | 全部兄弟节点 |
|
|
89
|
+
| `previousSiblings()` | 前面的兄弟 |
|
|
90
|
+
| `nextSiblings()` | 后面的兄弟 |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 选择器方法
|
|
95
|
+
|
|
96
|
+
### 加载与结果
|
|
97
|
+
|
|
98
|
+
| 方法 | 说明 |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| `releaseNode()` | 释放内存 |
|
|
101
|
+
| `loadNode(timeout?)` | 重新加载界面节点,默认超时 5000ms |
|
|
102
|
+
| `clearSelector()` | 清除已设置的筛选条件 |
|
|
103
|
+
| `xml(timeout?)` | 获取界面 XML,失败返回 `null` |
|
|
104
|
+
| `getNodeInfo(timeout?)` | 获取所有匹配节点 |
|
|
105
|
+
| `getOneNodeInfo(timeout?)` | 获取第一个匹配节点,没有则 `null` |
|
|
106
|
+
|
|
107
|
+
`timeout` 单位均为毫秒,默认 `5000`。
|
|
66
108
|
|
|
67
109
|
```typescript
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
value: string; // 节点值
|
|
74
|
-
placeholderValue: string; // 节点占位符值
|
|
75
|
-
title: string; // 节点名称
|
|
76
|
-
enabled: boolean; // 是否启用
|
|
77
|
-
bounds: NodeBoundsInfo; // 边界信息
|
|
78
|
-
depth: number; // 层级深度
|
|
79
|
-
index: number; // 索引
|
|
80
|
-
parentId: string; // 父节点ID
|
|
81
|
-
childCount: number; // 子节点数量
|
|
82
|
-
|
|
83
|
-
// 操作方法
|
|
84
|
-
clickCenter(): boolean; // 点击中心
|
|
85
|
-
clickRandom(): boolean; // 随机点击
|
|
86
|
-
hittable(): boolean; // 节点是否可接收事件,用于判断节点是否在屏幕可见
|
|
87
|
-
parent(): NodeInfo | null; // 获取父节点
|
|
88
|
-
child(index: number): NodeInfo | null; // 获取子节点
|
|
89
|
-
allChildren(): NodeInfo[]; // 获取所有子节点
|
|
90
|
-
siblings(): NodeInfo[]; // 获取兄弟节点
|
|
91
|
-
previousSiblings(): NodeInfo[]; // 获取前面的兄弟节点
|
|
92
|
-
nextSiblings(): NodeInfo[]; // 获取后面的兄弟节点
|
|
93
|
-
}
|
|
110
|
+
const selector = createNodeSelector();
|
|
111
|
+
const nodes = selector.label("确定").getNodeInfo(5000);
|
|
112
|
+
const one = selector.getOneNodeInfo(3000);
|
|
113
|
+
const xml = selector.xml();
|
|
114
|
+
selector.releaseNode();
|
|
94
115
|
```
|
|
95
116
|
|
|
96
|
-
###
|
|
117
|
+
### 筛选条件
|
|
97
118
|
|
|
98
|
-
|
|
119
|
+
可链式调用,多个条件同时满足(并且关系)。
|
|
120
|
+
带 `Match` 的为模糊/正则匹配。
|
|
99
121
|
|
|
100
|
-
|
|
101
|
-
// releaseNode - 释放内存
|
|
102
|
-
releaseNode(): void;
|
|
122
|
+
**文本**
|
|
103
123
|
|
|
104
|
-
|
|
105
|
-
|
|
124
|
+
| 方法 | 说明 |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `label` / `labelMatch` | 标签 |
|
|
127
|
+
| `title` / `titleMatch` | 标题 |
|
|
128
|
+
| `identifier` / `identifierMatch` | 标识符 |
|
|
129
|
+
| `value` / `valueMatch` | 值 |
|
|
130
|
+
| `placeholderValue` / `placeholderValueMatch` | 占位文字 |
|
|
106
131
|
|
|
107
|
-
|
|
108
|
-
getNodeInfo(timeout?: number): NodeInfo[]
|
|
132
|
+
**类型与状态**
|
|
109
133
|
|
|
110
|
-
|
|
111
|
-
|
|
134
|
+
| 方法 | 说明 |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| `type` / `typeMatch` | 类型,如 `XCUIElementTypeButton` |
|
|
137
|
+
| `enabled` | 是否启用 |
|
|
112
138
|
|
|
113
|
-
|
|
114
|
-
loadNode(timeout?: number): NodeSelector;
|
|
139
|
+
**位置与结构**
|
|
115
140
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
| 方法 | 说明 |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `index` | 序号 |
|
|
144
|
+
| `depth` | 层级 |
|
|
145
|
+
| `childCount` | 子节点数,支持数字或如 `">0"` |
|
|
146
|
+
| `bounds(x, y, width, height)` | 区域 |
|
|
147
|
+
| `xpath` | XPath |
|
|
148
|
+
| `id` | 按节点 ID |
|
|
121
149
|
|
|
122
150
|
```typescript
|
|
123
|
-
|
|
151
|
+
// 精确
|
|
152
|
+
selector.label("确定").type("XCUIElementTypeButton").getOneNodeInfo(3000);
|
|
124
153
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
154
|
+
// 模糊
|
|
155
|
+
selector.labelMatch(".*登录.*").getNodeInfo(3000);
|
|
156
|
+
selector.identifierMatch("^login_").getNodeInfo(3000);
|
|
128
157
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
selector.releaseNode();
|
|
158
|
+
// 组合
|
|
159
|
+
selector
|
|
160
|
+
.type("XCUIElementTypeTextField")
|
|
161
|
+
.enabled(true)
|
|
162
|
+
.getOneNodeInfo(3000);
|
|
136
163
|
```
|
|
137
164
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
##### 文本相关
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
// 精确匹配标签
|
|
144
|
-
label(label: string): NodeSelector
|
|
145
|
-
|
|
146
|
-
// 标签模糊匹配
|
|
147
|
-
labelMatch(match: string): NodeSelector
|
|
165
|
+
常见类型:`XCUIElementTypeButton`、`StaticText`、`TextField`、`SecureTextField`、`TextView`、`SearchField`、`Cell`、`Table`、`CollectionView`、`PickerWheel`、`Switch`、`Slider` 等。
|
|
148
166
|
|
|
149
|
-
|
|
150
|
-
title(title: string): NodeSelector
|
|
167
|
+
---
|
|
151
168
|
|
|
152
|
-
|
|
153
|
-
titleMatch(match: string): NodeSelector
|
|
169
|
+
## 节点操作说明
|
|
154
170
|
|
|
155
|
-
|
|
156
|
-
identifier(identifier: string): NodeSelector
|
|
157
|
-
|
|
158
|
-
// 标识符模糊匹配
|
|
159
|
-
identifierMatch(match: string): NodeSelector
|
|
160
|
-
|
|
161
|
-
// 精确匹配值
|
|
162
|
-
value(value: string): NodeSelector
|
|
163
|
-
|
|
164
|
-
// 值模糊匹配
|
|
165
|
-
valueMatch(match: string): NodeSelector
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**示例:**
|
|
171
|
+
### 是否可点 / 滚到可见
|
|
169
172
|
|
|
170
173
|
```typescript
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// 查找名称包含"button"的元素
|
|
178
|
-
const buttons = selector.titleMatch("button").getNodeInfo(3000);
|
|
179
|
-
|
|
180
|
-
// 查找值为"submit"的元素
|
|
181
|
-
const submitElement = selector.value("submit").getOneNodeInfo(2000);
|
|
182
|
-
|
|
183
|
-
// 通过标识符查找
|
|
184
|
-
const elById = selector.identifier("login_btn").getOneNodeInfo(2000);
|
|
185
|
-
const fuzzy = selector.identifierMatch("^login_.*").getNodeInfo(3000);
|
|
174
|
+
if (node.hittable()) {
|
|
175
|
+
node.tap();
|
|
176
|
+
} else {
|
|
177
|
+
node.scrollToVisible();
|
|
178
|
+
node.tap();
|
|
179
|
+
}
|
|
186
180
|
```
|
|
187
181
|
|
|
188
|
-
|
|
182
|
+
- `hittable()`:当前能否点到
|
|
183
|
+
- `scrollToVisible()`:手动滚到可见
|
|
184
|
+
- `tap` / `doubleTap` / `press`:不可见时会自动尝试滚到可见再操作
|
|
189
185
|
|
|
190
|
-
|
|
191
|
-
// 精确匹配类型
|
|
192
|
-
type(type: string): NodeSelector
|
|
186
|
+
### 点击
|
|
193
187
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
**示例:**
|
|
188
|
+
| 方法 | 说明 |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `tap()` | 推荐,单击 |
|
|
191
|
+
| `doubleTap()` | 双击 |
|
|
192
|
+
| `press(ms?)` | 长按,默认 500ms |
|
|
193
|
+
| `clickCenter()` | 点中心坐标 |
|
|
194
|
+
| `clickRandom()` | 范围内随机点 |
|
|
202
195
|
|
|
203
196
|
```typescript
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// 查找所有文本框
|
|
209
|
-
const textFields = selector
|
|
210
|
-
.typeMatch("XCUIElementTypeTextField")
|
|
211
|
-
.getNodeInfo(3000);
|
|
212
|
-
|
|
213
|
-
// 查找启用的元素
|
|
214
|
-
const enabledElements = selector.enabled(true).getNodeInfo(3000);
|
|
197
|
+
const btn = selector
|
|
198
|
+
.label("确定")
|
|
199
|
+
.type("XCUIElementTypeButton")
|
|
200
|
+
.getOneNodeInfo(3000);
|
|
215
201
|
|
|
216
|
-
|
|
202
|
+
if (btn) {
|
|
203
|
+
btn.tap();
|
|
204
|
+
btn.doubleTap();
|
|
205
|
+
btn.press(800);
|
|
206
|
+
}
|
|
217
207
|
```
|
|
218
208
|
|
|
219
|
-
|
|
209
|
+
### 输入与设值
|
|
220
210
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
211
|
+
| 方法 | 说明 |
|
|
212
|
+
| --- | --- |
|
|
213
|
+
| `clearInput()` | 清空 |
|
|
214
|
+
| `input(text)` | 追加输入,不清空原内容 |
|
|
215
|
+
| `setValue(text)` | 按控件类型设置 |
|
|
224
216
|
|
|
225
|
-
|
|
226
|
-
depth(depth: number): NodeSelector
|
|
217
|
+
**`setValue` 行为**
|
|
227
218
|
|
|
228
|
-
|
|
229
|
-
|
|
219
|
+
| 控件类型 | 传参 | 效果 |
|
|
220
|
+
| --- | --- | --- |
|
|
221
|
+
| `PickerWheel` | 选项文案,如 `"1小时"` | 滚到该选项 |
|
|
222
|
+
| 文本框类(TextField 等) | 字符串 | 聚焦后追加输入,不先清空 |
|
|
230
223
|
|
|
231
|
-
|
|
232
|
-
bounds(x: number, y: number, width: number, height: number): NodeSelector
|
|
224
|
+
覆盖原内容请先清空:
|
|
233
225
|
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
```typescript
|
|
227
|
+
field.clearInput();
|
|
228
|
+
field.setValue("hello");
|
|
229
|
+
// 或
|
|
230
|
+
field.clearInput();
|
|
231
|
+
field.input("hello");
|
|
236
232
|
```
|
|
237
233
|
|
|
238
|
-
**示例:**
|
|
239
|
-
|
|
240
234
|
```typescript
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
// 查找特定深度的元素
|
|
247
|
-
const level3Elements = selector.depth(3).getNodeInfo(3000);
|
|
248
|
-
|
|
249
|
-
// 查找有子节点的元素
|
|
250
|
-
const parentElements = selector.childCount(">0").getNodeInfo(3000);
|
|
251
|
-
|
|
252
|
-
// 查找特定区域的元素
|
|
253
|
-
const regionElements = selector.bounds(100, 100, 200, 50).getNodeInfo(3000);
|
|
254
|
-
|
|
255
|
-
// 使用 XPath 查找
|
|
256
|
-
const xpathElements = selector.xpath("//*[@title='快点JS']").getNodeInfo(3000);
|
|
257
|
-
|
|
258
|
-
selector.releaseNode();
|
|
235
|
+
const wheel = selector.type("XCUIElementTypePickerWheel").getOneNodeInfo(3000);
|
|
236
|
+
if (wheel) {
|
|
237
|
+
wheel.setValue("1小时");
|
|
238
|
+
}
|
|
259
239
|
```
|
|
260
240
|
|
|
261
|
-
###
|
|
262
|
-
|
|
263
|
-
#### 点击操作
|
|
241
|
+
### 树导航
|
|
264
242
|
|
|
265
243
|
```typescript
|
|
266
|
-
|
|
267
|
-
|
|
244
|
+
const field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000);
|
|
245
|
+
if (field) {
|
|
246
|
+
const parent = field.parent();
|
|
247
|
+
const children = parent?.allChildren() ?? [];
|
|
248
|
+
const prev = field.previousSiblings();
|
|
249
|
+
const next = field.nextSiblings();
|
|
250
|
+
const second = parent?.child(1);
|
|
251
|
+
}
|
|
252
|
+
```
|
|
268
253
|
|
|
269
|
-
|
|
270
|
-
node.clickRandom(): boolean;
|
|
254
|
+
---
|
|
271
255
|
|
|
272
|
-
|
|
273
|
-
node.hittable(): boolean;
|
|
274
|
-
```
|
|
256
|
+
## 示例
|
|
275
257
|
|
|
276
|
-
|
|
258
|
+
### 登录
|
|
277
259
|
|
|
278
260
|
```typescript
|
|
279
261
|
const selector = createNodeSelector();
|
|
280
262
|
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
263
|
+
try {
|
|
264
|
+
const user = selector.type("XCUIElementTypeTextField").getOneNodeInfo(5000);
|
|
265
|
+
if (user) {
|
|
266
|
+
user.clearInput();
|
|
267
|
+
user.setValue("demo_user");
|
|
268
|
+
}
|
|
286
269
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
270
|
+
const pass = selector
|
|
271
|
+
.clearSelector()
|
|
272
|
+
.type("XCUIElementTypeSecureTextField")
|
|
273
|
+
.getOneNodeInfo(3000);
|
|
274
|
+
if (pass) {
|
|
275
|
+
pass.clearInput();
|
|
276
|
+
pass.setValue("password");
|
|
277
|
+
}
|
|
290
278
|
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
279
|
+
const login = selector
|
|
280
|
+
.clearSelector()
|
|
281
|
+
.labelMatch(".*登录.*")
|
|
282
|
+
.type("XCUIElementTypeButton")
|
|
283
|
+
.getOneNodeInfo(3000);
|
|
284
|
+
if (login) {
|
|
285
|
+
login.tap();
|
|
294
286
|
}
|
|
287
|
+
} finally {
|
|
288
|
+
selector.releaseNode();
|
|
295
289
|
}
|
|
296
|
-
|
|
297
|
-
// 随机点击避免检测
|
|
298
|
-
const randomClick = confirmBtn?.clickRandom();
|
|
299
|
-
|
|
300
|
-
selector.releaseNode();
|
|
301
290
|
```
|
|
302
291
|
|
|
303
|
-
|
|
292
|
+
### 列表里靠后的项
|
|
304
293
|
|
|
305
294
|
```typescript
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
// 获取所有子节点
|
|
313
|
-
node.allChildren(): NodeInfo[]
|
|
314
|
-
|
|
315
|
-
// 获取兄弟节点
|
|
316
|
-
node.siblings(): NodeInfo[]
|
|
317
|
-
|
|
318
|
-
// 获取前面的兄弟节点
|
|
319
|
-
node.previousSiblings(): NodeInfo[]
|
|
320
|
-
|
|
321
|
-
// 获取后面的兄弟节点
|
|
322
|
-
node.nextSiblings(): NodeInfo[]
|
|
295
|
+
const selector = createNodeSelector({ mode: 2 });
|
|
296
|
+
const item = selector.label("第 30 项").getOneNodeInfo(5000);
|
|
297
|
+
if (item) {
|
|
298
|
+
item.tap(); // 不在可见区域时会自动滚动
|
|
299
|
+
}
|
|
300
|
+
selector.releaseNode();
|
|
323
301
|
```
|
|
324
302
|
|
|
325
|
-
|
|
303
|
+
### 查看界面结构
|
|
326
304
|
|
|
327
305
|
```typescript
|
|
328
306
|
const selector = createNodeSelector();
|
|
307
|
+
const xml = selector.xml(8000);
|
|
308
|
+
if (xml) {
|
|
309
|
+
logi(xml);
|
|
310
|
+
}
|
|
311
|
+
selector.releaseNode();
|
|
312
|
+
```
|
|
329
313
|
|
|
330
|
-
|
|
331
|
-
const textField = selector
|
|
332
|
-
.type("XCUIElementTypeTextField")
|
|
333
|
-
.getOneNodeInfo(3000);
|
|
314
|
+
---
|
|
334
315
|
|
|
335
|
-
|
|
336
|
-
const container = textField.parent();
|
|
337
|
-
if (container) {
|
|
338
|
-
logi(`容器类型: ${container.type}`);
|
|
316
|
+
## 常见问题
|
|
339
317
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
logi(`容器包含 ${siblings.length} 个子元素`);
|
|
318
|
+
**找不到节点**
|
|
319
|
+
加大超时;减少条件或改用 `*Match`;换 `mode`;用 `xml()` 看实际文案和类型。
|
|
343
320
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
(node) => node.type === "XCUIElementTypeButton",
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
321
|
+
**点了没反应**
|
|
322
|
+
先看 `hittable()`;确认点到的是目标控件;可对比 `clickCenter()`。
|
|
350
323
|
|
|
351
|
-
|
|
352
|
-
|
|
324
|
+
**输入叠在旧文字后面**
|
|
325
|
+
`input` / 文本类 `setValue` 是追加,先 `clearInput()`。
|
|
326
|
+
|
|
327
|
+
**滚轮设不中**
|
|
328
|
+
`setValue` 要传界面上显示的选项文案;确认类型是 `PickerWheel`;多列时选对那一列。
|