收藏
回答

请问uni-app开发的微信小程序使用蓝牙打印机时可以带着文字和图片一起打印出来吗?

为了直观的展示代码 前面的参数连接蓝牙的省略掉 直接看结构

这是页面结构

<template>
	<view class="body">
		<button class="button" hover-class="hover" @tap="receiptTest" :loading="isReceiptSend"
			:disabled="isReceiptSend">
			小票案例
		</button>
		<button class="button" hover-class="hover" @tap="queryStatus" :loading="isQuery" :disabled="isQuery">
			查询状态
		</button>
		<button ref='photo' class="button" hover-class="hover" @click="printPhoto">打印图片</button>
		<canvas canvas-id="canvasOut" class="canvas"
			:style="'border:0px solid; width:' + canvasWidth + 'px; height:' + canvasHeight + 'px'"></canvas>
		<!-- <button class="button" hover-class="hover" @tap="printJPGPhoto">打印彩图</button>
		<canvas canvas-id="canvasJPG" class="canvas"
			:style="'border:0px solid; width:' + jpgWidth + 'px; height:' + jpgHeight + 'px'"></canvas> -->
		<picker style="margin:20px" mode="selector" :range="buffSize" :value="buffIndex" @change="buffBindChange">
			当前每次发送字节数为(点击可更换):{{ buffSize[buffIndex] }}
		</picker>


		<picker style="margin:20px" mode="selector" :range="printNum" :value="printNumIndex"
			@change="printNumBindChange">
			当前打印份数(点击可更换):{{ printNum[printNumIndex] }}
		</picker>
	</view>
</template>

这是代码和参数

