tianyi 2 weeks ago
parent
commit
7bea92701e
  1. BIN
      components/kk-printer/.DS_Store
  2. BIN
      components/kk-printer/empty-icon.png
  3. 413
      components/kk-printer/index.js
  4. 613
      components/kk-printer/index.vue
  5. BIN
      components/kk-printer/utils/.DS_Store
  6. 402
      components/kk-printer/utils/barcode.js
  7. 695
      components/kk-printer/utils/bluetoolth.js
  8. 23
      components/kk-printer/utils/index.js
  9. 309
      components/kk-printer/utils/printUtil-GBK.js
  10. 778
      components/kk-printer/utils/qrcode.js
  11. 145
      components/kk-printer/utils/util.js
  12. 294
      components/print/bluetooth.js
  13. 42
      components/print/code128.js
  14. 241
      components/print/commands.js
  15. 47
      components/print/encoding-indexes.js
  16. 3313
      components/print/encoding.js
  17. 246
      components/print/escpos.js
  18. 201
      components/print/gbk.js
  19. 206
      components/print/printerjobs.js
  20. 128
      components/print/printerutil.js
  21. 66
      components/print/util.js
  22. 5
      components/print/weapp.qrcode.esm.js
  23. 341
      components/tab-bar/delivery.vue
  24. 47
      components/tab-bar/myCenter.vue

BIN
components/kk-printer/.DS_Store

Binary file not shown.

BIN
components/kk-printer/empty-icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

413
components/kk-printer/index.js

@ -1,413 +0,0 @@
import gbk from '@/components/kk-printer/utils/printUtil-GBK.js';
import * as blesdk from './utils/bluetoolth';
import util from './utils/util.js';
var bufferData = []
var deviceType = 'ios'
export default {
onPrint() {
let that = this
that.yNum = 10
let strCmd = blesdk.CreatCPCLPage(440, 1000, 1, 0);
strCmd += blesdk.addCPCLSETMAG(2, 2)
strCmd += blesdk.addCPCLLocation(2);
strCmd += blesdk.addCPCLSETBOLD('400');
// strCmd += blesdk.addCPCLText('0', that.yNum, '24', '2', 0, getApp().globalData.printData[0].order_id)
strCmd += blesdk.addCPCLText('0', that.yNum, '24', '2', 0, "#0112 外卖单")
strCmd += blesdk.addCPCLLocation(0);
strCmd += blesdk.addCPCLSETBOLD('0')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum+=60, '24', '0', 0, '七里香快餐明珠精品馆')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, "预计时间:2026-02-01 13:14:00")
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, "*********")
strCmd += blesdk.addCPCLSETMAG(2, 2)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '1', 0, '王 先生')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 50, '24', '0', 0, '联系电话: *******0775')
strCmd += blesdk.addCPCLSETMAG(2, 2)
strCmd += blesdk.addCPCLText('0', that.yNum += 50, '24', '0', 0, '地址:河北东川建设集团有限公司(河北省沧州市运河区)******')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 50, '24', '0', 0, '为保护隐私,顾客电话及地址已隐藏,')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '您可登陆商家端或骑手端查看')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '*******************************************')
strCmd += blesdk.addCPCLSETMAG(2, 2)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '1、红烧黛玉')
strCmd += blesdk.addCPCLSETMAG(2, 2)
strCmd += blesdk.addCPCLText('0', that.yNum += 50, '24', '0', 0, 'X1 16元')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 50, '24', '0', 0, '*******************************************')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '配送费: 1元')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '合计金额: 17元')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '*******************************************')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '商品取到后,如有任何商品问题,请')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '联系商家或平台,客服将为您服务客')
strCmd += blesdk.addCPCLSETMAG(1, 1)
strCmd += blesdk.addCPCLText('0', that.yNum += 30, '24', '0', 0, '服电话13521030702,谢谢您的惠顾')
strCmd += blesdk.addCPCLPrint();
bufferData.push(strCmd);
this.handlePrintTap()
},
//点击打印按钮
handlePrintTap() {
let that = this
uni.showLoading({
mask: true,
title: '打印中...'
});
uni.getSystemInfo({
success(res) {
console.log('设备类型',res.osName)
deviceType = res.osName
},fail(err){
console.log('getSystemInfo失败')
}
})
// 初始化蓝牙模块
uni.openBluetoothAdapter({ //111
mode: 'central',
success: (res2) => {
console.log('openBluetoothAdapter成功')
that.jiantingshebei()
},
fail: (res) => {
console.log('openBluetoothAdapter失败')
if (res.errCode == '10001') {
uni.showToast({
duration: 2000,
title: "请打开蓝牙后,再进行连接",
icon: 'none',
mask: true
})
} else {
that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-1')
that.isShowSearch = true
}
setTimeout(res => {
uni.hideLoading();
}, 2000)
}
})
},
/**
* jiantingshebei方法判断缓存中有没有deviceId等数据的时候
* 直接拿到缓存中的deviceId等直接请求 uni.createBLEConnection
* 没有才会调用 uni.onBluetoothDeviceFound 搜索
*/
jiantingshebei() {
let that = this;
console.log('jiantingshebei设备',uni.getStorageSync('deviceId'))
if (uni.getStorageSync('deviceId')) {
// that.huoqufuwu(uni.getStorageSync('deviceId'))
that.lianejieshebei(uni.getStorageSync('deviceId'))
} else {
uni.showToast({
duration: 2000,
title: "蓝牙连接失败,请去商家主页尝试重新连接",
icon: 'none',
mask: true
})
// uni.hideLoading();
// that.isShowSearch = true
// // 监听扫描到新设备事件
// uni.onBluetoothDeviceFound((res4) => { //333
// res4.devices.forEach((device) => {
// if (!device.name && !device.localName) {
// return
// }
// that.devicesList.push(device)
// })
// })
}
},
lianejieshebei(deviceId) {
let that = this;
uni.showLoading({
mask: true,
title: '加载中...'
});
// let timerId = setTimeout(() => {
// uni.closeBLEConnection({
// deviceId: deviceId,
// success(res2) {
// },fail(err1){
// }
// })
// uni.closeBluetoothAdapter({
// success(res) {
// },fail(err2){
// }
// })
// uni.removeStorageSync('deviceId')
// that.handlePrintTap()
// that.isShowSearch = true
// return
// }, 5000);
// 连接设备
uni.createBLEConnection({ //555
deviceId: deviceId, // 搜索到设备的 deviceId
success: () => {
console.log('createBLEConnection成功')
// 连接成功就清除定时器
// clearTimeout(timerId);
// that.isShowSearch = false
that.huoqufuwu(deviceId)
},
fail: (res) => {
uni.showToast({
duration: 2000,
title: "蓝牙连接失败,请查看打印机状态或重新连接",
icon: 'none',
mask: true
})
// console.log('deviceId对吗?',deviceId)
// console.log('createBLEConnection失败',res)
// clearTimeout(timerId);
// // if(res.errno == '1509007'){
// that.huoqufuwu(deviceId)
// // }
// if(res.errno == '1509003'){
// that.lianejieshebei(deviceId)
// }
}
})
},
huoqufuwu(deviceId) {
let that = this;
//获取服务
uni.getBLEDeviceServices({ //666
deviceId: deviceId, // 搜索到设备的 deviceId
success: (res5) => {
console.log('getBLEDeviceServices成功')
that.duxietezhengzhi(deviceId, res5)
},
fail: (res) => {
uni.showToast({
duration: 2000,
title: "蓝牙连接失败,请查看打印机状态或重新连接",
icon: 'none',
mask: true
})
// console.log('getBLEDeviceServices失败')
// that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-4',res)
// uni.closeBLEConnection({
// deviceId: uni.getStorageSync('deviceId'),
// success(res1) {
// }
// })
// uni.removeStorageSync('deviceId')
// that.sousuo()
// that.isShowSearch = true
// setTimeout(res => {
// uni.hideLoading();
// }, 2000)
}
})
},
duxietezhengzhi(deviceId, res5) {
let that = this;
//读写特征值
uni.getBLEDeviceCharacteristics({ //777
deviceId: deviceId, // 搜索到设备的 deviceId
serviceId: res5.services[2].uuid, // 上一步中找到的某个服务
success: (res6) => {
console.log('getBLEDeviceCharacteristics成功',res6)
for (let i = 0; i < res6.characteristics.length; i++) {
let item = res6.characteristics[i]
if (item.properties.write) { // 该特征值可写
that.startNoticeBle(deviceId, res5.services[2].uuid, res6.characteristics[2].uuid)
uni.setStorageSync('deviceId', deviceId);
uni.setStorageSync('serviceId', res5.services[2].uuid);
uni.setStorageSync('characteristicId', item.uuid);
that.xierushuju()
return;
}
}
},
fail: (res) => {
uni.showToast({
duration: 2000,
title: "蓝牙连接失败,请查看打印机状态或重新连接",
icon: 'none',
mask: true
})
// console.log('getBLEDeviceCharacteristics失败')
// that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-5',res)
// uni.closeBLEConnection({
// deviceId: uni.getStorageSync('deviceId'),
// success(res) {
// }
// })
// uni.removeStorageSync('deviceId')
// that.sousuo()
// that.isShowSearch = true
// setTimeout(res => {
// uni.hideLoading();
// }, 2000)
}
})
},
// 开启蓝牙数据监听
startNoticeBle(deviceId, serviceId, characteristicId) {
let that = this
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success(res) {
console.log("监听成功",res)
that.GetDataFromBle();
},
fail: function(err) {
console.log("监听失败了")
}
})
},
// 设备返回的数据接收
GetDataFromBle() {
var that = this;
console.log('哈希之前2222222222222222');
uni.onBLECharacteristicValueChange((res) => {
// 此时可以拿到蓝牙设备返回来的数据是一个ArrayBuffer类型数据,所以需要通过一个方法转换成字符串
console.log('哈希之前111111111111',res);
var bleData = that.ab2hex(res.value)
console.log('哈希了吗?',bleData)
uni.hideLoading()
setTimeout(res=>{
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res) {},
fail(err) {}
})
// that.getIsData("0")
bufferData = []
},1000)
})
},
ab2hex(buffer) {
return Array.from(new Uint8Array(buffer))
.map(byte => ('00' + byte.toString(16)).slice(-2))
.join('');
},
xierushuju() {
let that = this;
//写入数据
console.log("22222222222222",bufferData)
var dataStr = ''
for (let m = 0; m < bufferData.length; m++) {
dataStr += bufferData[m]
}
const maxChunk = deviceType == 'android' ? 20 : 180;
const delay = 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;
uni.writeBLECharacteristicValue({
deviceId: uni.getStorageSync('deviceId'),
serviceId: uni.getStorageSync('serviceId'),
characteristicId: uni.getStorageSync('characteristicId'),
value: buffer,
success(res) {
console.log("66666666666")
},
fail(res) {
console.log("777777777",res)
uni.showToast({
duration: 2000,
title: "打印失败,请查看打印机状态或重新连接",
icon: 'none',
mask: true
})
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res) {
}
})
// if (uni.getStorageSync('deviceId')) {
// // that.xierushuju()
// } else {
// that.jiantingshebei()
// }
// uni.hideLoading();
}
})
},
handleSearchClose() {
uni.closeBluetoothAdapter({
success(res) {
}
})
this.isShowSearch = false
},
getIsData(type){
if(type == 0){
// 删除数组中第一个元素
getApp().globalData.printData.shift();
}
if(getApp().globalData.printData.length>0){
this.onPrint()
}
}
}

613
components/kk-printer/index.vue

@ -1,613 +0,0 @@
<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;display: flex;flex-direction: column;">
<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: [],
//
picWaitTime:0,
//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() {
},
onLoad() {
},
beforeDestroy() {
this.stopSearchBtnTap();
},
methods: {
doNothing() {
return;
},
//
handlePrintTap() {
let that = this
uni.showLoading({
mask: true,
title: '打印中...'
});
uni.getSystemInfo({
success(res) {
console.log('设备类型',res.osName)
that.deviceType = res.osName
},fail(err){
}
})
//
uni.openBluetoothAdapter({ //111
mode: 'central',
success: (res2) => {
that.sousuo()
},
fail: (res) => {
if (res.errCode == '10001') {
uni.showToast({
duration: 2000,
title: "请打开蓝牙后,再进行连接",
icon: 'none',
mask: true
})
} else {
that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-1')
that.isShowSearch = true
}
setTimeout(res => {
uni.hideLoading();
}, 2000)
}
})
},
//
sousuo() {
let that = this;
this.devicesList = []
uni.startBluetoothDevicesDiscovery({ //222
success(res3) {
that.jiantingshebei()
},
fail(err) {
that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-2',err)
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res2) {
},fail(err1){
}
})
uni.closeBluetoothAdapter({
success(res) {
},fail(err2){
}
})
uni.removeStorageSync('deviceId')
that.handlePrintTap()
that.isShowSearch = true
setTimeout(res => {
uni.hideLoading();
}, 2000)
}
})
},
//
stopSearchBtnTap() {
uni.stopBluetoothDevicesDiscovery()
},
/**
* jiantingshebei方法判断缓存中有没有deviceId等数据的时候
* 直接拿到缓存中的deviceId等直接请求 uni.createBLEConnection
* 没有才会调用 uni.onBluetoothDeviceFound 搜索
*/
jiantingshebei() {
let that = this;
if (uni.getStorageSync('deviceId')) {
// that.huoqufuwu(uni.getStorageSync('deviceId'))
that.lianejieshebei(uni.getStorageSync('deviceId'))
} else {
uni.hideLoading();
that.isShowSearch = true
//
uni.onBluetoothDeviceFound((res4) => { //333
res4.devices.forEach((device) => {
if (!device.name && !device.localName) {
return
}
that.devicesList.push(device)
})
})
}
},
lianejieshebei(deviceId) {
let that = this;
uni.showLoading({
mask: true,
title: '加载中...'
});
let timerId = setTimeout(() => {
uni.closeBLEConnection({
deviceId: deviceId,
success(res2) {
},fail(err1){
}
})
uni.closeBluetoothAdapter({
success(res) {
},fail(err2){
}
})
uni.removeStorageSync('deviceId')
that.handlePrintTap()
that.isShowSearch = true
return
}, 5000);
//
uni.createBLEConnection({ //555
deviceId: deviceId, // deviceId
success: () => {
//
clearTimeout(timerId);
that.isShowSearch = false
uni.setStorageSync('deviceId', deviceId);
uni.showToast({
duration: 2000,
title: "蓝牙连接成功",
icon: 'none',
mask: true
})
that.$emit('statusChange')
setTimeout(res=>{
uni.closeBLEConnection({
deviceId:uni.getStorageSync('deviceId')
})
},1000)
// that.huoqufuwu(deviceId)
},
fail: (res) => {
clearTimeout(timerId);
if(res.errno == '1509007'){
that.huoqufuwu(deviceId)
}
if(res.errno == '1509003'){
that.lianejieshebei(deviceId)
}
}
})
},
huoqufuwu(deviceId) {
let that = this;
//
uni.getBLEDeviceServices({ //666
deviceId: deviceId, // deviceId
success: (res5) => {
that.duxietezhengzhi(deviceId, res5)
},
fail: (res) => {
that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-4',res)
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res1) {
}
})
uni.removeStorageSync('deviceId')
that.sousuo()
that.isShowSearch = true
setTimeout(res => {
uni.hideLoading();
}, 2000)
}
})
},
duxietezhengzhi(deviceId, res5) {
let that = this;
//
uni.getBLEDeviceCharacteristics({ //777
deviceId: deviceId, // deviceId
serviceId: res5.services[2].uuid, //
success: (res6) => {
for (let i = 0; i < res6.characteristics.length; i++) {
let item = res6.characteristics[i]
if (item.properties.write && item.properties.notify) { //
// that.startNoticeBle(deviceId, res5.services[2].uuid, item.uuid)
uni.setStorageSync('deviceId', deviceId);
uni.setStorageSync('serviceId', res5.services[2].uuid);
uni.setStorageSync('characteristicId', item.uuid);
// that.xierushuju()
return;
}
}
},
fail: (res) => {
that.tui.toast('连接失败,请重启蓝牙或删除小程序重新进入-5',res)
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res) {
}
})
uni.removeStorageSync('deviceId')
that.sousuo()
that.isShowSearch = true
setTimeout(res => {
uni.hideLoading();
}, 2000)
}
})
},
//
startNoticeBle(deviceId, serviceId, characteristicId) {
let that = this
uni.notifyBLECharacteristicValueChange({
state: true, // notify
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success(res) {
console.log("监听成功")
that.GetDataFromBle();
},
fail: function(err) {
console.log("监听失败了")
}
})
},
//
GetDataFromBle() {
var that = this;
uni.onBLECharacteristicValueChange((res) => {
// ArrayBuffer
that.bleData = that.ab2hex(res.value)
console.log('哈希了吗?',that.bleData)
uni.hideLoading()
setTimeout(res=>{
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res) {},
fail(err) {}
})
},that.picWaitTime)
})
},
ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
},
xierushuju() {
let that = this;
//
that.$emit('onPrint');
console.log("22222222222222",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' ? 180 : 180;
let buffer = gbk.strToGBKByte(dataStr)
if(dataStr.indexOf('EG ') != -1){
that.picWaitTime = buffer.byteLength + 200
}
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;
uni.writeBLECharacteristicValue({
deviceId: uni.getStorageSync('deviceId'),
serviceId: uni.getStorageSync('serviceId'),
characteristicId: uni.getStorageSync('characteristicId'),
value: buffer,
success(res) {
console.log("66666666666")
},
fail(res) {
console.log("777777777",res)
uni.closeBLEConnection({
deviceId: uni.getStorageSync('deviceId'),
success(res) {
}
})
if (uni.getStorageSync('deviceId')) {
// that.xierushuju()
} else {
that.jiantingshebei()
}
uni.hideLoading();
}
})
},
handleSearchClose() {
uni.closeBluetoothAdapter({
success(res) {
}
})
this.isShowSearch = false
}
}
}
</script>
<style lang="scss" scoped>
.kk-printer {
&-btn {
width: 100%;
height: 100%;
}
.kk-shadow {
display: none;
z-index: 999;
&.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: 420rpx;
height: 600rpx;
padding: 24rpx;
box-sizing: border-box;
overflow-y: auto;
border-radius: 20rpx;
background: #ffffff;
display: flex;
justify-content: center;
align-items: center;
.kk-search-device {
width: 100%;
height: 100%;
.kk-filter-wrap {
width: 100%;
height: 160rpx;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
&>slider {
width: 90%;
height: 90rpx;
}
&>input {
padding: 0 20rpx;
box-sizing: border-box;
border-radius: 10rpx;
height: 90rpx;
width: 100%;
border: 1rpx solid #ebebeb;
}
}
.kk-btn-wrap {
width: 100%;
height: 90rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
&>view {
flex: 1 1 auto;
height: 60rpx;
line-height: 60rpx;
border-radius: 16rpx;
text-align: center;
color: #ffffff;
font-size: 26rpx;
&.confirm-btn {
background: #007AFF;
margin-right: 30rpx;
}
&:nth-last-child(1) {
background: #DD524D;
}
}
}
.kk-devices-wrap {
height: calc(100% - 80rpx);
overflow-y: auto;
padding: 10rpx 20rpx;
box-sizing: border-box;
border: 1rpx solid #ebebeb;
box-sizing: border-box;
border-radius: 20rpx;
.empty-wrap {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.empty-icon {
width: 268rpx;
height: 240rpx;
background-size: 100% 100%;
margin-bottom: 26rpx;
}
.empty-text {
width: 100%;
line-height: 50rpx;
font-size: 30rpx;
text-align: center;
color: #999999;
}
}
.kk-devices-item {
width: 100%;
border-bottom: 1rpx solid #ebebeb;
padding: 10rpx 0;
box-sizing: border-box;
z-index: 500;
&:nth-last-child(1) {
border-bottom: none;
}
&>view {
width: 100%;
font-size: 30rpx;
}
}
}
}
}
}
}
}
</style>

BIN
components/kk-printer/utils/.DS_Store

Binary file not shown.

402
components/kk-printer/utils/barcode.js

@ -1,402 +0,0 @@
var CHAR_TILDE = 126;
var CODE_FNC1 = 102;
var SET_STARTA = 103;
var SET_STARTB = 104;
var SET_STARTC = 105;
var SET_SHIFT = 98;
var SET_CODEA = 101;
var SET_CODEB = 100;
var SET_STOP = 106;
var REPLACE_CODES = {
CHAR_TILDE: CODE_FNC1 //~ corresponds to FNC1 in GS1-128 standard
}
var CODESET = {
ANY: 1,
AB: 2,
A: 3,
B: 4,
C: 5
};
function getBytes(str) {
var bytes = [];
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
return bytes;
}
exports.code128 = function (ctx, text, width, height) {
width = parseInt(width);
height = parseInt(height);
var codes = stringToCode128(text);
var g = new Graphics(ctx, width, height);
var barWeight = g.area.width / ((codes.length - 3) * 11 + 35);
var x = g.area.left;
var y = g.area.top;
for (var i = 0; i < codes.length; i++) {
var c = codes[i];
//two bars at a time: 1 black and 1 white
for (var bar = 0; bar < 8; bar += 2) {
var barW = PATTERNS[c][bar] * barWeight;
// var barH = height - y - this.border;
var barH = height - y;
var spcW = PATTERNS[c][bar + 1] * barWeight;
//no need to draw if 0 width
if (barW > 0) {
g.fillFgRect(x, y, barW, barH);
}
x += barW + spcW;
}
}
ctx.draw();
}
function stringToCode128(text) {
var barc = {
currcs: CODESET.C
};
var bytes = getBytes(text);
//decide starting codeset
var index = bytes[0] == CHAR_TILDE ? 1 : 0;
var csa1 = bytes.length > 0 ? codeSetAllowedFor(bytes[index++]) : CODESET.AB;
var csa2 = bytes.length > 0 ? codeSetAllowedFor(bytes[index++]) : CODESET.AB;
barc.currcs = getBestStartSet(csa1, csa2);
barc.currcs = perhapsCodeC(bytes, barc.currcs);
//if no codeset changes this will end up with bytes.length+3
//start, checksum and stop
var codes = new Array();
switch (barc.currcs) {
case CODESET.A:
codes.push(SET_STARTA);
break;
case CODESET.B:
codes.push(SET_STARTB);
break;
default:
codes.push(SET_STARTC);
break;
}
for (var i = 0; i < bytes.length; i++) {
var b1 = bytes[i]; //get the first of a pair
//should we translate/replace
if (b1 in REPLACE_CODES) {
codes.push(REPLACE_CODES[b1]);
i++ //jump to next
b1 = bytes[i];
}
//get the next in the pair if possible
var b2 = bytes.length > (i + 1) ? bytes[i + 1] : -1;
codes = codes.concat(codesForChar(b1, b2, barc.currcs));
//code C takes 2 chars each time
if (barc.currcs == CODESET.C) i++;
}
//calculate checksum according to Code 128 standards
var checksum = codes[0];
for (var weight = 1; weight < codes.length; weight++) {
checksum += (weight * codes[weight]);
}
codes.push(checksum % 103);
codes.push(SET_STOP);
//encoding should now be complete
return codes;
function getBestStartSet(csa1, csa2) {
//tries to figure out the best codeset
//to start with to get the most compact code
var vote = 0;
vote += csa1 == CODESET.A ? 1 : 0;
vote += csa1 == CODESET.B ? -1 : 0;
vote += csa2 == CODESET.A ? 1 : 0;
vote += csa2 == CODESET.B ? -1 : 0;
//tie goes to B due to my own predudices
return vote > 0 ? CODESET.A : CODESET.B;
}
function perhapsCodeC(bytes, codeset) {
for (var i = 0; i < bytes.length; i++) {
var b = bytes[i]
if ((b < 48 || b > 57) && b != CHAR_TILDE)
return codeset;
}
return CODESET.C;
}
//chr1 is current byte
//chr2 is the next byte to process. looks ahead.
function codesForChar(chr1, chr2, currcs) {
var result = [];
var shifter = -1;
if (charCompatible(chr1, currcs)) {
if (currcs == CODESET.C) {
if (chr2 == -1) {
shifter = SET_CODEB;
currcs = CODESET.B;
}
else if ((chr2 != -1) && !charCompatible(chr2, currcs)) {
//need to check ahead as well
if (charCompatible(chr2, CODESET.A)) {
shifter = SET_CODEA;
currcs = CODESET.A;
}
else {
shifter = SET_CODEB;
currcs = CODESET.B;
}
}
}
}
else {
//if there is a next char AND that next char is also not compatible
if ((chr2 != -1) && !charCompatible(chr2, currcs)) {
//need to switch code sets
switch (currcs) {
case CODESET.A:
shifter = SET_CODEB;
currcs = CODESET.B;
break;
case CODESET.B:
shifter = SET_CODEA;
currcs = CODESET.A;
break;
}
}
else {
//no need to shift code sets, a temporary SHIFT will suffice
shifter = SET_SHIFT;
}
}
//ok some type of shift is nessecary
if (shifter != -1) {
result.push(shifter);
result.push(codeValue(chr2));
}
else {
if (currcs == CODESET.C) {
//include next as well
result.push(codeValue(chr1, chr2));
}
else {
result.push(codeValue(chr1));
}
}
barc.currcs = currcs;
return result;
}
}
//reduce the ascii code to fit into the Code128 char table
function codeValue(chr1, chr2) {
if (typeof chr2 == "undefined") {
return chr1 >= 32 ? chr1 - 32 : chr1 + 64;
}
else {
return parseInt(String.fromCharCode(chr1) + String.fromCharCode(chr2));
}
}
function charCompatible(chr, codeset) {
var csa = codeSetAllowedFor(chr);
if (csa == CODESET.ANY) return true;
//if we need to change from current
if (csa == CODESET.AB) return true;
if (csa == CODESET.A && codeset == CODESET.A) return true;
if (csa == CODESET.B && codeset == CODESET.B) return true;
return false;
}
function codeSetAllowedFor(chr) {
if (chr >= 48 && chr <= 57) {
//0-9
return CODESET.ANY;
}
else if (chr >= 32 && chr <= 95) {
//0-9 A-Z
return CODESET.AB;
}
else {
//if non printable
return chr < 32 ? CODESET.A : CODESET.B;
}
}
var Graphics = function(ctx, width, height) {
this.width = width;
this.height = height;
this.quiet = Math.round(this.width / 40);
this.border_size = 0;
this.padding_width = 0;
this.area = {
width : width - this.padding_width * 2 - this.quiet * 2,
height: height - this.border_size * 2,
top : this.border_size - 4,
left : this.padding_width + this.quiet
};
this.ctx = ctx;
this.fg = "#000000";
this.bg = "#ffffff";
// fill background
this.fillBgRect(0,0, width, height);
// fill center to create border
this.fillBgRect(0, this.border_size, width, height - this.border_size * 2);
}
//use native color
Graphics.prototype._fillRect = function(x, y, width, height, color) {
this.ctx.setFillStyle(color)
this.ctx.fillRect(x, y, width, height)
}
Graphics.prototype.fillFgRect = function(x,y, width, height) {
this._fillRect(x, y, width, height, this.fg);
}
Graphics.prototype.fillBgRect = function(x,y, width, height) {
this._fillRect(x, y, width, height, this.bg);
}
var PATTERNS = [
[2, 1, 2, 2, 2, 2, 0, 0], // 0
[2, 2, 2, 1, 2, 2, 0, 0], // 1
[2, 2, 2, 2, 2, 1, 0, 0], // 2
[1, 2, 1, 2, 2, 3, 0, 0], // 3
[1, 2, 1, 3, 2, 2, 0, 0], // 4
[1, 3, 1, 2, 2, 2, 0, 0], // 5
[1, 2, 2, 2, 1, 3, 0, 0], // 6
[1, 2, 2, 3, 1, 2, 0, 0], // 7
[1, 3, 2, 2, 1, 2, 0, 0], // 8
[2, 2, 1, 2, 1, 3, 0, 0], // 9
[2, 2, 1, 3, 1, 2, 0, 0], // 10
[2, 3, 1, 2, 1, 2, 0, 0], // 11
[1, 1, 2, 2, 3, 2, 0, 0], // 12
[1, 2, 2, 1, 3, 2, 0, 0], // 13
[1, 2, 2, 2, 3, 1, 0, 0], // 14
[1, 1, 3, 2, 2, 2, 0, 0], // 15
[1, 2, 3, 1, 2, 2, 0, 0], // 16
[1, 2, 3, 2, 2, 1, 0, 0], // 17
[2, 2, 3, 2, 1, 1, 0, 0], // 18
[2, 2, 1, 1, 3, 2, 0, 0], // 19
[2, 2, 1, 2, 3, 1, 0, 0], // 20
[2, 1, 3, 2, 1, 2, 0, 0], // 21
[2, 2, 3, 1, 1, 2, 0, 0], // 22
[3, 1, 2, 1, 3, 1, 0, 0], // 23
[3, 1, 1, 2, 2, 2, 0, 0], // 24
[3, 2, 1, 1, 2, 2, 0, 0], // 25
[3, 2, 1, 2, 2, 1, 0, 0], // 26
[3, 1, 2, 2, 1, 2, 0, 0], // 27
[3, 2, 2, 1, 1, 2, 0, 0], // 28
[3, 2, 2, 2, 1, 1, 0, 0], // 29
[2, 1, 2, 1, 2, 3, 0, 0], // 30
[2, 1, 2, 3, 2, 1, 0, 0], // 31
[2, 3, 2, 1, 2, 1, 0, 0], // 32
[1, 1, 1, 3, 2, 3, 0, 0], // 33
[1, 3, 1, 1, 2, 3, 0, 0], // 34
[1, 3, 1, 3, 2, 1, 0, 0], // 35
[1, 1, 2, 3, 1, 3, 0, 0], // 36
[1, 3, 2, 1, 1, 3, 0, 0], // 37
[1, 3, 2, 3, 1, 1, 0, 0], // 38
[2, 1, 1, 3, 1, 3, 0, 0], // 39
[2, 3, 1, 1, 1, 3, 0, 0], // 40
[2, 3, 1, 3, 1, 1, 0, 0], // 41
[1, 1, 2, 1, 3, 3, 0, 0], // 42
[1, 1, 2, 3, 3, 1, 0, 0], // 43
[1, 3, 2, 1, 3, 1, 0, 0], // 44
[1, 1, 3, 1, 2, 3, 0, 0], // 45
[1, 1, 3, 3, 2, 1, 0, 0], // 46
[1, 3, 3, 1, 2, 1, 0, 0], // 47
[3, 1, 3, 1, 2, 1, 0, 0], // 48
[2, 1, 1, 3, 3, 1, 0, 0], // 49
[2, 3, 1, 1, 3, 1, 0, 0], // 50
[2, 1, 3, 1, 1, 3, 0, 0], // 51
[2, 1, 3, 3, 1, 1, 0, 0], // 52
[2, 1, 3, 1, 3, 1, 0, 0], // 53
[3, 1, 1, 1, 2, 3, 0, 0], // 54
[3, 1, 1, 3, 2, 1, 0, 0], // 55
[3, 3, 1, 1, 2, 1, 0, 0], // 56
[3, 1, 2, 1, 1, 3, 0, 0], // 57
[3, 1, 2, 3, 1, 1, 0, 0], // 58
[3, 3, 2, 1, 1, 1, 0, 0], // 59
[3, 1, 4, 1, 1, 1, 0, 0], // 60
[2, 2, 1, 4, 1, 1, 0, 0], // 61
[4, 3, 1, 1, 1, 1, 0, 0], // 62
[1, 1, 1, 2, 2, 4, 0, 0], // 63
[1, 1, 1, 4, 2, 2, 0, 0], // 64
[1, 2, 1, 1, 2, 4, 0, 0], // 65
[1, 2, 1, 4, 2, 1, 0, 0], // 66
[1, 4, 1, 1, 2, 2, 0, 0], // 67
[1, 4, 1, 2, 2, 1, 0, 0], // 68
[1, 1, 2, 2, 1, 4, 0, 0], // 69
[1, 1, 2, 4, 1, 2, 0, 0], // 70
[1, 2, 2, 1, 1, 4, 0, 0], // 71
[1, 2, 2, 4, 1, 1, 0, 0], // 72
[1, 4, 2, 1, 1, 2, 0, 0], // 73
[1, 4, 2, 2, 1, 1, 0, 0], // 74
[2, 4, 1, 2, 1, 1, 0, 0], // 75
[2, 2, 1, 1, 1, 4, 0, 0], // 76
[4, 1, 3, 1, 1, 1, 0, 0], // 77
[2, 4, 1, 1, 1, 2, 0, 0], // 78
[1, 3, 4, 1, 1, 1, 0, 0], // 79
[1, 1, 1, 2, 4, 2, 0, 0], // 80
[1, 2, 1, 1, 4, 2, 0, 0], // 81
[1, 2, 1, 2, 4, 1, 0, 0], // 82
[1, 1, 4, 2, 1, 2, 0, 0], // 83
[1, 2, 4, 1, 1, 2, 0, 0], // 84
[1, 2, 4, 2, 1, 1, 0, 0], // 85
[4, 1, 1, 2, 1, 2, 0, 0], // 86
[4, 2, 1, 1, 1, 2, 0, 0], // 87
[4, 2, 1, 2, 1, 1, 0, 0], // 88
[2, 1, 2, 1, 4, 1, 0, 0], // 89
[2, 1, 4, 1, 2, 1, 0, 0], // 90
[4, 1, 2, 1, 2, 1, 0, 0], // 91
[1, 1, 1, 1, 4, 3, 0, 0], // 92
[1, 1, 1, 3, 4, 1, 0, 0], // 93
[1, 3, 1, 1, 4, 1, 0, 0], // 94
[1, 1, 4, 1, 1, 3, 0, 0], // 95
[1, 1, 4, 3, 1, 1, 0, 0], // 96
[4, 1, 1, 1, 1, 3, 0, 0], // 97
[4, 1, 1, 3, 1, 1, 0, 0], // 98
[1, 1, 3, 1, 4, 1, 0, 0], // 99
[1, 1, 4, 1, 3, 1, 0, 0], // 100
[3, 1, 1, 1, 4, 1, 0, 0], // 101
[4, 1, 1, 1, 3, 1, 0, 0], // 102
[2, 1, 1, 4, 1, 2, 0, 0], // 103
[2, 1, 1, 2, 1, 4, 0, 0], // 104
[2, 1, 1, 2, 3, 2, 0, 0], // 105
[2, 3, 3, 1, 1, 1, 2, 0] // 106
]

