修改条形码为二维码,同时对于扫码展示部分进行修改
This commit is contained in:
@ -16,18 +16,10 @@
|
||||
</template>
|
||||
|
||||
<div class="scan-section">
|
||||
<div v-if="showCamera" class="camera-wrapper">
|
||||
<QrScanner @decode="onScanSuccess" />
|
||||
<div class="scan-overlay">
|
||||
<el-button type="info" size="small" bg text @click="showCamera = false" icon="Close">
|
||||
关闭摄像头
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="camera-placeholder" @click="showCamera = true">
|
||||
<div class="camera-placeholder" @click="showCamera = true">
|
||||
<el-icon :size="40" color="#409EFF"><CameraFilled /></el-icon>
|
||||
<span class="text">点击开启扫码</span>
|
||||
<span class="text">点击开启全屏扫码</span>
|
||||
</div>
|
||||
|
||||
<div class="input-box">
|
||||
@ -150,6 +142,22 @@
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<div v-if="showCamera" class="fullscreen-scanner-overlay">
|
||||
<div class="scanner-header">
|
||||
<el-button circle icon="Close" @click="showCamera = false" class="close-btn" />
|
||||
<span class="scanner-title">扫码模式</span>
|
||||
<div class="scanner-placeholder"></div> </div>
|
||||
|
||||
<div class="scanner-body">
|
||||
<QrScanner @decode="onScanSuccess" />
|
||||
</div>
|
||||
|
||||
<div class="scanner-footer">
|
||||
<p>请对准条形码,识别成功后自动添加</p>
|
||||
<p v-if="cartItems.length > 0" class="current-count">当前已添加: {{ cartItems.length }} 件</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="showSignatureDialog"
|
||||
fullscreen
|
||||
@ -201,7 +209,7 @@ import { useUserStore } from '@/stores/user'
|
||||
const barcodeInput = ref('')
|
||||
const cartItems = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const showCamera = ref(false) // ★ 核心修改:默认改为 false
|
||||
const showCamera = ref(false)
|
||||
const barcodeRef = ref()
|
||||
const formRef = ref()
|
||||
const userStore = useUserStore()
|
||||
@ -266,26 +274,21 @@ const onScanSuccess = (code: string) => {
|
||||
if (!code) return
|
||||
const trimCode = code.trim()
|
||||
|
||||
// ★★★ 核心修改:防误触校验 ★★★
|
||||
// 1. 正则校验:只允许 数字、字母、横杠、点
|
||||
// 这样可以屏蔽掉条码解析错误产生的 { } $ # 等乱码
|
||||
const validPattern = /^[A-Za-z0-9\-\.]+$/
|
||||
if (!validPattern.test(trimCode)) {
|
||||
ElMessage.warning(`识别到异常符号,已忽略:${trimCode}`)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 长度校验:避免误扫到环境中的短数字
|
||||
if (trimCode.length < 3) {
|
||||
ElMessage.warning('扫描结果过短,请对准重试')
|
||||
return
|
||||
}
|
||||
|
||||
// 防抖:防止同一条码连续触发
|
||||
if (loading.value) return
|
||||
|
||||
barcodeInput.value = trimCode
|
||||
handleManualInput() // 复用手动输入逻辑
|
||||
handleManualInput()
|
||||
}
|
||||
|
||||
const handleManualInput = async () => {
|
||||
@ -343,8 +346,11 @@ const handleManualInput = async () => {
|
||||
if (navigator.vibrate) navigator.vibrate([200, 100, 200])
|
||||
} finally {
|
||||
loading.value = false
|
||||
// 聚焦输入框,方便连续扫
|
||||
nextTick(() => { barcodeRef.value?.focus() })
|
||||
// 注意:全屏扫码模式下,我们不需要 refocus input,因为用户还在看摄像头
|
||||
// 只有在非全屏模式下才 focus
|
||||
if (!showCamera.value) {
|
||||
nextTick(() => { barcodeRef.value?.focus() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,21 +511,73 @@ onUnmounted(() => {
|
||||
.title-box { font-size: 16px; font-weight: bold; display: flex; align-items: center; gap: 8px; }
|
||||
.header-price { font-size: 18px; color: #F56C6C; font-weight: bold; }
|
||||
|
||||
/* 扫码区 */
|
||||
/* 扫码区(卡片内触发器) */
|
||||
.scan-section { margin-bottom: 20px; }
|
||||
.camera-wrapper {
|
||||
height: 25vh; background: #000; border-radius: 12px; overflow: hidden; position: relative; margin-bottom: 10px;
|
||||
}
|
||||
.scan-overlay {
|
||||
position: absolute; bottom: 10px; right: 10px; z-index: 10;
|
||||
}
|
||||
.camera-placeholder {
|
||||
height: 120px; background: #f5f7fa; border: 1px dashed #dcdfe6; border-radius: 8px;
|
||||
display: flex; flex-direction: column; justify-content: center; align-items: center;
|
||||
color: #909399; margin-bottom: 10px; cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.camera-placeholder:active { background: #e6e8eb; }
|
||||
.camera-placeholder .text { margin-top: 5px; font-size: 13px; }
|
||||
|
||||
/* ★ 全屏扫码层样式 */
|
||||
.fullscreen-scanner-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: #000;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.scanner-header {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 15px;
|
||||
background: rgba(0,0,0,0.6);
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
}
|
||||
.scanner-title { font-size: 16px; font-weight: bold; }
|
||||
.close-btn { background: rgba(255,255,255,0.2); border: none; color: #fff; }
|
||||
|
||||
.scanner-body {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
/* 强制子组件(QrScanner)填满容器 */
|
||||
:deep(.qr-scanner-container) {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.scanner-footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
background: rgba(0,0,0,0.6);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
z-index: 10;
|
||||
}
|
||||
.current-count { color: #67c23a; font-weight: bold; margin-top: 5px; font-size: 16px; }
|
||||
|
||||
/* 表单与购物车 */
|
||||
.cart-section { margin-bottom: 20px; }
|
||||
.form-section { background: #fff; }
|
||||
|
||||
Reference in New Issue
Block a user