feat(scanner): add intelligent passport web terminal with real-time WS communication
- Implemented WebSocket connection management with connect, disconnect, and send commands - Added UI for server URL input, command selection, and send button with loading states - Developed message logging system with text and table views and export functionality - Included avatar display area supporting base64 image data with lazy loading and error handling - Created data table showing structured passport information with protocol-based field mappings - Integrated support for Base64 image data markers and toggleable full data display in logs - Used Tailwind CSS with custom theme colors and utility classes for consistent styling - Ensured accessibility with responsive layout and interactive controls - Added detailed error and connection status messages for better user feedbackmain
parent
376cb3a15f
commit
570a155399
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,215 @@
|
||||||
|
# 扫描仪集成分析
|
||||||
|
|
||||||
|
## 前端扫描仪架构
|
||||||
|
|
||||||
|
```
|
||||||
|
ViewerScanModalComponent (UI组件)
|
||||||
|
↓
|
||||||
|
PassportService (扫描服务层)
|
||||||
|
↓
|
||||||
|
PassportReader.js (扫描仪SDK/驱动 - 位于 assets/js/)
|
||||||
|
↓
|
||||||
|
WebSocket 连接
|
||||||
|
```
|
||||||
|
|
||||||
|
## 当前实现的 PassportReader.js
|
||||||
|
|
||||||
|
### WebSocket 连接
|
||||||
|
|
||||||
|
- **地址**: `ws://127.0.0.1:90`
|
||||||
|
- **消息协议**: JSON
|
||||||
|
|
||||||
|
### 请求格式
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{ Type: "Request", Command: "Get/Set", Operand: "OnLineStatus", Param: "True/False" }
|
||||||
|
{ Type: "Notify", Command: "Trigger", Operand: "ManualRecog", Param: "2" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应格式
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{ Type: "Notify", Operand: "CardContentText", Param: { ... } } // 文字结果
|
||||||
|
{ Type: "Notify", Operand: "Images", Param: { ... } } // 图片结果
|
||||||
|
{ Type: "Reply", Command: "Get", Operand: "OnLineStatus", Succeeded: "Y/N" }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 第二款SDK: DKePassport (智能读证终端)
|
||||||
|
|
||||||
|
### WebSocket 连接
|
||||||
|
|
||||||
|
- **地址**: `ws://127.0.0.1:9090`
|
||||||
|
- **消息协议**: JSON
|
||||||
|
|
||||||
|
### 请求格式
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{ "command": "get", "operand": "name" } // 获取设备名称
|
||||||
|
{ "command": "set", "operand": "auto", "param": 1 } // 设置自动模式
|
||||||
|
{ "command": "scan", "param": "{\"timeout\":5}" } // 扫描证件
|
||||||
|
{ "command": "getPhoto", "param": 5 } // 获取照片
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应格式
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"guestType": "100", // 旅客类型
|
||||||
|
"name": "张三", // 姓名
|
||||||
|
"sex": "1", // 性别
|
||||||
|
"birthday": "1990-01-01", // 出生日期
|
||||||
|
"cardType": "11", // 证件类型
|
||||||
|
"cardNo": "123456789012345678", // 证件号码
|
||||||
|
"nation": "01", // 民族
|
||||||
|
"nationalityArea": "CHN", // 国籍/地区
|
||||||
|
"curPhoto": "base64...", // 证件头像
|
||||||
|
"photo": "base64...", // 现场头像
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 支持的命令
|
||||||
|
|
||||||
|
| command | operand/param | 说明 |
|
||||||
|
|---------|----------------|------|
|
||||||
|
| get | name | 获取设备名称 |
|
||||||
|
| get | serialNo | 获取序列号 |
|
||||||
|
| get | model | 获取型号 |
|
||||||
|
| get | type | 获取类型 |
|
||||||
|
| set | auto=1 | 设置自动模式 |
|
||||||
|
| set | timeout=5 | 设置超时 |
|
||||||
|
| scan | timeout=5 | 扫描证件 |
|
||||||
|
| read | 5 | 读取数据 |
|
||||||
|
| readCode | 5 | 读取条码 |
|
||||||
|
| getPhoto | 5 | 获取照片 |
|
||||||
|
| scanRaw | - | 高级扫描 |
|
||||||
|
|
||||||
|
### 证件类型映射 (cardType)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 国内旅客
|
||||||
|
'11': '身份证'
|
||||||
|
'12': '居住证'
|
||||||
|
'13': '户口本'
|
||||||
|
'55': '港澳台居民居住证'
|
||||||
|
'93': '国内护照'
|
||||||
|
'95': '港澳通行证'
|
||||||
|
|
||||||
|
// 港澳台旅客
|
||||||
|
'16': '台湾居民来往大陆通行证'
|
||||||
|
'60': '港澳居民来往内地通行证'
|
||||||
|
|
||||||
|
// 国外旅客
|
||||||
|
'14': '国外护照'
|
||||||
|
'34': '外国人永久居留身份证'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 旅客类型映射 (guestType)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
'100': '国内旅客'
|
||||||
|
'200': '港澳台旅客'
|
||||||
|
'300': '国外旅客'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 关键差异对比
|
||||||
|
|
||||||
|
| 项目 | 当前SDK (Sinosecu) | 新SDK (DKePassport) |
|
||||||
|
|------|-------------------|---------------------|
|
||||||
|
| WebSocket端口 | 90 | 9090 |
|
||||||
|
| 请求格式 | `{Type, Command, Operand, Param}` | `{command, operand, param}` |
|
||||||
|
| 响应格式 | `{Type, Operand, Param}` | `{data: {...}}` |
|
||||||
|
| 图片字段 | `Param` (通过 onImageResult) | `curPhoto`, `photo` (在data内) |
|
||||||
|
| 触发扫描 | `triggerManualRead()` | `scan` 命令 |
|
||||||
|
|
||||||
|
## 替换影响分析
|
||||||
|
|
||||||
|
### 情况:新SDK (DKePassport) 替代当前SDK
|
||||||
|
|
||||||
|
**需要修改的文件**:
|
||||||
|
|
||||||
|
| 文件 | 改动程度 | 说明 |
|
||||||
|
|------|----------|------|
|
||||||
|
| `assets/js/PassportReader.js` | **完全重写** | 新SDK命令格式完全不同 |
|
||||||
|
| `passport.service.ts` | **需要调整** | 回调适配新响应格式 |
|
||||||
|
| `viewer-scan-modal.component.ts` | **大概率不变** | UI逻辑不变 |
|
||||||
|
| 后端 | **大概率不变** | 前端传过来的数据格式需确认 |
|
||||||
|
|
||||||
|
### 适配层设计建议
|
||||||
|
|
||||||
|
为了最小化改动,建议创建适配层:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 新的 DKePassportReader.js
|
||||||
|
export class DKePassportReader {
|
||||||
|
constructor(options = {}) {
|
||||||
|
this.host = options.host || "ws://127.0.0.1:9090"
|
||||||
|
// ... 新SDK实现
|
||||||
|
}
|
||||||
|
|
||||||
|
// 适配现有接口
|
||||||
|
connect() {
|
||||||
|
// WebSocket连接
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameter(param, value) {
|
||||||
|
// 转换: VIZ -> auto, RFID -> ?
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextResult(data) {
|
||||||
|
// 将新格式转换为旧格式
|
||||||
|
}
|
||||||
|
|
||||||
|
onImageResult(images) {
|
||||||
|
// 从 data.curPhoto 获取图片
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### PassportService 接口兼容方案
|
||||||
|
|
||||||
|
新SDK需要适配 `passport.service.ts` 的期望接口:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// passport.service.ts 期望的接口
|
||||||
|
passportReader.onTextResult = (result) => { ... }
|
||||||
|
passportReader.onImageResult = (images) => { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
需要 `DKePassportReader` 在收到 `{data: {...}}` 时:
|
||||||
|
1. 将 `data` 解析为符合现有期望的格式
|
||||||
|
2. 触发 `onTextResult` 和 `onImageResult` 回调
|
||||||
|
|
||||||
|
## 建议实施步骤
|
||||||
|
|
||||||
|
1. **创建新文件**: `assets/js/DKePassportReader.js`
|
||||||
|
2. **实现适配层**: 将DKePassport响应格式转换为现有格式
|
||||||
|
3. **修改 `passport.service.ts`**: 使用新Reader类
|
||||||
|
4. **测试**: 验证扫描流程完整性
|
||||||
|
|
||||||
|
## 相关文件路径
|
||||||
|
|
||||||
|
### 前端
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `AML_Frontend/src/assets/js/PassportReader.js` | 当前扫描仪SDK |
|
||||||
|
| `AML_Frontend/src/app/components/components-viewer/viewer-scan-modal/viewer-scan-modal.component.ts` | 扫描弹窗UI |
|
||||||
|
| `AML_Frontend/src/app/components/components-viewer/viewer-scan-modal/services/passport.service.ts` | 扫描服务层 |
|
||||||
|
| `AML_Frontend/src/app/modules/configuration/components/set-scan/set-scan.component.ts` | 扫描设置组件 |
|
||||||
|
|
||||||
|
### 新SDK参考
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `docs/KYC/Scanner/DKePassport-release-1.3.0/智能读证终端网页.html` | DKePassport SDK演示页面 |
|
||||||
|
|
||||||
|
## 版本信息
|
||||||
|
|
||||||
|
**文档版本**: v1.1
|
||||||
|
**创建日期**: 2026-04-30
|
||||||
|
**更新日期**: 2026-04-30
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
# 扫描仪集成分析
|
|
||||||
|
|
||||||
## 前端扫描仪架构
|
|
||||||
|
|
||||||
```
|
|
||||||
ViewerScanModalComponent (UI组件)
|
|
||||||
↓
|
|
||||||
PassportService (扫描服务层)
|
|
||||||
↓
|
|
||||||
PassportReader.js (扫描仪SDK/驱动 - 位于 assets/js/)
|
|
||||||
↓
|
|
||||||
WebSocket 连接 (ws://127.0.0.1:90)
|
|
||||||
```
|
|
||||||
|
|
||||||
## PassportReader.js 实现分析
|
|
||||||
|
|
||||||
### 当前架构
|
|
||||||
|
|
||||||
```
|
|
||||||
前端 WebSocket服务器 (127.0.0.1:90) 扫描仪硬件
|
|
||||||
│ │ │
|
|
||||||
│── connect() ──────────────>│ │
|
|
||||||
│<── onConnected() ──────────│ │
|
|
||||||
│ │ │
|
|
||||||
│── setParameter(VIZ,true) ──>│ │
|
|
||||||
│── setParameter(RFID,true) ─>│ │
|
|
||||||
│ │ │
|
|
||||||
│── triggerManualRead() ───>│ │
|
|
||||||
│<── onTextResult ───────────│<── 护照文字数据 ──────────── │
|
|
||||||
│<── onImageResult ──────────│<── 护照图片 ────────────── │
|
|
||||||
```
|
|
||||||
|
|
||||||
### 关键接口
|
|
||||||
|
|
||||||
#### 方法 (Methods)
|
|
||||||
|
|
||||||
| 方法 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| `connect()` | 建立WebSocket连接 |
|
|
||||||
| `disconnect()` | 断开连接 |
|
|
||||||
| `setParameter(param, value)` | 设置参数 (VIZ/RFID/WantFieldSource) |
|
|
||||||
| `getDeviceInfo(type)` | 获取设备状态 |
|
|
||||||
| `triggerManualRead()` | 触发读取 |
|
|
||||||
| `getOnLineStatus(callback)` | 检查设备在线状态 |
|
|
||||||
| `isConnected()` | 检查连接状态 |
|
|
||||||
|
|
||||||
#### 回调 (Callbacks)
|
|
||||||
|
|
||||||
| 回调 | 触发时机 |
|
|
||||||
|------|----------|
|
|
||||||
| `onConnected` | WebSocket连接成功 |
|
|
||||||
| `onDisconnected` | WebSocket断开 |
|
|
||||||
| `onError` | 连接或通信错误 |
|
|
||||||
| `onTextResult` | 收到文字识别结果 |
|
|
||||||
| `onImageResult` | 收到图片 |
|
|
||||||
| `onDeviceInfo` | 设备信息响应 |
|
|
||||||
| `onRealtimeMessage` | 实时消息 |
|
|
||||||
|
|
||||||
### 消息协议格式
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 请求格式
|
|
||||||
{ Type: "Request", Command: "Get/Set", Operand: "OnLineStatus", Param: "True/False" }
|
|
||||||
{ Type: "Notify", Command: "Trigger", Operand: "ManualRecog", Param: "2" }
|
|
||||||
|
|
||||||
// 响应格式
|
|
||||||
{ Type: "Notify", Operand: "CardContentText", Param: { ... } } // 文字结果
|
|
||||||
{ Type: "Notify", Operand: "Images", Param: { ... } } // 图片结果
|
|
||||||
{ Type: "Reply", Command: "Get", Operand: "OnLineStatus", Succeeded: "Y/N" }
|
|
||||||
```
|
|
||||||
|
|
||||||
## 替换扫描仪的影响分析
|
|
||||||
|
|
||||||
### 方案一:新SDK使用相同协议 (WebSocket + JSON)
|
|
||||||
|
|
||||||
**改动范围**: 仅 `PassportReader.js`
|
|
||||||
|
|
||||||
- 保持 `PassportReader.js` 接口不变
|
|
||||||
- 仅替换内部实现
|
|
||||||
- 上层代码 (`passport.service.ts`, `viewer-scan-modal.component.ts`) **无需修改**
|
|
||||||
- 后端代码 **无需修改**
|
|
||||||
|
|
||||||
### 方案二:新SDK使用不同协议
|
|
||||||
|
|
||||||
**改动范围**:
|
|
||||||
|
|
||||||
| 文件 | 改动程度 | 说明 |
|
|
||||||
|------|----------|------|
|
|
||||||
| `assets/js/PassportReader.js` | **完全重写** | 新SDK驱动 |
|
|
||||||
| `passport.service.ts` | **可能需要调整** | 适配新的调用方式 |
|
|
||||||
| `viewer-scan-modal.component.ts` | **大概率不变** | UI逻辑不变 |
|
|
||||||
| 后端 | **大概率不变** | 只接收前端传来的数据 |
|
|
||||||
|
|
||||||
### 方案三:新SDK使用ActiveX/NPAPI等浏览器插件
|
|
||||||
|
|
||||||
需要考虑:
|
|
||||||
- 前端技术方案是否支持
|
|
||||||
- 浏览器兼容性
|
|
||||||
- 安全策略限制
|
|
||||||
|
|
||||||
## 建议方案
|
|
||||||
|
|
||||||
最理想情况是让新SDK适配现有的 `PassportService` 接口模式:
|
|
||||||
|
|
||||||
```
|
|
||||||
新SDK → 适配层 → PassportReader.js (现有接口不变) → PassportService → ViewerScanModalComponent
|
|
||||||
```
|
|
||||||
|
|
||||||
这样前端只需:
|
|
||||||
1. 替换 `PassportReader.js` (新SDK)
|
|
||||||
2. 重写适配逻辑,让它映射到现有回调接口
|
|
||||||
3. `passport.service.ts` 和 UI组件**不用改**
|
|
||||||
|
|
||||||
## 相关文件路径
|
|
||||||
|
|
||||||
### 前端
|
|
||||||
|
|
||||||
| 文件 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| `AML_Frontend/src/assets/js/PassportReader.js` | 扫描仪SDK (核心) |
|
|
||||||
| `AML_Frontend/src/app/components/components-viewer/viewer-scan-modal/viewer-scan-modal.component.ts` | 扫描弹窗UI |
|
|
||||||
| `AML_Frontend/src/app/components/components-viewer/viewer-scan-modal/services/passport.service.ts` | 扫描服务层 |
|
|
||||||
| `AML_Frontend/src/app/modules/configuration/components/set-scan/set-scan.component.ts` | 扫描设置组件 |
|
|
||||||
|
|
||||||
### 后端
|
|
||||||
|
|
||||||
后端不直接和扫描仪交互,接收的是前端传来的OCR结果和图片数据。
|
|
||||||
|
|
||||||
## 版本信息
|
|
||||||
|
|
||||||
**文档版本**: v1.0
|
|
||||||
**创建日期**: 2026-04-30
|
|
||||||
Loading…
Reference in New Issue