更新记录

2.0.0(2026-10-22) 下载此版本

  • 新增 Android CameraX + ML Kit、iOS AVFoundation + ML Kit 实时原生引擎
  • 新增 Android/iOS 实时多码,支持定格选择与动态跟踪
  • 新增 App 图片多码和 Web 自定义解码器多码结果
  • 新增 App 原生增强相机连续自动对焦、双指缩放、手动变焦和点按对焦
  • 新增 App 标准相机和 Web 自动变焦
  • 新增码制能力查询,不支持码制通过 fail 明确返回
  • 新增工具栏按钮顺序、文案、图标、颜色、尺寸和自定义事件
  • 新增顶部栏、提示区、结果区和工具栏插槽
  • 新增 Web 摄像头枚举、能力查询、镜头切换和预览截图
  • 新增复制、分享、网址、拨号、WiFi、导航、邮件和短信结果动作

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 鸿蒙 微信小程序
√ - √ √ - √

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

lf-scan-x uni-app x 全平台扫码与多码识别

lf-scan-x 是面向 uni-app x(UTS / uvue)的二维码、条形码扫描组件。插件内置 easycom 组件、全屏扫码页、Android/iOS UTS 原生识别引擎与结果处理工具,一次导入即可覆盖 App、Web 与微信小程序,无需再安装任何第三方扫码依赖。经典 uni-app(Vue2 / Vue3)项目请使用独立的 lf-scan,两个插件互不依赖。

核心特性

能力 说明
🎯 同帧多码识别 单帧画面同时识别多个二维码 / 条形码,按码在画面中的真实位置叠加选择标记,点击即取
🖼️ 图片多码识别 相册选图或传入本地图片路径,一次识别出图中全部码,App / Web 均支持
🧊 定格 + 动态双多码模式 定格模式画面稳定、标记精准;动态模式实时跟踪,码移出画面自动消失
📷 原生识别引擎 Android CameraX + ML Kit、iOS AVFoundation + ML Kit 实时引擎,非 uni.scanCode 包装
🔍 原生级相机控制 连续自动对焦、点按对焦、双指缩放、setZoom() / focusAt()、闪光灯、前后镜头切换
🔁 连续逐个扫描 间隔可调、结果去重,适合仓库盘点、批量录入
🧩 深度 UI 定制 主题色、标题、提示、工具栏按钮的顺序 / 文案 / 图标 / 颜色 / 尺寸,以及 5 个区域插槽
🔗 内容智能解析 URL、WiFi、电话、邮件、短信、vCard、MeCard、日程、地理位置、JSON 等 12 类内容自动识别
⚡ 一键结果动作 复制、分享、打开网址、拨号、连接 WiFi、导航、发邮件、发短信,外部动作自动二次确认
🛰️ 运行时能力查询 getScanCapabilities() 返回引擎、码制与功能能力,不支持的码制通过 fail 明确反馈
🌐 全平台覆盖 App(Android / iOS)、Web(Chrome / Edge / Safari)、微信小程序
📦 零依赖 · 极轻量 纯原生 API 与手写算法实现,无第三方依赖、无广告、无埋点,MIT 开源免费

安装配置

1. 导入插件

在插件市场选择「使用 HBuilderX 导入插件」。组件符合 easycom 规范,无需手动注册:

<lf-scan-x @success="onSuccess"></lf-scan-x>

2. 注册扫码页

插件的 pages_init.json 会在导入时合并扫码页。请确认项目 pages.json 包含:

// #ifdef APP-ANDROID || APP-IOS
,
{
  "path": "uni_modules/lf-scan-x/pages/scan/scan",
  "style": {
    "navigationStyle": "custom",
    "backgroundColorContent": "#000000",
    "backgroundColor": "#000000",
    "bounces": false
  }
}
// #endif

3. App 模块、权限和基座

在 manifest.json 中勾选 uni-barcode-scanning。Android 至少需要相机和震动权限;iOS 至少填写:

{
  "NSCameraUsageDescription": "用于扫描二维码和条形码",
  "NSPhotoLibraryUsageDescription": "用于从相册选择图片识别二维码",
  "NSPhotoLibraryAddUsageDescription": "用于保存扫码截图到相册"
}

连接 WiFi 还需要 Android 的 WiFi、网络状态、定位及 Android 13 NEARBY_WIFI_DEVICES 权限;iOS 需要 com.apple.developer.networking.HotspotConfiguration entitlement。示例项目已包含完整配置。

插件包含 UTS 原生依赖。首次导入、更新原生代码或修改权限后,使用 HBuilderX 4.71+ 重新制作自定义调试基座。Android 最低 API 21;iOS deployment target 为 15.5。

快速开始

<template>
  <lf-scan-x ref="scan" :show-trigger="false" @success="onSuccess" @fail="onFail"></lf-scan-x>
  <button @click="start">开始扫码</button>
</template>

<script setup lang="uts">
import { LfScanResult, LfScanFail } from '@/uni_modules/lf-scan-x/utils/index.uts'

const scan = ref<LfScanXComponentPublicInstance | null>(null)

function start() : void {
  scan.value?.start()
}

function onSuccess(result : LfScanResult) : void {
  console.log(result.result, result.scanType)
}

function onFail(error : LfScanFail) : void {
  console.log(error.type, error.errMsg)
}
</script>

平台能力

平台 自定义扫码页 实时多码 图片多码 变焦/对焦 说明
App Android 支持 支持 支持 支持 Android 5.0+;需自定义基座
App iOS 支持 支持 支持 支持 iOS 15.5+;需自定义基座
Web Chrome/Edge 支持 取决于解码器 取决于解码器 支持缩放 需要 HTTPS 或 localhost
Web Safari 需自定义解码器 取决于解码器 取决于解码器 数字缩放 传入 h5Decoder
微信小程序 系统扫码页 不支持 不支持 由平台控制 使用 uni.scanCode

系统扫码页由运行平台实现,界面、相机控制和多码选择不受组件控制。App 需要完整相机能力时使用默认 auto 模式,或使用 custom 模式在当前页面显示扫码界面。

模式与引擎

mode 如何选择引擎

配置或平台 实际行为
App + mode="auto" 打开插件自带的全屏扫码页
App + mode="custom" 在当前 uvue 页面显示标准相机界面;原生增强会打开原生全屏层
App + mode="api" 调用 uni.scanCode 系统扫码页
Web 使用浏览器相机;mode 不会切换到 uni.scanCode
微信小程序 调用 uni.scanCode,不提供插件自定义相机界面
App + nativeCamera=false + 单码/连续扫描 使用 uni-app x camera 标准相机
App + nativeCamera=true 单码和连续扫描使用 CameraX/AVFoundation 原生增强相机
App + multiple=true 无论 nativeCamera 如何设置,实时多码固定使用原生增强相机

相机能力对照

功能 系统扫码 api App 标准相机 App 原生增强相机 Web 相机
单码扫描 支持 支持 支持 支持
连续逐个扫描 不支持 支持 支持 支持
实时多码选择 不支持 不支持 支持 取决于 BarcodeDetector 或 h5Decoder
定格多码 / 动态多码 不支持 不支持 支持 支持;取决于解码器是否返回位置
连续自动对焦 由系统控制 由 camera 和设备控制 支持 由浏览器和设备控制
点击指定位置对焦 不可控制 不支持 支持 不支持
focusAt() 不支持 不支持 支持 不支持
autoZoom 不控制系统页,系统可能自行变焦 支持 不生效 支持
双指缩放 / setZoom() 不可控制 支持 支持 支持
闪光灯 由系统界面控制 支持 支持 设备和浏览器支持时可用
完全自定义工具栏插槽 不支持 custom 模式支持 原生全屏层不支持插槽,可配置按钮 支持

自动对焦与自动变焦是两个独立能力。系统扫码、标准相机和原生增强相机都会使用各自相机栈的自动对焦;autoZoom 只负责改变画面倍率。原生增强相机保留完整视野,不执行自动变焦,实时多码也不会为某一个码自动放大。用户可双指缩放、点击对焦,或调用 setZoom()、focusAt()。

非相机功能

功能 App Web 微信小程序
图片单码 / 多码 支持 取决于 BarcodeDetector 或 h5Decoder 不支持组件直接识别本地图片
码制能力查询 支持,原生引擎返回明确列表 支持,按浏览器和解码器返回 系统页只能返回平台可声明的范围
结果内容解析与动作 支持 支持,受浏览器权限限制 支持,外部动作受平台安全策略限制
header / tip / result / toolbar 插槽 标准相机 custom 模式支持;独立页和原生全屏层不能跨层传递 支持 系统扫码页不支持

图片识别通过 scanImage() 独立执行,不受 mode 影响。saveImage 依赖当前引擎能否返回识别画面路径;原生实时相机不保证能够保存预览帧,业务需要截图时应以返回的 path 是否为空为准。

Props

属性 类型 默认值 说明
mode string auto auto 插件扫码页;api 系统扫码页;custom 当前页扫码界面
scanType string[] ['qrCode','barCode'] 允许识别的码制
onlyFromCamera boolean false 系统扫码页仅允许相机扫码
autoZoom boolean true App 标准相机和 Web 自动变焦;系统扫码页、原生增强和实时多码不受此属性控制
nativeCamera boolean false App 单码使用原生增强引擎
autoCharset boolean false App 条码字符集自动解析配置
enableAlbum boolean true 显示相册入口
color string #15966A 主题色
frameColor string 空 单码扫描框颜色
scanbarColor string 空 扫描光带颜色
title string 扫码 扫码页标题
tip string 将二维码或条形码完整置于取景框内 扫码提示
showHeader boolean true 显示顶部栏
showFlash boolean true 显示闪光灯操作
showTrigger boolean true 显示默认触发按钮
triggerText string 开始扫描 默认触发按钮文字
showResult boolean true 连续扫码时显示结果摘要
showToolbar boolean true 显示工具栏
toolbarItems LfToolbarItem[] 镜头、闪光灯、相册 工具栏按钮配置;不可用项目自动隐藏
flashText string 闪光灯 闪光灯按钮文字
flashOffText string 关闭 关闭闪光灯文字
albumText string 相册 相册按钮文字
cameraText string 切换镜头 Web 镜头切换按钮文字
autoStart boolean false 挂载后自动开始
continuous boolean false 连续扫码
continuousInterval number 1000 连续回调间隔,毫秒
dedupeTime number 0 相同内容去重窗口,毫秒
multiple boolean false 实时或图片多码识别
dynamicMultiple boolean false 多码标记是否动态更新
maxResults number 0 最大结果数,0 不限制
vibrate boolean true 成功后震动
sound boolean true 成功后播放提示音
soundSrc string 空 自定义提示音地址
saveImage boolean false 保存识别画面
parse boolean true 解析扫码内容
permissionTip boolean true 权限拒绝后显示引导
safeAreaTop string/boolean auto 顶部安全区策略
zIndex number 999 Web 扫码层级
pagePath string 插件扫码页 App 全屏页路径
debug boolean false 输出原始识别数据
h5Decoder Function 空 Web 自定义解码器
h5Facing string environment Web 默认摄像头方向
h5ScanInterval number 200 Web 解码间隔,毫秒

Events

事件 参数 说明
success LfScanResult 识别成功;图片多码包含 results
fail LfScanFail 失败;含错误类型和不支持码制
cancel 无 用户取消
start 无 扫码开始
stop 无 扫码停止
flash-change boolean 闪光灯状态变化
select { result, scanType, index, detectedCount } 用户选择多码结果
toolbar-action { key, text, item } 工具栏操作

Methods

方法 说明
start() / startScan() 开始扫码
stop() / stopScan() 停止扫码
cancel() 取消并触发 cancel
pause() / resume() 暂停或恢复
isScanning() 返回当前状态
toggleFlash() / setFlash(on) 控制闪光灯
setZoom(value, callback?) 设置缩放倍数
focusAt(x, y, callback?) 按归一化坐标对焦
chooseImage() 选择图片识别
scanImage(path) 识别指定图片
getScanCapabilities() 查询码制和功能能力
getResultActions(result?) 获取结果可用动作
executeResultAction(action, result?, options?) 执行结果动作
selectResult(result, index) 选择多码结果
getLastResult() 获取最近结果
getLastImage() 获取最近保存图片
getCameras() / getCameraCapabilities() 获取 Web 摄像头列表或当前能力
switchCamera(deviceId) / toggleCamera() 切换 Web 摄像头
captureImage(type?, quality?) 获取 Web 当前预览截图

Slots

插槽 作用域参数 说明
trigger start、startScan、scanning 自定义触发区
header cancel、title、scanning 自定义顶部栏
tip awaitingSelection、results、tip 自定义提示区
result count、latestText、lastResult 自定义连续扫描结果区
toolbar items、action、flashOn、zoom 自定义工具栏

App 默认 auto 模式使用独立全屏扫码页,插槽不能跨页面传递;需要使用插槽时将 mode 设为 custom。系统扫码页由平台实现,不能应用自定义插槽和工具栏。

数据类型

类型定义统一从 @/uni_modules/lf-scan-x/utils/index.uts 导入。

LfScanResult 识别结果

字段 类型 说明
result string 解码后的字符串内容
scanType string 码制名称,如 QR_CODE、EAN_13、CODE_128
charSet string 字符集,如 UTF-8、GBK
rawData string 原始数据(部分引擎会附加元数据)
path string 图片识别时的图片路径,实时扫描可能为空
source string 结果来源:live(实时)或 image(图片)
platform string 识别平台,如 android、ios、web、weixin
timestamp number 识别时间戳(毫秒)
bounds LfScanBounds \| null 码在预览区域的归一化坐标 { x, y, width, height },取值 0~1
cornerPoints LfScanPoint[] 码的角点坐标数组
imageSize LfScanImageSize \| null 识别图片尺寸 { width, height }
parsed LfScanParsed \| null 内容解析结果,parse=false 时为 null
imageSaved boolean \| null saveImage 是否保存成功
imageSaveError string \| null 保存失败原因

多码批次额外包含:

字段 类型 说明
results LfScanResult[] 完整的子结果列表
detectedCount number 实际检测到的码数量
acceptedCount number 通过码制过滤后的数量
displayedCount number 受 maxResults 限制后展示的数量
selectedIndex number 用户点击选择的码索引

LfScanParsed 内容解析

parse=true(默认)时,组件按内容自动识别类型,填充 result.parsed。字段随 parsed.type 变化:

type 含义 主要字段
url 网址 url、scheme
wifi WiFi 配置 ssid、password、encryption、hidden
vcard 电子名片 name、tels[]、emails[]、org、title、url、address、note
mecard 名片(MeCard) name、tels[]、emails[]、url、address、note、org
event 日历事件 summary、start、end、location、description
tel 电话号码 number
sms 短信 number、body
email 邮箱 email、subject、body
geo 地理位置 latitude、longitude、altitude
product 商品条码 code、format
json JSON 数据 data
text 纯文本 text

所有解析结果均包含 type 与 raw(原始内容)两个公共字段。

LfScanFail 错误对象

字段 类型 说明
errMsg string 错误描述
type string 错误类型,见下方枚举
origin any | null 平台原始错误对象
supportedFormats string[] | null 能力检查失败时,引擎支持的码制
unsupportedFormats string[] | null 能力检查失败时,请求但不支持的码制

错误类型包括 permission、unsupported、scan、album、flash、busy、action 和 cancel。

LfScanCapabilities 能力查询

getScanCapabilities() 返回 LfScanCapabilities,包含 platform、engine、precise、known、requestedFormats、supportedFormats、unsupportedFormats、available 与 features(realtimeMultiple / zoom / focus / customToolbar / resultActions)。可在开始扫描前据此做能力适配。

码制

常用值:qrCode、barCode、barCodeAll、datamatrix、pdf417、aztec、ean13、ean8、upca、upce、codabar、code39、code93、code128、itf、rss14、rssexpanded。

barCodeAll 会按当前引擎能力展开,只请求该引擎实际支持的一维码。显式请求不支持的码制时,组件不会进入扫码页,而是通过 fail 返回明确列表。

结果与动作

import { getScanResultActions, executeScanResultAction } from '@/uni_modules/lf-scan-x/utils/index.uts'

const actions = getScanResultActions(result)
executeScanResultAction('open', result, null)

动作名称为 copy、share、open、call、wifi、navigate、email、sms。

动作 触发条件 是否二次确认
copy 复制 任意结果 否
share 分享 任意结果 否
open 打开网址 parsed.type === 'url' 是
call 拨号 parsed.type === 'tel' 是
wifi 连接 WiFi parsed.type === 'wifi' 是
navigate 导航 parsed.type === 'geo' 是
email 发邮件 parsed.type === 'email' 是
sms 发短信 parsed.type === 'sms' 是

外部应用、拨号、WiFi 和导航默认二次确认,可传 { confirm: false } 关闭。

场景示例

实时多码

<lf-scan-x
  ref="scan"
  :show-trigger="false"
  :multiple="true"
  :dynamic-multiple="false"
  :max-results="0"
  @success="onSuccess"
  @select=""
/>

dynamicMultiple=false 时,检测到多个码后定格当前画面,用户点击对应标记返回结果。dynamicMultiple=true 时保持实时预览,码移出画面后标记自动消失。maxResults=0 不限制结果数量。

原生实时多码会把分析帧中的位置转换到当前预览层,设备倾斜或旋转后仍按屏幕上的实际位置显示标记。bounds 使用当前预览区域的 0 到 1 归一化坐标;不要直接把原始相机像素坐标当作页面坐标使用。

连续扫描

<lf-scan-x
  :continuous="true"
  :continuous-interval="1000"
  :dedupe-time="1500"
  @success="onEachResult"
