更新记录

1.3.3(2026-10-04) 下载此版本

  • package.json 的 displayName 改为简介内容去掉标点符号的版本
    • 与 description 信息保持一致,便于插件市场的检索匹配
    • 去掉中英文标点(,。、/ 等),并合并多余空格
    • 当前长度 107 字

1.3.2(2026-10-04) 下载此版本

  • 调整 demo 页结构,解决「小程序端点哪个扫码都一样」的困惑
    • 现象:使用者在小程序端依次点击各 API 按钮,发现界面全无区别, 误以为插件失效(控制台其实已打印被忽略的参数警告)
    • 原因:demo 页把「组件用法」放在了最底部,而小程序端只有组件能自定义界面, API 按钮全部走微信原生扫码页
    • 处理:
    • 把「组件用法」卡片移到页面最顶部,并用主推样式(蓝色边框)突出
    • 小程序端说明卡片改为对比式说明(API vs 组件 的能力差异), 并明确指向「用组件打开扫码」按钮
    • 小程序端在 API 区块前加一条分段提示 「以下均为 API 用法 · 小程序端界面参数不生效」

平台兼容性

uni-app(5.0)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× √ √ √ √ × √ √ √
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ × × × × × × × × × × ×

simple-scan 扫码插件

跨平台扫码 UTS 插件,内置自定义全屏扫码页。支持二维码与条形码、手电筒、相册识别,可定制标题、提示与扫码框配色。

平台支持

⚠️ 小程序与鸿蒙端无法自定义界面(重要)

微信小程序与鸿蒙端的扫码界面由系统提供,插件只能调起系统扫码页。 因此 frameColor、frameSize、frameStyle、titleColor、buttonColor、 continuous、multi、customButtons 等所有界面与交互参数在这两端都不生效。

表现为:无论怎么配置,扫码页看起来都一样。

这不是 bug,是平台限制:

  • 小程序端转发到 uni.scanCode,唤起的是微信原生扫码页, 该接口没有任何 UI 定制参数
  • 鸿蒙端调用系统 Scan Kit,界面同样由系统控制

👉 小程序端需要自定义界面,请改用 <simple-scan-view> 组件 —— 组件在小程序端用 <camera> + cover-view 自绘界面,界面参数全部生效, 详见「组件用法」。 也可以改用 App(Android / iOS)或 H5,这两端用 scanCode() API 即可自定义。

平台 实现方式 自定义 UI
App-Android CameraX + ML Kit,Kotlin 原生全屏页 ✅ 完整支持
App-iOS AVCaptureSession + Vision,Swift 原生全屏页 ✅ 完整支持
App-鸿蒙 系统 Scan Kit ❌ 系统 UI
H5 getUserMedia + jsQR,DOM 自绘界面 ✅ 完整支持
微信小程序 API 转发 uni.scanCode;组件用 <camera> 自绘 组件 ✅ / API ❌

小程序端在传入上述界面参数时,控制台会打印一条 [simple-scan] 开头的 警告并列出被忽略的参数,便于排查「配了没效果」的困惑。

功能支持矩阵

小程序分两列:组件 指 <simple-scan-view>,API 指 scanCode()。 两者能力差异很大,建议小程序端优先用组件,见上文「组件用法」。

界面类参数

参数 Android iOS 鸿蒙 H5 小程序·组件 小程序·API
title / tip ✅ ✅ ❌ ✅ ✅ ❌
titleColor / titleSize ✅ ✅ ❌ ✅ ✅ ❌
tipColor / tipSize ✅ ✅ ❌ ✅ ✅ ❌
showClose ✅ ✅ ❌ ✅ ✅ ❌
frameColor ✅ ✅ ❌ ✅ ✅ ❌
frameSize / frameRadius ✅ ✅ ❌ ✅ ✅ ❌
frameStyle ✅ ✅ ❌ ✅ ✅ ❌
scanLine / scanLineColor ✅ ✅ ❌ ✅ ⚠️ ❌
maskColor ✅ ✅ ❌ ✅ ✅ ❌
buttonColor / buttonBgColor ✅ ✅ ❌ ✅ ✅ ❌

