<template>
|
<view class="scan-container">
|
<view class="scan-header">
|
<text class="header-title">{{ scanTitle }}</text>
|
<text class="header-close" @click="closeScan">✕</text>
|
</view>
|
|
<view class="scan-body">
|
<view class="scan-tips">
|
<text class="tips-icon">📷</text>
|
<text class="tips-text">正在启动相机...</text>
|
<text class="tips-desc">请将条码对准取景框内</text>
|
</view>
|
|
<view class="scan-controls">
|
<button class="control-btn primary" @click="startScan">
|
<text class="btn-text">开始扫码</text>
|
</button>
|
<button class="control-btn" @click="manualInput">
|
<text class="btn-text">手动输入</text>
|
</button>
|
</view>
|
|
<view class="scan-info">
|
<text class="info-title">💡 扫码提示</text>
|
<text class="info-item">• 保持15-30cm距离</text>
|
<text class="info-item">• 确保光线充足</text>
|
<text class="info-item">• 条码清晰无破损</text>
|
<text class="info-item">• 支持工业条码(CODE128/CODE39)</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
scanTitle: 'SN确认',
|
};
|
},
|
|
onLoad(options) {
|
if (options.title) {
|
this.scanTitle = decodeURIComponent(options.title);
|
}
|
|
// 自动启动扫码
|
setTimeout(() => {
|
this.startScan();
|
}, 500);
|
},
|
|
methods: {
|
// 使用 uni.scanCode API 扫码(识别率更高)
|
startScan() {
|
const self = this;
|
|
// #ifdef APP-PLUS
|
uni.scanCode({
|
// 关键优化1:只扫描条形码,提高识别速度和成功率
|
scanType: ['barCode'],
|
// 关键优化2:仅使用相机
|
onlyFromCamera: true,
|
|
success(res) {
|
console.log('扫码成功 - 原始结果:', res);
|
console.log('扫码成功 - 条码内容:', res.result);
|
console.log('扫码成功 - 条码类型:', res.scanType);
|
console.log('扫码成功 - 字符集:', res.charSet);
|
|
let scanResult = res.result || '';
|
|
// 处理扫码结果
|
scanResult = scanResult.trim();
|
|
console.log('处理后的结果:', scanResult);
|
|
if (!scanResult) {
|
console.error('警告:扫码结果为空');
|
uni.showToast({
|
title: '扫码结果为空,请重试',
|
icon: 'none',
|
duration: 1500
|
});
|
// 自动重新扫码
|
setTimeout(() => {
|
self.startScan();
|
}, 1500);
|
return;
|
}
|
|
// 震动反馈
|
uni.vibrateShort();
|
|
// 显示成功提示
|
uni.showToast({
|
title: '扫码成功',
|
icon: 'success',
|
duration: 800
|
});
|
|
// 返回上一页并传递结果
|
setTimeout(() => {
|
const pages = getCurrentPages();
|
const prevPage = pages[pages.length - 2];
|
if (prevPage && prevPage.$vm && prevPage.$vm.onScanSuccess) {
|
prevPage.$vm.onScanSuccess(scanResult);
|
}
|
uni.navigateBack();
|
}, 800);
|
},
|
|
fail(err) {
|
console.error('扫码失败 - 详细信息:', err);
|
console.error('错误代码:', err.errCode);
|
console.error('错误消息:', err.errMsg);
|
|
// 如果是用户取消,直接返回
|
if (err.errMsg && err.errMsg.indexOf('cancel') > -1) {
|
console.log('用户取消扫码');
|
return;
|
}
|
|
// 其他错误,提示用户并提供重试选项
|
uni.showModal({
|
title: '扫码失败',
|
content: `建议:
|
1. 保持15-25cm距离
|
2. 确保光线充足
|
3. 条码水平对准
|
4. 尝试慢慢移动距离
|
|
如仍失败,可使用手动输入`,
|
confirmText: '重新扫码',
|
cancelText: '手动输入',
|
success(modalRes) {
|
if (modalRes.confirm) {
|
// 重新扫码
|
setTimeout(() => {
|
self.startScan();
|
}, 300);
|
} else if (modalRes.cancel) {
|
// 手动输入
|
self.manualInput();
|
}
|
}
|
});
|
}
|
});
|
// #endif
|
|
// #ifdef H5
|
uni.showModal({
|
title: '提示',
|
content: 'H5环境不支持扫码,请使用手动输入功能',
|
showCancel: false,
|
success() {
|
self.manualInput();
|
}
|
});
|
// #endif
|
|
// #ifdef MP-WEIXIN
|
uni.scanCode({
|
scanType: ['barCode', 'qrCode'],
|
success(res) {
|
const scanResult = res.result.trim();
|
const pages = getCurrentPages();
|
const prevPage = pages[pages.length - 2];
|
if (prevPage && prevPage.$vm && prevPage.$vm.onScanSuccess) {
|
prevPage.$vm.onScanSuccess(scanResult);
|
}
|
uni.navigateBack();
|
},
|
fail(err) {
|
console.error('扫码失败:', err);
|
self.manualInput();
|
}
|
});
|
// #endif
|
},
|
|
// 手动输入
|
manualInput() {
|
const self = this;
|
uni.showModal({
|
title: `输入${this.scanTitle}`,
|
editable: true,
|
placeholderText: '请输入条码内容(如:51105/ARAAZF5V553990)',
|
success(res) {
|
if (res.confirm && res.content) {
|
const inputValue = res.content.trim();
|
|
// 返回上一页并传递输入结果
|
const pages = getCurrentPages();
|
const prevPage = pages[pages.length - 2];
|
if (prevPage && prevPage.$vm && prevPage.$vm.onScanSuccess) {
|
prevPage.$vm.onScanSuccess(inputValue);
|
}
|
uni.navigateBack();
|
}
|
}
|
});
|
},
|
|
// 关闭扫码
|
closeScan() {
|
uni.navigateBack();
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.scan-container {
|
min-height: 100vh;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
padding: 20rpx;
|
}
|
|
.scan-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 30rpx 20rpx;
|
background-color: rgba(255, 255, 255, 0.95);
|
border-radius: 20rpx;
|
margin-bottom: 40rpx;
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
}
|
|
.header-title {
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.header-close {
|
font-size: 48rpx;
|
color: #999;
|
padding: 0 20rpx;
|
}
|
|
.scan-body {
|
flex: 1;
|
}
|
|
.scan-tips {
|
background-color: rgba(255, 255, 255, 0.95);
|
border-radius: 20rpx;
|
padding: 60rpx 40rpx;
|
margin-bottom: 30rpx;
|
text-align: center;
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
}
|
|
.tips-icon {
|
font-size: 120rpx;
|
display: block;
|
margin-bottom: 30rpx;
|
}
|
|
.tips-text {
|
font-size: 32rpx;
|
color: #333;
|
font-weight: bold;
|
display: block;
|
margin-bottom: 20rpx;
|
}
|
|
.tips-desc {
|
font-size: 28rpx;
|
color: #666;
|
display: block;
|
}
|
|
.scan-controls {
|
display: flex;
|
justify-content: space-between;
|
gap: 20rpx;
|
margin-bottom: 30rpx;
|
}
|
|
.control-btn {
|
flex: 1;
|
height: 90rpx;
|
background-color: rgba(255, 255, 255, 0.95);
|
border-radius: 15rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
border: none;
|
}
|
|
.control-btn.primary {
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
}
|
|
.control-btn.primary .btn-text {
|
color: #fff;
|
}
|
|
.btn-text {
|
font-size: 30rpx;
|
color: #333;
|
font-weight: bold;
|
}
|
|
.scan-info {
|
background-color: rgba(255, 255, 255, 0.95);
|
border-radius: 20rpx;
|
padding: 40rpx;
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
}
|
|
.info-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
color: #333;
|
display: block;
|
margin-bottom: 30rpx;
|
}
|
|
.info-item {
|
font-size: 28rpx;
|
color: #666;
|
line-height: 2;
|
display: block;
|
}
|
</style>
|