assistsx-js 0.0.1352 → 0.0.2001

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/src/Step.ts CHANGED
@@ -3,501 +3,690 @@
3
3
  * 用于管理和执行自动化步骤,提供步骤的生命周期管理、状态控制和界面操作功能
4
4
  */
5
5
  import { AssistsX } from "./AssistsX";
6
- import { Node } from './Node';
7
- import { CallMethod } from "CallMethod";
8
- import { useStepStore } from './StepStateStore';
6
+ import { Node } from "./Node";
7
+ import { CallMethod } from "./CallMethod";
8
+ import { useStepStore } from "./StepStateStore";
9
9
  import { generateUUID } from "./Utils";
10
-
10
+ import { StepError } from "./StepError";
11
+ import { StepAsync } from "./StepAsync";
11
12
 
12
13
  export class Step {
13
-
14
- static delayMsDefault: number = 1000;
15
- static readonly repeatCountInfinite: number = -1;
16
- static repeatCountMaxDefault: number = Step.repeatCountInfinite;
17
- static showLog: boolean = false;
18
-
19
- /**
20
- * 当前执行步骤的ID
21
- */
22
- private static _stepId: string | undefined = undefined;
23
-
24
- /**
25
- * 运行步骤实现
26
- * @param impl 步骤实现函数
27
- * @param tag 步骤标签
28
- * @param data 步骤数据
29
- * @param delayMs 步骤延迟时间(毫秒)
30
- */
31
- static async run(impl: (step: Step) => Promise<Step | undefined>, { tag, data, delayMs = Step.delayMsDefault }: { tag?: string | undefined, data?: any | undefined, delayMs?: number } = {}) {
32
- const stepStore = useStepStore();
33
- let implnName = impl.name
34
- try {
35
- //步骤开始
36
- this._stepId = generateUUID();
37
-
38
- stepStore.startStep(this._stepId, tag, data);
39
- let step = new Step({ stepId: this._stepId, impl, tag, data, delayMs });
40
- while (true) {
41
- if (step.delayMs) {
42
- if (Step.showLog) {
43
- console.log(`延迟${step.delayMs}毫秒`)
44
- }
45
- await step.delay(step.delayMs);
46
- Step.assert(step.stepId);
47
- }
48
- //执行步骤
49
- implnName = step.impl.name
50
- if (Step.showLog) {
51
- console.log(`执行步骤${implnName},重复次数${step.repeatCount}`)
52
- }
53
- const nextStep = await step.impl(step);
54
- if (step.repeatCountMax > Step.repeatCountInfinite && step.repeatCount > step.repeatCountMax) {
55
- if (Step.showLog) {
56
- console.log(`重复次数${step.repeatCount}超过最大次数${step.repeatCountMax},停止执行`)
57
- }
58
- break;
59
- }
60
-
61
- Step.assert(step.stepId);
62
- if (nextStep) {
63
- step = nextStep;
64
- } else {
65
- break;
66
- }
67
- }
68
-
69
- } catch (e: any) {
70
- if (Step.showLog) {
71
- console.error(`步骤${implnName}执行出错`, e)
72
- }
73
- //步骤执行出错
74
- const errorMsg = JSON.stringify({
75
- impl: implnName,
76
- tag: tag,
77
- data: data,
78
- error: e?.message ?? String(e)
79
- });
80
- stepStore.setError(errorMsg);
81
- throw new Error(errorMsg);
14
+ static delayMsDefault: number = 1000;
15
+ static readonly repeatCountInfinite: number = -1;
16
+ static repeatCountMaxDefault: number = Step.repeatCountInfinite;
17
+ static showLog: boolean = false;
18
+
19
+ /**
20
+ * 当前执行步骤的ID
21
+ */
22
+ private static _stepId: string | undefined = undefined;
23
+
24
+ /**
25
+ * 运行步骤实现
26
+ * @param impl 步骤实现函数
27
+ * @param tag 步骤标签
28
+ * @param data 步骤数据
29
+ * @param delayMs 步骤延迟时间(毫秒)
30
+ */
31
+ static async run(
32
+ impl: (step: Step) => Promise<Step | undefined>,
33
+ {
34
+ tag,
35
+ data,
36
+ backupSteps,
37
+ delayMs = Step.delayMsDefault,
38
+ }: {
39
+ tag?: string | undefined;
40
+ data?: any | undefined;
41
+ backupSteps?:
42
+ | { [key: string]: (step: Step) => Promise<Step | undefined> }
43
+ | undefined;
44
+ delayMs?: number;
45
+ } = {}
46
+ ): Promise<Step> {
47
+ const stepStore = useStepStore();
48
+ let implnName = impl.name;
49
+ let currentStep: Step | undefined;
50
+ let nextStep: Step | undefined;
51
+ try {
52
+ //步骤开始
53
+ this._stepId = generateUUID();
54
+
55
+ stepStore.startStep(this._stepId, tag, data);
56
+ currentStep = new Step({
57
+ stepId: this._stepId,
58
+ impl,
59
+ tag,
60
+ data,
61
+ backupSteps,
62
+ delayMs,
63
+ });
64
+ while (true) {
65
+ if (currentStep.delayMs) {
66
+ if (Step.showLog) {
67
+ console.log(`延迟${currentStep.delayMs}毫秒`);
68
+ }
69
+ await currentStep.delay(currentStep.delayMs);
70
+ Step.assert(currentStep.stepId);
82
71
  }
83
- //步骤执行结束
84
- stepStore.completeStep();
85
- }
86
-
87
- /**
88
- * 获取当前步骤ID
89
- */
90
- static get stepId(): string | undefined {
91
- return this._stepId;
92
- }
93
-
94
- /**
95
- * 验证步骤ID是否匹配
96
- * @param stepId 要验证的步骤ID
97
- */
98
- static assert(stepId: string | undefined) {
99
- if (stepId && Step.stepId != stepId) {
100
- throw new Error("StepId mismatch");
72
+ //执行步骤
73
+ implnName = currentStep.impl.name;
74
+ if (Step.showLog) {
75
+ console.log(
76
+ `执行步骤${implnName},重复次数${currentStep.repeatCount}`
77
+ );
101
78
  }
102
- }
103
-
104
- /**
105
- * 为节点数组分配步骤ID
106
- * @param nodes 节点数组
107
- * @param stepId 步骤ID
108
- */
109
- static assignIdsToNodes(nodes: Node[], stepId: string | undefined): void {
110
- if (stepId) {
111
- nodes.forEach(node => {
112
- node.stepId = stepId;
113
- });
79
+ nextStep = await currentStep.impl(currentStep);
80
+ if (
81
+ currentStep.repeatCountMax > Step.repeatCountInfinite &&
82
+ currentStep.repeatCount > currentStep.repeatCountMax
83
+ ) {
84
+ if (Step.showLog) {
85
+ console.log(
86
+ `重复次数${currentStep.repeatCount}超过最大次数${currentStep.repeatCountMax},停止执行`
87
+ );
88
+ }
89
+ break;
114
90
  }
115
- }
116
-
117
- /**
118
- * 停止当前步骤执行
119
- */
120
- static stop(): void {
121
- this._stepId = undefined;
122
- }
123
-
124
- /**
125
- * 步骤ID
126
- */
127
- stepId: string = "";
128
-
129
- /**
130
- * 步骤重复执行次数
131
- */
132
- repeatCount: number = 0;
133
-
134
- /**
135
- * 步骤重复执行最大次数,默认不限制
136
- */
137
- repeatCountMax: number = Step.repeatCountMaxDefault;
138
-
139
- /**
140
- * 步骤标签
141
- */
142
- tag: string | undefined;
143
-
144
- /**
145
- * 步骤数据
146
- */
147
- data: any | undefined;
148
-
149
- /**
150
- * 步骤延迟时间(毫秒)
151
- */
152
- delayMs: number = Step.delayMsDefault;
153
-
154
- /**
155
- * 步骤实现函数
156
- */
157
- impl: (step: Step) => Promise<Step | undefined>
158
-
159
- /**
160
- * 构造函数
161
- * @param stepId 步骤ID
162
- * @param impl 步骤实现函数
163
- * @param tag 步骤标签
164
- * @param data 步骤数据
165
- * @param delayMs 步骤延迟时间(毫秒)
166
- */
167
- constructor({ stepId, impl, tag, data, delayMs = Step.delayMsDefault, repeatCountMax = Step.repeatCountMaxDefault }: { stepId: string, impl: (step: Step) => Promise<Step | undefined>, tag?: string | undefined, data?: any | undefined, delayMs?: number, repeatCountMax?: number }) {
168
- this.tag = tag;
169
- this.stepId = stepId;
170
- this.data = data;
171
- this.impl = impl;
172
- this.delayMs = delayMs;
173
- this.repeatCountMax = repeatCountMax;
174
- }
175
-
176
- /**
177
- * 创建下一个步骤
178
- * @param impl 下一步骤实现函数
179
- * @param tag 步骤标签
180
- * @param data 步骤数据
181
- * @param delayMs 步骤延迟时间(毫秒)
182
- * @returns 新的步骤实例
183
- */
184
- next(impl: (step: Step) => Promise<Step | undefined>, { tag, data, delayMs = Step.delayMsDefault, repeatCountMax = Step.repeatCountMaxDefault }: { tag?: string | undefined, data?: any | undefined, delayMs?: number, repeatCountMax?: number } = {}): Step {
185
- Step.assert(this.stepId);
186
- return new Step({ stepId: this.stepId, impl, tag, data: data ?? this.data, delayMs, repeatCountMax });
187
- }
188
-
189
- /**
190
- * 重复当前步骤
191
- * @param stepId 步骤ID
192
- * @param tag 步骤标签
193
- * @param data 步骤数据
194
- * @param delayMs 步骤延迟时间(毫秒)
195
- * @returns 当前步骤实例
196
- */
197
- repeat({ stepId = this.stepId, tag = this.tag, data = this.data, delayMs = this.delayMs, repeatCountMax = this.repeatCountMax }: { stepId?: string, tag?: string | undefined, data?: any | undefined, delayMs?: number, repeatCountMax?: number } = {}): Step {
198
- Step.assert(this.stepId);
199
- this.repeatCount++;
200
- this.stepId = stepId;
201
- this.tag = tag;
202
- this.data = data;
203
- this.delayMs = delayMs;
204
- this.repeatCountMax = repeatCountMax;
205
- return this
206
- }
207
-
208
- /**
209
- * 延迟执行
210
- * @param ms 延迟时间(毫秒)
211
- * @returns Promise
212
- */
213
- delay(ms: number): Promise<void> {
214
- Step.assert(this.stepId);
215
- return new Promise((resolve, reject) => {
216
- setTimeout(() => {
217
- try {
218
- Step.assert(this.stepId);
219
- resolve();
220
- } catch (e) {
221
- reject(e);
222
- }
223
- }, ms);
224
- });
225
- }
226
-
227
- /**
228
- * 等待异步方法执行完成
229
- * @param method 异步方法
230
- * @returns Promise<T>
231
- */
232
- async await<T>(method: () => Promise<T>): Promise<T> {
233
- Step.assert(this.stepId);
234
- const result = await method();
235
- Step.assert(this.stepId);
236
- return result;
237
- }
238
-
239
- /**
240
- * 对单个节点进行截图
241
- * @param node 目标节点
242
- * @param overlayHiddenScreenshotDelayMillis 截图延迟时间(毫秒)
243
- * @returns 截图路径
244
- */
245
- public async takeScreenshotByNode(node: Node, overlayHiddenScreenshotDelayMillis: number = 250): Promise<string> {
246
- Step.assert(this.stepId);
247
- const result = await AssistsX.takeScreenshotNodes([node], overlayHiddenScreenshotDelayMillis);
248
- Step.assert(this.stepId);
249
- return result[0];
250
- }
251
-
252
- /**
253
- * 对多个节点进行截图
254
- * @param nodes 目标节点数组
255
- * @param overlayHiddenScreenshotDelayMillis 截图延迟时间(毫秒)
256
- * @returns 截图路径数组
257
- */
258
- public async takeScreenshotNodes(nodes: Node[], overlayHiddenScreenshotDelayMillis: number = 250): Promise<string[]> {
259
- Step.assert(this.stepId);
260
- const result = await AssistsX.takeScreenshotNodes(nodes, overlayHiddenScreenshotDelayMillis);
261
- Step.assert(this.stepId);
262
- return result;
263
- }
264
-
265
- /**
266
- * 获取所有符合条件的节点
267
- * @param filterClass 类名过滤
268
- * @param filterViewId 视图ID过滤
269
- * @param filterDes 描述过滤
270
- * @param filterText 文本过滤
271
- * @returns 节点数组
272
- */
273
- public getAllNodes({ filterClass, filterViewId, filterDes, filterText }: { filterClass?: string, filterViewId?: string, filterDes?: string, filterText?: string } = {}): Node[] {
274
- Step.assert(this.stepId);
275
- const nodes = AssistsX.getAllNodes({ filterClass, filterViewId, filterDes, filterText });
276
- Step.assert(this.stepId);
277
- Step.assignIdsToNodes(nodes, this.stepId);
278
- return nodes;
279
- }
280
-
281
- /**
282
- * 启动应用
283
- * @param packageName 应用包名
284
- * @returns 是否启动成功
285
- */
286
- public launchApp(packageName: string): boolean {
287
- Step.assert(this.stepId);
288
- const result = AssistsX.launchApp(packageName);
289
- Step.assert(this.stepId);
290
- return result;
291
- }
292
-
293
- /**
294
- * 获取当前应用包名
295
- * @returns 包名
296
- */
297
- public getPackageName(): string {
298
- Step.assert(this.stepId);
299
- const result = AssistsX.getPackageName();
300
- Step.assert(this.stepId);
301
- return result;
302
- }
303
-
304
- /**
305
- * 通过ID查找节点
306
- * @param id 节点ID
307
- * @param filterClass 类名过滤
308
- * @param filterText 文本过滤
309
- * @param filterDes 描述过滤
310
- * @returns 节点数组
311
- */
312
- public findById(id: string, { filterClass, filterText, filterDes }: { filterClass?: string, filterText?: string, filterDes?: string } = {}): Node[] {
313
- Step.assert(this.stepId);
314
- const nodes = AssistsX.findById(id, { filterClass, filterText, filterDes });
315
- Step.assert(this.stepId);
316
- Step.assignIdsToNodes(nodes, this.stepId);
317
- return nodes;
318
- }
319
-
320
- /**
321
- * 通过文本查找节点
322
- * @param text 要查找的文本
323
- * @param filterClass 类名过滤
324
- * @param filterViewId 视图ID过滤
325
- * @param filterDes 描述过滤
326
- * @returns 节点数组
327
- */
328
- public findByText(text: string, { filterClass, filterViewId, filterDes }: { filterClass?: string, filterViewId?: string, filterDes?: string } = {}): Node[] {
329
- Step.assert(this.stepId);
330
- const nodes = AssistsX.findByText(text, { filterClass, filterViewId, filterDes });
331
- Step.assert(this.stepId);
332
- Step.assignIdsToNodes(nodes, this.stepId);
333
- return nodes;
334
- }
335
-
336
- /**
337
- * 通过标签查找节点
338
- * @param className 类名
339
- * @param filterText 文本过滤
340
- * @param filterViewId 视图ID过滤
341
- * @param filterDes 描述过滤
342
- * @returns 节点数组
343
- */
344
- public findByTags(className: string, { filterText, filterViewId, filterDes }: { filterText?: string, filterViewId?: string, filterDes?: string, } = {}): Node[] {
345
- Step.assert(this.stepId);
346
- const nodes = AssistsX.findByTags(className, { filterText, filterViewId, filterDes });
347
- Step.assert(this.stepId);
348
- Step.assignIdsToNodes(nodes, this.stepId);
349
- return nodes;
350
- }
351
-
352
- /**
353
- * 查找所有匹配文本的节点
354
- * @param text 要查找的文本
355
- * @returns 节点数组
356
- */
357
- public findByTextAllMatch(text: string): Node[] {
358
- Step.assert(this.stepId);
359
- const nodes = AssistsX.findByTextAllMatch(text);
360
- Step.assert(this.stepId);
361
- Step.assignIdsToNodes(nodes, this.stepId);
362
- return nodes;
363
- }
364
-
365
- /**
366
- * 检查是否包含指定文本
367
- * @param text 要检查的文本
368
- * @returns 是否包含
369
- */
370
- public containsText(text: string): boolean {
371
- Step.assert(this.stepId);
372
- const result = AssistsX.containsText(text);
373
- Step.assert(this.stepId);
374
- return result;
375
- }
376
91
 
377
- /**
378
- * 获取所有文本
379
- * @returns 文本数组
380
- */
381
- public getAllText(): string[] {
382
- Step.assert(this.stepId);
383
- const texts = AssistsX.getAllText();
384
- Step.assert(this.stepId);
385
- return texts;
386
- }
387
-
388
- /**
389
- * 查找第一个匹配标签的父节点
390
- * @param className 类名
391
- * @returns 父节点
392
- */
393
- public findFirstParentByTags(className: string): Node {
394
- Step.assert(this.stepId);
395
- const node = AssistsX.findFirstParentByTags(className);
396
- Step.assert(this.stepId);
397
- return node;
398
- }
399
-
400
- /**
401
- * 执行点击手势
402
- * @param x 横坐标
403
- * @param y 纵坐标
404
- * @param duration 持续时间(毫秒)
405
- * @returns 是否成功
406
- */
407
- public async clickByGesture(x: number, y: number, duration: number): Promise<boolean> {
408
- Step.assert(this.stepId);
409
- const result = await AssistsX.clickByGesture(x, y, duration);
410
- Step.assert(this.stepId);
411
- return result;
412
- }
413
-
414
- public async longPressGestureAutoPaste(
415
- point: { x: number, y: number }, text: string,
416
- { matchedPackageName, matchedText, timeoutMillis, longPressDuration }:
417
- { matchedPackageName?: string, matchedText?: string, timeoutMillis?: number, longPressDuration?: number } =
418
- { matchedText: "粘贴", timeoutMillis: 1500, longPressDuration: 600 }
419
- ): Promise<boolean> {
420
- Step.assert(this.stepId);
421
- const result = await AssistsX.longPressGestureAutoPaste(point, text, { matchedPackageName, matchedText, timeoutMillis, longPressDuration });
422
- Step.assert(this.stepId);
423
- return result;
424
- }
425
- public async getAppInfo(packageName: string): Promise<any> {
426
- Step.assert(this.stepId);
427
- const result = await AssistsX.getAppInfo(packageName);
428
- Step.assert(this.stepId);
429
- return result;
430
- }
431
- public async performLinearGesture(startPoint: { x: number, y: number }, endPoint: { x: number, y: number }, { duration }: { duration?: number } = {}): Promise<boolean> {
432
- Step.assert(this.stepId);
433
- const result = await AssistsX.performLinearGesture(startPoint, endPoint, { duration });
434
- Step.assert(this.stepId);
435
- return result;
436
- }
437
-
438
- /**
439
- * 返回操作
440
- * @returns 是否成功
441
- */
442
- public back(): boolean {
443
- Step.assert(this.stepId);
444
- const result = AssistsX.back();
445
- Step.assert(this.stepId);
446
- return result;
447
- }
448
-
449
- /**
450
- * 回到主页
451
- * @returns 是否成功
452
- */
453
- public home(): boolean {
454
- Step.assert(this.stepId);
455
- const result = AssistsX.home();
456
- Step.assert(this.stepId);
457
- return result;
458
- }
459
-
460
- /**
461
- * 打开通知栏
462
- * @returns 是否成功
463
- */
464
- public notifications(): boolean {
465
- Step.assert(this.stepId);
466
- const result = AssistsX.notifications();
467
- Step.assert(this.stepId);
468
- return result;
469
- }
470
-
471
- /**
472
- * 显示最近应用
473
- * @returns 是否成功
474
- */
475
- public recentApps(): boolean {
476
- Step.assert(this.stepId);
477
- const result = AssistsX.recentApps();
478
- Step.assert(this.stepId);
479
- return result;
480
- }
481
-
482
- /**
483
- * 获取屏幕尺寸
484
- * @returns 屏幕尺寸对象
485
- */
486
- public getScreenSize(): any {
487
- Step.assert(this.stepId);
488
- const data = AssistsX.getScreenSize();
489
- Step.assert(this.stepId);
490
- return data;
491
- }
492
-
493
- /**
494
- * 获取应用窗口尺寸
495
- * @returns 应用窗口尺寸对象
496
- */
497
- public getAppScreenSize(): any {
498
- Step.assert(this.stepId);
499
- const data = AssistsX.getAppScreenSize();
500
- Step.assert(this.stepId);
501
- return data;
502
- }
503
- }
92
+ Step.assert(currentStep.stepId);
93
+ if (nextStep) {
94
+ currentStep = nextStep;
95
+ } else {
96
+ break;
97
+ }
98
+ }
99
+ } catch (e: any) {
100
+ if (Step.showLog) {
101
+ console.error(`步骤${implnName}执行出错`, e);
102
+ }
103
+ //步骤执行出错
104
+ const errorMsg = JSON.stringify({
105
+ impl: implnName,
106
+ tag: tag,
107
+ data: data,
108
+ error: e?.message ?? String(e),
109
+ });
110
+ stepStore.setError(errorMsg);
111
+ throw new StepError(
112
+ errorMsg,
113
+ implnName,
114
+ tag,
115
+ data,
116
+ e,
117
+ currentStep || undefined
118
+ );
119
+ }
120
+ //步骤执行结束
121
+ stepStore.completeStep();
122
+ return currentStep;
123
+ }
124
+
125
+ /**
126
+ * 获取当前步骤ID
127
+ */
128
+ static get stepId(): string | undefined {
129
+ return this._stepId;
130
+ }
131
+
132
+ /**
133
+ * 验证步骤ID是否匹配,如果不匹配则表示停止
134
+ * @param stepId 要验证的步骤ID
135
+ */
136
+ static assert(stepId: string | undefined) {
137
+ if (stepId && Step.stepId != stepId) {
138
+ throw new Error("StepId mismatch");
139
+ }
140
+ }
141
+
142
+ /**
143
+ * 为节点数组分配步骤ID
144
+ * @param nodes 节点数组
145
+ * @param stepId 步骤ID
146
+ */
147
+ static assignIdsToNodes(nodes: Node[], stepId: string | undefined): void {
148
+ if (stepId) {
149
+ nodes.forEach((node) => {
150
+ node.stepId = stepId;
151
+ });
152
+ }
153
+ }
154
+
155
+ /**
156
+ * 停止当前步骤执行
157
+ */
158
+ static stop(): void {
159
+ this._stepId = undefined;
160
+ }
161
+
162
+ /**
163
+ * 步骤ID
164
+ */
165
+ stepId: string = "";
166
+
167
+ /**
168
+ * 步骤重复执行次数
169
+ */
170
+ repeatCount: number = 0;
171
+
172
+ /**
173
+ * 步骤重复执行最大次数,默认不限制
174
+ */
175
+ repeatCountMax: number = Step.repeatCountMaxDefault;
176
+
177
+ /**
178
+ * 步骤标签
179
+ */
180
+ tag: string | undefined;
181
+
182
+ /**
183
+ * 步骤数据
184
+ */
185
+ data: any | undefined;
186
+
187
+ /**
188
+ * 步骤延迟时间(毫秒)
189
+ */
190
+ delayMs: number = Step.delayMsDefault;
191
+
192
+ /**
193
+ * 步骤实现函数
194
+ */
195
+ impl: (step: Step) => Promise<Step | undefined>;
196
+
197
+ /**
198
+ * 备份步骤,可用于在指定的步骤中转向其他步骤
199
+ */
200
+ backupSteps:
201
+ | { [key: string]: (step: Step) => Promise<Step | undefined> }
202
+ | undefined;
203
+
204
+ /**
205
+ * 构造函数
206
+ * @param stepId 步骤ID
207
+ * @param impl 步骤实现函数
208
+ * @param tag 步骤标签
209
+ * @param data 步骤数据
210
+ * @param delayMs 步骤延迟时间(毫秒)
211
+ */
212
+ constructor({
213
+ stepId,
214
+ impl,
215
+ tag,
216
+ data,
217
+ backupSteps,
218
+ delayMs = Step.delayMsDefault,
219
+ repeatCountMax = Step.repeatCountMaxDefault,
220
+ }: {
221
+ stepId: string;
222
+ impl: (step: Step) => Promise<Step | undefined>;
223
+ tag?: string | undefined;
224
+ data?: any | undefined;
225
+ backupSteps?:
226
+ | { [key: string]: (step: Step) => Promise<Step | undefined> }
227
+ | undefined;
228
+ delayMs?: number;
229
+ repeatCountMax?: number;
230
+ }) {
231
+ this.tag = tag;
232
+ this.stepId = stepId;
233
+ this.data = data;
234
+ this.impl = impl;
235
+ this.backupSteps = backupSteps;
236
+ this.delayMs = delayMs;
237
+ this.repeatCountMax = repeatCountMax;
238
+ }
239
+
240
+ public get async(): StepAsync {
241
+ return new StepAsync(this);
242
+ }
243
+ /**
244
+ * 创建下一个步骤
245
+ * @param impl 下一步骤实现函数
246
+ * @param tag 步骤标签
247
+ * @param data 步骤数据
248
+ * @param delayMs 步骤延迟时间(毫秒)
249
+ * @returns 新的步骤实例
250
+ */
251
+ next(
252
+ impl: (step: Step) => Promise<Step | undefined>,
253
+ {
254
+ tag,
255
+ data,
256
+ backupSteps,
257
+ delayMs = Step.delayMsDefault,
258
+ repeatCountMax = Step.repeatCountMaxDefault,
259
+ }: {
260
+ tag?: string | undefined;
261
+ data?: any | undefined;
262
+ backupSteps?:
263
+ | { [key: string]: (step: Step) => Promise<Step | undefined> }
264
+ | undefined;
265
+ delayMs?: number;
266
+ repeatCountMax?: number;
267
+ } = {}
268
+ ): Step {
269
+ Step.assert(this.stepId);
270
+ return new Step({
271
+ stepId: this.stepId,
272
+ impl,
273
+ tag,
274
+ data: data ?? this.data,
275
+ backupSteps: backupSteps ?? this.backupSteps,
276
+ delayMs,
277
+ repeatCountMax,
278
+ });
279
+ }
280
+
281
+ /**
282
+ * 重复当前步骤
283
+ * @param stepId 步骤ID
284
+ * @param tag 步骤标签
285
+ * @param data 步骤数据
286
+ * @param delayMs 步骤延迟时间(毫秒)
287
+ * @returns 当前步骤实例
288
+ */
289
+ repeat({
290
+ stepId = this.stepId,
291
+ tag = this.tag,
292
+ data = this.data,
293
+ backupSteps = this.backupSteps,
294
+ delayMs = this.delayMs,
295
+ repeatCountMax = this.repeatCountMax,
296
+ }: {
297
+ stepId?: string;
298
+ tag?: string | undefined;
299
+ data?: any | undefined;
300
+ backupSteps?:
301
+ | { [key: string]: (step: Step) => Promise<Step | undefined> }
302
+ | undefined;
303
+ delayMs?: number;
304
+ repeatCountMax?: number;
305
+ } = {}): Step {
306
+ Step.assert(this.stepId);
307
+ this.repeatCount++;
308
+ this.stepId = stepId;
309
+ this.tag = tag;
310
+ this.data = data;
311
+ this.backupSteps = backupSteps;
312
+ this.delayMs = delayMs;
313
+ this.repeatCountMax = repeatCountMax;
314
+ return this;
315
+ }
316
+
317
+ /**
318
+ * 延迟执行
319
+ * @param ms 延迟时间(毫秒)
320
+ * @returns Promise
321
+ */
322
+ delay(ms: number): Promise<void> {
323
+ Step.assert(this.stepId);
324
+ return new Promise((resolve, reject) => {
325
+ setTimeout(() => {
326
+ try {
327
+ Step.assert(this.stepId);
328
+ resolve();
329
+ } catch (e) {
330
+ reject(e);
331
+ }
332
+ }, ms);
333
+ });
334
+ }
335
+
336
+ /**
337
+ * 等待异步方法执行完成
338
+ * @param method 异步方法
339
+ * @returns Promise<T>
340
+ */
341
+ async await<T>(method: () => Promise<T>): Promise<T> {
342
+ Step.assert(this.stepId);
343
+ const result = await method();
344
+ Step.assert(this.stepId);
345
+ return result;
346
+ }
347
+
348
+ /**
349
+ * 对单个节点进行截图
350
+ * @param node 目标节点
351
+ * @param overlayHiddenScreenshotDelayMillis 截图延迟时间(毫秒)
352
+ * @returns 截图路径
353
+ */
354
+ public async takeScreenshotByNode(
355
+ node: Node,
356
+ overlayHiddenScreenshotDelayMillis: number = 250
357
+ ): Promise<string> {
358
+ Step.assert(this.stepId);
359
+ const result = await AssistsX.takeScreenshotNodes(
360
+ [node],
361
+ overlayHiddenScreenshotDelayMillis
362
+ );
363
+ Step.assert(this.stepId);
364
+ return result[0];
365
+ }
366
+
367
+ /**
368
+ * 对多个节点进行截图
369
+ * @param nodes 目标节点数组
370
+ * @param overlayHiddenScreenshotDelayMillis 截图延迟时间(毫秒)
371
+ * @returns 截图路径数组
372
+ */
373
+ public async takeScreenshotNodes(
374
+ nodes: Node[],
375
+ overlayHiddenScreenshotDelayMillis: number = 250
376
+ ): Promise<string[]> {
377
+ Step.assert(this.stepId);
378
+ const result = await AssistsX.takeScreenshotNodes(
379
+ nodes,
380
+ overlayHiddenScreenshotDelayMillis
381
+ );
382
+ Step.assert(this.stepId);
383
+ return result;
384
+ }
385
+
386
+ /**
387
+ * 获取所有符合条件的节点
388
+ * @param filterClass 类名过滤
389
+ * @param filterViewId 视图ID过滤
390
+ * @param filterDes 描述过滤
391
+ * @param filterText 文本过滤
392
+ * @returns 节点数组
393
+ */
394
+ public getAllNodes({
395
+ filterClass,
396
+ filterViewId,
397
+ filterDes,
398
+ filterText,
399
+ }: {
400
+ filterClass?: string;
401
+ filterViewId?: string;
402
+ filterDes?: string;
403
+ filterText?: string;
404
+ } = {}): Node[] {
405
+ Step.assert(this.stepId);
406
+ const nodes = AssistsX.getAllNodes({
407
+ filterClass,
408
+ filterViewId,
409
+ filterDes,
410
+ filterText,
411
+ });
412
+ Step.assert(this.stepId);
413
+ Step.assignIdsToNodes(nodes, this.stepId);
414
+ return nodes;
415
+ }
416
+
417
+ /**
418
+ * 启动应用
419
+ * @param packageName 应用包名
420
+ * @returns 是否启动成功
421
+ */
422
+ public launchApp(packageName: string): boolean {
423
+ Step.assert(this.stepId);
424
+ const result = AssistsX.launchApp(packageName);
425
+ Step.assert(this.stepId);
426
+ return result;
427
+ }
428
+
429
+ /**
430
+ * 获取当前应用包名
431
+ * @returns 包名
432
+ */
433
+ public getPackageName(): string {
434
+ Step.assert(this.stepId);
435
+ const result = AssistsX.getPackageName();
436
+ Step.assert(this.stepId);
437
+ return result;
438
+ }
439
+
440
+ /**
441
+ * 通过ID查找节点
442
+ * @param id 节点ID
443
+ * @param filterClass 类名过滤
444
+ * @param filterText 文本过滤
445
+ * @param filterDes 描述过滤
446
+ * @returns 节点数组
447
+ */
448
+ public findById(
449
+ id: string,
450
+ {
451
+ filterClass,
452
+ filterText,
453
+ filterDes,
454
+ }: { filterClass?: string; filterText?: string; filterDes?: string } = {}
455
+ ): Node[] {
456
+ Step.assert(this.stepId);
457
+ const nodes = AssistsX.findById(id, { filterClass, filterText, filterDes });
458
+ Step.assert(this.stepId);
459
+ Step.assignIdsToNodes(nodes, this.stepId);
460
+ return nodes;
461
+ }
462
+
463
+ /**
464
+ * 通过文本查找节点
465
+ * @param text 要查找的文本
466
+ * @param filterClass 类名过滤
467
+ * @param filterViewId 视图ID过滤
468
+ * @param filterDes 描述过滤
469
+ * @returns 节点数组
470
+ */
471
+ public findByText(
472
+ text: string,
473
+ {
474
+ filterClass,
475
+ filterViewId,
476
+ filterDes,
477
+ }: { filterClass?: string; filterViewId?: string; filterDes?: string } = {}
478
+ ): Node[] {
479
+ Step.assert(this.stepId);
480
+ const nodes = AssistsX.findByText(text, {
481
+ filterClass,
482
+ filterViewId,
483
+ filterDes,
484
+ });
485
+ Step.assert(this.stepId);
486
+ Step.assignIdsToNodes(nodes, this.stepId);
487
+ return nodes;
488
+ }
489
+
490
+ /**
491
+ * 通过标签查找节点
492
+ * @param className 类名
493
+ * @param filterText 文本过滤
494
+ * @param filterViewId 视图ID过滤
495
+ * @param filterDes 描述过滤
496
+ * @returns 节点数组
497
+ */
498
+ public findByTags(
499
+ className: string,
500
+ {
501
+ filterText,
502
+ filterViewId,
503
+ filterDes,
504
+ }: { filterText?: string; filterViewId?: string; filterDes?: string } = {}
505
+ ): Node[] {
506
+ Step.assert(this.stepId);
507
+ const nodes = AssistsX.findByTags(className, {
508
+ filterText,
509
+ filterViewId,
510
+ filterDes,
511
+ });
512
+ Step.assert(this.stepId);
513
+ Step.assignIdsToNodes(nodes, this.stepId);
514
+ return nodes;
515
+ }
516
+
517
+ /**
518
+ * 查找所有匹配文本的节点
519
+ * @param text 要查找的文本
520
+ * @returns 节点数组
521
+ */
522
+ public findByTextAllMatch(text: string): Node[] {
523
+ Step.assert(this.stepId);
524
+ const nodes = AssistsX.findByTextAllMatch(text);
525
+ Step.assert(this.stepId);
526
+ Step.assignIdsToNodes(nodes, this.stepId);
527
+ return nodes;
528
+ }
529
+
530
+ /**
531
+ * 检查是否包含指定文本
532
+ * @param text 要检查的文本
533
+ * @returns 是否包含
534
+ */
535
+ public containsText(text: string): boolean {
536
+ Step.assert(this.stepId);
537
+ const result = AssistsX.containsText(text);
538
+ Step.assert(this.stepId);
539
+ return result;
540
+ }
541
+
542
+ /**
543
+ * 获取所有文本
544
+ * @returns 文本数组
545
+ */
546
+ public getAllText(): string[] {
547
+ Step.assert(this.stepId);
548
+ const texts = AssistsX.getAllText();
549
+ Step.assert(this.stepId);
550
+ return texts;
551
+ }
552
+
553
+ /**
554
+ * 查找第一个匹配标签的父节点
555
+ * @param className 类名
556
+ * @returns 父节点
557
+ */
558
+ public findFirstParentByTags(className: string): Node {
559
+ Step.assert(this.stepId);
560
+ const node = AssistsX.findFirstParentByTags(className);
561
+ Step.assert(this.stepId);
562
+ return node;
563
+ }
564
+
565
+ /**
566
+ * 执行点击手势
567
+ * @param x 横坐标
568
+ * @param y 纵坐标
569
+ * @param duration 持续时间(毫秒)
570
+ * @returns 是否成功
571
+ */
572
+ public async clickByGesture(
573
+ x: number,
574
+ y: number,
575
+ duration: number
576
+ ): Promise<boolean> {
577
+ Step.assert(this.stepId);
578
+ const result = await AssistsX.clickByGesture(x, y, duration);
579
+ Step.assert(this.stepId);
580
+ return result;
581
+ }
582
+
583
+ public async longPressGestureAutoPaste(
584
+ point: { x: number; y: number },
585
+ text: string,
586
+ {
587
+ matchedPackageName,
588
+ matchedText,
589
+ timeoutMillis,
590
+ longPressDuration,
591
+ }: {
592
+ matchedPackageName?: string;
593
+ matchedText?: string;
594
+ timeoutMillis?: number;
595
+ longPressDuration?: number;
596
+ } = { matchedText: "粘贴", timeoutMillis: 1500, longPressDuration: 600 }
597
+ ): Promise<boolean> {
598
+ Step.assert(this.stepId);
599
+ const result = await AssistsX.longPressGestureAutoPaste(point, text, {
600
+ matchedPackageName,
601
+ matchedText,
602
+ timeoutMillis,
603
+ longPressDuration,
604
+ });
605
+ Step.assert(this.stepId);
606
+ return result;
607
+ }
608
+ public async getAppInfo(packageName: string): Promise<any> {
609
+ Step.assert(this.stepId);
610
+ const result = await AssistsX.getAppInfo(packageName);
611
+ Step.assert(this.stepId);
612
+ return result;
613
+ }
614
+ public async performLinearGesture(
615
+ startPoint: { x: number; y: number },
616
+ endPoint: { x: number; y: number },
617
+ { duration }: { duration?: number } = {}
618
+ ): Promise<boolean> {
619
+ Step.assert(this.stepId);
620
+ const result = await AssistsX.performLinearGesture(startPoint, endPoint, {
621
+ duration,
622
+ });
623
+ Step.assert(this.stepId);
624
+ return result;
625
+ }
626
+
627
+ /**
628
+ * 返回操作
629
+ * @returns 是否成功
630
+ */
631
+ public back(): boolean {
632
+ Step.assert(this.stepId);
633
+ const result = AssistsX.back();
634
+ Step.assert(this.stepId);
635
+ return result;
636
+ }
637
+
638
+ /**
639
+ * 回到主页
640
+ * @returns 是否成功
641
+ */
642
+ public home(): boolean {
643
+ Step.assert(this.stepId);
644
+ const result = AssistsX.home();
645
+ Step.assert(this.stepId);
646
+ return result;
647
+ }
648
+
649
+ /**
650
+ * 打开通知栏
651
+ * @returns 是否成功
652
+ */
653
+ public notifications(): boolean {
654
+ Step.assert(this.stepId);
655
+ const result = AssistsX.notifications();
656
+ Step.assert(this.stepId);
657
+ return result;
658
+ }
659
+
660
+ /**
661
+ * 显示最近应用
662
+ * @returns 是否成功
663
+ */
664
+ public recentApps(): boolean {
665
+ Step.assert(this.stepId);
666
+ const result = AssistsX.recentApps();
667
+ Step.assert(this.stepId);
668
+ return result;
669
+ }
670
+
671
+ /**
672
+ * 获取屏幕尺寸
673
+ * @returns 屏幕尺寸对象
674
+ */
675
+ public getScreenSize(): any {
676
+ Step.assert(this.stepId);
677
+ const data = AssistsX.getScreenSize();
678
+ Step.assert(this.stepId);
679
+ return data;
680
+ }
681
+
682
+ /**
683
+ * 获取应用窗口尺寸
684
+ * @returns 应用窗口尺寸对象
685
+ */
686
+ public getAppScreenSize(): any {
687
+ Step.assert(this.stepId);
688
+ const data = AssistsX.getAppScreenSize();
689
+ Step.assert(this.stepId);
690
+ return data;
691
+ }
692
+ }