Skip to content

Scanner 二维码扫描器

高性能 QR 码扫描与解析


功能描述

使用 Web Worker 后台解码二维码,支持地址扫描、支付请求、深度链接和联系人协议。


架构设计

核心类

typescript
// QRScanner - 主扫描器类
class QRScanner {
  constructor(options: QRScannerOptions)
  start(source: FrameSource): void
  stop(): void
  on(event: 'scan' | 'error', callback: Function): void
}

// FrameSource - 帧来源接口
interface FrameSource {
  getFrame(): Promise<ImageData | null>
  dispose(): void
}

Web Worker 解码

┌─────────────────┐     ┌─────────────────┐
│   主线程        │     │   Web Worker    │
│   - 获取帧      │ --> │   - jsQR 解码   │
│   - 回调处理    │ <-- │   - 返回结果    │
└─────────────────┘     └─────────────────┘

解析类型

ParsedQRContent 类型定义

typescript
type ParsedQRContent = 
  | ParsedAddress    // 纯地址
  | ParsedPayment    // 支付请求
  | ParsedDeepLink   // 深度链接
  | ParsedContact    // 联系人协议
  | ParsedUnknown    // 未知内容

支持的格式

类型格式示例说明
address0x1234...纯地址
paymentethereum:0x...?value=1000EIP-681 支付请求
deeplinkkeyapp://authorize?...应用深度链接
contact{"type":"contact",...}联系人协议

联系人协议 (Contact Protocol)

JSON 格式 (推荐)

json
{
  "type": "contact",
  "name": "张三",
  "addresses": [
    { "chainType": "ethereum", "address": "0x742d35Cc..." },
    { "chainType": "bitcoin", "address": "bc1qar0..." }
  ],
  "memo": "好友",
  "avatar": "👨‍💼"
}

URI 格式

contact://张三?eth=0x742d35Cc...&btc=bc1qar0...&memo=好友
参数说明
ethEthereum 地址
btcBitcoin 地址
trxTron 地址
memo备注

ScannerJob 组件

用途

Stackflow BottomSheet 模式的扫码器,用于在发送页面等场景扫描地址。

属性

属性类型说明
chainType'ethereum' | 'bitcoin' | 'tron' | 'any'限制扫描的地址类型

使用示例

tsx
// 在 SendPage 中使用
const flow = useFlow()
const callbackRef = useRef<(addr: string) => void>()

// 打开扫码器
callbackRef.current = (address) => {
  setRecipientAddress(address)
}
setScannerResultCallback(callbackRef)
flow.push('ScannerJob', { chainType: 'ethereum' })

验证器规范

内置验证器

验证器链类型规则
ethereumAddressethereum^0x[a-fA-F0-9]{40}$
bitcoinAddressbitcoinlegacy/segwit/bech32
tronAddresstron^T[a-zA-HJ-NP-Z1-9]{33}$
anyAddressany26-64 字符

自定义验证器

typescript
type ScanValidator = (
  content: string, 
  parsed: ParsedQRContent
) => true | string  // true = 通过, string = 错误消息 i18n key

相关 Job 组件

ContactAddConfirmJob

扫码获取联系人后的确认添加界面。

┌─────────────────────────────────┐
│           添加联系人             │
├─────────────────────────────────┤
│  👤 张三                         │
│  ────────────────────────────   │
│  ETH: 0x742d...                 │
│  BTC: bc1qar...                 │
│  ────────────────────────────   │
│  备注: [输入框]                  │
├─────────────────────────────────┤
│  [取消]          [保存]          │
└─────────────────────────────────┘

ContactShareJob

展示联系人名片二维码用于分享。

┌─────────────────────────────────┐
│           分享名片               │
├─────────────────────────────────┤
│                                 │
│        ┌─────────────┐         │
│        │   QR Code   │         │
│        │   (联系人)   │         │
│        └─────────────┘         │
│                                 │
│        张三 · ETH               │
│                                 │
├─────────────────────────────────┤
│  [下载图片]      [分享]          │
└─────────────────────────────────┘

测试覆盖

单元测试

  • qr-parser.test.ts: 38 个测试用例
  • ScannerJob.test.ts: 31 个测试用例
  • qr-scanner.test.ts: 10 个测试用例

Storybook Stories

  • ScannerJob.stories.tsx: ValidatorDemo, AddressFormats, UIPreview
  • ContactJobs.stories.tsx: ContactProtocolDemo, ContactAddConfirmPreview, ContactSharePreview, EdgeCases

E2E 测试

  • scanner.spec.ts: 扫描页面基础测试
  • contact-scanner.mock.spec.ts: 联系人协议集成测试

性能指标

指标目标说明
扫描帧率6-7 FPS150ms 间隔
解码延迟< 100msWeb Worker 后台处理
首次扫描< 500ms冷启动到首次成功

Released under the MIT License.