修改扫码时间间隔分辨率以及添加语音播报,对边框进行缩减由210px修改为180px

This commit is contained in:
dxc
2026-02-10 10:32:59 +08:00
parent 1edd9a95c6
commit bccbeaadce
2 changed files with 67 additions and 21 deletions

View File

@ -12,7 +12,7 @@
<div class="focus-tip success" v-if="isPaused">
<div class="scan-text-success">
<el-icon><CircleCheckFilled /></el-icon>
扫描成功3秒后继续...
扫描成功2秒后继续...
</div>
</div>
@ -50,6 +50,43 @@ const zoomMin = ref(1)
const zoomMax = ref(5)
const currentZoom = ref(1)
// 音频上下文
let audioCtx: AudioContext | null = null;
// 提示音播放函数
const playBeep = () => {
try {
const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
if (!AudioContext) return;
if (!audioCtx) {
audioCtx = new AudioContext();
}
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
// 三角波,清脆响亮
oscillator.type = 'triangle';
oscillator.frequency.value = 1500;
gainNode.gain.setValueAtTime(1.0, audioCtx.currentTime);
oscillator.start();
oscillator.stop(audioCtx.currentTime + 0.1);
} catch (e) {
console.error("播放提示音失败:", e);
}
};
const startScanning = async () => {
try {
html5QrCode = new Html5Qrcode(scannerElementId, {
@ -63,16 +100,16 @@ const startScanning = async () => {
const config = {
fps: 20,
// ★★★ 核心修改点 2移除了 qrbox 属性 ★★★
// 移除后,库默认会对每一帧的“全画面”进行解析,不再局限于中间区域
// qrbox: { width: 300, height: 100 },
disableFlip: false,
videoConstraints: {
facingMode: "environment",
// 保持高分辨率以支持微小条码
width: { min: 1280, ideal: 3840, max: 3840 },
height: { min: 720, ideal: 2160, max: 2160 },
// ★★★ 核心修改:设置为 2K (QHD) 分辨率 ★★★
// min: 1280x720 (保证低端机能启动)
// ideal: 2560x1440 (2K QHD清晰度与性能的平衡点)
width: { min: 1280, ideal: 2560, max: 3840 },
height: { min: 720, ideal: 1440, max: 2160 },
// 16:9 的比例
aspectRatio: { ideal: 1.7777777778 },
focusMode: "continuous",
advanced: [{ focusMode: "macro" }, { zoom: 2.0 }]
}
@ -84,14 +121,18 @@ const startScanning = async () => {
(decodedText) => {
if (isPaused.value) return
console.log(`Scan: ${decodedText}`)
isPaused.value = true
playBeep();
emit('decode', decodedText)
if (navigator.vibrate) navigator.vibrate(200);
setTimeout(() => {
isPaused.value = false
}, 3000)
}, 2000)
},
(errorMessage) => {
// ignore
@ -103,12 +144,14 @@ const startScanning = async () => {
} catch (err: any) {
let msg = '无法启动摄像头'
console.error("Scanner Error:", err)
if (err.name === 'OverconstrainedError') {
msg = '摄像头不支持 2K 分辨率,请尝试降低配置'
}
errorMsg.value = msg
emit('error', msg)
}
}
// 检测硬件变焦能力
const checkZoomCapability = () => {
if (!html5QrCode) return
@ -130,7 +173,6 @@ const checkZoomCapability = () => {
}
}
// 处理滑块拖动
const handleZoom = () => {
if (!html5QrCode) return
@ -154,9 +196,19 @@ const stopScanning = async () => {
console.error("Stop failed", e)
}
}
if (audioCtx) {
audioCtx.close();
audioCtx = null;
}
}
onMounted(() => {
try {
const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
if (AudioContext) audioCtx = new AudioContext();
} catch(e) {}
setTimeout(() => {
startScanning()
}, 500)
@ -178,7 +230,6 @@ onUnmounted(() => {
justify-content: center;
align-items: center;
overflow: hidden;
/* 如果是全屏模式这里不需要圆角或者保持圆角视你的UI设计而定 */
border-radius: 0;
}
@ -214,14 +265,12 @@ onUnmounted(() => {
z-index: 20;
}
/* --- ★ 修改点 3视觉层 CSS 更新 --- */
.focus-tip {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 移除了 border 和 box-shadow不再显示红框和黑色遮罩 */
pointer-events: none;
z-index: 10;
display: flex;
@ -230,23 +279,21 @@ onUnmounted(() => {
}
.focus-tip.success {
background: rgba(103, 194, 58, 0.2); /* 成功时全屏微微泛绿 */
background: rgba(103, 194, 58, 0.2);
}
/* 扫描线改为全屏宽度 */
.scan-line {
width: 100%;
height: 2px;
background: rgba(255, 0, 0, 0.5);
box-shadow: 0 0 4px rgba(255, 0, 0, 0.8);
position: absolute;
/* 动画范围从 10% 到 90% */
animation: scan-move 2.5s infinite linear;
}
.scan-text {
position: absolute;
bottom: 150px; /* 调整文字位置 */
bottom: 150px;
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
@ -275,7 +322,6 @@ onUnmounted(() => {
100% { top: 100%; opacity: 0; }
}
/* 变焦控制器 */
.zoom-control {
position: absolute;
bottom: 80px;

View File

@ -22,7 +22,7 @@ import AppMain from './components/AppMain.vue'
}
.sidebar-container {
width: 210px; /* 固定侧边栏宽度 */
width: 180px; /* 固定侧边栏宽度 */
height: 100%;
background-color: #304156; /* 侧边栏背景色 */
flex-shrink: 0; /* 防止被挤压 */
@ -37,7 +37,7 @@ import AppMain from './components/AppMain.vue'
flex-direction: column;
overflow-y: auto; /* 关键:页面内容过多时,只在右侧区域滚动 */
background-color: #f0f2f5; /* 右侧灰色背景,让白色卡片更明显 */
padding: 20px; /* 给内部页面留出边距 */
padding: 10px; /* 给内部页面留出边距 */
box-sizing: border-box;
}
</style>