首先要安装这两个依赖
vueuse/nuxt zxing/library
<script setup lang="ts">
const validNum = (val:any) => !(val.length === 0 || val ===''); // 设备序列号校验
const model = defineModel<any>()
const isScan = ref(false)
let codeReader: any
const cameraId = ref<any>()
const {videoInputs: cameras} = useDevicesList()
const show = ref(false);
const emit = defineEmits(["submit"])
watch(()=>cameras.value,(val)=>{
if(val.length){
cameraId.value=cameras.value[0].deviceId
}
})
function handleTxt(txt:any){
if(txt){
if(txt.indexOf(';')){
model.value = txt.split(';')[0]
}
else{
model.value = txt
}
}
show.value = false;
emit("submit", model.value )
}
function clearValue(){
model.value = ''
}
onUnmounted(()=>{
if(isScan.value){
codeReader.reset()
isScan.value = false
}
})
const updatainput=useDebounceFn((val:any)=>{
emit("submit", val )
}, 1000)
function btnScan() {
if (isScan.value) {
codeReader.reset()
isScan.value = false
return
}
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
// 用户授权了相机权限,可以进行后续操作
show.value = true;
import("@zxing/library").then(ZXing => {
console.log(ZXing)
codeReader = new ZXing.BrowserMultiFormatReader()
isScan.value = true
cameraId.value=null
codeReader.listVideoInputDevices().then((videoInputDevices:any)=>{
//videoInputDevices 设备摄像头参数数组
cameraId.value = videoInputDevices[0].deviceId //调用摄像头id
})
codeReader.decodeFromVideoDevice(cameraId.value, 'video', (result:any, err:any) => {
if (result) {
handleTxt(result.text);
isScan.value = false
codeReader.reset()
}
if (err && !(err instanceof ZXing.NotFoundException)) {
// 非 NotFound 错误
console.error('Error:', err);
}
});
})
})
.catch(err => {
// 处理错误,可能是因为权限被拒绝
console.log('获取相机权限失败:', err);
});
}
defineExpose({
clearValue
});
</script>
<template>
<van-field @update:model-value="updatainput" :rules="[{validator: validNum, message: '请输入设备序列号'}]" required label="设备序列号" v-bind="$attrs" v-model="model" placeholder="请输入设备序列号" clearable>
<template #right-icon>
<span class="cursor-pointer flex justify-center gap-2">
<u-icon title="从摄像头扫描" @click.stop="btnScan" size="24" name="i-heroicons-qr-code"></u-icon>
</span>
</template>
</van-field>
<van-popup v-model:show="show" :style="{height:'60%',width:'100%'}">
<video ref="video" autoplay id="video"></video>
</van-popup>
</template>
<style scoped>
</style>
测试只能在https