更新记录
1.1.1(2026-08-09)
修复已知错误
1.1.0(2026-08-09)
增加图片返回和参数配置
1.0.1(2026-08-08)
更新Info.plist
查看更多平台兼容性
uni-app(5.0)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | Android | iOS | iOS插件版本 | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | √ | 1.0.0 | - | - | 18 | 1.0.0 | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(5.0)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | - | - | - | - |
miko-scanqrcode
UTS 插件 — SwiftUI 实现的二维码扫描器(iOS 18+),支持自定义 UI 配置与快照返回。
功能特性
- 🚀 SwiftUI 原生实现 — iOS 18+,单 / 多二维码识别
- 🎨 9 个可配置项 — 按钮显隐、动效开关、圆点颜色、延迟启动、提示音、震动等
- 📷 快照双返回 — 同时返回 JPEG Base64(兼容)与本地文件绝对路径(更轻量)
- 🖼 相册识别 — 从系统相册选图识别二维码
- 🔦 手电筒 + 翻转摄像头 — 顶部 / 底部按钮栏
- ✅ 多码选择 — 检测到多个二维码时显示彩色圆点,点击选择
- 🔊 独立反馈开关 — 提示音与震动是两个独立开关,可单独控制
安装
本插件是 uni_modules 模块,直接放在项目的 uni_modules/miko-scanqrcode/ 目录即可。
uni_modules/
└── miko-scanqrcode/
├── package.json
├── readme.md
└── utssdk/
├── interface.uts # UTS 类型定义
├── unierror.uts # 错误码定义
└── app-ios/
├── ScannerView.swift # SwiftUI 扫码主视图
├── ScannerController.swift # AVCaptureSession 控制器
├── ScanQRBridge.swift # UTS ↔ Swift 桥接(含 DTO + 配置解析)
└── index.uts # iOS 端 UTS 调用入口
平台:目前仅 iOS(iOS 18+)。
快速开始
1. 最小化调用(使用全部默认配置)
import { scanQRCode } from "@/uni_modules/miko-scanqrcode";
scanQRCode({
success: (res) => {
console.log("二维码内容:", res.value);
console.log("快照 Base64 长度:", res.imageBase64.length);
console.log("快照本地路径:", res.imageURL);
},
fail: (err) => {
console.log("失败:", err.code, err.message);
},
complete: () => {},
});
2. 自定义配置
import { scanQRCode } from "@/uni_modules/miko-scanqrcode";
scanQRCode({
options: {
// 9 个可选项,按需传(缺省时用默认值)
showSwitchCamera: true, // 显示翻转摄像头按钮
showPhotoPicker: true, // 显示从相册选择按钮
showTorch: true, // 显示手电筒按钮
animationEnabled: true, // 显示扫描线动效
showQRCodeDot: true, // 多码时显示彩色圆点
dotColorHex: "#ff8800", // 圆点颜色(HEX,可带 alpha)
scanStartDelayMs: 800, // 进入页面后延迟 800ms 再扫描
soundEnabled: false, // 关闭提示音
vibrationEnabled: true, // 开启震动
},
success: (res) => {
// 处理结果...
},
});
API 参考
scanQRCode(options: ScanQRCodeOptions): void
异步扫码方法,弹出全屏 SwiftUI 扫码页面,识别完成后自动关闭并通过回调返回结果。
ScanQRCodeOptions
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
options |
ScanQRCodeConfiguration |
否 | UI 与行为配置,未传则用全部默认值 |
success |
(res: any) => void |
否 | 识别成功回调,res 是 MikoScanResultDTO |
fail |
(err: any) => void |
否 | 异常失败回调,err 是 MikoScanErrorDTO |
complete |
(res: any) => void |
否 | 结束回调(success/fail 谁触发就传谁) |
ScanQRCodeConfiguration(配置字典)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
showSwitchCamera |
boolean |
true |
顶部右上:翻转前后摄像头按钮 |
showPhotoPicker |
boolean |
true |
底部右:从系统相册选择图片识别 |
showTorch |
boolean |
true |
底部中央:手电筒开关 |
animationEnabled |
boolean |
true |
中央绿色扫描线上下循环动效 |
showQRCodeDot |
boolean |
true |
检测到多个二维码时显示彩色圆点供点击选择 |
dotColorHex |
string |
"#00ff00" |
圆点颜色(HEX,支持 #RRGGBB 与 #RRGGBBAA,# 可省略) |
scanStartDelayMs |
number |
0 |
进入页面后延迟启动扫描的毫秒数(0 = 立即) |
soundEnabled |
boolean |
false |
识别成功播放系统提示音(AudioServicesPlaySystemSound(1057)) |
vibrationEnabled |
boolean |
true |
识别成功震动反馈(UIImpactFeedbackGenerator.medium) |
所有字段均为可选。Swift 端会以
ScannerConfiguration.default兜底缺失字段,类型错误也会回退到默认值。
返回结果 MikoScanResultDTO
识别成功时传给 success / complete 的对象字段:
| 字段 | 类型 | 说明 |
|---|---|---|
value |
string |
二维码内容(解码后的原始字符串) |
imageBase64 |
string |
冻结画面快照的 JPEG Base64(失败时为空字符串 "") |
imageURL |
string |
快照写入 tmp 目录后的绝对文件 URL(如 file:///var/.../scanqrcode_xxx.jpg),可直接赋给 <image :src="..."> 显示,省内存 |
width |
number |
快照尺寸宽度(pt) |
height |
number |
快照尺寸高度(pt) |
scale |
number |
屏幕 scale(用于 1:1 像素换算) |
两种显示快照的方式:
// 方式 1:用 imageURL(推荐,文件已经在 tmp 里,<image> 直接读本地,加载快、内存小)
uni.previewImage({ urls: [res.imageURL] });
// 方式 2:用 imageBase64(兼容旧用法,SwiftUI Text(base64) 解析稍重)
const src = "data:image/jpeg;base64," + res.imageBase64;
imageURL指向NSTemporaryDirectory()下,每次扫码会生成独立 UUID 文件名。若需长期保留,可读取后自行转存到持久目录。
错误返回 MikoScanErrorDTO
| 字段 | 类型 | 说明 |
|---|---|---|
code |
number |
错误码(见下表) |
message |
string |
用户可读的错误描述 |
errStr |
string? |
原始异常字符串(可选) |
错误码
| 错误码 | 含义 |
|---|---|
9010001 |
无法获取当前页面(顶层 ViewController 不存在) |
9010002 |
用户未授权相机权限(暂未使用,预留) |
9010003 |
启动摄像头失败(暂未使用,预留) |
9010004 |
用户主动取消(注意:当前 ScannerView 未提供 onCancel 回调,用户点返回时直接 dismiss,不会触发 fail 回调) |
完整示例
<template>
<view>
<button @click="onScan">扫码</button>
<image v-if="result" :src="result.imageURL" mode="widthFix" />
</view>
</template>
<script lang="uts">
import { scanQRCode } from "@/uni_modules/miko-scanqrcode";
export default {
data() {
return {
result: null as any,
};
},
methods: {
onScan() {
// 关闭提示音 / 手电筒,方便静默识别
scanQRCode({
options: {
showTorch: false,
soundEnabled: false,
scanStartDelayMs: 600,
},
success: (res: any) => {
this.result = res;
console.log("识别到:", res.value);
},
fail: (err: any) => {
uni.showToast({ title: err.message, icon: "none" });
},
});
},
},
};
</script>
实现说明
三层架构
┌─────────────────────────────────────────────────────────────┐
│ Vue / nvue 调用层(pages/index/index.vue) │
│ - 拿到 ScanQRCodeConfiguration 字典、success/fail/complete│
└───────────────────────────┬─────────────────────────────────┘
│ UTS (interface.uts + index.uts)
┌───────────────────────────▼─────────────────────────────────┐
│ UTS 桥接层(app-ios/index.uts) │
│ - 仅做透传:options 字典原样转 Swift,DTO 对象原样回传 │
│ - 不做字段拆解(UTS 的 any 在 Swift 是 Any,无法做下标) │
└───────────────────────────┬─────────────────────────────────┘
│ @objc 暴露
┌───────────────────────────▼─────────────────────────────────┐
│ Swift 桥类层(ScanQRBridge.swift) │
│ - 解析 options → ScannerConfiguration │
│ - ScanResult → MikoScanResultDTO │
│ - UIHostingController 弹出 ScannerView │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────┐
│ SwiftUI 视图层(ScannerView.swift + ScannerController.swift)│
│ - AVCaptureSession + 元数据识别 │
│ - 多码稳定期、单码确认延迟 │
│ - 冻结画面快照写入 tmp │
│ - SwiftUI 动画 / 手电筒 / 摄像头切换 │
└─────────────────────────────────────────────────────────────┘
关键设计决策
- DTO 中转:UTS 的
any在 Swift 端编译为Any,既不下标也不能 cast 成自定义类型,因此 Swift 端必须用@objc(XXXDTO)把字段拍平到NSObject,UTS 才能透传。 - 配置可缺省:UTS 侧不强制传 options,Swift 端
ScannerConfigurationParser对每个 key 做"读取-校验-默认值兜底",类型错误也安全降级。 - 快照双返回:
imageBase64兼容旧 API 调用,imageURL让 Vue 端可以用本地文件 URL 直接渲染(性能更好、内存占用更小)。 - 快照写入 tmp:每次扫码生成独立 UUID 文件名,避免冲突;调用方若需长期保留,自行
readFile转存。 - 节流 + 稳定期:识别逻辑做 400ms 节流 + 300ms 稳定期 + 500ms 单码确认,避免每帧抖动与误触发。
兼容性
- iOS 18.0+
- HBuilderX 3.6.8+
- uni-app x 5.0+
许可
无

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 1661
赞赏 0
下载 12492918
赞赏 1939
赞赏
京公网安备:11010802035340号