金顶项目:扫码入库+lpapi-ble-uni 打印二维码

news/2024/12/23 7:25:19/文章来源:https://www.cnblogs.com/saturday-blog/p/18619453

项目简介

项目需求

  1. 入库出库的数据记录,通过扫码出库入库,入库经过扫码编辑等操作成功入库并打印生成箱码。
  2. 搭配指定打印设备-德佟蓝牙打印机

项目功能

  1. 登录、登出功能。
  2. 扫描毛胚二维码入库、产成品二维码入库、销售二维码出库、材料领用二维码出库
  3. 蓝牙连接打印机设备功能。
  4. 入库成功,打印二维码及简要信息。
  5. 权限访问路由拦截。
  • 除首页,功能页其余页面访问均需要满足登录且登录未过期条件否则跳转到login页面;

登录登出功能

  1. 填写用户信息,密码使用md5加密算法,加密调用登录接口;

入库功能

  1. 毛胚
  • 扫描毛胚二维码的获取编号、名称、数量
  • 查询编号获取毛胚信息进行入库
  • 返回继续扫描入库;
  • 数量可编辑

  1. 产成品
  • 扫描产成品的二维码获取名称、编号、数量
  • 仓库必选,数量可编辑;

入库扫描需要入库的毛胚或产成品,点击提交打包后使用德佟打印机打印出箱码;
扫描进入的数据可整条删除,亦可搜索插入数据。

  1. 扫码使用uniapp接口uni.scanCode调用客户端扫码界面;
  2. 打印使用lpapi-ble-uni基于 UniApp 本身提供的 BLE 接口和 canvas 所封装的标签编辑及蓝牙打印接口,通过 canvas 来按照用户需要进行 2D 绘图,绘制完毕后将图片内容转换为打印机所支持的指令,然后通过 BLE 将数据发送到打印机,然后开始打印图片。

出库功能

  1. 销售出库
  • 扫描入库时生成的箱码根据数据库记录数量判断提示是否出库成功
  • 扫描箱码,仓库必选,输入(选择)客户名称进行出库操作
  1. 材料领用出库
  • 扫描箱码,仓库必选,进行出库操作;
  • 查询编号进行出库;

连接打印机设备功能

  1. 接口包获取
// 1. 下载方式1
npm install lpapi-ble-uni
// 2. 下载方式2 DCloud市场
https://ext.dcloud.net.cn/plugin?id=15493
  1. 导入
// 如果是在cli模式下通过 npm或者yarn安装的插件,则通过如下方式引入接口:
import { LPAPIFactory } from "lpapi-ble-uni";
// 如果是通过插件市场安装的插件,则通本地插件路径导入插件;
import { LPAPIFactory } from "@/uni_modules/DothanTech-LPAPI-BLE/js_sdk/index.js";
  1. 核心代码
    1. 页面结构搭建;
    2. 初始化扫描设备方法
    3. 搜索设备方法
    4. 停止搜索
    5. 进入页面检测蓝牙打开情况
    6. 连接打印机成功跳转页面
