You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
467 lines
14 KiB
467 lines
14 KiB
<template>
|
|
<view class="">
|
|
<view class="btn">
|
|
<view class="print-mode-card">
|
|
<view class="print-mode-title">打印方式</view>
|
|
<view class="print-mode-options">
|
|
<view :class="['print-mode-option', printingMethod == 'bluetooth' ? 'active' : '']" @tap="changePrintMethod('bluetooth')">蓝牙打印</view>
|
|
<view :class="['print-mode-option', printingMethod == 'cloud' ? 'active' : '']" @tap="changePrintMethod('cloud')">云打印</view>
|
|
</view>
|
|
</view>
|
|
<view class="connected-printer" v-if="printingMethod == 'cloud'">
|
|
<text>{{cloudPrinterSn ? '已绑定云打印机' : '未绑定云打印机'}}</text>
|
|
<text class="connected-printer-name">{{cloudPrinterName || cloudPrinterSn || '请到后台绑定'}}</text>
|
|
</view>
|
|
<button type="primary" style="margin-top: 40rpx;font-size: 32rpx;" :loading="isCloudPrint" v-if="printingMethod == 'cloud' && cloudPrinterSn"
|
|
@tap="cloudPrintTest" text=''>云打印测试</button>
|
|
<view class="connected-printer" v-if="printingMethod == 'bluetooth' && savedDeviceId">
|
|
<text>{{okAddress ? '已连接设备' : (linkAddress == savedDeviceId ? '正在自动连接' : '已保存设备')}}</text>
|
|
<text class="connected-printer-name">{{connectedDeviceName || savedDeviceId}}</text>
|
|
</view>
|
|
<button type="primary" :loading="isSearching" v-if="printingMethod == 'bluetooth' && isSearching == false" @tap="startSearch(true)"
|
|
text="">搜索蓝牙设备
|
|
</button>
|
|
<button type="primary" :loading="isSearching" v-if="printingMethod == 'bluetooth' && isSearching == true" @tap="stopSearch" text="">搜索蓝牙设备
|
|
</button>
|
|
<button type="primary" style="margin-top: 40rpx;" v-if="printingMethod == 'bluetooth' && savedDeviceId !=''" @tap="endSearch(true)"
|
|
text="">删除已连接蓝牙设备
|
|
</button>
|
|
<button type="primary" style="margin-top: 40rpx;font-size: 32rpx;" :loading="isPrint" v-if="printingMethod == 'bluetooth' && okAddress"
|
|
@tap="pickUpOnce" text=''>打印测试</button>
|
|
</view>
|
|
|
|
<view class="content" v-if="printingMethod == 'bluetooth'">
|
|
<text>新设备</text>
|
|
<view v-for="(item) in list" :data-title="item.deviceId" :data-name="item.name"
|
|
:data-advertisData="item.advertisServiceUUIDs" :key="item.deviceId"
|
|
@tap="bindViewTap(item.deviceId,true)">
|
|
<view>
|
|
<text>{{item.name}}</text>
|
|
<view v-if="linkAddress == item.deviceId" style="background-color: #4caf50;">正在匹配</view>
|
|
<view v-if="okAddress == item.deviceId">匹配成功</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
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();
|
|
export default {
|
|
components: {},
|
|
data() {
|
|
return {
|
|
isSearching: false,
|
|
list: [],
|
|
savedDeviceId: '',
|
|
connectedDeviceName: '',
|
|
okAddress: '',
|
|
linkAddress: '',
|
|
data: {
|
|
"settled_name": "#0112配送",
|
|
"detail": {
|
|
"total_amount": "137.00",
|
|
"other_amount": "0.00",
|
|
"discount_amount": "0.00",
|
|
"actual_amount": "137.00",
|
|
"order_sn": "20220512165337",
|
|
"goods_count": 3,
|
|
"order_time": "2022-05-12 16:53:00",
|
|
"supplier_id": 1
|
|
},
|
|
"code": "https://www.oulaisong.com/purchase?id=8",
|
|
"list": [{
|
|
"id": 8,
|
|
"goods_name": "红烧带鱼",
|
|
"article_number": "1",
|
|
'sum_price':'16.00'
|
|
}, {
|
|
"id": 9,
|
|
"goods_name": "女童外套",
|
|
"article_number": "2",
|
|
|
|
"sum_price": "34.00"
|
|
}, {
|
|
"id": 10,
|
|
"goods_name": "25",
|
|
"article_number": "3",
|
|
"sum_price": "3.00"
|
|
}]
|
|
},
|
|
isPrint: false,
|
|
isCloudPrint: false,
|
|
printingMethod: uni.getStorageSync('printingMethod') || 'bluetooth',
|
|
cloudPrinterSn: '',
|
|
cloudPrinterName: '',
|
|
}
|
|
},
|
|
//页面卸载是关闭蓝牙链接
|
|
// onUnload() {
|
|
// uni.hideLoading()
|
|
// bluetooth.closeBLEConnection();
|
|
// bluetooth.closeBluetoothAdapter();
|
|
// },
|
|
//页面打开,打开蓝牙链接
|
|
onLoad() {},
|
|
onShow() {
|
|
this.initSavedPrinter()
|
|
this.getPrintConfig()
|
|
},
|
|
methods: {
|
|
endSearch(){
|
|
uni.hideLoading()
|
|
bluetooth.closeBLEConnection();
|
|
bluetooth.closeBluetoothAdapter();
|
|
bluetooth.removeSavedDevice();
|
|
this.savedDeviceId = ''
|
|
this.connectedDeviceName = ''
|
|
this.okAddress = ''
|
|
this.linkAddress = ''
|
|
},
|
|
initSavedPrinter() {
|
|
const deviceId = uni.getStorageSync('bluetoothDeviceId');
|
|
const deviceName = uni.getStorageSync('bluetoothDeviceName');
|
|
this.savedDeviceId = deviceId || '';
|
|
this.connectedDeviceName = deviceName || '';
|
|
if (!deviceId) {
|
|
this.okAddress = '';
|
|
this.linkAddress = '';
|
|
return;
|
|
}
|
|
this.linkAddress = deviceId;
|
|
bluetooth.connectSavedDevice({
|
|
silent: true
|
|
}).then(res => {
|
|
if (!res) return;
|
|
this.okAddress = deviceId;
|
|
this.linkAddress = '';
|
|
}).catch(() => {
|
|
this.okAddress = '';
|
|
this.linkAddress = '';
|
|
});
|
|
},
|
|
getPrintConfig() {
|
|
const shopId = uni.getStorageSync('shopId');
|
|
if (!shopId || !this.NB) return;
|
|
this.NB.sendRequest('/app/shop/printConfig', {
|
|
shopId
|
|
}, false, 'GET', 'application/x-www-form-urlencoded').then(res => {
|
|
if (res.code == 200 && res.result) {
|
|
this.printingMethod = res.result.printingMethod || 'bluetooth';
|
|
this.cloudPrinterSn = res.result.printerSn || '';
|
|
this.cloudPrinterName = res.result.printerName || '';
|
|
uni.setStorageSync('printingMethod', this.printingMethod);
|
|
uni.setStorageSync('cloudPrinterSn', this.cloudPrinterSn);
|
|
uni.setStorageSync('cloudPrinterName', this.cloudPrinterName);
|
|
}
|
|
}).catch(() => {});
|
|
},
|
|
changePrintMethod(method) {
|
|
if (method == this.printingMethod) return;
|
|
const shopId = uni.getStorageSync('shopId');
|
|
if (!shopId) {
|
|
uni.showToast({
|
|
title: '请先选择店铺',
|
|
icon: 'none'
|
|
});
|
|
return;
|
|
}
|
|
this.NB.sendRequest('/app/shop/printConfig', {
|
|
shopId,
|
|
printingMethod: method
|
|
}, false, 'POST', 'application/x-www-form-urlencoded').then(res => {
|
|
if (res.code == 200 && res.result) {
|
|
this.printingMethod = res.result.printingMethod || method;
|
|
this.cloudPrinterSn = res.result.printerSn || '';
|
|
this.cloudPrinterName = res.result.printerName || '';
|
|
uni.setStorageSync('printingMethod', this.printingMethod);
|
|
uni.setStorageSync('cloudPrinterSn', this.cloudPrinterSn);
|
|
uni.setStorageSync('cloudPrinterName', this.cloudPrinterName);
|
|
uni.showToast({
|
|
title: '保存成功',
|
|
icon: 'none'
|
|
});
|
|
} else {
|
|
uni.showToast({
|
|
title: res.message || '保存失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
}).catch(() => {});
|
|
},
|
|
cloudPrintTest() {
|
|
const shopId = uni.getStorageSync('shopId');
|
|
if (!shopId) return;
|
|
if (this.isCloudPrint) return;
|
|
this.isCloudPrint = true;
|
|
this.NB.sendRequest('/app/shop/printTest', {
|
|
shopId
|
|
}, false, 'POST', 'application/x-www-form-urlencoded').then(res => {
|
|
this.isCloudPrint = false;
|
|
uni.showToast({
|
|
title: res.message || (res.code == 200 ? '测试打印已发送' : '测试打印失败'),
|
|
icon: 'none'
|
|
});
|
|
}).catch(() => {
|
|
this.isCloudPrint = false;
|
|
});
|
|
},
|
|
getData() {
|
|
var that = this;
|
|
that.startSearch(false);
|
|
},
|
|
async bindViewTap(deviceId, state) {
|
|
var _this = this;
|
|
const device = this.list.find(item => item.deviceId == deviceId);
|
|
_this.okAddress = '';
|
|
_this.linkAddress = deviceId;
|
|
|
|
if (state == true) {
|
|
_this.isSearching = false
|
|
}
|
|
try {
|
|
if (_this.savedDeviceId && _this.savedDeviceId != deviceId) {
|
|
bluetooth.closeBLEConnection(_this.savedDeviceId);
|
|
}
|
|
await bluetooth.connectDevice(deviceId, {
|
|
deviceName: device && device.name
|
|
});
|
|
_this.okAddress = deviceId;
|
|
_this.savedDeviceId = deviceId;
|
|
_this.connectedDeviceName = device && device.name ? device.name : uni.getStorageSync('bluetoothDeviceName');
|
|
_this.linkAddress = '';
|
|
_this.stopSearch();
|
|
} catch (e) {
|
|
_this.okAddress = '';
|
|
_this.linkAddress = '';
|
|
//TODO handle the exception
|
|
|
|
}
|
|
},
|
|
//打印一次
|
|
pickUpOnce() {
|
|
this.isPrint = true;
|
|
bluetooth.notifyBLECharacteristicValue();
|
|
let self = this;
|
|
setTimeout(() => {
|
|
self.writeBLECharacteristicValue();
|
|
}, 500);
|
|
},
|
|
//写入控制命令
|
|
async writeBLECharacteristicValue() {
|
|
let data = this.data;
|
|
let printerJobs = new PrinterJobs();
|
|
printerJobs.setAlign('ct').setSize(2, 2).setLineSpacing(80).print('#0112配送')
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('预计时间:2026-02-01 13:41:00')
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('七里香快餐明珠店')
|
|
.print(printerUtil.fillLine('-', 1, 50))
|
|
.setAlign('lt').setSize(2, 2).setLineSpacing(80).print('王先生')
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('联系电话: *******0775')
|
|
.setAlign('lt').setSize(2, 2).setLineSpacing(80).print('地址:黑背生东川建设集团有限公司黑恶生运河区****')
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('为保护隐私,顾客电话及地址已被隐藏,您可登录商家端或骑手端查看')
|
|
.print(printerUtil.fillLine('-', 1, 50));
|
|
|
|
|
|
for (var i = 0; i < data.list.length; i++) {
|
|
printerJobs.setAlign('lt').setSize(1, 1).setLineSpacing(40).print(data.list[i].goods_name)
|
|
|
|
|
|
let setLineSpacing = 40
|
|
|
|
printerJobs.setLineSpacing(setLineSpacing).print(printerUtil.inlineArr([{
|
|
'text': 'X' + data.list[i].article_number,
|
|
'width': 20,
|
|
}, {
|
|
'text': data.list[i].sum_price,
|
|
'width': 10,
|
|
}], 1, 50));
|
|
}
|
|
printerJobs.print(printerUtil.fillLine('-', 1, 50))
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('配送费:1圆')
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('合计金额:17圆')
|
|
.print(printerUtil.fillLine('-', 1, 50))
|
|
.setAlign('lt').setSize(1, 1).setLineSpacing(40).print('商品取到后,如有任何商品问题,请及时联系商家和平台,客服将为您服务,客服电话15533910775,谢谢您的惠顾')
|
|
.println();
|
|
let buffer = printerJobs.buffer();
|
|
this.sendPrint(buffer);
|
|
},
|
|
sendPrint(buffer) {
|
|
// 1.并行调用多次会存在写失败的可能性
|
|
// 2.建议每次写入不超过20字节
|
|
// 分包处理,延时调用
|
|
let that = this
|
|
const maxChunk = 20;
|
|
const delay = 20;
|
|
that.isPrint = true;
|
|
for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
|
|
let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
|
|
setTimeout(this.sendPrintData, j * delay, subPackage);
|
|
}
|
|
that.isPrint = false;
|
|
},
|
|
sendPrintData(buffer) {
|
|
bluetooth.writeBLECharacteristicValue(buffer).then(res => {});
|
|
},
|
|
startSearch(state) {
|
|
let that = this
|
|
bluetooth.openBluetoothAdapter().then(e => {
|
|
that.isSearching = true;
|
|
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: err => {
|
|
uni.hideLoading();
|
|
uni.showToast({
|
|
title: `搜索设备失败` + JSON.stringify(err)
|
|
})
|
|
}
|
|
})
|
|
}).catch(e => {
|
|
|
|
});
|
|
},
|
|
// 停止搜索
|
|
stopSearch() {
|
|
this.isSearching = false;
|
|
uni.hideLoading();
|
|
bluetooth.stopBluetoothDevicesDiscovery();
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
page {
|
|
background: #F7F8FA;
|
|
}
|
|
</style>
|
|
<style scoped lang="scss">
|
|
.btn {
|
|
padding: 40rpx;
|
|
}
|
|
|
|
.print-mode-card {
|
|
margin-bottom: 30rpx;
|
|
padding: 24rpx 30rpx;
|
|
border-radius: 16rpx;
|
|
background: #fff;
|
|
}
|
|
|
|
.print-mode-title {
|
|
margin-bottom: 20rpx;
|
|
font-size: 30rpx;
|
|
font-weight: 700;
|
|
color: #333;
|
|
}
|
|
|
|
.print-mode-options {
|
|
display: flex;
|
|
}
|
|
|
|
.print-mode-option {
|
|
flex: 1;
|
|
height: 72rpx;
|
|
line-height: 72rpx;
|
|
text-align: center;
|
|
border-radius: 12rpx;
|
|
background: #f5f6f7;
|
|
color: #333;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
.print-mode-option.active {
|
|
background: #3769FF;
|
|
color: #fff;
|
|
}
|
|
|
|
.print-mode-option+.print-mode-option {
|
|
margin-left: 20rpx;
|
|
}
|
|
|
|
.connected-printer {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 30rpx;
|
|
padding: 24rpx 30rpx;
|
|
border-radius: 16rpx;
|
|
background: #fff;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.connected-printer-name {
|
|
max-width: 420rpx;
|
|
color: #3769FF;
|
|
text-align: right;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.content {
|
|
padding: 40rpx;
|
|
|
|
&>text {
|
|
display: block;
|
|
padding-bottom: 30rpx;
|
|
font-size: 28rpx;
|
|
color: #333
|
|
}
|
|
|
|
&>view {
|
|
background-color: #fff;
|
|
padding: 30rpx 40rpx;
|
|
margin-bottom: 24rpx;
|
|
|
|
&>view {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
|
|
&>text {
|
|
margin-left: 24rpx;
|
|
font-size: 32rpx;
|
|
font-weight: 500;
|
|
color: #333333;
|
|
}
|
|
|
|
&>view {
|
|
border-radius: 10rpx;
|
|
font-size: 24rpx;
|
|
color: #fff;
|
|
background-color: #3769FF;
|
|
padding: 5rpx 10rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
&>view:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
</style>
|
|
|