功能类参数

参数 Android iOS 鸿蒙 H5 小程序·组件 小程序·API
基础扫码 ✅ ✅ ✅ ✅ ✅ ✅
scanType 码类型 ✅ ✅ ✅ ❌ ❌ ✅
showTorch 手电筒 ✅ ✅ ❌ ⚠️ ✅ ❌
showAlbum 相册识别 ✅ ✅ ✅ ✅ ❌ ❌
albumMultiple 相册批量 ✅ ✅ ❌ ✅ ❌ ❌
vibrate 震动反馈 ✅ ✅ ❌ ❌ ✅ ❌
continuous 连续扫码 ✅ ✅ ❌ ✅ ✅ ❌
multi 多码识别 ✅ ✅ ❌ ❌ ❌ ❌
customButtons / onButtonTap ✅ ✅ ❌ ✅ ✅ ❌

矩阵说明

  • ⚠️ scanLine 在小程序·组件:cover-view 对 CSS 动画支持有限, 目前是静态线条,没有上下往返动画
  • ⚠️ showTorch 在 H5:依赖浏览器的 torch 能力,仅部分设备支持
  • ❌ scanType 在 H5:底层 jsQR 只解二维码,返回类型固定为 qrCode
  • ❌ scanType 在小程序·组件:<camera mode="scanCode"> 没有码类型过滤参数
  • ❌ showAlbum 在小程序·组件:<camera mode="scanCode"> 只能实时扫码, 不支持从相册选图(需要相册识别请用 API 或 App / H5)
  • ❌ multi 在 H5:jsQR 单帧只能解出一个码
  • ❌ 鸿蒙的界面类参数:界面由系统 Scan Kit 提供,无法定制

小程序端自定义扫码界面

微信小程序可以自定义扫码界面,但需要用页面级的 <camera> 组件, 而不是 uni.scanCode:

<template>
    <view class="scan-page">
        <camera
            mode="scanCode"
            device-position="back"
            flash="auto"
            @scancode="onScanCode"
            @error="onCameraError"
        >
            <!-- camera 是原生组件,层级高于普通 view,
                 叠加 UI 必须用 cover-view / cover-image -->
            <cover-view class="scan-frame" />
        </camera>
    </view>
</template>

关键点:

项 说明
mode="scanCode" 启用扫码模式,识别到码时触发 @scancode
cover-view / cover-image 必须用它们做覆盖层,普通 view 会被相机的原生层级盖住
flash auto / on / off / torch,可实现手电筒开关
scanArea 指定识别区域 [x, y, w, h],仅在 scanCode 模式生效
wx:if 控制显隐要用 wx:if 而非 hidden,否则相机资源不释放

插件已提供组件实现,不需要你自己写页面

上述逻辑已封装进 <simple-scan-view> 组件(见上文「组件用法」), 小程序端直接用即可:

<simple-scan-view
    v-model:visible="showScan"
    frame-color="#19be6b"
    frame-style="border"
    @success="onSuccess"
/>

下面这些要点是组件内部的实现细节,列出来是为了方便你排查问题 (比如覆盖层被遮挡、相机不释放等),日常使用不需要关心。

H5 端依赖安装(必做)

H5 端的解码使用 jsQR, 依赖声明在 utssdk/web/package.json 中。

从插件市场导入后需要在该目录安装依赖,否则运行到 H5 会报 Failed to resolve import "jsqr":

cd uni_modules/simple-scan/utssdk/web
npm install

说明:web/package.json 只声明依赖,不会自动安装。 这是 UTS 插件在 web 平台引入 npm 依赖的标准做法。

如果不想引入这个依赖,也可以改用浏览器原生的 BarcodeDetector API(零依赖), 但 Safari 与 Firefox 不支持该 API,会失去这两个浏览器的扫码能力。

安装

  1. 在 HBuilderX 中打开你的项目
  2. 访问 DCloud 插件市场,搜索 simple-scan
  3. 点击「下载插件并导入 HBuilderX」,选择你的项目