<script>
	var app = getApp();
	var esc = require("../../utils/esc.js");
	var encode = require("../../utils/encoding.js");


	function inArray(arr, key, val) {
		for (let i = 0; i < arr.length; i++) {
			if (arr[i][key] === val) {
				return i;
			}
		}


		return -1;
	} // ArrayBuffer转16进度字符串示例
	// ArrayBuffer转16进度字符串示例
	function ab2hex(buffer) {
		var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
			return ("00" + bit.toString(16)).slice(-2);
		});
		return hexArr.join("");
	}


	function convertToGrayscale(data) {
		let g = 0;


		for (let i = 0; i < data.length; i += 4) {
			g = data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11;
			data[i] = g;
			data[i + 1] = g;
			data[i + 2] = g;
		}


		return data;
	}


	function setPixel(data, offset, value) {
		data[offset] = value;
		data[offset + 1] = value;
		data[offset + 2] = value;
	}


	function adjustPixel(data, offset, value) {
		data[offset] += value;
	} // 彩色图转成单色图
	// 彩色图转成单色图
	function convertToMonoImage(width, height, data, shake) {
		let g = 0;
		let e = 0;


		for (let i = 0; i < data.length; i += 4) {
			data[i] = data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11;
		}


		for (let y = 0; y < height; y++) {
			for (let x = 0; x < width; x++) {
				let dataOffset = (width * y + x) * 4;
				g = data[dataOffset];


				if (g >= 150) {
					// 灰色转黑白的阈值, 可以调整打印效果
					e = g - 255;
					setPixel(data, dataOffset, 255);
				} else {
					e = g;
					setPixel(data, dataOffset, 0);
				}


				if (!shake) continue;


				if (x < width - 1 && y < height - 1) {
					//右边像素处理
					data[(width * y + x + 1) * 4] += (7 * e) / 16; //下


					data[(width * (y + 1) + x) * 4] += (5 * e) / 16; //右下


					data[(width * (y + 1) + x + 1) * 4] += e / 16; //左下


					if (x > 0) {
						data[(width * (y + 1) + x - 1) * 4] += (3 * e) / 16;
					}
				} else if (x == width - 1 && y < height - 1) {
					//下方像素处理
					data[(width * (y + 1) + x) * 4] += (5 * e) / 16;
				} else if (x < width - 1 && y == height - 1) {
					//右边像素处理
					data[(width * y + x + 1) * 4] += (7 * e) / 16;
				}
			}
		}


		return data;
	}


	export default {
		data() {
			return {
				looptime: 0,
				currentTime: 1,
				lastData: 0,
				oneTimeData: 0,
				buffSize: [],
				buffIndex: 0,
				//发送字节数下标
				printNum: [],
				printNumIndex: 0,
				printerNum: 1,
				currentPrint: 1,
				isReceiptSend: false,
				isQuery: false,
				imageSrc: "/static/小票章.png",
				jpgSrc: "/static/小票章.png",
				canvasWidth: 100,
				canvasHeight: 100,
				jpgWidth: 200,
				jpgHeight: 200
			};
		},
		/**
		 * 生命周期函数--监听页面初次渲染完成
		 */
		onReady() {
			var list = [];
			var numList = [];
			var j = 0;
			for (var i = 20; i < 200; i += 10) {
				list[j] = i;
				j++;
			}
			for (var i = 1; i < 10; i++) {
				numList[i - 1] = i;
			}
			this.setData({
				buffSize: list,
				oneTimeData: list[0],
				printNum: numList,
				printerNum: numList[0]
			});
			this.initPhoto();
		},
		/**
		 * 生命周期函数--监听页面卸载
		 */
		onUnload() {
			//关闭蓝牙连接
			// wx.closeBLEConnection({
			//   deviceId: app.BLEInformation.deviceId,
			//   success(res) {
			//     console.log("关闭蓝牙成功")
			//   },
			// })
		},
		/**
		 * 页面相关事件处理函数--监听用户下拉动作
		 */
		onPullDownRefresh() {},
		/**
		 * 页面上拉触底事件的处理函数
		 */
		onReachBottom() {},
		/**
		 * 用户点击右上角分享
		 */
		onShareAppMessage() {},
		methods: {
			setData(i) {
				for (const key in i) {
					if (i.hasOwnProperty(key)) {
						this[key] = i[key];
					}
				}
			},
			initPhoto() {
				//初始化画布数据
				//创建一个png格式
				var that = this;
				const ctx_out = uni.createCanvasContext("canvasOut", this);
				var png = that.imageSrc;
				uni.getImageInfo({
					src: png,


					success(res) {
						that.setData({
							canvasWidth: res.width,
							canvasHeight: res.height
						});
						console.log("画布宽度" + res.width, "画布高度" + res.height);
						ctx_out.drawImage(png, 0, 0, res.width, res.height);
						ctx_out.draw();
					}
				}); //创建一个jpg格式图片
				const ctx_jpg = uni.createCanvasContext("canvasJPG", this);
				var jpg_width = that.jpgWidth;
				var jpg_height = that.jpgHeight;
				var img = that.jpgSrc;
				uni.getImageInfo({
					src: img,
					success(res) {
						that.setData({
							jpgWidth: res.width,
							jpgHeight: res.height
						});
						console.log("JPG画布宽度" + res.width, "JPG画布高度" + res.height);
						ctx_jpg.drawImage(img, 0, 0, res.width, res.height);
						ctx_jpg.draw();
					}
				});
			},
			receiptTest() {
				//票据测试
				var that = this;
				var canvasWidth = that.canvasWidth;
				var canvasHeight = that.canvasHeight;
				var command = esc.jpPrinter.createNew();
				command.init(); //初始化打印机
				command.setSelectJustification(1); //居中
				command.setCharacterSize(17); //设置倍高倍宽
				command.setText("电子收据");
				command.setPrint();
				command.init();
				command.setCharacterSize(0); //设置正常大小
				command.setText("- - - - - - - - - - - - - - - - - - - - - - - - ");
				command.setPrint();
				command.setText(" ");
				command.setPrint();
				
                                command.setSelectJustification(0); //设置 0/居左 1/居中 2/居右
				command.setLineSpace(80)
				command.setText(item);
				command.setPrint(); //打印并换行
				command.setLineSpace(50)
				command.setText(" ");
				command.setPrint()
				command.setText("- - - - - - - - - - - - - - - - - - - - - - - - ");
				command.setPrint();
				command.setText(" ");
				command.setPrint()
				command.setText("居左");
				command.setPrint(); //打印并换行
				command.setSelectJustification(1); //设置居中
				command.setText("居中");
				command.setText("同行打印位置测试:");
				command.setPrint();
				command.setText("居左");
				command.setAbsolutePrintPosition(168);
				command.setText("居中");
				command.setAbsolutePrintPosition(336);
				command.setText("居右");
				command.setPrint();
				command.init(); //初始化打印机


				command.setPrint();
				command.setText("条码打印");
				command.setPrint();
				command.setHRIPosition(2); //设置HRI位置


				command.setHRIFont(0); //HRI字体大小


				command.setBarcodeHeight(60); //条码高度


				command.setBarcodeWidth(2); //设置条码宽度


				command.setAbsolutePrintPosition(24);
				command.setCode128("{A12345678"); //code128  A类型


				command.setPrint();
				command.setText("二维码测试:");
				command.setPrint();
				command.setAbsolutePrintPosition(115);
				command.setSelectSizeOfModuleForQRCode(5);
				command.setSelectErrorCorrectionLevelForQRCode(49);
				command.setStoreQRCodeData("http://www.howbest.cn/cn/");
				command.setPrintQRCode();
				command.setPrint();
				command.init();
				command.setSelectJustification(1);
				command.setText("二维码有效期30天,过期失效");
				command.setPrint();
				command.setText("- - - - - - - - - - - - - - - - - - - - - - - - ");
				command.setPrint();
				command.setText("获取发票说明:用微信扫上方二维码,填写开票信息及邮箱,24小时内发票推送至邮箱");
				command.setPrint();
				command.setText(" ");
				command.setPrint();
				command.setText(" ");
				command.setPrint();
				command.setText(" ");
				command.setPrint();
				command.setText(" ");
				command.setPrint();
				that.prepareSend(command.getData()); //准备发送数据
			},
			printPhoto() {
				//打印bitmap,图片内容不建议太大,小程序限制传输的字节数为20byte
				var that = this;
				var canvasWidth = that.canvasWidth;
				var canvasHeight = that.canvasHeight;
				var command = esc.jpPrinter.createNew();
				command.init(); //初始化打印机


				uni.canvasGetImageData({
					canvasId: "canvasOut",
					x: 0,
					y: 0,
					width: canvasWidth,
					height: canvasHeight,
					success(res) {
						console.log("获取画布数据成功");
						command.setBitmap(res);
						command.setPrint();
						that.prepareSend(command.getData()); //发送数据
					},
					complete(res) {
						console.log("finish");
					},
					fail(res) {
						console.log(res);
						uni.showToast({
							title: "获取画布数据失败",
							icon: "none"
						});
					}
				});
			},
			printJPGPhoto() {
				var that = this;
				var canvasWidth = that.jpgWidth;
				var canvasHeight = that.jpgHeight; //抖动处理JPG图片


				const cfg = {
					x: 0,
					y: 0,
					width: canvasWidth,
					height: canvasHeight
				};
				uni.canvasGetImageData({
					canvasId: "canvasJPG",
					...cfg,
					success: res => {
						//const data = convertToGrayscale(res.data)
						const data = convertToMonoImage(res.width, res.height, res.data, true);
						uni.canvasPutImageData({
							canvasId: "canvasJPG",
							data,
							...cfg,
							success: res => {
								console.log(res);
								console.log("deal graphic width: " + cfg.width);
								console.log("deal graphic width: " + cfg.height);
								that.printerJPG();
							},
							fail: err => {
								console.error(err);
							}
						});
					},
					fail: err => {
						console.error(err);
					}
				});
			},
			printerJPG() {
				var that = this;
				var canvasWidth = that.jpgWidth;
				var canvasHeight = that.jpgHeight;
				var command = esc.jpPrinter.createNew();
				command.init(); //初始化打印机


				uni.canvasGetImageData({
					canvasId: "canvasJPG",
					x: 0,
					y: 0,
					width: canvasWidth,
					height: canvasHeight,
					success(res) {
						console.log("获取画布数据成功");
						command.setBitmap(res);
						command.setPrint();
						that.prepareSend(command.getData()); //发送数据
					},
					complete(res) {
						console.log("finish");
					},
					fail(res) {
						console.log(res);
						uni.showToast({
							title: "获取画布数据失败",
							icon: "none"
						});
					}
				});
			},
			prepareSend(buff) {
				//准备发送,根据每次发送字节数来处理分包数量
				//console.log(buff)
				var that = this;
				var time = that.oneTimeData;
				var looptime = parseInt(buff.length / time);
				var lastData = parseInt(buff.length % time); //console.log(looptime + "---" + lastData)


				that.setData({
					looptime: looptime + 1,
					lastData: lastData,
					currentTime: 1
				});
				that.Send(buff);
			},
			queryStatus() {
				//查询打印机状态
				var that = this;
				var buf;
				var dateView;
				/*
      n = 1:传送打印机状态
      n = 2:传送脱机状态
      n = 3:传送错误状态
      n = 4:传送纸传感器状态
      */


				buf = new ArrayBuffer(3);
				dateView = new DataView(buf);
				dateView.setUint8(0, 16);
				dateView.setUint8(1, 4);
				dateView.setUint8(2, 2);
				uni.writeBLECharacteristicValue({
					deviceId: app.globalData.BLEInformation.deviceId,
					serviceId: app.globalData.BLEInformation.writeServiceId,
					characteristicId: app.globalData.BLEInformation.writeCharaterId,
					value: buf,
					success(res) {
						console.log("发送成功");
						that.setData({
							isQuery: true
						});
					},
					fail(e) {
						uni.showToast({
							title: "发送失败",
							icon: "none"
						}); //console.log(e)


						return;
					},
					complete() {}
				});
				uni.notifyBLECharacteristicValueChange({
					deviceId: app.globalData.BLEInformation.deviceId,
					serviceId: app.globalData.BLEInformation.notifyServiceId,
					characteristicId: app.globalData.BLEInformation.notifyCharaterId,
					state: true,
					success(res) {
						uni.onBLECharacteristicValueChange(function(r) {
							console.log(
								`characteristic ${r.characteristicId} has changed, now is ${r}`
							);
							var result = ab2hex(r.value);
							console.log("返回" + result);
							var tip = "";


							if (result == 12) {
								//正常
								tip = "正常";
							} else if (result == 32) {
								//缺纸
								tip = "缺纸";
							} else if (result == 36) {
								//开盖、缺纸
								tip = "开盖、缺纸";
							} else if (result == 16) {
								tip = "开盖";
							} else if (result == 40) {
								//其他错误
								tip = "其他错误";
							} else {
								//未处理错误
								tip = "未知错误";
							}


							uni.showModal({
								title: "打印机状态",
								content: tip,
								showCancel: false
							});
						});
					},
					fail(e) {
						uni.showModal({
							title: "打印机状态",
							content: "获取失败",
							showCancel: false
						});
						console.log(e);
					},
					complete(e) {
						that.setData({
							isQuery: false
						});
						console.log("执行完成");
					}
				});
			},
			Send(buff) {
				//分包发送
				var that = this;
				var currentTime = that.currentTime;
				var loopTime = that.looptime;
				var lastData = that.lastData;
				var onTimeData = that.oneTimeData;
				var printNum = that.printerNum;
				var currentPrint = that.currentPrint;
				var buf;
				var dataView;


				if (currentTime < loopTime) {
					buf = new ArrayBuffer(onTimeData);
					dataView = new DataView(buf);


					for (var i = 0; i < onTimeData; ++i) {
						dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i]);
					}
				} else {
					buf = new ArrayBuffer(lastData);
					dataView = new DataView(buf);


					for (var i = 0; i < lastData; ++i) {
						dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i]);
					}
				} //console.log("第" + currentTime + "次发送数据大小为:" + buf.byteLength)


				uni.writeBLECharacteristicValue({
					deviceId: app.globalData.BLEInformation.deviceId,
					serviceId: app.globalData.BLEInformation.writeServiceId,
					characteristicId: app.globalData.BLEInformation.writeCharaterId,
					value: buf,
					success(res) {
						if (currentTime <= loopTime) {
							// wx.showLoading({
							//   title: '传输中...',
							// })
						} else {
							uni.showToast({
								title: "已打印第" + currentPrint + "张成功"
							});
						} //console.log(res)
					},
					fail(e) {
						uni.showToast({
							title: "打印第" + currentPrint + "张失败",
							icon: "none"
						}); //console.log(e)
					},
					complete() {
						currentTime++;


						if (currentTime <= loopTime) {
							that.setData({
								currentTime: currentTime
							});
							that.Send(buff);
						} else {
							if (currentPrint == printNum) {
								that.setData({
									looptime: 0,
									lastData: 0,
									currentTime: 1,
									isReceiptSend: false,
									currentPrint: 1
								});
							} else {
								currentPrint++;
								that.setData({
									currentPrint: currentPrint,
									currentTime: 1
								});
								that.Send(buff);
							}
						}
					}
				});
			},
			buffBindChange(res) {
				//更改打印字节数
				var index = res.detail.value;
				var time = this.buffSize[index];
				this.setData({
					buffIndex: index,
					oneTimeData: time
				});
			},
			printNumBindChange(res) {
				//更改打印份数
				var index = res.detail.value;
				var num = this.printNum[index];
				this.setData({
					printNumIndex: index,
					printerNum: num
				});
			}
		}
	};
</script>

其中一些引用文件是esc模式的 网上有来源获取 现在问题是 我尝试过了调用receiptTest中途调用了图片打印的语法打印出来都是乱码和模糊影像连字都没打出来,自己也对小程序蓝牙打印机也是刚接触不是很明白。公司要求携带印章图片打在收据中间区块,有办法解决吗? 急

回答关注问题邀请回答
收藏
登录 后发表内容