695
components/kk-printer/utils/bluetoolth.js

@ -1,695 +0,0 @@
/**
* @export
* @param {string} name 微信api的名称 uniAsyncPromise("getSystemInfo",options)
* @param {object} options 除了success fail 的其他参数
* @returns
*/
export function uniAsyncPromise(name, options) {
return new Promise((resolve, reject) => {
uni[name]({
...(options || {}),
// ...options,
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
}
//微信小程序向蓝牙打印机发送数据进行打印的坑:
//小程序api向蓝牙打印机发送数据打印,发送的任何内容都应该要转成二进制数据,而且蓝牙打印的文本编码是GBK的,发送中文需转成GBK编码再转成二进制数据发送
//发送打印机指令也要转成二进制数据发送
//蓝牙打印机一次接收的二级制数据有限制,不同的系统不同的蓝牙设备限制可能不同,微信建议一次20个字节,需做递归分包发送
//发送完要打印的内容后,一定要发送一个打印的指令才能顺利打印 (有些指令就不需要)
//一、初始化蓝牙、开始检索蓝牙设备
// { allowDuplicatesKey: true, interval: 500}
export function openBlue() {
return uniAsyncPromise('openBluetoothAdapter')
}
//搜索蓝牙设备
export function startBluetoothDevicesDiscovery(option) {
uniAsyncPromise('startBluetoothDevicesDiscovery', option).then((res) => {
});
}
export function getConnectedBluetoothDevices(option) {
return uniAsyncPromise('getConnectedBluetoothDevices', option)
}
//二、
/**
*
*
* @export
* @param {function} getDevices uni.getBluetoothDevices的监听回调函数
*/
export function onfindBlueDevices(getDevices) {
//监听寻找到新设备的事件
uni.onBluetoothDeviceFound((devices)=>{
//获取在蓝牙模块生效期间所有已发现的蓝牙设备
uniAsyncPromise('getBluetoothDevices').then((res) => {
getDevices && getDevices(res.devices);
});
});
}
/**
* @export
* @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描
*/
export function stopBlueDevicesDiscovery() {
//监听寻找到新设备的事件
return uniAsyncPromise('stopBluetoothDevicesDiscovery').then((res) => {
});
}
//三、连接蓝牙设备
/**
* @export
* @param {function} createBLEConnection
* @param {number} deviceId 蓝牙设备id
*/
export function createBLEConnection(deviceId, sucess, fail) {
//连接蓝牙设备
uniAsyncPromise("createBLEConnection", {
deviceId
})
.then(res => {
//连接成功可选择停止搜索蓝牙
//stopBlueDevicesDiscovery();
sucess && sucess({
res: res,
});
})
.catch(res => {
fail && fail({
res: res,
});
})
}
//关闭蓝牙连接
export function closeBLEConnection(deviceId) {
uniAsyncPromise("closeBLEConnection", {
deviceId
})
.then(res => {
})
.catch(res => {
})
}
//四、连接成功后, 获取蓝牙设备的service服务
// uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
export function getBLEDeviceServices(deviceId, success, fail) {
//加延迟避免取不到service
setTimeout(()=>{
uniAsyncPromise("getBLEDeviceServices", {
deviceId: uni.getStorageSync('deviceId')?uni.getStorageSync('deviceId'):deviceId
})
.then(res => {
success && success({
serviceId: res.services,
});
})
.catch((res) => {
//getBLEDeviceServices(deviceId, success, fail);
fail && fail({
res: res,
});
});
},1000)
}
//五、获取的service服务可能有多个,递归获取特征值(最后要用的是能读,能写,能监听的那个值的uuid作为特征值id)
/**
*
*
* @export
* @param {number} deviceId 蓝牙设备id
* @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services
* @param {function} success 成功取得有用特征值uuid的回调函数
*/
export function getDeviceCharacteristics(deviceId, services, success, fail) {
//services = services.slice(0);
if (services.length) {
const serviceId = services.shift().uuid;
uniAsyncPromise('getBLEDeviceCharacteristics', {
deviceId,
serviceId,
}).then((res) => {
var readId;
var writeId;
for (var i = 0; i < res.characteristics.length; i++) {
if ((res.characteristics[i].properties.notify || res.characteristics[i].properties.indicate) && res.characteristics[i].properties.write) {
readId = res.characteristics[i].uuid;
writeId = res.characteristics[i].uuid;
/* 获取蓝牙特征值uuid */
success &&
success({
serviceId,
writeId: writeId,
readId: readId,
});
finished = true;
break;
}
}
})
.catch((res) => {
uni.showToast({
title: res.message,
icon: 'error'
})
getDeviceCharacteristics(deviceId, services, success, fail);
});
} else {
fail && fail();
}
}
//六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
/**
* @export
* @param {object} options
* {
deviceId,//蓝牙设备id
serviceId,//服务id
characteristicId,//可用特征值uuid
}
* @param {function} onChange 监听蓝牙设备传递数据回调函数
*/
export function onGetBLECharacteristicValueChange(options, onChange = function() {}) {
uniAsyncPromise('notifyBLECharacteristicValueChange', {
state: true,
...options,
}).then((res) => {
uni.onBLECharacteristicValueChange(onChange);
});
}
//七、发送数据(递归分包发送)
/**
* @export
* @param {object} options
* {
deviceId,
serviceId,
characteristicId,
value [ArrayBuffer],
lasterSuccess,
onceLength
}
*/
export function sendDataToDevice(options) {
let byteLength = options.value.byteLength;
//这里默认一次20个字节发送
const speed = options.onceLength; //20;
if (byteLength > 0) {
uniAsyncPromise('writeBLECharacteristicValue', {
...options,
value: options.value.slice(0, byteLength > speed ? speed : byteLength),
})
.then((res) => {
if (byteLength > speed) {
sendDataToDevice({
...options,
value: options.value.slice(speed, byteLength),
});
} else {
options.lasterSuccess && options.lasterSuccess();
}
})
.catch((res) => {
uni.showToast({
title: res,
icon: 'none'
})
});
}else{
uni.showToast({
title: '没数据',
icon: 'none'
})
}
}
export function charToArrayBuffer(str) {
var out = new ArrayBuffer(str.length);
var uint8 = new Uint8Array(out);
var strs = str.split('');
for (var i = 0; i < strs.length; i++) {
uint8[i] = strs[i].charCodeAt();
}
return uint8;
}
export function charToArray(str) {
var arr = [];
var strs = str.split('');
for (var i = 0; i < strs.length; i++) {
arr[i] = strs[i].charCodeAt();
}
return arr;
}
//打印二维码
/**
* @export
* @param {object} options
* {
deviceId,
serviceId,
characteristicId,
value,//ArrayBuffer:二维码的数据
}
*/
export function printQR(options) {
//打印二维码的十进制指令data:
let data = [29, 107, 97, 7, 4, options.value.byteLength, 0];
sendDataToDevice({
...options,
value: new Uint8Array(data).buffer,
lasterSuccess: () => {
//指令发送成功后,发送二维码的数据
sendDataToDevice(options);
},
});
}
function grayPixle(pix) {
return pix[0] * 0.299 + pix[1] * 0.587 + pix[2] * 0.114;
}
export function overwriteImageData(data) {
let sendWidth = data.width,
sendHeight = data.height;
const threshold = data.threshold || 180;
let sendImageData = new ArrayBuffer((sendWidth * sendHeight) / 8);
sendImageData = new Uint8Array(sendImageData);
let pix = data.imageData;
const part = [];
let index = 0;
for (let i = 0; i < pix.length; i += 32) {
//横向每8个像素点组成一个字节(8位二进制数)。
for (let k = 0; k < 8; k++) {
const grayPixle1 = grayPixle(pix.slice(i + k * 4, i + k * 4 + (4 - 1)));
//阈值调整
if (grayPixle1 > threshold) {
//灰度值大于threshold位 白色 为第k位0不打印
part[k] = 0;
} else {
part[k] = 1;
}
}
let temp = 0;
for (let a = 0; a < part.length; a++) {
temp += part[a] * Math.pow(2, part.length - 1 - a);
}
//开始不明白以下算法什么意思,了解了字节才知道,一个字节是8位的二进制数,part这个数组存的0和1就是二进制的0和1,传输到打印的位图数据的一个字节是0-255之间的十进制数,以下是用权相加法转十进制数,理解了这个就用上面的for循环替代了
// const temp =
// part[0] * 128 +
// part[1] * 64 +
// part[2] * 32 +
// part[3] * 16 +
// part[4] * 8 +
// part[5] * 4 +
// part[6] * 2 +
// part[7] * 1;
sendImageData[index++] = temp;
}
return {
array: Array.from(sendImageData),
width: sendWidth / 8,
height: sendHeight,
};
}
/**
* printImage
* @param {object} opt
* {
deviceId,//蓝牙设备id
serviceId,//服务id
characteristicId,//可用特征值uuid
lasterSuccess , //最后完成的回调
}
*/
export function printImage(opt = {}, imageInfo = {}) {
let arr = imageInfo.array,
width = imageInfo.width;
const writeArray = [];
const xl = width % 256;
const xh = width / 256;
//分行发送图片数据,用的十进制指令
const command = [29, 118, 48, 0, xl, xh, 1, 0]; //1D 76 30 00 w h
const enter = [13, 10];
for (let i = 0; i < arr.length / width; i++) {
const subArr = arr.slice(i * width, i * width + width);
const tempArr = command.concat(subArr);
writeArray.push(new Uint8Array(tempArr));
}
writeArray.push(new Uint8Array(enter));
const print = (options, writeArray) => {
if (writeArray.length) {
sendDataToDevice({
...options,
value: writeArray.shift().buffer,
lasterSuccess: () => {
if (writeArray.length) {
print(options, writeArray);
} else {
options.lasterSuccess && options.lasterSuccess();
}
},
});
}
};
print(opt, writeArray);
}
/* 16hex insert 0 */
function Hex2Str(num) {
if (num.toString(16).length < 2) return "0" + num.toString(16);
else
return num.toString(16);
}
/*****CPCL指令接口****/
/**
* 配置项如下
*
* width: 标签纸的宽度单位像素點
* height: 标签纸的高度单位像素點
* 8像素=1mm
* printNum: 打印张数默认为1
* rotation页面整体旋转 1-90 2-180 3-270 其他-不旋转
* back: 页面回退 back单位像素 退纸1mm给back 8
*/
export function CreatCPCLPage(width, height, printNum, rotation, back, offset = 0) {
var strCmd = '! ' + offset + ' 200 200 ' + height + ' ' + printNum + '\n';
strCmd += "PAGE-WIDTH " + width + '\n';
strCmd += "BF "+ back + "\n";
if (rotation == 1)
strCmd += "ZPROTATE90\n";
else if (rotation == 2)
strCmd += "ZPROTATE180\n";
else if (rotation == 3)
strCmd += "ZPROTATE270\n";
else
strCmd += "ZPROTATE0\n";
return strCmd;
}
/**
* 打印文字
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* fontName,fontSize: 字体取值 參考文檔
* rotation: 旋转 1-90 2-180 3-270 其他-不旋转
* content: 文字内容
*/
export function addCPCLText(x, y, fontName, fontSize, rotation, content) {
// alert(content);
var strCmd = '';
if (rotation == 1) {
strCmd += 'T90 ';
}
if (rotation == 2) {
strCmd += 'T180 ';
}
if (rotation == 3) {
strCmd += 'T270 ';
} else {
strCmd += 'T ';
}
strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
return strCmd;
};
/**
* 打印一维码
*
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* codeType: 条码类型取值为128UPCAUPCA2UPCA5UPCEUPCE2UPC5EAN13EAN13+2EAN13+5
* EAN8EAN8+2EAN8+53939CF39F39C93CODABARCODABAR16ITFI2OF5
* h: 条码高度单位dot
* rotation: 顺时针旋转角度取值如下
* - 0 不旋转
* - 1 顺时针旋转90度
*
* narrow: 窄条码比例因子(dot) 取值 參考文檔
* wide: 宽条码比例因子(dot) 取值 參考文檔
* content: 文字内容
*
*/
export function addCPCLBarCode(x, y, codeType, h, rotation, narrow, wide, content) {
var strCmd = '';
if (rotation == 0)
strCmd += 'B ';
else
strCmd += 'VB ';
strCmd += codeType + ' ' + narrow + ' ' + wide + ' ' + h + ' ' + x + ' ' + y + ' ' + content + '\n'
return strCmd;
};
/**
* 打印二维码
*
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* level: 错误纠正能力等级取值为L(7%)M(15%)Q(25%)H(30%)
* ver: 1-10 版本根据内容调整以获取合适容量
* scale: 1-10 放大倍数
* content: 文字内容
*
*/
export function addCPCLQRCode(x, y, level, ver, scale, content) {
var strCmd = 'B QR ' + x + ' ' + y + ' M ' + ver + ' U ' + scale + '\n' + level + 'A,' + content + '\n';
strCmd += 'ENDQR\n';
return strCmd;
};
/**
* 放大指令
* scaleX: 横向放大倍数 123等整数
* scaleY: 纵向放大倍数 123等整数
*/
export function addCPCLSETMAG(scaleX, scaleY) {
var strCmd = 'SETMAG ' + scaleX + ' ' + scaleY + '\n';
return strCmd;
};
/**
* 对齐指令 0-左对齐 1-右对齐 2-居中
*/
export function addCPCLLocation(set) {
var strCmd = '';
if (set == 1) {
strCmd += 'RIGHT\n';
} else if (set == 2) {
strCmd += 'CENTER\n';
} else {
strCmd += 'LEFT\n';
}
return strCmd;
};
/**
* 反白线 x0,y0,x1,y1,width
*/
export function addCPCLInverseLine(x0, y0, x1, y1, width) {
var strCmd = 'IL ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
return strCmd;
};
/**
* 画线 x0,y0,x1,y1,width
*/
export function addCPCLLine(x0, y0, x1, y1, width) {
var strCmd = 'L ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
return strCmd;
};
/**
* 画框 x0,y0,x1,y1,width
*/
export function addCPCLBox(x0, y0, x1, y1, width) {
var strCmd = 'BOX ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
return strCmd;
};
/**
* 字体加粗
*/
export function addCPCLSETBOLD(bold) {
var strCmd = 'SETBOLD ' + bold + '\n';
return strCmd;
};
/**
* 字体下划线
*/
export function addCPCLUNDERLINE(c) {
var strCmd = 'UNDERLINE ';
if (c) strCmd += 'ON\n';
else if (c) strCmd += 'OFF\n';
return strCmd;
};
/**
* 水印打印灰度等级 0-255
*/
export function addCPCLBACKGROUND(level) {
var strCmd = 'BACKGROUND ';
if (level > 255 || level < 0) level = 255;
strCmd += level + '\n';
return strCmd;
};
/**
* 打印水印文字
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* fontName,fontSize: 字体取值 參考文檔
* rotation: 旋转 1-90 2-180 3-270 其他-不旋转
* content: 文字内容
*/
export function addCPCLBKVText(x, y, fontName, fontSize, rotation, content) {
var strCmd = '';
if (rotation == 1) {
strCmd += 'BKT90 ';
}
if (rotation == 2) {
strCmd += 'BKT180 ';
}
if (rotation == 3) {
strCmd += 'BKT270 ';
} else {
strCmd += 'BKT ';
}
strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
return strCmd;
};
/**
* 标签缝隙定位指令
*/
export function addCPCLGAP() {
var strCmd = 'GAP-SENSE\nFORM\n';
return strCmd;
};
/**
* 标签右黑标检测指令
*/
export function addCPCLSENSE() {
var strCmd = 'BAR-SENSE\nFORM\n';
return strCmd;
};
/**
* 标签左黑标检测指令
*/
export function addCPCLSENSELEFT() {
var strCmd = 'BAR-SENSE LEFT\nFORM\n';
return strCmd;
};
/**
* 打印指令
*/
export function addCPCLPrint() {
var strCmd = 'PRINT\n';
return strCmd;
};
/**
* 图片打印指令
* x: 文字方块左上角X座标单位dot
* y: 文字方块左上角Y座标单位dot
* data{
threshold,//0/1提取的灰度级
width,//图像宽度
height,//图像高度
imageData , //图像数据
}
*/
export function addCPCLImageCmd(x, y, data) {
var strImgCmd = '';
const threshold = data.threshold || 180; // 默认阈值设为128
let myBitmapWidth = data.width,
myBitmapHeight = data.height;
let len = Math.ceil(myBitmapWidth / 8); // 确保宽度是对齐到8的倍数
// 使用 Uint8Array 而不是 Uint16Array
let sendImageData = new Uint8Array(len * myBitmapHeight);
let pix = data.imageData;
for (let i = 0; i < myBitmapHeight; i++) {
for (let j = 0; j < myBitmapWidth; j++) {
const avg = (pix[i * myBitmapWidth * 4 + j * 4] +
pix[i * myBitmapWidth * 4 + j * 4 + 1] +
pix[i * myBitmapWidth * 4 + j * 4 + 2]) / 3;
if (avg < threshold) {
sendImageData[i * len + Math.floor(j / 8)] |= (0x80 >> (j % 8));
}
}
}
// CPCL指令图片数据
strImgCmd += 'EG ' + len + ' ' + myBitmapHeight + ' ' + x + ' ' + y + ' ';
for (let i = 0; i < sendImageData.length; i++) {
strImgCmd += ('0' + sendImageData[i].toString(16)).slice(-2).toUpperCase(); // 确保两位十六进制数
}
strImgCmd += '\n';
return strImgCmd;
}
/**
* toast显示捕获的蓝牙异常
*/
export function catchToast(err) {
const errMsg = {
10000: '未初始化蓝牙模块',
10001: '蓝牙未打开',
10002: '没有找到指定设备',
10003: '连接失败',
10004: '没有找到指定服务',
10005: '没有找到指定特征值',
10006: '当前连接已断开',
10007: '当前特征值不支持此操作',
10008: '系统上报异常',
10009: '系统版本低于 4.3 不支持BLE'
};
let coode = err.errCode ? err.errCode.toString() : '';
let msg = errMsg[coode];
plus.nativeUI.toast(msg || coode, {
align: 'center',
verticalAlign: 'center'
});
}

23
components/kk-printer/utils/index.js

@ -1,23 +0,0 @@
var barcode = require('./barcode');
var qrcode = require('./qrcode');
function convert_length(length) {
return Math.round(wx.getSystemInfoSync().windowWidth * length / 750);
}
function barc(id, code, width, height) {
barcode.code128(wx.createCanvasContext(id), code, convert_length(width), convert_length(height))
}
function qrc(id, code, width, height) {
qrcode.api.draw(code, {
ctx: wx.createCanvasContext(id),
width: convert_length(width),
height: convert_length(height)
})
}
module.exports = {
barcode: barc,
qrcode: qrc
}

309
components/kk-printer/utils/printUtil-GBK.js

File diff suppressed because one or more lines are too long

778
components/kk-printer/utils/qrcode.js

@ -1,778 +0,0 @@
var QR = (function () {
// alignment pattern
var adelta = [
0, 11, 15, 19, 23, 27, 31, // force 1 pat
16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
];
// version block
var vpat = [
0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
0x541, 0xc69
];
// final format bits with mask: level << 3 | mask
var fmtword = [
0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
];
// 4 per version: number of blocks 1,2; data width; ecc width
var eccblocks = [
1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
];
// Galois field log table
var glog = [
0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
];
// Galios field exponent table
var gexp = [
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
];
// Working buffers:
// data input and ecc append, image working buffer, fixed part of image, run lengths for badness
var strinbuf=[], eccbuf=[], qrframe=[], framask=[], rlens=[];
// Control values - width is based on version, last 4 are from table.
var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
var ecclevel = 2;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function setmask(x, y)
{
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
// y*y = 1+3+5...
bt = y;
bt *= y;
bt += y;
bt >>= 1;
bt += x;
framask[bt] = 1;
}
// enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
function putalign(x, y)
{
var j;
qrframe[x + width * y] = 1;
for (j = -2; j < 2; j++) {
qrframe[(x + j) + width * (y - 2)] = 1;
qrframe[(x - 2) + width * (y + j + 1)] = 1;
qrframe[(x + 2) + width * (y + j)] = 1;
qrframe[(x + j + 1) + width * (y + 2)] = 1;
}
for (j = 0; j < 2; j++) {
setmask(x - 1, y + j);
setmask(x + 1, y - j);
setmask(x - j, y - 1);
setmask(x + j, y + 1);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function modnn(x)
{
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
var genpoly = [];
// Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
function appendrs(data, dlen, ecbuf, eclen)
{
var i, j, fb;
for (i = 0; i < eclen; i++)
strinbuf[ecbuf + i] = 0;
for (i = 0; i < dlen; i++) {
fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
if (fb != 255) /* fb term is non-zero */
for (j = 1; j < eclen; j++)
strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
else
for( j = ecbuf ; j < ecbuf + eclen; j++ )
strinbuf[j] = strinbuf[j + 1];
strinbuf[ ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask - since symmetrical use half.
function ismasked(x, y)
{
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
bt = y;
bt += y * y;
bt >>= 1;
bt += x;
return framask[bt];
}
//========================================================================
// Apply the selected mask out of the 8.
function applymask(m)
{
var x, y, r3x, r3y;
switch (m) {
case 0:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!((x + y) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 1:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!(y & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 2:
for (y = 0; y < width; y++)
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 3:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = r3y, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 4:
for (y = 0; y < width; y++)
for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) {
if (r3x == 3) {
r3x = 0;
r3y = !r3y;
}
if (!r3y && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 5:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 6:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 7:
for (r3y = 0, y = 0; y < width; y++, r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++, r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
}
return;
}
// Badness coefficients.
var N1 = 3, N2 = 3, N3 = 40, N4 = 10;
// Using the table of the length of each run, calculate the amount of bad image
// - long runs or those that look like finders; called twice, once each for X and Y
function badruns(length)
{
var i;
var runsbad = 0;
for (i = 0; i <= length; i++)
if (rlens[i] >= 5)
runsbad += N1 + rlens[i] - 5;
// BwBBBwB as in finder
for (i = 3; i < length - 1; i += 2)
if (rlens[i - 2] == rlens[i + 2]
&& rlens[i + 2] == rlens[i - 1]
&& rlens[i - 1] == rlens[i + 1]
&& rlens[i - 1] * 3 == rlens[i]
// white around the black pattern? Not part of spec
&& (rlens[i - 3] == 0 // beginning
|| i + 3 > length // end
|| rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
)
runsbad += N3;
return runsbad;
}
// Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
function badcheck()
{
var x, y, h, b, b1;
var thisbad = 0;
var bw = 0;
// blocks of same color.
for (y = 0; y < width - 1; y++)
for (x = 0; x < width - 1; x++)
if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
&& qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
|| !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
|| qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
thisbad += N2;
// X runs
for (y = 0; y < width; y++) {
rlens[0] = 0;
for (h = b = x = 0; x < width; x++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
bw += b ? 1 : -1;
}
thisbad += badruns(h);
}
// black/white imbalance
if (bw < 0)
bw = -bw;
var big = bw;
var count = 0;
big += big << 2;
big <<= 1;
while (big > width * width)
big -= width * width, count++;
thisbad += count * N4;
// Y runs
for (x = 0; x < width; x++) {
rlens[0] = 0;
for (h = b = y = 0; y < width; y++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
}
thisbad += badruns(h);
}
return thisbad;
}
function genframe(instring)
{
var x, y, k, t, v, i, j, m;
// find the smallest version that fits the string
t = instring.length;
version = 0;
do {
version++;
k = (ecclevel - 1) * 4 + (version - 1) * 16;
neccblk1 = eccblocks[k++];
neccblk2 = eccblocks[k++];
datablkw = eccblocks[k++];
eccblkwid = eccblocks[k];
k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
if (t <= k)
break;
} while (version < 40);
// FIXME - insure that it fits insted of being truncated
width = 17 + 4 * version;
// allocate, clear and setup data structures
v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for( t = 0; t < v; t++ )
eccbuf[t] = 0;
strinbuf = instring.slice(0);
for( t = 0; t < width * width; t++ )
qrframe[t] = 0;
for( t = 0 ; t < (width * (width + 1) + 1) / 2; t++)
framask[t] = 0;
// insert finders - black to frame, white to mask
for (t = 0; t < 3; t++) {
k = 0;
y = 0;
if (t == 1)
k = (width - 7);
if (t == 2)
y = (width - 7);
qrframe[(y + 3) + width * (k + 3)] = 1;
for (x = 0; x < 6; x++) {
qrframe[(y + x) + width * k] = 1;
qrframe[y + width * (k + x + 1)] = 1;
qrframe[(y + 6) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 6)] = 1;
}
for (x = 1; x < 5; x++) {
setmask(y + x, k + 1);
setmask(y + 1, k + x + 1);
setmask(y + 5, k + x);
setmask(y + x + 1, k + 5);
}
for (x = 2; x < 4; x++) {
qrframe[(y + x) + width * (k + 2)] = 1;
qrframe[(y + 2) + width * (k + x + 1)] = 1;
qrframe[(y + 4) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 4)] = 1;
}
}
// alignment blocks
if (version > 1) {
t = adelta[version];
y = width - 7;
for (;;) {
x = width - 7;
while (x > t - 3) {
putalign(x, y);
if (x < t)
break;
x -= t;
}
if (y <= t + 9)
break;
y -= t;
putalign(6, y);
putalign(y, 6);
}
}
// single black
qrframe[8 + width * (width - 8)] = 1;
// timing gap - mask only
for (y = 0; y < 7; y++) {
setmask(7, y);
setmask(width - 8, y);
setmask(7, y + width - 7);
}
for (x = 0; x < 8; x++) {
setmask(x, 7);
setmask(x + width - 8, 7);
setmask(x, width - 8);
}
// reserve mask-format area
for (x = 0; x < 9; x++)
setmask(x, 8);
for (x = 0; x < 8; x++) {
setmask(x + width - 8, 8);
setmask(8, x);
}
for (y = 0; y < 7; y++)
setmask(8, y + width - 7);
// timing row/col
for (x = 0; x < width - 14; x++)
if (x & 1) {
setmask(8 + x, 6);
setmask(6, 8 + x);
}
else {
qrframe[(8 + x) + width * 6] = 1;
qrframe[6 + width * (8 + x)] = 1;
}
// version block
if (version > 6) {
t = vpat[version - 7];
k = 17;
for (x = 0; x < 6; x++)
for (y = 0; y < 3; y++, k--)
if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
}
else {
setmask(5 - x, 2 - y + width - 11);
setmask(2 - y + width - 11, 5 - x);
}
}
// sync mask bits - only set above for white spaces, so add in black bits
for (y = 0; y < width; y++)
for (x = 0; x <= y; x++)
if (qrframe[x + width * y])
setmask(x, y);
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
v = strinbuf.length;
// string to array
for( i = 0 ; i < v; i++ )
eccbuf[i] = strinbuf.charCodeAt(i);
strinbuf = eccbuf.slice(0);
// calculate max string length
x = datablkw * (neccblk1 + neccblk2) + neccblk2;
if (v >= x - 2) {
v = x - 2;
if (version > 9)
v--;
}
// shift and repack to insert length prefix
i = v;
if (version > 9) {
strinbuf[i + 2] = 0;
strinbuf[i + 3] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 3] |= 255 & (t << 4);
strinbuf[i + 2] = t >> 4;
}
strinbuf[2] |= 255 & (v << 4);
strinbuf[1] = v >> 4;
strinbuf[0] = 0x40 | (v >> 12);
}
else {
strinbuf[i + 1] = 0;
strinbuf[i + 2] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 2] |= 255 & (t << 4);
strinbuf[i + 1] = t >> 4;
}
strinbuf[1] |= 255 & (v << 4);
strinbuf[0] = 0x40 | (v >> 4);
}
// fill to end with pad pattern
i = v + 3 - (version < 10);
while (i < x) {
strinbuf[i++] = 0xec;
// buffer has room if (i == x) break;
strinbuf[i++] = 0x11;
}
// calculate and append ECC
// calculate generator polynomial
genpoly[0] = 1;
for (i = 0; i < eccblkwid; i++) {
genpoly[i + 1] = 1;
for (j = i; j > 0; j--)
genpoly[j] = genpoly[j]
? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
}
for (i = 0; i <= eccblkwid; i++)
genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
// append ecc to data buffer
k = x;
y = 0;
for (i = 0; i < neccblk1; i++) {
appendrs(y, datablkw, k, eccblkwid);
y += datablkw;
k += eccblkwid;
}
for (i = 0; i < neccblk2; i++) {
appendrs(y, datablkw + 1, k, eccblkwid);
y += datablkw + 1;
k += eccblkwid;
}
// interleave blocks
y = 0;
for (i = 0; i < datablkw; i++) {
for (j = 0; j < neccblk1; j++)
eccbuf[y++] = strinbuf[i + j * datablkw];
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
}
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
for (i = 0; i < eccblkwid; i++)
for (j = 0; j < neccblk1 + neccblk2; j++)
eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
strinbuf = eccbuf;
// pack bits into frame avoiding masked area.
x = y = width - 1;
k = v = 1; // up, minus
/* inteleaved data and ecc codes */
m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for (i = 0; i < m; i++) {
t = strinbuf[i];
for (j = 0; j < 8; j++, t <<= 1) {
if (0x80 & t)
qrframe[x + width * y] = 1;
do { // find next fill position
if (v)
x--;
else {
x++;
if (k) {
if (y != 0)
y--;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y = 9;
}
}
}
else {
if (y != width - 1)
y++;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y -= 8;
}
}
}
}
v = !v;
} while (ismasked(x, y));
}
}
// save pre-mask copy of frame
strinbuf = qrframe.slice(0);
t = 0; // best
y = 30000; // demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for (k = 0; k < 8; k++) {
applymask(k); // returns black-white imbalance
x = badcheck();
if (x < y) { // current mask better than previous best?
y = x;
t = k;
}
if (t == 7)
break; // don't increment i to a void redoing mask
qrframe = strinbuf.slice(0); // reset for next pass
}
if (t != k) // redo best mask - none good enough, last wasn't t
applymask(t);
// add in final mask/ecclevel bytes
y = fmtword[t + ((ecclevel - 1) << 3)];
// low byte
for (k = 0; k < 8; k++, y >>= 1)
if (y & 1) {
qrframe[(width - 1 - k) + width * 8] = 1;
if (k < 6)
qrframe[8 + width * k] = 1;
else
qrframe[8 + width * (k + 1)] = 1;
}
// high byte
for (k = 0; k < 7; k++, y >>= 1)
if (y & 1) {
qrframe[8 + width * (width - 7 + k)] = 1;
if (k)
qrframe[(6 - k) + width * 8] = 1;
else
qrframe[7 + width * 8] = 1;
}
// return image
return qrframe;
}
var _canvas = null,
_size = null;
var api = {
get ecclevel () {
return ecclevel;
},
set ecclevel (val) {
ecclevel = val;
},
get size () {
return _size;
},
set size (val) {
_size = val
},
get canvas () {
return _canvas;
},
set canvas (el) {
_canvas = el;
},
getFrame: function (string) {
return genframe(string);
},
draw: function (string, canvas, size, ecc) {
ecclevel = ecc || ecclevel;
canvas = canvas || _canvas;
if (!canvas) {
console.warn('No canvas provided to draw QR code in!')
return;
}
size = size || _size || Math.min(canvas.width, canvas.height);
var frame = genframe(string),
ctx = canvas.ctx,
px = Math.round(size / (width + 8));
var roundedSize = px * (width + 8),
offset = Math.floor((size - roundedSize) / 2);
size = roundedSize;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setFillStyle('#000000');
for (var i = 0; i < width; i++) {
for (var j = 0; j < width; j++) {
if (frame[j * width + i]) {
ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
}
}
}
ctx.draw();
}
}
module.exports = {
api: api
}
})()

145
components/kk-printer/utils/util.js

@ -1,145 +0,0 @@
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
function toUnicode(s) {
var str = "";
for (var i = 0; i < s.length; i++) {
str += "\\u" + s.charCodeAt(i).toString(16) + "\t";
}
return str;
}
function strToHexCharCode(str) {
if (str === "")
return "";
var hexCharCode = [];
hexCharCode.push("0x");
for (var i = 0; i < str.length; i++) {
hexCharCode.push((str.charCodeAt(i)).toString(16));
}
return hexCharCode.join("");
}
function sumStrLength(str) {
var length = 0;
var data = str.toString();
for (var i = 0; i < data.length; i++) {
if (isCN(data[i])) { //是中文
length += 2;
} else {
length += 1;
}
}
return length;
}
function isCN(str) {
if (/^[\u3220-\uFA29]+$/.test(str)) {
return true;
} else {
return false;
}
}
//汉字转码
function hexStringToArrayBuffer(str) {
const buffer = new ArrayBuffer((str.length / 2) + 1)
const dataView = new DataView(buffer)
for (var i = 0; i < str.length / 2; i++) {
var temp = parseInt(str[i * 2] + str[i * 2 + 1], 16)
dataView.setUint8(i, temp)
}
dataView.setUint8((str.length / 2), 0x0a)
return buffer;
}
//返回八位数组
function subString(str) {
var arr = [];
if (str.length > 8) { //大于8
for (var i = 0;
(i * 8) < str.length; i++) {
var temp = str.substring(i * 8, 8 * i + 8);
arr.push(temp)
}
return arr;
} else {
return str
}
}
//不带有汉字
function hexStringToArrayBufferstr(str) {
let val = ""
for (let i = 0; i < str.length; i++) {
if (val === '') {
val = str.charCodeAt(i).toString(16)
} else {
val += ',' + str.charCodeAt(i).toString(16)
}
}
val += "," + "0x0a";
// 将16进制转化为ArrayBuffer
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) {
return parseInt(h, 16)
})).buffer
}
function ab2hex(buffer) {
let hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
})
return hexArr.join('');
}
// ArrayBuffer转为字符串,参数为ArrayBuffer对象
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
// 字符串转为ArrayBuffer对象,参数为字符串
function str2ab(str) {
var buf = new ArrayBuffer(str.length+1); // 补充/0
var bufView = new Uint8Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function send0X0A() {
const buffer = new ArrayBuffer(1)
const dataView = new DataView(buffer)
dataView.setUint8(0, 0x0a)
return buffer;
}
function buf2hex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
module.exports = {
hexStringToArrayBuffer: hexStringToArrayBuffer,
send0X0A: send0X0A,
ab2hex: ab2hex,
str2ab: str2ab,
ab2str: ab2str,
buf2hex: buf2hex
}

294
components/print/bluetooth.js

@ -0,0 +1,294 @@
class Bluetooth {
constructor() {
this.isOpenBle = false;
this.deviceId = "";
this.serviceId = "";
this.writeId = "";
this.notifyId = "";
this.num = 0;
this.serviceList = [];
this.openBluetoothAdapter();
}
showToast(title) {
uni.showToast({
title: title,
icon: 'none',
'duration': 2000
});
}
openBluetoothAdapter() {
return new Promise((resolve, reject) => {
uni.openBluetoothAdapter({
success: res => {
this.isOpenBle = true;
// this.showToast("初始化蓝牙模块成功");
resolve(res);
},
fail: err => {
this.showToast('蓝牙状态读取失败,请检查是否打开蓝牙');
reject(err);
},
});
});
}
startBluetoothDevicesDiscovery() {
if (!this.isOpenBle) {
this.showToast(`初始化蓝牙模块失败`)
return;
}
let self = this;
uni.showLoading({
title: '蓝牙搜索中'
})
return new Promise((resolve, reject) => {
setTimeout(() => {
uni.startBluetoothDevicesDiscovery({
success: res => {
resolve(res)
},
fail: res => {
self.showToast(`搜索设备失败` + JSON.stringify(err));
reject(err);
}
})
}, 300);
});
}
stopBluetoothDevicesDiscovery() {
let self = this;
return new Promise((resolve, reject) => {
uni.stopBluetoothDevicesDiscovery({
success: e => {
uni.hideLoading();
},
fail: e => {
uni.hideLoading();
self.showToast(`停止搜索蓝牙设备失败` + JSON.stringify(err));
}
})
});
}
createBLEConnection(deviceId) {
//设备deviceId
let self = this;
uni.showLoading({
mask: true,
title: '设别连接中,请稍候...'
})
console.log(deviceId);
return new Promise((resolve, reject) => {
uni.createBLEConnection({
deviceId,
timeout: 5000,
success: (res) => {
console.log(res)
resolve(res)
},
fail: err => {
console.log(err)
if (err.errMsg == "createBLEConnection:fail already connect") {
resolve(err)
return true;
}
if (err.errCode == 10012) {
self.showToast(`蓝牙连接超时`);
} else {
self.showToast(`停止搜索蓝牙设备失败` + JSON.stringify(err));
}
reject(err);
},
complete() {
uni.hideLoading();
}
})
});
}
//获取蓝牙设备所有服务(service)
getBLEDeviceServices() {
let _serviceList = [];
let deviceId = this.deviceId;
let self = this;
return new Promise((resolve, reject) => {
setTimeout(() => {
uni.getBLEDeviceServices({
deviceId,
success: res => {
for (let service of res.services) {
if (service.isPrimary) {
_serviceList.push(service);
}
}
uni.hideLoading();
resolve(_serviceList)
},
fail: err => {
uni.hideLoading();
self.showToast(`获取设备Services` + JSON.stringify(err));
reject(err);
},
})
}, 500);
});
}
//获取蓝牙设备某个服务中所有特征值(characteristic)
getBLEDeviceCharacteristics() {
let self = this;
let deviceId = self.deviceId;
let service = self.serviceList;
var uuid = service[self.num].uuid;
return new Promise((resolve, reject) => {
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: uuid,
success: res => {
console.log(res)
for (let _obj of res.characteristics) {
//获取notify
if (_obj.properties.notify) {
self.notifyId = _obj.uuid;
uni.setStorageSync('notifyId', self.notifyId);
}
//获取writeId
if (_obj.properties.write) {
self.writeId = _obj.uuid;
uni.setStorageSync('writeId', self.writeId);
}
}
console.log("notifyId:" + self.notifyId)
console.log("writeId:" + self.writeId)
if (!self.writeId || !self.notifyId) {
self.num++
if (self.num == service.length) {
console.log('找不到该读写的特征值')
reject('找不到该读写的特征值');
return false;
} else {
self.getBLEDeviceCharacteristics()
}
} else {
self.serviceId = uuid;
}
let result = {
'notifyId': self.notifyId,
'writeId': self.writeId
};
// self.showToast(`获取服务中所有特征值OK,${JSON.stringify(result)}`);
resolve(result)
},
fail: err => {
self.showToast(`getBLEDeviceCharacteristics` + JSON.stringify(err));
reject(err);
}
})
});
}
//断开联链接
closeBLEConnection() {
let deviceId = this.deviceId;
uni.closeBLEConnection({
deviceId,
success(res) {
console.log(res)
}
})
}
notifyBLECharacteristicValue() {
let deviceId = this.deviceId;
let serviceId = this.serviceId;
let characteristicId = this.notifyId;
console.log('----notifyBLECharacteristicValue----')
console.log(characteristicId)
console.log(serviceId)
console.log(deviceId)
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId,
serviceId,
characteristicId,
success(res) {
console.log(res);
uni.onBLECharacteristicValueChange(function(res) {
console.log(res);
});
},
fail(res) {
console.log('notifyBLECharacteristicValueChange failed:' + res.errMsg);
}
});
}
writeBLECharacteristicValue(buffer) {
let deviceId = this.deviceId;
let serviceId = this.serviceId;
let characteristicId = this.writeId;
console.log('----writeBLECharacteristicValue----')
console.log(characteristicId)
console.log(serviceId)
console.log(deviceId)
console.log("this: " + JSON.stringify(this));
return new Promise((resolve, reject) => {
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: buffer,
success(res) {
console.log('message发送成功', JSON.stringify(res));
resolve(res);
},
fail(err) {
console.log('message发送失败', JSON.stringify(err));
reject(err);
}
});
});
}
closeBluetoothAdapter() {
uni.closeBluetoothAdapter({
success: res => {
console.log(res)
}
});
}
//若APP在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需进行搜索操作。
reconnect() {
(async () => {
try {
this.deviceId = this.deviceId || uni.getStorageSync("deviceId");
this.serviceId = this.serviceId || uni.getStorageSync("serviceId");
let result1 = await this.createBLEConnection();
console.log("createBLEConnection: " + JSON.stringify(result1));
let result2 = await this.getBLEDeviceServices();
console.log("getBLEDeviceServices: " + JSON.stringify(result2));
let result3 = await this.getBLEDeviceCharacteristics();
console.log("getBLEDeviceCharacteristics: " + JSON.stringify(result3));
} catch (err) {
console.log("err: " + JSON.stringify(err));
}
})();
}
}
export default Bluetooth;