/>

图片多码

scan.value?.scanImage(tempFilePath)
// 或直接打开相册
scan.value?.chooseImage()

组件设置 multiple=true 时,完整结果列表位于 result.results,并返回 detectedCount、acceptedCount 和 displayedCount。

原生相机增强

<lf-scan-x :native-camera="true" />

App 开启 nativeCamera 后使用原生 CameraX/AVFoundation 引擎,支持连续自动对焦、双指缩放、点按对焦、setZoom() 和 focusAt()。实时多码始终使用原生引擎。原生增强模式不执行 autoZoom。

自定义工具栏

import { LfToolbarItem } from '@/uni_modules/lf-scan-x/utils/index.uts'

const toolbarItems : LfToolbarItem[] = [
  { key: 'flash', text: '补光' } as LfToolbarItem,
  { key: 'album', text: '图片' } as LfToolbarItem,
  { key: 'help', text: '说明', icon: '?', backgroundColor: '#24372F' } as LfToolbarItem
]
<lf-scan-x :toolbar-items="toolbarItems" @toolbar-action="onToolbarAction" />

内置键包括 flash、album、camera、input、close、pause、resume、zoom-in 和 zoom-out。未知键不执行内置操作,只触发 toolbar-action。所有按钮点击后都会触发该事件,参数包含 key、text 和完整的 item 配置。

Web 自定义解码器

<lf-scan-x :h5-decoder="decode" :multiple="true" />

解码器签名为 (imageData, { width, height, canvas }) => result,可同步或异步返回字符串、单个 { result, scanType, bounds }、结果数组或 { results }。多码位置 bounds 使用 0 到 1 的归一化坐标。

相机控制

scan.value?.toggleFlash()
scan.value?.setZoom(2.5, (v : number) => {})
scan.value?.focusAt(0.5, 0.5, () => {})
scan.value?.toggleCamera()          // Web 切换前后镜头
scan.value?.captureImage('png', 0.9) // Web 获取当前预览截图

常见问题

扫码黑屏 / 无画面? 确认已勾选 uni-barcode-scanning 模块、权限已授权,且 App 端已重新制作包含插件 UTS 原生依赖的自定义基座。

App 点扫码没反应? 检查 pages.json 是否已注册 uni_modules/lf-scan-x/pages/scan/scan;未注册时会改用系统扫码页。

Web 无法调用摄像头? 浏览器要求 HTTPS 或 localhost;Safari 无原生 BarcodeDetector,需传入 h5Decoder。最终能力以 getScanCapabilities() 返回为准。

多码标记位置不准? 标记基于预览区域的归一化坐标;请勿把原始相机像素坐标当页面坐标。若做了自定义缩放或裁剪,请核对坐标映射。

请求的码制不生效? 组件会在启动前校验码制能力,不支持的码制通过 fail 返回 supportedFormats / unsupportedFormats,请据此调整 scanType。

实时多码画面卡顿? 实时多码固定走原生引擎,请确认已使用自定义基座;Web 端性能取决于浏览器 BarcodeDetector 与设备算力。

隐私说明

插件仅在设备本地处理相机画面、用户主动选择的图片和扫码结果,不采集、不存储、不上传数据。相机用于实时扫码;相册用于图片识别或保存截图;震动用于成功反馈;WiFi、网络状态和定位权限只在业务主动执行 WiFi 连接动作时使用。宿主应用仍需根据实际业务完善隐私政策和权限用途说明。

注意事项

  • 原生依赖或权限变化后必须重新制作自定义基座,旧基座不会自动包含新能力。
  • 动态多码适合持续跟踪;定格多码位置更稳定,默认建议使用定格模式。
  • H5 相机必须运行在 HTTPS 或 localhost,最终能力以 getScanCapabilities() 返回为准。
  • Android 10 及以上连接 WiFi 时会显示系统授权面板;Android 9 及以下直接写入系统 WiFi 配置。
  • 发布前应在目标设备复核相机、权限和外部结果动作;跨平台编译通过不等于真机行为验证。

许可证

MIT License,详见 license.md。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

相机权限用于实时扫码;相册权限用于图片识别或保存截图;震动权限用于识别成功反馈;WiFi、网络状态和定位权限仅在业务主动调用 WiFi 连接动作时使用。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件仅在设备本地处理相机画面、用户选择的图片和扫码结果,不采集、不存储、不上传任何用户数据。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT License

Copyright (c) 2026 lf-scan contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

暂无用户评论。