导入后插件位于 uni_modules/simple-scan。

快速上手

<script>
import { scanCode } from '@/uni_modules/simple-scan'

export default {
    methods: {
        onScan() {
            scanCode({
                success: (res) => {
                    console.log('扫描结果:', res.result)
                    console.log('码类型:', res.scanType)
                },
                fail: (err) => {
                    console.log('失败:', err.errCode, err.errMsg)
                }
            })
        }
    }
}
</script>

组件用法(推荐)

除 scanCode() API 外,插件还提供 <simple-scan-view> 组件。 easycom 已自动注册,无需 import。

<template>
    <view>
        <simple-button text="扫码" @click="showScan = true" />

        <simple-scan-view
            v-model:visible="showScan"
            title="组件扫码"
            tip="对准二维码即可识别"
            frame-color="#19be6b"
            frame-style="border"
            @success="onSuccess"
            @fail="onFail"
        />
    </view>
</template>
export default {
    data() {
        return { showScan: false }
    },
    methods: {
        onSuccess(res) {
            console.log('扫描结果:', res.result)
        }
    }
}

组件 vs API 怎么选

场景 推荐
微信小程序 + 需要自定义界面 组件(API 在小程序端无法自定义界面)
其他平台 两者都行,看编码习惯

组件内部按平台分流:

平台 组件内部实现 自定义界面
微信小程序 <camera mode="scanCode"> + cover-view 自绘 ✅
App-Android / iOS 转交 UTS 原生全屏页 ✅
H5 转交 UTS 的 DOM 覆盖层实现 ✅

为什么 App / H5 也转交 UTS? 因为 uni-app 的 <camera> 组件只在各小程序端支持, App 与 H5 没有 camera 组件,组件内无法渲染相机预览。

组件属性

属性名与 scanCode() 的参数一一对应,仅多一个 visible:

属性 类型 默认值 说明
visible Boolean false 扫码层显隐,配合 v-model:visible
其余属性 - - 与下方「参数」表完全一致

组件事件

事件名 说明 回调参数
update:visible 显隐变化(v-model:visible 自动处理) visible
success 识别成功 同 scanCode 的 success 参数
fail 失败 同 scanCode 的 fail 参数
close 扫码层关闭 -
buttonTap 自定义按钮点击 { id }

API

scanCode(options)

调起扫码页。

参数

属性 类型 默认值 说明
scanType Array ['qrCode','barCode'] 需要识别的码类型。可选 qrCode / barCode / datamatrix / pdf417。传得越少识别越快
onlyFromCamera Boolean false 只允许相机扫码(为 true 时强制隐藏相册入口)
title String 扫码 扫码页标题,传空字符串则不显示标题栏
titleColor String #ffffff 标题文字颜色
titleSize Number 17 标题字号(px)
showClose Boolean true 是否显示左上角关闭按钮
tip String 将二维码放入框内,即可自动扫描 扫码框下方的提示文案
tipColor String #dddddd 提示文字颜色
tipSize Number 14 提示文字字号(px)
frameColor String #2979ff 扫码框颜色
frameSize Number 0.68 扫码框边长占屏幕短边的比例,取值 0.4 ~ 0.9
frameRadius Number 6 扫码框圆角(px)
frameStyle String corner 扫码框样式:corner 四角 / border 全边框 / none 无框
scanLineColor String 跟随 frameColor 扫描线颜色
maskColor String #99000000 扫码框外遮罩颜色
buttonColor String #ffffff 底部按钮文字颜色
buttonBgColor String #33ffffff 底部按钮背景色
showTorch Boolean true 是否显示手电筒按钮(设备无闪光灯时自动隐藏)
showAlbum Boolean true 是否显示相册入口
vibrate Boolean true 识别成功后是否震动(H5 不支持)
continuous Boolean false 连续扫码。相机不关闭,每识别一个回调一次,同一个码 2 秒内只回调一次
multi Boolean false 多码识别。一帧画面中的多个码一次性全部返回(H5 不支持)
albumMultiple Boolean false 相册批量。相册支持多选,配合 multi 可一次识别多张
customButtons Array [] 自定义按钮。格式 [{ id, text }],点击触发 onButtonTap
scanLine Boolean true 是否显示扫码框内的扫描线动画
onButtonTap Function - 自定义按钮点击回调
success Function - 成功回调
fail Function - 失败回调
complete Function - 完成回调

success 回调参数

属性 类型 说明
errMsg String 成功时为 scanCode:ok
result String 扫描到的内容
scanType String 实际识别出的码类型
charSet String 字符集,固定 UTF-8
path String 码图片路径;相册识别时有值
index Number 序号。多码模式为帧内序号,连续模式为会话内第几次识别,从 0 开始
total Number 本次回调涉及的码总数。普通模式固定 1

complete 回调参数

普通模式与 success 参数相同。连续模式下在关闭扫码页时触发,参数为:

属性 类型 说明
errMsg String 固定 scanCode:complete
count Number 本次会话累计识别到的数量
cancelled Boolean 是否被用户主动取消

onButtonTap 回调参数

属性 类型 说明
errMsg String 固定 scanCode:buttonTap
id String 被点击按钮的 id
continuous Boolean 点击时是否处于连续扫码模式

fail 回调参数

属性 类型 说明
errCode Number 错误码,见下表
errMsg String 错误描述
errSubject String 错误主题,固定 simple-scan

错误码

errCode 含义
9010001 用户取消
9010002 相机权限被拒绝
9010003 相机不可用
9010004 未识别到有效码
9010005 当前平台不支持
9010006 相册权限被拒绝
9010008 H5 非安全上下文,无法访问摄像头(需 https 或 localhost)

9010008 是 H5 最常见的报错。浏览器的 navigator.mediaDevices 只在安全上下文中存在,因此用 http:// + 局域网 IP (如 http://192.168.1.100:5173/)打开页面时会报此错。 改用 http://localhost:5173/ 或部署到 https 即可。

用法示例

只识别二维码(更快)

scanCode({
    scanType: ['qrCode'],
    title: '扫一扫',
    tip: '将二维码放入框内',
    success: (res) => { console.log(res.result) }
})

自定义配色与文案

scanCode({
    title: '扫码核销',
    tip: '请对准商品二维码',
    frameColor: '#19be6b',
    maskColor: '#B3000000',
    showTorch: true,
    showAlbum: true,
    vibrate: true,
    success: (res) => { console.log(res.result) }
})

只允许相机扫码

scanCode({
    onlyFromCamera: true,
    success: (res) => { console.log(res.result) }
})

连续扫码(盘点 / 入库)

相机不关闭,扫一个回调一次,适合批量录入场景。

scanCode({
    continuous: true,
    title: '连续扫码',
    tip: '对准二维码,可连续扫描',
    success: (res) => {
        // 每识别到一个就回调一次,自行累积即可
        console.log('第', res.index + 1, '个:', res.result)
    },
    complete: (res) => {
        // 关闭扫码页时触发,res.count 为本次累计数量
        console.log('共识别', res.count, '个')
    }
})

同一个码在 2 秒内只会回调一次,避免相机每秒几十帧导致重复触发。

多码同时识别

一帧画面里的多个码会一次性全部返回。

scanCode({
    multi: true,
    success: (res) => {
        console.log('第', res.index + 1, '/', res.total, '个:', res.result)
    }
})

相册批量识别

scanCode({
    albumMultiple: true,   // 相册多选
    multi: true,           // 配合多码识别,一张图里的多个码也都能识别
    success: (res) => {
        console.log(res.result, res.index + 1, '/', res.total)
    }
})

自定义按钮位

UTS 插件无法接收 Vue 插槽,因此用「传配置数组」的方式在扫码页上加按钮。

scanCode({
    customButtons: [
        { id: 'manual', text: '手动输入' }
    ],
    onButtonTap: (res) => {
        if (res.id === 'manual') {
            // 这里可以跳转到自己的「手动输入」页
        }
    },
    success: (res) => { console.log(res.result) }
})

关闭扫描线动画

