Files
campus-activity-system/web/src/components/WebQRScanner.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>