扫码枪扫描二维码 PC端功能对接

  • 首先需要扫码枪连接电脑,
  • 超过N秒不进行扫描二维码或者没有扫到二维码(即没有获取到二维码信息),则取消扫描,需要点击 “重新扫码” 按钮重新扫描
    • 点击“重新扫码”按钮后,重新计时 N 秒,超过 N 秒后需要再次点击“重新扫码”按钮(即只有在 N 秒内扫码才有效)

实现原理

  1. 页面要放一个 input 输入框,用来 存放扫码枪扫描到的内容,便于我们使用二维码信息;
  2. 扫描的同时,input 框要 获取到光标,扫描到的二维码内容才可以存在 input 输入框;
    • 在可以扫描二维码的 N 秒内,我们要将 input 获取光标,超过 N 秒后,input 框自动失去光标;
    • 在扫描二维码的 N 秒内:为防止用户点击页面其他空白位置导致 input 框失去光标获取不到二维码信息 → 当前页面 无论点哪里 (该页面是一个弹框,不存在点击其他位置与其他事件冲突的情况),都要让扫描二维码后获得的信息展示的 input 框获取焦点,详见方法 inputFocusHandler()
  3. 扫码枪扫描二维码获取到信息后,结束 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>

页面展示

扫码枪扫描二维码 PC端功能对接_第1张图片
扫码枪扫描二维码 PC端功能对接_第2张图片

你可能感兴趣的:(项目问题,对接硬件,java,前端,服务器)