点击查看代码
<template><view class="print-layout"><view class="container"><!-- 打印机列表 --><view class="uni-list-cell"><view class="uni-list-cell-left">打印机:</view><view class="uni-list-cell-db"><picker :value="deviceIndex" :range="deviceList" @change="onDeviceChanged" range-key="name"><view class="uni-input">{{ deviceList[deviceIndex].name }}</view></picker></view></view><!-- 二维码界面 --><view class="scan-page"><!-- 隐藏画布,用于标签绘制 --><canvas:id="canvasId":canvas-id="canvasId":style="{ width: labelWidth + 'px', height: labelHeight + 'px' }"style="position: fixed; left: -999999rpx; top: -999999rpx"/></view><!-- 按钮 --><view class="print-btn"><button type="primary" @click="startDiscovery" class="searchBtn">搜索打印机</button><button type="default" @click="stopDiscovery">停止搜索</button><!-- <button type="primary" plain="true" @click="qrcodePrintTest"> 立即打印 </button> --></view>	</view></view></template><script>import { LPAPIFactory , LPA_Result, LPAUtils} from "@/uni_modules/dothan-lpapi-ble/js_sdk/index.js";export default {data() {return {aceptTxt: "PG763883837838",sum:"668",canvasId: "lpapi-ble-uni2",labelWidth: 1000,labelHeight: 1000,deviceIndex: 0,deviceList: [{ name: "未检测到打印机" }],rotationIndex: 0,gapList: [{ name: "随打印机设置", value: 255 },{ name: "小票纸", value: 0 },{ name: "不干胶", value: 2 },{ name: "卡纸", value: 3 },],gapIndex: 0,darknessList: [{ name: "随打印机设置", value: 255 },{ name: "6 (正常)", value: 6 },{ name: "7", value: 7 },{ name: "8", value: 8 },{ name: "9", value: 9 },{ name: "10 (较浓)", value: 10 },{ name: "11", value: 11 },{ name: "12", value: 12 },{ name: "13", value: 13 },{ name: "14", value: 14 },{ name: "15 (最浓)", value: 15 },],darknessIndex: 0,printModes: [{ title: "打印", value: 0 },{ title: "预览", value: 1 },// { title: "透明色", value: 2 },],printMode: 0,isAppPlus: false,isWeiXin: false,isLark: false,isAlipay: false,isDingTalk: false,/*** 图片预览列表* @type {{value: string; key: string;}[]}***/previewList: [],threshold: 128,option: {printerDPI: 0,printMode: 0,},rotationList: [{ name: "横向打印", value: 0 },{ name: "右转90度", value: 90 },{ name: "转转180度", value: 180 },{ name: "左转90度", value: 270 },],speedList: [{ name: "随打印机设置", value: 255 },{ name: "最慢", value: 1 },{ name: "较慢", value: 2 },{ name: "正常", value: 3 },{ name: "较快", value: 4 },{ name: "最快", value: 5 },],speedIndex: 0,}},onReady() {console.log("========== onReady ==========");//this.initApi();},methods: {toUserPage() {uni.switchTab({url: "/pages/user/index"})},// 2. 初始化扫描设备方法initApi() {console.log(`---------- initApi ----------`);this.lpapi = LPAPIFactory.getInstance({showLog: 4, // 日志信息显示级别,值为 0 - 4,0表示不显示调试信息,4表示显示所有调试信息canvasId: this.canvasId, // 用于进行标签绘制的画布ID});// 5. 搜索蓝牙设备this.lpapi.startBleDiscovery({timeout: 0,deviceFound: (devices) => {this.onDeviceFound(devices);},success:(result) => {},fail:(result) => {// todo;uni.showToast({title: '蓝牙未打开',//将值设置为 success 或者直接不用写icon这个参数icon: 'error'})}});},// 4. 停止搜索stopDiscovery() {this.lpapi.stopBleDiscovery();uni.showLoading({title: "停止搜索",});setTimeout(function () {uni.hideLoading();}, 1000);},onDeviceChanged(e) {console.log(`---------- onDeviceChanged:${e.detail.value} ----------`);this.deviceIndex = e ? e.detail.value : 0;console.log(this.deviceIndex);},// 3. 搜索设备方法startDiscovery(e) {console.log(e,this.lpapi);uni.showLoading({title: "正在搜索打印机...",});console.log(this.lpapi);this.lpapi.startBleDiscovery({timeout: 5000,deviceFound: (devices) => {this.onDeviceFound(devices);},adapterStateChange: (result) => {if (!result.discovering) {uni.hideLoading();}},});},onPrintModeChanged(e) {console.log(`---------- onPrintModeChanged: ${e.detail.value} ----------`);this.option.printMode = Number(e.detail.value);},onDeviceFound(devices) {console.log(`---- 检测到打印机:`);console.log('hello',devices);if (devices && devices.length > 0) {this.deviceList.splice(0);for (let item of devices) {this.deviceList.push(item);}}// 6. 连接打印机成功跳转页面 ,设置定时跳转页面;uni.showLoading({title: "打印机已链接,回到个人中心",});const _this = this;setTimeout(function () {uni.hideLoading();_this.toUserPage();}, 2000);},checkAndOpenPrinter() {return new Promise((resolve) => {if (this.printMode > 0) {// 预览模式不需要链接打印机resolve(true);} else {// 打印模式自动链接打印机this.openPrinter((res) => {resolve(res);});}});},openPrinter(callback) {const currDevice = this.getDevice();const isAlipay = this.isAlipay;if (currDevice && currDevice.deviceId) {//uni.showLoading({title: "正在链接打印机...",});this.lpapi.openPrinter({name: currDevice.name,deviceId: currDevice.deviceId,// 如果打印机链接失败的话,可以尝试连续进行多次链接。tryTimes: isAlipay ? 1 : 5,success: (resp) => {console.log(`---- 【打印机链接成功】`);uni.showModal({content: "打印机链接成功",showCancel: false});console.log(resp.resultInfo);uni.hideLoading();//uni.showToast({ title: "打印机链接成功!", icon: "success" });if (typeof callback === "function") {callback(true);}},fail: (resp) => {console.warn(`---- 【打印机链接失败】:`);console.warn(JSON.stringify(resp));//uni.hideLoading();//uni.showToast({ title: "打印机链接失败!", icon: "fail" });if (typeof callback === "function") {callback(false);}},});} else {console.warn("---- 未检测到打印机!");uni.showToast({ title: "未检测到打印机", icon: "fail" });if (typeof callback === "function") {callback(false);}}},updateCanvas(jobInfo) {// 飞书小程序打印适配// #ifdef MP-LARKthis.processForLark(jobInfo);// #endif// 如果通过 createSelectorQuery 获取到了 Canvas 实例,则不需要延迟处理;// 在微信小程序、支付宝小程序中是支持该功能的;return new Promise((resolve) => {if (!this.printCanvas) {// 更新canvas大小;this.labelWidth = jobInfo.canvas.width;this.labelHeight = jobInfo.canvas.height;// 等 Canvas 大小更新后在执行后续绘制操作;setTimeout(() => {resolve(true);}, 100);} else {resolve(true);}});},getOrientation() {return this.rotationList[this.rotationIndex].value;},getJobName() {if (this.printMode === 1) {return "#!#preview#!#";} else if (this.printMode === 2) {return "#!#transparent#!#";} else {return "lpapi-ble";}},getGapType() {return this.gapList[this.gapIndex].value;},getPrintDarkness() {return this.darknessList[this.darknessIndex].value;},getPrintSpeed() {return this.speedList[this.speedIndex].value;},previewLabel(result) {console.log(`----- 打印结果:${result.statusCode} -----`);console.log(JSON.stringify(Object.keys(result)));if (result.statusCode === 0) {this.previewList.splice(0);result.dataUrls.forEach((value) => {console.log(`dataUrl: ${value}`);this.previewList.push({value: value,// 为了保证 v-for循环的唯一性,随便生成一个随机IDkey: `${new Date().getTime()}-${Math.random() * 1000}`,});});} else {//console.warn(`---- 打印/预览失败,statusCode: ${result.statusCode} ----`);}},getDevice() {return this.deviceList[this.deviceIndex];},qrcodePrintTest(data, callback) {const api = this.lpapi;const labelWidth = 40;const labelHeight = 30;const margin = 2;// 二维码底部文本的高度const textHeight = 4;// 二维码大小const codeWidth = labelHeight - margin * 2 - textHeight;const text = typeof data === "string" ? data : "www.dothantech.com";console.log('1');//return this.checkAndOpenPrinter().then(() => {// 创建 40mm x 30mm 大小的标签纸const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//return this.updateCanvas(jobInfo).then(() => {// 绘制二维码api.draw2DQRCode({text: text,x: (labelWidth - codeWidth) * 0.5,y: margin,width: codeWidth,});// 以文本形式,将二维码内容绘制到二维码底部api.drawText({text: text,x: 0,y: margin + codeWidth,width: labelWidth,height: textHeight,fontHeight: 3.5,horizontalAlignment: this.isLark ? 0 : 1,});//return api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);// 执行打印完毕回调函数if (typeof callback === "function") {callback(true);}return resp.statusCode === 0;});});});},}	}
</script>
<style lang="scss" scoped>.print-layout{height: 100%;.container {height: 100%;display: flex;flex-direction: column;justify-content: space-between;.uni-list-cell {display: flex;margin-top: 20px;padding-left: 20px;.uni-list-cell-left {line-height: 25px;}.uni-input {width: 200px;height: 25px;text-indent: 1em;border: 1px solid #ddd;line-height: 25px;border-radius: 5px 5px 5px 5px;}}.print-btn {padding: 10px;.searchBtn {margin-bottom: 20px;}}}}</style>

二维码打印的格式调整;

  1. 页面创建,canvas画布创建
  2. 画布大小,二维码宽度,边据,字体大小样式,对齐方式
  3. 结构及逻辑核心代码
点击查看代码
// 1. 页面创建,canvas画布创建
<template><view class="print-layout"><view class="container"><!-- 二维码界面 --><view class="scan-page"><!-- 隐藏画布,用于标签绘制 --><canvas:id="canvasId":canvas-id="canvasId":style="{ width: labelWidth + 'px', height: labelHeight + 'px' }"style="position: fixed; left: -999999rpx; top: -999999rpx"/></view><!-- 按钮 --><view class="print-btn"><button type="primary" plain="true" @click="qrcodePrintTest"> 立即打印 </button></view>		<view class=""><!-- 详情 --></view></view></view></template>
<script>
import { LPAPIFactory , LPA_Result, LPAUtils} from "@/uni_modules/dothan-lpapi-ble/js_sdk/index.js";
methods: {initApi() {console.log(`---------- initApi ----------`);this.lpapi = LPAPIFactory.getInstance({showLog: 4, // 日志信息显示级别,值为 0 - 4,0表示不显示调试信息,4表示显示所有调试信息canvasId: this.canvasId, // 用于进行标签绘制的画布ID});// 搜索蓝牙设备this.lpapi.startBleDiscovery({timeout: 0,deviceFound: (devices) => {this.onDeviceFound(devices);},// 蓝牙设备调用失败处理。fail:(result) => {// todo;uni.showToast({title: '蓝牙未打开',//将值设置为 success 或者直接不用写icon这个参数icon: 'error'})}});},
// 3. 结构及逻辑核心代码:扫码功能,及代码实现;
qrcodePrintTest(data, callback) {const api = this.lpapi;// 2. 创建容器大小const labelWidth = 40;const labelHeight = 80;const margin = 2;// 二维码底部文本的高度const textHeight = 8;// 2. 二维码宽度const codeWidth = labelHeight - margin * 2 - textHeight;// const text = "你好,我想下班"if (!this.aceptTxt.trim() ){uni.showToast({ title: "打印内容为空,打印失败", icon: "fail" });return}// const text = typeof data === "string" ? data : "你好,我想下班";//return this.checkAndOpenPrinter().then(() => {// 创建 40mm x 60mm 大小的标签纸const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}// 2. 边据,字体大小样式,对齐方式return this.updateCanvas(jobInfo).then(() => {// 以文本形式,将二维码内容绘制到二维码底部api.drawText({text: "包装编号",x: 5,y: 7,width: labelWidth,height: textHeight,horizontalAlignment: 0,verticalAlignment: 0,fontHeight: 5,// 常规字体样式fontStyle: 1,});api.drawText({text: this.aceptTxt,x: 5,y: 14,width: labelWidth,height: textHeight,horizontalAlignment: 0,verticalAlignment: 0,fontHeight: 5,// 常规字体样式fontStyle: 1,});api.drawText({text: "总数",x: 5,y: 22,width: labelWidth,height: textHeight,horizontalAlignment: 0,verticalAlignment: 0,fontHeight: 5,// 常规字体样式fontStyle: 1,});api.drawText({text: this.sum,x: 5,y: 29,width: labelWidth,height: textHeight,horizontalAlignment: 0,verticalAlignment: 0,fontHeight: 5,// 常规字体样式fontStyle: 1,});// 绘制二维码api.draw2DQRCode({text: this.aceptTxt,x: 5,y: 37,width: 32,});//return api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);// 执行打印完毕回调函数if (typeof callback === "function") {callback(true);}return resp.statusCode === 0;});});});},
}
</script>

参考文档

pnpm install lpapi-ble-uni
  1. 核心代码
点击查看代码
<template><view><view class="uni-list"><!-- 隐藏画布,用于标签绘制 --><canvas:id="canvasId":canvas-id="canvasId"type="2d":style="{ width: labelWidth + 'px', height: labelHeight + 'px' }"style="position: fixed; left: -999999rpx; top: -999999rpx"/><!-- 打印机列表 --><view class="uni-list-cell"><view class="uni-list-cell-left">打印机:</view><view class="uni-list-cell-db"><picker :value="deviceIndex" :range="deviceList" @change="onDeviceChanged" range-key="name"><view class="uni-input">{{ deviceList[deviceIndex].name }}</view></picker></view></view><!-- 出纸方向 --><view class="uni-list-cell"><view class="uni-list-cell-left">出纸方向:</view><view class="uni-list-cell-db"><picker :value="rotationIndex" :range="rotationList" @change="onRotationChanged" range-key="name"><view class="uni-input">{{ rotationList[rotationIndex].name }}</view></picker></view></view><!-- 标签纸类型 --><view class="uni-list-cell"><view class="uni-list-cell-left">纸张类型:</view><view class="uni-list-cell-db"><picker :value="gapIndex" :range="gapList" @change="onGapTypeChanged" range-key="name"><view class="uni-input">{{ gapList[gapIndex].name }}</view></picker></view></view><!-- 打印浓度 --><view class="uni-list-cell"><view class="uni-list-cell-left">打印浓度:</view><view class="uni-list-cell-db"><picker :value="darknessIndex" :range="darknessList" @change="onDarknessChanged" range-key="name"><view class="uni-input">{{ darknessList[darknessIndex].name }}</view></picker></view></view><!-- 打印速度 --><view class="uni-list-cell"><view class="uni-list-cell-left">打印速度:</view><view class="uni-list-cell-db"><picker :value="speedIndex" :range="speedList" @change="onPrintSpeedChanged" range-key="name"><view class="uni-input">{{ speedList[speedIndex].name }}</view></picker></view></view><!-- 打印或预览 --><view class="uni-list-cell"><view class="uni-list-cell-left">预览模式:</view><radio-group @change="onPrintModeChanged" style="padding: 10px"><label v-for="(item, index) in printModes" :key="item.value"><radio :value="item.value" :checked="item.value === printMode"></radio><text>{{ item.title }}</text></label></radio-group></view><!-- 图片处理灰度阈值 --><view class="uni-list-cell"><view class="uni-list-cell-left">灰度阈值:</view><view class="uni-list-cell-db"><input class="uni-input" type="number" v-model="threshold" /></view></view></view><view class="uni-padding-wrap uni-common-mt"><!-- 设备搜索 --><button type="primary" @click="startDiscovery">开始搜索打印机</button><button type="primary" @click="stopDiscovery">停止搜索打印机</button><!-- 链接打印机 --><button type="primary" @click="openPrinter">打开打印机</button><button type="primary" @click="closePrinter">关闭打印机</button><!-- 标签编辑及打印 --><button type="primary" plain="true" @click="textPrintTest">文本绘制打印测试</button><button type="primary" plain="true" @click="qrcodePrintTest">QRCode二维码打印测试</button><button type="primary" plain="true" @click="pdf417PrintTest">PDF417二维码打印测试</button><button type="primary" plain="true" @click="dataMatrixPrintTest">DataMatrix二维码打印测试</button><button type="primary" plain="true" @click="barcodePrintTest">一维码打印测试</button><button type="primary" plain="true" @click="localImagePrintTest">本地图片打印测试</button><button type="primary" plain="true" @click="remoteImagePrintTest">网络图片打印测试</button><button type="primary" plain="true" @click="rectanglePrintTest">矢量图绘制打印测试</button><button type="primary" plain="true" @click="alignmentPrintTest">文本对齐打印测试</button><button type="primary" plain="true" @click="rotationPrintTest">文本旋转打印测试</button><button type="primary" plain="true" @click="tablePrintTest">表格绘制及打印测试</button><button type="primary" plain="true" @click="jsonPrintTest">JSON数据批量打印测试</button><button type="primary" plain="true" @click="dataBindPrintTest">JSON数据绑定及批量打印</button><button type="primary" plain="true" @click="wdfxPrintTest">WDFX数据打印测试</button><button type="primary" plain="true" @click="multiPagePrintTest">多页(循环)打印测试</button><button type="primary" plain="true" @click="base64PrintTest">BASE64图片打印测试</button><button type="primary" plain="true" @click="gotoOtherPage">跳转到其他页面</button><!-- <button type="primary" plain="true" @click="gotoMultiCanvasPreview">多Canvas预览</button> --><!-- #ifdef APP-PLUS || H5 --><!-- <button type="primary" plain="true" @click="gotoRenderPage">跳转到RenderJs页面</button> --><!-- #endif --></view><view style="text-align: center; padding: 10px"><view style="margin: 10px; border: solid lightgray 1px"><imagev-for="item in previewList":src="item.value":key="item.key"class="image"mode="widthFix"style="margin: 10rpx; border: dashed lightgray 1px"/></view></view></view>
</template><script>
import { LPAPIFactory, LPA_Result, LPAUtils } from "@/uni_modules/dothan-lpapi-ble/js_sdk/index.js";
// import { LPAPI, LPAPIFactory } from "lpapi-ble-uni";
import { DOMParser } from "../../node_modules/xmldom";
import { wdfxStr, imgSrc } from "./resource.js";// /**
//  * 在多设备链接的情况下,UniAPP的 onBLECharacteristicValueChange 接口有个bug,调用该函数的时候会替换掉前面设置的特征值回调函数。
//  * 为了解决该问题,建议用户对该函数的调用进行统一处理,保证全局只调用一次。
//  */
// const bleAdapter = {
//     onBLECharacteristicValueChange: (callback, characteristicId) => {
//         uni.onBLECharacteristicValueChange(callback);
//     },
// };//
export default {data() {return {aceptText: "",canvasId: "lpapi-ble-uni1",labelWidth: 960,labelHeight: 960,deviceList: [{ name: "未检测到打印机" }],rotationIndex: 0,rotationList: [{ name: "横向打印", value: 0 },{ name: "右转90度", value: 90 },{ name: "转转180度", value: 180 },{ name: "左转90度", value: 270 },],deviceIndex: 0,gapList: [{ name: "随打印机设置", value: 255 },{ name: "小票纸", value: 0 },{ name: "不干胶", value: 2 },{ name: "卡纸", value: 3 },],gapIndex: 0,darknessList: [{ name: "随打印机设置", value: 255 },{ name: "6 (正常)", value: 6 },{ name: "7", value: 7 },{ name: "8", value: 8 },{ name: "9", value: 9 },{ name: "10 (较浓)", value: 10 },{ name: "11", value: 11 },{ name: "12", value: 12 },{ name: "13", value: 13 },{ name: "14", value: 14 },{ name: "15 (最浓)", value: 15 },],darknessIndex: 0,speedList: [{ name: "随打印机设置", value: 255 },{ name: "最慢", value: 1 },{ name: "较慢", value: 2 },{ name: "正常", value: 3 },{ name: "较快", value: 4 },{ name: "最快", value: 5 },],speedIndex: 0,printModes: [{ title: "打印", value: 0 },{ title: "预览", value: 1 },// { title: "透明色", value: 2 },],printMode: 1,isAppPlus: false,isWeiXin: false,isLark: false,isAlipay: false,isDingTalk: false,/*** 图片预览列表* @type {{value: string; key: string;}[]}***/previewList: [],threshold: 128,};},onLoad() {console.log("========== onLoad  ==========");// #ifdef APP-PLUSthis.isAppPlus = true;// #endif// #ifdef MP-ALIPAYthis.isAlipay = true;// #endif// #ifdef MP-LARKthis.isLark = true;// #endif// #ifdef MP-WEIXINthis.isWeiXin = true;// #endif// #ifdef MP-DINGTALKthis.isDingTalk = true;// #endif//this.lpapi = LPAPIFactory.getInstance({// 日志信息显示级别,值为 0 - 4,0表示不显示调试信息,4表示显示所有调试信息// showLog: 4,// 钉钉小程序需要备注下,UniApp无法识别钉钉小程序。isDingTalk: this.isAlipay ? true : false,// bleAdapter: bleAdapter,});// 搜索蓝牙设备this.lpapi.startBleDiscovery({timeout: 0, deviceFound: (devices) => {this.onDeviceFound(devices);}});},onShow() {console.log("========== onShow  ==========");// 跳转到其他页面,然后返回当前页面后,必须更新 lpapi示例中的 绘制上下文,否则绘制上下文错误的话就无法正常绘制了。if (this.context) {this.lpapi.setDrawContext(this.context);}},mounted() {console.log("========== mounted ==========");},onReady() {console.log("========== onReady ==========");uni.getSystemInfo({complete: (res) => {this.systemInfo = res;},});// 微信小程序、支付宝小程序需要通过 createSelectorQuery 来获取Canvas实例。if (this.isWeiXin || this.isAlipay) {setTimeout(() => {this.queryCanvas((canvas) => {this.createDrawContext(canvas);});}, 100);} else {this.createDrawContext();}},onUnload() {console.log("========== onUnload  ==========");this.closePrinter();},methods: {queryCanvas(callback) {// 微信小程序、支付宝小程序等 最新版本初始化方式// 注意:canvas 中必须配置 type="2d" 才能生效。try {uni.createSelectorQuery().select(`#${this.canvasId}`).node().exec((res) => {console.log(`------- exec.result: --------`);console.log(res);const canvas = res[0]?.node;this.printCanvas = canvas;callback(canvas);});} catch (e) {console.warn(`---- 不支持通过该方式获取 Canvas 对象!`);console.warn(e);callback(undefined);}},onDeviceChanged(e) {console.log(`---------- onDeviceChanged:${e.detail.value} ----------`);this.deviceIndex = e ? e.detail.value : 0;},onRotationChanged(e) {console.log(`---------- onRotationChanged: ${e.detail.value} ----------`);this.rotationIndex = e ? e.detail.value : 0;},onGapTypeChanged(e) {console.log(`---------- onGapTypeChanged:${e.detail.value} ----------`);this.gapIndex = e ? e.detail.value : 0;},onDarknessChanged(e) {console.log(`---------- onDarknessChanged:${e.detail.value} ----------`);this.darknessIndex = e ? e.detail.value : 0;},onPrintSpeedChanged(e) {console.log(`---------- onPrintSpeedChanged:${e.detail.value} ----------`);this.speedIndex = e ? e.detail.value : 0;},onPrintModeChanged(e) {console.log(`---------- onPrintModeChanged: ${e.detail.value} ----------`);this.printMode = Number(e.detail.value);},createDrawContext(canvas) {console.log(`---------- initApi ----------`);if (this.isWeiXin || this.isAlipay) {this.context = this.lpapi.createDrawContext({canvas: canvas,canvasId: this.canvasId,});} else {this.context = this.lpapi.createDrawContext({canvasId: this.canvasId,});}//this.lpapi.setDrawContext(this.context);},isAndroid() {const osName = this.mSystemInfo.osName || this.mSystemInfo.platform || "";return osName.toLowerCase() === "android";},gotoOtherPage() {uni.navigateTo({url: "/pages/page2/index",});},gotoRenderPage() {uni.navigateTo({url: "/pages/render/index",});},gotoMultiCanvasPreview() {uni.navigateTo({url: "/pages/page3/index",});},startDiscovery() {uni.showLoading({title: "正在搜索打印机...",});this.lpapi.startBleDiscovery({timeout: 5000,deviceFound: (devices) => {this.onDeviceFound(devices);},adapterStateChange: (result) => {if (!result.discovering) {uni.hideLoading();}},});},stopDiscovery() {getDevicethis.lpapi.stopBleDiscovery();},getDevice() {return this.deviceList[this.deviceIndex];},openPrinter(callback) {const currDevice = this.getDevice();const isAlipay = this.isAlipay;if (currDevice && currDevice.deviceId) {//uni.showLoading({title: "正在链接打印机...",});this.lpapi.openPrinter({name: currDevice.name,deviceId: currDevice.deviceId,// 如果打印机链接失败的话,可以尝试连续进行多次链接。tryTimes: isAlipay ? 1 : 5,success: (resp) => {console.log(`---- 【打印机链接成功】`);console.log(resp.resultInfo);uni.hideLoading();//uni.showToast({ title: "打印机链接成功!", icon: "success" });if (typeof callback === "function") {callback(true);}},fail: (resp) => {console.warn(`---- 【打印机链接失败】:`);console.warn(JSON.stringify(resp));//uni.hideLoading();//uni.showToast({ title: "打印机链接失败!", icon: "fail" });if (typeof callback === "function") {callback(false);}},});} else {console.warn("---- 未检测到打印机!");uni.showToast({ title: "未检测到打印机", icon: "fail" });if (typeof callback === "function") {callback(false);}}},closePrinter() {console.log(`---- 关闭打印机!`);this.lpapi.closePrinter();},onDeviceFound(devices) {console.log(`---- 检测到打印机:`);console.log(devices);if (devices && devices.length > 0) {this.deviceList.splice(0);for (let item of devices) {this.deviceList.push(item);//const advertisData = item.advertisData ? new Uint8Array(item.advertisData) : undefined;const advDataStr = advertisData ? LPAUtils.getHexStringOfBytes(advertisData) : "-";console.log(`---- advertisData [${item.name}] : [${advDataStr}]`);}}},getJobName() {if (this.printMode === 1) {return "#!#preview#!#";} else if (this.printMode === 2) {return "#!#transparent#!#";} else {return "lpapi-ble";}},isPrintJob() {return this.printMode > 2 || this.printMode < 1;},getOrientation() {return this.rotationList[this.rotationIndex].value;},getGapType() {return this.gapList[this.gapIndex].value;},getPrintDarkness() {return this.darknessList[this.darknessIndex].value;},getPrintSpeed() {return this.speedList[this.speedIndex].value;},getThreshold() {return Number(this.threshold);},/*** @returns {Promise<boolean>}*/checkAndOpenPrinter() {return new Promise((resolve) => {if (this.printMode > 0) {// 预览模式不需要链接打印机resolve(true);} else {// 打印模式自动链接打印机this.openPrinter((res) => {resolve(res);});}});},previewLabel(result) {console.log(`----- 打印结果:${result.statusCode} -----`);console.log(JSON.stringify(Object.keys(result)));if (result.statusCode === 0) {this.previewList.splice(0);result.dataUrls.forEach((value) => {console.log(`dataUrl: ${value}`);this.previewList.push({value: value,// 为了保证 v-for循环的唯一性,随便生成一个随机IDkey: `${new Date().getTime()}-${Math.random() * 1000}`,});});} else {//console.warn(`---- 打印/预览失败,statusCode: ${result.statusCode} ----`);}},clearPreview() {this.previewList.splice(0);},appendPreview(result) {console.log(`---- appendPreview, statusCode: ${result.statusCode}`);if (result && result.statusCode === 0) {console.log(`dataUrl: ${result.dataUrl}`);const dataUrl = result.dataUrl;if (dataUrl) {this.previewList.push({value: dataUrl,key: `${new Date().getTime()}-${Math.random() * 1000}`,});}}},updateCanvas(jobInfo) {// 飞书小程序打印适配// #ifdef MP-LARKthis.processForLark(jobInfo);// #endif// 如果通过 createSelectorQuery 获取到了 Canvas 实例,则不需要延迟处理;// 在微信小程序、支付宝小程序中是支持该功能的;return new Promise((resolve) => {if (!this.printCanvas) {// 更新canvas大小;this.labelWidth = jobInfo.canvas.width;this.labelHeight = jobInfo.canvas.height;// 等 Canvas 大小更新后在执行后续绘制操作;setTimeout(() => {resolve(true);}, 100);} else {resolve(true);}});},processForLark(result) {// 飞书小程序适配;// 	1. 在飞书小程序中通过 canvasGetImageData 获取到的打印数据是错误的,canvas中左上角的部分被放大了//		临时的解决方案是在绘制过程中,将内容缩小处理;//	2. 在飞书小程序的 canvas 中不支持 measureText 方法,字符串宽度计算的时候返回的是0,所以暂时不支持字符串对齐、字符串换行等功能;// 获取当前绘制内容的分辨率const dpi = result.dpi;if (this.isLark && this.lpapi && this.isPrintJob()) {if (this.isAndroid()) {this.lpapi.getCanvas().Dpi = dpi * 0.33;} else {this.lpapi.getCanvas().Dpi = dpi * 0.5;}}},textPrintTest() {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 30;const text1 = "上海道臻信息技术有限公司http://www.dothantch.com";// 将整个标签高度平均分成4个区域,分别显示四种绘制模式const cellHeight = labelHeight / 4;// 如果打印机未连接,则自动链接打印机return this.checkAndOpenPrinter().then(() => {let pos = 0;// 创建 40mm x 30mm 大小标签的打印任务;const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return false;}//return this.updateCanvas(jobInfo).then(() => {// 1. 最简单的绘制方式:只需要指定绘制内容和字体高度即可,默认绘制在左上角,字体高度为3毫米;api.drawText({text: text1,fontHeight: 3,});// 分割线pos += cellHeight;api.drawLine({x1: 0,y1: pos,x2: labelWidth,y2: pos,lineWidth: 0.3,});// 2. 通过指定绘制区域的宽度,来进行换行处理;api.drawText({text: text1,x: 0,y: pos,width: labelWidth,fontHeight: 3,});// 分割线pos += cellHeight;api.drawLine({x1: 0,y1: pos,x2: labelWidth,y2: pos,lineWidth: 0.3,});// 3. 不要自动换行,通过压缩方式将数据显示到一行api.drawText({text: text1,x: 0,y: pos,width: labelWidth,autoReturn: 0,fontHeight: 3,});// 分割线pos += cellHeight;api.drawLine({x1: 0,y1: pos,x2: labelWidth,y2: pos,lineWidth: 0.3,});// 4. 当文本内容超多的时候,可以通过指定显示区域的高度,来进行字体的自动缩小处理;如果不需要自动缩小,可以不指定宽度;api.drawText({text: text1,x: 0,y: pos,width: labelWidth,height: cellHeight,fontHeight: 3,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},qrcodePrintTest(data, callback) {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 30;const margin = 2;// 二维码底部文本的高度const textHeight = 4;// 二维码大小const codeWidth = labelHeight - margin * 2 - textHeight;const text = typeof data === "string" ? data : "www.dothantech.com";//return this.checkAndOpenPrinter().then(() => {// 创建 40mm x 30mm 大小的标签纸const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//return this.updateCanvas(jobInfo).then(() => {// 绘制二维码api.draw2DQRCode({text: text,x: (labelWidth - codeWidth) * 0.5,y: margin,width: codeWidth,});// 以文本形式,将二维码内容绘制到二维码底部api.drawText({text: text,x: 0,y: margin + codeWidth,width: labelWidth,height: textHeight,fontHeight: 3.5,horizontalAlignment: this.isLark ? 0 : 1,});//return api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);// 执行打印完毕回调函数if (typeof callback === "function") {callback(true);}return resp.statusCode === 0;});});});},pdf417PrintTest() {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 30;const margin = 2;const text = "上海道臻信息技术有限公司";const textHeight = 4;const codeHeight = labelHeight - margin * 2 - textHeight;//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return false;}//return this.updateCanvas(jobInfo).then(() => {api.draw2DPdf417({text: text,x: margin,y: margin,width: labelWidth - margin * 2,height: codeHeight,});//api.drawText({text: text,x: 0,y: margin + codeHeight,width: labelWidth,height: textHeight,fontHeight: 3.5,horizontalAlignment: this.isLark ? 0 : 1,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},dataMatrixPrintTest() {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 30;const textHeight = 4;const margin = 2;const codeWidth = labelHeight - margin * 2 - textHeight;const text = "上海道臻信息技术有限公司";//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return false;}//return this.updateCanvas(jobInfo).then(() => {api.draw2DDataMatrix({text: text,x: (labelWidth - codeWidth) * 0.5,y: margin,width: codeWidth,height: codeWidth,});api.drawText({text: text,x: 0,y: margin + codeWidth,width: labelWidth,height: textHeight,fontHeight: 3.5,horizontalAlignment: this.isLark ? 0 : 1,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},barcodePrintTest() {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 30;const margin = 2;//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//return this.updateCanvas(jobInfo).then(() => {// 绘制外边框api.drawRectangle({width: labelWidth,height: labelHeight,});api.draw1DBarcode({text: "12345678",x: margin,y: margin,width: labelWidth - margin * 2,height: labelHeight - margin * 2,textHeight: 5,type: 22,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},localImagePrintTest() {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 40;const margin = 2;const url = "/static/yinlifun.png";//return this.checkAndOpenPrinter().then(() => {api.loadImage(url).then((image) => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//this.updateCanvas(jobInfo).then(() => {// 绘制标签外边框api.drawRectangle({width: labelWidth,height: labelHeight,lineWidth: 0.3,});// 绘制图片api.drawImage({image: image,x: margin,y: margin,width: labelWidth - margin * 2,height: labelHeight - margin * 2,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),threshold: this.getThreshold(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});});},remoteImagePrintTest() {const api = this.lpapi;//const labelWidth = 30;const labelHeight = 30;const margin = 2;const url = "https://www.detonger.com/img/QRCode_OfficialAccounts.png";//return this.checkAndOpenPrinter().then(() => {api.loadImage(url).then((image) => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//this.updateCanvas(jobInfo).then(() => {// 绘制标签外边框api.drawRectangle({width: labelWidth,height: labelHeight,lineWidth: 0.3,});// 绘制图片api.drawImage({image: image,x: margin,y: margin,width: labelWidth - margin * 2,height: labelHeight - margin * 2,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),threshold: this.getThreshold(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});});},rectanglePrintTest() {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 30;const itemWidth = labelWidth * 0.5;const itemHeight = labelHeight * 0.5;const margin = 1;const padding = 2;const lineWidth = 0.3;//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: this.getOrientation(),jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//this.updateCanvas(jobInfo).then(() => {// 绘制中间横线api.drawLine({x1: 0,y1: itemHeight,x2: labelWidth,y2: itemHeight,lineWidth: 0.3,});// 绘制中间竖线(绘制虚线)api.drawLine({x1: itemWidth,y1: 0,x2: itemWidth,y2: labelHeight,lineWidth: 0.3,dashLens: [1, 0.5],});//====================================================////===== 常规矩形测试//====================================================//// 在左上角绘制矩形框api.drawRectangle({x: margin,y: margin,width: itemWidth - margin * 2,height: itemHeight - margin * 2,lineWidth: lineWidth,});// 左上角绘制填充矩形api.drawRectangle({x: margin + padding,y: margin + padding,width: itemWidth - (margin + padding) * 2,height: itemHeight - (margin + padding) * 2,fill: true,});//====================================================////===== 圆角矩形测试//====================================================//// 在右上角绘制圆角矩形框api.drawRectangle({x: margin + itemWidth,y: margin,width: itemWidth - margin * 2,height: itemHeight - margin * 2,lineWidth: lineWidth,cornerWidth: 1.5,});// 左上角绘制填充矩形api.drawRectangle({x: margin + padding + itemWidth,y: margin + padding,width: itemWidth - (margin + padding) * 2,height: itemHeight - (margin + padding) * 2,fill: true,cornerWidth: 1.5,});//====================================================////===== 椭圆测试//====================================================//// 在右上角绘制圆角矩形框api.drawEllipse({x: margin,y: margin + itemHeight,width: itemWidth - margin * 2,height: itemHeight - margin * 2,lineWidth: lineWidth,});// 左上角绘制填充矩形api.drawEllipse({x: margin + padding,y: margin + padding + itemHeight,width: itemWidth - (margin + padding) * 2,height: itemHeight - (margin + padding) * 2,fill: true,});//====================================================////===== 正圆测试//====================================================//// 在右下角绘制圆形边框api.drawCircle({x: itemWidth * 1.5,y: itemHeight * 1.5,radius: Math.min(itemWidth, itemHeight) * 0.5 - margin,});// 左下角绘制填充圆形api.drawCircle({x: itemWidth * 1.5,y: itemHeight * 1.5,radius: Math.min(itemWidth, itemHeight) * 0.5 - margin - padding,fill: true,});// 提交任务api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},alignmentPrintTest() {const api = this.lpapi;//const labelWidth = 60;const labelHeight = 40;const itemWidth = labelWidth * 0.5;const itemHeight = labelHeight * 0.5;const text = "上海道臻信息技术有限公司";const fontHeight = 4;// 标签整体右转90度const orientation = 90;//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: orientation,jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//this.updateCanvas(jobInfo).then(() => {// 将正张标签分割成四个显示区域api.drawRectangle({x: 0,y: 0,width: labelWidth,height: labelHeight,lineWidth: 0.3,});api.drawLine({y1: itemHeight,x2: labelWidth,lineWidth: 0.3,});api.drawLine({x1: itemWidth,y2: labelHeight,lineWidth: 0.3,});// 水平居左,垂直居右对齐api.drawText({text: text,x: 0,y: 0,width: itemWidth,height: itemHeight,horizontalAlignment: 0,verticalAlignment: 0,fontHeight: fontHeight,// 常规字体样式fontStyle: 0,});// 水平居中,垂直居中api.drawText({text: text,x: itemWidth,y: 0,width: itemWidth,height: itemHeight,horizontalAlignment: 1,verticalAlignment: 1,fontHeight: fontHeight,// 字体样式:黑体fontStyle: 1,});// 水平居右,垂直居下api.drawText({text: text,x: itemWidth,y: itemHeight,width: itemWidth,height: itemHeight,horizontalAlignment: 2,verticalAlignment: 2,fontHeight: fontHeight,// 字体样式:斜体fontStyle: 2,});// 水平拉伸,垂直拉伸api.drawText({text: text,x: 0,y: itemHeight,width: itemWidth,height: itemHeight,horizontalAlignment: 3,verticalAlignment: 3,fontHeight: fontHeight,// 字体样式:粗斜体fontStyle: 3,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},rotationPrintTest() {const api = this.lpapi;//const labelWidth = 60;const labelHeight = 40;const itemWidth = labelWidth * 0.5;const itemHeight = labelHeight * 0.5;const orientation = 90;const text = "上海道臻信息技术有限公司";//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: orientation,jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//this.updateCanvas(jobInfo).then(() => {// 将整个打印区域分割成四个区域,分别进行四种旋转测试api.drawRectangle({width: labelWidth,height: labelHeight,lineWidth: 0.3,});api.drawLine({y: itemHeight,width: labelWidth,height: 0.3,});api.drawLine({x: itemWidth,width: 0.3,height: labelHeight,});//api.drawText({text: text,x: 0,y: 0,width: itemWidth,height: itemHeight,// 0:表示不旋转orientation: 0,fontHeight: 4,});//api.drawText({text: text,x: itemWidth,y: 0,width: itemWidth,height: itemHeight,// 90:表示右转90度orientation: 90,fontHeight: 4,});//api.drawText({text: text,x: itemWidth,y: itemHeight,width: itemWidth,height: itemHeight,// 180:表示旋转180度orientation: 180,fontHeight: 4,});//api.drawText({text: text,x: 0,y: itemHeight,width: itemWidth,height: itemHeight,// 270:表示左转90度orientation: 270,fontHeight: 4,});//api.commitJob({gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},tablePrintTest() {const api = this.lpapi;//const labelWidth = 60;const labelHeight = 40;const margin = 1.5;//return this.checkAndOpenPrinter().then(() => {const jobInfo = api.startJob({width: labelWidth,height: labelHeight,orientation: 90,jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//this.updateCanvas(jobInfo).then(() => {// 将整个打印区域分割成四个区域,分别进行四种旋转测试api.drawTable({x: margin,y: margin,width: labelWidth - margin * 2,height: labelHeight - margin * 2,rowCount: 3,columnCount: 3,lineWidth: 0.4,// 指定单元格的宽度,未指定或者小于1表示按照一定的比例分配剩余空间columnWidths: [18, 0, 25],horizontalAlignment: 0,cells: [{type: "text",text: "表格打印测试",fontStyle: 1,fontHeight: 3.5,columnSpan: 3,horizontalAlignment: 1,},"","","设备名称","打印机",{type: "qrcode",text: "8888888888",rowSpan: 2,},"设备型号","DT60","",],});//api.commitJob({gapType: this.getGapType(),darkness: this.getPrintDarkness(),}).then((resp) => {this.previewLabel(resp);return resp.statusCode === 0;});});});},jsonPrintTest() {const device = this.getDevice();// 有个问题:无法更新画布大小const api = this.lpapi;this.clearPreview();//api.print({jobInfo: {jobWidth: 40,jobHeight: 30,jobName: this.getJobName(),orientation: this.getOrientation(),gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),},printerInfo: {name: device?.name,deviceId: device?.deviceId,},jobPages: [[// 第一张标签,打印一维码{ type: "rect", x: 1.5, y: 1.5, width: 40 - 3, height: 30 - 3, lineWidth: 0.4 },{type: "barcode",x: 2,y: 6,width: 36,height: 22,textHeight: 5,barcodeType: 60,horizontalAlignment: 1,text: "www.dothantech.com",},],[// 第二章标签,打印二维码{ type: "rect", x: 1.5, y: 1.5, width: 40 - 3, height: 30 - 3, lineWidth: 0.4 },{type: "qrcode",x: 1.5,y: 2.5,width: 37,height: 20,horizontalAlignment: 1,text: "上海道臻信息技术有限公司",},{type: "text",x: 1.5,y: 23,width: 37,height: 5,fontHeight: 3,horizontalAlignment: 1,text: "上海道臻信息技术有限公司",},],],onJobCreated: (info) => {return this.updateCanvas(info);},onPageComplete: (res) => {// 通过 pageComplete可以监控打印或者预览的进度。this.appendPreview(res);console.log(`----- 打印进度:[${res.pageIndex} / ${res.printPages}]`);},}).then((resp) => {if (resp.statusCode !== 0) {console.warn(`---- 打印失败,statusCode = ${resp.statusCode}`);} else {console.log(`---- 打印成功!`);}// this.previewLabel(resp);});},dataBindPrintTest() {const api = this.lpapi;const device = this.getDevice();this.clearPreview();//api.print({jobInfo: {jobWidth: 50,jobHeight: 70,jobName: this.getJobName(),orientation: this.getOrientation(),gapType: this.getGapType(),printDarkness: this.getPrintDarkness(),printSpeed: this.getPrintSpeed(),// startPage: 3,},printerInfo: {name: device?.name,deviceId: device?.deviceId,},jobPage: [{ type: "rect", x: 1, y: 1, width: 48, height: 68, lineWidth: 0.3 },{type: "text",// 打印内容可以通过 columnName 来绑定到 jobArguments 参数列表中相关数据columnName: "column1",x: 1,y: 1,width: 48,height: 68,fontHeight: 3,// UniApp中进行字符串的计算性能比较差,所以可以关闭字体自动缩小的功能;autoShrink: this.isAppPlus ? false : true,// 如果字符串太长的话,可以通过该参数来提高字符串换行计算时的性能;measureOptimizeStep: 10,},],jobArguments: [{ column1: "1德佟印立方是一家集研发、生产、销售和技术服务于一体的专业标签打印机生产厂家,旗下拥有德佟电子和印立方两个不同系列的品牌。 公司创立于2016年,主要生产和销售移动便携式标签打印机及配套耗材,并为顾客量身定制标签标识解决方案。公司总部位于中国上海,并在广州和苏州张家港设立分公司。公司生产基地位于苏州张家港总面积为8000平,主要生产标签打印机及其使用耗材。公司虽然成立时间不长,但已推出多款标签打印机,突破产品研发壁垒,填补了市场产品空缺,推动便携式标签打印机市场发展。公司进入市场之后,凭借切合市场需求的产品、过硬的软硬件技术能力、良好的线上线下代理商合作模式, 已经成为该市场领域事实上的标杆领头羊,在保持和客户多方共赢的同时,自身销售额每年也在以超过50%的速度高速增长。业务已覆盖:通讯电力,政企教育,烟草管理,危废管理,商业零售,办公生活。" },{ column1: "2德佟印立方是一家集研发、生产、销售和技术服务于一体的专业标签打印机生产厂家,旗下拥有德佟电子和印立方两个不同系列的品牌。 公司创立于2016年,主要生产和销售移动便携式标签打印机及配套耗材,并为顾客量身定制标签标识解决方案。公司总部位于中国上海,并在广州和苏州张家港设立分公司。公司生产基地位于苏州张家港总面积为8000平,主要生产标签打印机及其使用耗材。公司虽然成立时间不长,但已推出多款标签打印机,突破产品研发壁垒,填补了市场产品空缺,推动便携式标签打印机市场发展。公司进入市场之后,凭借切合市场需求的产品、过硬的软硬件技术能力、良好的线上线下代理商合作模式, 已经成为该市场领域事实上的标杆领头羊,在保持和客户多方共赢的同时,自身销售额每年也在以超过50%的速度高速增长。业务已覆盖:通讯电力,政企教育,烟草管理,危废管理,商业零售,办公生活。" },{ column1: "3德佟印立方是一家集研发、生产、销售和技术服务于一体的专业标签打印机生产厂家,旗下拥有德佟电子和印立方两个不同系列的品牌。 公司创立于2016年,主要生产和销售移动便携式标签打印机及配套耗材,并为顾客量身定制标签标识解决方案。公司总部位于中国上海,并在广州和苏州张家港设立分公司。公司生产基地位于苏州张家港总面积为8000平,主要生产标签打印机及其使用耗材。公司虽然成立时间不长,但已推出多款标签打印机,突破产品研发壁垒,填补了市场产品空缺,推动便携式标签打印机市场发展。公司进入市场之后,凭借切合市场需求的产品、过硬的软硬件技术能力、良好的线上线下代理商合作模式, 已经成为该市场领域事实上的标杆领头羊,在保持和客户多方共赢的同时,自身销售额每年也在以超过50%的速度高速增长。业务已覆盖:通讯电力,政企教育,烟草管理,危废管理,商业零售,办公生活。" },{ column1: "4德佟印立方是一家集研发、生产、销售和技术服务于一体的专业标签打印机生产厂家,旗下拥有德佟电子和印立方两个不同系列的品牌。 公司创立于2016年,主要生产和销售移动便携式标签打印机及配套耗材,并为顾客量身定制标签标识解决方案。公司总部位于中国上海,并在广州和苏州张家港设立分公司。公司生产基地位于苏州张家港总面积为8000平,主要生产标签打印机及其使用耗材。公司虽然成立时间不长,但已推出多款标签打印机,突破产品研发壁垒,填补了市场产品空缺,推动便携式标签打印机市场发展。公司进入市场之后,凭借切合市场需求的产品、过硬的软硬件技术能力、良好的线上线下代理商合作模式, 已经成为该市场领域事实上的标杆领头羊,在保持和客户多方共赢的同时,自身销售额每年也在以超过50%的速度高速增长。业务已覆盖:通讯电力,政企教育,烟草管理,危废管理,商业零售,办公生活。" },{ column1: "5德佟印立方是一家集研发、生产、销售和技术服务于一体的专业标签打印机生产厂家,旗下拥有德佟电子和印立方两个不同系列的品牌。 公司创立于2016年,主要生产和销售移动便携式标签打印机及配套耗材,并为顾客量身定制标签标识解决方案。公司总部位于中国上海,并在广州和苏州张家港设立分公司。公司生产基地位于苏州张家港总面积为8000平,主要生产标签打印机及其使用耗材。公司虽然成立时间不长,但已推出多款标签打印机,突破产品研发壁垒,填补了市场产品空缺,推动便携式标签打印机市场发展。公司进入市场之后,凭借切合市场需求的产品、过硬的软硬件技术能力、良好的线上线下代理商合作模式, 已经成为该市场领域事实上的标杆领头羊,在保持和客户多方共赢的同时,自身销售额每年也在以超过50%的速度高速增长。业务已覆盖:通讯电力,政企教育,烟草管理,危废管理,商业零售,办公生活。" },],onJobCreated: (info) => {return this.updateCanvas(info);},onPageComplete: (res) => {// 通过 pageComplete可以监控打印或者预览的进度。this.appendPreview(res);console.log(`----- 打印进度:[${res.pageIndex} / ${res.printPages}]`);},}).then((resp) => {if (resp.statusCode !== 0) {console.warn(`---- 打印失败,statusCode = ${resp.statusCode}`);} else {console.log(`---- 打印成功!`);}// this.previewLabel(resp);});},wdfxPrintTest() {const device = this.getDevice();// 清空预览列表this.clearPreview();//this.lpapi.printWdfx({content: wdfxStr,domParser: new DOMParser(),jobInfo: {jobName: this.getJobName(),gapType: this.getGapType(),},printerInfo: {name: device?.name,deviceId: device?.deviceId,},onJobCreated: (info) => {return this.updateCanvas(info);},onPageComplete: (res) => {// 通过 pageComplete可以监控打印或者预览的进度。this.appendPreview(res);console.log(`----- 打印进度:[${res.pageIndex} / ${res.printPages}]`);},}).then((resp) => {if (resp.statusCode !== 0) {console.warn(`---- 打印失败,statusCode = ${resp.statusCode}`);} else {console.log(`---- 打印成功!`);}});},async imagesPrintTest(url) {const api = this.lpapi;//const labelWidth = 40;const labelHeight = 40;const margin = 2;//const image = await api.loadImage(url);const jobInfo = api.startJob({width: labelWidth,height: labelHeight,jobName: this.getJobName(),});if (!jobInfo) {console.warn("---------- 打印任务创建失败!----------");return;}//await this.updateCanvas(jobInfo);// 绘制标签外边框api.drawRectangle({width: labelWidth,height: labelHeight,lineWidth: 0.3,});// 绘制图片api.drawImage({image: image,x: margin,y: margin,width: labelWidth - margin * 2,height: labelHeight - margin * 2,});//const resp = await api.commitJob({gapType: this.getGapType(),darkness: this.getPrintDarkness(),});this.previewLabel(resp);return true;},/*** 循环打印方式1,通过嵌套调用来实现。** @param {Object[]} list 打印数据列表* @param {number} index 当前打印数据的索引* @param {(result: any) => void} 打印结果回调函数*/printQrcodePages(list, index, callback) {if (index >= list.length) {console.log(`------ 打印完毕! -------`);if (callback) {callback("打印完毕!");}} else {// 未打印完毕,则继续打印下一张标签this.qrcodePrintTest(list[index], () => {console.log(`------ 打印进度:[${index + 1} / ${list.length}]`);this.printPages1(list, index + 1, callback);});}},async multiPagePrintTest() {const imageList = ["/static/yinlifun.png","https://www.detonger.com/img/QRCode_OfficialAccounts.png","/static/yinlifun.png","https://www.detonger.com/img/QRCode_OfficialAccounts.png","/static/yinlifun.png",];// 链接打印机const res = await this.checkAndOpenPrinter();if (!res) {console.warn(`---------- 打印机打开失败!----------`);uni.showToast({ title: "打印机链接失败!", icon: "fail" });return;}// 循环打印for (let i = 0; i < imageList.length; i++) {await this.imagesPrintTest(imageList[i]);console.log(`------ 打印进度:[${i + 1} / ${imageList.length}]`);}console.log(`------ 打印完毕! -------`);},base64PrintTest() {const currDevice = this.getDevice();if (currDevice) {this.lpapi.printImage({printerName: currDevice.name,// 在 UniApp 中无法获取 base64图片的像素大小,所以必须要指定图片的打印大小,单位毫米,否则无法完成打印;width: 45,height: 45,image: imgSrc,}).then((resp) => {if (resp.statusCode === 0) {console.log(`---- BASE64 图片打印成功!`);} else {console.warn(`---- BASE64 图片打印失败,statusCode= ${resp.statusCode}`);console.warn(resp);}});}},},
};
</script><style>
button {margin-top: 15upx;margin-bottom: 15upx;height: 40px;
}.content {display: flex;flex-direction: column;align-items: center;justify-content: center;
}.logo {height: 200rpx;width: 200rpx;margin: 200rpx auto 50rpx auto;
}.text-area {display: flex;justify-content: center;
}.title {font-size: 36rpx;color: #8f8f94;
}
</style>

项目开发类型选择

  1. WebApp
  1. 跨平台兼容性强,支持Windows、Android、IOS,语法通用,实时更新,多设备同时登录。
  2. 支持扫码功能,选用@zxing/library能够快速高效响应二维码的扫描。
  3. 弃用原因:用户指定的打印机工具包仅支持uniapp,微信小程序,鸿蒙原生app;
  • 参考文章:https://liubing.me/article/vue/vue3-h5-scan-qr-code.html#简单实现
  • webApp扫码功能实现
点击查看代码
<template><div class="content-table"><van-nav-bar title="扫码" left-arrow@click="backToHome"/> <div class="scan-page"><videoid="qrcode-scanner"></video><!-- 扫描框 --><div class="scan-box"><!-- 扫描框四个角 --><div class="relative h-full w-full color-white"><div class="role lt"></div><div class="role lb"></div><div class="role rt"></div><div class="role rb"></div></div><!-- 扫描动画 --><div class="animation-scan"><div class="scanning"></div></div></div></div></div>
</template><script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { BrowserMultiFormatReader } from '@zxing/library'
import router from '@/router';let render = null;
const deviceId = ref('')
onMounted(() => {render = new BrowserMultiFormatReader()openScan()
})
function openScan() {if(render === null) return;render.listVideoInputDevices().then((videoInputDevices) => {if (videoInputDevices.length) {// 0 前置摄像头  1 后置摄像头// 默认获取第一个摄像头设备iddeviceId.value = videoInputDevices[0]?.deviceIdif (videoInputDevices.length > 1) {deviceId.value = videoInputDevices[1]?.deviceId}decodeFromInputVideo()}})
}function decodeFromInputVideo() {render.decodeFromVideoDevice(deviceId.value, 'qrcode-scanner', (result) => {if (result) {console.log('result', result)backToScan()}})
}
const backToScan = async() => {try{await render.reset()await router.push("/insertData");}catch(e){console.log(e);}
}
const backToHome = async() => {try {await render.reset()await router.go(-1);}catch (e) {console.log(e);}
}
onUnmounted(() => {render = null;
})
</script><style lang="scss">
.content-table {height: 100%;overflow-x: hidden;.scan-page {height: 1500px !important;width: 100%;position: relative;#qrcode-scanner {position: absolute;height: 100%;left: 50%;transform: translate(-50%, 0);}.scan-box {position: absolute;//  background-color: rgba(1,1,1,.5);left: 50%;top: 50%;transform: translate(-50%, -50%);box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 0px 5000px;height: 10rem;width: 600px;border-radius: 20px 20px 20px 20px;.role {position: absolute;height: 100px;width: 100px;}.lt {top:10px;left:10px;background-image: url('../../images/lt.png') ;background-size: 100px 100px;}.lb {bottom: 10px;left: 10px;background-image: url('../../images/lb.png') ;background-size: 100px 100px;}.rt {right: 10px;top: 10px;background-image: url('../../images/rt.png') ;background-size: 100px 100px;}.rb {right: 10px;bottom: 10px;background-image: url('../../images/rb.png') ;background-size: 100px 100px;}// 扫描动画.animation-scan {position: absolute;top: 0;height: 100%;width: 100%;overflow: hidden;border-radius: 20px;.scanning {position: absolute;inset: 0;z-index: 2;height: 100%;background: linear-gradient(rgba(255, 255, 255, 0),80%,rgba(96, 165, 250, 0.8));animation: move 2s linear infinite;-webkit-animation: move 2s linear infinite;}}} }
}
.addInfo{padding: 0 30px;margin-top: 100px;.scan-btn {.delete-btn {margin-bottom: 30px;}}
}@keyframes move {0% {transform: translateY(-100%);}100% {transform: translateY(400px);}
} 
</style>
  1. UniApp---> 选用
  1. 可一套代码运行到多个平台,内置的扫描二维码接口,扫描速度快,聚焦强。编译为微信小程序支持二维码打印调试功能。
  1. 鸿蒙系统App(方舟语言)
  1. 支持Harmony系统安装软件,内置api,原生小程序支持版本兼容性有限。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/857282.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dotnet 简单使用 ICU 库进行分词和分行

本文将和大家介绍如何使用 ICU 库进行文本的分词和分行按照 dotnet 的惯例,先使用 NuGet 安装大佬封装好的 ICU 库,我这里选择的是 icu.net 库和 Microsoft.ICU.ICU4C.Runtime 库。其中 icu.net 库提供 ICU 的 dotnet 层封装,让咱上层 C# 代码可以方便调用。而 Microsoft.IC…

读图数据库实战笔记11读后总结与感想兼导读

读后总结与感想1. 基本信息 图数据库实战[ [美] 戴夫贝克伯杰(Dave Bechberger) (美) 乔希佩里曼著人民邮电出版社,2021年10月出版1.1. 读薄率 书籍总字数413千字,笔记总字数30938字。 读薄率30938413000≈7.49% 1.2. 读厚方向Data Mesh权威指南数据的边界:隐私与个人数据保护…

12.16 ~ 12.22

菜12.16 回归 OI 第一天。 打多校的模拟赛。 3 题 4.5h,已经是省选模拟了 T1 一眼可反悔贪心好像还是道原,于是在场上与 T1 大战 3h 遗憾离场 后边两题直接敲暴力了 T3 还是个构造,这下一点不会了 然后 T1 的 DP 出了点小锅,在新 OJ 绑包以及选手可以自行加点的情况下取得了…

给销售人

许多人不懂的是:销售最大的收获不是提成多少,不是升职,不是增加了炫耀的资本,不是完成任务,销售最大的收获是:你生活中多了一个信任你的人! 销售最大的敌人 不是对手,不是价格太高,不是拒绝你的客户,不是公司制度,不是产品不好,最大的敌人是:你的抱怨!你的借口!…

pve系统all in one 搭建

成功安装系统,硬件不支持8.x的pve 使用5.1 后续可以更新 换源 在更新软件包时出错因为 Proxmox 的 Ceph Quincy 源未正确导入公钥,导致系统无法验证其软件包的签名。重新更新成功 安装最新配置 过程中顺便加了一个pcie x1 转1g的网卡,不知是否需要驱动。使用的时候再看吧 不…

使用ollama+llama3.1+open-webui搭一个本地的模型

1、先安装我们的ollama 1.1、官网地址:https://ollama.com/ 选择合适的版本,我的是window版本,点击下载,不用填邮箱。1.2、开始安装,选择默认就可以1.3、安装完毕:cmd输入:ollama2、安装模型:llama3.1 2.1:找到模型 2.2复制下载2.3、命令行下载: 2.4、下载完毕就进入对…

windows修改mac 地址

参考 https://blog.csdn.net/u012559967/article/details/134768073 win11确认可行 (另外一种修改注册表,暂未确认) 网络适配器中配置 网络适配器中配置的方式适用于能够在网络适配器中找到物理地址(NetworkAddress)的情况。 1、打开控制面板 > 网络和共享中心 > 更改…

MADDPG算法

MADDPG算法 论文名称:《Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments》 一、基本问题 MADDPG是一篇经典的多智能体强化学习算法。在MADDPG以前,多智能体强化学习算法主要为独立学习技术。独立学习技术 独立学习技术就是在环境中对于每一个智能体…

ble广播和连接

蓝牙BLE设备的状态:从机处于待机,广播,连接状态中的一种,主机处于待机,扫描,连接状态的一种。 在BLE通讯中,数据收发都是通过连接事件触发的。连接事件的发生始终位于一个频率,这个频率由连接参数决定。连接参数是主机决定的,从机可以向主机发起连接参数请求,但是最终…

ble基础

一、蓝牙基础 蓝牙标准profile bluez linux tools 一文读懂BLE 1.1 蓝牙分类 蓝牙分为经典蓝牙(BT-Bluetooth)和低功耗蓝牙(BLE-Bluetooth Low Energy)。这两套原理和实现都不一样,也无法实现互通。 Basic Rate(BR)/EDR/AMP 最初的蓝牙技术,包括可选的EDR(Enhanced Da…

爬取小说案例-BeautifulSoup教学篇

@目录前言导航BeautifulSoupBeautifulSoup介绍BeautifulSoup的使用1. 导入库2. 实例化对象3. 提取数据成果共勉博客 前言 当我们进行爬取各种资源,拿到源码进行解析数据的时候,会用到各种解析方式,本文介绍的爬取小说的一个案例,使用比较受欢迎的python第三方库BeautifuSou…

vue基础指令示例

1、vue基础示例<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>基础指令</title><script src="../vu/js/vue.js"></script><style>.box1{width: 150px;height: 1…