- 首先需要扫码枪连接电脑,
- 超过N秒不进行扫描二维码或者没有扫到二维码(即没有获取到二维码信息),则取消扫描,需要点击 “重新扫码” 按钮重新扫描
- 点击“重新扫码”按钮后,重新计时 N 秒,超过 N 秒后需要再次点击“重新扫码”按钮(即只有在 N 秒内扫码才有效)
实现原理
- 页面要放一个
input 输入框
,用来存放扫码枪扫描到的内容
,便于我们使用二维码信息;- 扫描的同时,input 框要
获取到光标
,扫描到的二维码内容才可以存在 input 输入框;
- 在可以扫描二维码的 N 秒内,我们要将 input 获取光标,超过 N 秒后,input 框自动失去光标;
- 在扫描二维码的 N 秒内:为防止用户点击页面其他空白位置导致 input 框失去光标获取不到二维码信息 → 当前页面
无论点哪里
(该页面是一个弹框,不存在点击其他位置与其他事件冲突的情况),都要让扫描二维码后获得的信息展示的input 框获取焦点
,详见方法inputFocusHandler()
- 扫码枪扫描二维码获取到信息后,结束 N 秒计时,进行业务逻辑处理。
<!-- 扫描二维码 对话框 -->
<template>
<el-dialog
id="ScanQRcodeDialog"
:title="title"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
width="30%"
center
@close="closeHandler"
>
<div v-loading="dialogLoading" class="pic">
<img
:src="
btnDisabled
? require('@/assets/images/blood-involved/scanQRcode.png')
: require('@/assets/images/blood-involved/scanQRcode_again.png')
"
/>
</div>
<input
id="scanQRcodeGetContent_input"
v-model="scanContent"
type="password"
autocomplete="off"
name="QRCodeInfo"
/>
<span slot="footer" class="dialog-footer">
<el-button :disabled="btnDisabled" :type="btnType" round @click="ReScanCodeHandler">
重新扫码<span v-if="btnDisabled">({{ seconds }}s)</span>
</el-button>
</span>
</el-dialog>
</template>
<script>
import {
scanCarInQRcode,
scanCarOutQRcode,
scanBloodDestroyQRcode
} from '@/api/blood_access_api.js'
export default {
name: 'ScanQRcodeDialog',
components: {},
data() {
return {
title: '',
dialogVisible: false,
dialogType: '',
dialogLoading: false,
btnDisabled: true, // 是否禁用“重新扫码”按钮
seconds: 15, // 倒计时
timer: null, // 定时器
timeoutTimer: null,
scanContent: '', // 扫描到的二维码内容
tip: '',
xyjsr: []
}
},
computed: {
btnType() {
return this.btnDisabled ? 'info' : 'primary'
}
},
watch: {
scanContent: {
handler(val, oldVal) {
clearTimeout(this.timeoutTimer)
this.timeoutTimer = setTimeout(() => {
console.log('val---------扫码枪扫描内容', val)
// 扫描二维码得到数据后,调接口获取车辆信息(按钮倒计时时才可以获取车信息)
if (this.btnDisabled === true && this.dialogVisible === true && val !== '') {
// 第一次获取到扫码内容后停止监听扫描枪的输入进行校验
document
.getElementById('BloodEntryOrExit')
.removeEventListener('click', this.clickEventHandler)
document.getElementById('scanQRcodeGetContent_input').blur()
try {
// 没有获取到 id 、type!=='in'、type!=='out' :提示用户无效二维码
if (
!JSON.parse(this.scanContent).jyw ||
!JSON.parse(this.scanContent).pzbh ||
['in', 'out', 'destroy'].indexOf(JSON.parse(this.scanContent).type) === -1
) {
// return this.$message.error(this.tip);
return this.$confirm(this.tip, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then((val) => {
this.scanContent = ''
document.getElementById('scanQRcodeGetContent_input').focus()
this.inputFocusHandler()
})
.catch((err) => {
this.dialogVisible = false
})
}
} catch (err) {
// 扫码获得的数据可能不能被JSON转换,就会报错,同时获取到的数据也不对,这里捕获错误
// return this.$message.error(this.tip);
return this.$confirm(this.tip, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then((val) => {
this.scanContent = ''
document.getElementById('scanQRcodeGetContent_input').focus()
this.inputFocusHandler()
})
.catch((err) => {
this.dialogVisible = false
})
}
this.getBloodInfo()
}
}, 100)
}
}
},
mounted() {
this.inputFocusHandler()
},
created() {},
methods: {
// 打开
open(type, xyjsr) {
this.inputFocusHandler()
this.dialogType = type
this.xyjsr = xyjsr
this.title = this.getDialogTitle(type)
this.dialogVisible = true
this.countDownHandler()
},
// 点击页面任意位置
inputFocusHandler() {
document.getElementById('BloodEntryOrExit').addEventListener('click', this.clickEventHandler)
},
// 点击页面任意位置的点击事件处理函数
clickEventHandler() {
// 当前页面无论点哪里,都让扫描二维码后获得的信息展示的 input 框获取焦点
document.getElementById('scanQRcodeGetContent_input') &&
document.getElementById('scanQRcodeGetContent_input').focus()
},
getDialogTitle(type) {
const obj = {
entry: '请用扫描枪扫描血样入库码',
exit: '请用扫描枪扫描(委托书/销毁单)二维码',
destroy: '请用扫描枪扫描(委托书/销毁单)的二维码',
reset: '没有获取到二维码信息,请重新扫描二维码'
}
const tipObj = {
entry: '没有获取到二维码信息,请重新扫描二维码',
exit: '没有获取到二维码信息,请重新扫描二维码',
destroy: '没有获取到二维码信息,请重新扫描二维码'
}
this.tip = tipObj[type]
return obj[type]
},
closeHandler() {
this.dialogVisible = false
this.btnDisabled = true
this.seconds = 15
clearInterval(this.timer)
this.scanContent = ''
this.xyjsr = []
},
// 点击 “重新扫码” (禁用按钮并开始倒计时)
ReScanCodeHandler() {
this.inputFocusHandler() // input 框获取焦点
this.scanContent = ''
this.btnDisabled = true
this.title = this.getDialogTitle(this.dialogType)
this.countDownHandler()
},
// 倒计时
countDownHandler() {
this.timer = setInterval(() => {
this.seconds--
// if (this.seconds < 10) this.seconds = "0" + this.seconds;
if (this.seconds === 0) {
clearInterval(this.timer)
this.seconds = 15
this.btnDisabled = false
this.title = this.getDialogTitle('reset')
}
}, 1000)
},
// 获取到扫码枪的信息之后关闭当前对话框,打开核对车辆信息对话框
getBloodInfo() {
this.dialogLoading = true
const scan = JSON.parse(this.scanContent)
const params = {
jyw: scan.jyw
}
if (scan.type === 'destroy') this.dialogType = 'destroy'
let nextOpts
if (this.dialogType === 'entry') {
params.pzbh = scan.pzbh
params.type = 'in'
nextOpts = scanCarInQRcode
} else if (this.dialogType === 'exit') {
params.id = scan.id
params.type = 'out'
params.pzbh = scan.pzbh
params.sjcs = scan.sjcs
nextOpts = scanCarOutQRcode
} else if (this.dialogType === 'destroy') {
params.type = this.dialogType
params.pzbh = scan.pzbh
nextOpts = scanBloodDestroyQRcode
}
nextOpts(params).then((res) => {
this.getInfo(res)
})
},
// 获取血样信息返回值处理
getInfo(res) {
this.$common.CheckCode(
res,
null,
() => {
this.dialogVisible = false
this.dialogLoading = false
const result = res.data
if (this.dialogType === 'exit') {
result.id = JSON.parse(this.scanContent).id
}
result.operationType = this.dialogType // 操作类别
result.xyjsr = this.xyjsr
this.$emit('update', result)
},
() => {
// 如果请求数据不成功,让用户重新扫描二维码
this.dialogLoading = false
clearInterval(this.timer)
this.seconds = 15
this.btnDisabled = false
},
false
)
}
}
}
</script>
<style lang='scss'>
#ScanQRcodeDialog {
@import './styles/index.scss';
.el-dialog {
min-width: 460px;
}
.pic {
width: 100%;
// padding: 0 20px;
padding-left: 30px;
padding-right: 50px;
img {
width: 100%;
}
}
#scanQRcodeGetContent_input {
background-color: red;
z-index: -10;
position: absolute;
}
}
</style>