id-scanner-lib 1.6.7 → 2.0.0
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/dist/id-scanner-lib.esm.js +994 -1139
- package/dist/id-scanner-lib.esm.js.map +1 -1
- package/dist/id-scanner-lib.js +995 -1144
- package/dist/id-scanner-lib.js.map +1 -1
- package/package.json +1 -1
- package/src/compat/index.ts +7 -0
- package/src/compat/v1-adapter.ts +84 -0
- package/src/core/camera-manager.ts +43 -76
- package/src/core/camera-stream-manager.ts +318 -0
- package/src/core/config.ts +113 -267
- package/src/core/errors.ts +68 -117
- package/src/core/logger.ts +158 -81
- package/src/core/resource-manager.ts +150 -0
- package/src/core/scanner.ts +109 -0
- package/src/core/utils/browser.ts +7 -0
- package/src/core/utils/canvas-pool.ts +171 -0
- package/src/core/utils/canvas.ts +7 -0
- package/src/core/utils/image.ts +7 -0
- package/src/core/utils/index.ts +9 -0
- package/src/core/utils/resource-manager.ts +155 -0
- package/src/core/utils/validate.ts +7 -0
- package/src/core/utils/worker.ts +130 -0
- package/src/modules/face/comparator/comparator.ts +45 -0
- package/src/modules/face/comparator/index.ts +1 -0
- package/src/modules/face/detector/detector.ts +83 -0
- package/src/modules/face/detector/index.ts +2 -0
- package/src/modules/face/detector/types.ts +80 -0
- package/src/modules/face/face-comparator.ts +150 -0
- package/src/modules/face/face-detector-options.ts +104 -0
- package/src/modules/face/face-detector.ts +121 -376
- package/src/modules/face/face-detector.ts.bak +991 -0
- package/src/modules/face/face-model-loader.ts +222 -0
- package/src/modules/face/face-result-converter.ts +225 -0
- package/src/modules/face/face-tracker.ts +207 -0
- package/src/modules/face/liveness/index.ts +7 -0
- package/src/modules/face/liveness-detector.ts +2 -2
- package/src/modules/face/tracker/index.ts +7 -0
- package/src/modules/id-card/anti-fake/index.ts +7 -0
- package/src/modules/id-card/detector/index.ts +7 -0
- package/src/modules/id-card/id-card-text-parser.ts +151 -0
- package/src/modules/id-card/ocr-processor.ts +20 -257
- package/src/modules/id-card/ocr-worker.ts +2 -183
- package/src/modules/id-card/parser/index.ts +7 -0
- package/src/modules/qr/scanner/index.ts +7 -0
- package/src/utils/canvas-pool.ts +273 -0
- package/src/utils/edge-detector.ts +232 -0
- package/src/utils/image-processing.ts +92 -419
- package/src/utils/index.ts +1 -0
package/src/core/config.ts
CHANGED
|
@@ -1,37 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file 配置管理器
|
|
3
|
-
* @description 提供全局配置管理功能
|
|
2
|
+
* @file 配置管理器 + Scanner 配置
|
|
3
|
+
* @description 提供全局配置管理功能 + Scanner v2.0 配置接口
|
|
4
4
|
* @module core/config
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
// ============================================================
|
|
8
|
+
// 原有 ConfigManager(保持向后兼容)
|
|
9
|
+
// ============================================================
|
|
10
|
+
|
|
11
11
|
export class ConfigManager {
|
|
12
|
-
/** 单例实例 */
|
|
13
12
|
private static instance: ConfigManager;
|
|
14
|
-
|
|
15
|
-
/** 配置存储 */
|
|
16
13
|
private config: Record<string, any> = {};
|
|
17
|
-
|
|
18
|
-
/** 配置变更回调 */
|
|
19
14
|
private changeCallbacks: Map<string, Array<(value: any, oldValue: any) => void>> = new Map();
|
|
20
|
-
|
|
21
|
-
/** 初始化状态 */
|
|
22
15
|
private initialized = false;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 私有构造函数
|
|
26
|
-
*/
|
|
16
|
+
|
|
27
17
|
private constructor() {
|
|
28
|
-
// 设置默认配置
|
|
29
18
|
this._resetDefaults();
|
|
30
19
|
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 获取单例实例
|
|
34
|
-
*/
|
|
20
|
+
|
|
35
21
|
public static getInstance(): ConfigManager {
|
|
36
22
|
if (!ConfigManager.instance) {
|
|
37
23
|
ConfigManager.instance = new ConfigManager();
|
|
@@ -39,285 +25,145 @@ export class ConfigManager {
|
|
|
39
25
|
return ConfigManager.instance;
|
|
40
26
|
}
|
|
41
27
|
|
|
42
|
-
/**
|
|
43
|
-
* 重置单例实例(主要用于测试)
|
|
44
|
-
*/
|
|
45
28
|
public static resetInstance(): void {
|
|
46
29
|
ConfigManager.instance = undefined as any;
|
|
47
30
|
}
|
|
48
31
|
|
|
49
|
-
/**
|
|
50
|
-
* 重置为默认配置
|
|
51
|
-
*/
|
|
52
32
|
private _resetDefaults(): void {
|
|
53
33
|
this.config = {
|
|
54
34
|
debug: false,
|
|
55
35
|
logLevel: 'info',
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
36
|
+
modelPath: '/models',
|
|
37
|
+
maxRetries: 3,
|
|
38
|
+
retryDelay: 1000,
|
|
39
|
+
detectionInterval: 100,
|
|
40
|
+
face: {
|
|
41
|
+
enabled: true,
|
|
42
|
+
confidenceThreshold: 0.5,
|
|
43
|
+
maxFaces: 10,
|
|
44
|
+
},
|
|
45
|
+
idCard: {
|
|
46
|
+
enabled: false,
|
|
47
|
+
},
|
|
48
|
+
qr: {
|
|
49
|
+
enabled: false,
|
|
63
50
|
},
|
|
64
|
-
performance: {
|
|
65
|
-
useCache: true
|
|
66
|
-
}
|
|
67
51
|
};
|
|
68
52
|
this.initialized = true;
|
|
69
53
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
get<T = any>(key: string, defaultValue?: T): T {
|
|
77
|
-
const value = this.getNestedValue(this.config, key);
|
|
78
|
-
return (value !== undefined) ? value : (defaultValue as T);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* 设置配置值
|
|
83
|
-
* @param key 配置键,支持点号分隔的路径
|
|
84
|
-
* @param value 配置值
|
|
85
|
-
*/
|
|
86
|
-
set<T = any>(key: string, value: T): void {
|
|
87
|
-
const oldValue = this.get(key);
|
|
88
|
-
|
|
89
|
-
// 如果值相同,不做任何事
|
|
90
|
-
if (oldValue === value) {
|
|
91
|
-
return;
|
|
54
|
+
|
|
55
|
+
public get<T = any>(key: string, defaultValue?: T): T {
|
|
56
|
+
const keys = key.split('.');
|
|
57
|
+
let value: any = this.config;
|
|
58
|
+
for (const k of keys) {
|
|
59
|
+
value = value?.[k];
|
|
92
60
|
}
|
|
93
|
-
|
|
94
|
-
this.setNestedValue(this.config, key, value);
|
|
95
|
-
|
|
96
|
-
// 触发变更回调
|
|
97
|
-
this.triggerChangeCallbacks(key, value, oldValue);
|
|
61
|
+
return (value !== undefined ? value : defaultValue) as T;
|
|
98
62
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
reset(): void {
|
|
114
|
-
const oldConfig = { ...this.config };
|
|
115
|
-
|
|
116
|
-
// 使用私有 reset 方法重建默认配置
|
|
117
|
-
this.config = {
|
|
118
|
-
debug: false,
|
|
119
|
-
logLevel: 'info',
|
|
120
|
-
camera: {
|
|
121
|
-
resolution: {
|
|
122
|
-
width: 1280,
|
|
123
|
-
height: 720
|
|
124
|
-
},
|
|
125
|
-
frameRate: 30,
|
|
126
|
-
facingMode: 'environment'
|
|
127
|
-
},
|
|
128
|
-
performance: {
|
|
129
|
-
useCache: true
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// 触发所有回调
|
|
134
|
-
Object.keys(oldConfig).forEach(key => {
|
|
135
|
-
this.triggerChangeCallbacks(key, this.get(key), oldConfig[key]);
|
|
136
|
-
});
|
|
63
|
+
|
|
64
|
+
public set(key: string, value: any): void {
|
|
65
|
+
const keys = key.split('.');
|
|
66
|
+
let target: any = this.config;
|
|
67
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
68
|
+
if (!target[keys[i]]) target[keys[i]] = {};
|
|
69
|
+
target = target[keys[i]];
|
|
70
|
+
}
|
|
71
|
+
const oldValue = target[keys[keys.length - 1]];
|
|
72
|
+
target[keys[keys.length - 1]] = value;
|
|
73
|
+
const callbacks = this.changeCallbacks.get(key);
|
|
74
|
+
if (callbacks) {
|
|
75
|
+
callbacks.forEach(cb => cb(value, oldValue));
|
|
76
|
+
}
|
|
137
77
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
* 注册配置变更回调
|
|
141
|
-
* @param key 配置键
|
|
142
|
-
* @param callback 回调函数
|
|
143
|
-
*/
|
|
144
|
-
onConfigChange<T = any>(key: string, callback: (value: T, oldValue: T) => void): void {
|
|
78
|
+
|
|
79
|
+
public onChange(key: string, callback: (value: any, oldValue: any) => void): void {
|
|
145
80
|
if (!this.changeCallbacks.has(key)) {
|
|
146
81
|
this.changeCallbacks.set(key, []);
|
|
147
82
|
}
|
|
148
|
-
|
|
149
83
|
this.changeCallbacks.get(key)!.push(callback);
|
|
150
84
|
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
* @param callback 特定回调函数,如不提供则移除所有
|
|
156
|
-
*/
|
|
157
|
-
offConfigChange<T = any>(key: string, callback?: (value: T, oldValue: T) => void): void {
|
|
158
|
-
if (!this.changeCallbacks.has(key)) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (callback) {
|
|
163
|
-
// 移除特定回调
|
|
164
|
-
const callbacks = this.changeCallbacks.get(key)!;
|
|
165
|
-
const index = callbacks.indexOf(callback as any);
|
|
166
|
-
if (index !== -1) {
|
|
167
|
-
callbacks.splice(index, 1);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// 如果没有回调,删除键
|
|
171
|
-
if (callbacks.length === 0) {
|
|
172
|
-
this.changeCallbacks.delete(key);
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
// 移除所有回调
|
|
176
|
-
this.changeCallbacks.delete(key);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* 获取嵌套值
|
|
182
|
-
* @param obj 对象
|
|
183
|
-
* @param path 路径
|
|
184
|
-
*/
|
|
185
|
-
private getNestedValue(obj: Record<string, any>, path: string): any {
|
|
186
|
-
// 处理根路径
|
|
187
|
-
if (!path) {
|
|
188
|
-
return obj;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// 处理嵌套路径
|
|
192
|
-
const parts = path.split('.');
|
|
193
|
-
let current = obj;
|
|
194
|
-
|
|
195
|
-
for (const part of parts) {
|
|
196
|
-
if (current === undefined || current === null) {
|
|
197
|
-
return undefined;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
current = current[part];
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return current;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* 设置嵌套值
|
|
208
|
-
* @param obj 对象
|
|
209
|
-
* @param path 路径
|
|
210
|
-
* @param value 值
|
|
211
|
-
*/
|
|
212
|
-
private setNestedValue(obj: Record<string, any>, path: string, value: any): void {
|
|
213
|
-
// 处理根路径
|
|
214
|
-
if (!path) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 处理嵌套路径
|
|
219
|
-
const parts = path.split('.');
|
|
220
|
-
let current = obj;
|
|
221
|
-
|
|
222
|
-
// 遍历路径,直到倒数第二部分
|
|
223
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
224
|
-
const part = parts[i];
|
|
225
|
-
|
|
226
|
-
// 如果不存在,创建新对象
|
|
227
|
-
if (current[part] === undefined || current[part] === null || typeof current[part] !== 'object') {
|
|
228
|
-
current[part] = {};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
current = current[part];
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// 设置最终值
|
|
235
|
-
current[parts[parts.length - 1]] = value;
|
|
85
|
+
|
|
86
|
+
/** @deprecated Use onChange instead */
|
|
87
|
+
public onConfigChange<T = any>(key: string, callback: (value: T, oldValue: T) => void): void {
|
|
88
|
+
this.onChange(key, callback);
|
|
236
89
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
*/
|
|
244
|
-
private triggerChangeCallbacks(key: string, value: any, oldValue: any): void {
|
|
245
|
-
// 触发特定键的回调
|
|
246
|
-
if (this.changeCallbacks.has(key)) {
|
|
247
|
-
const callbacks = this.changeCallbacks.get(key)!;
|
|
248
|
-
callbacks.forEach(callback => {
|
|
249
|
-
try {
|
|
250
|
-
callback(value, oldValue);
|
|
251
|
-
} catch (error) {
|
|
252
|
-
console.error(`Error in config change callback for key ${key}:`, error);
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// 触发父路径的回调
|
|
258
|
-
const parts = key.split('.');
|
|
259
|
-
while (parts.length > 1) {
|
|
260
|
-
parts.pop();
|
|
261
|
-
const parentKey = parts.join('.');
|
|
262
|
-
|
|
263
|
-
if (this.changeCallbacks.has(parentKey)) {
|
|
264
|
-
const parentValue = this.get(parentKey);
|
|
265
|
-
this.changeCallbacks.get(parentKey)!.forEach(callback => {
|
|
266
|
-
try {
|
|
267
|
-
callback(parentValue, parentValue);
|
|
268
|
-
} catch (error) {
|
|
269
|
-
console.error(`Error in config change callback for parent key ${parentKey}:`, error);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
}
|
|
90
|
+
|
|
91
|
+
public removeChangeCallback(key: string, callback: (value: any, oldValue: any) => void): void {
|
|
92
|
+
const callbacks = this.changeCallbacks.get(key);
|
|
93
|
+
if (callbacks) {
|
|
94
|
+
const index = callbacks.indexOf(callback);
|
|
95
|
+
if (index > -1) callbacks.splice(index, 1);
|
|
273
96
|
}
|
|
274
97
|
}
|
|
275
98
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
*/
|
|
280
|
-
public isModuleEnabled(moduleName: string): boolean {
|
|
281
|
-
const key = `modules.${moduleName}.enabled`;
|
|
282
|
-
return this.get(key) ?? false;
|
|
99
|
+
public reset(): void {
|
|
100
|
+
this.config = {};
|
|
101
|
+
this._resetDefaults();
|
|
283
102
|
}
|
|
284
103
|
}
|
|
285
104
|
|
|
105
|
+
// ============================================================
|
|
106
|
+
// Scanner v2.0 配置接口
|
|
107
|
+
// ============================================================
|
|
108
|
+
|
|
286
109
|
/**
|
|
287
|
-
*
|
|
110
|
+
* Scanner configuration interface (v2.0)
|
|
288
111
|
*/
|
|
289
|
-
export interface
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
camera: {
|
|
298
|
-
resolution: { width: number; height: number };
|
|
299
|
-
frameRate: number;
|
|
300
|
-
facingMode: string;
|
|
112
|
+
export interface ScannerConfig {
|
|
113
|
+
debug?: boolean;
|
|
114
|
+
modules?: {
|
|
115
|
+
face?: boolean;
|
|
116
|
+
faceComparator?: boolean;
|
|
117
|
+
faceLiveness?: boolean;
|
|
118
|
+
idCard?: boolean;
|
|
119
|
+
qr?: boolean;
|
|
301
120
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
121
|
+
performance?: {
|
|
122
|
+
maxCanvasWidth?: number;
|
|
123
|
+
useWorker?: boolean;
|
|
124
|
+
lazyLoad?: boolean;
|
|
305
125
|
};
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Scanner module interface
|
|
130
|
+
* All modules must implement this interface
|
|
131
|
+
*/
|
|
132
|
+
export interface ScannerModule {
|
|
133
|
+
initialize(): Promise<void>;
|
|
134
|
+
destroy(): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Image source types
|
|
139
|
+
*/
|
|
140
|
+
export type ImageSource = HTMLVideoElement | HTMLCanvasElement | HTMLImageElement | ImageData | string;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Face detection result
|
|
144
|
+
*/
|
|
145
|
+
export interface Face {
|
|
146
|
+
box: {
|
|
147
|
+
x: number;
|
|
148
|
+
y: number;
|
|
149
|
+
width: number;
|
|
150
|
+
height: number;
|
|
151
|
+
};
|
|
152
|
+
confidence: number;
|
|
153
|
+
keypoints?: {
|
|
154
|
+
leftEye?: { x: number; y: number };
|
|
155
|
+
rightEye?: { x: number; y: number };
|
|
156
|
+
nose?: { x: number; y: number };
|
|
157
|
+
leftMouth?: { x: number; y: number };
|
|
158
|
+
rightMouth?: { x: number; y: number };
|
|
311
159
|
};
|
|
312
|
-
|
|
160
|
+
embedding?: number[];
|
|
161
|
+
}
|
|
313
162
|
|
|
314
163
|
/**
|
|
315
|
-
*
|
|
316
|
-
* 定义所有模块共享的基础配置属性
|
|
164
|
+
* Module configuration
|
|
317
165
|
*/
|
|
318
166
|
export interface ModuleConfig {
|
|
319
|
-
|
|
320
|
-
enabled: boolean;
|
|
321
|
-
/** 其他模块特定配置 */
|
|
167
|
+
enabled?: boolean;
|
|
322
168
|
[key: string]: any;
|
|
323
|
-
}
|
|
169
|
+
}
|
package/src/core/errors.ts
CHANGED
|
@@ -1,174 +1,125 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file
|
|
3
|
-
* @description
|
|
2
|
+
* @file Scanner Errors
|
|
3
|
+
* @description Error classes for Scanner
|
|
4
4
|
* @module core/errors
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* 所有库特定错误的基类
|
|
8
|
+
* Scanner specific error
|
|
10
9
|
*/
|
|
11
|
-
export class
|
|
12
|
-
/**
|
|
10
|
+
export class ScannerError extends Error {
|
|
11
|
+
/**
|
|
12
|
+
* Error code
|
|
13
|
+
*/
|
|
13
14
|
public code: string;
|
|
14
|
-
/**
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Module that threw the error
|
|
17
|
+
*/
|
|
18
|
+
public module?: string;
|
|
16
19
|
|
|
17
20
|
/**
|
|
18
|
-
*
|
|
19
|
-
* @param message
|
|
20
|
-
* @param
|
|
21
|
+
* Create a ScannerError
|
|
22
|
+
* @param message Error message
|
|
23
|
+
* @param code Error code
|
|
24
|
+
* @param module Module name
|
|
21
25
|
*/
|
|
22
|
-
constructor(message: string,
|
|
26
|
+
constructor(message: string, code: string, module?: string) {
|
|
23
27
|
super(message);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
|
|
28
|
-
// 设置错误代码
|
|
29
|
-
this.code = options?.code || 'UNKNOWN_ERROR';
|
|
30
|
-
|
|
31
|
-
// 设置错误原因
|
|
32
|
-
this.cause = options?.cause;
|
|
33
|
-
|
|
34
|
-
// 捕获堆栈 (Node.js专有,浏览器环境忽略)
|
|
35
|
-
if (typeof (Error as any).captureStackTrace === 'function') {
|
|
36
|
-
(Error as any).captureStackTrace(this, this.constructor);
|
|
37
|
-
}
|
|
28
|
+
this.name = 'ScannerError';
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.module = module;
|
|
38
31
|
}
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
/**
|
|
42
|
-
*
|
|
43
|
-
* 当库初始化失败时抛出
|
|
35
|
+
* Camera access error
|
|
44
36
|
*/
|
|
45
|
-
export class
|
|
46
|
-
constructor(message
|
|
47
|
-
super(
|
|
48
|
-
this.name = '
|
|
37
|
+
export class CameraAccessError extends Error {
|
|
38
|
+
constructor(message = 'Camera access denied') {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = 'CameraAccessError';
|
|
49
41
|
}
|
|
50
42
|
}
|
|
51
43
|
|
|
52
44
|
/**
|
|
53
|
-
*
|
|
54
|
-
* 当访问硬件设备(如摄像头)失败时抛出
|
|
45
|
+
* Device error
|
|
55
46
|
*/
|
|
56
|
-
export class DeviceError extends
|
|
57
|
-
constructor(message
|
|
58
|
-
super(
|
|
47
|
+
export class DeviceError extends Error {
|
|
48
|
+
constructor(message = 'Device error') {
|
|
49
|
+
super(message);
|
|
59
50
|
this.name = 'DeviceError';
|
|
60
51
|
}
|
|
61
52
|
}
|
|
62
53
|
|
|
63
54
|
/**
|
|
64
|
-
*
|
|
65
|
-
* 当无法访问或启动摄像头时抛出
|
|
55
|
+
* Resource load error
|
|
66
56
|
*/
|
|
67
|
-
export class
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.name = 'CameraAccessError';
|
|
57
|
+
export class ResourceLoadError extends Error {
|
|
58
|
+
public readonly id?: string;
|
|
59
|
+
constructor(message = 'Failed to load resource', id?: string) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = 'ResourceLoadError';
|
|
62
|
+
this.id = id;
|
|
74
63
|
}
|
|
75
64
|
}
|
|
76
65
|
|
|
77
66
|
/**
|
|
78
|
-
*
|
|
79
|
-
* 当人脸检测过程失败时抛出
|
|
67
|
+
* Face detection error
|
|
80
68
|
*/
|
|
81
|
-
export class FaceDetectionError extends
|
|
82
|
-
constructor(message
|
|
83
|
-
super(
|
|
69
|
+
export class FaceDetectionError extends Error {
|
|
70
|
+
constructor(message = 'Face detection failed') {
|
|
71
|
+
super(message);
|
|
84
72
|
this.name = 'FaceDetectionError';
|
|
85
73
|
}
|
|
86
74
|
}
|
|
87
75
|
|
|
88
76
|
/**
|
|
89
|
-
*
|
|
90
|
-
* 当人脸比对过程失败时抛出
|
|
77
|
+
* Face comparison error
|
|
91
78
|
*/
|
|
92
|
-
export class FaceComparisonError extends
|
|
93
|
-
constructor(message
|
|
94
|
-
super(
|
|
79
|
+
export class FaceComparisonError extends Error {
|
|
80
|
+
constructor(message = 'Face comparison failed') {
|
|
81
|
+
super(message);
|
|
95
82
|
this.name = 'FaceComparisonError';
|
|
96
83
|
}
|
|
97
84
|
}
|
|
98
85
|
|
|
99
86
|
/**
|
|
100
|
-
*
|
|
101
|
-
* 当活体检测过程失败时抛出
|
|
102
|
-
*/
|
|
103
|
-
export class LivenessDetectionError extends IDScannerError {
|
|
104
|
-
constructor(message: string) {
|
|
105
|
-
super(`活体检测失败: ${message}`, { code: 'LIVENESS_DETECTION_FAILED' });
|
|
106
|
-
this.name = 'LivenessDetectionError';
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* OCR识别错误
|
|
112
|
-
* 当OCR文字识别失败时抛出
|
|
87
|
+
* Initialization error
|
|
113
88
|
*/
|
|
114
|
-
export class
|
|
115
|
-
constructor(message
|
|
116
|
-
super(
|
|
117
|
-
this.name = '
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* 二维码扫描错误
|
|
123
|
-
* 当二维码扫描失败时抛出
|
|
124
|
-
*/
|
|
125
|
-
export class QRScanError extends IDScannerError {
|
|
126
|
-
constructor(message: string) {
|
|
127
|
-
super(`二维码扫描失败: ${message}`, { code: 'QR_SCAN_FAILED' });
|
|
128
|
-
this.name = 'QRScanError';
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 身份证检测错误
|
|
134
|
-
* 当身份证检测失败时抛出
|
|
135
|
-
*/
|
|
136
|
-
export class IDCardDetectionError extends IDScannerError {
|
|
137
|
-
constructor(message: string) {
|
|
138
|
-
super(`身份证检测失败: ${message}`, { code: 'ID_CARD_DETECTION_FAILED' });
|
|
139
|
-
this.name = 'IDCardDetectionError';
|
|
89
|
+
export class InitializationError extends Error {
|
|
90
|
+
constructor(message = 'Initialization failed') {
|
|
91
|
+
super(message);
|
|
92
|
+
this.name = 'InitializationError';
|
|
140
93
|
}
|
|
141
94
|
}
|
|
142
95
|
|
|
143
96
|
/**
|
|
144
|
-
*
|
|
145
|
-
* 当无法加载必要资源(如模型)时抛出
|
|
97
|
+
* Liveness detection error
|
|
146
98
|
*/
|
|
147
|
-
export class
|
|
148
|
-
constructor(
|
|
149
|
-
super(
|
|
150
|
-
this.name = '
|
|
99
|
+
export class LivenessDetectionError extends Error {
|
|
100
|
+
constructor(message = 'Liveness detection failed') {
|
|
101
|
+
super(message);
|
|
102
|
+
this.name = 'LivenessDetectionError';
|
|
151
103
|
}
|
|
152
104
|
}
|
|
153
105
|
|
|
154
106
|
/**
|
|
155
|
-
*
|
|
156
|
-
* 当提供的参数无效时抛出
|
|
107
|
+
* Error codes for Scanner
|
|
157
108
|
*/
|
|
158
|
-
export
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
109
|
+
export const ErrorCodes = {
|
|
110
|
+
/** Scanner not initialized */
|
|
111
|
+
NOT_INITIALIZED: 'SCANNER_001',
|
|
112
|
+
/** Module not found */
|
|
113
|
+
MODULE_NOT_FOUND: 'SCANNER_002',
|
|
114
|
+
/** Detection failed */
|
|
115
|
+
DETECTION_FAILED: 'SCANNER_003',
|
|
116
|
+
/** Camera access denied */
|
|
117
|
+
CAMERA_ACCESS_DENIED: 'CAMERA_001',
|
|
118
|
+
/** Camera not available */
|
|
119
|
+
CAMERA_NOT_AVAILABLE: 'CAMERA_002',
|
|
120
|
+
} as const;
|
|
164
121
|
|
|
165
122
|
/**
|
|
166
|
-
*
|
|
167
|
-
* 当尝试使用不支持的功能或当前环境无法使用的功能时抛出
|
|
123
|
+
* Type for error codes
|
|
168
124
|
*/
|
|
169
|
-
export
|
|
170
|
-
constructor(feature: string) {
|
|
171
|
-
super(`不支持的功能: ${feature}`, { code: 'NOT_SUPPORTED' });
|
|
172
|
-
this.name = 'NotSupportedError';
|
|
173
|
-
}
|
|
174
|
-
}
|
|
125
|
+
export type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];
|