42
components/print/code128.js

@ -0,0 +1,42 @@
function getCode128(val) {
// 开始位为固定格式 str.charCodeAt()
let code128A = [0x7B, 0x41]
let code128B = [0x7B, 0x42]
let code128C = [0x7B, 0x43]
let ret = [];
let n67 = 0;
for (let i = 0; i < val.length; i += 2) {
let tmp = val.substr(i, 2);
if (tmp == '00') {
if(i==0){
ret.push(123);
ret.push(66);
n67 = 66;
}else if(n67==67){
ret.push(123);
ret.push(66);
n67 = 66;
}
ret.push(48);
ret.push(48);
} else {
if(i==0){
ret.push(123);
ret.push(67);
n67 = 67;
}else if(n67==66){
ret.push(123);
ret.push(67);
n67 = 67;
}
ret.push(parseInt(tmp));
}
}
ret.unshift(ret.length)
return ret;
}
module.exports = getCode128;

241
components/print/commands.js

@ -0,0 +1,241 @@
/**
* 修改自https://github.com/song940/node-escpos/blob/master/commands.js
* ESC/POS _ (Constants)
*/
var _ = {
LF: [0x0a],
FS: [0x1c],
FF: [0x0c],
GS: [0x1d],
DLE: [0x10],
EOT: [0x04],
NUL: [0x00],
ESC: [0x1b],
EOL: '\n',
};
/**
* [FEED_CONTROL_SEQUENCES Feed control sequences]
* @type {Object}
*/
_.FEED_CONTROL_SEQUENCES = {
CTL_LF: [0x0a], // Print and line feed
CTL_GLF: [0x4a, 0x00], // Print and feed paper (without spaces between lines)
CTL_FF: [0x0c], // Form feed
CTL_CR: [0x0d], // Carriage return
CTL_HT: [0x09], // Horizontal tab
CTL_VT: [0x0b], // Vertical tab
};
_.CHARACTER_SPACING = {
CS_DEFAULT: [0x1b, 0x20, 0x00],
CS_SET: [0x1b, 0x20]
};
_.LINE_SPACING = {
LS_DEFAULT: [0x1b, 0x32],
LS_SET: [0x1b, 0x33]
};
/**
* [HARDWARE Printer hardware]
* @type {Object}
*/
_.HARDWARE = {
HW_INIT: [0x1b, 0x40], // Clear data in buffer and reset modes
HW_SELECT: [0x1b, 0x3d, 0x01], // Printer select
HW_RESET: [0x1b, 0x3f, 0x0a, 0x00], // Reset printer hardware
};
/**
* [CASH_DRAWER Cash Drawer]
* @type {Object}
*/
_.CASH_DRAWER = {
CD_KICK_2: [0x1b, 0x70, 0x00], // Sends a pulse to pin 2 []
CD_KICK_5: [0x1b, 0x70, 0x01], // Sends a pulse to pin 5 []
};
/**
* [MARGINS Margins sizes]
* @type {Object}
*/
_.MARGINS = {
BOTTOM: [0x1b, 0x4f], // Fix bottom size
LEFT: [0x1b, 0x6c], // Fix left size
RIGHT: [0x1b, 0x51], // Fix right size
};
/**
* [PAPER Paper]
* @type {Object}
*/
_.PAPER = {
PAPER_FULL_CUT: [0x1d, 0x56, 0x00], // Full cut paper
PAPER_PART_CUT: [0x1d, 0x56, 0x01], // Partial cut paper
PAPER_CUT_A: [0x1d, 0x56, 0x41], // Partial cut paper
PAPER_CUT_B: [0x1d, 0x56, 0x42], // Partial cut paper
};
/**
* [TEXT_FORMAT Text format]
* @type {Object}
*/
_.TEXT_FORMAT = {
TXT_NORMAL: [0x1b, 0x21, 0x00], // Normal text
TXT_2HEIGHT: [0x1b, 0x21, 0x10], // Double height text
TXT_2WIDTH: [0x1b, 0x21, 0x20], // Double width text
TXT_4SQUARE: [0x1b, 0x21, 0x30], // Double width & height text
TXT_UNDERL_OFF: [0x1b, 0x2d, 0x00], // Underline font OFF
TXT_UNDERL_ON: [0x1b, 0x2d, 0x01], // Underline font 1-dot ON
TXT_UNDERL2_ON: [0x1b, 0x2d, 0x02], // Underline font 2-dot ON
TXT_BOLD_OFF: [0x1b, 0x45, 0x00], // Bold font OFF
TXT_BOLD_ON: [0x1b, 0x45, 0x01], // Bold font ON
TXT_ITALIC_OFF: [0x1b, 0x35], // Italic font ON
TXT_ITALIC_ON: [0x1b, 0x34], // Italic font ON
TXT_FONT_A: [0x1b, 0x4d, 0x00], // Font type A
TXT_FONT_B: [0x1b, 0x4d, 0x01], // Font type B
TXT_FONT_C: [0x1b, 0x4d, 0x02], // Font type C
TXT_ALIGN_LT: [0x1b, 0x61, 0x00], // Left justification
TXT_ALIGN_CT: [0x1b, 0x61, 0x01], // Centering
TXT_ALIGN_RT: [0x1b, 0x61, 0x02], // Right justification
};
/**
* [BARCODE_FORMAT Barcode format]
* @type {Object}
*/
_.BARCODE_FORMAT = {
BARCODE_TXT_OFF: [0x1d, 0x48, 0x00], // HRI barcode chars OFF
BARCODE_TXT_ABV: [0x1d, 0x48, 0x01], // HRI barcode chars above
BARCODE_TXT_BLW: [0x1d, 0x48, 0x02], // HRI barcode chars below
BARCODE_TXT_BTH: [0x1d, 0x48, 0x03], // HRI barcode chars both above and below
BARCODE_FONT_A: [0x1d, 0x66, 0x00], // Font type A for HRI barcode chars
BARCODE_FONT_B: [0x1d, 0x66, 0x01], // Font type B for HRI barcode chars
BARCODE_HEIGHT: function (height) { // Barcode Height [1-255]
return [0x1d, 0x68, height];
},
BARCODE_WIDTH: function (width) { // Barcode Width [2-6]
return [0x1d, 0x77, width];
},
BARCODE_HEIGHT_DEFAULT: [0x1d, 0x68, 0x64], // Barcode height default:100
BARCODE_WIDTH_DEFAULT: [0x1d, 0x77, 0x01], // Barcode width default:1
BARCODE_UPC_A: [0x1d, 0x6b, 0x00], // Barcode type UPC-A
BARCODE_UPC_E: [0x1d, 0x6b, 0x01], // Barcode type UPC-E
BARCODE_EAN13: [0x1d, 0x6b, 0x02], // Barcode type EAN13
BARCODE_EAN8: [0x1d, 0x6b, 0x03], // Barcode type EAN8
BARCODE_CODE39: [0x1d, 0x6b, 0x04], // Barcode type CODE39
BARCODE_ITF: [0x1d, 0x6b, 0x05], // Barcode type ITF
BARCODE_NW7: [0x1d, 0x6b, 0x06], // Barcode type NW7
BARCODE_CODE93: [0x1d, 0x6b, 0x48], // Barcode type CODE93
BARCODE_CODE128: [0x1d, 0x6b, 0x49], // Barcode type CODE128
};
/**
* [QRCODE_FORMAT qrcode format二维码]
* @type {Object}
*/
_.QRCODE_FORMAT = {
QRCODE_SIZE: function(n) { // 设置二维码大小
let data = [29,40,107,3,0,49,67]
if (n > 15) {
n = 15
}
if (n < 1) {
n = 1
}
data.push(n)
return data;
},
QRCODE_ERROR: function(n) { // 设置纠错等级
/*
n 功能 纠错能力
48 选择纠错等级 L 7
49 选择纠错等级 M 15
50 选择纠错等级 Q 25
51 选择纠错等级 H 30
*/
let data = [29,40,107,3,0,49,69]
data.push(n)
return data;
},
QRCODE_DATA: function(content) { // 设置二维码内容
let data = [29,40,107]
var code = new encode.TextEncoder(
'gb18030', {
NONSTANDARD_allowLegacyEncoding: true
}).encode(content)
data.push(parseInt((code.length + 3) % 256))
data.push(parseInt((code.length + 3) / 256))
data.push(49)
data.push(80)
data.push(48)
for (var i = 0; i < code.length; ++i) {
data.push(code[i])
}
return data;
},
QRCODE_PRINT:[29,40,107,3,0,49,81,48],// 打印二维码
};
/**
* [IMAGE_FORMAT Image format]
* @type {Object}
*/
_.IMAGE_FORMAT = {
S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size
S_RASTER_2W: [0x1d, 0x76, 0x30, 0x01], // Set raster image double width
S_RASTER_2H: [0x1d, 0x76, 0x30, 0x02], // Set raster image double height
S_RASTER_Q: [0x1d, 0x76, 0x30, 0x03], // Set raster image quadruple
};
/**
* [BITMAP_FORMAT description]
* @type {Object}
*/
_.BITMAP_FORMAT = {
BITMAP_S8: [0x1b, 0x2a, 0x00],
BITMAP_D8: [0x1b, 0x2a, 0x01],
BITMAP_S24: [0x1b, 0x2a, 0x20],
BITMAP_D24: [0x1b, 0x2a, 0x21]
};
/**
* [GSV0_FORMAT description]
* @type {Object}
*/
_.GSV0_FORMAT = {
GSV0_NORMAL: [0x1d, 0x76, 0x30, 0x00],
GSV0_DW: [0x1d, 0x76, 0x30, 0x01],
GSV0_DH: [0x1d, 0x76, 0x30, 0x02],
GSV0_DWDH: [0x1d, 0x76, 0x30, 0x03]
};
/**
* [BEEP description]
* @type {string}
*/
_.BEEP = [0x1b, 0x42]; // Printer Buzzer pre hex
/**
* [COLOR description]
* @type {Object}
*/
_.COLOR = {
0: [0x1b, 0x72, 0x00], // black
1: [0x1b, 0x72, 0x01] // red
};
/**
* [exports description]
* @type {[type]}
*/
module.exports = _;

47
components/print/encoding-indexes.js

File diff suppressed because one or more lines are too long

3313
components/print/encoding.js

File diff suppressed because it is too large

246
components/print/escpos.js

@ -0,0 +1,246 @@
/**
* 修改自https://github.com/song940/node-escpos/blob/master/commands.js
* ESC/POS _ (Constants)
*/
const encode = require('./encoding');
var _ = {
LF: [0x0a],
FS: [0x1c],
FF: [0x0c],
GS: [0x1d],
DLE: [0x10],
EOT: [0x04],
NUL: [0x00],
ESC: [0x1b],
EOL: '\n',
};
/**
* [FEED_CONTROL_SEQUENCES Feed control sequences走纸]
* @type {Object}
*/
_.FEED_CONTROL_SEQUENCES = {
CTL_LF: [0x0a], // Print and line feed
CTL_GLF: [0x4a, 0x00], // Print and feed paper (without spaces between lines)
CTL_FF: [0x0c], // Form feed
CTL_CR: [0x0d], // Carriage return
CTL_HT: [0x09], // Horizontal tab
CTL_VT: [0x0b], // Vertical tab
};
_.CHARACTER_SPACING = {
CS_DEFAULT: [0x1b, 0x20, 0x00],
CS_SET: [0x1b, 0x20]
};
_.LINE_SPACING = {
LS_DEFAULT: [0x1b, 0x32],
LS_SET: [0x1b, 0x33]
};
/**
* [HARDWARE Printer hardware]
* @type {Object}
*/
_.HARDWARE = {
HW_INIT: [0x1b, 0x40], // Clear data in buffer and reset modes
HW_SELECT: [0x1b, 0x3d, 0x01], // Printer select
HW_RESET: [0x1b, 0x3f, 0x0a, 0x00], // Reset printer hardware
};
/**
* [CASH_DRAWER Cash Drawer 钱箱]
* @type {Object}
*/
_.CASH_DRAWER = {
CD_KICK_2: [0x1b, 0x70, 0x00], // Sends a pulse to pin 2 []
CD_KICK_5: [0x1b, 0x70, 0x01], // Sends a pulse to pin 5 []
};
/**
* [MARGINS Margins sizes边缘]
* @type {Object}
*/
_.MARGINS = {
BOTTOM: [0x1b, 0x4f], // Fix bottom size
LEFT: [0x1b, 0x6c], // Fix left size
RIGHT: [0x1b, 0x51], // Fix right size
};
/**
* [PAPER Paper切纸]
* @type {Object}
*/
_.PAPER = {
PAPER_FULL_CUT: [0x1d, 0x56, 0x00], // Full cut paper
PAPER_PART_CUT: [0x1d, 0x56, 0x01], // Partial cut paper
PAPER_CUT_A: [0x1d, 0x56, 0x41], // Partial cut paper
PAPER_CUT_B: [0x1d, 0x56, 0x42], // Partial cut paper
};
/**
* [TEXT_FORMAT Text format文本格式]
* @type {Object}
*/
_.TEXT_FORMAT = {
TXT_NORMAL: [0x1b, 0x21, 0x00], // Normal text
TXT_2HEIGHT: [0x1b, 0x21, 0x10], // Double height text
TXT_2WIDTH: [0x1b, 0x21, 0x20], // Double width text
TXT_4SQUARE: [0x1b, 0x21, 0x30], // Double width & height text
TXT_UNDERL_OFF: [0x1b, 0x2d, 0x00], // Underline font OFF
TXT_UNDERL_ON: [0x1b, 0x2d, 0x01], // Underline font 1-dot ON
TXT_UNDERL2_ON: [0x1b, 0x2d, 0x02], // Underline font 2-dot ON
TXT_BOLD_OFF: [0x1b, 0x45, 0x00], // Bold font OFF
TXT_BOLD_ON: [0x1b, 0x45, 0x01], // Bold font ON
TXT_ITALIC_OFF: [0x1b, 0x35], // Italic font ON
TXT_ITALIC_ON: [0x1b, 0x34], // Italic font ON
TXT_FONT_A: [0x1b, 0x4d, 0x00], // Font type A
TXT_FONT_B: [0x1b, 0x4d, 0x01], // Font type B
TXT_FONT_C: [0x1b, 0x4d, 0x02], // Font type C
TXT_ALIGN_LT: [0x1b, 0x61, 0x00], // Left justification
TXT_ALIGN_CT: [0x1b, 0x61, 0x01], // Centering
TXT_ALIGN_RT: [0x1b, 0x61, 0x02], // Right justification
};
/**
* [BARCODE_FORMAT Barcode format条码]
* @type {Object}
*/
_.BARCODE_FORMAT = {
BARCODE_TXT_OFF: [0x1d, 0x48, 0x00], // HRI barcode chars OFF
BARCODE_TXT_ABV: [0x1d, 0x48, 0x01], // HRI barcode chars above
BARCODE_TXT_BLW: [0x1d, 0x48, 0x02], // HRI barcode chars below
BARCODE_TXT_BTH: [0x1d, 0x48, 0x03], // HRI barcode chars both above and below
BARCODE_FONT_A: [0x1d, 0x66, 0x00], // Font type A for HRI barcode chars
BARCODE_FONT_B: [0x1d, 0x66, 0x01], // Font type B for HRI barcode chars
BARCODE_HEIGHT: function(height) { // Barcode Height [1-255]
return [0x1d, 0x68, height];
},
BARCODE_WIDTH: function(width) { // Barcode Width [2-6]
return [0x1d, 0x77, width];
},
BARCODE_HEIGHT_DEFAULT: [0x1d, 0x68, 0x64], // Barcode height default:100
BARCODE_WIDTH_1: [0x1d, 0x77, 0x01], // Barcode width default:1
BARCODE_WIDTH_2: [0x1d, 0x77, 0x02], // Barcode width default:1
BARCODE_WIDTH_3: [0x1d, 0x77, 0x03], // Barcode width default:1
BARCODE_WIDTH_4: [0x1d, 0x77, 0x04], // Barcode width default:1
BARCODE_UPC_A: [0x1d, 0x6b, 0x00], // Barcode type UPC-A
BARCODE_UPC_E: [0x1d, 0x6b, 0x01], // Barcode type UPC-E
BARCODE_EAN13: [0x1d, 0x6b, 0x02], // Barcode type EAN13
BARCODE_EAN8: [0x1d, 0x6b, 0x03], // Barcode type EAN8
BARCODE_CODE39: [0x1d, 0x6b, 0x04], // Barcode type CODE39
BARCODE_ITF: [0x1d, 0x6b, 0x05], // Barcode type ITF
BARCODE_NW7: [0x1d, 0x6b, 0x06], // Barcode type NW7
BARCODE_CODE93: [0x1d, 0x6b, 0x48], // Barcode type CODE93
BARCODE_CODE128: [0x1d, 0x6b, 0x49], // Barcode type CODE128
};
/**
* [QRCODE_FORMAT qrcode format二维码]
* @type {Object}
*/
_.QRCODE_FORMAT = {
QRCODE_SIZE: function(n) { // 设置二维码大小
let data = [29,40,107,3,0,49,67]
if (n > 15) {
n = 15
}
if (n < 1) {
n = 1
}
data.push(n)
return data;
},
QRCODE_ERROR: function(n) { // 设置纠错等级
/*
n 功能 纠错能力
48 选择纠错等级 L 7
49 选择纠错等级 M 15
50 选择纠错等级 Q 25
51 选择纠错等级 H 30
*/
let data = [29,40,107,3,0,49,69]
data.push(n)
return data;
},
QRCODE_DATA: function(content) { // 设置二维码内容
let data = [29,40,107]
var code = new encode.TextEncoder(
'gb18030', {
NONSTANDARD_allowLegacyEncoding: true
}).encode(content)
data.push(parseInt((code.length + 3) % 256))
data.push(parseInt((code.length + 3) / 256))
data.push(49)
data.push(80)
data.push(48)
for (var i = 0; i < code.length; ++i) {
data.push(code[i])
}
return data;
},
QRCODE_PRINT:[29,40,107,3,0,49,81,48],// 打印二维码
};
/**
* [IMAGE_FORMAT Image format图像]
* @type {Object}
*/
_.IMAGE_FORMAT = {
S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size
S_RASTER_2W: [0x1d, 0x76, 0x30, 0x01], // Set raster image double width
S_RASTER_2H: [0x1d, 0x76, 0x30, 0x02], // Set raster image double height
S_RASTER_Q: [0x1d, 0x76, 0x30, 0x03], // Set raster image quadruple
};
/**
* [BITMAP_FORMAT description BMP图片]
* @type {Object}
*/
_.BITMAP_FORMAT = {
BITMAP_S8: [0x1b, 0x2a, 0x00],
BITMAP_D8: [0x1b, 0x2a, 0x01],
BITMAP_S24: [0x1b, 0x2a, 0x20],
BITMAP_D24: [0x1b, 0x2a, 0x21]
};
/**
* [GSV0_FORMAT description]
* @type {Object}
*/
_.GSV0_FORMAT = {
GSV0_NORMAL: [0x1d, 0x76, 0x30, 0x00],
GSV0_DW: [0x1d, 0x76, 0x30, 0x01],
GSV0_DH: [0x1d, 0x76, 0x30, 0x02],
GSV0_DWDH: [0x1d, 0x76, 0x30, 0x03]
};
/**
* [BEEP description 嗡鸣]
* @type {string}
*/
_.BEEP = [0x1b, 0x42]; // Printer Buzzer pre hex
/**
* [COLOR description]
* @type {Object}
*/
_.COLOR = {
0: [0x1b, 0x72, 0x00], // black
1: [0x1b, 0x72, 0x01] // red
};
/**
* [exports description]
* @type {[type]}
*/
module.exports = _;

201
components/print/gbk.js

File diff suppressed because one or more lines are too long

206
components/print/printerjobs.js

@ -0,0 +1,206 @@
const escCmd = require('./escpos');
const gbk = require('./gbk');
const printerJobs = function() {
this._queue = Array.from(escCmd.HARDWARE.HW_INIT);
this._enqueue = function(cmd) {
this._queue.push.apply(this._queue, cmd);
}
};
/**
* 增加打印内容
* @param {string} content 文字内容
*/
printerJobs.prototype.text = function(content) {
if (content) {
let uint8Array = gbk.encode(content);
let encoded = Array.from(uint8Array);
this._enqueue(encoded);
}
return this;
};
/**
* 打印文字
* @param {string} content 文字内容
*/
printerJobs.prototype.print = function(content) {
this.text(content);
this._enqueue(escCmd.LF);
return this;
};
/**
* 打印条码
* @param {string} content 条码内容 code128A,B,C可以混合打印在一起
*/
printerJobs.prototype.printBarcode = function(content) {
if (content) {
let bar = escCmd.BARCODE_FORMAT;
const cmds = [].concat(bar.BARCODE_TXT_BLW,bar.BARCODE_WIDTH(2),bar.BARCODE_CODE128, content);
this._enqueue(cmds);
this._enqueue(escCmd.LF);
}
return this;
};
/**
* 打印二维码
* @param {string} content 二维码内容
*/
printerJobs.prototype.printQrcode = function(content,size) {
if (content) {
let qr = escCmd.QRCODE_FORMAT;
// const cmds = [].concat([27, 97, 1], [29, 118, 48, 0, 30, 0, 240, 0], content, [27, 74, 3], [27, 64]);
const cmds = [].concat(qr.QRCODE_SIZE(size),qr.QRCODE_ERROR(49),qr.QRCODE_DATA(content),qr.QRCODE_PRINT);
this._enqueue(cmds);
this._enqueue(escCmd.LF);
}
return this;
};
/**
* 打印图片
* @param {string} content bmp内容
*/
printerJobs.prototype.printImage = function(content) {
if (content) {
const cmds = [].concat([27, 97, 1], [29, 118, 48, 0, 30, 0, 240, 0], content, [27, 74, 3], [27, 64]);
this._enqueue(cmds);
this._enqueue(escCmd.LF);
}
return this;
};
/**
* 打印文字并换行
* @param {string} content 文字内容
*/
printerJobs.prototype.println = function(content = '') {
return this.print(content + escCmd.EOL);
};
/**
* 设置对齐方式
* @param {string} align 对齐方式 LT/CT/RT
*/
printerJobs.prototype.setAlign = function(align) {
this._enqueue(escCmd.TEXT_FORMAT['TXT_ALIGN_' + align.toUpperCase()]);
return this;
};
/**
* 设置字体
* @param {string} family A/B/C
*/
printerJobs.prototype.setFont = function(family) {
this._enqueue(escCmd.TEXT_FORMAT['TXT_FONT_' + family.toUpperCase()]);
return this;
};
/**
* 设定字体尺寸
* @param {number} width 字体宽度 1~2
* @param {number} height 字体高度 1~2
*/
printerJobs.prototype.setSize = function(width, height) {
if (2 >= width && 2 >= height) {
this._enqueue(escCmd.TEXT_FORMAT.TXT_NORMAL);
if (2 === width && 2 === height) {
this._enqueue(escCmd.TEXT_FORMAT.TXT_4SQUARE);
} else if (1 === width && 2 === height) {
this._enqueue(escCmd.TEXT_FORMAT.TXT_2HEIGHT);
} else if (2 === width && 1 === height) {
this._enqueue(escCmd.TEXT_FORMAT.TXT_2WIDTH);
}
}
return this;
};
/**
* 设定字体是否加粗
* @param {boolean} bold
*/
printerJobs.prototype.setBold = function(bold) {
if (typeof bold !== 'boolean') {
bold = true;
}
this._enqueue(bold ? escCmd.TEXT_FORMAT.TXT_BOLD_ON : escCmd.TEXT_FORMAT.TXT_BOLD_OFF);
return this;
};
/**
* 设定是否开启下划线
* @param {boolean} underline
*/
printerJobs.prototype.setUnderline = function(underline) {
if (typeof underline !== 'boolean') {
underline = true;
}
this._enqueue(underline ? escCmd.TEXT_FORMAT.TXT_UNDERL_ON : escCmd.TEXT_FORMAT.TXT_UNDERL_OFF);
return this;
};
/**
* 设置行间距为 n 点行,默认值行间距是 30
* @param {number} n 0n255
*/
printerJobs.prototype.setLineSpacing = function(n) {
if (n === undefined || n === null) {
this._enqueue(escCmd.LINE_SPACING.LS_DEFAULT);
} else {
this._enqueue(escCmd.LINE_SPACING.LS_SET);
this._enqueue([n]);
}
return this;
};
/**
* 打印空行
* @param {number} n
*/
printerJobs.prototype.lineFeed = function(n = 1) {
return this.print(new Array(n).fill(escCmd.EOL).join(''));
};
/**
* 设置字体颜色需要打印机支持
* @param {number} color - 0 默认颜色黑色 1 红色
*/
printerJobs.prototype.setColor = function(color) {
this._enqueue(escCmd.COLOR[color === 1 ? 1 : 0]);
return this;
};
/**
* https://support.loyverse.com/hardware/printers/use-the-beeper-in-a-escpos-printers
* 蜂鸣警报需要打印机支持
* @param {number} n 蜂鸣次数,1-9
* @param {number} t 蜂鸣长短,1-9
*/
printerJobs.prototype.beep = function(n, t) {
this._enqueue(escCmd.BEEP);
this._enqueue([n, t]);
return this;
};
/**
* 清空任务
*/
printerJobs.prototype.clear = function() {
this._queue = Array.from(escCmd.HARDWARE.HW_INIT);
return this;
};
/**
* 返回ArrayBuffer
*/
printerJobs.prototype.buffer = function() {
return new Uint8Array(this._queue).buffer;
};
module.exports = printerJobs;

128
components/print/printerutil.js

@ -0,0 +1,128 @@
// 打印机纸宽58mm,页的宽度384,字符宽度为1,每行最多盛放32个字符
const PAGE_WIDTH = 384;
const MAX_CHAR_COUNT_EACH_LINE = 32;
const PAGE_WIDTH_80 = 576;
const MAX_CHAR_COUNT_EACH_LINE_80 = 48;
/**
* @param str
* @returns {boolean} str是否全是中文
*/
function isChinese(str) {
return /^[\u4e00-\u9fa5]$/.test(str);
}
/**
* 返回字符串宽度(1个中文=2个英文字符)
* @param str
* @returns {number}
*/
function getStringWidth(str) {
let width = 0;
for (let i = 0, len = str.length; i < len; i++) {
width += isChinese(str.charAt(i)) ? 2 : 1;
}
return width;
}
/**
* 同一行输出居左, str2居右
* @param {string} str1 内容1
* @param {string} str2 内容2
* @param {number} fontWidth 字符宽度 1/2
* @param {string} fillWith str1 str2之间的填充字符
*
*/
function inlineArr(arr, fontWidth = 1, max_char = 0) {
var str = '';
var fillWith = ' ';
for (var i = 0; i < arr.length; i++) {
let fillCount = arr[i].width - (getStringWidth(arr[i].text)) % arr[i].width;
let fillStr = new Array(fillCount).fill(fillWith.charAt(0)).join('');
str = str + arr[i].text + fillStr;
}
return str;
}
/**
* 同一行输出str1, str2str1居左, str2居右
* @param {string} str1 内容1
* @param {string} str2 内容2
* @param {number} fontWidth 字符宽度 1/2
* @param {string} fillWith str1 str2之间的填充字符
*
*/
function inline(str1, str2, fillWith = ' ', fontWidth = 1, max_char = 0) {
var char_count = MAX_CHAR_COUNT_EACH_LINE;
if (max_char == 80) {
char_count = MAX_CHAR_COUNT_EACH_LINE_80
}
const lineWidth = max_char / fontWidth;
// 需要填充的字符数量
let fillCount = lineWidth - (getStringWidth(str1) + getStringWidth(str2)) % lineWidth;
let fillStr = new Array(fillCount).fill(fillWith.charAt(0)).join('');
return str1 + fillStr + str2;
}
/**
* 用字符填充一整行
* @param {string} fillWith 填充字符
* @param {number} fontWidth 字符宽度 1/2
*/
function fillLine(fillWith = '-', fontWidth = 1, max_char = 0) {
var char_count = MAX_CHAR_COUNT_EACH_LINE;
if (max_char == 80) {
char_count = MAX_CHAR_COUNT_EACH_LINE_80
}
const lineWidth = char_count / fontWidth;
return new Array(lineWidth).fill(fillWith.charAt(0)).join('');
}
/**
* 文字内容居中左右用字符填充
* @param {string} str 文字内容
* @param {number} fontWidth 字符宽度 1/2
* @param {string} fillWith str1 str2之间的填充字符
*/
function fillAround(str, fillWith = '-', fontWidth = 1, max_char = 0) {
var char_count = MAX_CHAR_COUNT_EACH_LINE;
if (max_char == 80) {
char_count = MAX_CHAR_COUNT_EACH_LINE_80
}
const lineWidth = char_count / fontWidth;
let strWidth = getStringWidth(str);
// 内容已经超过一行了,没必要填充
if (strWidth >= lineWidth) {
return str;
}
// 需要填充的字符数量
let fillCount = lineWidth - strWidth;
// 左侧填充的字符数量
let leftCount = Math.round(fillCount / 2);
// 两侧的填充字符,需要考虑左边需要填充,右边不需要填充的情况
let fillStr = new Array(leftCount).fill(fillWith.charAt(0)).join('');
return fillStr + str + fillStr.substr(0, fillCount - leftCount);
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join(',')
}
module.exports = {
inline: inline,
inlineArr: inlineArr,
fillLine: fillLine,
fillAround: fillAround,
ab2hex: ab2hex,
};

66
components/print/util.js

@ -0,0 +1,66 @@
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
//4合1
function convert4to1(res) {
let arr = [];
for (let i = 0; i < res.length; i++) {
if (i % 4 == 0) {
let rule = 0.29900 * res[i] + 0.58700 * res[i + 1] + 0.11400 * res[i + 2];
if (rule > 200) {
res[i] = 0;
} else {
res[i] = 1;
}
arr.push(res[i]);
}
}
return arr;
}
//8合1
function convert8to1(arr) {
let data = [];
for (let k = 0; k < arr.length; k += 8) {
let temp = arr[k] * 128 + arr[k + 1] * 64 + arr[k + 2] * 32 + arr[k + 3] * 16 + arr[k + 4] * 8 + arr[k + 5] * 4 +
arr[k + 6] * 2 + arr[k + 7] * 1
data.push(temp);
}
return data;
}
//我的图片宽度是240,那么拼接的指令就是[29, 118, 48, 0, 30, 0, 240, 0]
//我的图片宽度是160,那么拼接的指令就是[29, 118, 48, 0, 20, 0, 160, 0]
//补充一点,打印非二维码的图片,宽度一定要是24的倍数,不然打印也会出现乱码
function toArrayBuffer(res) {
let arr = convert4to1(res.data);
let data = convert8to1(arr);
let cmds = [].concat([27, 97, 1], [29, 118, 48, 0, 30, 0, 240, 0], data, [27, 74, 3], [27, 64]);
return new Uint8Array(cmds).buffer;
}
function zip_image(res) {
let arr = convert4to1(res.data);
let data = convert8to1(arr);
return data;
}
module.exports = {
formatTime: formatTime,
toArrayBuffer: toArrayBuffer,
zip_image: zip_image,
}

5
components/print/weapp.qrcode.esm.js

File diff suppressed because one or more lines are too long

341
components/tab-bar/delivery.vue

@ -1,25 +1,52 @@
<template>
<!-- 商家订单列表 -->
<view class="page1">
<view class="title-gary"></view>
<view class="title">外卖订单</view>
<view style="background: #fff;border: 1px solid #eee;">
<uni-segmented-control :current="current" :values="items" @clickItem="onClickItem" styleType="text" activeColor="#007aff"></uni-segmented-control>
</view>
<view class="content" style="background: #fff;">
<view v-show="current === 0">
</view>
<view v-show="current === 1">
</view>
<view v-show="current === 2">
<view class="title">
<view class="title-sreach">
<view class="title-name" >
商家订单
</view>
</view>
<view v-show="current === 3">
</view>
<view class="title-tab">
<scroll-view class="status-scroll-view" scroll-x enable-flex :show-scrollbar="false"
:scroll-with-animation="true">
<view class="status-list">
<view v-for="(item, index) in statusList" :key="index" class="status-item"
:class="{ 'active': currentIndex == item.value }" @click="handleStatusClick(item.value,item.value)">
<text class="status-text">{{ item.name }}</text>
</view>
</view>
</scroll-view>
</view>
<view class="box1" @tap="goDetail(item.id)" v-for="(item,index) in orderList" :key="index">
<view style="display: flex;height: 50rpx;border-bottom: 1px solid #eee;">
<view>
{{'#' + item.numberCode}}
</view>
<view style="flex: 1;display: flex;padding-left: 20rpx;">
{{item.createTime | formatISOTime}}
<!-- <text>已退款</text> -->
</view>
<view>
{{item.status == 0?'待支付':item.status == 1?' 待成团':item.status == 2?'待消费':item.status == 3?'待接单':item.status == 4?'待取货':item.status == 5?'待送达':item.status == 6?'已完成':item.status == 7?'待退款':item.status == 8?'已退款':item.status == 9?'已取消':item.status == 11?'售后中':item.status == 12?'已售后':""}}
</view>
</view>
<view v-show="current === 4">
<view style="height: 120rpx;padding-top: 20rpx;">
<view style="height: 50rpx;line-height: 50rpx;font-size: 28rpx;font-weight: 700;display: flex;">
商品 <text><text>{{item.goodsNum}}</text></text> <text style="color: red;flex: 1;text-align: right;">已出餐</text>
</view>
<view style="display: flex;" v-for="(item1,index1) in item.goodsList" :key="index">
<view style="flex: 1;">
{{item1.productName}}
</view>
<view style="width: 100rpx;">
{{'X' + item1.quantity}}
</view>
<view>
{{'¥'+ item1.price}}
</view>
</view>
</view>
</view>
</view>
@ -29,72 +56,260 @@
export default {
data() {
return {
items:['待接单', '待发货', '待退款','待售后','已发货','已完成','已取消','已售后'],
current: 0,
loadStatus: 'more',
searchForm:{
pageNum:1,
pageSize:10,
shopName:'',
searchStatus:10,
shopId:uni.getStorageSync('shopId'),
regionId:JSON.parse(uni.getStorageSync('area')).id
},
totalPages: 1,
orderList:[],
currentIndex: 10,
statusList: [{
name: '全部',
value: 10,
checked: true
},{
name: '待支付',
value: 0,
checked: true
},
{
name: '待成团',
value: 1,
checked: false
},
{
name: '待消费',
value: 2,
checked: false
},
{
name: '待接单',
value: 3,
checked: false
},
{
name: '待取货',
value: 4,
checked: false
},
{
name: '待送达',
value: 5,
checked: false
},
{
name: '已完成',
value: 6,
checked: false
},
{
name: '待退款',
value: 7,
checked: false
},
{
name: '已退款',
value: 8,
checked: false
},
{
name: '已取消',
value: 9,
checked: false
},
{
name: '售后中',
value: 11,
checked: false
},
{
name: '已售后',
value: 12,
checked: false
}
]
}
},
props:{
onReachBottom() {
if (this.searchForm.pageNum >= this.totalPages) return;
// this.status = 'loading';
this.searchForm.pageNum++;
this.getOrderList();
},
watch: {
filters:{
formatISOTime(isoString) {
const date = new Date(isoString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
},
methods: {
onClickItem(e) {
// this.pageNum = 1
// this.detailList = []
// if (this.current !== e.currentIndex) {
// this.current = e.currentIndex
// }
// if(e.currentIndex == 0){
// this.getShareList();
// }else if(e.currentIndex == 1){
// this.getWaitStorage('1')
// }else if(e.currentIndex == 2){
// this.getWaitStorage('2')
// }else if(e.currentIndex == 3){
// this.getWaitStorage('3')
init(){
// if(option.index){
// this.searchForm.searchStatus = option.index
// this.currentIndex = option.index
// }
this.getList()
},
ceshi(e) {
console.log("11111111",e)
if (e.detail.code) {
// code
this.tui.request("/social/wechat/getPhone", "POST", {
code:e.detail.code
}, false, true).then((res) => {
if (res.code == 200) {
getList(){
this.loadStatus = 'loading'
let that = this
that.NB.sendRequest("/mall/order/page", this.searchForm, true, 'POST', 'application/json').then((res) => {
that.loadStatus = 'nomore';
if (res.code == 200) {
if (that.searchForm.pageNum == 1) {
that.orderList = res.result.records;
} else {
this.tui.toast(res.message)
that.orderList = [...that.orderList, ...res.result.records]
}
for(let i=0;i<that.orderList.length;i++){
that.orderList[i].goodsNum = 0
for(let m=0;m<that.orderList[i].goodsList.length;m++){
that.orderList[i].goodsNum += that.orderList[i].goodsList[m].quantity
}
}
})
} else {
//
console.log('用户取消授权');
}
that.totalPages = res.result.pages; // pages =
that.$forceUpdate();
} else {
that.tui.toast(res.message);
return;
}
uni.hideLoading();
}).catch((res) => {});
},
goDetail(id){
uni.navigateTo({
url:'/package2/shop/orderDetail?id=' + id
})
},
handleStatusClick(index,value) {
if (this.currentIndex === index) return;
this.currentIndex = index;
this.searchForm.searchStatus = value
this.getList()
}
}
}
</script>
<style>
page,.page1{
page {
width: 100%;
height: 100%;
font-size: 28rpx;
font-size: 24rpx;
background: #F5F8F5;
color: #00231C;
}
.title-gary{
.page1 {
width: 100%;
height: 80rpx;
background: #777;
height: 100%;
font-size: 24rpx;
position: relative;
}
.title{
.title {
background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/8bc15960c2dc40268e295d6dd23aecce.png') no-repeat;
width: 100%;
height: 100rpx;
background: #fff;
line-height: 100rpx;
height: 20%;
}
.title-sreach {
width: 100%;
display: flex;
height: 200rpx;
position: relative;
}
.title-name {
padding-top: 110rpx;
font-size: 36rpx;
font-weight: 700;
flex: 1;
text-align: center;
}
.title-tab {
display: flex;
margin: -120rpx auto 0;
}
.status-scroll-view {
width: 100%;
white-space: nowrap;
/* 辅助滚动,与 flex 配合确保不换行 */
height: auto;
}
.status-list {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
padding: 0 0;
/* 可根据设计添加左右留白,但会影响“一排5个”精准计算,故留白为0 */
min-height: 88rpx;
/* 保证内部项撑开高度 */
}
/* 每个状态项:宽度为屏幕宽度的1/5,保证一行正好显示5个,超出滚动 */
.status-item {
flex-shrink: 0;
width: 20vw;
/* 关键:屏幕宽度的1/5,正好一排5个 */
text-align: center;
padding: 20rpx 0;
position: relative;
box-sizing: border-box;
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* 点击反馈 */
-webkit-tap-highlight-color: transparent;
}
.status-text {
font-size: 28rpx;
color: #666666;
font-weight: normal;
line-height: 1.4;
transition: color 0.2s, font-weight 0.2s;
}
/* 激活状态样式 */
.status-item.active .status-text {
color: #ff6b35;
font-weight: 500;
}
/* 激活指示条(下划线) */
.status-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background-color: #ff6b35;
border-radius: 2rpx;
transition: width 0.2s ease;
}
.box1 {
width: 95%;
margin: 20rpx auto;
background: #fff;
border-radius: 20rpx;
padding: 20rpx;
}
</style>

47
components/tab-bar/myCenter.vue

@ -4,12 +4,12 @@
<view class="title">我的</view>
<view class="shop-box" @click="navigatorTo('xiugaixinxi')">
<view class="shop-left">
<image src="/static/image/xiangzi.png" alt="">
<image :src="shopIcon" alt="">
</view>
<view class="shop-center">
<!-- 入驻信息修改 副标题 -->
<view class="shop-name">张三的店</view>
<view class="shop-address">沧州医学高等专科学校</view>
<view class="shop-name">{{shopName}}</view>
<view class="shop-address">{{region}}</view>
</view>
<view class="shop-right">
<uni-icons type="right" size="22"></uni-icons>
@ -31,8 +31,8 @@
<view class="list-icon">
<uni-icons type="wallet" size="22"></uni-icons>
</view>
<view class="list-name">
信息
<view class="list-name" @click="navigatorTo('yingyexinxi')">
业信息
</view>
<view class="list-right">
<uni-icons type="right" size="22"></uni-icons>
@ -73,7 +73,7 @@
</view>
</view>
<view class="list-box">
<view class="list-2">
<view class="list-2" @click="logOut">
退出登录
</view>
<view class="list-2">
@ -84,10 +84,13 @@
</template>
<script>
var jpushModule = uni.requireNativePlugin("JG-JPush");
export default {
data() {
return {
shopName:'',
shopIcon:'',
region:''
}
},
props:{
@ -97,6 +100,34 @@
},
methods: {
init(){
this.shopName = uni.getStorageSync('shopName');
this.shopIcon = uni.getStorageSync('shopIcon');
this.region = JSON.parse(uni.getStorageSync('shop')).region;
// key
const { keys } = uni.getStorageInfoSync();
const data = {};
keys.forEach(key => {
data[key] = uni.getStorageSync(key);
});
console.log('所有的缓存',data)
},
logOut() {
uni.clearStorage()
this.getRegistrationID()
getApp().globalData.userinfo = ''
uni.reLaunch({
url: '../login/login'
})
},
getRegistrationID() { //registerID
jpushModule.getRegistrationID(result => {
let registerID = result.registerID
console.log("看这里", result)
uni.setStorageSync("registerID", registerID)
// uni.setStorageSync("signPerson", result.signPerson)
})
},
navigatorTo(e){
let url = ""
if(e=='addgoods'){
@ -105,6 +136,8 @@
url = '/package1/myCenter/myMerchant'
}else if(e == 'xiugaixinxi'){
url = '/pages/myCenter/shopDetail'
}else if(e == 'yingyexinxi'){
url = '/pages/myCenter/businessInfo'
}
uni.navigateTo({
url: url

Loading…
Cancel
Save