import PrinterJobs from '@/components/print/printerjobs.js' import printerUtil from '@/components/print/printerutil.js' import util from '@/components/print/util.js' import drawQrcode from '@/components/print/weapp.qrcode.esm.js' import Bluetooth from '@/components/print/bluetooth.js' let bluetooth = new Bluetooth(); let isPrint= false let data1 = {} export default { // onDone: 打印完成(或失败/跳过)后执行的回调,用于队列驱动 getData(onDone) { var that = this; if(uni.getStorageSync('bluetoothDeviceId')){ let id = uni.getStorageSync('bluetoothDeviceId') const baseUrl = getApp().globalData.mainurl uni.request({ url: baseUrl + "/mall/order/detail/"+ getApp().globalData.printData[0].order_id, data: {}, method:'GET', header: { "content-type": 'application/x-www-form-urlencoded', 'accessToken':uni.getStorageSync('hiver_token') }, success: function(res) { if (res.data.code == 200) { data1 = res.data.result that.bindViewTap(id, false, onDone) } else { uni.showToast({ title: res.data.message, icon: 'none' }); // 请求失败也需要通知队列继续处理下一条 if (typeof onDone === 'function') onDone(); return; } uni.hideLoading(); }, fail: function(err) { uni.hideLoading(); // 请求失败也需要通知队列继续处理下一条 if (typeof onDone === 'function') onDone(); } }) }else{ uni.showModal({ title: '提示', content: '您还没有连接打印机,将无法为您打印小票!', confirmText:'连接蓝牙', cancelText:'暂不连接', success: function (res) { if (res.confirm) { uni.navigateTo({ url:'/pages/myCenter/setPrint' }) } // 未连接打印机也通知队列继续(跳过当前条) if (typeof onDone === 'function') onDone(); } }); } }, async bindViewTap(deviceId, state, onDone) { var _this = this; try { //1.链接设备 await bluetooth.createBLEConnection(deviceId).then((res) => { bluetooth.deviceId = deviceId; }).catch((e) => { throw e; }); let server = []; //2.寻找服务 await bluetooth.getBLEDeviceServices().then((res) => { bluetooth.notifyId = ''; bluetooth.writeId = ''; bluetooth.num = 0; bluetooth.serviceList = res }).catch((e) => { throw e; }); //3.获取蓝牙设备所有服务 let result3 = await bluetooth.getBLEDeviceCharacteristics().then(res => { uni.setStorageSync('bluetoothDeviceId', deviceId); this.pickUpOnce(onDone) }).catch((e) => { throw e; }); } catch (e) { // 蓝牙连接异常也需要通知队列继续 if (typeof onDone === 'function') onDone(); } }, //打印一次 pickUpOnce(onDone) { isPrint = true; bluetooth.notifyBLECharacteristicValue(); let self = this; setTimeout(() => { self.writeBLECharacteristicValue(onDone); }, 500); }, maskPhoneLastFour(phone) { if (!phone) return ''; const str = String(phone); if (str.length <= 4) return str; // 长度不足4位直接返回 return str.replace(/.(?=.{4})/g, '*'); }, //写入控制命令 async writeBLECharacteristicValue(onDone) { let printerJobs = new PrinterJobs(); printerJobs.setAlign('ct').setSize(2, 2).setLineSpacing(60).print( (data1.deliveryType == 1 && data1.orderType == 3 ? data1.deliveryInfo.numberCode :data1.numberCode) + ( (data1.status == 7 || data1.status == 11) ? '待退款' : data1.deliveryType == 1 && data1.orderType == 3 ? '面对面配送' : data1.deliveryType == 1 ? '配送' : data1.isPack == 0 ? '到店-堂食' : data1.isPack == 1 ? '到店-打包' : '到店' ) ); printerJobs.setSize(1, 1).setLineSpacing(40); printerJobs.setAlign('lt').print( '预计时间:' + (data1.deliveryInfo == null ? '暂无' : this.formatTime(data1.deliveryInfo.mustFinishTime)) ); printerJobs.setAlign('lt').print(data1.shopName); printerJobs.print(printerUtil.fillLine('-', 1, 32)); printerJobs.setAlign('lt').setSize(2, 2).setLineSpacing(60).print( data1.receiverName == null ? '暂无' : data1.receiverName ); printerJobs.setSize(1, 1).setLineSpacing(40); printerJobs.setAlign('lt').print('联系电话: ' + this.maskPhoneLastFour(data1.receiverPhone)); printerJobs.setAlign('lt').setSize(2, 2).setLineSpacing(60).print( '地址:' + (data1.receiverAddress == null ? '暂无' : data1.receiverAddress) ); printerJobs.setSize(1, 1).setLineSpacing(40); printerJobs.setAlign('lt').print('顾客电话已被隐藏,您可登录商家端或骑手端查看'); printerJobs.print(printerUtil.fillLine('-', 1, 32)); // 商品列表 for (var i = 0; i < data1.goodsList.length; i++) { var productName = this.removeEmojis(data1.goodsList[i].productName) printerJobs.setAlign('lt').setSize(2, 2).print(productName); if (data1.goodsList[i].specs) { printerJobs.setSize(1, 1).print(this.delNode(data1.goodsList[i].specs)); } printerJobs.setSize(2, 2); printerJobs.setAlign('lt').text('¥ ',data1.goodsList[i].price); printerJobs.text(" "); printerJobs.print('X' + data1.goodsList[i].quantity); printerJobs.setSize(1, 1); } printerJobs.print(printerUtil.fillLine('-', 1, 32)); printerJobs.setAlign('lt').print('配送费:' + data1.deliveryFee); printerJobs.print('合计金额:' + data1.totalAmount); printerJobs.setSize(2, 2).print('备注:' + data1.remark); printerJobs.setSize(1, 1).print(printerUtil.fillLine('-', 1, 32)); printerJobs.setAlign('lt').print('商品取到后,如有任何商品问题,请及时联系商家和平台,客服将为您服务,客服电话 15533910775,谢谢您的惠顾'); printerJobs.lineFeed(3); let buffer = printerJobs.buffer(); this.sendPrint(buffer, onDone); }, // 去除字符串中的 Emoji 表情 removeEmojis(str) { if (!str) return ''; // 兼容性极好的 Emoji 正则表达式(支持各种运行环境,包括小程序和旧版浏览器) var emojiRegex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g; return str.replace(emojiRegex, ''); }, formatTime(value) { if (!value) return ''; if (value == '尽快送达') return '尽快送达'; const date = new Date(value); // 获取年份 const year = date.getFullYear(); // 获取月份 (getMonth 返回 0-11,所以需要 +1),并补齐0 const month = String(date.getMonth() + 1).padStart(2, '0'); // 获取日 (getDate),并补齐0 const day = String(date.getDate()).padStart(2, '0'); // 获取小时 (getHours),并补齐0 const hour = String(date.getHours()).padStart(2, '0'); // 获取分钟 (getMinutes),并补齐0 const minute = String(date.getMinutes()).padStart(2, '0'); // 获取秒 (getSeconds),并补齐0 const second = String(date.getSeconds()).padStart(2, '0'); // 拼接格式:年-月-日 时:分:秒 return `${year}-${month}-${day} ${hour}:${minute}:${second}`; }, delNode(data) { // 1. 统一转为字符串 let str; if (typeof data === 'object' && data !== null) { // 对象或数组 → JSON 字符串 str = JSON.stringify(data); } else if (typeof data === 'string') { str = data; } else { // 其他类型(数字、布尔等)先转字符串 str = String(data); } // 2. 删除所有大括号 { } 和双引号 " const result = str.replace(/[{}"]/g, ''); return result; }, sendPrint(buffer, onDone) { const maxChunk = 20; // 每次20字节 const delay = 50; // 间隔50ms isPrint = true; const totalLength = buffer.byteLength; let currentIndex = 0; // 创建源数据的视图,方便读取 const srcView = new Uint8Array(buffer); const sendNextChunk = () => { if (currentIndex >= totalLength) { // 发送完毕 isPrint = false; if (typeof onDone === 'function') onDone(); return; } const end = Math.min(currentIndex + maxChunk, totalLength); const chunkLength = end - currentIndex; const valueToSend = new ArrayBuffer(chunkLength); const dstView = new Uint8Array(valueToSend); dstView.set(srcView.subarray(currentIndex, end)); bluetooth.writeBLECharacteristicValue(valueToSend).then(() => { currentIndex = end; setTimeout(sendNextChunk, delay); }).catch((err) => { isPrint = false; if (typeof onDone === 'function') onDone(err); }); }; // 开始发送第一个包 sendNextChunk(); }, sendPrintData(buffer) { bluetooth.writeBLECharacteristicValue(buffer).then(res => {}); }, startSearch(state) { let that = this bluetooth.openBluetoothAdapter().then(e => { uni.startBluetoothDevicesDiscovery({ success: res => { uni.onBluetoothDeviceFound(result => { let arr = that.list; let devices = []; let list = result.devices; for (let i = 0; i < list.length; ++i) { if (list[i].name && list[i].name != "未知设备") { let arrNew = arr.filter((item) => { return item.deviceId == list[i].deviceId; }); if (arrNew.length == 0) { devices.push(list[i]); } if (uni.getStorageSync('bluetoothDeviceId') == list[i] .deviceId) { // that.bindViewTap(list[i].deviceId, state) } } } that.list = arr.concat(devices); }); }, fail: res => { uni.hideLoading(); uni.showToast({ title: `搜索设备失败` + JSON.stringify(err) }) } }) }).catch(e => {}); }, // 停止搜索 stopSearch() { uni.hideLoading(); bluetooth.stopBluetoothDevicesDiscovery(); } }