assistsx-js 0.0.133 → 0.0.1332
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/README.md +5 -32
- package/dist/AssistsX.js +1 -1
- package/package.json +5 -1
- package/src/AssistsX.ts +1 -1
- package/README-DEV.md +0 -350
- package/tsconfig.json +0 -20
package/README.md
CHANGED
|
@@ -13,38 +13,6 @@
|
|
|
13
13
|
|
|
14
14
|
> 下载安装后会默认安装一个示例插件,可长按删除
|
|
15
15
|
|
|
16
|
-
# 示例源码安装运行
|
|
17
|
-
|
|
18
|
-
源码:[https://github.com/ven-coder/assistsx-js-simple](https://github.com/ven-coder/assistsx-js-simple)
|
|
19
|
-
|
|
20
|
-
## 本地安装运行
|
|
21
|
-
|
|
22
|
-
### 1. 安装[AssistsX](https://www.pgyer.com/SqGaCx8C)
|
|
23
|
-
|
|
24
|
-
安装前请先在手机安装[AssistsX](https://www.pgyer.com/SqGaCx8C)
|
|
25
|
-
|
|
26
|
-
### 2. 插件包传至手机
|
|
27
|
-
下载本示例源码后(*前提`npm`环境配置好*)
|
|
28
|
-
1. 终端依次运行命令:`npm install`,`npm run build`
|
|
29
|
-
2. 编译完成后将`dist`文件夹压缩为`.zip`文件,然后将`.zip`文件传至手机。
|
|
30
|
-
3. 手机打开[AssistsX](https://www.pgyer.com/SqGaCx8C),点击+号->本地添加->选择传至手机的`zip`压缩包
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<img src="https://github.com/user-attachments/assets/7dc27910-be61-473b-8900-f09c16ca5f46" width="250">
|
|
34
|
-
|
|
35
|
-
## 局域网加载运行
|
|
36
|
-
> 确保手机与电脑处于同一个局域网
|
|
37
|
-
### 1. 安装[AssistsX](https://www.pgyer.com/SqGaCx8C)
|
|
38
|
-
加载运行前请先在手机安装[AssistsX](https://www.pgyer.com/SqGaCx8C)
|
|
39
|
-
|
|
40
|
-
### 2. 启动项目
|
|
41
|
-
下载本示例源码后,终端依次运行命令:`npm install`,`npm run dev`
|
|
42
|
-
|
|
43
|
-
### 3. 加载插件
|
|
44
|
-
手机打开[AssistsX](https://www.pgyer.com/SqGaCx8C),点击+号->扫描局域网->点击扫描到插件+号
|
|
45
|
-
|
|
46
|
-
<img src="https://github.com/user-attachments/assets/d0f24763-266e-4e3c-bd64-a63be9e6c68c" width="250"/>
|
|
47
|
-
|
|
48
16
|
# 快速开始
|
|
49
17
|
## 1. 创建项目
|
|
50
18
|
- 创建`vite`模版项目:`npm create vite@latest assistsx-helloword -- --template vue`
|
|
@@ -103,8 +71,13 @@ export default defineConfig({
|
|
|
103
71
|
<br/>
|
|
104
72
|
<br/>
|
|
105
73
|
|
|
74
|
+
|
|
106
75
|
**[API开发文档](https://github.com/ven-coder/assistsx-js/blob/main/README-DEV.md)**
|
|
107
76
|
|
|
77
|
+
## 示例
|
|
78
|
+
|
|
79
|
+
示例源码及使用教程:[https://github.com/ven-coder/assistsx-js-simple](https://github.com/ven-coder/assistsx-js-simple)
|
|
80
|
+
|
|
108
81
|
## 🙋有问题欢迎反馈交流
|
|
109
82
|
|
|
110
83
|
| QQ交流群| 个人微信 |
|
package/dist/AssistsX.js
CHANGED
|
@@ -269,7 +269,7 @@ export class AssistsX {
|
|
|
269
269
|
*/
|
|
270
270
|
static getChildren(node) {
|
|
271
271
|
const response = this.call(CallMethod.getChildren, { node });
|
|
272
|
-
return Node.fromJSONArray(response.getDataOrDefault(
|
|
272
|
+
return Node.fromJSONArray(response.getDataOrDefault([]));
|
|
273
273
|
}
|
|
274
274
|
/**
|
|
275
275
|
* 查找第一个可点击的父节点
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assistsx-js",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1332",
|
|
4
4
|
"description": "assistsx-js自动化开发SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"import": "./dist/index.js",
|
package/src/AssistsX.ts
CHANGED
|
@@ -316,7 +316,7 @@ export class AssistsX {
|
|
|
316
316
|
*/
|
|
317
317
|
public static getChildren(node: Node): Node[] {
|
|
318
318
|
const response = this.call(CallMethod.getChildren, { node });
|
|
319
|
-
return Node.fromJSONArray(response.getDataOrDefault(
|
|
319
|
+
return Node.fromJSONArray(response.getDataOrDefault([]));
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
/**
|
package/README-DEV.md
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
### 基本用法
|
|
2
|
-
|
|
3
|
-
```typescript
|
|
4
|
-
import { AssistsX, Node } from 'assistsx-js';
|
|
5
|
-
|
|
6
|
-
// 获取所有节点
|
|
7
|
-
const nodes: Node[] = AssistsX.getAllNodes();
|
|
8
|
-
|
|
9
|
-
// 通过ID查找节点
|
|
10
|
-
const nodeList: Node[] = AssistsX.findById('target_id');
|
|
11
|
-
|
|
12
|
-
// 点击第一个节点
|
|
13
|
-
if (nodeList.length > 0) {
|
|
14
|
-
AssistsX.click(nodeList[0]);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 执行手势点击
|
|
18
|
-
AssistsX.gestureClick(100, 200, 50); // 在(100,200)位置点击,持续50ms
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### 节点对象的常用操作
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
const node: Node = nodeList[0];
|
|
25
|
-
|
|
26
|
-
// 设置节点文本
|
|
27
|
-
node.setNodeText('new text');
|
|
28
|
-
|
|
29
|
-
// 节点点击
|
|
30
|
-
node.click();
|
|
31
|
-
|
|
32
|
-
// 节点长按
|
|
33
|
-
node.longClick();
|
|
34
|
-
|
|
35
|
-
// 节点滚动
|
|
36
|
-
node.scrollForward();
|
|
37
|
-
node.scrollBackward();
|
|
38
|
-
|
|
39
|
-
// 获取节点在屏幕中的位置
|
|
40
|
-
const bounds = node.getBoundsInScreen();
|
|
41
|
-
console.log(bounds);
|
|
42
|
-
|
|
43
|
-
// 节点截图
|
|
44
|
-
const imagePath = await node.takeScreenshot();
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### 复杂查找与遍历
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// 通过文本查找节点
|
|
51
|
-
const textNodes = AssistsX.findByText('确定');
|
|
52
|
-
|
|
53
|
-
// 通过标签查找节点
|
|
54
|
-
const tagNodes = AssistsX.findByTags('android.widget.Button', { filterText: '提交' });
|
|
55
|
-
|
|
56
|
-
// 获取节点的所有子节点
|
|
57
|
-
const children = node.getChildren();
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## 主要类型说明
|
|
61
|
-
|
|
62
|
-
### AssistsX
|
|
63
|
-
|
|
64
|
-
- 提供静态方法用于节点查找、手势操作、系统操作等。
|
|
65
|
-
- 常用方法:
|
|
66
|
-
- `getAllNodes`:获取所有节点
|
|
67
|
-
- `findById`、`findByText`、`findByTags`:多种查找方式
|
|
68
|
-
- `click`、`longClick`、`gestureClick`:节点点击与手势
|
|
69
|
-
- `takeScreenshotNodes`:节点截图
|
|
70
|
-
- `launchApp`、`back`、`home`、`notifications`、`recentApps`:系统操作
|
|
71
|
-
|
|
72
|
-
### Node
|
|
73
|
-
|
|
74
|
-
- 表示界面上的一个可交互元素,包含属性和操作方法。
|
|
75
|
-
- 主要属性:
|
|
76
|
-
- `nodeId`、`text`、`des`、`viewId`、`className`
|
|
77
|
-
- `isScrollable`、`isClickable`、`isEnabled`
|
|
78
|
-
- 主要方法:
|
|
79
|
-
- `setNodeText(text: string)`:设置文本
|
|
80
|
-
- `click()`、`longClick()`:点击/长按
|
|
81
|
-
- `scrollForward()`、`scrollBackward()`:滚动
|
|
82
|
-
- `getBoundsInScreen()`:获取屏幕位置
|
|
83
|
-
- `takeScreenshot()`:节点截图
|
|
84
|
-
- `findById`、`findByText`、`findByTags`:在当前节点范围内查找
|
|
85
|
-
|
|
86
|
-
## 典型场景
|
|
87
|
-
|
|
88
|
-
### 1. 自动化测试
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
// 启动应用
|
|
92
|
-
AssistsX.launchApp('com.example.app');
|
|
93
|
-
|
|
94
|
-
// 等待并点击登录按钮
|
|
95
|
-
const loginBtn = AssistsX.findByText('登录');
|
|
96
|
-
if (loginBtn.length > 0) {
|
|
97
|
-
loginBtn[0].click();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 检查是否包含某文本
|
|
101
|
-
const hasText = AssistsX.containsText('登录成功');
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 2. 界面元素操作
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
// 查找输入框并输入文本
|
|
108
|
-
const input = AssistsX.findById('input_field');
|
|
109
|
-
if (input.length > 0) {
|
|
110
|
-
input[0].setNodeText('测试文本');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// 查找并点击提交按钮
|
|
114
|
-
const submit = AssistsX.findByText('提交');
|
|
115
|
-
if (submit.length > 0) {
|
|
116
|
-
submit[0].click();
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### 3. 手势操作
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// 简单点击
|
|
124
|
-
AssistsX.gestureClick(100, 200, 50);
|
|
125
|
-
|
|
126
|
-
// 节点手势点击(支持偏移)
|
|
127
|
-
const node = AssistsX.findById('target')[0];
|
|
128
|
-
await node.nodeGestureClick({
|
|
129
|
-
offsetX: 10,
|
|
130
|
-
offsetY: 10,
|
|
131
|
-
clickDuration: 50
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// 双击操作
|
|
135
|
-
await node.nodeGestureClickByDouble({
|
|
136
|
-
clickInterval: 200
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### 4. 滚动和导航
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
// 系统导航
|
|
144
|
-
AssistsX.back(); // 返回
|
|
145
|
-
AssistsX.home(); // 主页
|
|
146
|
-
AssistsX.notifications(); // 通知栏
|
|
147
|
-
|
|
148
|
-
// 滚动操作
|
|
149
|
-
const scrollable = AssistsX.findByTags('android.widget.ScrollView')[0];
|
|
150
|
-
scrollable.scrollForward();
|
|
151
|
-
scrollable.scrollBackward();
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## 步骤器(Step)使用说明
|
|
155
|
-
|
|
156
|
-
步骤器提供了一种结构化的方式来组织和执行自动化操作,支持步骤的生命周期管理、状态控制和界面操作。
|
|
157
|
-
|
|
158
|
-
### 基本用法
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
import { Step } from 'assistsx-js';
|
|
162
|
-
|
|
163
|
-
// 定义步骤实现
|
|
164
|
-
async function loginStep(step: Step): Promise<Step | undefined> {
|
|
165
|
-
// 启动应用
|
|
166
|
-
step.launchApp('com.example.app');
|
|
167
|
-
|
|
168
|
-
// 查找用户名输入框并输入
|
|
169
|
-
const usernameInput = step.findById('username_input');
|
|
170
|
-
if (usernameInput.length > 0) {
|
|
171
|
-
usernameInput[0].setNodeText('user123');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 查找密码输入框并输入
|
|
175
|
-
const passwordInput = step.findById('password_input');
|
|
176
|
-
if (passwordInput.length > 0) {
|
|
177
|
-
passwordInput[0].setNodeText('password123');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// 点击登录按钮
|
|
181
|
-
const loginButton = step.findByText('登录');
|
|
182
|
-
if (loginButton.length > 0) {
|
|
183
|
-
loginButton[0].click();
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// 返回 undefined 表示步骤结束
|
|
187
|
-
return undefined;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// 运行步骤
|
|
191
|
-
await Step.run(loginStep, {
|
|
192
|
-
tag: 'login', // 步骤标签
|
|
193
|
-
data: { user: 'test' }, // 步骤数据
|
|
194
|
-
delayMs: 1000 // 步骤延迟
|
|
195
|
-
});
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### 步骤链式调用
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
async function step1(step: Step): Promise<Step | undefined> {
|
|
202
|
-
// 执行某些操作
|
|
203
|
-
// ...
|
|
204
|
-
|
|
205
|
-
// 返回下一个步骤
|
|
206
|
-
return step.next(step2, { tag: 'step2' });
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async function step2(step: Step): Promise<Step | undefined> {
|
|
210
|
-
// 执行某些操作
|
|
211
|
-
// ...
|
|
212
|
-
|
|
213
|
-
// 重复当前步骤
|
|
214
|
-
if (needRepeat) {
|
|
215
|
-
return step.repeat();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 返回下一个步骤
|
|
219
|
-
return step.next(step3, { tag: 'step3' });
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
async function step3(step: Step): Promise<Step | undefined> {
|
|
223
|
-
// 执行最后的操作
|
|
224
|
-
// ...
|
|
225
|
-
|
|
226
|
-
// 步骤结束
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// 运行步骤链
|
|
231
|
-
await Step.run(step1, { tag: 'step1' });
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### 异步操作处理
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
async function asyncStep(step: Step): Promise<Step | undefined> {
|
|
238
|
-
// 等待异步操作
|
|
239
|
-
await step.delay(1000);
|
|
240
|
-
|
|
241
|
-
// 执行异步方法
|
|
242
|
-
const result = await step.await(async () => {
|
|
243
|
-
// 异步操作
|
|
244
|
-
return 'result';
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// 节点截图
|
|
248
|
-
const node = step.findById('target')[0];
|
|
249
|
-
const imagePath = await step.takeScreenshotByNode(node);
|
|
250
|
-
|
|
251
|
-
return undefined;
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
## Step API 文档
|
|
256
|
-
|
|
257
|
-
### 静态方法
|
|
258
|
-
|
|
259
|
-
#### `Step.run(impl, options)`
|
|
260
|
-
运行步骤实现。
|
|
261
|
-
- `impl`: `(step: Step) => Promise<Step | undefined>` - 步骤实现函数
|
|
262
|
-
- `options`:
|
|
263
|
-
- `tag?: string` - 步骤标签
|
|
264
|
-
- `data?: any` - 步骤数据
|
|
265
|
-
- `delayMs?: number` - 步骤延迟时间(毫秒),默认 1000
|
|
266
|
-
|
|
267
|
-
#### `Step.stop()`
|
|
268
|
-
停止当前步骤执行。
|
|
269
|
-
|
|
270
|
-
### 实例属性
|
|
271
|
-
|
|
272
|
-
- `stepId: string` - 步骤ID
|
|
273
|
-
- `repeatCount: number` - 步骤重复执行次数
|
|
274
|
-
- `tag?: string` - 步骤标签
|
|
275
|
-
- `data?: any` - 步骤数据
|
|
276
|
-
- `delayMs: number` - 步骤延迟时间(毫秒)
|
|
277
|
-
|
|
278
|
-
### 实例方法
|
|
279
|
-
|
|
280
|
-
#### 步骤控制
|
|
281
|
-
- `next(impl, options)` - 创建下一个步骤
|
|
282
|
-
- `repeat(options)` - 重复当前步骤
|
|
283
|
-
- `delay(ms)` - 延迟执行
|
|
284
|
-
- `await<T>(method)` - 等待异步方法执行完成
|
|
285
|
-
|
|
286
|
-
#### 节点操作
|
|
287
|
-
- `getAllNodes(options)` - 获取所有符合条件的节点
|
|
288
|
-
- `findById(id, options)` - 通过ID查找节点
|
|
289
|
-
- `findByText(text, options)` - 通过文本查找节点
|
|
290
|
-
- `findByTags(className, options)` - 通过标签查找节点
|
|
291
|
-
- `findByTextAllMatch(text)` - 查找所有匹配文本的节点
|
|
292
|
-
- `findFirstParentByTags(className)` - 查找第一个匹配标签的父节点
|
|
293
|
-
|
|
294
|
-
#### 界面操作
|
|
295
|
-
- `takeScreenshotByNode(node, delay)` - 对单个节点进行截图
|
|
296
|
-
- `takeScreenshotNodes(nodes, delay)` - 对多个节点进行截图
|
|
297
|
-
- `gestureClick(x, y, duration)` - 执行点击手势
|
|
298
|
-
- `back()` - 返回操作
|
|
299
|
-
- `home()` - 回到主页
|
|
300
|
-
- `notifications()` - 打开通知栏
|
|
301
|
-
- `recentApps()` - 显示最近应用
|
|
302
|
-
|
|
303
|
-
#### 应用控制
|
|
304
|
-
- `launchApp(packageName)` - 启动应用
|
|
305
|
-
- `getPackageName()` - 获取当前应用包名
|
|
306
|
-
|
|
307
|
-
#### 其他操作
|
|
308
|
-
- `containsText(text)` - 检查是否包含指定文本
|
|
309
|
-
- `getAllText()` - 获取所有文本
|
|
310
|
-
- `getScreenSize()` - 获取屏幕尺寸
|
|
311
|
-
- `getAppScreenSize()` - 获取应用窗口尺寸
|
|
312
|
-
|
|
313
|
-
## 最佳实践
|
|
314
|
-
|
|
315
|
-
1. 步骤组织
|
|
316
|
-
- 将复杂的自动化流程拆分为多个步骤
|
|
317
|
-
- 每个步骤专注于完成特定的任务
|
|
318
|
-
- 使用有意义的标签和数据来标识步骤
|
|
319
|
-
|
|
320
|
-
2. 错误处理
|
|
321
|
-
```typescript
|
|
322
|
-
async function robustStep(step: Step): Promise<Step | undefined> {
|
|
323
|
-
try {
|
|
324
|
-
const node = step.findById('target')[0];
|
|
325
|
-
if (!node) {
|
|
326
|
-
throw new Error('Target node not found');
|
|
327
|
-
}
|
|
328
|
-
// ... 其他操作
|
|
329
|
-
} catch (error) {
|
|
330
|
-
console.error(`Step failed: ${error.message}`);
|
|
331
|
-
// 可以选择重试或执行其他步骤
|
|
332
|
-
return step.repeat({ delayMs: 2000 });
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
3. 步骤复用
|
|
338
|
-
```typescript
|
|
339
|
-
// 创建可复用的步骤
|
|
340
|
-
function createLoginStep(username: string, password: string) {
|
|
341
|
-
return async function(step: Step): Promise<Step | undefined> {
|
|
342
|
-
// ... 登录逻辑
|
|
343
|
-
return undefined;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// 在不同地方复用
|
|
348
|
-
await Step.run(createLoginStep('user1', 'pass1'));
|
|
349
|
-
await Step.run(createLoginStep('user2', 'pass2'));
|
|
350
|
-
```
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2018",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"rootDir": "./src",
|
|
13
|
-
"baseUrl": ".",
|
|
14
|
-
"paths": {
|
|
15
|
-
"*": ["src/*"]
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"include": ["src/**/*"],
|
|
19
|
-
"exclude": ["node_modules", "dist"]
|
|
20
|
-
}
|