2 changed files with 231 additions and 4 deletions
@ -0,0 +1,195 @@ |
|||
<template> |
|||
<div style="height: 100vh"> |
|||
<qrcode-stream @detect="onDecode" @error="onInit" style="height: 100%"> |
|||
<div> |
|||
<div class="qr-scanner"> |
|||
<!--顶部左边的返回箭头--> |
|||
<div> |
|||
<el-icon @click="onClickLeft" style="margin:15px;width: 20px;height: 20px;"> |
|||
<Close style="width: 20px;height: 20px;" /> |
|||
</el-icon> |
|||
</div> |
|||
<!--中间的扫码框--> |
|||
<div class="box"> |
|||
<div class="line"></div> |
|||
<div class="angle"></div> |
|||
</div> |
|||
<div class="txt"> |
|||
将二维码/条码放入框内,即自动扫描 |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</qrcode-stream> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { QrcodeStream } from "vue-qrcode-reader"; |
|||
import { ref } from "vue"; |
|||
|
|||
const emits = defineEmits<{ |
|||
(e: 'update-qrScaning', value: any): void |
|||
(e: 'update-scanResult', value: any): void |
|||
}>() |
|||
// 定义变量 |
|||
const dataList = ref('') |
|||
const result = ref(true) |
|||
const error = ref('') |
|||
|
|||
|
|||
// 扫码后返回的结果 |
|||
const onDecode = (res: any) => { |
|||
dataList.value = res |
|||
result.value = false |
|||
//console.log('你好',dataList.value) |
|||
//alert(dataList.value) |
|||
//showSuccessToast('扫描成功')--------------------------------------- |
|||
console.log('扫描成功'+dataList.value[0].rawValue) |
|||
emits('update-scanResult', dataList.value[0].rawValue) // 触发父组件事件 |
|||
// 调用后台接口存入数据库 |
|||
// 数据存入数据库后跳转页面 |
|||
} |
|||
// 初始化摄像头 |
|||
const onInit = async (promise: any) => { |
|||
console.log('初始化摄像头', promise) |
|||
try { |
|||
await promise |
|||
} catch (err: any) { |
|||
if (err.name === 'NotAllowedError') { |
|||
error.value = 'ERROR: 您需要授予相机访问权限'; |
|||
} else if (err.name === 'NotFoundError') { |
|||
error.value = 'ERROR: 这个设备上没有摄像头'; |
|||
} else if (err.name === 'NotSupportedError') { |
|||
error.value = 'ERROR: 所需的安全上下文(HTTPS、本地主机)'; |
|||
} else if (err.name === 'NotReadableError') { |
|||
error.value = 'ERROR: 相机被占用'; |
|||
} else if (err.name === 'OverconstrainedError') { |
|||
error.value = 'ERROR: 安装摄像头不合适'; |
|||
} else if (err.name === 'StreamApiNotSupportedError') { |
|||
error.value = 'ERROR: 此浏览器不支持流API'; |
|||
} |
|||
} |
|||
|
|||
} |
|||
// 返回上一页箭头 |
|||
const onClickLeft = () => { |
|||
//history.back(); |
|||
emits('update-qrScaning', '1') // 触发父组件事件 |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
:deep(i.van-badge__wrapper.van-icon.van-icon-arrow-left.scanImg) { |
|||
font-size: 40px; |
|||
color: white; |
|||
} |
|||
|
|||
.scanImg { |
|||
margin-top: 30px; |
|||
margin-left: 10px; |
|||
} |
|||
|
|||
.error { |
|||
font-weight: bold; |
|||
color: red; |
|||
} |
|||
|
|||
.cameraMessage { |
|||
width: 100%; |
|||
height: 60px; |
|||
} |
|||
|
|||
.qr-scanner { |
|||
background-size: 3rem 3rem; |
|||
background-position: -1rem -1rem; |
|||
width: 100%; |
|||
/* height: 100%; */ |
|||
height: 100vh; |
|||
/* height: 288px; */ |
|||
position: relative; |
|||
background-color: #1110; |
|||
} |
|||
|
|||
.qr-scanner .box { |
|||
width: 213px; |
|||
height: 213px; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 40%; |
|||
transform: translate(-50%, -50%); |
|||
overflow: hidden; |
|||
border: 1px solid #3aa5ff; |
|||
} |
|||
|
|||
.qr-scanner .txt { |
|||
width: 100%; |
|||
height: 35px; |
|||
line-height: 35px; |
|||
font-size: 14px; |
|||
text-align: center; |
|||
/* color: #f9f9f9; */ |
|||
margin: 0 auto; |
|||
position: absolute; |
|||
top: 60%; |
|||
left: 0; |
|||
} |
|||
|
|||
.qr-scanner .myQrcode { |
|||
text-align: center; |
|||
color: #3aa5ff; |
|||
} |
|||
|
|||
.qr-scanner .line { |
|||
height: calc(100% - 2px); |
|||
width: 100%; |
|||
background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #3aa5ff 211%); |
|||
border-bottom: 1px solid #3aa5ff; |
|||
transform: translateY(-100%); |
|||
animation: radar-beam 2s infinite alternate; |
|||
animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99); |
|||
animation-delay: 1.4s; |
|||
} |
|||
|
|||
.qr-scanner .box:after, |
|||
.qr-scanner .box:before, |
|||
.qr-scanner .angle:after, |
|||
.qr-scanner .angle:before { |
|||
content: ''; |
|||
display: block; |
|||
position: absolute; |
|||
width: 3vw; |
|||
height: 3vw; |
|||
} |
|||
|
|||
.qr-scanner .box:after, |
|||
.qr-scanner .box:before { |
|||
top: 0; |
|||
border-top-color: #3aa5ff; |
|||
} |
|||
|
|||
.qr-scanner .angle:after, |
|||
.qr-scanner .angle:before { |
|||
bottom: 0; |
|||
border-bottom-color: #3aa5ff; |
|||
} |
|||
|
|||
.qr-scanner .box:before, |
|||
.qr-scanner .angle:before { |
|||
left: 0; |
|||
border-left-color: #3aa5ff; |
|||
} |
|||
|
|||
.qr-scanner .box:after, |
|||
.qr-scanner .angle:after { |
|||
right: 0; |
|||
border-right-color: #3aa5ff; |
|||
} |
|||
|
|||
@keyframes radar-beam { |
|||
0% { |
|||
transform: translateY(-100%); |
|||
} |
|||
|
|||
100% { |
|||
transform: translateY(0); |
|||
} |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue