uu
This commit is contained in:
parent
38b475eb66
commit
e82e92c6d9
@ -1,193 +0,0 @@
|
|||||||
/**
|
|
||||||
* 修改自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
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [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]}
|
|
||||||
*/
|
|
||||||
export default _
|
|
||||||
File diff suppressed because one or more lines are too long
298
components/tpx-bluetooth-print/print/printJob.js
Normal file
298
components/tpx-bluetooth-print/print/printJob.js
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
|
||||||
|
|
||||||
|
//微信小程序向蓝牙打印机发送数据进行打印的坑:
|
||||||
|
//小程序api向蓝牙打印机发送数据打印,发送的任何内容都应该要转成二进制数据,而且蓝牙打印的文本编码是GBK的,发送中文需转成GBK编码再转成二进制数据发送
|
||||||
|
//发送打印机指令也要转成二进制数据发送
|
||||||
|
//蓝牙打印机一次接收的二级制数据有限制,不同的系统不同的蓝牙设备限制可能不同,微信建议一次20个字节,需做递归分包发送
|
||||||
|
//发送完要打印的内容后,一定要发送一个打印的指令才能顺利打印 (有些指令就不需要)
|
||||||
|
|
||||||
|
|
||||||
|
// 发送数据(递归分包发送)
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {object} options
|
||||||
|
* {
|
||||||
|
deviceId,
|
||||||
|
serviceId,
|
||||||
|
characteristicId,
|
||||||
|
value [ArrayBuffer],
|
||||||
|
lasterSuccess,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function sendDataToDevice(options) {
|
||||||
|
let byteLength = options.value.byteLength;
|
||||||
|
//这里默认一次20个字发送
|
||||||
|
const speed = options.onceByleLength || 20;
|
||||||
|
if (byteLength > 0) {
|
||||||
|
uni.writeBLECharacteristicValue({
|
||||||
|
...options,
|
||||||
|
// writeType:"writeNoResponse",
|
||||||
|
value: options.value.slice(0, byteLength > speed ? speed : byteLength),
|
||||||
|
success: function (res) {
|
||||||
|
if (byteLength > speed) {
|
||||||
|
sendDataToDevice({
|
||||||
|
...options,
|
||||||
|
value: options.value.slice(speed, byteLength),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
options.lasterSuccess && options.lasterSuccess();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: function (res) {
|
||||||
|
options.onError && options.onError(res);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用的 ESC/POS指令, 十进制方式
|
||||||
|
// 更多指令请查看 ./PrintCommandDocs/ESC-POS指令文档(凯盛诺打印机代表).pdf
|
||||||
|
|
||||||
|
export const printCommand = {
|
||||||
|
left: [27, 97, 0], //居左
|
||||||
|
center: [27, 97, 1], //居中
|
||||||
|
right: [27, 97, 2], //居右
|
||||||
|
clear: [27, 64], //初始化
|
||||||
|
enter: [10],
|
||||||
|
};
|
||||||
|
|
||||||
|
//打印二维码
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {object} options
|
||||||
|
* {
|
||||||
|
deviceId,
|
||||||
|
serviceId,
|
||||||
|
characteristicId,
|
||||||
|
value,//ArrayBuffer:二维码的数据
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
export function printQR(options) {
|
||||||
|
//打印二维码的十进制指令data:
|
||||||
|
let data = [...printCommand.clear, 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;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* overwriteImageData 图片数据转 位图数据
|
||||||
|
* @param {object} data
|
||||||
|
* {
|
||||||
|
width,//图片宽度
|
||||||
|
height,//图片高度
|
||||||
|
imageData,//Uint8ClampedArray
|
||||||
|
threshold,//阈值, 越大,打印点数越多,图形越黑
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
//灰度值大于128位 白色 为第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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 分段发送二进制数据,按allUint8Array的length产生发送的进度
|
||||||
|
* @export
|
||||||
|
* @param {object} options
|
||||||
|
* {
|
||||||
|
deviceId,
|
||||||
|
serviceId,
|
||||||
|
characteristicId,
|
||||||
|
lasterSuccess,
|
||||||
|
onProgress,
|
||||||
|
}
|
||||||
|
* * @param {array} allUint8Array 所有的Uint8Array
|
||||||
|
*/
|
||||||
|
export function sendDataToPrint(options, allUint8Array) {
|
||||||
|
const allLenth = allUint8Array.length;
|
||||||
|
const writeArrayCopyer = allUint8Array.slice(0);
|
||||||
|
const print = (options, writeArray) => {
|
||||||
|
if (writeArray.length) {
|
||||||
|
sendDataToDevice({
|
||||||
|
...options,
|
||||||
|
value: writeArray.shift().buffer,
|
||||||
|
lasterSuccess: () => {
|
||||||
|
options.onProgress &&
|
||||||
|
options.onProgress(Math.floor(((allLenth - writeArray.length) / allLenth) * 100));
|
||||||
|
if (writeArray.length) {
|
||||||
|
print(options, writeArray);
|
||||||
|
} else {
|
||||||
|
options.lasterSuccess && options.lasterSuccess();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
print(options, writeArrayCopyer);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取打印图片的指令
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {object} options
|
||||||
|
* {
|
||||||
|
lineByLine, // 是否逐行打印,默认true
|
||||||
|
}
|
||||||
|
* @param {object} imageInfo overwriteImageData 得到的位图数据数组和宽高信息
|
||||||
|
{
|
||||||
|
array,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
export function getImageCommandArray(opt = {}, imageInfo = {}) {
|
||||||
|
const lineByLine = typeof opt.lineByLine !== 'boolean' ? true : opt.lineByLine;
|
||||||
|
const width = imageInfo.width;
|
||||||
|
const h = imageInfo.height;
|
||||||
|
const xl = width % 256;
|
||||||
|
const xh = (width - xl) / 256;
|
||||||
|
const yl = h % 256;
|
||||||
|
const yh = (h - yl) / 256;
|
||||||
|
//打印图片的十进制指令数组
|
||||||
|
let command = [];
|
||||||
|
|
||||||
|
if (lineByLine) {
|
||||||
|
// 分段逐行的指令
|
||||||
|
command = command.concat([29, 118, 48, 0, xl, xh, 1, 0]);
|
||||||
|
} else {
|
||||||
|
// 非分段逐行的指令
|
||||||
|
command = command.concat([29, 118, 48, 0, xl, xh, yl, yh]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取一张图片数据与指令整合的writeArray,结合 sendDataToPrint 发送二进制数据到蓝牙打印机
|
||||||
|
* @param {object} options
|
||||||
|
* {
|
||||||
|
lineByLine, // 是否逐行打印,默认true
|
||||||
|
printAlign, // 打印的位置
|
||||||
|
}
|
||||||
|
* @param {object} imageInfo overwriteImageData 得到的位图数据数组和宽高信息
|
||||||
|
{
|
||||||
|
array,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
export function getPrintImageWriteArray(opt = {}, imageInfo = {}) {
|
||||||
|
const lineByLine = typeof opt.lineByLine !== 'boolean' ? true : opt.lineByLine;
|
||||||
|
const width = imageInfo.width;
|
||||||
|
let arr = imageInfo.array;
|
||||||
|
let writeArray = [];
|
||||||
|
const iniTcommand = [].concat(printCommand.clear).concat(printCommand[opt.printAlign || 'left']);
|
||||||
|
const command = getImageCommandArray(opt, imageInfo);
|
||||||
|
writeArray.push(new Uint8Array(iniTcommand));
|
||||||
|
// 分段逐行打印的数据
|
||||||
|
if (lineByLine) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非逐行打印
|
||||||
|
writeArray.push(new Uint8Array(command.concat(arr)));
|
||||||
|
}
|
||||||
|
// writeArray.push(new Uint8Array([27, 74, 3]));
|
||||||
|
return writeArray;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 只打印一张图片数据的方法
|
||||||
|
* @param {object} options
|
||||||
|
* {
|
||||||
|
deviceId,
|
||||||
|
serviceId,
|
||||||
|
characteristicId,
|
||||||
|
lasterSuccess,
|
||||||
|
onProgress,
|
||||||
|
printAlign, "left"|"right"|"center"
|
||||||
|
}
|
||||||
|
* @param {object} imageInfo overwriteImageData 得到的位图数据数组和宽高信息
|
||||||
|
{
|
||||||
|
array,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function printImage(opt, imageInfo) {
|
||||||
|
sendDataToPrint(
|
||||||
|
opt,
|
||||||
|
getPrintImageWriteArray(
|
||||||
|
{
|
||||||
|
printAlign: opt.printAlign,
|
||||||
|
lineByLine: opt.lineByLine,
|
||||||
|
},
|
||||||
|
imageInfo,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,220 +0,0 @@
|
|||||||
import commands from'./commands'
|
|
||||||
import gbk from'./gbk'
|
|
||||||
import * as printerUtil from'./printerutil'
|
|
||||||
|
|
||||||
const printerJobs = function() {
|
|
||||||
this._queue = Array.from(commands.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(commands.LF);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
printerJobs.prototype.printArray = function(array) {
|
|
||||||
array.forEach(v => {
|
|
||||||
if (v.number) {
|
|
||||||
this.text(printerUtil.inline(v.title + '*' + v.number, `${v.price}`))
|
|
||||||
} else {
|
|
||||||
this.text(printerUtil.inline(v.title, `${v.price}`))
|
|
||||||
}
|
|
||||||
this._enqueue(commands.LF);
|
|
||||||
})
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
printerJobs.prototype.printQrcode = function(content, width) {
|
|
||||||
|
|
||||||
if (content) {
|
|
||||||
const cmds = [].concat(...printerUtil.makeImageCode(content, width));
|
|
||||||
this._enqueue(cmds);
|
|
||||||
this._enqueue(commands.LF);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
printerJobs.prototype.printQrcodeByESC = function(content) {
|
|
||||||
let arrPrint = [];
|
|
||||||
|
|
||||||
let uint8Array = gbk.encode(content);
|
|
||||||
let encoded = Array.from(uint8Array);
|
|
||||||
|
|
||||||
//初始化打印机
|
|
||||||
arrPrint= arrPrint.concat([0x1B, 0x40]); //16进制
|
|
||||||
//居中对齐
|
|
||||||
arrPrint=arrPrint.concat([0x1B, 0x61, 0x01]); //16进制
|
|
||||||
//正文
|
|
||||||
/*
|
|
||||||
* QR Code 设置单元大小 【格式】 ASCII GS ( k pL pH 1 C n 十六进制 1D 28 6B 03
|
|
||||||
* 00 31 43 n 十进制 29 40 107 03 0 49 67 n 功能:设置QR CODE 单元大小。
|
|
||||||
* 说明:·n 对应QR版本号, 决定QR CODE的高度与宽度。 · 1≤n ≤16。(十六进制为0x01≤n ≤0x0f)
|
|
||||||
*/
|
|
||||||
//设置设置 QR Code 的单元大小为 n 点
|
|
||||||
arrPrint=arrPrint.concat([0x1d, 0x28, 0x6b, 0x03, 0x00, 0x31, 0x43, 0x05]);
|
|
||||||
//设置错误纠正等级
|
|
||||||
arrPrint=arrPrint.concat([0x1d, 0x28, 0x6b, 0x03, 0x00, 0x31, 0x45, 0x05]);
|
|
||||||
//传入数据的长度+3
|
|
||||||
arrPrint=arrPrint.concat([0x1d, 0x28, 0x6b, encoded.length+3, 0x00, 0x31, 0x50, 0x30]);
|
|
||||||
//二维码内容
|
|
||||||
arrPrint=arrPrint.concat(encoded);
|
|
||||||
//开始打印二维码
|
|
||||||
arrPrint=arrPrint.concat([0x1d, 0x28, 0x6b, 0x03, 0x00, 0x31, 0x51, 0x30]);
|
|
||||||
//恢复居左对齐
|
|
||||||
arrPrint=arrPrint.concat([0x1B, 0x61, 0x00]); //16进制
|
|
||||||
this._enqueue(arrPrint);
|
|
||||||
this._enqueue(commands.LF);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印文字并换行
|
|
||||||
* @param {string} content 文字内容
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.println = function(content = '') {
|
|
||||||
return this.print(content + commands.EOL);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置对齐方式
|
|
||||||
* @param {string} align 对齐方式 LT/CT/RT
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.setAlign = function(align) {
|
|
||||||
this._enqueue(commands.TEXT_FORMAT['TXT_ALIGN_' + align.toUpperCase()]);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置字体
|
|
||||||
* @param {string} family A/B/C
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.setFont = function(family) {
|
|
||||||
this._enqueue(commands.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(commands.TEXT_FORMAT.TXT_NORMAL);
|
|
||||||
if (2 === width && 2 === height) {
|
|
||||||
this._enqueue(commands.TEXT_FORMAT.TXT_4SQUARE);
|
|
||||||
} else if (1 === width && 2 === height) {
|
|
||||||
this._enqueue(commands.TEXT_FORMAT.TXT_2HEIGHT);
|
|
||||||
} else if (2 === width && 1 === height) {
|
|
||||||
this._enqueue(commands.TEXT_FORMAT.TXT_2WIDTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设定字体是否加粗
|
|
||||||
* @param {boolean} bold
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.setBold = function(bold) {
|
|
||||||
if (typeof bold !== 'boolean') {
|
|
||||||
bold = true;
|
|
||||||
}
|
|
||||||
this._enqueue(bold ? commands.TEXT_FORMAT.TXT_BOLD_ON : commands.TEXT_FORMAT.TXT_BOLD_OFF);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设定是否开启下划线
|
|
||||||
* @param {boolean} underline
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.setUnderline = function(underline) {
|
|
||||||
if (typeof underline !== 'boolean') {
|
|
||||||
underline = true;
|
|
||||||
}
|
|
||||||
this._enqueue(underline ? commands.TEXT_FORMAT.TXT_UNDERL_ON : commands.TEXT_FORMAT.TXT_UNDERL_OFF);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置行间距为 n 点行,默认值行间距是 30 点
|
|
||||||
* @param {number} n 0≤n≤255
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.setLineSpacing = function(n) {
|
|
||||||
if (n === undefined || n === null) {
|
|
||||||
this._enqueue(commands.LINE_SPACING.LS_DEFAULT);
|
|
||||||
} else {
|
|
||||||
this._enqueue(commands.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(commands.EOL).join(''));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置字体颜色,需要打印机支持
|
|
||||||
* @param {number} color - 0 默认颜色黑色 1 红色
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.setColor = function(color) {
|
|
||||||
this._enqueue(commands.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(commands.BEEP);
|
|
||||||
this._enqueue([n, t]);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空任务
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.clear = function() {
|
|
||||||
this._queue = Array.from(commands.HARDWARE.HW_INIT);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回ArrayBuffer
|
|
||||||
*/
|
|
||||||
printerJobs.prototype.buffer = function() {
|
|
||||||
return new Uint8Array(this._queue).buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default printerJobs
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
// 打印机纸宽58mm,页的宽度384,字符宽度为1,每行最多盛放32个字符
|
|
||||||
const PAGE_WIDTH = 384;
|
|
||||||
const MAX_CHAR_COUNT_EACH_LINE = 32;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同一行输出str1, str2,str1居左, 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) {
|
|
||||||
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
|
|
||||||
// 需要填充的字符数量
|
|
||||||
let fillCount = lineWidth - (getStringWidth(str1) + getStringWidth(str2) + 2) % 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) {
|
|
||||||
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / 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) {
|
|
||||||
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / 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(',')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打印图片,需要根据图片宽度算出rate, rate = 图片宽度/imgRateSize
|
|
||||||
const imgRateSize = 8
|
|
||||||
|
|
||||||
// 默认240宽度 注意!! 图片宽度必须是8的倍数
|
|
||||||
const makeImageCode = (data, width = 240)=> {
|
|
||||||
//我的图片宽度是240,那么拼接的指令就是[29, 118, 48, 0, 30, 0, 240, 0]
|
|
||||||
//我的图片宽度是160,那么拼接的指令就是[29, 118, 48, 0, 20, 0, 160, 0]
|
|
||||||
//补充一点,打印非二维码的图片,宽度一定要是24的倍数,不然打印也会出现乱码
|
|
||||||
let rate = width / imgRateSize
|
|
||||||
|
|
||||||
return [
|
|
||||||
[27, 97, 1], [29, 118, 48, 0, 1*rate, 0, 8*rate, 0], data, [27, 74, 3], [27, 64]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
inline,
|
|
||||||
fillLine,
|
|
||||||
fillAround,
|
|
||||||
ab2hex,
|
|
||||||
imgRateSize,
|
|
||||||
makeImageCode,
|
|
||||||
};
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
import { makeImageCode } from "./printerutil.js"
|
|
||||||
|
|
||||||
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, width) {
|
|
||||||
let arr = convert4to1(res.data);
|
|
||||||
let data = convert8to1(arr);
|
|
||||||
let cmds = [].concat(...makeImageCode(data, width));
|
|
||||||
return new Uint8Array(cmds).buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function zip_image(res) {
|
|
||||||
let arr = convert4to1(res.data);
|
|
||||||
let data = convert8to1(arr);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
formatTime,
|
|
||||||
toArrayBuffer,
|
|
||||||
zip_image,
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<tpx-bluetooth v-model:value="blueToothData">
|
<tpx-bluetooth v-model:value="blueToothData">
|
||||||
<template v-slot:button>
|
<template v-slot:button>
|
||||||
<u-button @click="writeBLECharacteristicValue" type="primary" :disabled="!(blueToothData.deviceId && blueToothData.serviceId && blueToothData.characteristicId)">打印</u-button>
|
<u-button @click="handlePrint" type="primary" :disabled="!(blueToothData.deviceId && blueToothData.serviceId && blueToothData.characteristicId)">打印</u-button>
|
||||||
</template>
|
</template>
|
||||||
</tpx-bluetooth>
|
</tpx-bluetooth>
|
||||||
<canvas canvas-id="shareCanvas" :style="{width:canvasWidth + 'px', height: canvasHeight + 'px'}"></canvas>
|
<canvas canvas-id="shareCanvas" :style="{width:canvasWidth + 'px', height: canvasHeight + 'px'}"></canvas>
|
||||||
@ -9,9 +9,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { showLoading, showToast, hideLoading } from "@/common/untool"
|
import { showLoading, showToast, hideLoading } from "@/common/untool"
|
||||||
import PrinterJobs from './print/printerjobs.js'
|
import * as printJob from './print/printJob'
|
||||||
import * as printerUtil from './print/printerutil.js'
|
|
||||||
import * as util from './print/util.js'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props:{
|
props:{
|
||||||
@ -37,7 +35,9 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
canvasId: 'shareCanvas',
|
canvasId: 'shareCanvas',
|
||||||
imgZipData: '',
|
imgData: '',
|
||||||
|
percentage: 0, // 打印进度
|
||||||
|
threshold: [200], // 阈值(值越大,图片打印越深)
|
||||||
blueToothData: {
|
blueToothData: {
|
||||||
deviceId: '',
|
deviceId: '',
|
||||||
serviceId: '',
|
serviceId: '',
|
||||||
@ -52,70 +52,82 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async initData() {
|
async initData() {
|
||||||
this.imgZipData = await this.renderCanvasImg();
|
this.imgData = await this.renderCanvasImg();
|
||||||
},
|
},
|
||||||
// 打印-发送二进制数据
|
// 打印
|
||||||
async writeBLECharacteristicValue(){
|
async handlePrint(){
|
||||||
let imgZipData = this.imgZipData
|
|
||||||
let printerJobs = new PrinterJobs()
|
|
||||||
|
|
||||||
printerJobs
|
|
||||||
// .print(`下单时间:2021-07-25 15:30:23`)
|
|
||||||
// .print(printerUtil.fillLine())
|
|
||||||
// .print('备注')
|
|
||||||
// .setSize(2, 2)
|
|
||||||
// .setBold(true)
|
|
||||||
// .print(`叫那位非常漂亮的小姐姐送来,其他人送来拒收`)
|
|
||||||
// .print(printerUtil.fillLine())
|
|
||||||
.printQrcode(imgZipData, this.canvasWidth)
|
|
||||||
// .setSize(1, 1)
|
|
||||||
// .setBold(false)
|
|
||||||
// .print(printerUtil.fillLine('*'))
|
|
||||||
// .setAlign('lt')
|
|
||||||
// .printArray(arr)
|
|
||||||
// .print(printerUtil.fillAround('其它'))
|
|
||||||
// .print(printerUtil.inline('平台随机立减', `-2.10`))
|
|
||||||
// .print(printerUtil.inline('平台服务费', `-10.99`))
|
|
||||||
// .printArray(arr2)
|
|
||||||
// .print(printerUtil.fillLine())
|
|
||||||
// .setAlign('rt')
|
|
||||||
// .setSize(1, 2)
|
|
||||||
// .setBold(true)
|
|
||||||
// .print(`用户支付:¥99.99`)
|
|
||||||
// .print(printerUtil.fillLine())
|
|
||||||
|
|
||||||
let buffer = printerJobs.buffer();
|
|
||||||
console.log('buffer>>>',buffer)
|
|
||||||
showLoading('正在打印')
|
showLoading('正在打印')
|
||||||
try{
|
const pix = res.data;
|
||||||
await this.printbuffs(buffer)
|
const opt = {
|
||||||
hideLoading()
|
...this.blueToothData,
|
||||||
showToast('打印成功')
|
onProgress: (percentage) => {
|
||||||
}catch(e){
|
this.setData({
|
||||||
console.log('打印异常', e)
|
percentage,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
lasterSuccess: () => {
|
||||||
|
this.setData({
|
||||||
|
percentage: 0,
|
||||||
|
});
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '数据已发送完,请检查打印的内容是否正常',
|
||||||
|
showCancel: false,
|
||||||
|
confirmText: '好的',
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//打印图片
|
||||||
|
printJob.printImage(
|
||||||
|
opt,
|
||||||
|
// 将图片数据转成位图数据
|
||||||
|
printJob.overwriteImageData({
|
||||||
|
threshold: threshold[0],
|
||||||
|
imageData: this.imgData,
|
||||||
|
width: this.canvasWidth,
|
||||||
|
height: this.canvasHeight,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
},
|
},
|
||||||
printbuffs(buffer) {
|
// 选择本地文件打印-- TODO
|
||||||
let _this = this
|
// chooseImage() {
|
||||||
return new Promise(async (resolve, reject)=> {
|
// wx.chooseImage({
|
||||||
// 1.并行调用多次会存在写失败的可能性
|
// success: (res) => {
|
||||||
// 2.建议每次写入不超过20字节
|
// const tempFilePath = res.tempFilePaths[0];
|
||||||
// 分包处理,延时调用
|
// wx.getImageInfo({
|
||||||
const maxChunk = 20;
|
// src: tempFilePath,
|
||||||
for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
|
// success: (res) => {
|
||||||
let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
|
// // 打印宽度须是8的整数倍,这里处理掉多余的,使得宽度合适,不然有可能乱码
|
||||||
try{
|
// const mw = this.data.paperWidth % 8;
|
||||||
await _this.printbuff(subPackage)
|
// const w = mw === 0 ? this.data.paperWidth : this.data.paperWidth - mw;
|
||||||
}catch(msg){
|
// // 等比算出图片的高度
|
||||||
console.log("printbuffs:异常==", msg)
|
// const h = Math.floor((res.height * w) / res.width);
|
||||||
showToast('分段printbuff异常', msg)
|
// // 设置canvas宽高
|
||||||
reject(msg)
|
// this.setData({
|
||||||
return
|
// img: tempFilePath,
|
||||||
}
|
// canvasHeight: h,
|
||||||
}
|
// canvasWidth: w,
|
||||||
resolve()
|
// });
|
||||||
})
|
// // 在canvas 画一张图片
|
||||||
},
|
// ctx.fillStyle = 'rgba(255,255,255,1)';
|
||||||
|
// ctx.clearRect(0, 0, w, h);
|
||||||
|
// ctx.fillRect(0, 0, w, h);
|
||||||
|
// ctx.drawImage(tempFilePath, 0, 0, w, h);
|
||||||
|
// ctx.draw(false, () => {
|
||||||
|
// wx.hideLoading();
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// fail: (res) => {
|
||||||
|
// console.log('get info fail', res);
|
||||||
|
// wx.hideLoading();
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// },
|
||||||
getImageZip(params = {}) {
|
getImageZip(params = {}) {
|
||||||
return new Promise((resolve, reject)=> {
|
return new Promise((resolve, reject)=> {
|
||||||
uni.canvasGetImageData({
|
uni.canvasGetImageData({
|
||||||
@ -125,8 +137,8 @@ export default {
|
|||||||
success(res) {
|
success(res) {
|
||||||
console.log("img====",res);
|
console.log("img====",res);
|
||||||
if(res.data) {
|
if(res.data) {
|
||||||
let data = util.zip_image(res)
|
let data = res.data
|
||||||
console.log("zip====", data);
|
console.log("image data====", data);
|
||||||
resolve(data);
|
resolve(data);
|
||||||
} else {
|
} else {
|
||||||
showToast('获取图片信息异常:getImageZip')
|
showToast('获取图片信息异常:getImageZip')
|
||||||
@ -139,7 +151,6 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
renderCanvasImg() {
|
renderCanvasImg() {
|
||||||
let filePath = this.imageUrl
|
let filePath = this.imageUrl
|
||||||
@ -173,30 +184,6 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
|
||||||
printbuff(buffer) {
|
|
||||||
var _this = this
|
|
||||||
return new Promise((resolve, reject)=> {
|
|
||||||
uni.writeBLECharacteristicValue({
|
|
||||||
..._this.blueToothData,
|
|
||||||
// 这里的value是ArrayBuffer类型
|
|
||||||
value: buffer,
|
|
||||||
success:(res)=> {
|
|
||||||
console.log('writeBLECharacteristicValue success', res.errMsg)
|
|
||||||
// 必须加延迟返回,防止高频率调用
|
|
||||||
setTimeout(()=> {
|
|
||||||
resolve()
|
|
||||||
}, 10)
|
|
||||||
},
|
|
||||||
fail:(res)=> {
|
|
||||||
console.log('writeBLECharacteristicValue fail', res.errMsg)
|
|
||||||
reject(res.errMsg)
|
|
||||||
},
|
|
||||||
complete (e) {
|
|
||||||
console.log('writeBLECharacteristicValue complete', e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user