id-scanner-lib 1.0.0 → 1.1.1
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 +96 -0
- package/dist/core.d.ts +77 -0
- package/dist/id-recognition/data-extractor.d.ts +31 -0
- package/dist/id-recognition/id-detector.d.ts +25 -1
- package/dist/id-scanner-core.esm.js +10710 -0
- package/dist/id-scanner-core.esm.js.map +1 -0
- package/dist/id-scanner-core.js +10722 -0
- package/dist/id-scanner-core.js.map +1 -0
- package/dist/id-scanner-core.min.js +9 -0
- package/dist/id-scanner-core.min.js.map +1 -0
- package/dist/id-scanner-ocr.esm.js +914 -0
- package/dist/id-scanner-ocr.esm.js.map +1 -0
- package/dist/id-scanner-ocr.js +923 -0
- package/dist/id-scanner-ocr.js.map +1 -0
- package/dist/id-scanner-ocr.min.js +9 -0
- package/dist/id-scanner-ocr.min.js.map +1 -0
- package/dist/id-scanner-qr.esm.js +613 -0
- package/dist/id-scanner-qr.esm.js.map +1 -0
- package/dist/id-scanner-qr.js +622 -0
- package/dist/id-scanner-qr.js.map +1 -0
- package/dist/id-scanner-qr.min.js +9 -0
- package/dist/id-scanner-qr.min.js.map +1 -0
- package/dist/id-scanner.js +1243 -94656
- package/dist/id-scanner.js.map +1 -1
- package/dist/id-scanner.min.js +7 -7
- package/dist/id-scanner.min.js.map +1 -1
- package/dist/index-umd.d.ts +96 -0
- package/dist/index.d.ts +23 -88
- package/dist/ocr-module.d.ts +67 -0
- package/dist/qr-module.d.ts +68 -0
- package/dist/types/core.d.ts +77 -0
- package/dist/types/demo/demo.d.ts +14 -0
- package/dist/types/id-recognition/data-extractor.d.ts +105 -0
- package/dist/types/id-recognition/id-detector.d.ts +100 -0
- package/dist/types/id-recognition/ocr-processor.d.ts +64 -0
- package/dist/types/index-umd.d.ts +96 -0
- package/dist/types/index.d.ts +78 -0
- package/dist/types/ocr-module.d.ts +67 -0
- package/dist/types/qr-module.d.ts +68 -0
- package/dist/types/scanner/barcode-scanner.d.ts +90 -0
- package/dist/types/scanner/qr-scanner.d.ts +80 -0
- package/dist/types/utils/camera.d.ts +81 -0
- package/dist/types/utils/image-processing.d.ts +75 -0
- package/dist/types/utils/types.d.ts +65 -0
- package/dist/utils/camera.d.ts +18 -13
- package/dist/utils/types.d.ts +6 -6
- package/package.json +25 -4
- package/src/core.ts +138 -0
- package/src/id-recognition/data-extractor.ts +97 -0
- package/src/id-recognition/id-detector.ts +20 -2
- package/src/id-recognition/ocr-processor.ts +3 -6
- package/src/index-umd.ts +240 -0
- package/src/index.ts +125 -139
- package/src/ocr-module.ts +139 -0
- package/src/qr-module.ts +129 -0
- package/src/utils/camera.ts +61 -36
- package/src/utils/types.ts +23 -6
package/src/index-umd.ts
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ID扫描识别库UMD格式入口文件
|
|
3
|
+
* @description 专门为UMD格式构建的入口,使用静态导入而非动态导入
|
|
4
|
+
* @module IDScannerLib
|
|
5
|
+
* @version 1.1.0
|
|
6
|
+
* @license MIT
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Camera, CameraOptions } from './utils/camera';
|
|
10
|
+
import { IDCardInfo, DetectionResult } from './utils/types';
|
|
11
|
+
import type { QRScannerOptions } from './scanner/qr-scanner';
|
|
12
|
+
import type { BarcodeScannerOptions } from './scanner/barcode-scanner';
|
|
13
|
+
|
|
14
|
+
// 静态导入所有依赖
|
|
15
|
+
import { QRScanner } from './scanner/qr-scanner';
|
|
16
|
+
import { BarcodeScanner } from './scanner/barcode-scanner';
|
|
17
|
+
import { IDCardDetector, IDCardDetectorOptions } from './id-recognition/id-detector';
|
|
18
|
+
import { OCRProcessor } from './id-recognition/ocr-processor';
|
|
19
|
+
import { DataExtractor } from './id-recognition/data-extractor';
|
|
20
|
+
import { ImageProcessor } from './utils/image-processing';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* IDScanner配置选项接口
|
|
24
|
+
*/
|
|
25
|
+
export interface IDScannerOptions {
|
|
26
|
+
cameraOptions?: CameraOptions;
|
|
27
|
+
qrScannerOptions?: QRScannerOptions;
|
|
28
|
+
barcodeScannerOptions?: BarcodeScannerOptions;
|
|
29
|
+
onQRCodeScanned?: (result: string) => void;
|
|
30
|
+
onBarcodeScanned?: (result: string) => void;
|
|
31
|
+
onIDCardScanned?: (info: IDCardInfo) => void;
|
|
32
|
+
onError?: (error: Error) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* IDScanner 主类
|
|
37
|
+
* UMD版本使用静态导入实现
|
|
38
|
+
*/
|
|
39
|
+
export class IDScanner {
|
|
40
|
+
private camera: Camera;
|
|
41
|
+
private qrScanner: QRScanner | null = null;
|
|
42
|
+
private barcodeScanner: BarcodeScanner | null = null;
|
|
43
|
+
private idDetector: IDCardDetector | null = null;
|
|
44
|
+
private ocrProcessor: OCRProcessor | null = null;
|
|
45
|
+
private dataExtractor: DataExtractor | null = null;
|
|
46
|
+
private scanMode: 'qr' | 'barcode' | 'idcard' = 'qr';
|
|
47
|
+
private videoElement: HTMLVideoElement | null = null;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 构造函数
|
|
51
|
+
* @param options 配置选项
|
|
52
|
+
*/
|
|
53
|
+
constructor(private options: IDScannerOptions = {}) {
|
|
54
|
+
this.camera = new Camera(options.cameraOptions);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 初始化模块
|
|
59
|
+
* 根据需要初始化OCR引擎
|
|
60
|
+
*/
|
|
61
|
+
async initialize(): Promise<void> {
|
|
62
|
+
try {
|
|
63
|
+
// 初始化OCR模块
|
|
64
|
+
this.ocrProcessor = new OCRProcessor();
|
|
65
|
+
this.dataExtractor = new DataExtractor();
|
|
66
|
+
await this.ocrProcessor.initialize();
|
|
67
|
+
|
|
68
|
+
console.log('IDScanner initialized');
|
|
69
|
+
} catch (error) {
|
|
70
|
+
this.handleError(error as Error);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 启动二维码扫描
|
|
77
|
+
* @param videoElement HTML视频元素
|
|
78
|
+
*/
|
|
79
|
+
async startQRScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
80
|
+
this.stop();
|
|
81
|
+
this.videoElement = videoElement;
|
|
82
|
+
this.scanMode = 'qr';
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
if (!this.qrScanner) {
|
|
86
|
+
this.qrScanner = new QRScanner({
|
|
87
|
+
...this.options.qrScannerOptions,
|
|
88
|
+
onScan: this.handleQRScan.bind(this)
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
await this.camera.start(videoElement);
|
|
93
|
+
this.qrScanner.start(videoElement);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
this.handleError(error as Error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 启动条形码扫描
|
|
101
|
+
* @param videoElement HTML视频元素
|
|
102
|
+
*/
|
|
103
|
+
async startBarcodeScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
104
|
+
this.stop();
|
|
105
|
+
this.videoElement = videoElement;
|
|
106
|
+
this.scanMode = 'barcode';
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
if (!this.barcodeScanner) {
|
|
110
|
+
this.barcodeScanner = new BarcodeScanner({
|
|
111
|
+
...this.options.barcodeScannerOptions,
|
|
112
|
+
onScan: this.handleBarcodeScan.bind(this)
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await this.camera.start(videoElement);
|
|
117
|
+
this.barcodeScanner.start(videoElement);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
this.handleError(error as Error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 启动身份证扫描
|
|
125
|
+
* @param videoElement HTML视频元素
|
|
126
|
+
*/
|
|
127
|
+
async startIDCardScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
128
|
+
this.stop();
|
|
129
|
+
this.videoElement = videoElement;
|
|
130
|
+
this.scanMode = 'idcard';
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
if (!this.ocrProcessor) {
|
|
134
|
+
await this.initialize();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!this.idDetector) {
|
|
138
|
+
this.idDetector = new IDCardDetector({
|
|
139
|
+
onDetection: this.handleIDDetection.bind(this),
|
|
140
|
+
onError: this.handleError.bind(this)
|
|
141
|
+
} as IDCardDetectorOptions);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
await this.camera.start(videoElement);
|
|
145
|
+
this.idDetector.start(videoElement);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
this.handleError(error as Error);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 停止扫描
|
|
153
|
+
*/
|
|
154
|
+
stop(): void {
|
|
155
|
+
if (this.scanMode === 'qr' && this.qrScanner) {
|
|
156
|
+
this.qrScanner.stop();
|
|
157
|
+
} else if (this.scanMode === 'barcode' && this.barcodeScanner) {
|
|
158
|
+
this.barcodeScanner.stop();
|
|
159
|
+
} else if (this.scanMode === 'idcard' && this.idDetector) {
|
|
160
|
+
this.idDetector.stop();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
this.camera.stop();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 处理二维码扫描结果
|
|
168
|
+
*/
|
|
169
|
+
private handleQRScan(result: string): void {
|
|
170
|
+
if (this.options.onQRCodeScanned) {
|
|
171
|
+
this.options.onQRCodeScanned(result);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* 处理条形码扫描结果
|
|
177
|
+
*/
|
|
178
|
+
private handleBarcodeScan(result: string): void {
|
|
179
|
+
if (this.options.onBarcodeScanned) {
|
|
180
|
+
this.options.onBarcodeScanned(result);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 处理身份证检测结果
|
|
186
|
+
*/
|
|
187
|
+
private async handleIDDetection(result: DetectionResult): Promise<void> {
|
|
188
|
+
if (!this.ocrProcessor || !this.dataExtractor) return;
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
// 检查 imageData 是否存在
|
|
192
|
+
if (!result.imageData) {
|
|
193
|
+
this.handleError(new Error('无效的图像数据'));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const idCardInfo = await this.ocrProcessor.processIDCard(result.imageData);
|
|
198
|
+
const extractedInfo = this.dataExtractor.extractAndValidate(idCardInfo);
|
|
199
|
+
|
|
200
|
+
if (this.options.onIDCardScanned) {
|
|
201
|
+
this.options.onIDCardScanned(extractedInfo);
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
this.handleError(error as Error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 处理错误
|
|
210
|
+
*/
|
|
211
|
+
private handleError(error: Error): void {
|
|
212
|
+
if (this.options.onError) {
|
|
213
|
+
this.options.onError(error);
|
|
214
|
+
} else {
|
|
215
|
+
console.error('IDScanner error:', error);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 释放资源
|
|
221
|
+
*/
|
|
222
|
+
async terminate(): Promise<void> {
|
|
223
|
+
this.stop();
|
|
224
|
+
|
|
225
|
+
if (this.ocrProcessor) {
|
|
226
|
+
await this.ocrProcessor.terminate();
|
|
227
|
+
this.ocrProcessor = null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
this.qrScanner = null;
|
|
231
|
+
this.barcodeScanner = null;
|
|
232
|
+
this.idDetector = null;
|
|
233
|
+
this.dataExtractor = null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 导出核心类型
|
|
238
|
+
export { IDCardInfo } from './utils/types';
|
|
239
|
+
export { CameraOptions } from './utils/camera';
|
|
240
|
+
export { QRScanner, BarcodeScanner, IDCardDetector, OCRProcessor, DataExtractor, ImageProcessor };
|
package/src/index.ts
CHANGED
|
@@ -6,25 +6,15 @@
|
|
|
6
6
|
* @license MIT
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { QRScanner, QRScannerOptions } from './scanner/qr-scanner';
|
|
10
|
-
import { BarcodeScanner, BarcodeScannerOptions } from './scanner/barcode-scanner';
|
|
11
|
-
import { IDCardDetector } from './id-recognition/id-detector';
|
|
12
|
-
import { OCRProcessor } from './id-recognition/ocr-processor';
|
|
13
|
-
import { DataExtractor } from './id-recognition/data-extractor';
|
|
14
9
|
import { Camera, CameraOptions } from './utils/camera';
|
|
15
|
-
import { ImageProcessor } from './utils/image-processing';
|
|
16
10
|
import { IDCardInfo, DetectionResult } from './utils/types';
|
|
17
11
|
|
|
12
|
+
// 先只导入类型定义,不导入实际实现
|
|
13
|
+
import type { QRScannerOptions } from './scanner/qr-scanner';
|
|
14
|
+
import type { BarcodeScannerOptions } from './scanner/barcode-scanner';
|
|
15
|
+
|
|
18
16
|
/**
|
|
19
17
|
* IDScanner配置选项接口
|
|
20
|
-
* @interface IDScannerOptions
|
|
21
|
-
* @property {CameraOptions} [cameraOptions] - 相机配置选项
|
|
22
|
-
* @property {QRScannerOptions} [qrScannerOptions] - 二维码扫描配置选项
|
|
23
|
-
* @property {BarcodeScannerOptions} [barcodeScannerOptions] - 条形码扫描配置选项
|
|
24
|
-
* @property {Function} [onQRCodeScanned] - 二维码识别成功回调
|
|
25
|
-
* @property {Function} [onBarcodeScanned] - 条形码识别成功回调
|
|
26
|
-
* @property {Function} [onIDCardScanned] - 身份证识别成功回调
|
|
27
|
-
* @property {Function} [onError] - 错误处理回调
|
|
28
18
|
*/
|
|
29
19
|
export interface IDScannerOptions {
|
|
30
20
|
cameraOptions?: CameraOptions;
|
|
@@ -40,189 +30,185 @@ export interface IDScannerOptions {
|
|
|
40
30
|
* IDScanner 主类
|
|
41
31
|
*
|
|
42
32
|
* 整合二维码、条形码扫描和身份证识别功能,提供统一的接口
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```typescript
|
|
46
|
-
* // 创建扫描器实例
|
|
47
|
-
* const scanner = new IDScanner({
|
|
48
|
-
* onQRCodeScanned: (result) => {
|
|
49
|
-
* console.log('扫描到二维码:', result);
|
|
50
|
-
* },
|
|
51
|
-
* onIDCardScanned: (info) => {
|
|
52
|
-
* console.log('识别到身份证信息:', info);
|
|
53
|
-
* }
|
|
54
|
-
* });
|
|
55
|
-
*
|
|
56
|
-
* // 初始化OCR引擎和相关资源
|
|
57
|
-
* await scanner.initialize();
|
|
58
|
-
*
|
|
59
|
-
* // 启动二维码扫描
|
|
60
|
-
* const videoElement = document.getElementById('video');
|
|
61
|
-
* await scanner.startQRScanner(videoElement);
|
|
62
|
-
*
|
|
63
|
-
* // 停止扫描
|
|
64
|
-
* scanner.stop();
|
|
65
|
-
*
|
|
66
|
-
* // 使用结束后释放资源
|
|
67
|
-
* scanner.terminate();
|
|
68
|
-
* ```
|
|
33
|
+
* 使用动态导入实现按需加载
|
|
69
34
|
*/
|
|
70
35
|
export class IDScanner {
|
|
71
|
-
private
|
|
72
|
-
private barcodeScanner: BarcodeScanner;
|
|
73
|
-
private idDetector: IDCardDetector;
|
|
74
|
-
private ocrProcessor: OCRProcessor;
|
|
36
|
+
private camera: Camera;
|
|
75
37
|
private scanMode: 'qr' | 'barcode' | 'idcard' = 'qr';
|
|
38
|
+
private videoElement: HTMLVideoElement | null = null;
|
|
39
|
+
|
|
40
|
+
// 延迟加载的模块
|
|
41
|
+
private qrModule: any = null;
|
|
42
|
+
private ocrModule: any = null;
|
|
43
|
+
|
|
44
|
+
// 模块加载状态
|
|
45
|
+
private isQRModuleLoaded: boolean = false;
|
|
46
|
+
private isOCRModuleLoaded: boolean = false;
|
|
76
47
|
|
|
77
48
|
/**
|
|
78
|
-
*
|
|
79
|
-
* @param
|
|
49
|
+
* 构造函数
|
|
50
|
+
* @param options 配置选项
|
|
80
51
|
*/
|
|
81
52
|
constructor(private options: IDScannerOptions = {}) {
|
|
82
|
-
this.
|
|
83
|
-
...options.qrScannerOptions,
|
|
84
|
-
onScan: this.handleQRScan.bind(this),
|
|
85
|
-
onError: this.handleError.bind(this)
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
this.barcodeScanner = new BarcodeScanner({
|
|
89
|
-
...options.barcodeScannerOptions,
|
|
90
|
-
onScan: this.handleBarcodeScan.bind(this),
|
|
91
|
-
onError: this.handleError.bind(this)
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
this.idDetector = new IDCardDetector(this.handleIDDetection.bind(this));
|
|
95
|
-
this.ocrProcessor = new OCRProcessor();
|
|
53
|
+
this.camera = new Camera(options.cameraOptions);
|
|
96
54
|
}
|
|
97
55
|
|
|
98
56
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* @returns {Promise<void>} 初始化完成的Promise
|
|
102
|
-
* @throws 如果初始化失败,将抛出错误
|
|
57
|
+
* 初始化模块
|
|
58
|
+
* 根据需要初始化OCR引擎
|
|
103
59
|
*/
|
|
104
60
|
async initialize(): Promise<void> {
|
|
105
61
|
try {
|
|
106
|
-
|
|
62
|
+
// 预加载OCR模块但不初始化
|
|
63
|
+
if (!this.isOCRModuleLoaded) {
|
|
64
|
+
// 动态导入OCR模块
|
|
65
|
+
const OCRModule = await import('./ocr-module').then(m => m.OCRModule);
|
|
66
|
+
this.ocrModule = new OCRModule({
|
|
67
|
+
cameraOptions: this.options.cameraOptions,
|
|
68
|
+
onIDCardScanned: this.options.onIDCardScanned,
|
|
69
|
+
onError: this.options.onError
|
|
70
|
+
});
|
|
71
|
+
this.isOCRModuleLoaded = true;
|
|
72
|
+
|
|
73
|
+
// 初始化OCR模块
|
|
74
|
+
await this.ocrModule.initialize();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log('IDScanner initialized');
|
|
107
78
|
} catch (error) {
|
|
108
|
-
this.handleError(error
|
|
79
|
+
this.handleError(error as Error);
|
|
80
|
+
throw error;
|
|
109
81
|
}
|
|
110
82
|
}
|
|
111
83
|
|
|
112
84
|
/**
|
|
113
85
|
* 启动二维码扫描
|
|
114
|
-
*
|
|
115
|
-
* @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
|
|
116
|
-
* @returns {Promise<void>} 启动完成的Promise
|
|
86
|
+
* @param videoElement HTML视频元素
|
|
117
87
|
*/
|
|
118
88
|
async startQRScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
89
|
+
this.stop();
|
|
90
|
+
this.videoElement = videoElement;
|
|
119
91
|
this.scanMode = 'qr';
|
|
120
|
-
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
// 动态加载二维码模块
|
|
95
|
+
if (!this.isQRModuleLoaded) {
|
|
96
|
+
const ScannerModule = await import('./qr-module').then(m => m.ScannerModule);
|
|
97
|
+
this.qrModule = new ScannerModule({
|
|
98
|
+
cameraOptions: this.options.cameraOptions,
|
|
99
|
+
qrScannerOptions: this.options.qrScannerOptions,
|
|
100
|
+
barcodeScannerOptions: this.options.barcodeScannerOptions,
|
|
101
|
+
onQRCodeScanned: this.options.onQRCodeScanned,
|
|
102
|
+
onBarcodeScanned: this.options.onBarcodeScanned,
|
|
103
|
+
onError: this.options.onError
|
|
104
|
+
});
|
|
105
|
+
this.isQRModuleLoaded = true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await this.qrModule.startQRScanner(videoElement);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
this.handleError(error as Error);
|
|
111
|
+
}
|
|
121
112
|
}
|
|
122
113
|
|
|
123
114
|
/**
|
|
124
115
|
* 启动条形码扫描
|
|
125
|
-
*
|
|
126
|
-
* @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
|
|
127
|
-
* @returns {Promise<void>} 启动完成的Promise
|
|
116
|
+
* @param videoElement HTML视频元素
|
|
128
117
|
*/
|
|
129
118
|
async startBarcodeScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
119
|
+
this.stop();
|
|
120
|
+
this.videoElement = videoElement;
|
|
130
121
|
this.scanMode = 'barcode';
|
|
131
|
-
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
// 动态加载二维码模块
|
|
125
|
+
if (!this.isQRModuleLoaded) {
|
|
126
|
+
const ScannerModule = await import('./qr-module').then(m => m.ScannerModule);
|
|
127
|
+
this.qrModule = new ScannerModule({
|
|
128
|
+
cameraOptions: this.options.cameraOptions,
|
|
129
|
+
qrScannerOptions: this.options.qrScannerOptions,
|
|
130
|
+
barcodeScannerOptions: this.options.barcodeScannerOptions,
|
|
131
|
+
onQRCodeScanned: this.options.onQRCodeScanned,
|
|
132
|
+
onBarcodeScanned: this.options.onBarcodeScanned,
|
|
133
|
+
onError: this.options.onError
|
|
134
|
+
});
|
|
135
|
+
this.isQRModuleLoaded = true;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
await this.qrModule.startBarcodeScanner(videoElement);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
this.handleError(error as Error);
|
|
141
|
+
}
|
|
132
142
|
}
|
|
133
143
|
|
|
134
144
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
* @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
|
|
138
|
-
* @returns {Promise<void>} 启动完成的Promise
|
|
145
|
+
* 启动身份证扫描
|
|
146
|
+
* @param videoElement HTML视频元素
|
|
139
147
|
*/
|
|
140
148
|
async startIDCardScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
149
|
+
this.stop();
|
|
150
|
+
this.videoElement = videoElement;
|
|
141
151
|
this.scanMode = 'idcard';
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
this.barcodeScanner.stop();
|
|
153
|
-
} else {
|
|
154
|
-
this.idDetector.stop();
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* 处理二维码扫描结果
|
|
160
|
-
* @private
|
|
161
|
-
* @param {string} result - 扫描到的二维码内容
|
|
162
|
-
*/
|
|
163
|
-
private handleQRScan(result: string): void {
|
|
164
|
-
if (this.options.onQRCodeScanned) {
|
|
165
|
-
this.options.onQRCodeScanned(result);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* 处理条形码扫描结果
|
|
171
|
-
* @private
|
|
172
|
-
* @param {string} result - 扫描到的条形码内容
|
|
173
|
-
*/
|
|
174
|
-
private handleBarcodeScan(result: string): void {
|
|
175
|
-
if (this.options.onBarcodeScanned) {
|
|
176
|
-
this.options.onBarcodeScanned(result);
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
// 检查OCR模块是否已加载,若未加载则自动初始化
|
|
155
|
+
if (!this.isOCRModuleLoaded) {
|
|
156
|
+
await this.initialize();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await this.ocrModule.startIDCardScanner(videoElement);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
this.handleError(error as Error);
|
|
177
162
|
}
|
|
178
163
|
}
|
|
179
164
|
|
|
180
165
|
/**
|
|
181
|
-
*
|
|
182
|
-
* @private
|
|
183
|
-
* @param {DetectionResult} result - 身份证检测结果
|
|
166
|
+
* 停止扫描
|
|
184
167
|
*/
|
|
185
|
-
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (this.options.onIDCardScanned) {
|
|
194
|
-
this.options.onIDCardScanned(enhancedInfo);
|
|
195
|
-
}
|
|
196
|
-
} catch (error) {
|
|
197
|
-
this.handleError(error instanceof Error ? error : new Error(String(error)));
|
|
168
|
+
stop(): void {
|
|
169
|
+
if (this.scanMode === 'qr' || this.scanMode === 'barcode') {
|
|
170
|
+
if (this.qrModule) {
|
|
171
|
+
this.qrModule.stop();
|
|
172
|
+
}
|
|
173
|
+
} else if (this.scanMode === 'idcard') {
|
|
174
|
+
if (this.ocrModule) {
|
|
175
|
+
this.ocrModule.stop();
|
|
198
176
|
}
|
|
199
177
|
}
|
|
200
178
|
}
|
|
201
179
|
|
|
202
180
|
/**
|
|
203
181
|
* 处理错误
|
|
204
|
-
* @private
|
|
205
|
-
* @param {Error} error - 错误对象
|
|
206
182
|
*/
|
|
207
183
|
private handleError(error: Error): void {
|
|
208
184
|
if (this.options.onError) {
|
|
209
185
|
this.options.onError(error);
|
|
210
186
|
} else {
|
|
211
|
-
console.error('
|
|
187
|
+
console.error('IDScanner error:', error);
|
|
212
188
|
}
|
|
213
189
|
}
|
|
214
190
|
|
|
215
191
|
/**
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* @returns {Promise<void>} 资源释放完成的Promise
|
|
192
|
+
* 释放资源
|
|
219
193
|
*/
|
|
220
194
|
async terminate(): Promise<void> {
|
|
221
195
|
this.stop();
|
|
222
|
-
|
|
196
|
+
|
|
197
|
+
// 释放OCR资源
|
|
198
|
+
if (this.isOCRModuleLoaded && this.ocrModule) {
|
|
199
|
+
await this.ocrModule.terminate();
|
|
200
|
+
this.ocrModule = null;
|
|
201
|
+
this.isOCRModuleLoaded = false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 释放QR扫描资源
|
|
205
|
+
if (this.isQRModuleLoaded && this.qrModule) {
|
|
206
|
+
this.qrModule = null;
|
|
207
|
+
this.isQRModuleLoaded = false;
|
|
208
|
+
}
|
|
223
209
|
}
|
|
224
210
|
}
|
|
225
211
|
|
|
226
|
-
//
|
|
227
|
-
export {
|
|
228
|
-
export
|
|
212
|
+
// 导出核心类型
|
|
213
|
+
export { IDCardInfo } from './utils/types';
|
|
214
|
+
export { CameraOptions } from './utils/camera';
|