更新记录
1.0.0(2026-09-28) 下载此版本
lf-scan 的 uni-app x / UTS 版本,界面重新设计。
-
组件(easycom):App 端 auto 模式跳转插件自带全屏扫码页,custom 模式在当前页面内使用 camera 组件取景,api 模式使用系统扫码页 - UTS 原生能力:Android / iOS 基于 ML Kit 的相册图片识别、短震动、相机权限申请
- 连续扫码、相同内容去重、一维码二次确认与最小长度校验,系统扫码页可疑码型自动重扫
- 自动放大:App 端未识别时在 1x / 2.5x 之间切换,双击取景区域手动放大
- 识别成功震动 / 提示音、闪光灯、相册识别、识别后保存截图
- 相机权限预检与设置页引导,切后台释放相机、回前台自动恢复
- 扫码结果解析:网址 / WiFi / vCard / MECARD / 日程 / 电话 / 短信 / 邮件 / 位置 / 商品条码 / JSON
- Web:getUserMedia + BarcodeDetector,支持 h5Decoder 接入 jsQR / zxing
平台兼容性
uni-app x(4.71)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| √ | - | √ | 16 | - | - |
lf-scan-x 扫码组件(uni-app x / UTS)
lf-scan 的 uni-app x 版本。组件、页面、工具函数全部使用 .uvue / .uts 编写,App 端识别、震动、权限、相册识别由 UTS 原生插件实现,无第三方依赖。
- App(Android / iOS):自带全屏扫码页(
camera组件原生取景,Google ML Kit 识别),一行调用;也可在当前页面内嵌入取景;也可使用系统扫码页 - 鸿蒙 / 微信小程序:系统扫码页
uni.scanCode - Web:浏览器
BarcodeDetector,支持接入自定义解码器(jsQR / zxing 等),支持双指缩放 - 识别准确:默认只启用带校验位的常用一维码,一维码二次确认 + 长度校验,系统扫码页误识别自动重扫
- 反馈可控:震动、提示音(内置音效)开关真实生效
- 稳定:相机权限预检、切后台自动恢复、连续扫码、去重
- 结果解析:网址、WiFi、名片、电话、短信、邮件、地理位置、日程、商品条码、JSON
环境要求
| 项目 | 要求 |
|---|---|
| HBuilderX | 4.71 及以上(camera 组件扫码模式、uni.openAppAuthorizeSetting) |
| 项目类型 | uni-app x(manifest.json 含 uni-app-x 节点) |
| App 运行 | 需制作自定义基座(使用了 UTS 原生插件与 uni-barcode-scanning 模块) |
平台兼容
| 平台 | 自定义界面 | 系统扫码页 | 相册识别 | 说明 |
|---|---|---|---|---|
| App Android | ✅ 插件扫码页 / 页面内取景 | ✅ uni.scanCode |
✅ ML Kit(UTS) | 已在真机验证的主要目标平台 |
| App iOS | ✅ 插件扫码页 / 页面内取景 | ✅ | ✅ ML Kit(UTS) | UTS iOS 部分需自定义基座真机验证 |
| 鸿蒙 | – | ✅ | – | 自定义界面自动回退为系统扫码页 |
| 微信小程序 | – | ✅ | – | 自定义界面自动回退为系统扫码页 |
| Web | ✅ getUserMedia + BarcodeDetector |
– | ✅ | 需 HTTPS;不支持 BarcodeDetector 的浏览器需传入 h5Decoder |
安装
- 插件市场点击「使用 HBuilderX 导入插件」,或将
uni_modules/lf-scan-x复制到项目uni_modules目录 - 组件遵循 easycom 规范,无需 import 和注册,直接使用
<lf-scan-x> - App 端注册扫码页:导入插件时 HBuilderX 会根据
pages_init.json提示合并到pages.json;手动注册时在pages中加入(未注册时自动回退为系统扫码页并在控制台提示):
// #ifdef APP-ANDROID || APP-IOS
{
"path": "uni_modules/lf-scan-x/pages/scan/scan",
"style": {
"navigationStyle": "custom",
"backgroundColorContent": "#000000",
"backgroundColor": "#000000",
"bounces": false
}
}
// #endif
- manifest.json:App 端勾选模块 uni-barcode-scanning(相机组件扫码),这是
camera组件 scanCode 模式的依赖;iOS 在「隐私信息访问的许可描述」中填写相机与相册用途;Android 权限由插件的AndroidManifest.xml自动合并(CAMERA、VIBRATE),示例项目也在 manifest 中显式声明了一遍:
"app-android": {
"distribute": {
"modules": { "uni-barcode-scanning": {} },
"permissions": [
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>"
]
}
},
"app-ios": {
"distribute": {
"modules": { "uni-barcode-scanning": {} },
"privacyDescription": {
"NSCameraUsageDescription": "用于扫描二维码 / 条形码",
"NSPhotoLibraryUsageDescription": "用于从相册选择图片识别二维码",
"NSPhotoLibraryAddUsageDescription": "用于保存扫码截图到相册"
}
}
}
- 制作自定义基座后真机运行(标准基座不包含 UTS 插件与扫码模块)
快速开始
1. 一行接入
<lf-scan-x @success="onSuccess" @fail="onFail" @cancel="onCancel" />
import { LfScanResult, LfScanFail } from '@/uni_modules/lf-scan-x/utils/index.uts'
function onSuccess(res : LfScanResult) {
console.log(res.result, res.scanType, res.parsed?.type)
}
function onFail(err : LfScanFail) {
console.log(err.type, err.errMsg)
}
App 端打开插件扫码页,小程序 / 鸿蒙打开系统扫码页,Web 使用浏览器摄像头。识别成功后触发 success,App 端扫码页自动关闭。
2. 通过 ref 调用、自定义按钮
<lf-scan-x ref="scan" :show-trigger="false" @success="onSuccess" />
<button @click="scan?.start()">扫码</button>
const scan = ref<LfScanXComponentPublicInstance | null>(null)
3. 连续扫码
<lf-scan-x ref="scan" :continuous="true" :continuous-interval="1000" @success="onEach" />
每次识别触发一次 success 并震动 / 播放提示音,扫码页底部实时显示已识别数量与最新内容;识别后等待 continuousInterval 再继续,同一个码停留在框内会按该节奏重复回调,去重由业务层按需处理(或设置 dedupeTime)。点击左上角关闭或调用 stop() 结束,结束时触发 stop。
4. 页面内嵌入(App)
uni-app x 的任意页面都可以放置 camera 组件,因此 custom 模式不再区分 vue / nvue:
<template>
<view style="flex: 1; background-color: #000000">
<lf-scan-x ref="scan" mode="custom" :auto-start="true" :show-trigger="false" safe-area-top="true"
@success="onSuccess" @cancel="goBack" @fail="onFail" />
</view>
</template>
<script setup lang="uts">
import { LfScanResult, LfScanFail } from '@/uni_modules/lf-scan-x/utils/index.uts'
const scan = ref<LfScanXComponentPublicInstance | null>(null)
function onSuccess(res : LfScanResult) { uni.$emit('scan-result', JSON.stringify(res)); uni.navigateBack() }
function goBack() { uni.navigateBack() }
function onFail(err : LfScanFail) { uni.showToast({ title: err.errMsg, icon: 'none' }) }
onUnload(() => { scan.value?.stop() })
</script>
页面建议设置 navigationStyle: custom。组件会自动监听页面的 onPageHide / onPageShow,切后台释放相机、回前台恢复,无需手动调用 pause() / resume()。
5. 系统扫码页
<lf-scan-x mode="api" @success="onSuccess" />
系统扫码页由 uni-app x 内置扫码页提供,其震动与提示音不受 vibrate / sound 控制。App 端关闭系统扫码页不会回调 fail,组件在回到页面后仍无结果时按 cancel 处理。
6. Web 接入自定义解码器
浏览器不支持 BarcodeDetector 时(如 iOS Safari)传入解码函数,以 jsQR 为例:
<lf-scan-x :h5-decoder="decode" @success="onSuccess" />
import jsQR from 'jsqr'
function decode(imageData : any, _ctx : any) : any {
const code = jsQR(imageData.data, imageData.width, imageData.height)
return code != null ? { result: code.data, scanType: 'QR_CODE' } : null
}
签名:(imageData, { width, height, canvas }) => string | { result, scanType } | null,支持 Promise。
识别准确率说明
barCode默认只包含 EAN-13 / EAN-8 / UPC-A / UPC-E / Code128,全部带校验位。ITF、Codabar、Code39、RSS 没有校验位,识别引擎对着二维码、文字、条纹都可能"读出"一串甚至一个字符;需要这些码型时显式传入code39、itf、codabar、rss14、rssexpanded或barCodeAllcamera组件返回所有码型,组件按scanType在结果端过滤,不在范围内的结果直接丢弃verifyBarcode(默认开启):一维码需连续两次读到相同内容、且长度不少于 4 位才返回;二维码自带纠错不受影响- 系统扫码页无法配置码型细节,组件会拦截可疑码型(ITF / Codabar / Code39 / RSS)并自动重扫,最多 2 次
- 遇到识别异常可开启
:debug="true",控制台会输出 camera 识别事件的原始数据;正常使用请关闭
提升识别率的建议
| 做法 | 效果 |
|---|---|
只扫二维码时设置 :scan-type="['qrCode']" |
一维码结果不再参与二次确认,回调更快 |
| 双击取景区域 | App 端放大 1.5 倍,再次双击复位;也可调用 setZoom() |
| 让码占据扫描框的 1/3 以上,一维码保持水平 | ML Kit 对模块过小的码识别率下降 |
| 光线不足时打开闪光灯 | 减少噪点与对焦失败 |
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| mode | string | auto |
auto:App 插件扫码页 / 小程序系统扫码页 / Web 浏览器扫码;api:始终系统扫码页;custom:当前页面内自定义界面(小程序 / 鸿蒙回退为系统扫码页) |
| scanType | string[] | ['qrCode','barCode'] |
码类型,见下表 |
| onlyFromCamera | boolean | false |
系统扫码页仅允许相机 |
| autoZoom | boolean | true |
自动放大。Web:对画面中心区域放大识别;App:未识别时在 1x 与 2.5x 之间自动切换(相机支持时),双击或调用 setZoom() 后停止自动切换 |
| autoCharset | boolean | false |
保留字段(uni-app x 引擎自动识别字符集) |
| barCodeInput | boolean | false |
保留字段 |
| enableAlbum | boolean | true |
允许从相册识别 |
| color | string | #00E5A0 |
主题色:默认按钮、闪光灯激活态、默认扫描框 / 扫描线颜色 |
| frameColor | string | '' |
扫描框颜色,为空时使用 color |
| scanbarColor | string | '' |
扫描线颜色,为空时使用 color |
| title | string | 扫一扫 |
扫码页标题 |
| tip | string | 将二维码 / 条形码放入框内,即可自动扫描 |
提示文字 |
| showHeader | boolean | true |
显示标题栏(含关闭按钮) |
| showFlash | boolean | true |
显示闪光灯按钮 |
| showTrigger | boolean | true |
渲染默认触发按钮 |
| triggerText | string | 扫一扫 |
默认按钮文字 |
| showResult | boolean | true |
连续扫码时在底部显示已识别数量与最新内容 |
| autoStart | boolean | false |
挂载后自动开始 |
| continuous | boolean | false |
连续扫码(自定义界面 / Web) |
| continuousInterval | number | 1000 |
连续扫码两次识别最小间隔 ms |
| dedupeTime | number | 0 |
相同内容去重时间 ms,默认不去重 |
| verifyBarcode | boolean | true |
一维码二次确认与长度校验 |
| vibrate | boolean | true |
识别成功震动(自定义界面 / Web) |
| sound | boolean | true |
识别成功提示音(自定义界面 / Web) |
| soundSrc | string | '' |
自定义提示音地址,为空使用内置音效 |
| saveImage | boolean | false |
识别成功后拍一张取景截图保存到相册(App) |
| parse | boolean | true |
解析内容到 result.parsed |
| permissionTip | boolean | true |
无相机权限时弹窗引导去设置 |
| safeAreaTop | string | auto |
标题栏预留状态栏高度:auto 按页面 navigationStyle 判断,true / false 强制 |
| zIndex | number | 999 |
扫码界面层级 |
| pagePath | string | /uni_modules/lf-scan-x/pages/scan/scan |
App auto 模式跳转的扫码页路径 |
| debug | boolean | false |
控制台输出识别事件的原始数据 |
| h5Decoder | function | null |
Web 自定义解码器 |
| h5Facing | string | environment |
Web 摄像头方向 |
| h5ScanInterval | number | 200 |
Web 解码间隔 ms |
scanType 取值
| 值 | 说明 |
|---|---|
| qrCode | 二维码 |
| barCode | 常用一维码:EAN-13 / EAN-8 / UPC-A / UPC-E / Code128 |
| barCodeAll | 全部一维码(含 Code39 / ITF / Codabar / RSS,误识别率较高) |
| datamatrix / pdf417 / aztec / maxicode | 二维码型(aztec / maxicode 仅自定义界面) |
| ean13 / ean8 / upca / upce / code128 / code93 / code39 / itf / codabar / rss14 / rssexpanded | 精确指定一维码(系统扫码页归并为 barCode) |
Events
| 事件 | 回调参数 | 说明 |
|---|---|---|
| success | LfScanResult |
识别成功 |
| fail | LfScanFail:{ errMsg, type, origin } |
type:permission / unsupported / scan / album / flash / busy |
| cancel | – | 用户取消 |
| start | – | 开始扫码 |
| stop | – | 扫码结束(扫码页关闭、Web 停止、系统扫码页返回) |
| flash-change | boolean |
闪光灯状态变化 |
LfScanResult
{
result: 'https://uniapp.dcloud.net.cn',
scanType: 'QR_CODE', // QR_CODE EAN_13 CODE_128 DATA_MATRIX PDF_417 ...
charSet: 'UTF-8',
path: '', // 图片路径(相册识别 / saveImage 截图)
rawData: '',
source: 'camera', // camera | album | api | web
platform: 'app-android', // app-android | app-ios | app-harmony | web | mp-weixin
timestamp: 1700000000000,
parsed: { type: 'url', url: 'https://uniapp.dcloud.net.cn', raw: '...' }, // parse 为 false 时为 null
imageSaved: null,
imageSaveError: null
}
parsed 解析类型(LfScanParsed)
| type | 字段 |
|---|---|
| url | url、scheme |
| wifi | ssid、password、encryption、hidden |
| vcard / mecard | name、tels[]、emails[]、org、title、url、address、note |
| event | summary、start、end、location、description |
| tel | number |
| sms | number、body |
email、subject、body |
|
| geo | latitude、longitude、altitude |
| product | code、format |
| json | data |
| text | text |
UTS 为强类型,LfScanParsed 包含以上全部字段,未使用的字段为 null。
Methods(通过 ref 调用)
| 方法 | 说明 |
|---|---|
| start() | 开始扫码(别名 startScan()) |
| stop() | 停止并释放相机 / 关闭扫码页(别名 stopScan()),系统扫码页不可用 |
| cancel() | 停止并触发 cancel |
| pause() / resume() | 暂停 / 恢复识别;组件已自动监听页面显示隐藏,一般无需调用 |
| setFlash(boolean) / toggleFlash() | 闪光灯(页面内取景 / Web) |
| setZoom(number, callback?) | 设置缩放倍数(App 页面内取景 / Web),callback 返回实际倍数 |
| chooseImage() | 选择相册图片识别(App / Web) |
| scanImage(path) | 识别本地图片(App / Web) |
| isScanning() | 是否扫码中 |
| getLastResult() / getLastImage() | 上次结果 / 上次保存的图片路径 |
Slots
| 名称 | 作用域参数 | 说明 |
|---|---|---|
| trigger | { scanning } |
自定义触发按钮,通过 ref 调用 start() |
工具函数
import {
parseScanResult, createScanHistory,
checkCameraPermission, showPermissionGuide, openAppSettings,
vibrate, playSound,
LfScanResult, LfScanFail, LfScanParsed
} from '@/uni_modules/lf-scan-x/utils/index.uts'
@/uni_modules/lf-scan-x 根路径指向 UTS 原生插件,导出 lfDecodeImage、lfVibrate、lfRequestCameraPermission、lfCheckCameraPermission,可在自己的页面中直接使用。
FAQ
1. App 端点击「开始扫码」打开的是系统扫码页
扫码页未在 pages.json 注册,按「安装」第 3 步注册后重新运行;控制台会有 [lf-scan-x] 扫码页面 ... 未注册 提示。
2. 自定义界面黑屏 / 没有画面
确认 manifest.json 勾选了 uni-barcode-scanning 模块并重新打包自定义基座;确认系统设置中已允许相机;开启 :debug="true" 查看控制台的 camera error 事件。
3. 相册识别提示「未识别到二维码 / 条形码」
图片中的码需清晰且不过小;只在 scanType 范围内查找,多个码时返回第一个符合的结果。
4. 震动无效 Android 需要 VIBRATE 权限(插件已声明,需重新打包基座);iOS 使用触感反馈,静音模式或关闭系统触感时不会震动。
5. Web 提示不支持
需要 HTTPS;iOS Safari 等不支持 BarcodeDetector 的浏览器请传入 h5Decoder。
更新日志
见 changelog.md。
许可证
MIT

收藏人数:
下载插件并导入HBuilderX
下载示例项目ZIP
赞赏(0)
下载 709
赞赏 7
下载 12644592
赞赏 1952
赞赏
京公网安备:11010802035340号