更新记录
1.0.80(2026-09-22)
- 修复 Android 识别 GS1-128 条形码时可能把
]C1码制标识一并返回的问题;现在与 iOS 一样返回实际业务内容,例如705440893。无需修改调用代码;升级后需要重新制作并安装 Android 自定义基座或重新打包 App。
1.0.79(2026-09-21)
- 调整 Android 接入环境说明:当前 CameraX 1.6.1 要求
compileSdk 36,Android 云打包请使用 HBuilderX 5.09 及以上;HBuilderX 5.07 / 5.08 的云打包环境为compileSdk 35,无法打包当前 Android 版本。这是打包环境要求,不表示手机必须使用 Android 16,也不要求将项目minSdkVersion或targetSdkVersion改为 36。本项仅更新说明和最低版本声明,不改变 Android 源码及原生依赖。
1.0.78(2026-09-21)
- 修复使用 HBuilderX 5.07 进行 iOS 云打包时,部分数字状态比较可能触发
ambiguous use of operator '!='并导致编译失败的问题。无需修改调用代码或项目配置;升级后需要重新制作并安装 iOS 自定义基座或重新打包 App,Android 与 Harmony 原有行为不变。
平台兼容性
uni-app(4.84)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.84)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | √ | √ | √ | - |
lizhao-scan-pro
介绍
lizhao-scan-pro 是一个面向 uni-app / uni-app x 的原生扫码 UTS 插件。既可以通过 API 拉起原生全屏扫码页,也可以在 .nvue/.uvue 页面使用 <lizhao-scan-pro /> 原生预览组件,完全自由布局扫码框、按钮、提示和业务结果 UI。
功能特色
| 特色功能 | 能解决什么问题 | 相关配置 |
|---|---|---|
| 扫码自动抓图 | 扫到快递条码时自动保留相机画面,拿到图片即可上传后端识别 | captureOnSuccess |
| 原生全屏扫码 | 不依赖页面组件拼装,直接使用平台原生相机能力 | startScan |
| 多码制识别 | 支持二维码、Data Matrix、PDF417、Code39、Code128、EAN、UPC 等常见码制 | formats |
| 同帧多码返回 | 一张画面中多个码可一次性回传 | returnAllResults |
| 连续扫码 | 适合盘点、核销、批量入库等高频扫码场景 | continuous、continuousIntervalMs |
| 多码人工选择 | Android / iOS 全屏支持跨帧补扫;稳定多码后冻结画面,由用户确认需要的结果 | enableMultiCodeSelection |
| 近距聚焦增强 | 改善细小码、设备铭牌、近距离扫码体验 | nearFocusLock、zoomRatio |
| 远码自动拉近 | 检测到远处小码时逐步放大辅助识别,显式模式默认关闭 | autoZoom(Android / iOS) |
| 密集二维码补救 | Android 普通全屏 QR/all 持续未识别时,自动尝试候选拉近与高清识别 | 无需新增参数 |
| 相册识别 | 支持从本地图片中识别码 | enableAlbum、pickImageAndScan |
| 扫码页自定义 | 支持扫码框、遮罩、扫描线、文案、图片图标和布局偏移配置 | scanFrameStyle、uiTextConfig、uiImageConfig、uiLayoutConfig |
| 完全自由布局 | 原生预览嵌入 .nvue/.uvue,页面自由编写扫码框、按钮和业务区 |
<lizhao-scan-pro /> |
插件底层按平台走原生能力:Android 使用 CameraX 与 Google ML Kit,iOS 使用 AVFoundation + Vision,Harmony 使用 CameraKit + Scan Kit。三端普通扫码和抓图扫码都使用插件原生全屏界面;Web 和小程序会返回明确的不支持错误。
适合哪些场景
| 场景 | 推荐能力 | 说明 |
|---|---|---|
| 快递面单识别 | captureOnSuccess、uni.uploadFile |
无需手动拍照,扫码成功后拿到图片并上传自己的后端 |
| 普通扫码 | startScan |
打开全屏扫码页,识别成功后回调结果 |
| 商品条码/库存盘点 | formats、minBarcodeLength、continuous |
限制条码类型、过滤短码、连续返回结果 |
| 一屏多个码 | returnAllResults |
同一帧内返回多条识别结果,适合货架、票据、批量标签 |
| 一屏多个码由用户选择 | enableMultiCodeSelection |
Android / iOS 单次全屏扫码和嵌入式组件支持冻结画面后由用户确认要返回的码 |
| 相册识别 | enableAlbum、pickImageAndScan |
支持从图片中识别二维码或条形码 |
| 近距离扫码 | nearFocusLock、zoomRatio |
适合约 5cm 近距标签、设备码、细小条码 |
| 品牌化扫码页 | scanFrameStyle、uiTextConfig、uiImageConfig、uiLayoutConfig、uiVisibilityConfig |
自定义扫码框、文案、图标、按钮位置和元素显隐 |
| 完全自由布局 | <lizhao-scan-pro /> |
原生预览嵌入客户页面,扫码框、按钮与业务 UI 全部由页面决定 |
| 页面状态联动 | pauseScan、resumeScan、stopScan、destroyScanner |
页面隐藏、返回、销毁时控制相机资源 |
下载与导入
- 在插件市场选择“使用 HBuilderX 导入插件”,导入到自己的 uni-app 或 uni-app x 项目。
- 保留完整的
uni_modules/lizhao-scan-pro目录和插件名称。 - 在页面脚本中从插件根目录导入:
Android 云打包请使用 HBuilderX 5.09 及以上。插件当前使用 CameraX 1.6.1,该依赖要求 compileSdk 36;HBuilderX 5.07 / 5.08 的云打包环境使用 compileSdk 35,会在依赖检查阶段失败。这里要求的是打包环境版本,不表示手机必须是 Android 16,也不要求把项目的 minSdkVersion 或 targetSdkVersion 改为 36。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
uni-app 使用普通页面脚本,uni-app x 使用 <script setup lang="uts">。两者调用同名 API,下面分别给出基础示例。
完整示例位于插件的 uni_modules/lizhao-scan-pro/example/ 目录下,按项目类型选择对应子目录:
- uni-app:
example/uniapp/,API 调用见 scan.vue,自由布局见 free-layout.nvue。 - uni-app x:
example/uniappx/,API 调用见 index.uvue,自由布局见 free-layout.uvue。
5 分钟跑通:用 API 打开扫码页
默认推荐使用 API 调用。 通过 startScan() 即可打开带相机预览、扫码框和操作按钮的全屏扫码页,不需要自己编写扫码组件。先跑通下面的基础示例,再按业务需要添加连续扫码、多码选择、相册或样式配置。
uni-app:按钮点击后打开扫码
把下面内容放到一个已注册的 .vue 页面。点击按钮、对准二维码,识别后会显示扫码内容。
<template>
<view>
<button @tap="openScanner">开始扫码</button>
<text>{{ scanText }}</text>
</view>
</template>
<script>
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
export default {
data() {
// 保存本次识别到的内容。
return { scanText: '' }
},
onUnload() {
// 页面销毁时释放该页面的扫码会话。
LizhaoScanPro.destroyScanner({ scannerId: 'main' })
},
methods: {
openScanner() {
LizhaoScanPro.startScan({
scannerId: 'main',
onResult: (res) => {
const first = res.results[0]
if (first != null) this.scanText = first.value
},
onError: (err) => {
// 取消扫码无需提示为故障。
if (err.errCode === 9010008) return
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
}
}
}
</script>
uni-app x:相同 API,使用 UTS 脚本
<template>
<view>
<button @tap="openScanner">开始扫码</button>
<text>{{ scanText }}</text>
</view>
</template>
<script setup lang="uts">
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
// 保存本次识别到的内容。
const scanText = ref<string>('')
function openScanner(): void {
LizhaoScanPro.startScan({
scannerId: 'main',
onResult: (res) => {
const first = res.results[0]
if (first != null) scanText.value = first.value
},
onError: (err) => {
if (err.errCode === 9010008) return
uni.showToast({ title: err.errMsg, icon: 'none' })
}
})
}
onUnload(() => {
LizhaoScanPro.destroyScanner({ scannerId: 'main' })
})
</script>
读取结果用 res.results[0].value。 results 是数组,每一项的 value 是识别内容,format 是码制。默认单次扫码;基础调用正常后,再增加下面需要的配置。
核心配置
首次使用只需关注这些参数。未填写的配置使用默认值,详细字段放在后面的查询表中。
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| formats | Array<ScanFormat> | 否 | 限制需要识别的码制 | ["all"] |
all / qrCode / code128 / dataMatrix / 其他支持码制 |
| continuous | boolean | 否 | 是否持续返回扫码结果 | false |
true / false |
| returnAllResults | boolean | 否 | 是否返回同一帧的全部有效结果 | false |
true / false |
| captureOnSuccess | boolean | 否 | Android / iOS / Harmony 全屏扫码成功自动保存完整 JPG,成功回调附带图片路径与尺寸;不可与多码点击选择组合,不用于相册识别 | false |
true / false |
| enableMultiCodeSelection | boolean | 否 | 单次扫码时是否允许用户从多个候选中选择;Harmony 当前不支持 | false |
true / false |
| enableAlbum | boolean | 否 | 全屏扫码页是否提供相册入口 | false |
true / false |
| nearFocusLock | boolean | 否 | 是否启用近距辅助锁焦 | false |
true / false |
接入方式选择
| 你的需求 | 推荐方式 | 阅读位置 |
|---|---|---|
| 普通扫码、核销、录入 | 默认推荐:startScan(options) |
快速开始、模块一 |
| 连续录入、同帧批量返回 | 继续使用 startScan(options),增加配置 |
模块二 |
| 从多个码中确认一个 | 继续使用 startScan(options),启用人工选择 |
模块三 |
| 从图片中识别 | pickImageAndScan(options) |
模块四 |
| 改文案、按钮、颜色或扫码框 | 继续使用全屏 API 的样式配置 | 模块五 |
| 整个页面布局和业务区都自己编写 | 进阶使用嵌入式组件 | 后文“完全自由布局组件” |
从基础到进阶:按业务模块使用
以下 API 示例放在页面按钮事件或业务方法中调用;一次只打开一个扫码会话。可以把所需配置合并到上面的 openScanner,保留自己的结果和错误处理。
模块一:只识别业务需要的码
适合商品条码、设备标签或只允许二维码的入口。指定 formats 后,只接收对应码制的结果。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
// 只识别二维码和 Code128,减少无关码制干扰
formats: ['qrCode', 'code128'],
onResult(res) {
const first = res.results[0]
if (first != null) {
console.log('命中指定码制:', first.value)
}
}
})
formats 中使用 qrCode 表示二维码,code128 表示 Code128,ean13 表示 EAN-13;不确定码制时先保留默认的 ['all']。
模块二:连续扫码和批量返回
适合入库、盘点等需要持续扫描的场景。下面每次最多返回当前画面中全部有效结果,回调间隔至少 500 毫秒。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
// 开启连续扫码,适合仓储、盘点、核销等连续作业
continuous: true,
// 两次回调至少间隔 500ms,业务侧也建议继续做去重
continuousIntervalMs: 500,
// 同一帧出现多个码时返回全部识别结果
returnAllResults: true,
onResult(res) {
res.results.forEach((item) => {
console.log('批量结果:', item.value, item.format)
})
}
})
只需每次返回一个码时,去掉 returnAllResults 即可。continuousIntervalMs 控制回调频率,不能代替业务去重;同一商品是否允许重复入库,应由业务处理。Harmony 的连续扫描和批量返回差异见后文平台说明。
模块三:多个码中,由使用者选择一个
适合一张票据或货架上有多个码,但只需要确认其中一个的场景。开启后,Android / iOS 单次全屏扫码会显示可点击标记。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
continuous: false,
enableMultiCodeSelection: true,
onResult(res) {
console.log('用户选择的码:', res.results[0].value)
}
})
Android 单次全屏扫码会在整个可见预览范围收集结果,不限于界面显示的扫码框。首个可靠二维码出现后先跨帧收集,并最多进行两次高清补识别。若仍检测到独立的第二个二维码区域,但尚未读出内容,会保持预览继续识别,不自动选中第一个码;可以调整距离、角度或清晰度,也可随时关闭。短暂漏检不会立即结束,确认画面只剩单码后恢复单码返回;从未发现其他码的普通单码仍按原流程返回。多个有效码读出后冻结画面供点选,未解码区域不会作为可选结果。iOS 单次全屏扫码会在首个结果后进行最多约 3 秒的有界聚合,并在窗口内使用系统 Vision 补充带位置的多码结果;两个候选稳定后立即冻结,到期仍只有一个候选时只返回一次。切换连续扫码或进入相册时恢复实时预览。
Android 优化继续使用插件已有的 Google ML Kit,iOS 使用系统 Vision;不引入华为扫码 SDK 或其他新原生依赖。无需修改现有配置和结果回调;升级后需要重新制作并安装 Android / iOS 自定义基座。
与 returnAllResults=true 同时设置时,人工选择优先于 returnAllResults,最终只返回选中的一条结果。需要连续批量录入时使用模块二,不要开启人工选择。
模块四:从相册图片中识别
如果扫码页需要一个“相册”按钮,在 startScan 中加上 enableAlbum: true 即可,识别结果仍从同一个 onResult 返回。
如果业务入口就是“识别图片”,直接使用下面的 API,无需先调用 startScan:
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.pickImageAndScan({
scannerId: 'album',
onResult(res) {
const first = res.results[0]
if (first != null) console.log('图片识别结果:', first.value)
},
onError(err) {
if (err.errCode === 9010008) return
console.error('图片识别失败:', err.errMsg)
}
})
取消选图返回 9010008,图片中没有可识别码时返回 9010006。Android 相册识别支持 returnAllResults=true;iOS / Harmony 相册识别仍返回单条结果。Harmony 普通扫码页右上角可按 enableAlbum 显示相册入口;抓图模式不显示相册入口。
模块五:调整全屏扫码页外观
适合把扫码页改成自己的品牌风格。改扫码框、文案和按钮,仍然推荐使用 API,不需要改用组件。以下视觉配置用于 Android / iOS / Harmony 全屏扫码。
先改扫码框和文案
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
scanFrameStyle: {
// 调整扫码框宽高和位置,适配业务视觉
widthRatio: 0.72,
heightRatio: 0.5,
topRatio: 0.2,
cornerRadius: 22,
borderColor: '#88FFFFFF',
cornerColor: '#FFFF6B6B'
},
uiTextConfig: {
// 自定义提示文案和按钮文案
tipText: '请对准二维码或条形码',
closeText: '关闭',
albumText: '相册',
torchOffText: '打开手电筒',
torchOnText: '关闭手电筒'
},
onResult(res) {
const first = res.results[0]
if (first != null) {
console.log('扫码结果:', first.value)
}
}
})
再按需要隐藏元素、修改多码标记
下面只显示必要操作与多码选择标记。启用相册需额外设置 enableAlbum=true;显示“单次/连续”切换按钮需设置 showContinuousToggle=true。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
enableMultiCodeSelection: true,
uiVisibilityConfig: {
showMaskOverlay: false,
showScanFrameBorder: false,
showScanFrameCorners: false,
showScanLine: false,
showTip: false,
showTorchButton: false,
showContinuousButton: false
},
multiCodeMarkerStyle: {
backgroundColor: '#16A34A',
foregroundColor: '#FFFFFF',
borderColor: '#FFFFFF',
size: 48,
cornerRadius: 24
},
onResult(res) {
console.log('扫码结果:', res.results)
},
onError(err) {
console.error('扫码失败:', err.errMsg)
}
})
使用自己的图片图标、调整位置
先在项目中放入 static/scan-close.png,再调用以下示例。无需替换插件源码。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
uiTextConfig: { closeText: '返回' },
uiImageConfig: {
close: { src: '/static/scan-close.png', width: 20, height: 20 }
},
uiLayoutConfig: {
close: { containerOffset: { x: 4, y: 4 } }
},
onResult(res) {
console.log('扫码结果:', res.results)
},
onError(err) {
console.error('扫码失败:', err.errMsg)
}
})
x 为正向右、y 为正向下;Android 按 dp、iOS 按 pt 处理。彩色图片通常不传 tintColor,单色图标需要统一颜色时再配置。
远处小码自动拉近
Android / iOS 可通过 autoZoom: true 开启显式远码模式。将目标放在画面中央,检测到小码候选后逐步拉近;iOS 在画面持续稳定、尚未检测到码框时,还会试探拉近一次,最高 1.5 倍。无需设置固定放大倍率,识别结果仍通过原有 onResult 返回。Android 普通全屏 QR/all 扫码还带有独立的密集二维码补救,即使未开启该参数,也可能在连续发现稳定未解码候选时受限拉近。
import { startScan } from '@/uni_modules/lizhao-scan-pro'
startScan({
scannerId: 'main',
formats: ['qrCode'],
autoZoom: true,
onResult(res) {
console.log('识别结果:', res.results)
},
onError(err) {
console.error('扫码失败:', err.errMsg)
}
})
内嵌组件使用 :auto-zoom="true",uni-app 的 .nvue 与 uni-app x 的 .uvue 均支持。完整示例的扫码配置区和自由布局页均提供默认关闭的“远码自动拉近”开关。
- 未传或设为
false时关闭显式远码模式;Android 普通全屏 QR/all 的密集二维码补救仍可能受限拉近。该补救不用于内嵌组件、近距锁焦、多码人工选择或混合指定码制。仅实时相机生效,相册识别不使用该配置;鸿蒙暂不支持此能力。 - 自动拉近遵循
formats:iOS 可使用系统返回的 QR、Aztec、Data Matrix、PDF417 及一维条形码候选。只识别 QR 时设置['qrCode'],只识别 Code128 时设置['code128'];需要多种码制时传入对应数组,或保留['all']。 zoomRatio作为起始倍率,自动拉近最高为 4 倍且不超过设备能力,不会主动缩小。手动设置倍率或点击聚焦后,本次扫码停止自动调整,重新开始扫码才恢复。- Android / iOS 在小码候选稳定出现后分步平滑拉近,每一步约半秒,并重新检查目标位置和相机实际倍率。尽量将码保持在画面中央,边缘目标会限制拉近幅度以避免移出画面。
- iOS 尚无有效候选时,独立观察实时画面的稳定性,持续稳定约 0.65 秒、至少三次有效观察后,可先试探拉近一次,绝对倍率不超过 1.5 倍;稳定观察不再等待完整的后备检测。画面移动、对焦中或画面缺乏纹理时重新等待,实际启动时间仍受设备和画面影响。试探后仍无码框则保持倍率,找到码框后继续跟踪;暂停恢复不会重复试探,已识别或已按候选拉近的会话也不再试探。
- iOS 单次扫码时,同一标签上相邻的小码可按一组逐步拉近,并保留整组的显示范围;分散且无法确定目标时等待重新对准。
- iOS 在系统已发现有效码框、尚未读出文字时也可开始拉近;扫码结果仍只在成功识别内容后返回。
- 开启
nearFocusLock或enableMultiCodeSelection时优先保留这两种模式,自动拉近不生效。暂停、退后台或选择相册时停止自动调整。 - 距离过远、反光、画面不稳定或摄像头能力不足仍可能无法拉近或识别,实际效果以设备为准。升级后需重新制作并安装对应平台自定义基座或重新打包。
模块六:识别近距离小码和 Data Matrix
适合设备铭牌、小标签等场景。可启用近距辅助聚焦并设置初始缩放;识别效果仍取决于相机焦距、画面清晰度和反光情况。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
// 开启近距辅助聚焦,实际距离按设备对焦能力调整。
nearFocusLock: true,
// 预设缩放倍率,帮助小码在画面中更清晰
zoomRatio: 1.8,
// 固定码长业务可过滤明显错误的短结果
minBarcodeLength: 8,
onResult(res) {
const first = res.results[0]
if (first != null) {
console.log('近距识别结果:', first.value)
}
}
})
minBarcodeLength 只用于一维条码最小长度过滤,按实际业务长度填写。二维码、Data Matrix 等二维格式不受该字段影响。
识别 Data Matrix(DM)时,改用下列配置:
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'dm',
formats: ['dataMatrix'],
nearFocusLock: true,
onResult(res) {
console.log('DM 识别结果:', res.results)
},
onError(err) {
console.error('DM 识别失败:', err.errMsg)
}
})
Android 支持反色 DM 识别增强,但不能保证所有材质、打标质量或光照下都能识别。让码清晰地位于画面中心,再根据实际标签调整距离和补光。
模块七:控制扫描、手电和缩放
适合业务需要暂停、继续或结束扫描的场景。控制已有会话时,scannerId 必须和打开时一致;下面函数在扫码会话已经创建后按需调用。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
// 暂停与继续:例如业务弹层显示和关闭时调用。
function pauseScanner() {
LizhaoScanPro.pauseScan({ scannerId: 'main' })
}
function resumeScanner() {
LizhaoScanPro.resumeScan({ scannerId: 'main' })
}
// 结束扫码:业务完成或主动退出时调用。
function closeScanner() {
LizhaoScanPro.stopScan({ scannerId: 'main' })
}
Android / iOS 可通过 setTorchEnabled({ scannerId: 'main', enabled: true }) 打开手电,通过 setZoomRatio({ scannerId: 'main', zoomRatio: 1.8 }) 调整缩放;全屏扫码页本身也提供相应操作。页面销毁时使用 destroyScanner({ scannerId: 'main' }) 释放资源。
模块八:监听扫码页状态
适合需要知道扫码页何时显示、关闭或发生模式切换的进阶业务。仅取得扫码内容时,使用 onResult 即可。
import * as LizhaoScanPro from '@/uni_modules/lizhao-scan-pro'
LizhaoScanPro.startScan({
scannerId: 'main',
overlayConfig: { enabled: true },
onResult(res) {
console.log('扫码结果:', res.results)
},
onError(err) {
console.error('扫码失败:', err.errMsg)
},
onOverlayEvent(event) {
console.log('扫码页状态:', event.type, event.payload)
}
})
onOverlayEvent 必须配合 overlayConfig.enabled=true 才会触发。overlayConfig 用于事件信息传递,不会加载网页,也不能用它创建 H5 扫码界面。
模块九:扫码成功后自动抓图并上传识别
适用于快递面单、收货核验等流程:扫描条码的同时保留完整相机画面,再把图片上传后端识别文字。只需显式设置 captureOnSuccess: true,全程无需点击拍照。
Android / iOS / Harmony 全屏 API 使用同一套参数和返回字段。Harmony 从 1.0.74 起支持,需 HarmonyOS 5.0(API 12)及以上;嵌入式抓图仍仅支持 Android / iOS。
该开关默认 false,不传时保持原有扫码行为。开启后,插件先保存与本次识别对应的视频帧 JPG,再通过 onResult 返回条码和图片路径。图片包含完整相机画面,不含按钮、遮罩等页面 UI;不自动上传、不自动写入相册。视频帧分辨率受设备及相机配置影响,请用实际面单确认文字清晰度。
先在原有示例中体验
打开 uni-app 原示例 scan.vue 或 uni-app x 原示例 index.uvue,使用新增的“扫码自动抓图”区域:
- 打开“识别成功时保存图片”,关闭“连续扫码”和“多码点击选择”,点击原有“打开原生扫码”。
- 对准面单条码,成功后自动回到本页,显示图片、路径与像素尺寸。
- 在原页填写自己的 HTTPS 上传接口。开启“抓图后自动上传”,下次扫码成功后会自动上传;也可点击“上传 / 重试当前图片”。这是上传操作,无需手动拍照。
- 后端识别通过后显示“可以进入下一步”;HTTP、网络或业务失败时显示原因并保留图片供重试。示例不内置可用后端,也不会将图片发往作者服务器。
uni-app:图片路径直接用于文件上传
将以下方法放入现有页面脚本,并从按钮调用 scanAndUpload。把接口地址换成自己的服务地址;需要鉴权时使用业务系统当前登录态。
import { startScan } from '@/uni_modules/lizhao-scan-pro'
// 改成自己的后端;后端接收 multipart/form-data 的 file 文件字段。
const uploadUrl = 'https://your-api.example.com/parcel/recognize'
function scanAndUpload() {
startScan({
scannerId: 'parcel',
captureOnSuccess: true,
continuous: false,
enableAlbum: false,
onResult: (res) => {
if (!res.imagePath || res.results.length === 0) return
// 传文件路径即可,不要把本地路径作为普通 JSON 发给服务器。
uni.uploadFile({
url: uploadUrl,
filePath: res.imagePath,
name: 'file',
formData: {
barcode: res.results[0].value,
requestId: res.scannerId + '-' + res.timestamp + '-' + res.frameIndex
},
timeout: 30000,
// 如需鉴权:header: { Authorization: 'Bearer ' + 业务登录令牌 }
success: (response) => {
if (response.statusCode < 200 || response.statusCode >= 300) {
uni.showToast({ title: '上传失败 HTTP ' + response.statusCode, icon: 'none' })
return
}
try {
const body = JSON.parse(response.data)
// 这里按下文示例响应判断,请改成你自己的后端协议。
if (body != null && body.code === 0 && body.data != null && body.data.accepted === true) {
console.log('后端识别通过,执行下一步', body.data)
// 在这里更新业务数据或跳转页面。
} else {
uni.showToast({ title: '后端未确认通过,请核对面单', icon: 'none' })
}
} catch (error) {
uni.showToast({ title: '后端返回格式异常', icon: 'none' })
}
},
fail: (error) => {
console.error('上传失败,保留图片后可重试', error.errMsg)
}
})
},
onError: (error) => {
console.error('扫码或抓图失败', error.errCode, error.errMsg)
}
})
}
// 页面卸载时调用 destroyScanner({ scannerId: 'parcel' });上传任务的中止和重试见完整原页示例。
uni-app x:用 UTS 读取图片和后端 JSON
在原有 <script setup lang="uts"> 中使用相同参数,图片仍直接交给 uni.uploadFile:
import { startScan, ScanFrameResult, ScanFail } from '@/uni_modules/lizhao-scan-pro'
function scanAndUpload() : void {
startScan({
scannerId: 'parcel',
captureOnSuccess: true,
continuous: false,
enableAlbum: false,
onResult: (res : ScanFrameResult) => {
const path = res.imagePath ?? ''
if (path.length == 0 || res.results.length == 0) return
uni.uploadFile({
url: 'https://your-api.example.com/parcel/recognize', // 替换为自己的接口。
filePath: path,
name: 'file',
formData: {
barcode: res.results[0].value,
requestId: res.scannerId + '-' + res.timestamp.toString() + '-' + res.frameIndex.toString()
},
timeout: 30000,
success: (response : UploadFileSuccess) => {
if (response.statusCode < 200 || response.statusCode >= 300) {
console.error('上传失败 HTTP', response.statusCode)
return
}
try {
const body = JSON.parseObject(response.data)
const data = body?.getJSON('data')
if (body?.getNumber('code') == 0 && data?.getBoolean('accepted') == true) {
console.log('后端识别通过,执行下一步', data)
// 在这里更新业务数据或跳转页面。
} else {
console.warn('后端未确认通过,请核对面单')
}
} catch (error) {
console.error('后端返回格式异常', error)
}
},
fail: (error : UploadFileFail) => { console.error('上传失败,可重试', error.errMsg) }
})
},
onError: (error : ScanFail) => { console.error('扫码或抓图失败', error.errCode, error.errMsg) }
})
}
后端怎样接收
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| file | 文件 | 是 | JPG 二进制,对应 uni.uploadFile.name;若后端字段叫 image,请同步修改 name |
无 | 无 |
| barcode | string | 是 | 扫码结果内容,通过 formData 传递 | 无 | 无 |
| requestId | string | 否 | 同一张图片重试保持相同值,后端可用来避免重复处理 | 无 | 无 |
以下仅是示例约定的响应格式,插件不限定后端技术栈或业务协议:
{ "code": 0, "data": { "accepted": true, "trackingNo": "EXAMPLE123" } }
uni.uploadFile 会以文件表单上传;不要手动设置 Content-Type: application/json 或遗漏文件边界,也不必转换成 base64。success 表示收到了上传响应,还要检查 HTTP 状态码并解析字符串 response.data,再判断业务是否通过。complete 只用于解除忙碌状态、释放任务,不表示后端识别成功。完整示例还包含上传进度、页面卸载中止、失败重试。API 细节见 uni-app 上传文件 与 uni-app x 上传文件。
嵌入式与连续扫码
在现有 <lizhao-scan-pro /> 上设置 :capture-on-success="true",其 scan 事件也返回同样的三个图片字段,沿用上述上传方法即可。
原页上传演示采用单次扫码,便于一单一图地等待后端结果。插件开启 continuous: true 时仍可抓图;业务应使用 pauseScan/resumeScan(组件使用实例 pause/resume)控制上传期间的扫码,并自行处理并发、失败重试与后端幂等,不能只靠回调间隔防止重复业务处理。captureOnSuccess 不支持与 enableMultiCodeSelection 同时开启,也不用于 pickImageAndScan;相册识别请沿用原接口且不传该属性。
API 用途速查
| 模块 | 适用业务 | 常用方法 | 使用结果 |
|---|---|---|---|
| 全屏扫码 | 普通扫码、核销、连续录入 | startScan |
从 onResult 取得识别结果 |
| 相册识别 | 图片、截图中的码 | pickImageAndScan |
选图后返回识别结果 |
| 会话控制 | 暂停、继续、主动结束 | pauseScan / resumeScan / stopScan |
控制指定扫描器 |
| 相机与规则 | 手电、缩放、动态码制 | setTorchEnabled / setZoomRatio / setScanFormats |
调整正在使用的扫描器 |
| 资源释放 | 页面销毁、业务结束 | destroyScanner |
释放指定扫描器 |
| 业务事件 | 监听页面状态、传递业务消息 | postOverlayMessage / onOverlayEvent |
收到状态或 nativeMessage 事件 |
| 本地诊断 | 排查 iOS 扫码问题 | getDebugTrace / clearDebugTrace / getCrashReports / clearCrashReports |
读取或清理本地记录;其他平台返回空数组或不执行操作 |
参数说明(ScanOptions)
以下是全屏扫码和相册 API 的配置查询表,不需要一次填完。回调单独见后文;嵌入式组件属性见进阶部分。
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| scannerId | string | 否 | 扫描器 ID | default |
任意非空字符串 |
| formats | Array<ScanFormat> | 否 | 识别格式列表 | ["all"] |
all / qrCode / aztec / codabar / code39 / code93 / code128 / dataMatrix / ean8 / ean13 / itf / pdf417 / upcA / upcE |
| minBarcodeLength | number | 否 | 一维条码最小长度过滤(Android 相机扫码 / 相册识别、iOS 相机扫码;Harmony 回调前过滤);固定码长业务建议传实际位数 | 0 |
大于 0 的数值 |
| returnAllResults | boolean | 否 | 是否返回同一帧内全部识别结果(默认保持历史行为:每帧仅返回一个优先结果) | false |
true / false |
| captureOnSuccess | boolean | 否 | Android / iOS / Harmony 全屏扫码成功自动保存完整 JPG,成功回调附带图片路径与尺寸;不可与多码点击选择组合,不用于相册识别 | false |
true / false |
| enableMultiCodeSelection | boolean | 否 | Android / iOS 单次全屏扫码识别到多个码时显示点击选择标记并冻结当前画面;仅 continuous=false 生效;Harmony 当前不支持,传 true 返回 9010009 |
false |
true / false |
| continuous | boolean | 否 | 是否连续扫码 | false |
true / false |
| continuousIntervalMs | number | 否 | 连续扫码最小回调间隔(ms);仅 continuous=true 生效 |
0 |
大于等于 0 的数值 |
| showContinuousToggle | boolean | 否 | 是否在 Android / iOS / Harmony 原生扫码全屏界面显示“单次/连续”切换按钮 | false |
true / false |
| enableAlbum | boolean | 否 | 是否在原生扫码全屏界面右上角显示相册入口(仅 startScan 生效) |
false |
true / false |
| enableTorch | boolean | 否 | 是否启用闪光灯 | false |
true / false |
| zoomRatio | number | 否 | 缩放倍率 | 1 |
大于 0 的数值 |
| autoZoom | boolean | 否 | 显式远码自动拉近,仅 Android / iOS 实时扫码;设为 false 不关闭 Android 默认全屏 QR/all 的密集二维码补救 |
false |
true / false |
| nearFocusLock | boolean | 否 | 是否启用近距锁焦模式(Android / iOS);开启后点击聚焦会优先应用近距辅助缩放,适合约 5cm 场景 |
false |
true / false |
| showScanFrame | boolean | 否 | 是否显示红色扫码角框与中间透明框遮罩;传 false 时隐藏角框和遮罩仅保留扫描线 |
true |
true / false |
| showMaskOverlay | boolean | 否 | 是否显示扫码页黑色遮罩层;仅控制黑色遮罩显隐,不影响扫码框、扫描线、提示文案与操作按钮 | true |
true / false |
| scanFrameStyle | ScanFrameStyle | 否 | Android / iOS / Harmony 扫码框样式配置;支持区域大小、圆角、顶角显隐与颜色定制 | null |
widthRatio / heightRatio / topRatio / cornerRadius / showCorners / borderColor / cornerColor |
| scanLineColor | string | 否 | 扫描线颜色 | #FF3B30 |
#RRGGBB / #AARRGGBB |
| tipText | string | 否 | 提示文案 | 请将二维码/条形码放入框内 |
任意字符串 |
| uiTextConfig | ScanUiTextConfig | 否 | 扫码页文案/图标配置,支持提示文案与“关闭/相册/手电”按钮图标文案自定义 | null |
tipIcon / tipText / closeIcon / closeText / albumIcon / albumText / torchIcon / torchOnText / torchOffText / torchUnsupportedText |
| uiImageConfig | ScanUiImageConfig | 否 | 扫码页图片图标配置(提示区/关闭/相册/手电),可与 uiTextConfig 组合使用 |
null |
tip / close / album / torchOn / torchOff / torchUnsupported |
| uiLayoutConfig | ScanUiLayoutConfig | 否 | 扫码页布局偏移配置,支持 close/album/continuous/torch/tip 的容器+图标+文字三层独立偏移 |
null |
close / album / continuous / torch / tip |
| uiVisibilityConfig | ScanUiVisibilityConfig | 否 | Android / iOS / Harmony 全屏扫码页元素显隐配置;既有功能开关先允许,本配置再进一步隐藏;showFocusIndicator 当前仅 Android / iOS 生效 |
null |
showCloseButton / showAlbumButton / showTorchButton / showContinuousButton / showTip / showFocusIndicator / showMaskOverlay / showScanFrameBorder / showScanFrameCorners / showScanLine |
| multiCodeMarkerStyle | ScanMultiCodeMarkerStyle | 否 | Android / iOS 多码点击标记颜色、尺寸和圆角 | null |
backgroundColor / foregroundColor / borderColor / size / cornerRadius |
| showActionCapsuleBackground | boolean | 否 | 是否显示顶部/底部操作按钮胶囊背景(关闭/相册/单次连续/手电) | true |
true / false |
| beepOnScan | boolean | 否 | 成功识别时播放提示音;对相机扫码与相册识别都生效 | false |
true / false |
| vibrateOnScan | boolean | 否 | 成功识别时触发短震动;对相机扫码与相册识别都生效 | false |
true / false |
| overlayConfig | OverlayConfig | 否 | 遮罩事件透传配置(不加载 webview) | null |
enabled / htmlUrl / bridgeName / userAgentSuffix |
| permissionRationale | PermissionRationale | 否 | 权限说明文案 | null |
cameraTitle / cameraMessage / albumTitle / albumMessage |
样式配置查询
只调整某一项时,仅传该字段,其余保持默认值。
扫码框(scanFrameStyle)
scanFrameStyle 作用于 Android / iOS / Harmony 全屏原生扫码页:
- 不传时保持默认扫码框样式。
- 比例参数使用 0~1 坐标系:
widthRatio / heightRatio / topRatio。 cornerRadius单位:Android / Harmony 按vp视觉尺寸、iOS 按pt。showScanFrame=false时,scanFrameStyle整体忽略。showCorners=false时隐藏四个顶角,仅保留边框与扫描线。- 字段缺失或非法值自动回退默认值,不抛错、不影响扫码链路。
参数结构:
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| scanFrameStyle.widthRatio | number | 否 | 扫码框宽度占屏宽比例 | 0.68 |
推荐 0.3~0.9 |
| scanFrameStyle.heightRatio | number | 否 | 扫码框高度占屏高比例 | 0.44 |
推荐 0.25~0.85 |
| scanFrameStyle.topRatio | number | 否 | 扫码框顶部占屏高比例 | 0.24 |
推荐 0.05~0.7 |
| scanFrameStyle.cornerRadius | number | 否 | 扫码框圆角(Android/Harmony=vp,iOS=pt) | 14(Android/Harmony)/18(iOS) |
大于等于 0 |
| scanFrameStyle.showCorners | boolean | 否 | 是否显示四个顶角;false 时仅显示边框与扫描线 |
true |
true / false |
| scanFrameStyle.borderColor | string | 否 | 框体描边色 | 平台默认色 | #RRGGBB / #AARRGGBB |
| scanFrameStyle.cornerColor | string | 否 | 四角线条色(仅影响四角,不影响边框) | 平台默认色 | #RRGGBB / #AARRGGBB |
扫码页元素显隐配置
uiVisibilityConfig 影响 Android / iOS / Harmony 的全屏 startScan。既有功能开关先决定能力是否允许,新配置只能在此基础上进一步隐藏,不能反向强制开启:例如相册按钮仍需 enableAlbum=true,连续模式按钮仍需 showContinuousToggle=true。showFocusIndicator 当前仅 Android / iOS 生效。
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| showCloseButton | boolean | 否 | 是否显示关闭按钮 | true |
true / false |
| showAlbumButton | boolean | 否 | 是否显示相册按钮,仍需 enableAlbum=true |
true |
true / false |
| showTorchButton | boolean | 否 | 是否显示手电按钮,仍受设备闪光灯能力限制 | true |
true / false |
| showContinuousButton | boolean | 否 | 是否显示单次/连续按钮,仍需 showContinuousToggle=true |
true |
true / false |
| showTip | boolean | 否 | 是否显示提示图标、文字和背景 | true |
true / false |
| showFocusIndicator | boolean | 否 | 是否显示点击聚焦提示框;实际聚焦仍会执行 | true |
true / false |
| showMaskOverlay | boolean | 否 | 是否显示扫码框外遮罩,仍受 showScanFrame/showMaskOverlay 限制 |
true |
true / false |
| showScanFrameBorder | boolean | 否 | 是否显示扫码框细边框,仍受 showScanFrame 限制 |
true |
true / false |
| showScanFrameCorners | boolean | 否 | 是否显示四角,仍受 showScanFrame/scanFrameStyle.showCorners 限制 |
true |
true / false |
| showScanLine | boolean | 否 | 是否显示并运行扫描线动画,可独立于边框和四角使用 | true |
true / false |
若设置 showCloseButton=false,请保留系统返回或业务可用的退出路径,或由业务调用 stopScan(),避免用户无法退出扫码页。鸿蒙普通扫码与抓图扫码共用这套原生界面;抓图模式按能力约束隐藏相册入口。嵌入式组件的扫码框、按钮和提示由业务页面自行绘制,不应用本配置。
多码点击标记样式
multiCodeMarkerStyle 在 Android / iOS 全屏扫码启用人工选择时可配置原生标记;嵌入式组件仅在 native 绘制模式下使用 multiCodeMarkerStyle,custom 模式由业务页面决定标记样式。样式错误不会触发扫码失败,非法字段会回退安全默认值。
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| backgroundColor | string | 否 | 标记背景颜色 | #5046EE |
#RRGGBB / #AARRGGBB |
| foregroundColor | string | 否 | 箭头前景颜色 | #FFFFFF |
#RRGGBB / #AARRGGBB |
| borderColor | string | 否 | 标记边框颜色,边框宽度固定为 Android 2dp / iOS 2pt |
#FFFFFF |
#RRGGBB / #AARRGGBB |
| size | number | 否 | 标记宽高,超出时自动限制 | 44 |
44~72dp/pt |
| cornerRadius | number | 否 | 标记圆角,超出时自动限制 | size / 2 |
0~size / 2 |
文案和图片图标
| 配置 | 常用字段 | 使用说明 |
|---|---|---|
uiTextConfig |
tipIcon / tipText |
提示图标和提示文字;这里的 tipText 优先于顶层同名字段 |
uiTextConfig |
closeIcon / closeText / albumIcon / albumText |
关闭、相册按钮的字符图标和文案 |
uiTextConfig |
torchIcon / torchOnText / torchOffText / torchUnsupportedText |
手电图标及开、关、不支持时的文字 |
uiImageConfig |
tip / close / album / torchOn / torchOff / torchUnsupported |
对应位置的图片,每个位置填写下表中的图标对象 |
图片来源可使用应用静态资源路径、本地文件路径、file:// / content:// URI 或 data:image/*;base64,...。一般优先填写 /static/xxx.png,并确认对应资源存在。
ScanUiImageItem 字段说明:
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| src | string | 是 | 图标来源(建议 png/jpg/webp 或 data URI) | 无 | 无 |
| width | number | 否 | 图标宽度(Android / Harmony 按 vp 视觉尺寸,iOS 按 pt) | 16~18(按位置默认) |
大于 0 的数值 |
| height | number | 否 | 图标高度(Android / Harmony 按 vp 视觉尺寸,iOS 按 pt) | 16~18(按位置默认) |
大于 0 的数值 |
| tintColor | string | 否 | 图标染色 | null |
#RRGGBB / #AARRGGBB |
按钮和提示的位置(uiLayoutConfig)
uiLayoutConfig 作用于 Android / iOS / Harmony 全屏原生扫码页,用于解决“隐藏胶囊后图标离边太远”场景:
- 坐标语义统一:
x > 0向右,y > 0向下;支持负值。 - 单位:Android / Harmony 按
vp视觉尺寸、iOS 按pt。 - 未传字段按
0处理,不影响旧布局。
参数结构:
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| uiLayoutConfig.close | ScanUiElementLayout | 否 | 左上角关闭按钮偏移配置 | null |
containerOffset / iconOffset / textOffset |
| uiLayoutConfig.album | ScanUiElementLayout | 否 | 右上角相册按钮偏移配置 | null |
containerOffset / iconOffset / textOffset |
| uiLayoutConfig.continuous | ScanUiElementLayout | 否 | 底部“单次/连续”按钮偏移配置 | null |
containerOffset / iconOffset / textOffset |
| uiLayoutConfig.torch | ScanUiElementLayout | 否 | 底部手电按钮偏移配置 | null |
containerOffset / iconOffset / textOffset |
| uiLayoutConfig.tip | ScanUiElementLayout | 否 | 底部提示区偏移配置 | null |
containerOffset / iconOffset / textOffset |
ScanUiElementLayout 字段说明:
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| containerOffset | ScanUiOffset | 否 | 元素整体偏移(容器位置) | { x: 0, y: 0 } |
x / y |
| iconOffset | ScanUiOffset | 否 | 图标相对容器偏移(无图标时忽略) | { x: 0, y: 0 } |
x / y |
| textOffset | ScanUiOffset | 否 | 文案相对容器偏移(无文案时忽略) | { x: 0, y: 0 } |
x / y |
回调说明(startScan)
| 回调 | 何时使用 | 读取内容 |
|---|---|---|
onResult(res) |
获取单次、连续或相册识别结果 | res.results 数组 |
onError(err) |
处理取消、权限、参数或识别错误 | err.errCode / err.errMsg |
success / fail / complete |
监听 API 调用的成功、失败、完成 | 不同 API 的动作结果;扫码内容统一在 onResult 中处理 |
onOverlayEvent(event) |
进阶监听全屏页状态,需开启事件配置 | event.type / scannerId / payload |
不要把 startScan 的 success 当作识别成功;识别结果使用 onResult。相册识别成功会触发 onResult 及 success/complete,业务保存操作只放在其中一个入口,避免重复处理。
扫码页事件类型
onOverlayEvent 回调事件结构:
{
type: string,
scannerId: string,
payload: any
}
| 事件 type | payload 类型 | 说明 |
|---|---|---|
| overlayReady | string | null | 遮罩事件通道初始化完成,payload 为 overlayConfig.htmlUrl(如未配置则为 null) |
| shown | null | 原生扫码全屏界面已显示 |
| cameraReady | null | 相机预览与分析链路已绑定完成 |
| albumClick | null | 点击右上角相册按钮后触发(需 enableAlbum=true) |
| albumRecognized | string | 通过右上角相册入口识别成功,payload 为识别字符串 |
| focusTapped | string | object | 点击预览触发聚焦后回传;Android 为 "x,y",iOS 为坐标对象 |
| recognized | string | 识别到码内容,payload 为识别字符串 |
| continuousChanged | object | 原生页模式切换事件,payload 固定为 { continuous: boolean, source: "nativeToggle" } |
| paused | null | 调用 pauseScan 后触发 |
| resumed | null | 调用 resumeScan 后触发 |
| buildInfo | string | 运行标识,反馈扫码问题时可用于定位 |
| error | string | 原生扫码过程异常,payload 为错误文本 |
| closed | null | 原生扫码界面已关闭并释放 |
| nativeMessage | any | 调用 postOverlayMessage 后回传的消息内容 |
说明:上述事件仅在 overlayConfig.enabled=true 时派发。
完全自由布局组件(进阶选用)
只有需要自行编写整个扫码页面布局时才使用本节。 普通全屏扫码、连续扫码、相册识别和样式调整,优先使用前面的 API。
组件只负责相机预览、识别和事件,扫码框、按钮、提示及业务区域由页面绘制。以下内容可在 API 接入完成后按需阅读。
最小正确接入
uni-app x 使用 .uvue 页面。下面只展示基础预览和结果处理,给组件设置明确宽高,页面返回时恢复、卸载时释放。
<template>
<view>
<lizhao-scan-pro
ref="scanner"
scanner-id="embeddedDemo"
class="scanner-preview"
@ready="onScannerReady"
@scan="onScan"
@error="onError"
/>
</view>
</template>
<script setup lang="uts">
import { ScanEmbeddedState, ScanFrameResult, ScanFail } from '@/uni_modules/lizhao-scan-pro'
// 保存组件引用与就绪状态,首次 onShow 不重复启动。
const scanner = ref<LizhaoScanProComponentPublicInstance | null>(null)
const scannerReady = ref<boolean>(false)
function onScannerReady(_state: ScanEmbeddedState): void {
scannerReady.value = true
}
function onScan(res: ScanFrameResult): void {
console.log('扫码结果:' + JSON.stringify(res.results))
}
function onError(err: ScanFail): void {
console.error('扫码失败:' + err.errMsg)
}
onShow(() => {
if (scannerReady.value) scanner.value?.resume?.()
})
onHide(() => { scanner.value?.pause?.() })
onUnload(() => { scanner.value?.dispose?.() })
</script>
<style>
.scanner-preview { width: 100%; height: 400px; }
</style>
uni-app 使用 .nvue,事件数据可能位于 event.detail 中;请使用随插件提供的对应示例,完整页面入口见下表。
完整示例入口
| 需求 | uni-app | uni-app x |
|---|---|---|
| API 全屏扫码、相册、样式配置 | scan.vue | index.uvue |
| 嵌入式预览、自定义布局、多码标记 | free-layout.nvue | free-layout.uvue |
组件职责与扫码范围
| 能力 | 由谁负责 | 说明 |
|---|---|---|
| 相机预览、码识别、格式过滤、连续扫码、多码冻结选择 | <lizhao-scan-pro /> |
通过 props 配置,通过事件返回结果 |
| 扫码框、扫描线、遮罩、按钮、提示、动画、结果区 | 业务页面 | 使用 .nvue/.uvue 页面元素覆盖在组件上方 |
| 相册识别 | 业务页面调用 pickImageAndScan |
嵌入式组件不内置相册按钮 |
| 页面隐藏、恢复和销毁 | 业务页面生命周期 | 分别调用 pause()、resume()、dispose() |
自定义扫码框只是视觉引导,不是识别裁剪区域。组件会识别整个相机预览范围内的有效码;如业务只允许扫码框内的码,需要在业务层结合结果规则做校验,不能仅依赖页面上画出的方框。
showScanFrame、showMaskOverlay、scanFrameStyle、uiVisibilityConfig、uiTextConfig、uiImageConfig、uiLayoutConfig、tipText 和 enableAlbum 属于全屏 startScan 的界面配置,不是嵌入式组件属性。自由布局模式下请直接在页面中实现这些 UI。
页面覆盖层如果拦截了点击事件,组件不会自动收到点击位置。需要点按聚焦时,在覆盖层的点击事件中取得组件局部坐标,再调用 focusAt(x, y)。
嵌入式多码点击选择
Android / iOS 嵌入式组件可通过 enableMultiCodeSelection=true 开启人工选码。该能力只在 continuous=false 的单次扫码中生效:第一条可定位结果会进入有界聚合,multiCodeDetectionWaitMs 默认最多等待 500ms,有效范围仍为 200~1500ms;候选集合连续稳定为多码时冻结当前画面。若候选集合未稳定为多码,包括始终只有单码或候选发生波动,到期后会按确定顺序降级返回一条结果并进入 stopped。Android 全屏模式另有“发现未解码的第二个二维码时继续识别”机制,详见前面的多码人工选择说明;该机制不改变嵌入式等待参数。iOS 全屏模式仍聚合最多约 3 秒;两端都不会把仅有轮廓、没有解码内容的潜在框直接作为可选结果。
先按界面需求选择绘制模式:
| 模式 | 谁绘制候选标记 | 是否由插件冻结画面 | 适用场景 |
|---|---|---|---|
native |
插件原生层 | 是 | 希望最少接入代码,直接使用内置可点击标记 |
custom |
业务页面 | 是 | 希望完全控制标记形态、布局和点击交互 |
两种模式都会由插件冻结预览,并通过 multicodechange 返回同一套候选坐标;custom 只把标记绘制和点击入口交给业务页面,不要求业务页面自行截取或冻结相机画面。
以下示例适用于 uni-app .nvue 的 Options API;uni-app x 请直接参考随插件提供的强类型示例 example/uniappx/free-layout.uvue。
使用插件内置标记:
<template>
<view class="scanner-wrap">
<lizhao-scan-pro
ref="scanner"
class="scanner-preview"
scanner-id="nativeSelectionScanner"
:continuous="false"
:enable-multi-code-selection="true"
multi-code-selection-render-mode="native"
@scan="onScan"
@error="onError"
@multicodechange="onMultiCodeChange"
/>
</view>
</template>
<script>
export default {
methods: {
onScan(event) {
const detail = event != null && event.detail != null ? event.detail : event
console.log('选中结果:', detail)
},
onError(event) {
const detail = event != null && event.detail != null ? event.detail : event
console.error('扫码失败:', detail)
},
onMultiCodeChange(event) {
const detail = event != null && event.detail != null ? event.detail : event
const candidates = detail != null && Array.isArray(detail.candidates) ? detail.candidates : []
console.log('候选坐标:', candidates)
}
}
}
</script>
<style>
.scanner-wrap {
width: 100%;
height: 500px;
}
.scanner-preview {
width: 100%;
height: 500px;
}
</style>
由业务页面绘制标记并确认或重扫:
<template>
<view class="scanner-wrap">
<lizhao-scan-pro
ref="scanner"
class="scanner-preview"
scanner-id="customSelectionScanner"
:continuous="false"
:enable-multi-code-selection="true"
multi-code-selection-render-mode="custom"
@scan="onScan"
@error="onError"
@multicodechange="onMultiCodeChange"
/>
<view
v-for="candidate in candidates"
:key="candidate.id"
class="candidate-marker"
:style="markerStyle(candidate.normalizedCenter)"
@tap="selectCandidate(candidate.id)"
>选择</view>
<button
v-if="candidates.length > 0"
class="resume-button"
@tap="resumeSelection"
>重新扫描</button>
</view>
</template>
<script>
export default {
data() {
return { candidates: [] }
},
methods: {
onScan(event) {
const detail = event != null && event.detail != null ? event.detail : event
console.log('选中结果:', detail)
},
onError(event) {
const detail = event != null && event.detail != null ? event.detail : event
console.error('扫码失败:', detail)
},
onMultiCodeChange(event) {
const detail = event != null && event.detail != null ? event.detail : event
const nextCandidates = detail != null && Array.isArray(detail.candidates) ? detail.candidates : []
this.candidates = detail != null && detail.frozen === true ? nextCandidates : []
},
markerStyle(center) {
return {
left: (center.x * 100) + '%',
top: (center.y * 100) + '%'
}
},
selectCandidate(candidateId) {
const scanner = this.$refs.scanner
if (scanner != null) {
scanner.selectMultiCodeCandidate(candidateId)
}
},
resumeSelection() {
const scanner = this.$refs.scanner
if (scanner != null) {
scanner.resumeMultiCodeSelection()
}
}
}
}
</script>
<style>
.scanner-wrap {
position: relative;
width: 100%;
height: 500px;
}
.scanner-preview {
width: 100%;
height: 500px;
}
.candidate-marker {
position: absolute;
z-index: 40;
width: 52px;
height: 52px;
margin-left: -26px;
margin-top: -26px;
border-radius: 26px;
background-color: #5b43d6;
color: #ffffff;
text-align: center;
}
.resume-button {
position: absolute;
right: 16px;
bottom: 16px;
z-index: 41;
}
</style>
returnAllResults=true与人工选择同时开启时,人工选择优先,scan事件的results只包含用户选中的一条。continuous=true时不会进入冻结选择,继续按原有连续扫码协议返回结果。multiCodeMarkerStyle可配置标记背景色、箭头前景色、边框色、尺寸和圆角,仅在native模式由插件绘制时生效;两种模式都会返回multicodechange事件和坐标。- iOS Vision 与 Android Bitmap 等兜底识别结果没有可靠预览坐标时保持无位置状态,不伪造候选坐标或点击标记;只有可定位候选才进入嵌入式多码选择。
- 冻结快照失败时不会留下不可点击的假界面,组件会继续实时扫描。
- 只有
enableMultiCodeSelection=true且continuous=false、人工选择实际生效时才校验选择配置:multiCodeSelectionRenderMode不是native/custom时通过error返回9010009并安全回退为native;multiCodeDetectionWaitMs默认500ms,有效范围为200~1500ms,越界时返回9010009并钳制到安全范围,无效数值回退为默认值。 - 选择完成、重新扫描、停止或销毁时会发出一次
frozen=false、candidates=[]的清理事件;过期候选id会被安全忽略,不会误选新批次。
uni-app x .uvue 的装饰扫码框、四角、扫描线和提示应设置 pointer-events="none"。uni-app .nvue 不应依赖该 CSS 做点击穿透:不要创建整屏透明装饰容器,并像完整示例一样在 enableEmbeddedMultiCodeSelection=true 时通过 v-if 移除扫码框和提示。关闭、手电和模式切换等业务按钮应放在独立的小范围可点击容器中,不要用整屏透明点击层覆盖相机预览。uiVisibilityConfig 仍只控制全屏扫码页,不参与嵌入式自由布局。
组件属性
| 参数 | 类型 | 必填 | 说明 | 默认值 | 可选参数 |
|---|---|---|---|---|---|
| scannerId | string | 否 | 扫描器唯一标识,用于组件注册与公共 API 控制;挂载后不要修改 | embedded |
任意非空且当前页面唯一的字符串 |
| formats | Array<ScanFormat> | 否 | 允许识别的码制 | ["all"] |
all / qrCode / aztec / codabar / code39 / code93 / code128 / dataMatrix / ean8 / ean13 / itf / pdf417 / upcA / upcE |
| minBarcodeLength | number | 否 | 一维码最小长度过滤 | 0 |
大于等于 0 |
| returnAllResults | boolean | 否 | 是否返回同一帧的全部有效结果 | false |
true / false |
| captureOnSuccess | boolean | 否 | Android / iOS 扫码成功自动保存完整 JPG,成功回调附带图片路径与尺寸;不可与多码点击选择组合,不用于相册识别 | false |
true / false |
| enableMultiCodeSelection | boolean | 否 | Android / iOS 单次嵌入式扫码开启有界聚合;稳定多码时冻结预览供用户选择,单码到期仅返回一次 | false |
true / false |
| multiCodeSelectionRenderMode | ScanMultiCodeSelectionRenderMode | 否 | 嵌入式多码标记绘制模式;两种模式均由插件冻结并返回事件坐标 | native |
native / custom |
| multiCodeDetectionWaitMs | number | 否 | 第一条可定位结果出现后的最大聚合等待时间,单位毫秒;越界返回 9010009 并钳制 |
500 |
200~1500 |
| multiCodeMarkerStyle | ScanMultiCodeMarkerStyle | 否 | 插件原生标记的背景色、箭头色、边框色、尺寸和圆角;仅 native 模式绘制生效,与全屏扫码共用样式结构 |
{} |
backgroundColor / foregroundColor / borderColor / size / cornerRadius |
| continuous | boolean | 否 | 是否持续识别 | false |
true / false |
| continuousIntervalMs | number | 否 | 连续结果最小间隔,单位毫秒;仅 continuous=true 生效 |
0 |
大于等于 0 |
| autoStart | boolean | 否 | 原生 View 挂载后是否自动启动;设为 false 后需在 ref 可用时调用 start() |
true |
true / false |
| zoomRatio | number | 否 | 初始缩放倍率 | 1 |
大于 0 |
| autoZoom | boolean | 否 | 远码自动拉近;切换属性后重启扫码会话,手动倍率优先 | false |
true / false |
| torchEnabled | boolean | 否 | 初始手电状态 | false |
true / false |
| nearFocusLock | boolean | 否 | 是否启用近距辅助锁焦 | false |
true / false |
| beepOnScan | boolean | 否 | 识别成功后是否播放提示音 | false |
true / false |
| vibrateOnScan | boolean | 否 | 识别成功后是否短震动 | false |
true / false |
组件事件
| 事件 | 数据类型 | 说明 |
|---|---|---|
ready |
ScanEmbeddedState | 原生预览与识别链路准备完成;收到后才可安全执行前后台恢复控制 |
scan |
ScanFrameResult | 返回单码或同帧多码结果,业务数据读取 results 数组,结构与 startScan 一致 |
multicodechange |
ScanMultiCodeSelectionEvent | 嵌入式多码冻结与清理事件;native/custom 两种模式都会返回候选及组件局部坐标 |
error |
ScanFail | 权限、初始化、参数或会话冲突错误;必须监听并记录 errCode/errMsg |
statechange |
ScanEmbeddedEvent | 返回 starting/running/paused/stopped/destroyed 状态变化 |
focus |
ScanEmbeddedEvent | 返回点按聚焦坐标与执行状态 |
uni-app .nvue 的原生组件事件数据可能包装在 event.detail 中,建议像完整示例一样先取 event.detail,不存在时再使用事件对象本身;uni-app x .uvue 按表格中的强类型直接接收。
ScanMultiCodeSelectionEvent 返回值:
| 字段 | 类型 | 说明 |
|---|---|---|
| scannerId | string | 产生事件的组件扫描器标识 |
| timestamp | number | 事件时间戳,单位毫秒 |
| selectionId | string | 当前冻结选择批次标识;用于区分前后两批候选 |
| frozen | boolean | true 表示画面已冻结且可选择;false 表示该批次已清理 |
| coordinateSpace | component |
坐标空间固定为扫码组件本地坐标 |
| unit | ScanCoordinateUnit | Android 为 px,iOS 为 pt |
| viewWidth | number | 事件产生时的组件宽度 |
| viewHeight | number | 事件产生时的组件高度 |
| candidates | Array<ScanMultiCodeCandidate> | 当前可选候选;清理事件固定为空数组 |
ScanMultiCodeCandidate 候选字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 当前冻结批次内唯一的候选标识,选择时原样传回 |
| value | string | 识别内容 |
| format | ScanFormat | 归一化后的码制 |
| rawType | string | 原生识别器返回的码制名称 |
| bounds | ScanRect | 候选在组件内的外接矩形,单位由事件 unit 指定 |
| center | ScanPoint | 候选在组件内的中心点 |
| cornerPoints | Array<number> | 四个角点,共 8 个数值,顺序固定为左上、右上、右下、左下(LT/RT/RB/LB) |
| normalizedBounds | ScanRect | 按组件宽高归一化后的外接矩形,范围为 0..1 |
| normalizedCenter | ScanPoint | 按组件宽高归一化后的中心点,范围为 0..1 |
页面自绘时优先使用 normalizedBounds/normalizedCenter,避免 Android px 与 iOS pt 的单位差异。iOS Vision、Android Bitmap 等无法取得可靠组件坐标的兜底结果不会伪造这些字段,也不会作为可点击候选返回。
组件方法
| 方法 | 说明 |
|---|---|
start() |
请求权限并启动或重新绑定相机;适用于 autoStart=false 或 stop() 后重启 |
stop() |
停止识别并解绑相机,保留组件实例和 scannerId 注册;打开不同 ID 的全屏扫码前必须先调用 |
pause() |
暂停分析,不派发识别结果 |
resume() |
恢复分析;尚未启动时会启动会话 |
applyTorchEnabled(enabled) |
设置手电状态 |
applyZoomRatio(zoomRatio) |
设置缩放倍率 |
setScanFormats(formats) |
动态更新码制 |
focusAt(x, y) |
按组件局部坐标执行聚焦 |
getState() |
返回当前组件状态快照 |
selectMultiCodeCandidate(candidateId) |
选择当前冻结批次中的候选;传入已清理或过期的 candidateId 时安全忽略 |
resumeMultiCodeSelection() |
放弃当前冻结批次并恢复实时识别,不触发 scan 事件 |
dispose() |
永久释放相机、识别器、线程、回调和注册表引用;调用后必须重新挂载组件才能再次使用 |
组件与现有 pauseScan/resumeScan/setTorchEnabled/setZoomRatio/setScanFormats/stopScan/destroyScanner 共用 scannerId。公共 API 会优先控制同 ID 的组件;若同 ID 已被组件占用,再调用全屏 startScan 会返回 9010011 scanner id occupied,不会隐式关闭业务页面中的相机。
支持平台
| 平台 | 全屏扫码 API | 相册 API | 嵌入式组件 |
|---|---|---|---|
| Android | 支持,全屏样式可配置 | 支持,可返回多条结果 | 支持,uni-app 用 .nvue,uni-app x 用 .uvue |
| iOS | 支持,全屏样式可配置 | 支持,当前返回单条结果 | 支持,uni-app 用 .nvue,uni-app x 用 .uvue |
| Harmony | 支持,普通扫码与抓图共用可配置的原生全屏界面 | 支持,普通扫码页可打开系统相册选择器 | 不支持 |
| Web / 微信小程序 / 支付宝小程序 | 不支持,返回 9010001 |
不支持,返回 9010001 |
不支持 |
uni-app 的普通 .vue 页面可调用全屏 API;嵌入式组件需要 .nvue。uni-app x 的 App 页面使用 .uvue。
Harmony 使用差异
Harmony 使用同名 API,并与 Android / iOS 共用全屏扫码配置。使用时请按以下差异处理:
startScan:普通扫码与captureOnSuccess=true的抓图扫码都使用 CameraKit 原生全屏界面;预览按相机画面比例等比铺满,扫码框、遮罩、扫描线、文案、图片图标、布局偏移和元素显隐使用同一套参数。enableAlbum=true:普通扫码页显示相册入口,选图后按当前formats识别;取消、无码或失败后回到相机预览。抓图模式不显示相册入口。showContinuousToggle=true:页面内可实时切换单次/连续模式;continuousIntervalMs继续控制连续回调最小间隔,业务仍应自行去重。setTorchEnabled/setZoomRatio:直接控制当前 CameraKit 会话,设备不支持或未生效时返回明确失败。formats:CameraKit 识别阶段按二维码、Data Matrix、PDF417、Code39、Code128、EAN、UPC 等细分格式过滤;minBarcodeLength继续用于过滤过短的一维码结果。returnAllResults=true:相机帧可返回同帧多条结果;Harmony 相册识别当前仍返回单条结果。enableMultiCodeSelection=true:Harmony 当前不支持人工点选多个候选,返回9010009。beepOnScan / vibrateOnScan:Harmony 当前暂不承诺生效。
开启 captureOnSuccess 后,识码器读取的完整 JPG 会通过 file:/// 本地路径连同图片宽高返回;预览的等比裁剪不会裁切保存的原图。低于 API 12 返回 9010001,图片保存失败返回 9010013。请重新构建并安装包含 1.0.74 的鸿蒙 App 后使用。
iOS 多码选择与条码识别
iOS 全屏扫码开启多码选择后,会从首个可定位结果起聚合最多约 3 秒,并使用带可靠坐标的 metadata 与 Vision 候选。两个候选稳定后冻结供用户点选;到期只有一个候选时按单码返回。没有可靠位置的结果不会显示为可点击标记;未开启多码选择、连续扫码、相册、成功抓图和嵌入式组件仍沿用原流程。
已知条码格式时请明确填写 formats;固定长度的一维条码可配合 minBarcodeLength 过滤过短结果。普通 ITF 设备码使用 formats: ['itf'];最小长度按实际标签填写。
返回值说明(ScanFrameResult)
| 字段 | 类型 | 说明 |
|---|---|---|
| scannerId | string | 扫描器 ID |
| timestamp | number | 时间戳 |
| frameIndex | number | 帧序号 |
| imagePath | string(可选) | 开启抓图时返回的临时 JPG 本地文件 URI(file://...),可直接用于 image.src 或 uni.uploadFile.filePath;保留完整 URI,不自行拼接或截取路径 |
| imageWidth | number(可选) | 已校正方向的图片宽度,单位像素 |
| imageHeight | number(可选) | 已校正方向的图片高度,单位像素 |
| results | Array<ScanResultItem> | 当前帧结果列表(默认 1 条;returnAllResults=true 时可返回多条) |
results 数组元素结构:
| 字段 | 类型 | 说明 |
|---|---|---|
| value | string | 识别出的二维码或条形码内容 |
| format | ScanFormat | 实际识别码制 |
| rawType | string | 原生识别器返回的码制名称 |
| cornerPoints | Array<number>(可选) | 可定位时返回左上、右上、右下、左下四个角点 |
| bounds | ScanRect(可选) | 可定位时返回结果在嵌入式组件内的外接矩形 |
| center | ScanPoint(可选) | 可定位时返回结果在嵌入式组件内的中心点 |
| normalizedBounds | ScanRect(可选) | 可定位时返回 0..1 归一化外接矩形 |
| normalizedCenter | ScanPoint(可选) | 可定位时返回 0..1 归一化中心点 |
嵌入式多码人工选择完成后,最终选中的 ScanResultItem 会在坐标可靠时保留上述位置字段;这些字段均为嵌入式组件局部坐标,Android 使用 px、iOS 使用 pt,归一化字段范围为 0..1。普通结果或 Vision/Bitmap 等无可靠组件映射的兜底结果不会伪造坐标。
错误码说明
| 错误码 | 含义 | 建议处理 |
|---|---|---|
| 9010001 | 当前平台不支持 | 按支持平台表隐藏对应入口 |
| 9010002 | 相机权限不足 | 引导使用者允许相机访问后重试 |
| 9010003 | 相册权限不足 | 检查相册访问权限及用途说明 |
| 9010004 | 相机启动失败 | 确认相机未被其他活动会话占用后重试 |
| 9010005 | 码制不支持或格式配置有误 | 检查 formats 的拼写与平台支持范围 |
| 9010006 | 图片中没有识别到码或图片解析失败 | 换用更清晰、完整的图片 |
| 9010007 | 预留错误码 | 当前不触发 |
| 9010008 | 取消或中止扫码 | 一般按正常取消处理,无需报错弹窗 |
| 9010009 | 参数不合法 | 检查数值范围、码制和组件选择配置 |
| 9010010 | 系统异常 | 记录错误信息后重试 |
| 9010011 | 扫描器 ID 被占用 | 为活动会话使用唯一 ID,或先释放原会话 |
| 9010012 | 组件未就绪或已销毁 | 等待组件挂载;销毁后需重新挂载 |
| 9010013 | 扫码图片保存失败 | 检查存储空间并重试;该次不返回成功结果 |
注意事项
Android 普通全屏扫码持续未识别时会分两层补救:码制为空、仅 qrCode 或仅 all 时,对稳定的未解码候选受限拉近;码制包含 qrCode 或 all 时,按节奏尝试高清二维码识别。多码人工选择采用前述“第二码未解全时继续识别”规则,高清补识别仍最多两次,不会持续拍照;未解码区域不会直接作为可选结果,最终能否读出仍取决于画质。近距锁焦和内嵌模式沿用原识别流程;混合指定码制不会触发默认候选拉近,但其中包含 qrCode 时仍可使用高清补救。手动设置倍率或点击聚焦后停止本次自动调整。设备不支持高清取帧时仍可继续普通扫码。该流程继续使用已有 Google ML Kit,未引入华为扫码 SDK 或其他新原生依赖。
高清补救的图像用于本机识别,不额外写入相册;开启 captureOnSuccess 时仍按原配置返回与结果对应的图片。
基础接入与结果处理
-
captureOnSuccess默认关闭;全屏支持 Android / iOS / Harmony,嵌入式仅支持 Android / iOS。Android / iOS 需包含 1.0.73 抓图能力的自定义基座;Harmony 需 API 12+ 并重新构建安装包含 1.0.74 的鸿蒙 App。Web / 小程序返回9010001。 -
抓图文件是临时资源,请及时上传或按业务需要另存;不要只把本地路径存到后端当作图片。上传成功后可用文件 API 删除本次文件,失败时保留用于重试,勿在上传完成前删除。
-
开启抓图时不提供相册入口;与多码点击选择组合或用于相册识别返回
9010009。 -
Android 云打包必须使用 HBuilderX 5.09 及以上;首次接入或原生能力变更后,需要安装包含对应插件的自定义基座或正式包,纯文档更新不需要重打。
-
全屏扫码和嵌入式预览需要相机权限;相册识别由系统选择器处理,iOS 应配置相册用途说明。
-
API 只从插件根目录导入。全屏扫码使用
startScan,相册使用pickImageAndScan,不需要为了使用 API 再挂载组件。 -
scannerId应固定,后续暂停、恢复、停止、销毁都使用相同 ID。同一时间保持一个活动相机会话。 -
全屏扫码打开系统或原生页面时,宿主页面可能暂时不可见;不要把宿主
onHide一律当作业务结束并立即停止扫码。根据实际导航决定停止时机,页面卸载时释放会话。 -
连续扫码需要业务去重;批量结果只表示当前识别到的有效码,不能保证图中所有码一次都能识别。
-
条码模糊、反光、缺损或距离过近时,先调整距离与光照;近距聚焦与缩放不能突破设备相机的对焦能力。
-
beepOnScan / vibrateOnScan默认关闭,Android / iOS 可按需开启;Harmony 当前暂不承诺生效。
接入前先确认(仅嵌入式组件)
先按页面形态选择正确入口:
| 你的需求 | 正确接入方式 | 不要这样用 |
|---|---|---|
| 快速打开完整扫码页 | 调用 startScan(options) |
不需要为了改几段文案就改用组件 |
| 页面结构、按钮和业务区完全自定义 | 在 .nvue/.uvue 使用 <lizhao-scan-pro /> |
不要同时再调用同 ID 的全屏 startScan |
uni-app 普通 .vue 页面 |
继续使用全屏 startScan |
不要在普通 .vue 中放嵌入式组件 |
开始接入前必须满足以下条件:
- 只在 Android/iOS App 使用;Harmony、Web 和小程序当前不支持嵌入式预览。
- uni-app 页面文件必须是
.nvue,uni-app x 页面文件必须是.uvue,不能只把普通.vue改个组件标签。 - 安装包含当前插件原生能力的应用包后再测试组件。
- 给预览容器和组件设置明确的宽度、高度;高度为
0时不会显示相机画面。 scannerId必须是非空且当前页面唯一的固定字符串,组件挂载后不要动态修改。- 必须监听
error,权限被拒绝、参数错误或会话冲突都会通过该事件返回,不能只监听scan。 - 一个页面只保留一个活动相机会话;打开全屏扫码前先停止嵌入式组件。
生命周期必须这样处理
| 页面时机/动作 | 应调用 | 说明 |
|---|---|---|
| 首次进入页面 | 通常无需手动调用 | 默认 autoStart=true,组件挂载后自动请求权限并启动;不要再在 onReady 中重复调用 start() |
| 页面进入前台 | resume() |
仅在已经收到 ready 且没有活动中的全屏会话时调用;首次 onShow 应跳过 |
| 页面进入后台 | pause() |
暂停识别但保留相机和组件实例,返回页面后可快速恢复 |
| 临时关闭相机 | stop() |
解绑相机但保留组件实例和 scannerId 注册,之后可调用 start() 再次启动 |
| Android 示例切换全屏扫码 | 先 stop(),再用不同 ID 调用 startScan() |
仅 Android 示例提供“嵌入 → 全屏 → 返回恢复”比较链;必须监听 onOverlayEvent,收到 closed/stopped 后再调用组件 start() |
| 页面卸载或永久关闭 | dispose() |
释放相机、线程、回调和注册关系;dispose() 后不能再次调用 start(),重新使用必须重新挂载组件 |
页面 ref 的最终释放方法是 dispose(),不要调用 scanner.destroy()。脚本层使用 destroyScanner({ scannerId }) 按 ID 释放扫码会话;两种调用方式不要混用。
Android 从嵌入式组件切换到全屏扫码时,onResult 只表示已经返回识别结果,不表示全屏原生页面和相机已经释放。不要在 onResult/onError 中直接调用组件 start();示例会设置 overlayConfig.enabled=true,并在 onOverlayEvent 收到 closed/stopped 后恢复嵌入预览。iOS 支持嵌入式自由布局,但本示例不提供嵌入与全屏混合切换;iOS 使用时应在同一页面只选择一种相机会话形态。
Android 全屏 Activity 返回时,页面 onShow 可能早于原生 closed/stopped 事件触发。fullScreenActive=true 时必须跳过页面 onShow 中的 resume();只能由 closed/stopped(或全屏启动前同步失败)调用统一恢复方法,避免两个相机会话同时抢占摄像头。
如果设置 autoStart=false,请在组件 ref 可用后主动调用 start();不要等待 ready 再启动,因为 ready 只有原生相机真正启动后才会触发。
scannerId 使用规则
- 每个已挂载组件使用一个非空、唯一且固定的
scannerId,推荐按页面或业务命名,例如warehouseInboundScanner。 - 通过公共 API 控制组件时,API 参数中的
scannerId必须与组件完全一致。 - 为保证 Android/iOS 行为一致,组件挂载后不要动态修改
scannerId;需要换 ID 时先卸载旧组件,再挂载新组件。 - 同一个
scannerId不能同时属于全屏扫码和嵌入式组件,否则返回9010011 scanner id occupied。stop()不会释放组件注册;必须复用同 ID 时需要先dispose()或卸载组件。 - 即使使用不同 ID,设备通常也只能稳定占用一个相机会话,因此打开全屏扫码前仍应先调用组件
stop()。
常见错误与处理
| 现象/错误 | 常见原因 | 正确处理 |
|---|---|---|
| 组件不显示或 easycom 无法识别 | uni-app 使用了普通 .vue |
改用 .nvue;uni-app x 使用 .uvue |
| 页面有位置但相机黑屏 | 组件宽高为 0、相机权限未授权或安装包未包含当前插件原生能力 |
明确设置宽高、处理 error,并确认安装包已包含当前插件 |
9010011 scanner id occupied |
同 ID 已被另一个组件或全屏扫码占用 | 改用新的唯一 ID;如必须复用原 ID,先 dispose() 或卸载旧组件,单独调用 stop() 不会释放 ID |
9010012 scanner component unavailable |
ref 尚未就绪、组件已卸载或已执行 dispose() |
等待组件挂载;dispose() 后重新挂载组件,不要复用旧 ref |
调用 scanner.destroy() 编译失败或方法不存在 |
使用了旧示例或把页面 ref 方法与公共 API 混用 | 页面 ref 改用 scanner.dispose();脚本 API 使用 destroyScanner({ scannerId }) |
| 首次进入页面重复启动 | autoStart=true,同时又在首次 onShow/onReady 调用了 start/resume |
使用 scannerReady 标记,首次 onShow 跳过,收到 ready 后再允许恢复 |
| 连续收到相同结果 | 开启了 continuous,但没有设置间隔或业务去重 |
设置 continuousIntervalMs,并按业务主键做二次去重 |
| Android 全屏扫码无法打开或返回后黑屏 | 嵌入式组件仍占用相机,或在 onResult/onError 中过早恢复 |
先 stop() 再调用不同 ID 的 startScan();设置 overlayConfig.enabled=true,只在 closed/stopped 后调用组件 start() |
| 扫码框外的码也被识别 | 误以为自定义扫码框会裁剪识别区域 | 扫码框只是视觉提示;在业务层校验结果或调整相机预览范围 |
隐私与数据处理
- 二维码/条形码图像和识别结果默认在设备端处理;插件不会主动把扫码内容上传到作者服务器,也不内置广告或账号追踪。
- Android 使用 Google ML Kit Barcode Scanning。按照 ML Kit 官方条款,SDK 可能联系 Google 服务以获取模型、错误修复、硬件兼容信息或相关运行指标;因此不能把 Android 能力描述为“任何情况下都绝对不联网”。
getDebugTrace()和getCrashReports()用于本地诊断。业务仍不应把账号、口令、Token、完整证件号或其他敏感内容写入扫码参数、页面日志或反馈材料。- 应用开发者仍需根据自身业务、上架地区和目标应用商店要求,在应用隐私政策中说明相机、相册、扫码数据和所用 SDK。
依赖版本、用途、许可与官方条款见 THIRD_PARTY_NOTICES.md。
联系方式
信-微:l-z-1-8-7-1512-5421(-去掉,不这样写会被和谐)
作者系列 UTS 插件
以下为已在 DCloud 插件市场上架的作者系列 UTS 插件,可按业务场景组合使用。未列出的插件表示当前未确认公开市场页,后续上架后再补充。
| 插件 | 能力方向 | 插件市场 |
|---|---|---|
lizhao-nfc-pro |
NFC 标签读写、NDEF、IsoDep 与诊断 | 查看插件 |
lizhao-float-window |
悬浮窗、画中画、权限与诊断 | 查看插件 |
lizhao-device-id |
设备标识、隐私策略与诊断 | 查看插件 |
lizhao-scan-pro |
原生扫码、连续扫码、相册识别 | 查看插件 |
lizhao-choose-file |
原生文件选择、上传、进度与取消 | 查看插件 |
lizhao-bg-audio |
背景音频播放、队列、倍速与事件 | 查看插件 |
lizhao-smart-tts |
系统 TTS、云端合成、听书方案 | 查看插件 |
lizhao-share-plus |
系统分享、远程文件下载后分享 | 查看插件 |
lizhao-sqlite-pro |
原生 SQLite、迁移、备份与诊断 | 查看插件 |
lizhao-icon-pro |
SVG 图标组件、多主题与缓存 | 查看插件 |
lizhao-cast-screen |
DLNA 投屏、AirPlay 路由入口 | 查看插件 |
lizhao-call-kit |
电话、短信、通讯录原生能力 | 查看插件 |
lizhao-app-keepalive |
应用保活、唤醒、自愈与报告 | 查看插件 |
lizhao-doc-corrector |
文档扫描、矫正、增强与识别 | 查看插件 |
lizhao-emu-detect |
模拟器环境检测、风险评分与证据 | 查看插件 |
lizhao-gallery-pro |
相册媒体分页、筛选、缩略图与导出 | 查看插件 |
lizhao-video-thumb |
视频封面、批量取帧与 Base64 返回 | 查看插件 |
lizhao-ble |
BLE 扫描、连接、读写、通知与自动重连 | 查看插件 |
lizhao-sse-pro |
SSE、Line、JSONL 与 Raw 流式请求 | 查看插件 |
lizhao-pdf-pro |
PDF 阅读、签批、真实写回与页面处理 | 查看插件 |
lizhao-serial-port |
路径串口、USB 串口、多会话收发与诊断 | 查看插件 |
lizhao-wechat-kit |
微信登录、分享、支付、小程序与客服 | 查看插件 |
lizhao-video-editor |
视频裁剪、压缩、取帧与 FFmpeg/FFprobe | 查看插件 |
lizhao-vpn-pro |
企业 VPN、IKEv2、安全接入与脱敏诊断 | 查看插件 |
lizhao-camera-pro |
原生相机、拍照录像、水印与媒体保存 | 查看插件 |
lizhao-tcp-pro |
TCP 客户端、服务端、多连接与诊断 | 查看插件 |
lizhao-notify-pro |
本地通知、点击动作、进度与定时提醒 | 查看插件 |

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 6486
赞赏 5
下载 12638763
赞赏 1950
赞赏
京公网安备:11010802035340号