更新记录
1.0.0(2026-11-13)
下载此版本
H5 扫码组件:基于 qr-scanner-wechat,支持摄像头实时扫码与相册图片识别,仅适用于 H5 平台,低端机自行测试
平台兼容性
uni-app(3.8.11)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
√ |
- |
- |
- |
- |
- |
- |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| - |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
uni-app x(3.8.11)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| - |
- |
- |
- |
- |
- |
lu-qr-scan-h5
H5 扫码组件,基于 qr-scanner-wechat(OpenCV WASM + 微信自研 QR 检测模型),识别率高、容错性好。支持摄像头实时扫码,可通过 ref 获取相机列表、控制开始/停止,所有参数均可在父组件传入。
仅适用于 H5 平台。组件依赖 DOM(document.createElement)与 navigator.mediaDevices,小程序 / App 端不可用。
特性
- 高识别率:OpenCV WASM + 微信 QR 检测模型,对模糊、破损、反光二维码仍有较好表现
- 默认后置摄像头(
facingMode: environment)
- 图像预处理:灰度 / 对比度 / 亮度 / 模糊可调
- 扫码超时控制,超时视为失败
- 事件统一结构:
{ code, message, data }
- 相机画面宽高可配,默认 100%
安装
pnpm i qr-scanner-wechat
依赖使用 pnpm 安装,不要再用 npm/yarn 重装,否则可能解析不到包。
快速使用
<template>
<view>
<lu-qr-scan-h5
ref="scannerRef"
:view-mode="'original'"
:mirror="false"
:sample-delay="200"
:grayscale="false"
:contrast="100"
:brightness="100"
:blur="0"
:auto-scan="true"
:timeout="30000"
:width="600"
:height="400"
@scan="onScan"
@scan-error="onScanError"
/>
</view>
</template>
<script setup>
import { ref } from "vue";
const scannerRef = ref(null);
function onScan(res) {
// res = { code: 0, message: "ok", data: "二维码文本" }
const text = res?.data;
console.log("扫码结果:", text);
}
function onScanError(e) {
// e = { code: 1001 | 1002 | 2001 | 2003 | 2004, message }
console.error("扫码失败:", e?.code, e?.message);
}
</script>
Props
| 属性 |
类型 |
默认 |
说明 |
viewMode |
String |
'original' |
预览视图:original(原始)/ processed(处理后) |
mirror |
Boolean |
false |
画面镜像 |
sampleDelay |
Number |
100 |
采样间隔 ms,越小扫描越频繁 |
grayscale |
Boolean |
false |
灰度处理 |
contrast |
Number |
100 |
对比度 %(0-1000) |
brightness |
Number |
100 |
亮度 %(0-1000) |
blur |
Number |
0 |
模糊 px(0-10) |
autoScan |
Boolean |
true |
挂载后是否自动开启扫描 |
timeout |
Number |
0 |
扫码超时 ms,0=不限制 |
width |
Number |
0 |
相机画面宽度 rpx,0=100% |
height |
Number |
0 |
相机画面高度 rpx,0=100% |
事件
| 事件 |
触发时机 |
参数 |
@scan |
识别成功 |
{ code: 0, message: "ok", data: "二维码文本" } |
@scan-error |
所有错误统一出口 |
{ code, message } |
@scan-error 状态码
| code |
常量 |
含义 |
1001 |
SCAN_FAILED |
单帧解析失败 |
1002 |
TIMEOUT |
扫码超时 |
2001 |
CAMERA_NOT_SUPPORTED |
环境不支持摄像头(非 H5 / 无 HTTPS) |
2003 |
CAMERA_ERROR |
摄像头打开失败(含权限拒绝) |
2004 |
ENUMERATE_ERROR |
枚举摄像头失败 |
ref 方法(通过 ref 调用)
const scannerRef = ref(null);
scannerRef.value?.start(); // 开始扫码
scannerRef.value?.stop(); // 停止扫码并释放摄像头
const cameras = await scannerRef.value?.loadCameras(); // 获取相机列表
loadCameras() 返回 Promise,始终成功:
- 有摄像头 →
[MediaDeviceInfo, ...](后置排前)
- 无摄像头 / 环境不支持 / 枚举异常 →
[](异常时同时触发 @scan-error)
示例:受控开始/停止 + 加载相机
<template>
<view>
<lu-qr-scan-h5 ref="scannerRef" :auto-scan="false" @scan="onScan" @scan-error="onScanError" />
<button @click="start">开始</button>
<button @click="stop">停止</button>
<button @click="getCameras">加载相机</button>
</view>
</template>
<script setup>
import { ref } from "vue";
const scannerRef = ref(null);
function start() { scannerRef.value?.start(); }
function stop() { scannerRef.value?.stop(); }
async function getCameras() {
const cameras = (await scannerRef.value?.loadCameras()) || [];
if (cameras.length) {
console.log("相机列表:", cameras);
} else {
console.log("未检测到摄像头");
}
}
function onScan(res) { console.log("扫码结果:", res?.data); }
function onScanError(e) { console.error("扫码失败:", e?.code, e?.message); }
</script>
注意事项
- 必须 HTTPS:
getUserMedia 在非安全上下文下不可用
- 首次加载约 2.5MB:WASM + 模型首次使用时下载,建议配合 loading 提示
- uni-app 内置
<video> 组件不支持流预览:组件内部使用 document.createElement('video') 动态挂载,请勿用内置 video 替换
- 页面切后台 / 组件卸载:组件会自动释放摄像头轨道,无需额外处理
- 停止后再开始:
start() 会自动检测摄像头是否已释放并重新打开