Web 扫码枪对接
扫码枪对接知识点
- 扫码枪本质是一个外接的输入设备(类似键盘)
- 扫码枪按照说明书配置好
- web对接扫码枪的原理:
- 监听input框输入事件keyup.enter
- 扫码枪输出文字的间隔在几十ms
- 可能会受中文输入法的影响(因为本质就是个输入设备)
- 是否需要保留web页面的input显示,取决于你的产品是否需要保留手动输入的功能
- 扫码页面需要不停聚焦input框
<template>
<div class="scanner">
<el-button size="mini" @click="handleClick"> {{ buttonText }}<i class="el-icon-camera-solid el-icon--right"></i> </el-button>
<l-fullscreen-dialog
:okLabel="$t('确认') + $t('(已扫描:') + scanData.length + $t('条)')"
:title="$t(title)"
:visible.sync="visible"
@ok="handleOk"
@opened="handleOpened"
@close="handleClose"
>
<template #headerMid>
<div class="scanner-title">
<el-tag size="medium" type="primary" effect="plain">{{ $t("单据编码:") + document }}</el-tag>
<el-tag size="medium" type="primary" effect="plain">{{ $t("产品名称:") + name }}</el-tag>
<el-tag size="medium" type="primary" effect="plain">{{ $t("已扫描:") + scanData.length + $t(" 条") }}</el-tag>
<el-tag size="medium" type="primary" effect="plain" v-if="max">{{ $t("本次扫描上限:") + max + $t(" 条") }}</el-tag>
</div>
</template>
<el-table size="mini" border stripe :data="scanData" :empty-text="$t('暂无扫描数据')">
<el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="value" label="扫描内容"></el-table-column>
<el-table-column label="操作" width="220" align="right">
<!-- eslint-disable-next-line vue/no-unused-vars -->
<template slot="header" slot-scope="scope">
<input
ref="scannerInput"
class="scanner-input"
v-model="scanInput"
@keyup.enter="handleScan"
@blur="handleInputBlur"
:placeholder="$t('条码失效时,手动输入后回车')"
/>
</template>
<template slot-scope="{ $index }">
<el-button size="mini" type="danger" @click="handleDelete($index)"><i class="el-icon-delete" /> </el-button>
</template>
</el-table-column>
</el-table>
</l-fullscreen-dialog>
</div>
</template>
<script>
export default {
name: "l-scanner",
props: {
title: {
type: String,
default: "扫码录入"
},
document: {
type: String,
default: ""
},
name: {
type: String,
default: ""
},
value: {
type: Array,
default: () => []
},
max: {
type: Number
}
},
data() {
return {
visible: false,
scanInput: "",
scanData: [],
isManualBlur: false
};
},
computed: {
buttonText() {
return this.value.length > 0 ? `已扫码 (${this.value.length} 条)` : "扫码录入";
}
},
methods: {
handleClick() {
this.visible = true;
this.scanData = this.value.map(v => ({ value: v }));
},
handleScan() {
if (this.scanData.length >= this.max) {
this.scanInput = "";
this.$message.warning(this.$t("本次扫描数量已达上限"));
return;
}
const code = this.scanInput.trim();
if (code) {
if (!this.scanData.some(v => v.value === code)) {
this.scanData.push({ value: code });
this.$message.success(this.$t("录入成功"));
} else {
this.$message.warning(this.$t("【警告】重复录入"));
}
this.scanInput = "";
this.$nextTick(this.focusScanner);
}
},
handleDelete(index) {
this.scanData.splice(index, 1);
},
focusScanner() {
const input = this.$refs.scannerInput;
input && input.focus();
},
handleInputBlur() {
if (!this.isManualBlur) {
setTimeout(this.focusScanner, 100);
}
this.isManualBlur = false;
},
handleOpened() {
this.$nextTick(() => {
this.focusScanner();
setTimeout(this.focusScanner, 50);
});
},
handleOk() {
if (this.scanData.length < 1) return this.$message.warning(this.$t("请先扫码后提交数据"));
const result = this.scanData.map(item => item.value);
this.$emit("input", result);
this.$emit("updateNumber", this.scanData.length);
this.visible = false;
},
handleClose() {
this.scanInput = "";
this.scanData = [];
}
}
};
</script>
<style lang="scss" scoped>
.scanner {
&-title {
span {
margin-right: 10px;
}
}
}
.scanner-input {
width: 100%;
}
</style>
洗尽铅华始见金,褪去浮华归本真