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.
517 lines
13 KiB
517 lines
13 KiB
<template>
|
|
<view class="kk-printer">
|
|
<view class="kk-printer-btn" @tap="handlePrintTap" style="color:#FFF;">
|
|
{{isPrinting?printingText:defaultText}}
|
|
</view>
|
|
<view class="kk-shadow" :class="isShowSearch?'show':''" @tap="handleSearchClose">
|
|
<view class="kk-modal" @tap.stop="doNothing">
|
|
<view class="kk-search-device">
|
|
<view class="kk-btn-wrap">
|
|
<view class="kk-btn-item confirm-btn" @tap="sousuo" v-if="!isSearching">
|
|
搜索设备
|
|
</view>
|
|
<view class="kk-btn-item confirm-btn" v-else>
|
|
搜索中...
|
|
</view>
|
|
<view class="kk-btn-item" @tap="stopSearchBtnTap">
|
|
停止搜索
|
|
</view>
|
|
</view>
|
|
<view class="kk-devices-wrap">
|
|
<view class="empty-wrap" v-if="devicesList.length <= 0">
|
|
<view class="empty-icon"></view>
|
|
<view class="empty-text">无可搜索到的设备</view>
|
|
</view>
|
|
<view class="" v-else>
|
|
<view class="kk-devices-item" v-for="(item,index) in devicesList" :key="index"
|
|
@tap="lianejieshebei(item.deviceId)">
|
|
<view class="name" style="color:#000;">
|
|
<text>设备名称:</text>
|
|
<text>{{item.name?item.name:'未命名'}}</text>
|
|
</view>
|
|
<!-- <view class="rssi">
|
|
<text>信号强度:</text>
|
|
<text>({{item.RSSI}})</text>
|
|
</view> -->
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import gbk from '@/components/kk-printer/utils/printUtil-GBK.js';
|
|
import * as blesdk from './utils/bluetoolth';
|
|
import util from './utils/util.js';
|
|
export default {
|
|
data() {
|
|
return {
|
|
//是否正在打印
|
|
isPrinting: false,
|
|
//是否正在搜索设备
|
|
isSearching: false,
|
|
//是否显示蓝牙列表
|
|
isShowSearch: false,
|
|
//按蓝牙名过滤
|
|
filterName: '',
|
|
//按信号过滤
|
|
filterRSSI: -95,
|
|
//设备列表
|
|
devicesList: [],
|
|
//连接的设备ID
|
|
deviceId: '',
|
|
//根据设备ID获取的服务
|
|
services: '',
|
|
//获取特征值时返回的三要素
|
|
serviceId: '',
|
|
writeId: '',
|
|
readId: '',
|
|
iosNo: false,
|
|
deviceType: 'ios'
|
|
}
|
|
},
|
|
props: {
|
|
//按钮默认文字
|
|
defaultText: {
|
|
type: String,
|
|
default: '打印'
|
|
},
|
|
//按钮打印中的文字
|
|
printingText: {
|
|
type: String,
|
|
default: '打印中...'
|
|
},
|
|
bufferData: {
|
|
type: Array,
|
|
require: true
|
|
},
|
|
roomcode: {
|
|
type: String,
|
|
require: true
|
|
},
|
|
CustName: {
|
|
type: String,
|
|
require: true
|
|
},
|
|
roomid: {
|
|
type: String,
|
|
require: true
|
|
}
|
|
},
|
|
mounted() {
|
|
|
|
},
|
|
watch: {
|
|
isShowSearch(newVal, oldVal) {
|
|
if(newVal == false){
|
|
this.$parent.$parent.isShow = true
|
|
}
|
|
}
|
|
},
|
|
onLoad() {
|
|
|
|
},
|
|
beforeDestroy() {
|
|
|
|
this.stopSearchBtnTap();
|
|
},
|
|
methods: {
|
|
doNothing() {
|
|
return;
|
|
},
|
|
//点击打印按钮
|
|
handlePrintTap() {
|
|
let that = this
|
|
console.log(this.$parent)
|
|
this.$parent.$parent.clickShow();
|
|
uni.showLoading({
|
|
mask: true,
|
|
title: '加载中...'
|
|
});
|
|
uni.getSystemInfo({
|
|
success(res) {
|
|
that.deviceType = res.osName
|
|
console.log('设备类型', res.osName)
|
|
}
|
|
})
|
|
// 初始化蓝牙模块
|
|
wx.openBluetoothAdapter({ //111
|
|
mode: 'central',
|
|
success: (res2) => {
|
|
console.log('初始化蓝牙模块', res2)
|
|
that.sousuo()
|
|
},
|
|
fail: (res) => {
|
|
console.log('初始化蓝牙模块', res)
|
|
that.tui.toast('初始化失败', res)
|
|
this.isShowSearch = true
|
|
uni.hideLoading();
|
|
}
|
|
})
|
|
|
|
},
|
|
// 开始搜索附近的蓝牙外围设备
|
|
sousuo() {
|
|
let that = this;
|
|
wx.startBluetoothDevicesDiscovery({ //222
|
|
success(res3) {
|
|
console.log('获取设备成功', res3)
|
|
that.jiantingshebei()
|
|
},
|
|
fail(err) {
|
|
console.log('获取设备失败', err)
|
|
that.tui.toast('获取设备失败', err)
|
|
wx.closeBLEConnection({
|
|
deviceId: uni.getStorageSync('deviceId'),
|
|
success(res) {
|
|
console.log(res)
|
|
}
|
|
})
|
|
uni.removeStorageSync('deviceId');
|
|
that.isShowSearch = true
|
|
that.sousuo()
|
|
uni.hideLoading();
|
|
}
|
|
})
|
|
},
|
|
//停止搜索蓝牙设备
|
|
stopSearchBtnTap() {
|
|
wx.stopBluetoothDevicesDiscovery()
|
|
},
|
|
/**
|
|
* jiantingshebei方法,判断缓存中有没有deviceId等数据的时候,
|
|
* 有: 直接拿到缓存中的deviceId等,直接请求 wx.createBLEConnection
|
|
* 没有:才会调用 wx.onBluetoothDeviceFound 搜索
|
|
*/
|
|
jiantingshebei() {
|
|
let that = this;
|
|
if (uni.getStorageSync('deviceId')) {
|
|
console.log("111")
|
|
// that.huoqufuwu(uni.getStorageSync('deviceId'))
|
|
that.lianejieshebei(uni.getStorageSync('deviceId'))
|
|
} else {
|
|
console.log("222")
|
|
uni.hideLoading();
|
|
this.isShowSearch = true
|
|
// 监听扫描到新设备事件
|
|
wx.onBluetoothDeviceFound((res4) => { //333
|
|
console.log('监听新设备列表,拿到想要的就自动停止', res4)
|
|
res4.devices.forEach((device) => {
|
|
if (!device.name && !device.localName) {
|
|
return
|
|
}
|
|
that.devicesList.push(device)
|
|
})
|
|
})
|
|
}
|
|
|
|
},
|
|
lianejieshebei(deviceId) {
|
|
let that = this;
|
|
// 连接设备
|
|
wx.createBLEConnection({ //555
|
|
deviceId: deviceId, // 搜索到设备的 deviceId
|
|
success: () => {
|
|
that.isShowSearch = false
|
|
console.log('连接设备成功')
|
|
that.huoqufuwu(deviceId)
|
|
},
|
|
fail: (res) => {
|
|
console.log('连接设备失败', res)
|
|
that.tui.toast('连接设备失败', res)
|
|
if (uni.getStorageSync('deviceId')) {
|
|
that.huoqufuwu(uni.getStorageSync('deviceId'))
|
|
} else {
|
|
wx.closeBLEConnection({
|
|
deviceId: uni.getStorageSync('deviceId'),
|
|
success(res) {
|
|
console.log(res)
|
|
}
|
|
})
|
|
uni.removeStorageSync('deviceId')
|
|
that.sousuo()
|
|
that.isShowSearch = true
|
|
}
|
|
|
|
uni.hideLoading();
|
|
}
|
|
})
|
|
},
|
|
huoqufuwu(deviceId) {
|
|
let that = this;
|
|
//获取服务
|
|
wx.getBLEDeviceServices({ //666
|
|
deviceId: deviceId, // 搜索到设备的 deviceId
|
|
success: (res5) => {
|
|
console.log('获取服务成功', res5)
|
|
that.duxietezhengzhi(deviceId, res5)
|
|
},
|
|
fail: (res) => {
|
|
console.log(res)
|
|
that.tui.toast('获取服务失败', res)
|
|
wx.closeBLEConnection({
|
|
deviceId: uni.getStorageSync('deviceId'),
|
|
success(res1) {
|
|
console.log(res1)
|
|
}
|
|
})
|
|
that.isShowSearch = true
|
|
uni.hideLoading();
|
|
}
|
|
})
|
|
},
|
|
duxietezhengzhi(deviceId, res5) {
|
|
let that = this;
|
|
//读写特征值
|
|
wx.getBLEDeviceCharacteristics({ //777
|
|
deviceId: deviceId, // 搜索到设备的 deviceId
|
|
serviceId: res5.services[0].uuid, // 上一步中找到的某个服务
|
|
success: (res6) => {
|
|
console.log('读写特征值成功', res6)
|
|
for (let i = 0; i < res6.characteristics.length; i++) {
|
|
let item = res6.characteristics[i]
|
|
if (item.properties.write) { // 该特征值可写
|
|
console.log('该特征值可写')
|
|
uni.setStorageSync('deviceId', deviceId);
|
|
uni.setStorageSync('serviceId', res5.services[0].uuid);
|
|
uni.setStorageSync('characteristicId', item.uuid);
|
|
that.xierushuju()
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
fail: (res) => {
|
|
that.tui.toast('读写特征值失败', res)
|
|
wx.closeBLEConnection({
|
|
deviceId: uni.getStorageSync('deviceId'),
|
|
success(res) {
|
|
console.log(res)
|
|
}
|
|
})
|
|
that.isShowSearch = true
|
|
uni.hideLoading();
|
|
}
|
|
})
|
|
},
|
|
xierushuju() {
|
|
let that = this;
|
|
//写入数据
|
|
if (this.defaultText == '打印小票') {
|
|
that.$emit('onPrintSmall');
|
|
} else if (this.defaultText == '确认打印') {
|
|
that.$emit('goPrint');
|
|
} else {
|
|
that.$emit('onPrint');
|
|
}
|
|
console.log('查看数据是否正确', that.bufferData)
|
|
that.$nextTick(() => {
|
|
var dataStr = ''
|
|
for (let m = 0; m < that.bufferData.length; m++) {
|
|
dataStr += that.bufferData[m]
|
|
}
|
|
const maxChunk = that.deviceType == 'android' ? 20 : 180;
|
|
const delay = that.deviceType == 'android' ? 20 : 180;
|
|
|
|
let buffer = gbk.strToGBKByte(dataStr)
|
|
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(that._writeBLECharacteristicValue, j * delay, subPackage);
|
|
}
|
|
|
|
})
|
|
return;
|
|
},
|
|
_writeBLECharacteristicValue(buffer) {
|
|
let that = this;
|
|
wx.writeBLECharacteristicValue({
|
|
deviceId: uni.getStorageSync('deviceId'),
|
|
serviceId: uni.getStorageSync('serviceId'),
|
|
characteristicId: uni.getStorageSync('characteristicId'),
|
|
value: buffer,
|
|
success(res) {
|
|
console.log('打印buffer', buffer)
|
|
console.log('writeBLECharacteristicValue success', res)
|
|
},
|
|
fail(res) {
|
|
console.log('writeBLECharacteristicValue fail', res)
|
|
wx.closeBLEConnection({
|
|
deviceId: uni.getStorageSync('deviceId'),
|
|
success(res) {
|
|
console.log(res)
|
|
}
|
|
})
|
|
if (uni.getStorageSync('deviceId')) {
|
|
console.log("111")
|
|
that.xierushuju()
|
|
} else {
|
|
that.jiantingshebei()
|
|
}
|
|
}
|
|
})
|
|
uni.hideLoading();
|
|
},
|
|
handleSearchClose() {
|
|
this.isShowSearch = false
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.kk-printer {
|
|
&-btn {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.kk-shadow {
|
|
display: none;
|
|
|
|
&.show {
|
|
display: block;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.kk-modal {
|
|
width: 680upx;
|
|
height: 60%;
|
|
padding: 24upx;
|
|
box-sizing: border-box;
|
|
overflow-y: auto;
|
|
border-radius: 20upx;
|
|
background: #ffffff;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.kk-search-device {
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
.kk-filter-wrap {
|
|
width: 100%;
|
|
height: 160upx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: flex-start;
|
|
align-items: flex-start;
|
|
|
|
.filter-title {
|
|
line-height: 70upx;
|
|
font-size: 30upx;
|
|
color: #999999;
|
|
}
|
|
|
|
&>slider {
|
|
width: 90%;
|
|
height: 90upx;
|
|
}
|
|
|
|
&>input {
|
|
padding: 0 20upx;
|
|
box-sizing: border-box;
|
|
border-radius: 10upx;
|
|
height: 90upx;
|
|
width: 100%;
|
|
border: 1upx solid #ebebeb;
|
|
}
|
|
}
|
|
|
|
.kk-btn-wrap {
|
|
width: 100%;
|
|
height: 140upx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
&>view {
|
|
flex: 1 1 auto;
|
|
height: 100upx;
|
|
line-height: 100upx;
|
|
border-radius: 16upx;
|
|
text-align: center;
|
|
color: #ffffff;
|
|
|
|
&.confirm-btn {
|
|
background: #007AFF;
|
|
margin-right: 30upx;
|
|
}
|
|
|
|
&:nth-last-child(1) {
|
|
background: #DD524D;
|
|
}
|
|
}
|
|
}
|
|
|
|
.kk-devices-wrap {
|
|
height: calc(100% - 460upx);
|
|
overflow-y: auto;
|
|
padding: 10upx 20upx;
|
|
box-sizing: border-box;
|
|
border: 1upx solid #ebebeb;
|
|
box-sizing: border-box;
|
|
border-radius: 20upx;
|
|
|
|
.empty-wrap {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.empty-icon {
|
|
width: 268upx;
|
|
height: 240upx;
|
|
background-size: 100% 100%;
|
|
margin-bottom: 26upx;
|
|
}
|
|
|
|
.empty-text {
|
|
width: 100%;
|
|
line-height: 50upx;
|
|
font-size: 30upx;
|
|
text-align: center;
|
|
color: #999999;
|
|
}
|
|
}
|
|
|
|
.kk-devices-item {
|
|
width: 100%;
|
|
border-bottom: 1upx solid #ebebeb;
|
|
padding: 10upx 0;
|
|
box-sizing: border-box;
|
|
z-index: 500;
|
|
|
|
&:nth-last-child(1) {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&>view {
|
|
width: 100%;
|
|
font-size: 30upx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
.kk-placeholder-class {
|
|
font-size: 30upx;
|
|
color: #999999;
|
|
}
|
|
</style>
|