vuex项目扫码枪收款
一. 扫码枪工作原理
扫码枪会将扫到的数据带入到获取焦点的输入框中,并且触发输入框的enter回车事件
1.页面上要有一个输入框,并且是获取焦点状态,当然它是隐藏的看不到,我是把宽高设置为0,然后加上回车事件。
<el-input ref="barCodeInput" v-model="barCode" size="small" @keyup.enter.native="payCode"></el-input>
2.获取焦点的方法
Vue.nextTick(() => { this.$refs["barCodeInput"].focus(); });
3.执行回车事件
payCode(){ //这里进行扫码枪扫码后的操作,调后台接口 }
二、 项目使用实际代码
因为产品要求是不能展示出扫码枪的输入框的,所以使用的input 的hidden属性隐藏了输入框,监听onkeyup事件处理
代码如下:
扫码枪组件代码:
scannerTipDialog.vue
<template> /* 点开这个弹框的时候,提示需要扫码,待扫码input获取到数据后,则会自动关闭弹框,将数据传送给上一级做处理*/ <el-dialog custom-class="jpark-center-mgr" title="支付提示" :visible.sync="dialogVisible" :before-close="handleClose" width="30%" append-to-body :close-on-click-modal="false"> <div class="text"> <span>请使用扫码枪完成支付!</span> </div> <!-- <el-input style="display: none;" width="50px" ref="barCodeInput" v-model="barCode" size="small" @keyup.native="payCode"></el-input> --> <input ref="barCodeInput" v-model="barCode" style="width:500px;" type="text" hidden placeholder=""> </el-dialog> </template> <script> export default { name: "ScannerTipDialog", props: { scannerDialogVisible: { type: Boolean, default: false, }, }, data() { return { dialogVisible: true, loading: false, barCode: '', //扫码枪获取到的值 regexRules: [ { regex: /^(10|11|12|13|14|15|16|17|18|19)[0-9]{16,17}/, value: "WX", }, { regex: /^(25|26|27|28|29|30)[0-9]{14,22}/, value: "ZFB", } ], delay: 200, _start: null }; }, mounted() { let _this = this this.$nextTick(() => { _this.$refs["barCodeInput"].focus(); document.onkeydown = function(event) { console.log('event', event) let result = _this.barCode || ''; let _start = _this._start || new Date(); let now = new Date(); // if ((now.getTime() - _start.getTime()) > _this.delay) { // _start = now; // result = ''; // } let bizCode = String.fromCharCode(event.keyCode); // console.log('bizCode', bizCode) if (event.code == "Enter") { let type = _this.initRegexRules(_this.barCode) console.log('获取到的值',_this.barCode, type) _this.$emit('getScanCode',_this.barCode, type) } result += bizCode _this.barCode = result _this._start = _start }; }) }, destroyed () { document.onkeydown = null }, methods: { initRegexRules(v) { let atype = this.regexRules.filter(item => item.regex.test(v)) if (atype.length) { return atype[0].value } else { return 'UNKNOW' } }, handleClose() { this.$emit('closeScanner') this.dialogVisible = false document.onkeydown = null }, }, watch: { }, }; </script> <style lang="scss" scoped> .text { text-align: center; font-size: 17px; font-weight: 700; } </style>
父组件处理数据代码:
html: <scanner-tip-dialog v-if="isShowScanner" ref="scannerTipDialog" @getScanCode="getScanCode" @closeScanner="closeScanner"/> data () { isShowScanner: false, // 方便每次打开扫码枪弹框的时候会重新挂载,获取焦点 } methods: { getScanCode (code,type) { console.log('扫码得到的数据',code,type) this.isShowScanner = false this.dialogLoading = true this.open({code, type}) }, closeScanner () { this.isShowScanner = false }, /* 下面是事件处理函数,通过promise避免了回调地狱,可供以后写代码参考 promise 返回的reject() 数据处理都会被catch捕获到,展示出错误信息 promise 返回的resolve() 数据处理都会被try捕获到,函数继续往下执行 */ async open(scanner){ var payMode = null var order = null try { //2. 查询对应的支付编号 payMode = await this.getPayModeByType(scanner.type) console.log('==>>payMode', payMode) // 3. 支付订单 order = await this.payOrder(scanner) console.log('==>>order', order) // 4. 开卡 let open = await this.handleOpen(order) this.dialogLoading = false console.log('==>>handleOpen', open) } catch(error){ this.dialogLoading = false; console.log('==>>error', error) if(error.code == this.errorTypes.scannerError.code) { // 扫码枪扫描失败 this.$message({ type: 'error', message: '扫码枪扫描失败,请重新提交并扫码' }) } else if(error.code == this.errorTypes.payModeError.code){ // 获取支付方式失败 this.$message({ type: 'error', message: '订单支付类型获取失败,请更换支付方式' }) } else if(error.code == this.errorTypes.serverError.code){ // 订单支付失败 this.$message({ type: 'error', message: '订单支付失败,请重新扫码' }) } else if(error.code == this.errorTypes.payOrderError.code){ // 订单支付失败 需要反查 let param = { subsystemCode: this.model.subsystemCode, orderNum: error.outTradeNo } try{ let orderStatus = await this.queryOrderStatus(param) console.log("===>orderStatus",orderStatus) let open = await this.handleOpen(order) console.log('==>>handleOpen', open) } catch(e){ console.log('==>>e', e) this.handleOpenFailed() } } else if(error.code == this.errorTypes.openMonthCardError.code){ // 月卡开卡失败处理 this.handleOpenFailed() } } }, // 订单状态反查 queryOrderStatus(param){ let that = this return new Promise((resolve, reject) => { getOrderStatus(param).then(res => { if(res.respCode == 'success' && res.respData ){ if(res.respData.resultCode == 0){ if(res.respData.attributes && res.respData.attributes.tradeState == 'SUCCESS'){ that.model.orderId = res.respData.attributes.orderNo resolve(res.respData) } else { let e = Object.assign({}, this.errorTypes.payOrderError, {orderNo: res.respData.attributes.orderNo}) reject(e) } } else { reject(this.errorTypes.serverError) } } else { reject(this.errorTypes.serverError) } }).catch(err => { reject(this.errorTypes.serverError) }) }) }, // 获取对用的支付方式 getPayModeByType(type){ return new Promise((resolve, reject) => { getPayMode(type).then(res => { this.tempPayMode = res.respData.itemKey resolve(res.respData) }).catch(e => { reject(this.errorTypes.payModeError) }) }) }, // 月卡开卡失败处理 handleOpenFailed(){ // 判断是否使用扫码枪支付 if (this.payMode == this.offlinePay.itemKey){ this.model.payMode = this.tempPayMode } handleOpenPayFailed(this.model).then(res => { var msg = "月卡开卡失败,请稍后重试"; this.$message({ message: msg, type: "success", duration: 5000 }); this.cancel() }).catch(err => { this.$message({ type: 'warning', message: '系统错误,请稍后再试' }) }) }, //支付订单 payOrder(scanner){ let that = this return new Promise((resolve, reject) => { // 获取车牌号码 let carNos = that.model.personCars.map(e => { return e.carNo }).join(',') that.orderParam.carNo = carNos that.orderParam.subsystemCode = that.model.subsystemCode that.orderParam.ysMoney = that.model.ysMoney that.orderParam.ssMoney = that.model.ssMoney that.orderParam.newBeginTime = that.model.beginTime that.orderParam.newEndTime = that.model.endTime that.orderParam.authCode = scanner.code that.orderParam.payChannel = scanner.type payParkServiceOrder(that.orderParam).then(res => { if(res.respCode == 'success' && res.respData){ //需要细分失败类型 that.orderParam.id = res.respData.id that.orderParam.outTradeNo = res.respData.outTradeNo if(res.respData.payStatus == '1'){ that.model.orderId = res.respData.outTradeNo resolve(res.respData) } else if(res.respData.payStatus == '0'){ let e = Object.assign({}, this.errorTypes.payOrderError, {outTradeNo: res.respData.outTradeNo}) reject(e) } else if(res.respData.payStatus == '-2'){ reject(this.errorTypes.serverError) } } else { reject(this.errorTypes.serverError) } }).catch(err => { reject(this.errorTypes.serverError) }) }) }, }
参考:
基于VUE的插件,实现无需输入框得情况下网页监听扫码枪扫码结果
本地测试html文件:
<!DOCTYPE html> <html> <head> <title>扫码枪测试demo</title> </head> <body> <div>
<!--hidden 可以先去掉来测试扫码枪-->
<input id="inputData" style="width:500px;" type="text" hidden value="" placeholder="请输入优惠券码/扫描优惠券码" onBlur="blur" onkeyup="getDetail()"> </div> <script type="text/javascript"> let msg = '' window.onload = function () { let oInput = document.querySelector('#inputData') let b = '1111'; let _this = this; // oInput.value = b; oInput.focus() document.onkeydown = function(event) { console.log('event', event) if (event.keyCode != 13) { var bizCode = String.fromCharCode(event.keyCode); console.log('bizCode', bizCode) if (event.keyCode >= 48 && event.keyCode <= 122) { b = b + bizCode; } } else { b = ""; } _this.msg = b; if (event.code == "Enter") { console.log('获取到的值',oInput.value) } }; } function getDetail (data) { console.log('获取到的数据', msg) } </script> </body> </html>
hidden