提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- [H5 扫码功能安装指南](#H5 扫码功能安装指南)
-
- [📦 安装依赖](#📦 安装依赖)
- [📁 已创建的文件](#📁 已创建的文件)
-
- [1. 扫码组件](#1. 扫码组件)
- [2. 核销页面(已更新)](#2. 核销页面(已更新))
- [🚀 使用方法](#🚀 使用方法)
- [🎯 功能特性](#🎯 功能特性)
- [⚙️ 配置说明](#⚙️ 配置说明)
- [🔧 对接后端接口](#🔧 对接后端接口)
-
- 修改核销接口
- [创建 API 文件](#创建 API 文件)
- [⚠️ 注意事项](#⚠️ 注意事项)
-
- [1. HTTPS 要求](#1. HTTPS 要求)
- 部署环境
-
-
- [5. 错误处理](#5. 错误处理)
- [🧪 测试建议](#🧪 测试建议)
-
- [1. 功能测试](#1. 功能测试)
- [2. 兼容性测试](#2. 兼容性测试)
- [3. 异常测试](#3. 异常测试)
- [4. 性能测试](#4. 性能测试)
- [📱 移动端优化](#📱 移动端优化)
-
- [1. 全屏显示](#1. 全屏显示)
- [2. 防止滚动穿透](#2. 防止滚动穿透)
- [3. 触摸友好](#3. 触摸友好)
- [🔗 参考资料](#🔗 参考资料)
- [📞 常见问题](#📞 常见问题)
-
- [Q1: 为什么摄像头无法启动?](#Q1: 为什么摄像头无法启动?)
- [Q2: 扫描识别率低怎么办?](#Q2: 扫描识别率低怎么办?)
- [Q3: 可以同时支持微信小程序吗?](#Q3: 可以同时支持微信小程序吗?)
- [Q4: 如何更换扫描框样式?](#Q4: 如何更换扫描框样式?)
-
前言
H5 扫码功能安装指南
📦 安装依赖
bash
# 使用 npm
npm install html5-qrcode
# 或使用 pnpm(推荐)
pnpm install html5-qrcode
📁 已创建的文件
1. 扫码组件
- 文件 :
src/components/QrScanner/index.vue - 功能:封装的扫码组件,支持二维码和条形码
2. 核销页面(已更新)
- 文件 :
src/views/verify/index.vue - 功能 :
- ✅ 扫码核销
- ✅ 手动输入核销码
- ✅ 摄像头切换
- ✅ 核销结果提示
🚀 使用方法
方式一:直接使用(已集成到核销页)
bash
# 1. 安装依赖
pnpm install html5-qrcode
# 2. 启动项目
npm run dev
# 3. 访问核销页面
# 登录后点击"去核销",或直接访问 /verify
方式二:在其他页面使用扫码组件
js
<template>
<div>
<el-button @click="startScan">开始扫码</el-button>
<QrScanner
v-if="isScanning"
ref="scannerRef"
@success="onScanSuccess"
@error="onScanError"
@close="isScanning = false"
/>
</div>
</template>
<script setup>
import { ref } from 'vue'
import QrScanner from '@/components/QrScanner/index.vue'
const isScanning = ref(false)
const scannerRef = ref(null)
const startScan = async () => {
isScanning.value = true
await nextTick()
scannerRef.value?.startScan()
}
const onScanSuccess = (code) => {
console.log('扫码结果:', code)
// 处理扫码结果
}
const onScanError = (error) => {
console.error('扫码错误:', error)
}
</script>
🎯 功能特性
扫码组件功能
- ✅ 支持二维码和条形码
- ✅ 自动识别后置/前置摄像头
- ✅ 支持切换摄像头
- ✅ 扫描框可视化
- ✅ 防抖处理(2秒内不重复扫描)
- ✅ 震动反馈(支持的设备)
- ✅ 错误提示(权限、摄像头等)
- ✅ 完全响应式(移动端/PC端)
核销页面功能
- ✅ 立即扫码核销
- ✅ 手动输入核销码
- ✅ 核销成功/失败提示
- ✅ 可连续核销
⚙️ 配置说明
扫码配置
编辑 src/components/QrScanner/index.vue:
javascript
const config = {
fps: 10, // 每秒扫描帧数(1-60),建议 10
qrbox: { width: 250, height: 250 }, // 扫描框大小
aspectRatio: 1.0, // 宽高比
disableFlip: false, // 是否禁用翻转识别
videoConstraints: {
facingMode: { ideal: 'environment' } // 优先后置摄像头
}
}
防抖时间调整
javascript
// src/components/QrScanner/index.vue
// 防抖:2秒内不重复扫描(可调整)
const now = Date.now()
if (now - lastScanTime < 2000) { // 改为 3000 = 3秒
return
}
🔧 对接后端接口
修改核销接口
编辑 src/views/verify/index.vue:
javascript
// 核销订单
const verifyOrder = async (code) => {
try {
// 1
import { verifyOrderXApi } from '@/api/verifyXxx'
// 2. 调用接口
const res = await verifyOrderApi({ code })
// 3. 成功处理
await ElMessageBox.alert(
`订单号:${res.data.orderId}<br/>
商品:${res.data.productName}<br/>
核销成功!`,
'核销成功',
{
dangerouslyUseHTMLString: true,
confirmButtonText: '继续核销',
type: 'success'
}
)
isScanning.value = false
} catch (error) {
// 4. 失败处理
ElMessageBox.alert(
error.message || '核销失败,请稍后重试',
'核销失败',
{
confirmButtonText: '重新扫码',
type: 'error'
}
)
}
}
创建 API 文件
创建 src/api/verify.js:
javascript
import request from '@/utils/request'
// 核销订单
export function verifyOrderApi(data) {
return request({
url: '/api/verify/order',
method: 'post',
data
})
}
// 查询核销记录
export function getVerifyHistory(params) {
return request({
url: '/api/verify/history',
method: 'get',
params
})
}
⚠️ 注意事项
1. HTTPS 要求
摄像头功能必须在 HTTPS 环境下使用(localhost 除外)
部署环境
https://your-domain.com # ✅ 可以使用摄像头
http://your-domain.com # ❌ 不能使用摄像头
### 2. 浏览器兼容性
| 浏览器 | 支持版本 | 备注 |
|--------|----------|------|
| Chrome | 53+ | ✅ 完全支持 |
| Safari | 11+ | ✅ 完全支持 |
| Firefox | 36+ | ✅ 完全支持 |
| Edge | 79+ | ✅ 完全支持 |
| 微信内置浏览器 | - | ✅ 支持 |
| QQ浏览器 | - | ⚠️ 需要测试 |
### 3. 摄像头权限
首次使用时浏览器会请求摄像头权限:
┌────────────────────────────────┐
│ 允许访问您的摄像头吗? │
│ │
│ [阻止] [允许] │
└────────────────────────────────┘
**如果用户拒绝:**
- 显示错误提示
- 提供手动输入核销码的备用方案
- 引导用户在浏览器设置中开启权限
### 4. 性能优化建议
```javascript
// 1. 扫码成功后立即停止
const onScanSuccess = async (code) => {
await html5QrCode.stop() // 停止扫描,释放资源
handleVerify(code)
}
// 2. 组件卸载时清理
onBeforeUnmount(() => {
if (html5QrCode) {
html5QrCode.stop()
html5QrCode.clear()
}
})
// 3. 降低扫描帧率(如果性能不佳)
const config = {
fps: 5 // 降低到 5 帧/秒
}
5. 错误处理
javascript
try {
await html5QrCode.start(...)
} catch (err) {
if (err.name === 'NotAllowedError') {
// 用户拒绝授权
ElMessage.error('请允许访问摄像头')
} else if (err.name === 'NotFoundError') {
// 未检测到摄像头
ElMessage.error('未检测到摄像头')
} else if (err.name === 'NotReadableError') {
// 摄像头被占用
ElMessage.error('摄像头被其他应用占用')
} else {
// 其他错误
ElMessage.error('启动扫码失败')
}
}
🧪 测试建议
1. 功能测试
- ✅ 扫描二维码
- ✅ 扫描条形码
- ✅ 切换前后摄像头
- ✅ 取消扫码
- ✅ 手动输入核销码
- ✅ 扫码成功/失败提示
2. 兼容性测试
- ✅ Chrome(移动端/PC端)
- ✅ Safari(iPhone/iPad/Mac)
- ✅ 微信内置浏览器
- ✅ 各种Android浏览器
3. 异常测试
- ✅ 拒绝摄像头权限
- ✅ 没有摄像头的设备
- ✅ 摄像头被占用
- ✅ 网络断开
- ✅ 扫描无效二维码
4. 性能测试
- ✅ 扫描识别速度
- ✅ 内存占用
- ✅ CPU占用
- ✅ 电量消耗(移动端)
📱 移动端优化
1. 全屏显示
js
.scanner-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 9999;
}
2. 防止滚动穿透
javascript
// 开始扫码时
document.body.style.overflow = 'hidden'
// 停止扫码时
document.body.style.overflow = ''
3. 触摸友好
js
.action-btn {
height: 44px; // 至少 44px,方便点击
padding: 0 20px;
}
🔗 参考资料
📞 常见问题
Q1: 为什么摄像头无法启动?
A: 检查以下几点:
- 是否在 HTTPS 环境(或 localhost)
- 是否授予了摄像头权限
- 摄像头是否被其他应用占用
- 浏览器是否支持
Q2: 扫描识别率低怎么办?
A: 尝试:
- 提高 fps 值(如 fps: 15)
- 增大扫描框尺寸
- 确保光线充足
- 二维码/条形码清晰完整
Q3: 可以同时支持微信小程序吗?
A: 不可以。微信小程序需要使用 wx.scanCode() API。
建议:
- H5:使用 html5-qrcode
- 小程序:使用 wx.scanCode()
- 通过环境判断选择不同方案
Q4: 如何更换扫描框样式?
A: 修改组件样式:
js
:deep(#qr-shaded-region) {
border: 50px solid rgba(0, 0, 0, 0.5) !important; // 扫描框外阴影
}
:deep(#qr-shaded-region::before) {
// 自定义扫描框样式
}