ms-vite-plugin 1.4.41 → 1.4.45
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/global.md +70 -15
- package/docs/api/node.md +239 -348
- package/docs/apicn/global.md +65 -10
- package/docs/apicn/node.md +242 -365
- package/docs/apipython/g.md +74 -23
- package/docs/apipython/node.md +186 -287
- package/docs/httpapi/api.md +190 -189
- package/package.json +1 -1
package/docs/apipython/node.md
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
# 节点模块 (Node)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
用于查找和操作当前界面上的控件节点。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**注意**
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- 仅支持快点 Agent 模式
|
|
8
|
+
- 通过 `from kuaijs import node` 使用
|
|
9
|
+
|
|
10
|
+
**基本流程**
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
createNodeSelector → 设置筛选条件 → getOneNodeInfo / getNodeInfo
|
|
14
|
+
→ 点击 / 输入 / 设值等
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
8
18
|
|
|
9
19
|
## 类型定义
|
|
10
20
|
|
|
11
21
|
```python
|
|
12
|
-
from typing import List,
|
|
22
|
+
from typing import List, Optional, TypedDict
|
|
13
23
|
|
|
14
24
|
class NodeBounds:
|
|
15
25
|
x: int
|
|
@@ -52,361 +62,250 @@ class NodeInfo:
|
|
|
52
62
|
def nextSiblings(self) -> List["NodeInfo"]: ...
|
|
53
63
|
|
|
54
64
|
class NodeSelectorOptions(TypedDict, total=False):
|
|
55
|
-
maxDepth: int #
|
|
56
|
-
mode: int
|
|
65
|
+
maxDepth: int # 最大层级,默认 50
|
|
66
|
+
mode: int # 抓取模式 1 | 2 | 3,默认 1
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
节点选择器是访问 UI 元素的核心工具,提供了灵活的筛选和查找机制。
|
|
62
|
-
|
|
63
|
-
### 创建节点选择器
|
|
64
|
-
|
|
65
|
-
#### `createNodeSelector` - 创建节点选择器
|
|
69
|
+
---
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
## 创建选择器
|
|
68
72
|
|
|
69
73
|
```python
|
|
70
74
|
def createNodeSelector(params: Optional[NodeSelectorOptions] = None) -> NodeSelector
|
|
71
75
|
```
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
| `maxDepth` | int | 否 | 50 | 最大层级深度,默认 50 |
|
|
78
|
-
| `mode` | int | 否 | 1 | 抓取模式。支持模式 1、模式 2、模式 3,默认模式 1 |
|
|
79
|
-
|
|
80
|
-
**返回值:** `NodeSelector`
|
|
81
|
-
|
|
82
|
-
**示例:**
|
|
77
|
+
| 参数 | 默认 | 说明 |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| `maxDepth` | `50` | 抓取深度,深层控件抓不到时可调大 |
|
|
80
|
+
| `mode` | `1` | 抓取模式,可选 `1` / `2` / `3`,默认 `1` |
|
|
83
81
|
|
|
84
82
|
```python
|
|
85
83
|
from kuaijs import node
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"mode": 1 # 默认模式 1
|
|
91
|
-
})
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 选择器方法
|
|
95
|
-
|
|
96
|
-
#### 获取节点
|
|
97
|
-
|
|
98
|
-
```python
|
|
99
|
-
# 获取当前页面的 XML 字符串
|
|
100
|
-
def xml(timeout: int = 5000) -> Optional[str]
|
|
101
|
-
|
|
102
|
-
# 获取多个节点
|
|
103
|
-
def getNodeInfo(timeout: int = 5000) -> List[NodeInfo]
|
|
104
|
-
|
|
105
|
-
# 获取单个节点
|
|
106
|
-
def getOneNodeInfo(timeout: int = 5000) -> Optional[NodeInfo]
|
|
107
|
-
|
|
108
|
-
# 加载节点数据(通常内部自动调用)
|
|
109
|
-
def loadNode(timeout: int = 5000) -> NodeSelector
|
|
110
|
-
|
|
111
|
-
# 清除所有选择条件
|
|
112
|
-
def clearSelector() -> NodeSelector
|
|
85
|
+
selector = node.createNodeSelector()
|
|
86
|
+
shallow = node.createNodeSelector({"maxDepth": 15})
|
|
87
|
+
list_page = node.createNodeSelector({"mode": 2})
|
|
113
88
|
```
|
|
114
89
|
|
|
115
|
-
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 节点信息
|
|
93
|
+
|
|
94
|
+
### 属性
|
|
95
|
+
|
|
96
|
+
| 字段 | 说明 |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `id` | 节点 ID(内部定位用,不要改) |
|
|
99
|
+
| `identifier` | 控件标识符 |
|
|
100
|
+
| `label` | 标签文案 |
|
|
101
|
+
| `type` | 类型,如 `XCUIElementTypeButton` |
|
|
102
|
+
| `value` | 当前值 |
|
|
103
|
+
| `placeholderValue` | 输入框占位文字 |
|
|
104
|
+
| `title` | 标题 |
|
|
105
|
+
| `enabled` | 是否启用 |
|
|
106
|
+
| `bounds` | 位置大小 |
|
|
107
|
+
| `depth` / `index` | 层级 / 序号 |
|
|
108
|
+
| `parentId` / `childCount` | 父节点 ID / 子节点数 |
|
|
109
|
+
|
|
110
|
+
### 方法
|
|
111
|
+
|
|
112
|
+
| 方法 | 说明 |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| `hittable()` | 当前是否可点击(可见且未被挡住) |
|
|
115
|
+
| `scrollToVisible()` | 仅滚动到可见,不点击;一般不必手动调用 |
|
|
116
|
+
| `tap()` | 单击;不可见时会先自动滚到可见 |
|
|
117
|
+
| `doubleTap()` | 双击;不可见时会先自动滚到可见 |
|
|
118
|
+
| `press(duration=500)` | 长按,毫秒,默认 500;不可见时会先自动滚到可见 |
|
|
119
|
+
| `clickCenter()` | 点击中心(坐标点击,不会自动滚动) |
|
|
120
|
+
| `clickRandom()` | 范围内随机点击(坐标点击,不会自动滚动) |
|
|
121
|
+
| `clearInput()` | 清空输入(内部会先 `tap` 聚焦,因而也会自动滚到可见) |
|
|
122
|
+
| `input(text)` | 追加输入(不先清空;内部会先 `tap` 聚焦) |
|
|
123
|
+
| `setValue(text)` | 设置值(见下方;不可见时会先自动滚到可见) |
|
|
124
|
+
| `parent()` / `child(i)` / `allChildren()` | 父 / 子 / 全部子节点 |
|
|
125
|
+
| `siblings()` / `previousSiblings()` / `nextSiblings()` | 兄弟节点 |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 选择器方法
|
|
130
|
+
|
|
131
|
+
### 加载与结果
|
|
132
|
+
|
|
133
|
+
| 方法 | 说明 |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `loadNode(timeout=5000)` | 重新加载界面节点 |
|
|
136
|
+
| `clearSelector()` | 清除筛选条件 |
|
|
137
|
+
| `xml(timeout=5000)` | 获取界面 XML,失败返回 `None` |
|
|
138
|
+
| `getNodeInfo(timeout=5000)` | 所有匹配节点 |
|
|
139
|
+
| `getOneNodeInfo(timeout=5000)` | 第一个匹配节点,没有则 `None` |
|
|
140
|
+
|
|
141
|
+
`timeout` 单位毫秒。
|
|
116
142
|
|
|
117
143
|
```python
|
|
118
144
|
from kuaijs import node
|
|
119
145
|
|
|
120
146
|
selector = node.createNodeSelector()
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
print(f"找到 {len(all_nodes)} 个节点")
|
|
125
|
-
|
|
126
|
-
# 获取第一个匹配的节点
|
|
127
|
-
first_node = selector.getOneNodeInfo(3000)
|
|
128
|
-
if first_node:
|
|
129
|
-
print(f"节点标签: {first_node.label}")
|
|
147
|
+
nodes = selector.label("确定").getNodeInfo(5000)
|
|
148
|
+
one = selector.getOneNodeInfo(3000)
|
|
149
|
+
xml = selector.xml()
|
|
130
150
|
```
|
|
131
151
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
##### 文本相关
|
|
135
|
-
|
|
136
|
-
```python
|
|
137
|
-
# 精确匹配标签
|
|
138
|
-
def label(text: str) -> NodeSelector
|
|
139
|
-
|
|
140
|
-
# 标签模糊匹配
|
|
141
|
-
def labelMatch(pattern: str) -> NodeSelector
|
|
142
|
-
|
|
143
|
-
# 精确匹配名称
|
|
144
|
-
def title(text: str) -> NodeSelector
|
|
152
|
+
### 筛选条件
|
|
145
153
|
|
|
146
|
-
|
|
147
|
-
def titleMatch(pattern: str) -> NodeSelector
|
|
154
|
+
可链式调用,多个条件同时满足。带 `Match` 的为模糊匹配。
|
|
148
155
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
# 精确匹配值
|
|
156
|
-
def value(text: str) -> NodeSelector
|
|
157
|
-
|
|
158
|
-
# 值模糊匹配
|
|
159
|
-
def valueMatch(pattern: str) -> NodeSelector
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
**示例:**
|
|
156
|
+
| 分类 | 方法 |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| 文本 | `label` / `labelMatch`、`title` / `titleMatch`、`identifier` / `identifierMatch`、`value` / `valueMatch`、`placeholderValue` / `placeholderValueMatch` |
|
|
159
|
+
| 类型状态 | `type` / `typeMatch`、`enabled` |
|
|
160
|
+
| 结构位置 | `index`、`depth`、`childCount`(支持 `">0"`)、`bounds`、`xpath`、`id` |
|
|
163
161
|
|
|
164
162
|
```python
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
# 查找包含"登录"的元素
|
|
169
|
-
login_elements = selector.labelMatch(".*登录.*").getNodeInfo(3000)
|
|
170
|
-
|
|
171
|
-
# 查找名称包含"button"的元素
|
|
172
|
-
buttons = selector.titleMatch("button").getNodeInfo(3000)
|
|
173
|
-
|
|
174
|
-
# 查找值为"submit"的元素
|
|
175
|
-
submit_element = selector.value("submit").getOneNodeInfo(2000)
|
|
176
|
-
|
|
177
|
-
# 通过标识符查找
|
|
178
|
-
el_by_id = selector.identifier("login_btn").getOneNodeInfo(2000)
|
|
179
|
-
fuzzy = selector.identifierMatch("^login_.*").getNodeInfo(3000)
|
|
163
|
+
selector.label("确定").type("XCUIElementTypeButton").getOneNodeInfo(3000)
|
|
164
|
+
selector.labelMatch(".*登录.*").getNodeInfo(3000)
|
|
165
|
+
selector.type("XCUIElementTypeTextField").enabled(True).getOneNodeInfo(3000)
|
|
180
166
|
```
|
|
181
167
|
|
|
182
|
-
|
|
168
|
+
常见类型:`Button`、`StaticText`、`TextField`、`SecureTextField`、`TextView`、`SearchField`、`Cell`、`Table`、`CollectionView`、`PickerWheel`、`Switch`、`Slider` 等(完整名为 `XCUIElementType...`)。
|
|
183
169
|
|
|
184
|
-
|
|
185
|
-
# 精确匹配类型
|
|
186
|
-
def type(type_title: str) -> NodeSelector
|
|
170
|
+
---
|
|
187
171
|
|
|
188
|
-
|
|
189
|
-
def typeMatch(pattern: str) -> NodeSelector
|
|
172
|
+
## 节点操作说明
|
|
190
173
|
|
|
191
|
-
|
|
192
|
-
def enabled(flag: bool) -> NodeSelector
|
|
193
|
-
```
|
|
174
|
+
### 是否可点 / 滚到可见
|
|
194
175
|
|
|
195
|
-
|
|
176
|
+
`tap` / `doubleTap` / `press` / `setValue`(以及内部会先 `tap` 的 `clearInput` / `input`)在元素当前不可见时,会**自动**先滚到可见再操作,一般不用手写滚动:
|
|
196
177
|
|
|
197
178
|
```python
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
all_buttons = selector.type("XCUIElementTypeButton").getNodeInfo(3000)
|
|
204
|
-
|
|
205
|
-
# 查找所有文本框
|
|
206
|
-
text_fields = selector.typeMatch("XCUIElementTypeTextField").getNodeInfo(3000)
|
|
207
|
-
|
|
208
|
-
# 查找启用的元素
|
|
209
|
-
enabled_elements = selector.enabled(True).getNodeInfo(3000)
|
|
179
|
+
# 推荐:直接操作,不可见时会自动滚到可见
|
|
180
|
+
node.tap()
|
|
181
|
+
node.doubleTap()
|
|
182
|
+
node.press(800)
|
|
183
|
+
node.setValue("hello")
|
|
210
184
|
```
|
|
211
185
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
# 索引位置
|
|
216
|
-
def index(idx: int) -> NodeSelector
|
|
217
|
-
|
|
218
|
-
# 层级深度
|
|
219
|
-
def depth(d: int) -> NodeSelector
|
|
220
|
-
|
|
221
|
-
# 子节点数量(支持表达式,如 ">0")
|
|
222
|
-
def childCount(expr: Union[int, str]) -> NodeSelector
|
|
186
|
+
- `hittable()`:当前能否点到(可见且未被挡住),用于排查“点了没反应”
|
|
187
|
+
- `scrollToVisible()`:只滚到可见、不点击;仅在你想先露出元素、稍后再操作时使用
|
|
188
|
+
- `clickCenter()` / `clickRandom()`:按坐标点击,**不会**自动滚动
|
|
223
189
|
|
|
224
|
-
|
|
225
|
-
def bounds(x: int, y: int, width: int, height: int) -> NodeSelector
|
|
226
|
-
|
|
227
|
-
# XPath 路径
|
|
228
|
-
def xpath(path: str) -> NodeSelector
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
**说明:** `*_match` 支持正则/模糊匹配;`childCount` 支持表达式(如 `>0`)。
|
|
232
|
-
|
|
233
|
-
**示例:**
|
|
190
|
+
### 点击
|
|
234
191
|
|
|
235
192
|
```python
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
#
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
#
|
|
247
|
-
parent_elements = selector.childCount(">0").getNodeInfo(3000)
|
|
248
|
-
|
|
249
|
-
# 查找特定区域的元素
|
|
250
|
-
region_elements = selector.bounds(100, 100, 200, 50).getNodeInfo(3000)
|
|
251
|
-
|
|
252
|
-
# 使用 XPath 查找
|
|
253
|
-
xpath_elements = selector.xpath("//*[@title='快点JS']").getNodeInfo(3000)
|
|
193
|
+
btn = (
|
|
194
|
+
selector.label("确定")
|
|
195
|
+
.type("XCUIElementTypeButton")
|
|
196
|
+
.getOneNodeInfo(3000)
|
|
197
|
+
)
|
|
198
|
+
if btn:
|
|
199
|
+
btn.tap() # 不可见时自动滚到可见
|
|
200
|
+
btn.doubleTap() # 同上
|
|
201
|
+
btn.press(800) # 同上
|
|
202
|
+
# btn.clickCenter() # 坐标点击,不自动滚动
|
|
203
|
+
# btn.clickRandom()
|
|
254
204
|
```
|
|
255
205
|
|
|
256
|
-
|
|
206
|
+
### 输入与设值
|
|
257
207
|
|
|
258
|
-
|
|
208
|
+
| 方法 | 说明 |
|
|
209
|
+
| --- | --- |
|
|
210
|
+
| `clearInput()` | 清空(内部先 `tap` 聚焦,不可见时也会自动滚到可见) |
|
|
211
|
+
| `input(text)` | 追加输入(内部先 `tap` 聚焦) |
|
|
212
|
+
| `setValue(text)` | 按类型设置;不可见时会先自动滚到可见 |
|
|
259
213
|
|
|
260
|
-
|
|
214
|
+
| 控件 | 传参 | 效果 |
|
|
215
|
+
| --- | --- | --- |
|
|
216
|
+
| `PickerWheel` | 选项文案,如 `"1小时"` | 滚到该选项(控件本身不可见时也会先自动滚到可见) |
|
|
217
|
+
| 文本框类 | 字符串 | 追加输入,不先清空 |
|
|
261
218
|
|
|
262
219
|
```python
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
# 随机点击节点区域(坐标点击)
|
|
267
|
-
def clickRandom() -> bool
|
|
268
|
-
|
|
269
|
-
# 节点是否可接收事件(用于判断是否显示在屏幕上)
|
|
270
|
-
def hittable() -> bool
|
|
271
|
-
|
|
272
|
-
# 无障碍点击
|
|
273
|
-
def tap() -> bool
|
|
274
|
-
|
|
275
|
-
# 无障碍双击
|
|
276
|
-
def doubleTap() -> bool
|
|
277
|
-
|
|
278
|
-
# 无障碍长按,duration 单位毫秒,默认 500
|
|
279
|
-
def press(duration: int = 500) -> bool
|
|
280
|
-
|
|
281
|
-
# 将节点滚动到可见区域
|
|
282
|
-
def scrollToVisible() -> bool
|
|
220
|
+
field.clearInput()
|
|
221
|
+
field.setValue("hello")
|
|
283
222
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
def input(text: str) -> bool
|
|
289
|
-
|
|
290
|
-
# 设置节点的值
|
|
291
|
-
def setValue(text: str) -> bool
|
|
223
|
+
wheel = selector.type("XCUIElementTypePickerWheel").getOneNodeInfo(3000)
|
|
224
|
+
if wheel:
|
|
225
|
+
# 不可见时会自动滚到可见,再调到目标选项
|
|
226
|
+
wheel.setValue("1小时")
|
|
292
227
|
```
|
|
293
228
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
通过无障碍 API 直接操作节点,不依赖坐标点击。
|
|
297
|
-
|
|
298
|
-
| 方法 | 参数 | 说明 |
|
|
299
|
-
| --- | --- | --- |
|
|
300
|
-
| `tap()` | 无 | 无障碍单击 |
|
|
301
|
-
| `doubleTap()` | 无 | 无障碍双击 |
|
|
302
|
-
| `press(duration=500)` | `duration`:长按持续时间,单位毫秒,默认 500 | 无障碍长按 |
|
|
303
|
-
|
|
304
|
-
**示例:**
|
|
229
|
+
### 树导航
|
|
305
230
|
|
|
306
231
|
```python
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
# 无障碍单击
|
|
314
|
-
btn.tap()
|
|
315
|
-
|
|
316
|
-
# 无障碍双击
|
|
317
|
-
btn.doubleTap()
|
|
318
|
-
|
|
319
|
-
# 无障碍长按 800ms
|
|
320
|
-
btn.press(800)
|
|
232
|
+
field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000)
|
|
233
|
+
if field:
|
|
234
|
+
parent = field.parent()
|
|
235
|
+
children = parent.allChildren() if parent else []
|
|
236
|
+
prev = field.previousSiblings()
|
|
237
|
+
next_ = field.nextSiblings()
|
|
321
238
|
```
|
|
322
239
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
按控件类型自动处理,常用支持如下:
|
|
326
|
-
|
|
327
|
-
| 控件类型 | 传参示例 | 说明 |
|
|
328
|
-
| --- | --- | --- |
|
|
329
|
-
| `XCUIElementTypePickerWheel` | `"1小时"` | 滚轮选到对应选项文案 |
|
|
330
|
-
| `XCUIElementTypeTextField` | `"hello"` | 先聚焦再输入文本 |
|
|
331
|
-
| `XCUIElementTypeSecureTextField` | `"123456"` | 同上 |
|
|
332
|
-
| `XCUIElementTypeTextView` | `"多行内容"` | 同上 |
|
|
333
|
-
| `XCUIElementTypeSearchField` | `"关键词"` | 同上 |
|
|
240
|
+
---
|
|
334
241
|
|
|
335
|
-
|
|
242
|
+
## 示例
|
|
336
243
|
|
|
337
|
-
|
|
244
|
+
### 登录
|
|
338
245
|
|
|
339
246
|
```python
|
|
340
247
|
from kuaijs import node
|
|
341
248
|
|
|
342
249
|
selector = node.createNodeSelector()
|
|
343
250
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
wheel.setValue("1小时")
|
|
251
|
+
user = selector.type("XCUIElementTypeTextField").getOneNodeInfo(5000)
|
|
252
|
+
if user:
|
|
253
|
+
user.clearInput()
|
|
254
|
+
user.setValue("demo_user")
|
|
255
|
+
|
|
256
|
+
password = (
|
|
257
|
+
selector.clearSelector()
|
|
258
|
+
.type("XCUIElementTypeSecureTextField")
|
|
259
|
+
.getOneNodeInfo(3000)
|
|
260
|
+
)
|
|
261
|
+
if password:
|
|
262
|
+
password.clearInput()
|
|
263
|
+
password.setValue("password")
|
|
264
|
+
|
|
265
|
+
login = (
|
|
266
|
+
selector.clearSelector()
|
|
267
|
+
.labelMatch(".*登录.*")
|
|
268
|
+
.type("XCUIElementTypeButton")
|
|
269
|
+
.getOneNodeInfo(3000)
|
|
270
|
+
)
|
|
271
|
+
if login:
|
|
272
|
+
login.tap()
|
|
367
273
|
```
|
|
368
274
|
|
|
369
|
-
###
|
|
275
|
+
### 列表里靠后的项
|
|
370
276
|
|
|
371
277
|
```python
|
|
372
|
-
|
|
373
|
-
def parent() -> Optional[NodeInfo]
|
|
374
|
-
|
|
375
|
-
# 获取指定索引的子节点
|
|
376
|
-
def child(index: int) -> Optional[NodeInfo]
|
|
377
|
-
|
|
378
|
-
# 获取所有子节点
|
|
379
|
-
def allChildren() -> List[NodeInfo]
|
|
380
|
-
|
|
381
|
-
# 获取兄弟节点
|
|
382
|
-
def siblings() -> List[NodeInfo]
|
|
383
|
-
|
|
384
|
-
# 获取前面的兄弟节点
|
|
385
|
-
def previousSiblings() -> List[NodeInfo]
|
|
278
|
+
from kuaijs import node
|
|
386
279
|
|
|
387
|
-
|
|
388
|
-
|
|
280
|
+
selector = node.createNodeSelector({"mode": 2})
|
|
281
|
+
item = selector.label("第 30 项").getOneNodeInfo(5000)
|
|
282
|
+
if item:
|
|
283
|
+
item.tap() # 不在可见区域时会自动滚动
|
|
389
284
|
```
|
|
390
285
|
|
|
391
|
-
|
|
286
|
+
### 查看界面结构
|
|
392
287
|
|
|
393
288
|
```python
|
|
394
289
|
from kuaijs import node
|
|
395
290
|
|
|
396
291
|
selector = node.createNodeSelector()
|
|
292
|
+
xml = selector.xml(8000)
|
|
293
|
+
if xml:
|
|
294
|
+
print(xml)
|
|
295
|
+
```
|
|
397
296
|
|
|
398
|
-
|
|
399
|
-
text_field = selector.type("XCUIElementTypeTextField").getOneNodeInfo(3000)
|
|
297
|
+
---
|
|
400
298
|
|
|
401
|
-
|
|
402
|
-
container = text_field.parent()
|
|
403
|
-
if container:
|
|
404
|
-
print(f"容器类型: {container.type}")
|
|
299
|
+
## 常见问题
|
|
405
300
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
print(f"容器包含 {len(children)} 个子元素")
|
|
301
|
+
**找不到节点**
|
|
302
|
+
加大超时;减少条件或改用 `*Match`;换 `mode`;用 `xml()` 看实际文案和类型。
|
|
409
303
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
304
|
+
**点了没反应**
|
|
305
|
+
先看 `hittable()`;确认点到的是目标控件;可对比 `clickCenter()`。
|
|
306
|
+
|
|
307
|
+
**输入叠在旧文字后面**
|
|
308
|
+
`input` / 文本类 `setValue` 是追加,先 `clearInput()`。
|
|
309
|
+
|
|
310
|
+
**滚轮设不中**
|
|
311
|
+
`setValue` 要传界面上显示的选项文案;确认类型是 `PickerWheel`;多列时选对那一列。
|