Vue获取扫码枪输入内容(可一定程度无视输入法)

背景

WMS项目需要使用扫码枪,但当我输入法为中文输入法时,扫码枪输入会出现中文或者缺字母少数字的情况,尝试了不少方法,最终于找到了一种比较合适的解决办法。

环境

名称内容
语言Vue、ElementUI、Js
扫码枪型号OBM-3802

前提

经过不停的扫码和观察,发现了一点扫码枪的规律

  1. 扫码枪扫描之后模拟了keyboardEvent键盘输入(废话
  2. 扫码枪扫描到大写字母时,在发送key为该字母的keyboardEvent事件后,还会附带一个key为shift的keyboardEvent事件(这个事件在keydown里面监听不到),但是输入小写字母时不会附带这个事件
    注:后来我才知道,这是有些扫码枪可配置的功能,所以如果扫码枪还配置了其他特殊操作,需要自行根据扫码枪规则修改事件规则
  3. 扫码枪模拟的事件很快,单个事件基本低于20~30毫秒,有的只要几毫秒
  4. 当中文输入法开启后,在字母的keyboardEvent事件前都会带一个key为Process的keyboardEvent事件(这个事件在keydown里面是监听不到)(这很重要)

方案

基于上述前提,我在此有两种比较好的解决方案

一、隐藏密码框法

众所周知,密码框是无视输入法的,管你输的什么,只要不是特殊的按键,一律小黑点
那我是不是可以整一个密码框,放在一个文本框下面?当然可以

代码

<template>
  <div>
    <el-form>
      <el-form-item label="输入条码">
        <el-input v-model="barcode" type="password" ref="barcode"></el-input>
        <el-input v-model="barcode" type="text" placeholder="输入条码" readonly="readonly" @focus="handleFocus" style="top:-36px;"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
	name: "Barcodescan",
	data() {
		return {
			barcode: undefined
		}
	},
	methods: {
		handleFocus() {
			this.$refs.barcode.select();
		}
	}
}
</script>

测试

好了,就这么简单,每次只要点击文本框,然后随便你怎么扫,都是对的,如果你需要重新扫,只需要再点一下文本框即可。然后就是无尽的调样式之路。
在这里插入图片描述

优点

简单

缺点

在你以为问题解决了的时候,作为一个成熟的程序员,你该想到,产品经理会问:我点了怎么没有选中样式?我的鼠标光标不在里面,客户会觉得自己不能扫码,我的光标呢?为什么这个框不能选中?客户想复制怎么办?

结果

本人半路出家vue,虽然是个全栈,但是学艺不精,调了一上午样式,一脸头大的我,实在不知道光标怎么模拟(这字母、数字、中文、符号长度都不一致太难搞了,我弄成长度一致了,小黑点又只能调字体大小,小黑点太大了,我的鼠标光标也会跟着变大,凸(⊙▂⊙ )),网上也没有找到大佬搞这个,然后果断放弃了方案一。

二、输入时间间隔法

根据扫码枪输的快,外加WMS仓库人员输条码应该不会很快,再加个输入法会有Process键盘事件这几个特性。我有了个想法,要不不管输入框的内容,他爱咋样咋样,我自己记keyboardEvent事件的输入值好了。

代码

<template>
  <div>
    <!-- 阻止扫码枪的Enter事件自动提交el-form的提交特性 -->
    <el-form @submit.native.prevent>
      <el-form-item label="输入条码">
        <el-input v-model="barcode" type="text" placeholder="输入条码" @keyup.native="handleKeyUp"></el-input>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
let barcodeVue = {
  name: "Barcodescan",
  data() {
    return {
      barcode: "",
      realBarcode: "",
      keyupLastTime: undefined,
    };
  },
  methods: {
    // 处理keyup事件
    handleKeyUp(e) {
      let gap = 0;
      if (this.keyupLastTime) {
        gap = new Date().getTime() - this.keyupLastTime;
        if (gap > 50) {
          gap = 0;
          this.realBarcode = "";
        }
      }
      this.keyupLastTime = new Date().getTime();
      // 输入法会触发keyup事件,key为Process,跳过即可
      if (e.key != "Process" && gap < 50) {
        if (e.key.trim().length == 1) {
          // 输入单个字母或者数字
          this.realBarcode += e.key;
        } else if (e.key.trim() == "Enter") {
          // 根据规则,判断barcode类型,返回数据(自定义规则)
          if (this.realBarcode) {
            this.barcode = this.realBarcode;
            this.realBarcode = "";
          }else{
            return;
          }
        }
      }
    }
  }
};

export default { ...barcodeVue };
</script>

测试

在这里插入图片描述

优点

基本考虑了人正常的行为方式去开发的一个组件,当然体验下来肯定是比方案一要好很多的,起码focus之后框颜色会变,重要的是还有光标了。只要对方拿的是扫码枪,不是扫码机关枪,或者遇上人形扫码枪,基本不会出什么问题。

不足

尽管我们觉得体验好了很多。但是作为一个成熟的程序员,应该会想到产品经理会说:你这个框还要点一下才能输入啊,一点都不智能!如果我有多个码怎么办?就不能我开着页面随便扫,然后智能的去判断是什么码呢?
okokok,那我们在这个方案二的基础上再改良一下。

结果

接着干

三、页面事件监听+输入时间间隔法

在方案二的基础上,我决定从created运行盘古开天辟地之时就开始监听事件,然后再根据自定义的业务规则去判断扫码的类型,最后根据门店门称对比来确定本地还是其他门店单子。

代码

调用组件方
<template>
  <div style="height:800px;width:800px;border:1px solid;padding:20px;margin:0 auto;margin-top:20px;">
    <p style="text-align:center;">测试区域</p>
    <barcodescan shopName="GZ1" @handle="handleBarcode"></barcodescan>
    {{value}}
  </div>
</template>

<script>
import Barcodescan from './components/Barcodescan'

export default {
  name: 'Index',
  components: {
    Barcodescan
  },
  data() {
    return {
      value: undefined
    }
  },
  methods: {
    handleBarcode(barcodeMap) {
      this.value = barcodeMap;
    }
  }
}
</script>
组件方
<template>
  <div>
  </div>
</template>
<script>
let barcodeVue = {
  name: "Barcodescan",
  props: {
    shopName: {
      type: String
    }
  },
  data() {
    return {
      realBarcode: "",
      keyupLastTime: undefined,
      name: undefined,
      regexRules: []
    };
  },
  created() {
    let that = this;
    // 监听页面的keyup事件
    document.onkeyup = function (e) {
      that.handleKeyUp(e);
    };
    this.name = this.shopName;
    this.initRegexRules();
  },
  methods: {
    // 初始化条码规则(自定义)
    initRegexRules() {
      this.regexRules = [
        {
          regex: "/^IN(\\w|\\d)+$/",
          value: "putInStorageNumber"
        },
        {
          regex: "/^CH(\\w|\\d)+$/",
          value: "checkNumber"
        },
        {
          regex: "/^AL(\\w|\\d)+$/",
          value: "allocateNumber"
        },
        {
          regex: "/^\\d{12}$/",
          value: "orderNumber"
        },
        {
          regex: "/^SR(\\w|\\d)+$/",
          value: "transferNumber"
        },
        {
          regex: "/^\\d{12}-\\d{3}$/",
          value: "sendNo"
        },
        {
          regex: "/^PL\\d{10}$/",
          value: "wavePickingNumber"
        },
        {
          regex: "/^PL\\d{10}-\\d{3}$/",
          value: "wavePickingGroupNumber"
        },
        {
          regex: "/^(\\w|\\d)*-[\\w|\\d]*-\\d*-[A-Z]-\\d*/",
          value: "location"
        }
      ]
    },
    // 处理keyup事件
    handleKeyUp(e) {
      let gap = 0;
      if (this.keyupLastTime) {
        gap = new Date().getTime() - this.keyupLastTime;
        if (gap > 50) {
          gap = 0;
          this.realBarcode = "";
        }
      }
      this.keyupLastTime = new Date().getTime();
      // 输入法会触发keyup事件,key为Process,跳过即可
      if (e.key != "Process" && gap < 50) {
        if (e.key.trim().length == 1) {
          // 输入单个字母或者数字
          this.realBarcode += e.key;
        } else if (e.key.trim() == "Enter") {
          // 根据规则,判断barcode类型,返回数据(自定义规则)
          if (this.realBarcode) {
            let data = {
              type: this.barcodeRule(this.realBarcode),
              code: this.realBarcode,
              isLocal: this.isLocal(this.realBarcode)
            };
            this.$emit('handle',data);
            this.realBarcode = "";
          }
        }
      }
    },
    // 判断条码类型,如果没找到,则返回类型为barCode
    barcodeRule(barcode) {
      let value;
      this.regexRules.some((item,index)=>{
         let regex = eval(item.regex);
         if(regex.test(barcode)){
           value = item.value;
           return true;
         }
      })
      return value?value:"barCode";
    },
    // 根据条码是否包含门店名,判断是否本地条码
    isLocal(barcode) {
      return this.name?barcode.indexOf(this.name)!=-1:undefined;
    }
  },
};

export default { ...barcodeVue };
</script>

测试

我在调用时设置的shopName为GZ1,表示本地门店名为GZ1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

优点

页面只需要设置@handle的方法,即可对扫描的内容去赋值、渲染,或者做什么奇怪的操作都可以,最关键的是页面只需要加一个标签就行。随便扫,随便用。

不足

作为一个成熟的产品经理,差不多得了。

结果

就这样吧

  • 26
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
Vue 是一个用于构建用户界面的渐进式 JavaScript 框架,Vue 扫码能够实现无焦点捕获扫码输入扫码是一种硬件设备,它能够将二维码或条形码的信息转化为可识别的数据。传统上,为了使用扫码,用户需要将光标聚焦于输入框中,然后才能够将扫码对准二维码或条形码进行扫描。然而,使用 Vue 扫码插件,我们能够实现无焦点捕获扫码输入的功能。 通过在 Vue 组件中使用合适的库或插件,我们可以实现这一功能。这样做的原理是将扫码的扫描结果直接传递给指定输入框,而不需要用户手动聚焦于输入框中。 在 Vue 的生命周期钩子中,我们可以监听扫码设备的事件,如 "scan"。当扫码扫描到二维码或条形码时,将触发这个事件。我们可以在这个事件中通过 JavaScript 来处理扫描结果,然后将其赋值给指定的输入框。 同时,我们可以借助 Vue 的双向数据绑定功能,实现将扫码扫描结果的值动态更新到其他需要使用这个值的地方。 需要注意的是,为了确保无焦点捕获扫码输入的功能正常工作,我们需要在 Vue 组件中的对应输入框上添加适当的事件监听器,以便识别到扫码输入。 总的来说,通过使用 Vue 扫码插件和相关的库或插件,我们可以实现无焦点捕获扫码输入的功能,提高用户的扫码体验和输入效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值