rust-rpa 0.2.3 → 0.2.5
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 +41 -1
- package/index.d.ts +104 -0
- package/index.js +15 -3
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
- ⚡ **非阻塞**: 异步操作不会阻塞 Node.js 事件循环
|
|
11
11
|
- 🔒 **类型安全**: 完整的 TypeScript 类型定义
|
|
12
12
|
- 🖱️ **输入自动化**: Mouse 和 Keyboard 类,完整的输入控制
|
|
13
|
-
-
|
|
13
|
+
- 📑 **窗口管理**: 基于 XCap 实现窗口枚举和信息获取
|
|
14
|
+
- 👁️ **窗口内容监听**: `Window.watchChanges()` 降采样差异检测,内容变化时再截图,低开销监听 UI 变化
|
|
14
15
|
- 🖥️ **多显示器支持**: Monitor 类,支持多显示器设置
|
|
15
16
|
- 📸 **屏幕截图**: 基于 XCap 实现全屏和窗口截图,多种图片格式(PNG/JPEG/BMP)
|
|
16
17
|
- 🔑 **权限管理**: Permission 类,自动检测并弹出系统权限授权对话框
|
|
@@ -121,11 +122,13 @@ rpa pause 1000
|
|
|
121
122
|
- `image-processing-demo.js` - 图像处理功能演示
|
|
122
123
|
- `find-icon-demo.js` - 完整的 findIcon 功能演示
|
|
123
124
|
- `find-icon-basic.js` - findIcon 基础用法示例
|
|
125
|
+
- `window-watch-changes-demo.js` - 监听窗口内容变化(`watchChanges`),可选 `chrome` / `ding` / `qianniu`
|
|
124
126
|
|
|
125
127
|
运行示例:
|
|
126
128
|
```bash
|
|
127
129
|
node examples/permission-demo.js
|
|
128
130
|
node examples/list-windows.js
|
|
131
|
+
node examples/window-watch-changes-demo.js chrome
|
|
129
132
|
```
|
|
130
133
|
|
|
131
134
|
## 使用方法
|
|
@@ -202,6 +205,7 @@ main();
|
|
|
202
205
|
- `setBounds(bounds)` - 设置窗口边界
|
|
203
206
|
- `toJSON()` - 转为 JSON 对象
|
|
204
207
|
- `captureImage(options?)` - 截图
|
|
208
|
+
- `watchChanges(options?, callback)` - 监听窗口内容变化;返回 `WindowWatcher`(`stop()` / `isRunning()`),回调收到变化后的 `ImageData` 或 `null`(见 `sendImage` 选项)
|
|
205
209
|
- `recognizeText(options?)` - OCR 识别文字
|
|
206
210
|
- `findText(text, options?)` - 查找文字
|
|
207
211
|
- `findIcon(template, options?)` - 查找图标
|
|
@@ -587,6 +591,42 @@ if (targetWindow) {
|
|
|
587
591
|
|
|
588
592
|
## 更新日志
|
|
589
593
|
|
|
594
|
+
### 0.2.5
|
|
595
|
+
|
|
596
|
+
#### 改进
|
|
597
|
+
|
|
598
|
+
- **Window.watchChanges 优化**: `threshold` 参数默认值改为 `0.0`,并优化为 `0` 时跳过图像对比
|
|
599
|
+
- `threshold: 0`(默认)- 跳过像素对比,每次轮询直接触发回调,最低延迟
|
|
600
|
+
- `threshold > 0` - 执行降采样对比,变化比例超过阈值才触发回调
|
|
601
|
+
- 适用于已知窗口会变化、需要立即获取截图的场景
|
|
602
|
+
|
|
603
|
+
### 0.2.5
|
|
604
|
+
|
|
605
|
+
#### 新功能
|
|
606
|
+
|
|
607
|
+
- **findText / waitText / clickText 新增 `index` 参数**: 支持选择第几个匹配的文字结果
|
|
608
|
+
- `index` 默认为 `0`,返回第一个匹配结果
|
|
609
|
+
- 正数表示第 n 个(从 0 开始):`index: 1` 返回第二个
|
|
610
|
+
- 负数表示倒数第 n 个:`index: -1` 返回最后一个,`index: -2` 返回倒数第二个
|
|
611
|
+
- 超出匹配数量范围时返回 `null`
|
|
612
|
+
- 适用场景:页面中存在多个相同文字,需要点击特定位置
|
|
613
|
+
- 示例:`findText('确定', { index: 1 })` 查找第二个「确定」,`clickText('确定', { index: -2 })` 点击倒数第二个「确定」
|
|
614
|
+
|
|
615
|
+
#### 类型定义更新
|
|
616
|
+
|
|
617
|
+
- `FindTextOptions` 新增 `index?: number` 字段
|
|
618
|
+
- `WindowFindTextOptions` 新增 `index?: number` 字段
|
|
619
|
+
- `MonitorFindTextOptions` 新增 `index?: number` 字段
|
|
620
|
+
- `WindowWaitOptions` 新增 `index?: number` 字段
|
|
621
|
+
- `MonitorWaitOptions` 新增 `index?: number` 字段
|
|
622
|
+
- `WaitOptions` 新增 `index?: number` 字段
|
|
623
|
+
|
|
624
|
+
### 0.2.4
|
|
625
|
+
|
|
626
|
+
#### 新功能
|
|
627
|
+
|
|
628
|
+
- **Window.watchChanges(窗口内容变化监听)**: 后台线程降采样对比相邻帧,超过阈值才截取完整窗口图并回调;支持 `threshold`、`from`(`window`/`screen`)、`region`、`captureSize`、`sendImage`;返回 `WindowWatcher` 可 `stop()`。
|
|
629
|
+
|
|
590
630
|
### 0.2.3
|
|
591
631
|
|
|
592
632
|
#### 修复
|
package/index.d.ts
CHANGED
|
@@ -60,6 +60,8 @@ export interface FindTextOptions {
|
|
|
60
60
|
regions?: Array<MatchRegion>
|
|
61
61
|
/** 排除文字,若同一行中包含此文字则排除该匹配结果 */
|
|
62
62
|
notText?: string
|
|
63
|
+
/** 匹配索引,默认为 0(第一个匹配)。负数表示倒数:-1 最后一个,-2 倒数第二个 */
|
|
64
|
+
index?: number
|
|
63
65
|
}
|
|
64
66
|
/** 文字查找选项(Window 专用) */
|
|
65
67
|
export interface WindowFindTextOptions {
|
|
@@ -73,6 +75,8 @@ export interface WindowFindTextOptions {
|
|
|
73
75
|
* - `'screen'`:截取窗口所在显示器的整屏
|
|
74
76
|
*/
|
|
75
77
|
from?: 'window' | 'screen'
|
|
78
|
+
/** 匹配索引,默认为 0(第一个匹配)。负数表示倒数:-1 最后一个,-2 倒数第二个 */
|
|
79
|
+
index?: number
|
|
76
80
|
}
|
|
77
81
|
/** 文字查找选项(Monitor 专用) */
|
|
78
82
|
export interface MonitorFindTextOptions {
|
|
@@ -80,6 +84,8 @@ export interface MonitorFindTextOptions {
|
|
|
80
84
|
regions?: Array<MatchRegion>
|
|
81
85
|
/** 排除文字,若同一行中包含此文字则排除该匹配结果 */
|
|
82
86
|
notText?: string
|
|
87
|
+
/** 匹配索引,默认为 0(第一个匹配)。负数表示倒数:-1 最后一个,-2 倒数第二个 */
|
|
88
|
+
index?: number
|
|
83
89
|
}
|
|
84
90
|
/** 文字识别选项(ImageData 使用) */
|
|
85
91
|
export interface RecognizeTextOptions {
|
|
@@ -118,6 +124,8 @@ export interface WindowWaitOptions {
|
|
|
118
124
|
* - `'screen'`:截取窗口所在显示器的整屏
|
|
119
125
|
*/
|
|
120
126
|
from?: 'window' | 'screen'
|
|
127
|
+
/** 匹配索引,默认为 0(第一个匹配)。负数表示倒数:-1 最后一个,-2 倒数第二个(仅用于 waitText/clickText) */
|
|
128
|
+
index?: number
|
|
121
129
|
}
|
|
122
130
|
/** 等待选项(Monitor 专用) */
|
|
123
131
|
export interface MonitorWaitOptions {
|
|
@@ -129,6 +137,8 @@ export interface MonitorWaitOptions {
|
|
|
129
137
|
threshold?: number
|
|
130
138
|
/** 排除文字,若同一行中包含此文字则排除该匹配结果(仅用于 waitText/clickText) */
|
|
131
139
|
notText?: string
|
|
140
|
+
/** 匹配索引,默认为 0(第一个匹配)。负数表示倒数:-1 最后一个,-2 倒数第二个(仅用于 waitText/clickText) */
|
|
141
|
+
index?: number
|
|
132
142
|
}
|
|
133
143
|
/** 等待选项(兼容旧代码,与 WindowWaitOptions 相同) */
|
|
134
144
|
export interface WaitOptions {
|
|
@@ -146,6 +156,8 @@ export interface WaitOptions {
|
|
|
146
156
|
* - `'screen'`:截取窗口所在显示器的整屏
|
|
147
157
|
*/
|
|
148
158
|
from?: 'window' | 'screen'
|
|
159
|
+
/** 匹配索引,默认为 0(第一个匹配)。负数表示倒数:-1 最后一个,-2 倒数第二个(仅用于 waitText/clickText) */
|
|
160
|
+
index?: number
|
|
149
161
|
}
|
|
150
162
|
/** 图标匹配结果 */
|
|
151
163
|
export interface MatchResult {
|
|
@@ -237,6 +249,40 @@ export interface CaptureImageOptions {
|
|
|
237
249
|
*/
|
|
238
250
|
writeFilePath?: string | null
|
|
239
251
|
}
|
|
252
|
+
/** 截图目标尺寸(用于窗口变化监听) */
|
|
253
|
+
export interface CaptureSizeJs {
|
|
254
|
+
/** 目标宽度(像素) */
|
|
255
|
+
width: number
|
|
256
|
+
/** 目标高度(像素) */
|
|
257
|
+
height: number
|
|
258
|
+
}
|
|
259
|
+
/** 窗口变化监听的选项 */
|
|
260
|
+
export interface WindowWatchOptionsJs {
|
|
261
|
+
/**
|
|
262
|
+
* 变化检测的灵敏度阈值 (0.0-1.0),默认 0.0
|
|
263
|
+
*
|
|
264
|
+
* - 0.0 表示跳过对比,每次轮询都触发回调(最敏感,最低延迟)
|
|
265
|
+
* - 大于 0.0 时,仅当像素变化比例超过阈值才触发回调
|
|
266
|
+
*/
|
|
267
|
+
threshold?: number
|
|
268
|
+
/** 图片来源:'window'(默认)或 'screen' */
|
|
269
|
+
from?: 'window' | 'screen'
|
|
270
|
+
/** 仅在指定区域检测变化(逻辑像素) */
|
|
271
|
+
region?: CaptureRegion | null
|
|
272
|
+
/** 检测到变化后传递给回调的截图目标尺寸 */
|
|
273
|
+
captureSize?: CaptureSizeJs | null
|
|
274
|
+
/** 是否在回调中传递截图图像,默认 true */
|
|
275
|
+
sendImage?: boolean
|
|
276
|
+
}
|
|
277
|
+
/** 窗口内容变化监听的回调函数签名 */
|
|
278
|
+
export type WindowChangeCallback = (image: ImageData | null) => void
|
|
279
|
+
/** 窗口变化监听器句柄,用于停止监听 */
|
|
280
|
+
export interface WindowWatcher {
|
|
281
|
+
/** 停止监听,释放底层资源 */
|
|
282
|
+
stop(): void
|
|
283
|
+
/** 检查是否仍在运行 */
|
|
284
|
+
isRunning(): boolean
|
|
285
|
+
}
|
|
240
286
|
/** 窗口尺寸信息 */
|
|
241
287
|
export interface WindowSize {
|
|
242
288
|
/** 窗口宽度 */
|
|
@@ -1248,6 +1294,64 @@ export declare class Window {
|
|
|
1248
1294
|
* ```
|
|
1249
1295
|
*/
|
|
1250
1296
|
clickIcon(template: ImageData, options?: WindowWaitOptions | null): Promise<ClickResult>
|
|
1297
|
+
/**
|
|
1298
|
+
* 监听窗口内容变化,当检测到变化时自动截取最新截图并传递给回调函数
|
|
1299
|
+
*
|
|
1300
|
+
* 底层使用降采样差异检测,仅在窗口内容发生变化时才截取完整图像,
|
|
1301
|
+
* 资源开销远低于定时轮询截图。
|
|
1302
|
+
*
|
|
1303
|
+
* @param options 监听选项(可选)
|
|
1304
|
+
* @param callback 变化时的回调函数,sendImage=true 时接收 ImageData,否则接收 null
|
|
1305
|
+
* @returns WindowWatcher 句柄,调用 stop() 可停止监听
|
|
1306
|
+
*
|
|
1307
|
+
* @example
|
|
1308
|
+
* ```javascript
|
|
1309
|
+
* // 场景 1:需要获取变化后的截图
|
|
1310
|
+
* const watcher = targetWindow.watchChanges(
|
|
1311
|
+
* { threshold: 0.02, from: 'window' },
|
|
1312
|
+
* (image) => {
|
|
1313
|
+
* console.log(`窗口变化,新截图: ${image.width}x${image.height}`);
|
|
1314
|
+
* sendToExternalService(image);
|
|
1315
|
+
* }
|
|
1316
|
+
* );
|
|
1317
|
+
* ```
|
|
1318
|
+
*
|
|
1319
|
+
* @example
|
|
1320
|
+
* ```javascript
|
|
1321
|
+
* // 场景 2:只需要知道窗口有变化,不需要截图(更低开销)
|
|
1322
|
+
* const watcher = targetWindow.watchChanges(
|
|
1323
|
+
* { sendImage: false },
|
|
1324
|
+
* (image) => {
|
|
1325
|
+
* console.log('窗口内容发生了变化');
|
|
1326
|
+
* onWindowChanged();
|
|
1327
|
+
* }
|
|
1328
|
+
* );
|
|
1329
|
+
* ```
|
|
1330
|
+
*
|
|
1331
|
+
* @example
|
|
1332
|
+
* ```javascript
|
|
1333
|
+
* // 场景 3:仅监听窗口的特定区域
|
|
1334
|
+
* const watcher = targetWindow.watchChanges(
|
|
1335
|
+
* {
|
|
1336
|
+
* region: { x: 100, y: 200, width: 400, height: 300 },
|
|
1337
|
+
* captureSize: { width: 800, height: 600 },
|
|
1338
|
+
* sendImage: true
|
|
1339
|
+
* },
|
|
1340
|
+
* (image) => {
|
|
1341
|
+
* processScreenshot(image);
|
|
1342
|
+
* }
|
|
1343
|
+
* );
|
|
1344
|
+
*
|
|
1345
|
+
* // 停止监听
|
|
1346
|
+
* setTimeout(() => {
|
|
1347
|
+
* watcher.stop();
|
|
1348
|
+
* }, 60000);
|
|
1349
|
+
* ```
|
|
1350
|
+
*/
|
|
1351
|
+
watchChanges(
|
|
1352
|
+
options: WindowWatchOptionsJs | null | undefined,
|
|
1353
|
+
callback: WindowChangeCallback
|
|
1354
|
+
): WindowWatcher
|
|
1251
1355
|
}
|
|
1252
1356
|
/** Clipboard 类 - 剪贴板控制 */
|
|
1253
1357
|
export declare class Clipboard {
|
package/index.js
CHANGED
|
@@ -10,12 +10,24 @@ const { join } = require('path')
|
|
|
10
10
|
// 自动设置 OCR 模型路径,指向包内的 models/ 目录
|
|
11
11
|
// 优先使用用户自定义路径(通过环境变量 RPA_OCR_MODELS),否则使用包内路径
|
|
12
12
|
if (!process.env.RPA_OCR_MODELS) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
process.
|
|
13
|
+
// electron打包后路径
|
|
14
|
+
const dirs = process.resourcesPath ? [
|
|
15
|
+
join(process.resourcesPath, 'app.asar.unpacked', 'node_modules', 'rust-rpa', 'models'),
|
|
16
|
+
// 备用路径:app/node_modules/rust-rpa/models
|
|
17
|
+
join(process.resourcesPath, 'app', 'node_modules', 'rust-rpa', 'models'),
|
|
18
|
+
join(process.resourcesPath, 'node_modules', 'rust-rpa', 'models'),
|
|
19
|
+
] : [];
|
|
20
|
+
dirs.push(join(process.cwd(), 'node_modules', 'rust-rpa', 'models'))
|
|
21
|
+
dirs.push(join(__dirname, 'models'));
|
|
22
|
+
for (const dir of dirs) {
|
|
23
|
+
if (existsSync(dir)) {
|
|
24
|
+
process.env.RPA_OCR_MODELS = dir
|
|
25
|
+
break
|
|
26
|
+
}
|
|
16
27
|
}
|
|
17
28
|
}
|
|
18
29
|
|
|
30
|
+
|
|
19
31
|
const { platform, arch } = process
|
|
20
32
|
|
|
21
33
|
let nativeBinding = null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rust-rpa",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Rust-based RPA automation library for Node.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "index.js",
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
"commander": "^14.0.3"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
|
-
"@alibot/rust-rpa-win32-x64-msvc": "0.2.
|
|
71
|
-
"@alibot/rust-rpa-win32-ia32-msvc": "0.2.
|
|
72
|
-
"@alibot/rust-rpa-darwin-x64": "0.2.
|
|
73
|
-
"@alibot/rust-rpa-darwin-arm64": "0.2.
|
|
70
|
+
"@alibot/rust-rpa-win32-x64-msvc": "0.2.5",
|
|
71
|
+
"@alibot/rust-rpa-win32-ia32-msvc": "0.2.5",
|
|
72
|
+
"@alibot/rust-rpa-darwin-x64": "0.2.5",
|
|
73
|
+
"@alibot/rust-rpa-darwin-arm64": "0.2.5"
|
|
74
74
|
}
|
|
75
75
|
}
|