@bettergi/utils 0.1.19 → 0.1.21

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 CHANGED
@@ -59,6 +59,16 @@ const i3 = findImageBetweenCoordinates("assets/关闭.png", 960, 0, 1920, 1080);
59
59
  // 在指定方向上搜索图片,找不到返回 undefined
60
60
  const i4 = findImageInDirection("assets/关闭.png", "north-east");
61
61
 
62
+ // 在列表视图中查找图片,并滚动列表视图直到找到目标图片 或 列表视图触底
63
+ const i5 = await findImageWithinListView("assets/foo.png", {
64
+ x: 115,
65
+ y: 95,
66
+ w: 1157,
67
+ h: 906,
68
+ lineHeight: 175,
69
+ scrollLines: 4
70
+ });
71
+
62
72
  // 在整个画面内搜索文本(不包含、忽略大小写),找不到返回 undefined
63
73
  const t1 = findText("购买");
64
74
 
@@ -70,6 +80,20 @@ const t3 = findTextBetweenCoordinates("确认", 960, 540, 1920, 1080);
70
80
 
71
81
  // 在指定方向上搜索文本(包含、忽略大小写),找不到返回 undefined
72
82
  const t4 = findTextInDirection("师傅", "east", { contains: true, ignoreCase: true });
83
+
84
+ // 在列表视图中查找文本,并滚动列表视图直到找到目标文本 或 列表视图触底
85
+ const t5 = await findTextWithinListView(
86
+ "小麦",
87
+ {
88
+ x: 120,
89
+ y: 95,
90
+ w: 1045,
91
+ h: 865,
92
+ lineHeight: 115,
93
+ scrollLines: 7
94
+ },
95
+ { contains: true }
96
+ );
73
97
  ```
74
98
 
75
99
  ### 行为流程
@@ -102,22 +126,32 @@ await assertRegionDisappearing(findButton, "点击购买按钮超时", () => fin
102
126
  > 对常见鼠标操作的封装,如鼠标的平滑移动、鼠标滚轮滚动、鼠标拖拽等。
103
127
 
104
128
  ```ts
105
- // 鼠标从 (745, 610) 平滑自然地移动 (1920, 1080)
106
- await naturalMouseMove(745, 610, 1920, 1080);
129
+ // 鼠标沿路径点移动并拖拽
130
+ await mouseMoveAlongWaypoints(
131
+ [
132
+ { x: 100, y: 100 },
133
+ { x: 200, y: 200 },
134
+ { x: 300, y: 300 }
135
+ ],
136
+ { shouldDrag: true }
137
+ );
107
138
 
108
139
  // 鼠标从 (745, 610) 拖拽到 (1280, 610)
109
140
  await mouseDrag(745, 610, 1280, 610);
110
141
 
142
+ // 鼠标从 (745, 610) 平滑自然地移动 (1920, 1080)
143
+ await naturalMouseMove(745, 610, 1920, 1080);
144
+
111
145
  // 鼠标滚轮向上滚动 175 像素
112
146
  await mouseScrollUp(175);
113
147
 
114
148
  // 鼠标滚轮向下滚动 175 像素
115
149
  await mouseScrollDown(175);
116
150
 
117
- // 鼠标滚轮向上滚动 99 行,行高 175(默认: 背包物品行高)
151
+ // 鼠标滚轮向上滚动 99 行(默认: 175为背包物品行高)
118
152
  await mouseScrollUpLines(99);
119
153
 
120
- // 鼠标滚轮向下滚动 1 行,行高 115(自定义: 商店物品行高)
154
+ // 鼠标滚轮向下滚动 1 行(自定义: 115为商店物品行高)
121
155
  await mouseScrollDownLines(1, 115);
122
156
  ```
123
157
 
@@ -177,12 +211,14 @@ tracker.complete(`任务完成`);
177
211
 
178
212
  ```ts
179
213
  // 发送 GET 请求获取响应体内容
180
- const body1 = await getForBody("https://example.com/", undefined, { "User-Agent": "BetterGI" });
181
- log.info(`GET 请求响应体内容${body1}`);
214
+ const body1 = await getForBody("https://jsonplaceholder.typicode.com/todos/1");
182
215
 
183
216
  // 发送 POST 请求获取响应体内容
184
- const body2 = await postForBody("https://example.com/", undefined, { "User-Agent": "BetterGI" });
185
- log.info(`POST 请求响应体内容${body2}`);
217
+ const body2 = await postForBody("https://jsonplaceholder.typicode.com/posts", {
218
+ title: "foo",
219
+ body: "bar",
220
+ userId: 1
221
+ });
186
222
  ```
187
223
 
188
224
  ### 文件操作
package/dist/http.d.ts CHANGED
@@ -2,24 +2,24 @@
2
2
  * 发送 HTTP 请求,获取响应体内容
3
3
  * @param method 请求方法
4
4
  * @param url 请求 URL
5
- * @param body 请求体
5
+ * @param body 请求体(UTF-8 编码)
6
6
  * @param headers 请求头
7
7
  * @returns 响应体内容
8
8
  */
9
- export declare const requestForBody: (method: Parameters<typeof http.request>[0], url: string, body?: string, headers?: Record<string, any>) => Promise<string>;
9
+ export declare const requestForBody: (method: Parameters<typeof http.request>[0], url: string, body?: string | object, headers?: Record<string, any>) => Promise<string>;
10
10
  /**
11
11
  * 发送 HTTP GET 请求,获取响应体内容
12
12
  * @param url 请求 URL
13
- * @param body 请求体
13
+ * @param body 请求体(UTF-8 编码)
14
14
  * @param headers 请求头
15
15
  * @returns 响应体内容
16
16
  */
17
- export declare const getForBody: (url: string, body?: string, headers?: Record<string, any>) => Promise<string>;
17
+ export declare const getForBody: (url: string, body?: string | object, headers?: Record<string, any>) => Promise<string>;
18
18
  /**
19
19
  * 发送 HTTP POST 请求,获取响应体内容
20
20
  * @param url 请求 URL
21
- * @param body 请求体
21
+ * @param body 请求体(UTF-8 编码)
22
22
  * @param headers 请求头
23
23
  * @returns 响应体内容
24
24
  */
25
- export declare const postForBody: (url: string, body?: string, headers?: Record<string, any>) => Promise<string>;
25
+ export declare const postForBody: (url: string, body?: string | object, headers?: Record<string, any>) => Promise<string>;
package/dist/http.js CHANGED
@@ -2,33 +2,37 @@
2
2
  * 发送 HTTP 请求,获取响应体内容
3
3
  * @param method 请求方法
4
4
  * @param url 请求 URL
5
- * @param body 请求体
5
+ * @param body 请求体(UTF-8 编码)
6
6
  * @param headers 请求头
7
7
  * @returns 响应体内容
8
8
  */
9
9
  export const requestForBody = async (method, url, body, headers) => {
10
- const resp = await http.request(method, url, body ?? "null", headers ? JSON.stringify(headers) : "null");
10
+ if (body && typeof body === "object") {
11
+ body = JSON.stringify(body);
12
+ headers = { ...headers, "Content-Type": "application/json" };
13
+ }
14
+ const resp = await http.request(method, url, body ?? null, headers ? JSON.stringify(headers) : null);
11
15
  if (resp.status_code >= 200 && resp.status_code < 400) {
12
16
  return resp.body;
13
17
  }
14
18
  else {
15
- throw new Error(`HTTP request failed with status ${resp.status_code}`);
19
+ throw new Error(`HTTP request failed with status ${resp.status_code}: ${resp.body}`);
16
20
  }
17
21
  };
18
22
  /**
19
23
  * 发送 HTTP GET 请求,获取响应体内容
20
24
  * @param url 请求 URL
21
- * @param body 请求体
25
+ * @param body 请求体(UTF-8 编码)
22
26
  * @param headers 请求头
23
27
  * @returns 响应体内容
24
28
  */
25
- export const getForBody = async (url, body, headers) => {
29
+ export const getForBody = (url, body, headers) => {
26
30
  return requestForBody("GET", url, body, headers);
27
31
  };
28
32
  /**
29
33
  * 发送 HTTP POST 请求,获取响应体内容
30
34
  * @param url 请求 URL
31
- * @param body 请求体
35
+ * @param body 请求体(UTF-8 编码)
32
36
  * @param headers 请求头
33
37
  * @returns 响应体内容
34
38
  */
package/dist/mouse.js CHANGED
@@ -72,9 +72,9 @@ export const naturalMouseMove = async (x1, y1, x2, y2, options) => {
72
72
  return mouseMoveAlongWaypoints(waypoints, options);
73
73
  };
74
74
  /** 使用回放脚本模拟滚动 */
75
- const simulateScroll = async (scrollAmountInClicks, times) => {
75
+ const simulateScroll = async (wheelDelta, times) => {
76
76
  const script = {
77
- macroEvents: Array(times).fill({ type: 6, mouseX: 0, mouseY: scrollAmountInClicks, time: 0 }),
77
+ macroEvents: Array(times).fill({ type: 6, mouseX: 0, mouseY: wheelDelta, time: 0 }),
78
78
  info: { name: "", description: "", x: 0, y: 0, width: 1920, height: 1080, recordDpi: 1.5 }
79
79
  };
80
80
  await keyMouseScript.run(JSON.stringify(script));
@@ -84,7 +84,7 @@ const simulateScroll = async (scrollAmountInClicks, times) => {
84
84
  * @param height 滚动高度
85
85
  * @param algorithm 自定义滚动算法函数,接收高度参数并返回滚动次数(默认算法为每18像素滚动一次)
86
86
  */
87
- export const mouseScrollUp = (height, algorithm = h => Math.floor(h / 18)) => {
87
+ export const mouseScrollUp = (height, algorithm = h => Math.floor(h / 17.9795)) => {
88
88
  return simulateScroll(120, algorithm(height));
89
89
  };
90
90
  /**
@@ -92,7 +92,7 @@ export const mouseScrollUp = (height, algorithm = h => Math.floor(h / 18)) => {
92
92
  * @param height 滚动高度
93
93
  * @param algorithm 自定义滚动算法函数,接收高度参数并返回滚动次数(默认算法为每18像素滚动一次)
94
94
  */
95
- export const mouseScrollDown = (height, algorithm = h => Math.floor(h / 18)) => {
95
+ export const mouseScrollDown = (height, algorithm = h => Math.floor(h / 17.9795)) => {
96
96
  return simulateScroll(-120, algorithm(height));
97
97
  };
98
98
  /**
package/dist/ocr.d.ts CHANGED
@@ -9,14 +9,14 @@ export type ImageMat = ReturnType<typeof file.readImageMatSync>;
9
9
  export type MatchDirection = "north" /** 上半边 */ | "north-east" /** 右上四分之一 */ | "east" /** 右半边 */ | "south-east" /** 右下四分之一 */ | "south" /** 下半边 */ | "south-west" /** 左下四分之一 */ | "west" /** 左半边 */ | "north-west"; /** 左上四分之一 */
10
10
  /**
11
11
  * 在整个画面内搜索图片
12
- * @param image 图片路径 或 图片矩阵
12
+ * @param image 图片路径 或 图片Mat
13
13
  * @param config 识别对象配置
14
14
  * @returns 如果找到匹配的图片区域,则返回该区域
15
15
  */
16
16
  export declare const findImage: (image: string | ImageMat, config?: ROConfig) => Region | undefined;
17
17
  /**
18
18
  * 在指定区域内搜索图片
19
- * @param image 图片路径 或 图片矩阵
19
+ * @param image 图片路径 或 图片Mat
20
20
  * @param x 水平方向偏移量(像素)
21
21
  * @param y 垂直方向偏移量(像素)
22
22
  * @param w 宽度
@@ -27,7 +27,7 @@ export declare const findImage: (image: string | ImageMat, config?: ROConfig) =>
27
27
  export declare const findImageWithinBounds: (image: string | ImageMat, x: number, y: number, w: number, h: number, config?: ROConfig) => Region | undefined;
28
28
  /**
29
29
  * 在指定坐标范围内搜索图片
30
- * @param image 图片路径 或 图片矩阵
30
+ * @param image 图片路径 或 图片Mat
31
31
  * @param left 左边界偏移量(像素)
32
32
  * @param top 上边界偏移量(像素)
33
33
  * @param right 右边界偏移量(像素)
@@ -38,13 +38,13 @@ export declare const findImageWithinBounds: (image: string | ImageMat, x: number
38
38
  export declare const findImageBetweenCoordinates: (image: string | ImageMat, left: number, top: number, right: number, bottom: number, config?: ROConfig) => Region | undefined;
39
39
  /**
40
40
  * 在指定方向上搜索图片
41
- * @param image 图片路径 或 图片矩阵
41
+ * @param image 图片路径 或 图片Mat
42
42
  * @param direction 搜索方向
43
43
  * @param config 识别对象配置
44
44
  * @returns 如果找到匹配的图片区域,则返回该区域
45
45
  */
46
46
  export declare const findImageInDirection: (image: string | ImageMat, direction: MatchDirection, config?: ROConfig) => Region | undefined;
47
- /** 文本搜索选项 */
47
+ /** 文本匹配选项 */
48
48
  export type TextMatchOptions = {
49
49
  /** 是否忽略大小写(默认: 是) */
50
50
  ignoreCase?: boolean;
@@ -107,6 +107,15 @@ export type ListView = {
107
107
  /** 纵向内边距 (默认: 10) */
108
108
  paddingY?: number;
109
109
  };
110
+ /**
111
+ * 在列表视图中滚动搜索区域
112
+ * @param condition 查找条件
113
+ * @param listView 列表视图参数
114
+ * @param retryOptions 重试选项
115
+ * @param sampling 区域采样函数,通过采样区域画面变化判断列表是否触底(默认:取上半部分)
116
+ * @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
117
+ */
118
+ export declare const findWithinListView: (condition: (listViewRegion: ImageRegion) => Region | undefined, listView: ListView, retryOptions?: RetryOptions, sampling?: (listViewRegion: ImageRegion) => ImageRegion) => Promise<Region | undefined>;
110
119
  /**
111
120
  * 在列表视图中滚动搜索文本
112
121
  * @param text 待搜索文本
@@ -116,4 +125,13 @@ export type ListView = {
116
125
  * @param config 识别对象配置
117
126
  * @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
118
127
  */
119
- export declare const findTextWithinListView: (text: string, listView: ListView, matchOptions?: TextMatchOptions, retryOptions?: RetryOptions, config?: ROConfig) => Promise<Region | undefined>;
128
+ export declare const findTextWithinListView: (text: string, listView: ListView, matchOptions?: TextMatchOptions, retryOptions?: RetryOptions, config?: ROConfig, sampling?: (listViewRegion: ImageRegion) => ImageRegion) => Promise<Region | undefined>;
129
+ /**
130
+ * 在列表视图中查找图像
131
+ * @param image 图片路径 或 图片Mat
132
+ * @param listView 列表视图参数
133
+ * @param config 识别对象配置
134
+ * @param retryOptions 重试选项
135
+ * @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
136
+ */
137
+ export declare const findImageWithinListView: (image: string | ImageMat, listView: ListView, config?: ROConfig, retryOptions?: RetryOptions, sampling?: (listViewRegion: ImageRegion) => ImageRegion) => Promise<Region | undefined>;
package/dist/ocr.js CHANGED
@@ -15,7 +15,7 @@ const directionToBounds = (direction) => {
15
15
  };
16
16
  /**
17
17
  * 在整个画面内搜索图片
18
- * @param image 图片路径 或 图片矩阵
18
+ * @param image 图片路径 或 图片Mat
19
19
  * @param config 识别对象配置
20
20
  * @returns 如果找到匹配的图片区域,则返回该区域
21
21
  */
@@ -39,7 +39,7 @@ export const findImage = (image, config = {}) => {
39
39
  };
40
40
  /**
41
41
  * 在指定区域内搜索图片
42
- * @param image 图片路径 或 图片矩阵
42
+ * @param image 图片路径 或 图片Mat
43
43
  * @param x 水平方向偏移量(像素)
44
44
  * @param y 垂直方向偏移量(像素)
45
45
  * @param w 宽度
@@ -67,7 +67,7 @@ export const findImageWithinBounds = (image, x, y, w, h, config = {}) => {
67
67
  };
68
68
  /**
69
69
  * 在指定坐标范围内搜索图片
70
- * @param image 图片路径 或 图片矩阵
70
+ * @param image 图片路径 或 图片Mat
71
71
  * @param left 左边界偏移量(像素)
72
72
  * @param top 上边界偏移量(像素)
73
73
  * @param right 右边界偏移量(像素)
@@ -80,7 +80,7 @@ export const findImageBetweenCoordinates = (image, left, top, right, bottom, con
80
80
  };
81
81
  /**
82
82
  * 在指定方向上搜索图片
83
- * @param image 图片路径 或 图片矩阵
83
+ * @param image 图片路径 或 图片Mat
84
84
  * @param direction 搜索方向
85
85
  * @param config 识别对象配置
86
86
  * @returns 如果找到匹配的图片区域,则返回该区域
@@ -89,7 +89,14 @@ export const findImageInDirection = (image, direction, config = {}) => {
89
89
  const { x, y, w, h } = directionToBounds(direction);
90
90
  return findImageWithinBounds(image, x, y, w, h, config);
91
91
  };
92
- const findFirst = (ir, ro, predicate) => {
92
+ /**
93
+ * 在图像区域内查找第一个符合条件的识别区域
94
+ * @param ir 图像区域
95
+ * @param ro 识别对象
96
+ * @param predicate 筛选条件
97
+ * @returns 第一个符合条件的识别区域,未找到则返回 undefined
98
+ */
99
+ const findFirstRegion = (ir, ro, predicate) => {
93
100
  const candidates = ir.findMulti(ro);
94
101
  for (let i = 0; i < candidates.count; i++) {
95
102
  if (predicate(candidates[i]))
@@ -97,6 +104,19 @@ const findFirst = (ir, ro, predicate) => {
97
104
  }
98
105
  return undefined;
99
106
  };
107
+ /**
108
+ * 文本匹配
109
+ * @param text 待匹配文本
110
+ * @param searchText 待搜索文本
111
+ * @param options 搜索选项
112
+ * @returns 是否匹配
113
+ */
114
+ const textMatch = (text, searchText, options) => {
115
+ const { ignoreCase = true, contains = false } = options || {};
116
+ text = ignoreCase ? text.toLowerCase() : text;
117
+ searchText = ignoreCase ? searchText.toLowerCase() : searchText;
118
+ return contains ? text.includes(searchText) : text === searchText;
119
+ };
100
120
  /**
101
121
  * 在整个画面内搜索文本
102
122
  * @param text 待搜索文本
@@ -105,18 +125,14 @@ const findFirst = (ir, ro, predicate) => {
105
125
  * @returns 如果找到匹配的文本区域,则返回该区域
106
126
  */
107
127
  export const findText = (text, options, config = {}) => {
108
- const { ignoreCase = true, contains = false } = options || {};
109
- const searchText = ignoreCase ? text.toLowerCase() : text;
110
128
  const ir = captureGameRegion();
111
129
  try {
112
130
  const ro = RecognitionObject.ocrThis;
113
131
  if (Object.keys(config).length > 0) {
114
132
  Object.assign(ro, config) && ro.initTemplate();
115
133
  }
116
- return findFirst(ir, ro, region => {
117
- const itemText = ignoreCase ? region.text.toLowerCase() : region.text;
118
- const isMatch = contains ? itemText.includes(searchText) : itemText === searchText;
119
- return isMatch && region.isExist();
134
+ return findFirstRegion(ir, ro, region => {
135
+ return region.isExist() && textMatch(region.text, text, options);
120
136
  });
121
137
  }
122
138
  catch (err) {
@@ -138,18 +154,14 @@ export const findText = (text, options, config = {}) => {
138
154
  * @returns 如果找到匹配的文本区域,则返回该区域
139
155
  */
140
156
  export const findTextWithinBounds = (text, x, y, w, h, options, config = {}) => {
141
- const { ignoreCase = true, contains = false } = options || {};
142
- const searchText = ignoreCase ? text.toLowerCase() : text;
143
157
  const ir = captureGameRegion();
144
158
  try {
145
159
  const ro = RecognitionObject.ocr(x, y, w, h);
146
160
  if (Object.keys(config).length > 0) {
147
161
  Object.assign(ro, config) && ro.initTemplate();
148
162
  }
149
- return findFirst(ir, ro, region => {
150
- const itemText = ignoreCase ? region.text.toLowerCase() : region.text;
151
- const isMatch = contains ? itemText.includes(searchText) : itemText === searchText;
152
- return isMatch && region.isExist();
163
+ return findFirstRegion(ir, ro, region => {
164
+ return region.isExist() && textMatch(region.text, text, options);
153
165
  });
154
166
  }
155
167
  catch (err) {
@@ -186,40 +198,75 @@ export const findTextInDirection = (text, direction, options, config = {}) => {
186
198
  return findTextWithinBounds(text, x, y, w, h, options, config);
187
199
  };
188
200
  /**
189
- * 在列表视图中滚动搜索文本
190
- * @param text 待搜索文本
201
+ * 在列表视图中滚动搜索区域
202
+ * @param condition 查找条件
191
203
  * @param listView 列表视图参数
192
- * @param matchOptions 搜索选项
193
204
  * @param retryOptions 重试选项
194
- * @param config 识别对象配置
195
- * @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
205
+ * @param sampling 区域采样函数,通过采样区域画面变化判断列表是否触底(默认:取上半部分)
206
+ * @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
196
207
  */
197
- export const findTextWithinListView = async (text, listView, matchOptions, retryOptions, config = {}) => {
208
+ export const findWithinListView = async (condition, listView, retryOptions, sampling) => {
198
209
  const { x, y, w, h, lineHeight, scrollLines = 1, paddingX = 10, paddingY = 10 } = listView;
199
- const { maxAttempts = 30, retryInterval = 1000 } = retryOptions || {};
200
- const findTargetText = () => findTextWithinBounds(text, x, y, w, h, matchOptions, config);
201
- let lastTextRegion;
210
+ const { maxAttempts = 99, retryInterval = 1000 } = retryOptions || {};
211
+ sampling = sampling || (r => r.deriveCrop(0, 0, r.width, Math.floor(r.height / 2)));
212
+ const captureListViewRegion = () => captureGameRegion().deriveCrop(x, y, w, h);
213
+ let _lvr;
202
214
  const isReachedBottom = () => {
203
- const textRegion = findFirst(captureGameRegion(), RecognitionObject.ocr(x, y, w, h), region => {
204
- return region.isExist() && region.text.trim().length > 0;
205
- });
206
- if (textRegion) {
207
- if (lastTextRegion?.text === textRegion.text &&
208
- Math.abs(textRegion.y - lastTextRegion.y) < lineHeight) {
215
+ const region = sampling(captureListViewRegion());
216
+ if (region?.isExist()) {
217
+ if (_lvr?.find(RecognitionObject.templateMatch(region.srcMat))) {
209
218
  return true;
210
219
  }
211
220
  else {
212
- lastTextRegion = textRegion;
221
+ _lvr = region;
213
222
  return false;
214
223
  }
215
224
  }
216
- // 异常情况: 找不到任何文本
217
- return true;
225
+ return true; // 异常情况: 无法获取列表视图截图
218
226
  };
219
- const isTextFoundOrBottomReached = await waitForAction(() => findTargetText() != undefined || isReachedBottom(), async () => {
227
+ const isFoundOrReachedBottom = await waitForAction(() => condition(captureListViewRegion())?.isExist() || isReachedBottom(), async () => {
220
228
  moveMouseTo(x + w - paddingX, y + paddingY); // 移动到滚动条附近
221
229
  await sleep(50);
222
230
  await mouseScrollDownLines(scrollLines, lineHeight); // 滚动指定行数
223
231
  }, { maxAttempts, retryInterval });
224
- return isTextFoundOrBottomReached ? findTargetText() : undefined;
232
+ return isFoundOrReachedBottom ? condition(captureListViewRegion()) : undefined;
233
+ };
234
+ /**
235
+ * 在列表视图中滚动搜索文本
236
+ * @param text 待搜索文本
237
+ * @param listView 列表视图参数
238
+ * @param matchOptions 搜索选项
239
+ * @param retryOptions 重试选项
240
+ * @param config 识别对象配置
241
+ * @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
242
+ */
243
+ export const findTextWithinListView = async (text, listView, matchOptions, retryOptions, config = {}, sampling) => {
244
+ const ro = RecognitionObject.ocrThis;
245
+ if (Object.keys(config).length > 0) {
246
+ Object.assign(ro, config) && ro.initTemplate();
247
+ }
248
+ return findWithinListView(lvr => {
249
+ return findFirstRegion(lvr, ro, region => {
250
+ return region.isExist() && textMatch(region.text, text, matchOptions);
251
+ });
252
+ }, listView, retryOptions, sampling);
253
+ };
254
+ /**
255
+ * 在列表视图中查找图像
256
+ * @param image 图片路径 或 图片Mat
257
+ * @param listView 列表视图参数
258
+ * @param config 识别对象配置
259
+ * @param retryOptions 重试选项
260
+ * @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
261
+ */
262
+ export const findImageWithinListView = async (image, listView, config = {}, retryOptions, sampling) => {
263
+ const mat = typeof image === "string" ? file.readImageMatSync(image) : image;
264
+ const ro = RecognitionObject.templateMatch(mat);
265
+ if (Object.keys(config).length > 0) {
266
+ Object.assign(ro, config) && ro.initTemplate();
267
+ }
268
+ return findWithinListView(ir => {
269
+ const region = ir.find(ro);
270
+ return region.isExist() ? region : undefined;
271
+ }, listView, retryOptions, sampling);
225
272
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bettergi/utils",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "开发 BetterGI 脚本常用工具集",
5
5
  "type": "module",
6
6
  "author": "Bread Grocery<https://github.com/breadgrocery>",
@@ -33,8 +33,8 @@
33
33
  "build": "rimraf dist && tsc"
34
34
  },
35
35
  "devDependencies": {
36
- "@bettergi/types": "workspace:latest",
37
- "rimraf": "^6.1.0",
36
+ "@bettergi/types": "workspace:^",
37
+ "rimraf": "^6.1.2",
38
38
  "typescript": "^5.9.3"
39
39
  }
40
40
  }