scanCode({
    scanLine: false,
    success: (res) => { console.log(res.result) }
})

界面定制

扫码页的所有视觉元素都可以通过参数定制,不需要写代码。

限制说明:UTS 插件是原生能力层,无法接收 Vue 插槽, 因此不能把自定义的 Vue 组件放进扫码页。 需要在扫码页上增加交互入口时,用 customButtons(见上文「自定义按钮位」)。

可定制项一览

分类 参数 说明
扫码框 frameColor 边框 / 角标颜色
frameSize 大小(占屏幕短边比例,0.4 ~ 0.9)
frameRadius 圆角
frameStyle corner 四角 / border 全边框 / none 无框
scanLine / scanLineColor 扫描线开关与颜色
遮罩 maskColor 框外遮罩颜色(支持 #AARRGGBB 带透明度)
标题 title / titleColor / titleSize 文案、颜色、字号
showClose 是否显示关闭按钮
提示 tip / tipColor / tipSize 文案、颜色、字号
按钮 buttonColor / buttonBgColor 按钮文字与背景色
showTorch / showAlbum / customButtons 按钮显隐与自定义按钮

完整示例:品牌主题

scanCode({
    title: '扫码核销',
    tip: '请对准商品二维码',
    frameColor: '#ff6b00',        // 扫码框橙色
    frameSize: 0.75,              // 放大到短边的 75%
    frameRadius: 16,              // 圆角
    frameStyle: 'border',         // 完整边框
    scanLineColor: '#ffcc00',     // 扫描线单独配色
    maskColor: '#B3000000',       // 遮罩加深
    titleColor: '#ffffff',
    titleSize: 18,
    tipColor: '#ffd8a8',
    tipSize: 15,
    buttonColor: '#ff6b00',
    buttonBgColor: '#33ff6b00',
    success: (res) => { console.log(res.result) }
})

完整示例:极简

scanCode({
    title: '',                    // 不要标题
    tip: '',
    showClose: true,              // 保留关闭按钮,否则没法退出
    frameStyle: 'none',           // 不画框
    scanLine: false,              // 不要扫描线
    maskColor: '#66000000',       // 遮罩调浅
    success: (res) => { console.log(res.result) }
})

⚠️ title 与 tip 传空字符串即可隐藏,但建议保留 showClose: true—— 否则用户在扫码页上没有可见的退出入口(Android 物理返回键仍可退出)。

生效平台

上述界面参数仅 Android / iOS / H5 生效。 鸿蒙与微信小程序由系统提供扫码界面,配色、字号、框样式等参数不生效。

已知限制

不支持 DPM 码

DPM(Direct Part Marking,直接零件打标)码无法识别。

DPM 指激光蚀刻在金属 / 塑料表面的点状 DataMatrix 码,常见于工厂零部件盘点。 本插件底层依赖的 ML Kit Barcode Scanning 不支持 DPM (Google 官方仓库 issue #1053 已确认「DPM Data Matrix / ECC 200 检测不到」),iOS 的 Vision 同样不支持。

这是底层引擎的限制,不是插件实现问题。DPM 需要专门的工业解码算法, 目前只有商业方案提供:

方案 说明
Dynamsoft Barcode Reader 明确支持 DPM,需商业授权
Cognex / Datalogic 工业视觉方案,需商业授权
工业扫码枪 如 HPRT N180 等支持 DPM 的专用设备

DPM 场景建议直接使用工业扫码枪,手机方案的识别率难以满足产线要求。

识别率受图像质量影响

情况 说明
轻微模糊 / 褶皱 / 低对比度 通常可正常识别
电子屏摩尔纹 摩尔纹是采样干涉产生的信息污染,难以通过算法还原
强反光 / 遮挡 属信息丢失,无法识别
破损面积过大 二维码纠错容量有限,超出即无法还原

本插件未做额外的图像增强预处理。若场景对识别率有更高要求, 建议在采集端改善光照与对焦——效果远好于事后算法补偿。

App 端运行环境(Android)

本插件在 Android 端依赖以下三方库,因此无法用标准基座直接运行:

依赖 用途
androidx.camera:* 相机预览与逐帧分析
com.google.mlkit:barcode-scanning 条码解码(自带算法,不依赖 Google Play 服务)
androidx.activity CameraX 需要的 LifecycleOwner

运行到 Android 真机时若报 kotlin编译失败 / 找不到名称 "camera", 说明本地编译环境尚未配置,HBuilderX 无法下载上述依赖。二选一:

方案一:配置本地运行环境(推荐)

HBuilderX【设置 - 运行配置】(4.27 之前为「设置 - 插件配置」)需填三项:

项 要求
Gradle ≥ 7.5,且 < 9.0(9.0 及以上暂不支持)
Gradle JDK 17(HBuilderX 4.27+ 内置 JDK 17;Gradle 8+ 最低要求 17)
Android SDK build-tools ≥ 30.0.0,platforms ≥ android-30

SDK 可通过安装 Android Studio 获得(首次启动会自动下载), 或单独下载 Command line tools 后手动安装:

sdkmanager --sdk_root=%sdk路径% --install "build-tools;30.0.0"
sdkmanager --sdk_root=%sdk路径% --install "platforms;android-30"

配置完成后首次运行会自动下载依赖,缓存到 用户目录/.gradle/caches, 之后运行会跳过检测和下载。

官方文档:Android UTS 扩展开发

方案二:云端打包自定义基座

不想装本地环境时,可提交云端打包自定义基座。 代价是每次改动原生代码都要重新打包,调试较慢。

⚠️ 若报错信息末尾出现 [AI修复],不用理会—— 这属于运行环境未配置,不是代码问题,AI 修复也改不动环境。

注意事项

  1. App 端需自定义基座:插件依赖 CameraX 与 ML Kit(Android)、AVFoundation(iOS), 这些原生依赖需云端打包才能生效。标准基座无法运行 App 端扫码。

    Kotlin 混编代码本身标准基座即可生效,但 config.json 中声明的第三方依赖需要自定义基座。

  2. iOS 需要相机权限描述:在 manifest.json 的 iOS 配置中补充 NSCameraUsageDescription 与 NSPhotoLibraryUsageDescription,否则提交审核会被拒。
  3. 鸿蒙与小程序端 UI 由系统提供:frameColor / maskColor 两个配色参数在这两端不生效, 其余参数(标题、提示、手电筒、相册、码类型)正常。
  4. H5 端需要 https:浏览器出于安全限制,非 https / localhost 环境无法访问摄像头。
  5. 相册识别:Android 走 SAF 选图,无需存储权限;iOS 走系统相册选择器。

目录结构

uni_modules/simple-scan/
├── components/
│   └── simple-scan-view/
│       └── simple-scan-view.vue   # Vue 组件(小程序端自绘界面)
├── utssdk/
│   ├── interface.uts          # 对外 API 声明
│   ├── unierror.uts           # 错误码实现
│   ├── utils.uts              # 参数归一化与回调分发(各平台共用)
│   ├── index.uts              # 兜底实现(未支持平台)
│   ├── app-android/
│   │   ├── config.json        # CameraX + ML Kit 依赖
│   │   ├── AndroidManifest.xml
│   │   ├── ScanNative.kt      # UTS 桥接
│   │   ├── ScanActivity.kt    # 全屏扫码页
│   │   ├── ScanFrameView.kt   # 扫码框遮罩
│   │   └── index.uts
│   ├── app-ios/
│   │   ├── config.json
│   │   ├── ScanNative.swift   # UTS 桥接
│   │   ├── ScanViewController.swift
│   │   └── index.uts
│   ├── app-harmony/index.uts
│   ├── web/
│   │   ├── package.json       # jsqr 依赖
│   │   └── index.uts
│   └── mp-weixin/index.uts
├── package.json
├── readme.md
└── changelog.md

更新日志

见 changelog.md

隐私、权限声明

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

相机权限(CAMERA)、相册读取权限(仅相册识别功能需要)

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

本插件不采集、不上传任何用户数据

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

无

许可协议

MIT协议

暂无用户评论。