101 lines
2.1 KiB
Vue
101 lines
2.1 KiB
Vue
<template>
|
|
<div class="web-qr-scanner">
|
|
<div id="qr-reader" class="qr-reader"></div>
|
|
<div class="scanner-controls">
|
|
<van-button block round @click="$emit('close')">关闭</van-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
import { onMounted, onBeforeUnmount } from 'vue';
|
|
import { Html5Qrcode } from 'html5-qrcode';
|
|
import { showToast } from 'vant';
|
|
|
|
const emit = defineEmits(['result', 'error', 'close']);
|
|
let html5QrCode: Html5Qrcode | null = null;
|
|
|
|
onMounted(() => {
|
|
startScanning();
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
stopScanning();
|
|
});
|
|
|
|
const startScanning = async () => {
|
|
try {
|
|
const devices = await Html5Qrcode.getCameras();
|
|
if (devices && devices.length) {
|
|
let cameraId = devices[0]!.id;
|
|
if (devices.length > 1 && devices[1]) {
|
|
cameraId = devices[1].id;
|
|
}
|
|
|
|
html5QrCode = new Html5Qrcode("qr-reader");
|
|
|
|
await html5QrCode.start(
|
|
cameraId,
|
|
{
|
|
fps: 10,
|
|
qrbox: { width: 250, height: 250 }
|
|
},
|
|
(decodedText) => {
|
|
emit('result', decodedText);
|
|
stopScanning();
|
|
},
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
(_errorMessage) => {
|
|
// ignore error
|
|
}
|
|
);
|
|
} else {
|
|
showToast('未发现相机设备');
|
|
emit('error', new Error('No cameras found'));
|
|
}
|
|
} catch (err) {
|
|
showToast('无法启动相机');
|
|
emit('error', err);
|
|
}
|
|
};
|
|
|
|
const stopScanning = () => {
|
|
if (html5QrCode && html5QrCode.isScanning) {
|
|
html5QrCode.stop().then(() => {
|
|
html5QrCode?.clear();
|
|
}).catch(err => {
|
|
console.error("Failed to stop scanning", err);
|
|
});
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.web-qr-scanner {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: black;
|
|
z-index: 2000;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
|
|
.qr-reader {
|
|
width: 100%;
|
|
}
|
|
|
|
.scanner-controls {
|
|
padding: 20px;
|
|
background: transparent;
|
|
position: absolute;
|
|
bottom: 20px;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
}
|
|
</style>
|