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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 类型定义文件
|
|
3
|
+
* @description 定义全局类型
|
|
4
|
+
* @module Types
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 身份证检测结果接口
|
|
8
|
+
*
|
|
9
|
+
* 包含身份证检测的结果信息,如是否成功检测到身份证、身份证的四个角点坐标以及裁剪后的身份证图像
|
|
10
|
+
*
|
|
11
|
+
* @interface DetectionResult
|
|
12
|
+
* @property {boolean} success - 是否成功检测到身份证
|
|
13
|
+
* @property {Object[]} [corners] - 检测到的身份证四个角点坐标
|
|
14
|
+
* @property {number} corners[].x - 角点X坐标
|
|
15
|
+
* @property {number} corners[].y - 角点Y坐标
|
|
16
|
+
* @property {ImageData} [croppedImage] - 裁剪后的身份证图像
|
|
17
|
+
*/
|
|
18
|
+
export interface DetectionResult {
|
|
19
|
+
success: boolean;
|
|
20
|
+
corners?: {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
}[];
|
|
24
|
+
croppedImage?: ImageData;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 身份证信息接口
|
|
28
|
+
*
|
|
29
|
+
* 包含从身份证中提取的各项个人信息
|
|
30
|
+
*
|
|
31
|
+
* @interface IDCardInfo
|
|
32
|
+
* @property {string} [name] - 姓名
|
|
33
|
+
* @property {string} [gender] - 性别
|
|
34
|
+
* @property {string} [nationality] - 民族
|
|
35
|
+
* @property {string} [birthDate] - 出生日期
|
|
36
|
+
* @property {string} [address] - 地址
|
|
37
|
+
* @property {string} [idNumber] - 身份证号码
|
|
38
|
+
* @property {string} [issuingAuthority] - 签发机关
|
|
39
|
+
* @property {string} [validPeriod] - 有效期限
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // 身份证信息示例
|
|
44
|
+
* const idInfo: IDCardInfo = {
|
|
45
|
+
* name: '张三',
|
|
46
|
+
* gender: '男',
|
|
47
|
+
* nationality: '汉族',
|
|
48
|
+
* birthDate: '1990-01-01',
|
|
49
|
+
* address: '北京市海淀区xxxxx',
|
|
50
|
+
* idNumber: '110101199001011234',
|
|
51
|
+
* issuingAuthority: '北京市公安局海淀分局',
|
|
52
|
+
* validPeriod: '2020.01.01-2040.01.01'
|
|
53
|
+
* };
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export interface IDCardInfo {
|
|
57
|
+
name?: string;
|
|
58
|
+
gender?: string;
|
|
59
|
+
nationality?: string;
|
|
60
|
+
birthDate?: string;
|
|
61
|
+
address?: string;
|
|
62
|
+
idNumber?: string;
|
|
63
|
+
issuingAuthority?: string;
|
|
64
|
+
validPeriod?: string;
|
|
65
|
+
}
|
package/dist/utils/camera.d.ts
CHANGED
|
@@ -32,13 +32,13 @@ export interface CameraOptions {
|
|
|
32
32
|
*
|
|
33
33
|
* // 初始化相机
|
|
34
34
|
* const videoElement = document.getElementById('video') as HTMLVideoElement;
|
|
35
|
-
* await camera.
|
|
35
|
+
* await camera.start(videoElement);
|
|
36
36
|
*
|
|
37
37
|
* // 捕获当前视频帧
|
|
38
38
|
* const imageData = camera.captureFrame();
|
|
39
39
|
*
|
|
40
40
|
* // 使用结束后释放资源
|
|
41
|
-
* camera.
|
|
41
|
+
* camera.stop();
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
export declare class Camera {
|
|
@@ -47,30 +47,35 @@ export declare class Camera {
|
|
|
47
47
|
private videoElement;
|
|
48
48
|
/**
|
|
49
49
|
* 创建相机实例
|
|
50
|
-
*
|
|
51
50
|
* @param {CameraOptions} [options] - 相机配置选项
|
|
52
51
|
*/
|
|
53
52
|
constructor(options?: CameraOptions);
|
|
54
53
|
/**
|
|
55
|
-
*
|
|
54
|
+
* 启动摄像头并将视频流绑定到视频元素
|
|
55
|
+
* @param videoElement HTML视频元素
|
|
56
|
+
* @returns Promise<void>
|
|
57
|
+
*/
|
|
58
|
+
start(videoElement: HTMLVideoElement): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* 停止摄像头并释放资源
|
|
61
|
+
*/
|
|
62
|
+
stop(): void;
|
|
63
|
+
/**
|
|
64
|
+
* 初始化相机,获取视频流并绑定到视频元素
|
|
56
65
|
*
|
|
57
|
-
* @param {HTMLVideoElement} videoElement -
|
|
66
|
+
* @param {HTMLVideoElement} videoElement - 用于显示视频流的视频元素
|
|
58
67
|
* @returns {Promise<void>} 初始化完成的Promise
|
|
59
|
-
* @throws
|
|
68
|
+
* @throws 如果无法访问摄像头,将抛出错误
|
|
60
69
|
*/
|
|
61
70
|
initialize(videoElement: HTMLVideoElement): Promise<void>;
|
|
62
71
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* 捕获当前视频画面并转换为ImageData对象,可用于图像处理和分析
|
|
72
|
+
* 捕获当前视频帧
|
|
66
73
|
*
|
|
67
|
-
* @returns {ImageData|null}
|
|
74
|
+
* @returns {ImageData|null} 视频帧的ImageData对象,如果未初始化则返回null
|
|
68
75
|
*/
|
|
69
76
|
captureFrame(): ImageData | null;
|
|
70
77
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* 停止所有视频流轨道并清理资源。在不再需要相机时应调用此方法。
|
|
78
|
+
* 释放摄像头资源
|
|
74
79
|
*/
|
|
75
80
|
release(): void;
|
|
76
81
|
}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file 类型定义文件
|
|
3
|
-
* @description
|
|
3
|
+
* @description 定义全局类型
|
|
4
4
|
* @module Types
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
@@ -30,11 +30,11 @@ export interface DetectionResult {
|
|
|
30
30
|
*
|
|
31
31
|
* @interface IDCardInfo
|
|
32
32
|
* @property {string} [name] - 姓名
|
|
33
|
-
* @property {string} [gender] -
|
|
34
|
-
* @property {string} [nationality] -
|
|
35
|
-
* @property {string} [birthDate] -
|
|
36
|
-
* @property {string} [address] -
|
|
37
|
-
* @property {string} [idNumber] -
|
|
33
|
+
* @property {string} [gender] - 性别
|
|
34
|
+
* @property {string} [nationality] - 民族
|
|
35
|
+
* @property {string} [birthDate] - 出生日期
|
|
36
|
+
* @property {string} [address] - 地址
|
|
37
|
+
* @property {string} [idNumber] - 身份证号码
|
|
38
38
|
* @property {string} [issuingAuthority] - 签发机关
|
|
39
39
|
* @property {string} [validPeriod] - 有效期限
|
|
40
40
|
*
|
package/package.json
CHANGED
|
@@ -1,15 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "id-scanner-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/id-scanner.js",
|
|
6
|
-
"module": "dist/id-scanner.esm.js",
|
|
7
|
-
"
|
|
6
|
+
"module": "dist/id-scanner-core.esm.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/id-scanner-core.esm.js",
|
|
10
|
+
"require": "./dist/id-scanner.js"
|
|
11
|
+
},
|
|
12
|
+
"./core": {
|
|
13
|
+
"import": "./dist/id-scanner-core.esm.js",
|
|
14
|
+
"require": "./dist/id-scanner-core.js"
|
|
15
|
+
},
|
|
16
|
+
"./ocr": {
|
|
17
|
+
"import": "./dist/id-scanner-ocr.esm.js",
|
|
18
|
+
"require": "./dist/id-scanner-ocr.js"
|
|
19
|
+
},
|
|
20
|
+
"./qr": {
|
|
21
|
+
"import": "./dist/id-scanner-qr.esm.js",
|
|
22
|
+
"require": "./dist/id-scanner-qr.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"types": "dist/types/index.d.ts",
|
|
26
|
+
"sideEffects": false,
|
|
8
27
|
"scripts": {
|
|
9
28
|
"build": "rollup -c",
|
|
10
29
|
"dev": "rollup -c -w",
|
|
11
30
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
-
"prepublishOnly": "npm run build"
|
|
31
|
+
"prepublishOnly": "npm run build",
|
|
32
|
+
"publish:npm": "node scripts/publish.js",
|
|
33
|
+
"update:github": "node scripts/update-github.js"
|
|
13
34
|
},
|
|
14
35
|
"keywords": [
|
|
15
36
|
"id-card",
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 轻量级扫描库核心
|
|
3
|
+
* @description 不包含OCR功能的轻量版,只提供二维码和条形码扫描功能
|
|
4
|
+
* @module IDScannerCore
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
* @license MIT
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { QRScanner, QRScannerOptions } from './scanner/qr-scanner';
|
|
10
|
+
import { BarcodeScanner, BarcodeScannerOptions } from './scanner/barcode-scanner';
|
|
11
|
+
import { Camera, CameraOptions } from './utils/camera';
|
|
12
|
+
import { ImageProcessor } from './utils/image-processing';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* IDScannerCore配置选项
|
|
16
|
+
*/
|
|
17
|
+
export interface IDScannerCoreOptions {
|
|
18
|
+
cameraOptions?: CameraOptions;
|
|
19
|
+
qrScannerOptions?: QRScannerOptions;
|
|
20
|
+
barcodeScannerOptions?: BarcodeScannerOptions;
|
|
21
|
+
onQRCodeScanned?: (result: string) => void;
|
|
22
|
+
onBarcodeScanned?: (result: string) => void;
|
|
23
|
+
onError?: (error: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* IDScannerCore 轻量级扫描类
|
|
28
|
+
*
|
|
29
|
+
* 提供二维码和条形码扫描功能,不包含OCR身份证识别功能
|
|
30
|
+
*/
|
|
31
|
+
export class IDScannerCore {
|
|
32
|
+
private qrScanner: QRScanner;
|
|
33
|
+
private barcodeScanner: BarcodeScanner;
|
|
34
|
+
private camera: Camera;
|
|
35
|
+
private scanMode: 'qr' | 'barcode' = 'qr';
|
|
36
|
+
private videoElement: HTMLVideoElement | null = null;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 构造函数
|
|
40
|
+
* @param options 配置选项
|
|
41
|
+
*/
|
|
42
|
+
constructor(private options: IDScannerCoreOptions = {}) {
|
|
43
|
+
this.camera = new Camera(options.cameraOptions);
|
|
44
|
+
this.qrScanner = new QRScanner({
|
|
45
|
+
...options.qrScannerOptions,
|
|
46
|
+
onScan: this.handleQRScan.bind(this)
|
|
47
|
+
});
|
|
48
|
+
this.barcodeScanner = new BarcodeScanner({
|
|
49
|
+
...options.barcodeScannerOptions,
|
|
50
|
+
onScan: this.handleBarcodeScan.bind(this)
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 初始化扫描器
|
|
56
|
+
*/
|
|
57
|
+
async initialize(): Promise<void> {
|
|
58
|
+
// 轻量版无需初始化OCR引擎
|
|
59
|
+
console.log('IDScannerCore initialized');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 启动二维码扫描
|
|
64
|
+
* @param videoElement HTML视频元素
|
|
65
|
+
*/
|
|
66
|
+
async startQRScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
67
|
+
this.videoElement = videoElement;
|
|
68
|
+
this.scanMode = 'qr';
|
|
69
|
+
await this.camera.start(videoElement);
|
|
70
|
+
this.qrScanner.start(videoElement);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 启动条形码扫描
|
|
75
|
+
* @param videoElement HTML视频元素
|
|
76
|
+
*/
|
|
77
|
+
async startBarcodeScanner(videoElement: HTMLVideoElement): Promise<void> {
|
|
78
|
+
this.videoElement = videoElement;
|
|
79
|
+
this.scanMode = 'barcode';
|
|
80
|
+
await this.camera.start(videoElement);
|
|
81
|
+
this.barcodeScanner.start(videoElement);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 停止扫描
|
|
86
|
+
*/
|
|
87
|
+
stop(): void {
|
|
88
|
+
if (this.scanMode === 'qr') {
|
|
89
|
+
this.qrScanner.stop();
|
|
90
|
+
} else if (this.scanMode === 'barcode') {
|
|
91
|
+
this.barcodeScanner.stop();
|
|
92
|
+
}
|
|
93
|
+
this.camera.stop();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 处理二维码扫描结果
|
|
98
|
+
*/
|
|
99
|
+
private handleQRScan(result: string): void {
|
|
100
|
+
if (this.options.onQRCodeScanned) {
|
|
101
|
+
this.options.onQRCodeScanned(result);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 处理条形码扫描结果
|
|
107
|
+
*/
|
|
108
|
+
private handleBarcodeScan(result: string): void {
|
|
109
|
+
if (this.options.onBarcodeScanned) {
|
|
110
|
+
this.options.onBarcodeScanned(result);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 处理错误
|
|
116
|
+
*/
|
|
117
|
+
private handleError(error: Error): void {
|
|
118
|
+
if (this.options.onError) {
|
|
119
|
+
this.options.onError(error);
|
|
120
|
+
} else {
|
|
121
|
+
console.error('IDScannerCore error:', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 释放资源
|
|
127
|
+
*/
|
|
128
|
+
async terminate(): Promise<void> {
|
|
129
|
+
this.stop();
|
|
130
|
+
// 轻量版无需释放OCR资源
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 导出相关类型和工具
|
|
135
|
+
export { QRScanner, QRScannerOptions } from './scanner/qr-scanner';
|
|
136
|
+
export { BarcodeScanner, BarcodeScannerOptions } from './scanner/barcode-scanner';
|
|
137
|
+
export { Camera, CameraOptions } from './utils/camera';
|
|
138
|
+
export { ImageProcessor } from './utils/image-processing';
|
|
@@ -162,4 +162,101 @@ export class DataExtractor {
|
|
|
162
162
|
|
|
163
163
|
return result;
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 提取并验证身份证信息
|
|
168
|
+
*
|
|
169
|
+
* @param idCardInfo 初步提取的身份证信息
|
|
170
|
+
* @returns 验证和增强后的身份证信息
|
|
171
|
+
*/
|
|
172
|
+
extractAndValidate(idCardInfo: IDCardInfo): IDCardInfo {
|
|
173
|
+
const enhancedInfo = {...idCardInfo};
|
|
174
|
+
|
|
175
|
+
// 验证和规范化身份证号
|
|
176
|
+
if (enhancedInfo.idNumber) {
|
|
177
|
+
enhancedInfo.idNumber = this.normalizeIDNumber(enhancedInfo.idNumber);
|
|
178
|
+
|
|
179
|
+
// 如果身份证号有效,推断出生日期
|
|
180
|
+
if (this.validateIDNumber(enhancedInfo.idNumber)) {
|
|
181
|
+
if (!enhancedInfo.birthDate) {
|
|
182
|
+
enhancedInfo.birthDate = this.extractBirthDateFromID(enhancedInfo.idNumber);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 推断性别
|
|
186
|
+
if (!enhancedInfo.gender) {
|
|
187
|
+
enhancedInfo.gender = this.extractGenderFromID(enhancedInfo.idNumber);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 规范化日期格式
|
|
193
|
+
if (enhancedInfo.birthDate) {
|
|
194
|
+
enhancedInfo.birthDate = this.normalizeDate(enhancedInfo.birthDate);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 规范化地址信息
|
|
198
|
+
if (enhancedInfo.address) {
|
|
199
|
+
enhancedInfo.address = this.normalizeAddress(enhancedInfo.address);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return enhancedInfo;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 规范化身份证号码
|
|
207
|
+
*/
|
|
208
|
+
private normalizeIDNumber(idNumber: string): string {
|
|
209
|
+
// 移除空格和特殊字符
|
|
210
|
+
return idNumber.replace(/[\s\-]/g, '').toUpperCase();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 验证身份证号码是否有效
|
|
215
|
+
*/
|
|
216
|
+
private validateIDNumber(idNumber: string): boolean {
|
|
217
|
+
// 简单验证身份证号码长度和格式
|
|
218
|
+
const idRegex = /(^\d{15}$)|(^\d{17}([0-9]|X)$)/;
|
|
219
|
+
return idRegex.test(idNumber);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 从身份证号中提取出生日期
|
|
224
|
+
*/
|
|
225
|
+
private extractBirthDateFromID(idNumber: string): string {
|
|
226
|
+
if (idNumber.length === 18) {
|
|
227
|
+
return `${idNumber.substring(6, 10)}-${idNumber.substring(10, 12)}-${idNumber.substring(12, 14)}`;
|
|
228
|
+
} else if (idNumber.length === 15) {
|
|
229
|
+
return `19${idNumber.substring(6, 8)}-${idNumber.substring(8, 10)}-${idNumber.substring(10, 12)}`;
|
|
230
|
+
}
|
|
231
|
+
return '';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 从身份证号中提取性别信息
|
|
236
|
+
*/
|
|
237
|
+
private extractGenderFromID(idNumber: string): string {
|
|
238
|
+
let sexCode: number;
|
|
239
|
+
if (idNumber.length === 18) {
|
|
240
|
+
sexCode = parseInt(idNumber.charAt(16));
|
|
241
|
+
} else {
|
|
242
|
+
sexCode = parseInt(idNumber.charAt(14));
|
|
243
|
+
}
|
|
244
|
+
return sexCode % 2 === 1 ? '男' : '女';
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 规范化日期格式
|
|
249
|
+
*/
|
|
250
|
+
private normalizeDate(date: string): string {
|
|
251
|
+
// 简单的日期格式化逻辑
|
|
252
|
+
return date.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 规范化地址信息
|
|
257
|
+
*/
|
|
258
|
+
private normalizeAddress(address: string): string {
|
|
259
|
+
// 地址格式化逻辑
|
|
260
|
+
return address.trim();
|
|
261
|
+
}
|
|
165
262
|
}
|
|
@@ -8,6 +8,15 @@ import { Camera } from '../utils/camera';
|
|
|
8
8
|
import { ImageProcessor } from '../utils/image-processing';
|
|
9
9
|
import { DetectionResult } from '../utils/types';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* IDCardDetector配置选项
|
|
13
|
+
*/
|
|
14
|
+
export interface IDCardDetectorOptions {
|
|
15
|
+
onDetection?: (result: DetectionResult) => void;
|
|
16
|
+
onError?: (error: Error) => void;
|
|
17
|
+
detectionInterval?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
/**
|
|
12
21
|
* 身份证检测器类
|
|
13
22
|
*
|
|
@@ -37,14 +46,23 @@ export class IDCardDetector {
|
|
|
37
46
|
private camera: Camera;
|
|
38
47
|
private detecting = false;
|
|
39
48
|
private detectTimer: number | null = null;
|
|
49
|
+
private onDetected?: (result: DetectionResult) => void;
|
|
40
50
|
|
|
41
51
|
/**
|
|
42
52
|
* 创建身份证检测器实例
|
|
43
53
|
*
|
|
44
|
-
* @param
|
|
54
|
+
* @param options 身份证检测器配置选项,或者检测回调函数
|
|
45
55
|
*/
|
|
46
|
-
constructor(
|
|
56
|
+
constructor(options?: IDCardDetectorOptions | ((result: DetectionResult) => void)) {
|
|
47
57
|
this.camera = new Camera();
|
|
58
|
+
|
|
59
|
+
if (typeof options === 'function') {
|
|
60
|
+
// 兼容旧的构造函数方式
|
|
61
|
+
this.onDetected = options;
|
|
62
|
+
} else if (options) {
|
|
63
|
+
// 使用新的选项对象方式
|
|
64
|
+
this.onDetected = options.onDetection;
|
|
65
|
+
}
|
|
48
66
|
}
|
|
49
67
|
|
|
50
68
|
/**
|
|
@@ -56,11 +56,8 @@ export class OCRProcessor {
|
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* 处理身份证图像并提取信息
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* @param {ImageData} imageData - 身份证图像数据
|
|
63
|
-
* @returns {Promise<IDCardInfo>} 提取到的身份证信息
|
|
59
|
+
* @param imageData 要处理的身份证图像数据
|
|
60
|
+
* @returns 提取的身份证信息
|
|
64
61
|
*/
|
|
65
62
|
async processIDCard(imageData: ImageData): Promise<IDCardInfo> {
|
|
66
63
|
if (!this.worker) {
|
|
@@ -81,7 +78,7 @@ export class OCRProcessor {
|
|
|
81
78
|
return this.parseIDCardText(data.text);
|
|
82
79
|
} catch (error) {
|
|
83
80
|
console.error('OCR识别错误:', error);
|
|
84
|
-
return {}
|
|
81
|
+
return {} as IDCardInfo;
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
|