# scan-code-jssdk 统一扫码 JSSDK,支持桥接扫码、微信小程序、微信 JSSDK 扫码、Web 摄像头扫码、选择图片识别和扫码枪输入。 ## 功能 - App 桥接环境:优先调用原生桥接 `startScan` / `stopScan`。 - 微信浏览器:初始化微信 JSSDK 后调用 `wx.scanQRCode`。 - Web 浏览器:使用 `BarcodeDetector` 识别二维码和条形码。 - 图片识别:选择本地图片后识别二维码/条形码。 - 扫码枪:监听键盘快速输入并统一走扫码监听回调。 - 监听规则:支持按 `match` 正则和 `level` 优先级分发扫码结果。 ## 引入 构建后使用 `dist/index.js`: ```html ``` 如果脚本是后加载的,可以监听 `IScanReady`: ```js function init() { IScan.config().then(function () { // ready }); } if (window.IScan) { init(); } else { window.addEventListener("IScanReady", init, { once: true }); } ``` ## 快速开始 ```js IScan.config({ initWechatJssdk: { apiUrl: "https://your-domain.com/wechat/jssdk-config" } }).then(function () { // 监听识别状态 IScan.setStatusListener(function (status) { console.log("status:", status); }); // 监听识别结果 IScan.onScanListener(function (res) { console.log("scan result:", res.result, res.key); }, "scan", null, 100); }); // 自动选择可用扫码方式:桥接 -> 微信 -> Web 摄像头 -> 图片识别 IScan.startScan(); // 仅打开 Web 视频扫码 IScan.scanVideo(); // 仅选择图片识别 IScan.scanImage(); // 停止当前扫码 IScan.stopScan(); ``` ## 配置项 通过 `IScan.config(options)` 配置。 ```ts interface ScanConfigOptions { scanRestartDelay?: number, bridgeEnabled?: boolean; bridgeName?: string; webScanEnabled?: boolean, webScanCanvasEnabled?: boolean; webScanCanvasStyle?: string; webScanCloseButtonStyle?: string; webScanType?: ("qrCode" | "barCode")[]; webScanVideoMirror?: boolean; webScanVideoMirrorVertical?: boolean; webScanBeepAudio?: string; webScanBeepEnabled?: boolean; initWechatJssdk?: { apiUrl?: string; sdkConfig?: { debug?: boolean; appId: string; timestamp: number; nonceStr: string; signature: string; }; sdkUrl?: string; jsApiList?: string[]; }; } ``` | 配置 | 说明 | 默认值 | | --- | --- | --- | | `scanRestartDelay` | 扫码重启延迟,单位:毫秒 | `500ms` | | `bridgeEnabled` | 是否启用桥接扫码 | `true` | | `bridgeName` | 挂载在 `window` 上的桥接对象名称 | `__bridge_client__` | | `webScanEnabled` | 是否支持 WebScan 扫码 | `true` | | `webScanCanvasEnabled` | 是否显示 WebScan 扫码 canvas;关闭后仍会用隐藏 canvas 识别 | `true` | | `webScanCanvasStyle` | WebScan 扫码 canvas 样式 | `position: fixed; width: 300px; height: 300px; top: 0; left: 0; z-index: 9999;` | | `webScanCloseButtonStyle` | WebScan 扫码 canvas 关闭按钮样式 | 显示在 canvas 右上角 | | `webScanType` | WebScan 扫码类型 | `["qrCode", "barCode"]` | | `webScanVideoMirror` | WebScan 视频是否水平镜像;不配置时自动判断:前置/PC 镜像,后置不镜像 | 自动 | | `webScanVideoMirrorVertical` | WebScan 视频是否垂直镜像 | `false` | | `webScanBeepAudio` | WebScan 扫码成功提示音地址 | 内置提示音 | | `webScanBeepEnabled` | WebScan 扫码成功是否播放提示音 | `true` | | `initWechatJssdk` | 微信 JSSDK 初始化配置,仅微信环境生效 | 无 | `initWechatJssdk` 子配置: | 配置 | 说明 | 默认值 | | --- | --- | --- | | `apiUrl` | 微信 JSSDK 签名配置接口地址;未传 `sdkConfig` 时会请求该接口,并自动携带当前页面 URL 参数 | 无 | | `sdkConfig` | 直接传入微信 JSSDK 签名配置;配置后不再请求 `apiUrl` | 无 | | `sdkConfig.debug` | 是否开启微信 JSSDK 调试模式 | `false` | | `sdkConfig.appId` | 微信公众平台应用 ID | 必填 | | `sdkConfig.timestamp` | 签名时间戳 | 必填 | | `sdkConfig.nonceStr` | 签名随机字符串 | 必填 | | `sdkConfig.signature` | 微信 JSSDK 签名 | 必填 | | `sdkUrl` | 微信 JSSDK 脚本地址 | `https://res.wx.qq.com/open/js/jweixin-1.6.0.js` | | `jsApiList` | 微信 JSSDK JS-API 列表,SDK 会自动追加 `scanQRCode` | `["scanQRCode"]` | ## 桥接接入 桥接对象需要挂载到 `window[bridgeName]`,并实现 `call(method, data)`。 SDK 会调用: - `startScan` - `stopScan` 异步回调方法名为 `${bridgeName}_handle_callback`。 ```js window.__bridge_client__ = { call: function (method, data) { var requestId = data.request_id; if (method === "startScan") { // 调用原生扫码后回调 window.__bridge_client___handle_callback({ code: 0, method: method, request_id: requestId, payload: { result: "https://example.com" } }); } if (method === "stopScan") { window.__bridge_client___handle_callback({ code: 0, method: method, request_id: requestId, payload: {} }); } } }; ``` ## 微信 JSSDK 接入 配置接口方式: ```js IScan.config({ initWechatJssdk: { apiUrl: "https://your-domain.com/wechat/jssdk-config" } }); ``` 接口会收到当前页面 URL 参数:`url=location.href.split("#")[0]`。 也可以直接传入微信签名配置: ```js IScan.config({ initWechatJssdk: { apiUrl: "", sdkConfig: { appId: "wx_app_id", timestamp: 123456, nonceStr: "nonce", signature: "signature" } } }); ``` `jsApiList` 会默认追加 `scanQRCode`。 ## API ### `config(options?): Promise` 配置并初始化 SDK。 ```js IScan.config({ webScanCanvasEnabled: true }); ``` ### `setStatusListener(callback): void` 监听扫码状态,状态为: - `scanning` - `closed` ```js IScan.setStatusListener(function (status) { console.log(status); }); ``` ### `onScanListener(callback, key, match?, level?): ScanListenerInfo` 添加扫码结果监听。 ```js var listener = IScan.onScanListener(function (res) { console.log(res.result, res.key); }, "order", "^https://", 100); ``` 参数说明: - `callback`:扫码结果回调。 - `key`:监听 key,同 key 会覆盖旧监听。 - `match`:可选正则字符串;扫码结果匹配后才回调。 - `level`:优先级,数值越大越先匹配。 ### `offScanListener(callbackOrKey): void` 移除监听,可传 callback 或 key。 ```js IScan.offScanListener("order"); listener.cancel(); ``` ### `getStatus(): "scanning" | "ready"` 获取当前扫码状态。 ```js console.log(IScan.getStatus()); ``` ### `startScan(): void` 开启扫码。SDK 会按以下顺序选择可用能力: 1. 桥接扫码 2. 微信扫码 3. Web 摄像头扫码 4. 图片识别 扫码结果通过 `onScanListener` 回调。 ```js IScan.startScan(); ``` ### `scanVideo(): void` 直接开启 Web 摄像头扫码。扫码结果通过 `onScanListener` 回调。 ```js IScan.scanVideo(); ``` ### `scanImage(): void` 直接选择图片进行识别。识别结果通过 `onScanListener` 回调。 ```js IScan.scanImage(); ``` ### `stopScan(): void` 停止当前扫码。 ```js IScan.stopScan(); ``` ### `clear(): void` 清空全部扫码监听。 ```js IScan.clear(); ``` ## 类型 ```ts interface ScanResult { result: string; key: string; } type ScanStatus = "scanning" | "ready"; type ScanResultCallback = (result: ScanResult) => any; type ScanStatusCallback = (status: ScanStatus) => any; ``` ## 开发 ```bash npm install npm run build ``` 构建产物输出到 `dist` 目录。