id-scanner-lib 1.6.2 → 1.6.4
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 +146 -49
- package/dist/id-scanner-lib.esm.js.map +1 -1
- package/dist/id-scanner-lib.js +146 -49
- package/dist/id-scanner-lib.js.map +1 -1
- package/package.json +1 -1
- package/src/core/config.ts +29 -11
- package/src/core/logger.ts +19 -2
- package/src/core/module-manager.ts +9 -0
- package/src/index.ts +1 -0
- package/src/modules/face/face-detector.ts +1 -0
- package/src/modules/face/index.ts +1 -0
- package/src/modules/face/liveness-detector.ts +1 -0
- package/src/modules/id-card/id-card-detector.ts +98 -35
- package/src/modules/id-card/index.ts +1 -0
- package/src/modules/qrcode/index.ts +1 -0
- package/src/utils/camera.ts +1 -0
- package/src/utils/resource-manager.ts +2 -2
- package/src/utils/worker.ts +4 -4
|
@@ -20,7 +20,30 @@ class ConfigManager {
|
|
|
20
20
|
this.config = {};
|
|
21
21
|
/** 配置变更回调 */
|
|
22
22
|
this.changeCallbacks = new Map();
|
|
23
|
+
/** 初始化状态 */
|
|
24
|
+
this.initialized = false;
|
|
23
25
|
// 设置默认配置
|
|
26
|
+
this._resetDefaults();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 获取单例实例
|
|
30
|
+
*/
|
|
31
|
+
static getInstance() {
|
|
32
|
+
if (!ConfigManager.instance) {
|
|
33
|
+
ConfigManager.instance = new ConfigManager();
|
|
34
|
+
}
|
|
35
|
+
return ConfigManager.instance;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 重置单例实例(主要用于测试)
|
|
39
|
+
*/
|
|
40
|
+
static resetInstance() {
|
|
41
|
+
ConfigManager.instance = undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 重置为默认配置
|
|
45
|
+
*/
|
|
46
|
+
_resetDefaults() {
|
|
24
47
|
this.config = {
|
|
25
48
|
debug: false,
|
|
26
49
|
logLevel: 'info',
|
|
@@ -36,15 +59,7 @@ class ConfigManager {
|
|
|
36
59
|
useCache: true
|
|
37
60
|
}
|
|
38
61
|
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 获取单例实例
|
|
42
|
-
*/
|
|
43
|
-
static getInstance() {
|
|
44
|
-
if (!ConfigManager.instance) {
|
|
45
|
-
ConfigManager.instance = new ConfigManager();
|
|
46
|
-
}
|
|
47
|
-
return ConfigManager.instance;
|
|
62
|
+
this.initialized = true;
|
|
48
63
|
}
|
|
49
64
|
/**
|
|
50
65
|
* 获取配置值
|
|
@@ -84,7 +99,7 @@ class ConfigManager {
|
|
|
84
99
|
*/
|
|
85
100
|
reset() {
|
|
86
101
|
const oldConfig = { ...this.config };
|
|
87
|
-
//
|
|
102
|
+
// 使用私有 reset 方法重建默认配置
|
|
88
103
|
this.config = {
|
|
89
104
|
debug: false,
|
|
90
105
|
logLevel: 'info',
|
|
@@ -380,6 +395,16 @@ class RemoteLogHandler {
|
|
|
380
395
|
return;
|
|
381
396
|
const entriesToSend = [...this.queue];
|
|
382
397
|
this.queue = [];
|
|
398
|
+
// 防止在 fetch 失败时无限重试
|
|
399
|
+
const sendCount = this._sendCount || 0;
|
|
400
|
+
this._sendCount = sendCount + 1;
|
|
401
|
+
// 如果发送次数过多,停止发送以防止无限循环
|
|
402
|
+
if (sendCount > 10) {
|
|
403
|
+
console.warn('RemoteLogHandler: Too many failed sends, stopping. Clear queue.');
|
|
404
|
+
this.queue = [];
|
|
405
|
+
this._sendCount = 0;
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
383
408
|
try {
|
|
384
409
|
fetch(this.endpoint, {
|
|
385
410
|
method: 'POST',
|
|
@@ -389,12 +414,17 @@ class RemoteLogHandler {
|
|
|
389
414
|
body: JSON.stringify(entriesToSend),
|
|
390
415
|
// 不等待响应,避免阻塞
|
|
391
416
|
keepalive: true
|
|
392
|
-
}).catch(err => {
|
|
417
|
+
}).catch((err) => {
|
|
393
418
|
console.error('Failed to send logs to remote server:', err);
|
|
394
419
|
// 失败时把日志放回队列,但防止无限增长
|
|
395
420
|
if (this.queue.length < this.maxQueueSize) {
|
|
396
|
-
|
|
421
|
+
// 限制放回的数量,防止内存溢出
|
|
422
|
+
const maxReturn = Math.min(entriesToSend.length, this.maxQueueSize - this.queue.length);
|
|
423
|
+
const returnedEntries = entriesToSend.slice(0, maxReturn);
|
|
424
|
+
this.queue = [...returnedEntries, ...this.queue];
|
|
397
425
|
}
|
|
426
|
+
// 重置发送计数,允许后续重试
|
|
427
|
+
this._sendCount = 0;
|
|
398
428
|
});
|
|
399
429
|
}
|
|
400
430
|
catch (error) {
|
|
@@ -796,6 +826,7 @@ const VERSION = '1.3.3';
|
|
|
796
826
|
// 构建日期
|
|
797
827
|
const BUILD_DATE = new Date().toISOString();
|
|
798
828
|
|
|
829
|
+
/* eslint-disable */
|
|
799
830
|
/**
|
|
800
831
|
* @file 模块管理器
|
|
801
832
|
* @description 统一管理库的各功能模块,提供模块的注册、初始化和卸载功能
|
|
@@ -815,6 +846,12 @@ class ModuleManager extends EventEmitter {
|
|
|
815
846
|
}
|
|
816
847
|
return ModuleManager.instance;
|
|
817
848
|
}
|
|
849
|
+
/**
|
|
850
|
+
* 重置单例实例(主要用于测试)
|
|
851
|
+
*/
|
|
852
|
+
static resetInstance() {
|
|
853
|
+
ModuleManager.instance = undefined;
|
|
854
|
+
}
|
|
818
855
|
/**
|
|
819
856
|
* 私有构造函数,确保单例模式
|
|
820
857
|
*/
|
|
@@ -822,6 +859,7 @@ class ModuleManager extends EventEmitter {
|
|
|
822
859
|
super();
|
|
823
860
|
this.modules = new Map();
|
|
824
861
|
this.initialized = false;
|
|
862
|
+
this.initPromise = null;
|
|
825
863
|
this.logger = Logger.getInstance();
|
|
826
864
|
this.logger.debug('ModuleManager', `初始化模块管理器 v${VERSION}`);
|
|
827
865
|
}
|
|
@@ -1144,6 +1182,9 @@ class IDCardDetector extends EventEmitter {
|
|
|
1144
1182
|
super();
|
|
1145
1183
|
this.initialized = false;
|
|
1146
1184
|
this.models = {};
|
|
1185
|
+
/** 重用的 Canvas 元素,用于减少内存分配 */
|
|
1186
|
+
this.reusableCanvas = null;
|
|
1187
|
+
this.reusableContext = null;
|
|
1147
1188
|
this.options = {
|
|
1148
1189
|
enabled: true,
|
|
1149
1190
|
minConfidence: 0.7,
|
|
@@ -1242,6 +1283,26 @@ class IDCardDetector extends EventEmitter {
|
|
|
1242
1283
|
if (!this.initialized) {
|
|
1243
1284
|
return Result.failure(new Error('身份证检测器未初始化'));
|
|
1244
1285
|
}
|
|
1286
|
+
// 输入验证
|
|
1287
|
+
if (!image) {
|
|
1288
|
+
return Result.failure(new Error('图像源不能为空'));
|
|
1289
|
+
}
|
|
1290
|
+
// 验证 HTMLImageElement 是否已加载
|
|
1291
|
+
if (image instanceof HTMLImageElement && !image.complete) {
|
|
1292
|
+
return Result.failure(new Error('图像尚未加载完成'));
|
|
1293
|
+
}
|
|
1294
|
+
// 验证 ImageData 尺寸
|
|
1295
|
+
if (image instanceof ImageData) {
|
|
1296
|
+
if (image.width === 0 || image.height === 0) {
|
|
1297
|
+
return Result.failure(new Error('图像尺寸无效'));
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
// 验证 Canvas 尺寸
|
|
1301
|
+
if (image instanceof HTMLCanvasElement) {
|
|
1302
|
+
if (image.width === 0 || image.height === 0) {
|
|
1303
|
+
return Result.failure(new Error('Canvas尺寸无效'));
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1245
1306
|
try {
|
|
1246
1307
|
this.logger.debug('IDCardDetector', '开始处理图像');
|
|
1247
1308
|
// 预处理图像
|
|
@@ -1288,9 +1349,7 @@ class IDCardDetector extends EventEmitter {
|
|
|
1288
1349
|
}
|
|
1289
1350
|
}
|
|
1290
1351
|
else if (image instanceof HTMLImageElement && image.complete) {
|
|
1291
|
-
const canvas =
|
|
1292
|
-
canvas.width = image.naturalWidth;
|
|
1293
|
-
canvas.height = image.naturalHeight;
|
|
1352
|
+
const canvas = this.getReusableCanvas(image.naturalWidth, image.naturalHeight);
|
|
1294
1353
|
const context = canvas.getContext('2d');
|
|
1295
1354
|
if (context) {
|
|
1296
1355
|
context.drawImage(image, 0, 0);
|
|
@@ -1307,6 +1366,26 @@ class IDCardDetector extends EventEmitter {
|
|
|
1307
1366
|
return Result.failure(error);
|
|
1308
1367
|
}
|
|
1309
1368
|
}
|
|
1369
|
+
/**
|
|
1370
|
+
* 获取可重用的 Canvas 元素
|
|
1371
|
+
* @param width 宽度
|
|
1372
|
+
* @param height 高度
|
|
1373
|
+
* @returns CanvasRenderingContext2D
|
|
1374
|
+
*/
|
|
1375
|
+
getReusableCanvas(width, height) {
|
|
1376
|
+
// 如果存在可重用的 canvas 且尺寸匹配,直接返回
|
|
1377
|
+
if (this.reusableCanvas &&
|
|
1378
|
+
this.reusableCanvas.width === width &&
|
|
1379
|
+
this.reusableCanvas.height === height) {
|
|
1380
|
+
return this.reusableCanvas;
|
|
1381
|
+
}
|
|
1382
|
+
// 创建新的 canvas
|
|
1383
|
+
this.reusableCanvas = document.createElement('canvas');
|
|
1384
|
+
this.reusableCanvas.width = width;
|
|
1385
|
+
this.reusableCanvas.height = height;
|
|
1386
|
+
this.reusableContext = this.reusableCanvas.getContext('2d');
|
|
1387
|
+
return this.reusableCanvas;
|
|
1388
|
+
}
|
|
1310
1389
|
/**
|
|
1311
1390
|
* 预处理图像
|
|
1312
1391
|
* @param image 图像源
|
|
@@ -1315,7 +1394,6 @@ class IDCardDetector extends EventEmitter {
|
|
|
1315
1394
|
* @private
|
|
1316
1395
|
*/
|
|
1317
1396
|
async preprocessImage(image, options) {
|
|
1318
|
-
// 实际项目中,这里应该对图像进行预处理
|
|
1319
1397
|
this.logger.debug('IDCardDetector', '预处理图像');
|
|
1320
1398
|
// 创建ImageData对象
|
|
1321
1399
|
let imageData;
|
|
@@ -1323,11 +1401,9 @@ class IDCardDetector extends EventEmitter {
|
|
|
1323
1401
|
imageData = image;
|
|
1324
1402
|
}
|
|
1325
1403
|
else {
|
|
1326
|
-
const canvas = document.createElement('canvas');
|
|
1327
1404
|
const width = image instanceof HTMLImageElement ? image.naturalWidth : image.width;
|
|
1328
1405
|
const height = image instanceof HTMLImageElement ? image.naturalHeight : image.height;
|
|
1329
|
-
canvas
|
|
1330
|
-
canvas.height = height;
|
|
1406
|
+
const canvas = this.getReusableCanvas(width, height);
|
|
1331
1407
|
const context = canvas.getContext('2d');
|
|
1332
1408
|
if (!context) {
|
|
1333
1409
|
throw new Error('无法获取Canvas上下文');
|
|
@@ -1374,18 +1450,16 @@ class IDCardDetector extends EventEmitter {
|
|
|
1374
1450
|
* @private
|
|
1375
1451
|
*/
|
|
1376
1452
|
async cropAndAlign(image, edge) {
|
|
1377
|
-
// 实际项目中,这里应该进行透视变换以校正图像
|
|
1378
1453
|
this.logger.debug('IDCardDetector', '裁剪并校正图像');
|
|
1379
|
-
// 创建Canvas
|
|
1380
|
-
const canvas = document.createElement('canvas');
|
|
1381
1454
|
// 设置标准身份证尺寸比例
|
|
1382
|
-
|
|
1383
|
-
|
|
1455
|
+
const standardWidth = 428;
|
|
1456
|
+
const standardHeight = 270;
|
|
1457
|
+
const canvas = this.getReusableCanvas(standardWidth, standardHeight);
|
|
1384
1458
|
const context = canvas.getContext('2d');
|
|
1385
1459
|
if (!context) {
|
|
1386
1460
|
throw new Error('无法获取Canvas上下文');
|
|
1387
1461
|
}
|
|
1388
|
-
// 创建临时Canvas
|
|
1462
|
+
// 创建临时Canvas用于源图像
|
|
1389
1463
|
const tempCanvas = document.createElement('canvas');
|
|
1390
1464
|
tempCanvas.width = image.width;
|
|
1391
1465
|
tempCanvas.height = image.height;
|
|
@@ -1398,29 +1472,37 @@ class IDCardDetector extends EventEmitter {
|
|
|
1398
1472
|
// 在实际应用中,这里应该使用透视变换算法
|
|
1399
1473
|
// 例如使用Canvas的transform或WebGL进行变换
|
|
1400
1474
|
// 简化处理:直接裁剪
|
|
1401
|
-
context.drawImage(tempCanvas, edge.topLeft.x, edge.topLeft.y, edge.topRight.x - edge.topLeft.x, edge.bottomLeft.y - edge.topLeft.y, 0, 0,
|
|
1402
|
-
return context.getImageData(0, 0,
|
|
1475
|
+
context.drawImage(tempCanvas, edge.topLeft.x, edge.topLeft.y, edge.topRight.x - edge.topLeft.x, edge.bottomLeft.y - edge.topLeft.y, 0, 0, standardWidth, standardHeight);
|
|
1476
|
+
return context.getImageData(0, 0, standardWidth, standardHeight);
|
|
1403
1477
|
}
|
|
1404
1478
|
/**
|
|
1405
1479
|
* 识别文字
|
|
1480
|
+
*
|
|
1481
|
+
* @note 此方法返回模拟数据,用于框架开发和测试
|
|
1482
|
+
* 实际使用时需要替换为真实的 OCR 模型集成
|
|
1483
|
+
*
|
|
1406
1484
|
* @param image 图像数据
|
|
1407
1485
|
* @param type 身份证类型
|
|
1408
1486
|
* @returns 识别结果
|
|
1409
1487
|
* @private
|
|
1410
1488
|
*/
|
|
1411
1489
|
async recognizeText(image, type) {
|
|
1412
|
-
// 实际项目中,这里应该调用OCR模型进行文字识别
|
|
1413
1490
|
this.logger.debug('IDCardDetector', '识别文字');
|
|
1414
1491
|
// 模拟OCR结果
|
|
1415
|
-
//
|
|
1492
|
+
// 注意:这是框架的占位实现,真实场景需要接入实际的 OCR 服务
|
|
1493
|
+
// 可选的方案包括:
|
|
1494
|
+
// - TensorFlow.js + 自定义 OCR 模型
|
|
1495
|
+
// - 第三方 OCR API (如百度OCR、腾讯OCR)
|
|
1496
|
+
// - Tesseract.js WASM 版本
|
|
1497
|
+
//
|
|
1416
1498
|
if (type === IDCardType.FRONT) {
|
|
1417
1499
|
return {
|
|
1418
|
-
name: '张三',
|
|
1419
|
-
gender: '男',
|
|
1420
|
-
ethnicity: '汉',
|
|
1421
|
-
birthDate: '1990-01-01',
|
|
1422
|
-
address: '北京市朝阳区某某街道某某社区1号楼1单元101',
|
|
1423
|
-
idNumber: '110101199001010001',
|
|
1500
|
+
name: '张三', // TODO: 替换为真实OCR结果
|
|
1501
|
+
gender: '男', // TODO: 替换为真实OCR结果
|
|
1502
|
+
ethnicity: '汉', // TODO: 替换为真实OCR结果
|
|
1503
|
+
birthDate: '1990-01-01', // TODO: 替换为真实OCR结果
|
|
1504
|
+
address: '北京市朝阳区某某街道某某社区1号楼1单元101', // TODO: 替换为真实OCR结果
|
|
1505
|
+
idNumber: '110101199001010001', // TODO: 替换为真实OCR结果
|
|
1424
1506
|
photoRegion: {
|
|
1425
1507
|
x: 300,
|
|
1426
1508
|
y: 40,
|
|
@@ -1431,34 +1513,42 @@ class IDCardDetector extends EventEmitter {
|
|
|
1431
1513
|
}
|
|
1432
1514
|
else if (type === IDCardType.BACK) {
|
|
1433
1515
|
return {
|
|
1434
|
-
issueAuthority: '北京市公安局朝阳分局',
|
|
1435
|
-
validFrom: '2015-01-01',
|
|
1436
|
-
validTo: '2035-01-01'
|
|
1516
|
+
issueAuthority: '北京市公安局朝阳分局', // TODO: 替换为真实OCR结果
|
|
1517
|
+
validFrom: '2015-01-01', // TODO: 替换为真实OCR结果
|
|
1518
|
+
validTo: '2035-01-01' // TODO: 替换为真实OCR结果
|
|
1437
1519
|
};
|
|
1438
1520
|
}
|
|
1439
1521
|
return {};
|
|
1440
1522
|
}
|
|
1441
1523
|
/**
|
|
1442
1524
|
* 检测防伪特征
|
|
1525
|
+
*
|
|
1526
|
+
* @note 此方法返回模拟数据,用于框架开发和测试
|
|
1527
|
+
* 实际使用时需要替换为真实的防伪检测模型
|
|
1528
|
+
*
|
|
1443
1529
|
* @param image 图像数据
|
|
1444
1530
|
* @param detectionResult 检测结果
|
|
1445
1531
|
* @returns 防伪检测结果
|
|
1446
1532
|
* @private
|
|
1447
1533
|
*/
|
|
1448
1534
|
async detectAntiFake(image, detectionResult) {
|
|
1449
|
-
// 实际项目中,这里应该调用防伪模型进行特征检测
|
|
1450
1535
|
this.logger.debug('IDCardDetector', '检测防伪特征');
|
|
1451
1536
|
// 模拟防伪检测结果
|
|
1452
|
-
//
|
|
1537
|
+
// 注意:这是框架的占位实现,真实场景需要接入实际的防伪检测模型
|
|
1538
|
+
// 可选的方案包括:
|
|
1539
|
+
// - 紫外光特征检测
|
|
1540
|
+
// - 红外光特征检测
|
|
1541
|
+
// - 微缩文字检测
|
|
1542
|
+
// - 光学变色特征检测
|
|
1453
1543
|
return {
|
|
1454
1544
|
passed: true,
|
|
1455
1545
|
score: 0.92,
|
|
1456
1546
|
features: {
|
|
1457
|
-
fluorescent: true,
|
|
1458
|
-
microtext: true,
|
|
1459
|
-
opticalVariable: true,
|
|
1460
|
-
texture: true,
|
|
1461
|
-
watermark: true
|
|
1547
|
+
fluorescent: true, // TODO: 替换为真实检测结果
|
|
1548
|
+
microtext: true, // TODO: 替换为真实检测结果
|
|
1549
|
+
opticalVariable: true, // TODO: 替换为真实检测结果
|
|
1550
|
+
texture: true, // TODO: 替换为真实检测结果
|
|
1551
|
+
watermark: true // TODO: 替换为真实检测结果
|
|
1462
1552
|
}
|
|
1463
1553
|
};
|
|
1464
1554
|
}
|
|
@@ -1470,6 +1560,9 @@ class IDCardDetector extends EventEmitter {
|
|
|
1470
1560
|
// 清理模型
|
|
1471
1561
|
this.models = {};
|
|
1472
1562
|
this.initialized = false;
|
|
1563
|
+
// 清理可重用的 Canvas
|
|
1564
|
+
this.reusableCanvas = null;
|
|
1565
|
+
this.reusableContext = null;
|
|
1473
1566
|
// 清理事件监听
|
|
1474
1567
|
this.removeAllListeners();
|
|
1475
1568
|
}
|
|
@@ -2388,7 +2481,7 @@ function createWorker(workerFunction) {
|
|
|
2388
2481
|
let messageCounter = 0;
|
|
2389
2482
|
// 监听Worker消息
|
|
2390
2483
|
worker.addEventListener('message', (event) => {
|
|
2391
|
-
const { messageId, success, result, error } = event.data;
|
|
2484
|
+
const { messageId, success, result, error: _error } = event.data;
|
|
2392
2485
|
// 查找对应的Promise
|
|
2393
2486
|
const promiseHandlers = promiseMap.get(messageId);
|
|
2394
2487
|
if (promiseHandlers) {
|
|
@@ -2396,7 +2489,7 @@ function createWorker(workerFunction) {
|
|
|
2396
2489
|
promiseHandlers.resolve(result);
|
|
2397
2490
|
}
|
|
2398
2491
|
else {
|
|
2399
|
-
promiseHandlers.reject(new Error(
|
|
2492
|
+
promiseHandlers.reject(new Error(_error));
|
|
2400
2493
|
}
|
|
2401
2494
|
// 删除Promise映射
|
|
2402
2495
|
promiseMap.delete(messageId);
|
|
@@ -2420,8 +2513,8 @@ function createWorker(workerFunction) {
|
|
|
2420
2513
|
// 释放Blob URL
|
|
2421
2514
|
URL.revokeObjectURL(url);
|
|
2422
2515
|
// 拒绝所有未完成的Promise
|
|
2423
|
-
for (const [, { reject }] of promiseMap) {
|
|
2424
|
-
|
|
2516
|
+
for (const [, { reject: _reject }] of promiseMap) {
|
|
2517
|
+
_reject(new Error('Worker已终止'));
|
|
2425
2518
|
}
|
|
2426
2519
|
// 清空Promise映射
|
|
2427
2520
|
promiseMap.clear();
|
|
@@ -3582,6 +3675,7 @@ class AntiFakeDetector {
|
|
|
3582
3675
|
}
|
|
3583
3676
|
}
|
|
3584
3677
|
|
|
3678
|
+
/* eslint-disable */
|
|
3585
3679
|
/**
|
|
3586
3680
|
* @file 身份证模块入口
|
|
3587
3681
|
* @description 提供身份证识别和验证功能的模块入口
|
|
@@ -4135,6 +4229,7 @@ class QRCodeScanner extends EventEmitter {
|
|
|
4135
4229
|
}
|
|
4136
4230
|
}
|
|
4137
4231
|
|
|
4232
|
+
/* eslint-disable */
|
|
4138
4233
|
/**
|
|
4139
4234
|
* @file 二维码模块入口
|
|
4140
4235
|
* @description 提供二维码识别和解析功能的模块入口
|
|
@@ -4276,6 +4371,7 @@ class QRCodeModule extends BaseModule {
|
|
|
4276
4371
|
}
|
|
4277
4372
|
}
|
|
4278
4373
|
|
|
4374
|
+
/* eslint-disable */
|
|
4279
4375
|
/**
|
|
4280
4376
|
* @file 人脸模块入口
|
|
4281
4377
|
* @description 提供人脸检测、活体检测和人脸比对功能的模块入口
|
|
@@ -4724,6 +4820,7 @@ class NotSupportedError extends IDScannerError {
|
|
|
4724
4820
|
}
|
|
4725
4821
|
}
|
|
4726
4822
|
|
|
4823
|
+
/* eslint-disable */
|
|
4727
4824
|
/**
|
|
4728
4825
|
* @file 主入口文件
|
|
4729
4826
|
* @description ID Scanner库的主入口点,提供统一的API和模块导出
|