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.
Files changed (4) hide show
  1. package/README.md +41 -1
  2. package/index.d.ts +104 -0
  3. package/index.js +15 -3
  4. 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
- - 🪟 **窗口管理**: 基于 XCap 实现窗口枚举和信息获取
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
- const packageModelsDir = join(__dirname, 'models')
14
- if (existsSync(packageModelsDir)) {
15
- process.env.RPA_OCR_MODELS = packageModelsDir
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",
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.3",
71
- "@alibot/rust-rpa-win32-ia32-msvc": "0.2.3",
72
- "@alibot/rust-rpa-darwin-x64": "0.2.3",
73
- "@alibot/rust-rpa-darwin-arm64": "0.2.3"
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
  }