|
|
@@ -82,8 +82,10 @@ function startScan() {
|
|
|
|
|
|
// ============================== H5 端扫码实现 ==============================
|
|
|
async function h5StartBarcodeScanner() {
|
|
|
+ console.log('[H5 扫码] start')
|
|
|
// 1. 检测摄像头权限 API
|
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
|
+ console.warn('[H5 扫码] 浏览器不支持 getUserMedia')
|
|
|
tipText.value = '浏览器不支持获取摄像头,请点击下方"手动输入"'
|
|
|
return
|
|
|
}
|
|
|
@@ -93,6 +95,7 @@ async function h5StartBarcodeScanner() {
|
|
|
video: { facingMode: { ideal: 'environment' } },
|
|
|
audio: false
|
|
|
})
|
|
|
+ console.log('[H5 扫码] getUserMedia 成功')
|
|
|
} catch (e: any) {
|
|
|
if (e?.name === 'NotAllowedError' || e?.name === 'PermissionDeniedError') {
|
|
|
tipText.value = '摄像头权限被拒绝,请在浏览器设置中允许后重试'
|
|
|
@@ -124,43 +127,13 @@ async function h5StartBarcodeScanner() {
|
|
|
console.warn('[H5 扫码] video.play 失败', e)
|
|
|
}
|
|
|
|
|
|
- // 4. 选 QR 识别方案:
|
|
|
- // 优先 BarcodeDetector(Chrome/Edge/iOS 17+ 性能好),
|
|
|
- // 不可用时 fallback jsQR(纯 JS,兼容老浏览器但稍慢)
|
|
|
- const BarcodeDetectorCtor: any = (window as any).BarcodeDetector
|
|
|
- if (typeof BarcodeDetectorCtor === 'function') {
|
|
|
- let detector: any
|
|
|
- try {
|
|
|
- detector = new BarcodeDetectorCtor({ formats: ['qr_code'] })
|
|
|
- } catch (e) {
|
|
|
- // ignore
|
|
|
- }
|
|
|
- if (detector) {
|
|
|
- const tick = async () => {
|
|
|
- if (!h5Stream) return
|
|
|
- try {
|
|
|
- const codes = await detector.detect(video)
|
|
|
- if (codes && codes.length && codes[0].rawValue) {
|
|
|
- h5StopScanner()
|
|
|
- scanResult.value = codes[0].rawValue
|
|
|
- onScanSuccess(codes[0].rawValue)
|
|
|
- return
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- // 单帧失败忽略
|
|
|
- }
|
|
|
- h5RafId = requestAnimationFrame(tick)
|
|
|
- }
|
|
|
- h5RafId = requestAnimationFrame(tick)
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 5. Fallback:jsQR(用 canvas 抽帧识别)
|
|
|
- tipText.value = '正在用 jsQR 识别中…'
|
|
|
+ // 4. 选 QR 识别方案:直接用 jsQR(纯 JS,兼容性最好,iOS Safari 11+ 全支持)
|
|
|
+ // BarcodeDetector 在 iOS Safari 16.4 早期版本有 bug,直接弃用
|
|
|
+ tipText.value = '正在识别中…'
|
|
|
const canvas = document.createElement('canvas')
|
|
|
const ctx = canvas.getContext('2d', { willReadFrequently: true })
|
|
|
if (!ctx) {
|
|
|
+ console.warn('[H5 扫码] canvas 2d 不可用')
|
|
|
tipText.value = '当前浏览器不支持 QR 码识别,请点击下方"手动输入"'
|
|
|
return
|
|
|
}
|
|
|
@@ -170,15 +143,20 @@ async function h5StartBarcodeScanner() {
|
|
|
canvas.width = video.videoWidth
|
|
|
canvas.height = video.videoHeight
|
|
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
|
|
- const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
|
- const code = jsQR(imageData.data, imageData.width, imageData.height, {
|
|
|
- inversionAttempts: 'dontInvert'
|
|
|
- })
|
|
|
- if (code && code.data) {
|
|
|
- h5StopScanner()
|
|
|
- scanResult.value = code.data
|
|
|
- onScanSuccess(code.data)
|
|
|
- return
|
|
|
+ try {
|
|
|
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
|
+ const code = jsQR(imageData.data, imageData.width, imageData.height, {
|
|
|
+ inversionAttempts: 'dontInvert'
|
|
|
+ })
|
|
|
+ if (code && code.data) {
|
|
|
+ console.log('[H5 扫码] 命中:', code.data)
|
|
|
+ h5StopScanner()
|
|
|
+ scanResult.value = code.data
|
|
|
+ onScanSuccess(code.data)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('[H5 扫码] 单帧识别失败', e)
|
|
|
}
|
|
|
}
|
|
|
h5RafId = requestAnimationFrame(tick)
|