Commit c0fd900e authored by xieyishang's avatar xieyishang

优化扫码枪监听,可用按钮监听扫码枪。~

parent 8fe6e58a
...@@ -8,8 +8,15 @@ import router from './router' ...@@ -8,8 +8,15 @@ import router from './router'
import store from './store' import store from './store'
import App from './App.vue' import App from './App.vue'
import BarcodeScanner from '@/utils/barcode-scanner';
const app = createApp(App); const app = createApp(App);
//扫码组件
app.use(BarcodeScanner);
app.use(i18n); app.use(i18n);
app.use(store); app.use(store);
app.use(router); app.use(router);
......
<template> <template>
<el-container> <el-container>
<el-main class="nopadding"> <el-main class="nopadding">
<!-- <input class="input" id="inputsmq" ref="inputRef" type="password" /> -->
<input class="input" id="inputsmq" value="" ref="scannerInput" type="text" @focus="onFocus" @blur="blurfun" @input="handleScannerInput" />
<!-- --> <!-- -->
<div class="pos"> <div class="pos">
<el-row> <el-row>
...@@ -109,11 +108,11 @@ ...@@ -109,11 +108,11 @@
</div> </div>
<div class="pos_btn"> <div class="pos_btn">
<!-- <el-button size="large" type="primary" @click="chooseSerial" >连接扫码枪</el-button> -->
<el-button size="large" type="primary" @click="focusfun(1)" >监听扫码枪识别</el-button> <el-button size="large" type="primary" @click="focusfun(1)" >监听扫码枪识别</el-button>
<el-button size="large" type="danger" @click="delAllGoods()">清空购物单</el-button> <el-button size="large" type="danger" @click="delAllGoods()">清空购物单</el-button>
<el-button size="large" type="success" @click="focusfun(2)">会员扣积分</el-button> <!-- <el-button size="large" type="success" @click="focusfun(2)">会员扣积分</el-button> -->
<el-button size="large" type="success" @click="checkOut()">用户结算</el-button> <el-button size="large" type="success" @click="checkOut()">用户结算</el-button>
<!-- addjf 会员扣积分 --> <!-- addjf 会员扣积分 -->
...@@ -229,9 +228,10 @@ ...@@ -229,9 +228,10 @@
import { ElLoading, ElMessage } from "element-plus"; import { ElLoading, ElMessage } from "element-plus";
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import qrcode from "@/components/qrcode/qrcode.vue"; import qrcode from "@/components/qrcode/qrcode.vue";//二维码
import save from '../goods/lists/save.vue'; import save from '../goods/lists/save.vue'; //编辑产品
import jfsave from "../member/score/save.vue"; import jfsave from "../member/score/save.vue"; //扣积分
export default { export default {
name: "ucenter.cashierhome", name: "ucenter.cashierhome",
...@@ -246,7 +246,6 @@ export default { ...@@ -246,7 +246,6 @@ export default {
dialogVisible:false, dialogVisible:false,
scrollbarheight:0, scrollbarheight:0,
dialogVisibletwo:false, dialogVisibletwo:false,
dialog: {search: false, import: false, print: false}, dialog: {search: false, import: false, print: false},
list: { list: {
apiObj: this.$API.goods.lists.list, apiObj: this.$API.goods.lists.list,
...@@ -262,19 +261,12 @@ export default { ...@@ -262,19 +261,12 @@ export default {
}, },
selection: [], selection: [],
search: {}, search: {},
totalMoney: 0, totalMoney: 0,
totalCount: 0, totalCount: 0,
loading:null, loading:null,
scannedCode: '', // 存储扫码后的结果 结果 scannedCode: '', // 存储扫码后的结果 结果
isTyping: false, // 用户是否正在手动输入
typingTimeout: null, // 用于判断输入间隔的定时器
port:null, port:null,
// 原始数据 购物车 // 原始数据 购物车
odata: [], odata: [],
listdata: [], listdata: [],
...@@ -282,10 +274,8 @@ export default { ...@@ -282,10 +274,8 @@ export default {
total: 0, total: 0,
totaljifen:0,//总共所需积分 totaljifen:0,//总共所需积分
Userprice:0,//不使用积分的价格 Userprice:0,//不使用积分的价格
qrcodeurl:"", qrcodeurl:"",
listeningtype:1,//1 扫产品 2扫会员码 状态
listeningtype:1,//1 扫产品 2扫会员码
}; };
}, },
...@@ -294,6 +284,17 @@ export default { ...@@ -294,6 +284,17 @@ export default {
// document.getElementById("order_list").style.height = (orderHeight - 100) + "px"; // document.getElementById("order_list").style.height = (orderHeight - 100) + "px";
this.scrollbarheight = orderHeight - 330; this.scrollbarheight = orderHeight - 330;
//扫码枪监听事件
this.$barcodeScanner.init({
endChar: 'Enter',
minLength: 4
});
document.addEventListener('barcodeScanned', this.handleScan);
},
beforeUnmount() {
this.$barcodeScanner.destroy();
document.removeEventListener('barcodeScanned', this.handleScan);
}, },
created: function() { created: function() {
this.getCartList();//获取购物清单 this.getCartList();//获取购物清单
...@@ -321,15 +322,12 @@ export default { ...@@ -321,15 +322,12 @@ export default {
this.totalMoney = total; this.totalMoney = total;
this.totalCount = totalCount; this.totalCount = totalCount;
this.totaljifen = totaljifen;//积分 this.totaljifen = totaljifen;//积分
this.Userprice = parseFloat(parseFloat(total) - parseFloat(this.totaljifen)).toFixed(2); this.Userprice = parseFloat(parseFloat(total) - parseFloat(this.totaljifen)).toFixed(2);
}, },
deep: true, deep: true,
} }
}, },
methods: { methods: {
add(){ add(){
this.dialog.save = true this.dialog.save = true
this.$nextTick(() => { this.$nextTick(() => {
...@@ -343,9 +341,6 @@ export default { ...@@ -343,9 +341,6 @@ export default {
}) })
}, },
//---规格加入购物车------------------------------------------------------------------------- //---规格加入购物车-------------------------------------------------------------------------
popCloseHandle() {
this.$emit("close");
},
//规格提交 //规格提交
addCartHandle() { addCartHandle() {
this.dialogVisible = false; this.dialogVisible = false;
...@@ -353,8 +348,6 @@ export default { ...@@ -353,8 +348,6 @@ export default {
let number = this.childgoods.popNumber; let number = this.childgoods.popNumber;
// this.$emit("popAddCart", skuId, number); // this.$emit("popAddCart", skuId, number);
this.addCart("multiple", skuId, number); this.addCart("multiple", skuId, number);
}, },
//提交加入购物车 //提交加入购物车
addCart(type, skuId, number) { addCart(type, skuId, number) {
...@@ -384,10 +377,6 @@ export default { ...@@ -384,10 +377,6 @@ export default {
message: "添加成功~", message: "添加成功~",
type: "success" type: "success"
}); });
// getApp().getMyCarList();
// this.show = false;
// this.$forceUpdate();
this.getCartList();//获取购物清单 this.getCartList();//获取购物清单
}else{ }else{
this.$message.error(res.message); this.$message.error(res.message);
...@@ -400,7 +389,6 @@ export default { ...@@ -400,7 +389,6 @@ export default {
stepMinusHandle(num,cc) { stepMinusHandle(num,cc) {
console.info('stepMinusHandle',num,cc); console.info('stepMinusHandle',num,cc);
let that = this; let that = this;
let goods_id = cc.goods_id; let goods_id = cc.goods_id;
let goods_sku_id = cc.goods_sku_id; let goods_sku_id = cc.goods_sku_id;
let cart_id = cc.cart_id; let cart_id = cc.cart_id;
...@@ -451,24 +439,15 @@ export default { ...@@ -451,24 +439,15 @@ export default {
console.log(this.childgoods.popStock.match(/\d+/)[0]); console.log(this.childgoods.popStock.match(/\d+/)[0]);
if (Number(e.detail) > Number(this.childgoods.popStock.match(/\d+/)[0])) { if (Number(e.detail) > Number(this.childgoods.popStock.match(/\d+/)[0])) {
this.$message.error("库存不足~"); this.$message.error("库存不足~");
} else { } else {
this.childgoods.popNumber = e.detail; this.childgoods.popNumber = e.detail;
} }
}, },
//规格被选择 //规格被选择
skuTapHandle(item, outer, cc) { skuTapHandle(item, outer, cc) {
// this.$set(this.childgoods.spec_list[outer], "selected", cc);
this.childgoods.spec_list[outer]["selected"] = cc; this.childgoods.spec_list[outer]["selected"] = cc;
this.changeSku(); this.changeSku();
}, },
// 更新 detail 的方法
updateDetail(newContent) {
this.childgoods = {
...newContent
};
},
//修改规格 //修改规格
changeSku() { changeSku() {
let arr = this.childgoods.spec_list; let arr = this.childgoods.spec_list;
...@@ -496,13 +475,10 @@ export default { ...@@ -496,13 +475,10 @@ export default {
}, },
//删除产品 //删除产品
goodsDeleteHandle(gid, sid) { goodsDeleteHandle(gid, sid) {
let that = this; let that = this;
let cid = that.odata let cid = that.odata
.filter((v) => v.goods_id == gid && v.goods_sku_id == sid) .filter((v) => v.goods_id == gid && v.goods_sku_id == sid)
.map((v) => v.id); .map((v) => v.id);
let req = { let req = {
ids: cid, ids: cid,
}; };
...@@ -621,10 +597,12 @@ export default { ...@@ -621,10 +597,12 @@ export default {
return acc; return acc;
}, {}); }, {});
}, },
//关闭 支付订单 弹窗
cleardialog(){ cleardialog(){
this.dialogVisibletwo = false; this.dialogVisibletwo = false;
this.getCartList(); this.getCartList();
}, },
//关闭 支付订单 弹窗
handleClosetwo(done) { handleClosetwo(done) {
ElMessageBox.confirm('确定要关闭弹窗吗?') ElMessageBox.confirm('确定要关闭弹窗吗?')
.then(() => { .then(() => {
...@@ -636,7 +614,7 @@ export default { ...@@ -636,7 +614,7 @@ export default {
}) })
}, },
//---规格加入购物车------------------------------------------------------------------------- //---规格加入购物车-------------------------------------------------------------------------
//关闭 //关闭 选择规格 弹窗
handleClose(done) { handleClose(done) {
ElMessageBox.confirm('确定要关闭弹窗吗?') ElMessageBox.confirm('确定要关闭弹窗吗?')
.then(() => { .then(() => {
...@@ -647,102 +625,49 @@ export default { ...@@ -647,102 +625,49 @@ export default {
}) })
}, },
//监听扫码枪识别 和 会员扣积分
focusfun(types){ focusfun(types){
// 自动聚焦到输入框,方便直接扫描 // 自动聚焦到输入框,方便直接扫描
if(types==2 && this.totaljifen==0){ if(types==2 && this.totaljifen==0){
this.$message.error("店员,没有东西,怎么扣积分呀~"); this.$message.error("店员,没有可抵积分的东西,怎么扣积分呀~");
return false; return false;
} }
this.listeningtype = types; this.listeningtype = types;
this.loading = ElLoading.service({ // this.loading = ElLoading.service({
lock: true, // lock: true,
text: "请开始扫码识别", // text: "请开始扫码识别",
background: "rgba(255, 255, 255, 0.7)", // background: "rgba(255, 255, 255, 0.7)",
}); // });
this.$nextTick(() => {
this.$refs.scannerInput.focus();
});
// this.loading.close();
}, },
handleScannerInput(event) { // 扫码识别
// return false; handleScan(event){
console.info('handleScan',event);
const input = event.target; console.log('扫描结果:', event.detail);
clearTimeout(this.typingTimeout); // this.$emit('scan', event.detail);
console.log('input.value00:', input.value ); this.scannedCode = event.detail;
if(this.listeningtype==1){
// 如果用户手动输入,则设置一个短暂的延迟 //扫产品
if (this.isTyping) { if(this.scannedCode && this.scannedCode.length>5){
this.typingTimeout = setTimeout(() => { this.childgoods.goods_sn = this.scannedCode;
this.isTyping = false; this.childgoods.store_id = 0;
this.addCart("single", "", 1);
}
// 扫描完成后的处理逻辑 }else if(this.listeningtype==2){
this.scannedCode = input.value; //扫会员码
console.log('Scanned code:', this.scannedCode); console.info("this.scannedCode 扫会员码",this.scannedCode);
var idPattern = /^\d+$/;
console.log('input.value:', input.value ); if(this.scannedCode && idPattern.test(this.scannedCode) && this.scannedCode.length<8){
this.addjf(this.scannedCode);
if(this.listeningtype==1){
//扫产品
if(input.value && input.value.length>5){
this.childgoods.goods_sn = input.value;
this.childgoods.store_id = 0;
this.addCart("single", "", 1);
}
}else if(this.listeningtype==2){
//扫会员码
console.info("input.value 扫会员码",input.value);
var idPattern = /^\d+$/;
if(input.value && idPattern.test(input.value) && input.value.length<8){
this.addjf(input.value);
}
}
// 清空输入框以便下一次扫描
input.value = '';
// 处理扫码后的业务逻辑...
this.blurfun();
}, 700); // 假设用户不会连续输入超过500ms
} else {
clearTimeout(this.typingTimeout);
// 扫描完成后的处理逻辑
this.scannedCode = input.value;
console.log('Scanned code:', this.scannedCode);
if(this.listeningtype==1){
//扫产品
if(input.value && input.value.length>5){
this.childgoods.goods_sn = input.value;
this.childgoods.store_id = 0;
this.addCart("single", "", 1);
}
}else if(this.listeningtype==2){
//扫会员码
console.info("input.value 扫会员码",input.value);
var idPattern = /^\d+$/;
if(input.value && idPattern.test(input.value) && input.value.length<8){
this.addjf(input.value);
}
} }
console.log('input.value:', input.value );
// 清空输入框以便下一次扫描
input.value = '';
this.blurfun();
// 处理扫码后的业务逻辑...
} }
}, },
//会员扣积分 事件
addjf(user_id){ addjf(user_id){
console.info("addjf"); console.info("addjf");
this.dialog.save1 = true this.dialog.save1 = true
...@@ -755,17 +680,7 @@ export default { ...@@ -755,17 +680,7 @@ export default {
}) })
}) })
}, },
onFocus() { // 添加和计算商品价格 添加数量
// 当输入框获得焦点时,认为用户可能开始手动输入
this.isTyping = true;
},
//失去焦点
blurfun(){
console.info('blurfun');
this.isTyping = false;
this.loading.close();
},
// 添加和计算商品价格
addOrderList(goods,index) { addOrderList(goods,index) {
// 商品是否已经存在于订单列表中 // 商品是否已经存在于订单列表中
if(goods.sku.length){ if(goods.sku.length){
...@@ -779,9 +694,7 @@ export default { ...@@ -779,9 +694,7 @@ export default {
this.addCart("single", 0, 1); this.addCart("single", 0, 1);
return false; return false;
} }
}, },
// 全部删除商品 清空购物车 // 全部删除商品 清空购物车
delAllGoods() { delAllGoods() {
// this.odata = []; // this.odata = [];
...@@ -791,7 +704,6 @@ export default { ...@@ -791,7 +704,6 @@ export default {
this.totaljifen = 0; this.totaljifen = 0;
this.childgoods = {spec_list:[]}; this.childgoods = {spec_list:[]};
let req = { let req = {
ids: this.odata.map(product => product.id), ids: this.odata.map(product => product.id),
}; };
...@@ -807,14 +719,11 @@ export default { ...@@ -807,14 +719,11 @@ export default {
.catch((err) => { .catch((err) => {
console.log("🚀 ~ delCart ~ err:", err); console.log("🚀 ~ delCart ~ err:", err);
}); });
}, },
// 模拟结账 用户结算
// 模拟结账
checkOut() { checkOut() {
// this.$message.error("程序猿小哥正在开发中~"); // this.$message.error("程序猿小哥正在开发中~");
if(this.odata.length){ if(this.odata.length){
this.$API.cashier.cart.simple.post({ this.$API.cashier.cart.simple.post({
carts:this.odata.map(item=>{return item.id}), carts:this.odata.map(item=>{return item.id}),
}) })
...@@ -830,7 +739,6 @@ export default { ...@@ -830,7 +739,6 @@ export default {
let qrcodeurl = match[1]; let qrcodeurl = match[1];
console.log(qrcodeurl); // 输出: weixin://wxpay/bizpayurl?pr=g5bMCytz3 console.log(qrcodeurl); // 输出: weixin://wxpay/bizpayurl?pr=g5bMCytz3
this.qrcodeurl = qrcodeurl; this.qrcodeurl = qrcodeurl;
this.dialogVisibletwo = true; this.dialogVisibletwo = true;
this.$nextTick(()=>{ this.$nextTick(()=>{
setTimeout(()=>{ setTimeout(()=>{
...@@ -838,12 +746,10 @@ export default { ...@@ -838,12 +746,10 @@ export default {
},100) },100)
}) })
} }
}else{ }else{
this.$message.error(restwo.message); this.$message.error(restwo.message);
} }
}) })
}else{ }else{
this.$message.error(res.message); this.$message.error(res.message);
} }
...@@ -856,7 +762,6 @@ export default { ...@@ -856,7 +762,6 @@ export default {
}else{ }else{
this.$message.error("店员,没有东西,怎么结账呀~"); this.$message.error("店员,没有东西,怎么结账呀~");
} }
}, },
upsearch(){ upsearch(){
this.$refs.table.reload(this.search); this.$refs.table.reload(this.search);
...@@ -878,58 +783,6 @@ export default { ...@@ -878,58 +783,6 @@ export default {
selectionChange(selection){ selectionChange(selection){
this.selection = selection; this.selection = selection;
}, },
//----2.0 扫码枪监听-------------------------------------------------------------------------------
async chooseSerial(){
if ('serial' in navigator) {
try {
this.port = (await navigator.serial.requestPort()) || null;
console.log('选择串口成功');
this.port && this.openSerial();
} catch (e) {
console.log('选择串口失败');
}
} else {
console.log('浏览器不支持serial API');
}
},
//打开串口读取数据
async openSerial() {
console.info("6666");
await this.port.open({ baudRate: 9600 });
try {
const textDecoder = new TextDecoderStream();
this.port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();
let data = ''; //扫码数据
while (true) {
const { value, done } = await reader.read();
if (done) {
reader.releaseLock();
break;
}
data=`${data}${value}`
if(value.includes('\r')){//读取结束
let codeData=data;
data="";//清空下次读取不会叠加
console.log(`二维码数据:${codeData}`)
//处理拿到数据逻辑
}
}
} catch (error) {
console.error(error);
this.port = null;
} finally {
try {
reader.releaseLock();
//关闭串口
await this.port.close();
} catch (e) {}
}
this.port = null;
}
//----2.0 扫码枪监听-------------------------------------------------------------------------------
}, },
}; };
</script> </script>
......
class BarcodeScanner {
constructor(options = {}) {
this.options = {
endChar: 'Enter', // 默认结束符为回车
minLength: 3, // 最小条码长度
timeout: 100, // 输入超时(毫秒)
...options
};
this.barcode = '';
this.timer = null;
this.init();
this.handleKeyDown = this.handleKeyDown.bind(this); // 固定this指向
}
init() {
// document.addEventListener('keydown', this.handleKeyDown.bind(this));
document.addEventListener('keydown', this.handleKeyDown);
}
handleKeyDown(event) {
// 忽略组合键和结束符之前的处理
if (event.ctrlKey || event.altKey || event.metaKey || event.keyCode === 229) return;
const { key } = event;
// 检测到结束符
if (key === this.options.endChar) {
event.preventDefault(); // 阻止默认回车行为
if (this.barcode.length >= this.options.minLength) {
this.processBarcode(this.barcode);
}
this.reset();
return;
}
// 处理有效字符
if (key.length === 1 && !event.repeat) {
this.barcode += key;
this.resetTimer();
}
}
resetTimer() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
if (this.barcode.length >= this.options.minLength) {
this.processBarcode(this.barcode);
}
this.reset();
}, this.options.timeout);
}
reset() {
this.barcode = '';
clearTimeout(this.timer);
}
processBarcode(barcode) {
console.log('Scanned barcode:', barcode);
// 触发自定义事件或回调函数
const event = new CustomEvent('barcodeScanned', { detail: barcode });
document.dispatchEvent(event);
}
// 保持之前的类实现,但增加销毁方法
destroy() {
// document.removeEventListener('keydown', this.handleKeyDown);
document.removeEventListener('keydown', this.handleKeyDown);
}
}
export default BarcodeScanner
/*
// 使用示例
const scanner = new BarcodeScanner();
// 监听扫描事件
document.addEventListener('barcodeScanned', (e) => {
console.log('Received barcode:', e.detail);
});
*/
//本代码为1.0 版本
\ No newline at end of file
let scannerInstance = null;
export default {
install(app) {
const createScanner = () => {
class BarcodeScanner {
constructor(options = {}) {
// 先绑定事件处理器!!!
this.handleKeyDown = this.handleKeyDown.bind(this);
// 初始化配置
this.options = {
endChar: 'Enter',
minLength: 3,
timeout: 100,
...options
};
// 状态初始化
this.barcode = '';
this.timer = null;
// 启动监听
this.init();
}
init() {
// document.addEventListener('keydown', this.handleKeyDown);
try {
document.addEventListener('keydown', this.handleKeyDown);
} catch (e) {
console.error('条码扫描器初始化失败:', e);
}
}
// 其他方法保持不变...
handleKeyDown(event) {
if (event.ctrlKey || event.altKey || event.metaKey || event.keyCode === 229) return;
const { key } = event;
if (key === this.options.endChar) {
event.preventDefault();
if (this.barcode.length >= this.options.minLength) {
this.processBarcode(this.barcode);
}
this.reset();
return;
}
if (key.length === 1 && !event.repeat) {
this.barcode += key;
this.resetTimer();
}
}
resetTimer() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
if (this.barcode.length >= this.options.minLength) {
this.processBarcode(this.barcode);
}
this.reset();
}, this.options.timeout);
}
reset() {
this.barcode = '';
clearTimeout(this.timer);
}
processBarcode(barcode) {
// 防重复触发(500ms内不处理相同条码)
if (this.lastBarcode === barcode && Date.now() - this.lastScan < 500) return;
this.lastBarcode = barcode;
this.lastScan = Date.now();
// 触发事件...
const event = new CustomEvent('barcodeScanned', { detail: barcode });
document.dispatchEvent(event);
}
destroy() {
document.removeEventListener('keydown', this.handleKeyDown);
}
}
return new BarcodeScanner();
};
app.config.globalProperties.$barcodeScanner = {
init(options) {
if (!scannerInstance) {
scannerInstance = createScanner(options);
}
return scannerInstance;
},
destroy() {
scannerInstance?.destroy();
scannerInstance = null;
}
};
}
};
//本代码为2.0 版本 在使用中
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment