添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印

在现代物流、仓储和零售行业中,RFID和二维码技术发挥着至关重要的作用。这些技术不仅提高了效率,还增强了追踪和管理的能力。本文将介绍如何使用JavaScript和斑马打印机的BrowserPrint API来打印RFID二维码贴纸。

1. BrowserPrint API 简介

BrowserPrint是斑马技术公司提供的一个JavaScript库,它允许网页应用直接与连接到客户端计算机上的斑马打印机进行交互。这意味着开发者可以在不需要安装额外软件的情况下,直接从网页应用中发送打印任务到斑马打印机。

2. 环境设置

要使用BrowserPrint API,首先需要确保斑马打印机正确连接到计算机,并且用户的系统上已安装BrowserPrint应用程序。此应用程序作为一个服务运行,允许通过本地网络接口与打印机通信。

本例使用的是zebra-browser-print-windows-v131445.exe作为驱动。
安装后运行程序,驱动会通过串口查询到已经连接的斑马打印机,并启动一个本地服务与之通信。

3. 打印机初始化

在JavaScript代码中,首先需要初始化BrowserPrint API,并搜索可用的打印设备。以下是初始化打印机并检索连接的打印机列表的代码段:

BrowserPrint.getLocalDevices(devices => {
  this.printers = devices.printer.filter(device => device.deviceType === 'printer');
  if (!this.printers || !this.printers.length) {
    this.$message.error('没有可用的打印机,请检查驱动或USB连接!');
}, error => {
  this.$message.error('无法找到打印机,请检查驱动或USB连接!');
});
4. 构建ZPL指令

ZPL(Zebra Programming Language)是斑马打印机使用的命令语言,用于定义打印标签的布局和内容。在我们的示例中,我们构建了一个ZPL字符串,用于设置标签的大小、位置和内容,包括二维码和RFID数据。

let index = 1;
      let zpl = '^XA'
      let x = baseX;
      let y = baseY;
      for (let item of tableData) {
        if (item.h) {
          zpl += ' ^CI28 ^FO' + (x - spacingX * 2) + ',' + y + '^A@R,32,32,E:SIMSUN.TTF ^FB160,8,,J, ^FD' + (item.lable || '') + ':' + '^FS ';
          zpl += ' ^CI28 ^FO' + (x - spacingX * 2) + ',' + (y + 160) + '^A@R,32,32,E:SIMSUN.TTF ^FB330,8,,J, ^FD' + (item.value || '') + '^FS ';
        } else {
          zpl += ' ^CI28 ^FO' + x + ',' + y + '^A@R,32,32,E:SIMSUN.TTF ^FB160,2,,J, ^FD' + (item.lable || '') + ':' + '^FS ';
          zpl += ' ^CI28 ^FO' + x + ',' + (y + 160) + '^A@R,32,32,E:SIMSUN.TTF ^FB330,2,,J, ^FD' + (item.value || '') + '^FS ';
        if (index === 3) {
          x -= spacingX;
          y = baseY;
          index = 1;
        } else {
          index++;
          y += spacingY;
      zpl += ' ^FO' + baseY + ',' + (baseY + (spacingY * 0.9)) + '^BY3 ^BCR,100,Y,N,N ^FD' + (tableData.find(item => item.lable === '条码号').value || '') + '^FS '
      let bdbh = tableData.find(item => item.lable === '磅单编号').value || '';
      if (bdbh.length > 12) {
        this.$message.error('磅单编号长度大于12,写入RFID将不正确!')
      function stringToHexAscii (input) {
        let hexAscii = '';
        for (let i = 0; i < input.length; i++) {
          const charCode = input.charCodeAt(i);
          const hexValue = charCode.toString(16).padStart(2, '0');
          hexAscii += hexValue.toUpperCase();
        return hexAscii;
      bdbh = stringToHexAscii(bdbh)
      zpl += '^RFW,H^FD' + bdbh + 'FFFFFFFFFFFFFFFFFFFFFFFF' + '^FS'
      zpl += '^XZ'
构建ZPL指令详解

ZPL(Zebra Programming Language)是斑马打印机专用的一种命令语言,用于控制标签的打印格式和内容。在构建ZPL指令时,每个指令都有特定的功能,用于定义打印内容的布局、样式和特性。下面将详细介绍示例中使用的主要ZPL指令及其意义:

1. ^XA^XZ
  • ^XA:这是每个ZPL脚本的开始指令,表示开始一条新的标签格式指令。
  • ^XZ:这是结束指令,表示标签格式指令结束。在这之后的指令将不会被执行,直到遇到下一个^XA
2. ^FO(Field Origin)
  • ^FOx,y:设置接下来的打印字段的起始位置,其中[x](file:///d%3A/ch/template-builder/print.js#51%2C231-51%2C231)和[y](file:///d%3A/ch/template-builder/print.js#197%2C11-197%2C11)是横纵坐标。这个指令用于定位条码、文本或图像在标签上的具体位置。
3. ^A(Font Specification)
  • ^A@R,32,32,E:SIMSUN.TTF:这个指令用于设置字体。[@R](file:///d%3A/ch/template-builder/print.js#200%2C67-200%2C67)表示字体旋转角度,[32,32](file:///d%3A/ch/template-builder/print.js#200%2C70-200%2C70)分别是字体的宽度和高度,E:SIMSUN.TTF指定使用的字体文件。
4. ^FB(Field Block)
  • ^FB160,2,,J,:这个指令用于定义一个文本字段的属性。[160](file:///d%3A/ch/template-builder/print.js#201%2C65-201%2C65)是字段宽度,[2](file:///d%3A/ch/template-builder/print.js#14%2C136-14%2C136)是最大行数,[J](file:///d%3A/ch/template-builder/print.js#200%2C99-200%2C99)表示文本的对齐方式(此处为居中对齐)。
5. ^FD(Field Data)
  • ^FDtext^FS:这个指令用于定义字段的内容。[text](file:///d%3A/ch/template-builder/print.js#23%2C31-23%2C31)是要打印的文本。^FS(Field Separator)标记字段数据的结束。
6. ^BY(Bar Code Field Default)
  • ^BY3:这个指令用于设置条码的默认宽度因子,[3](file:///d%3A/ch/template-builder/print.js#36%2C172-36%2C172)表示条码宽度为标准宽度的三倍。
7. ^BC(Code 128 Bar Code)
  • ^BCR,100,Y,N,N:这个指令用于打印Code 128条码。[R](file:///d%3A/ch/template-builder/print.js#200%2C68-200%2C68)表示条码旋转角度,[100](file:///d%3A/ch/template-builder/print.js#164%2C22-164%2C22)是条码的高度,后面的[Y](file:///d%3A/ch/template-builder/print.js#215%2C81-215%2C81)和[N](file:///d%3A/ch/template-builder/print.js#215%2C83-215%2C83)分别表示是否打印解释行(条码下的数字或字母)和是否在条码下方打印解释行。
8. ^RFW,H^FD(RFID Encoding)
  • ^RFW,H^FDdata^FS:这个指令用于向RFID标签写入数据。[H](file:///d%3A/ch/template-builder/print.js#230%2C20-230%2C20)指定数据的写入模式(此处为十六进制),[data](file:///d%3A/ch/template-builder/print.js#18%2C11-18%2C11)是要写入的数据。

通过这些指令的组合,可以精确地控制斑马打印机打印出的标签的每一个细节,从简单的文本到复杂的条码和RFID数据,都可以通过ZPL指令灵活配置。

5. 发送打印任务

构建完ZPL指令后,可以使用BrowserPrint API将其发送到打印机进行打印:

printer.send(zpl, _ => {
  this.$message.success('开始打印!');
  callback && callback();
}, error => {
  this.$message.error('打印失败,请确认打印机状态!');
});
6. 错误处理和用户反馈

在整个过程中,代码通过Vue.js的$message方法提供了用户反馈,包括成功消息和错误消息。这确保了用户能够了解打印过程中发生的任何问题,并采取相应的措施。

7.完整代码

以下代码可以作为一个vue项目的混入直接使用,你可以根据自己的实际情况对参数进行调整

let finishedFunction = null;
let response = null;
var $jscomp = $jscomp || {}; $jscomp.scope = {}; $jscomp.checkStringArgs = function (b, h, c) { if (null == b) throw new TypeError("The 'this' value for String.prototype." + c + " must not be null or undefined"); if (h instanceof RegExp) throw new TypeError("First argument to String.prototype." + c + " must not be a regular expression"); return b + "" }; $jscomp.ASSUME_ES5 = !1; $jscomp.ASSUME_NO_NATIVE_MAP = !1; $jscomp.ASSUME_NO_NATIVE_SET = !1;
$jscomp.defineProperty = $jscomp.ASSUME_ES5 || "function" == typeof Object.defineProperties ? Object.defineProperty : function (b, h, c) { b != Array.prototype && b != Object.prototype && (b[h] = c.value) }; $jscomp.getGlobal = function (b) { return "undefined" != typeof window && window === b ? b : "undefined" != typeof global && null != global ? global : b }; $jscomp.global = $jscomp.getGlobal(this);
$jscomp.polyfill = function (b, h, c, e) { if (h) { c = $jscomp.global; b = b.split("."); for (e = 0; e < b.length - 1; e++) { var k = b[e]; k in c || (c[k] = {}); c = c[k] } b = b[b.length - 1]; e = c[b]; h = h(e); h != e && null != h && $jscomp.defineProperty(c, b, { configurable: !0, writable: !0, value: h }) } };
$jscomp.polyfill("String.prototype.startsWith", function (b) { return b ? b : function (b, c) { var e = $jscomp.checkStringArgs(this, b, "startsWith"); b += ""; var h = e.length, p = b.length; c = Math.max(0, Math.min(c | 0, e.length)); for (var l = 0; l < p && c < h;)if (e[c++] != b[l++]) return !1; return l >= p } }, "es6", "es3");
var BrowserPrint = function () {
  function b (a, b) { var d = new XMLHttpRequest; "withCredentials" in d ? d.open(a, b, !0) : "undefined" != typeof XDomainRequest ? (d = new XDomainRequest, d.open(a, b)) : d = null; return d } function h (a, b, d) { void 0 === b && (b = e.defaultSuccessCallback); void 0 === d && (d = e.defaultErrorCallback); return c(a, b, d) } function c (a, b, d) {
    a.onreadystatechange = function () {
      a.readyState === XMLHttpRequest.DONE && 200 === a.status ? "" === a.responseType ? b(a.responseText) : b(a.response) : a.readyState === XMLHttpRequest.DONE && (d ? d(a.response) :
        console.log("error occurred with no errorCallback set."))
    }; return a
  } var e = {}, k = {}, p = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); navigator.userAgent.indexOf("Trident/7.0"); var l = "http://127.0.0.1:9100/"; p && "https:" === location.protocol && (l = "https://127.0.0.1:9101/"); e.Device = function (a) {
    var m = this; this.name = a.name; this.deviceType = a.deviceType; this.connection = a.connection; this.uid = a.uid; this.version = 2; this.provider = a.provider; this.manufacturer = a.manufacturer; this.readRetries = "bluetooth" ===
      this.connection ? 1 : 0; this.sendErrorCallback = function (d) { }; this.sendFinishedCallback = function (d) { }; this.readErrorCallback = function (d) { }; this.readFinishedCallback = function (d) { }; this.send = function (d, a, f) {
        var g = b("POST", l + "write"); g && (void 0 !== m && (void 0 === a && (a = m.sendFinishedCallback), void 0 === f && (f = m.sendErrorCallback)), c(g, a, f), g.send(JSON.stringify({
          device: { name: this.name, uid: this.uid, connection: this.connection, deviceType: this.deviceType, version: this.version, provider: this.provider, manufacturer: this.manufacturer },
          data: d
        })))
      }; this.sendUrl = function (d, a, f, e) { var g = b("POST", l + "write"); g && (c(m, g, a, f), d = { device: { name: this.name, uid: this.uid, connection: this.connection, deviceType: this.deviceType, version: this.version, provider: this.provider, manufacturer: this.manufacturer }, url: d }, null != e && void 0 != e && (d.options = e), g.send(JSON.stringify(d))) }; this.sendFile = function (d, a, f) {
        if ("string" === typeof d) e.loadFileFromUrl(d, function (d) { m.sendFile(d, a, f) }, f); else {
          var g = b("POST", l + "write"); if (g) {
            g.responseType = "text"; h(g, a, f); var c =
              new FormData, n = {}; n.device = m; c.append("json", JSON.stringify(n)); c.append("blob", d); g.send(c)
      }; this.convertAndSendFile = function (d, a, b, c) { c || (c = {}); c.action || (c.action = "print"); e.convert(d, this, c, a, b) }; this.read = function (d, a) {
        var f = b("POST", l + "read"); f && (void 0 !== m && (void 0 === d && (d = m.readFinishedCallback), void 0 === a && (a = m.readErrorCallback)), c(f, d, a), f.send(JSON.stringify({
          device: {
            name: this.name, uid: this.uid, connection: this.connection, deviceType: this.deviceType, version: this.version, provider: this.provider,
            manufacturer: this.manufacturer
        })))
      }; this.readUntilStringReceived = function (d, a, b, e, c) { c || (c = ""); void 0 === e && (e = this.readRetries); a = function (a, b, e, f, g) { return function (c) { if (c && 0 !== c.length) f = 0; else if (0 >= f) { b(g); return } c = g + c; "" !== d && -1 < c.indexOf(d) ? b(c) : a.readUntilStringReceived(d, b, e, f - 1, c) } }(this, a, b, e, c); this.read(a, b) }; this.readAllAvailable = function (a, b, f) { this.readUntilStringReceived("", a, b, f) }; this.sendThenRead = function (a, b, f) { this.send(a, function (a) { return function () { a.read(b, f) } }(this), f) };
    this.sendThenReadUntilStringReceived = function (a, b, f, e, c) { this.send(a, function (a) { return function () { a.readUntilStringReceived(b, f, e, c) } }(this), e) }; this.sendThenReadAllAvailable = function (a, b, e, c) { this.send(a, function (a) { return function () { a.readUntilStringReceived("", b, e, c) } }(this), e) }
  }; e.defaultSuccessCallback = function () { }; e.defaultErrorCallback = function () { }; e.ApplicationConfiguration = function () { this.application = { version: "1.2.0.3", build_number: 3, api_level: 2, platform: "", supportedConversions: {} } }; e.getLocalDevices =
    function (a, c, d) { var g = b("GET", l + "available"); g && (finishedFunction = function (b) { response = b; response = JSON.parse(response); for (var c in response) if (response.hasOwnProperty(c) && response[c].constructor === Array) for (let arr = response[c], b = 0; b < arr.length; ++b)arr[b] = new e.Device(arr[b]); void 0 === d ? a(response) : (response.hasOwnProperty(d) || (response[d] = []), a(response[d])) }, h(g, finishedFunction, c), g.send()) }; e.getDefaultDevice = function (a, c, d) {
      var g = "default"; void 0 !== a && null != a && (g = g + "?type=" + a); if (a = b("GET", l + g)) finishedFunction =
        function (a) { response = a; "" === response ? c(null) : (response = JSON.parse(response), a = new e.Device(response), c(a)) }, a = h(a, finishedFunction, d), a.send()
    }; e.getApplicationConfiguration = function (a, c) { var d = b("GET", l + "config"); d && (finishedFunction = function (b) { response = b; "" === response ? a(null) : (response = JSON.parse(response), a(response)) }, h(d, finishedFunction, c), d.send()) }; e.readOnInterval = function (a, b, d) {
      if (void 0 === d || 0 === d) d = 1; readFunc = function () {
        a.read(function (c) { b(c); k[a] = setTimeout(readFunc, d) }, function (b) {
          k[a] =
            setTimeout(readFunc, d)
      }; k[a] = setTimeout(readFunc, d)
    }; e.stopReadOnInterval = function (a) { k[a] && clearTimeout(k[a]) }; e.bindFieldToReadData = function (a, b, d, c) { e.readOnInterval(a, function (a) { "" !== a && (b.value = a, void 0 !== c && null != c && c()) }, d) }; e.loadFileFromUrl = function (a, c, d) { request = b("get", a); console.log("ResponseType: " + request.responseType); request.responseType = "blob"; h(request, c, d); request.send() }; e.convert = function (a, c, d, g, f) {
      if (a) if ("string" === typeof a) e.loadFileFromUrl(a, function (b) {
        d.fromFormat ||
          (d.fromFormat = a.substring(a.length - 3)); e.convert(b, c, d, g, f)
      }, f); else { var k = b("POST", l + "convert"); a.type && (a.type.startsWith("image/") || a.type.startsWith("application/")) && (d.fromFormat = a.type.toLowerCase().replace("image/", "").replace("application/", "").replace("x-ms-", "")); if (k) { k.responseType = "text"; h(k, function (a) { g(JSON.parse(a)) }, f); var m = new FormData, n = {}; null != d && void 0 !== d && (n.options = d); c && (n.device = c); m.append("json", JSON.stringify(n)); m.append("blob", a); k.send(m) } } else f ? f("Resource not specified") :
        e.defaultErrorCallback("Resource not specified")
    }; return e
}();
var $jscomp = $jscomp || {}; $jscomp.scope = {}; $jscomp.ASSUME_ES5 = !1; $jscomp.ASSUME_NO_NATIVE_MAP = !1; $jscomp.ASSUME_NO_NATIVE_SET = !1; $jscomp.defineProperty = $jscomp.ASSUME_ES5 || "function" == typeof Object.defineProperties ? Object.defineProperty : function (e, h, g) { e != Array.prototype && e != Object.prototype && (e[h] = g.value) }; $jscomp.getGlobal = function (e) { return "undefined" != typeof window && window === e ? e : "undefined" != typeof global && null != global ? global : e }; $jscomp.global = $jscomp.getGlobal(this); $jscomp.SYMBOL_PREFIX = "jscomp_symbol_";
$jscomp.initSymbol = function () { $jscomp.initSymbol = function () { }; $jscomp.global.Symbol || ($jscomp.global.Symbol = $jscomp.Symbol) }; $jscomp.Symbol = function () { var e = 0; return function (h) { return $jscomp.SYMBOL_PREFIX + (h || "") + e++ } }();
$jscomp.initSymbolIterator = function () { $jscomp.initSymbol(); var e = $jscomp.global.Symbol.iterator; e || (e = $jscomp.global.Symbol.iterator = $jscomp.global.Symbol("iterator")); "function" != typeof Array.prototype[e] && $jscomp.defineProperty(Array.prototype, e, { configurable: !0, writable: !0, value: function () { return $jscomp.arrayIterator(this) } }); $jscomp.initSymbolIterator = function () { } }; $jscomp.arrayIterator = function (e) { var h = 0; return $jscomp.iteratorPrototype(function () { return h < e.length ? { done: !1, value: e[h++] } : { done: !0 } }) };
$jscomp.iteratorPrototype = function (e) { $jscomp.initSymbolIterator(); e = { next: e }; e[$jscomp.global.Symbol.iterator] = function () { return this }; return e }; $jscomp.makeIterator = function (e) { $jscomp.initSymbolIterator(); var h = e[Symbol.iterator]; return h ? h.call(e) : $jscomp.arrayIterator(e) };
$jscomp.polyfill = function (e, h, g, l) { if (h) { g = $jscomp.global; e = e.split("."); for (l = 0; l < e.length - 1; l++) { var c = e[l]; c in g || (g[c] = {}); g = g[c] } e = e[e.length - 1]; l = g[e]; h = h(l); h != l && null != h && $jscomp.defineProperty(g, e, { configurable: !0, writable: !0, value: h }) } }; $jscomp.FORCE_POLYFILL_PROMISE = !1;
$jscomp.polyfill("Promise", function (e) {
  function h () { this.batch_ = null } function g (b) { return b instanceof c ? b : new c(function (a, f) { a(b) }) } if (e && !$jscomp.FORCE_POLYFILL_PROMISE) return e; h.prototype.asyncExecute = function (b) { null == this.batch_ && (this.batch_ = [], this.asyncExecuteBatch_()); this.batch_.push(b); return this }; h.prototype.asyncExecuteBatch_ = function () { var b = this; this.asyncExecuteFunction(function () { b.executeBatch_() }) }; var l = $jscomp.global.setTimeout; h.prototype.asyncExecuteFunction = function (b) {
    l(b,
  }; h.prototype.executeBatch_ = function () { for (; this.batch_ && this.batch_.length;) { var b = this.batch_; this.batch_ = []; for (var a = 0; a < b.length; ++a) { var f = b[a]; delete b[a]; try { f() } catch (k) { this.asyncThrow_(k) } } } this.batch_ = null }; h.prototype.asyncThrow_ = function (b) { this.asyncExecuteFunction(function () { throw b; }) }; var c = function (b) { this.state_ = 0; this.result_ = void 0; this.onSettledCallbacks_ = []; var a = this.createResolveAndReject_(); try { b(a.resolve, a.reject) } catch (f) { a.reject(f) } }; c.prototype.createResolveAndReject_ =
    function () { function b (b) { return function (k) { f || (f = !0, b.call(a, k)) } } var a = this, f = !1; return { resolve: b(this.resolveTo_), reject: b(this.reject_) } }; c.prototype.resolveTo_ = function (b) { if (b === this) this.reject_(new TypeError("A Promise cannot resolve to itself")); else if (b instanceof c) this.settleSameAsPromise_(b); else { a: switch (typeof b) { case "object": var a = null != b; break a; case "function": a = !0; break a; default: a = !1 }a ? this.resolveToNonPromiseObj_(b) : this.fulfill_(b) } }; c.prototype.resolveToNonPromiseObj_ = function (b) {
      var a =
        void 0; try { a = b.then } catch (f) { this.reject_(f); return } "function" == typeof a ? this.settleSameAsThenable_(a, b) : this.fulfill_(b)
    }; c.prototype.reject_ = function (b) { this.settle_(2, b) }; c.prototype.fulfill_ = function (b) { this.settle_(1, b) }; c.prototype.settle_ = function (b, a) { if (0 != this.state_) throw Error("Cannot settle(" + b + ", " + a | "): Promise already settled in state" + this.state_); this.state_ = b; this.result_ = a; this.executeOnSettledCallbacks_() }; c.prototype.executeOnSettledCallbacks_ = function () {
      if (null != this.onSettledCallbacks_) {
        for (var b =
          this.onSettledCallbacks_, a = 0; a < b.length; ++a)b[a].call(), b[a] = null; this.onSettledCallbacks_ = null
    }; var d = new h; c.prototype.settleSameAsPromise_ = function (b) { var a = this.createResolveAndReject_(); b.callWhenSettled_(a.resolve, a.reject) }; c.prototype.settleSameAsThenable_ = function (b, a) { var f = this.createResolveAndReject_(); try { b.call(a, f.resolve, f.reject) } catch (k) { f.reject(k) } }; c.prototype.then = function (b, a) {
      function f (a, f) { return "function" == typeof a ? function (f) { try { k(a(f)) } catch (n) { d(n) } } : f } var k, d, e = new c(function (a,
        f) { k = a; d = f }); this.callWhenSettled_(f(b, k), f(a, d)); return e
    }; c.prototype.catch = function (b) { return this.then(void 0, b) }; c.prototype.callWhenSettled_ = function (b, a) { function f () { switch (k.state_) { case 1: b(k.result_); break; case 2: a(k.result_); break; default: throw Error("Unexpected state: " + k.state_); } } var k = this; null == this.onSettledCallbacks_ ? d.asyncExecute(f) : this.onSettledCallbacks_.push(function () { d.asyncExecute(f) }) }; c.resolve = g; c.reject = function (b) { return new c(function (a, f) { f(b) }) }; c.race = function (b) {
      return new c(function (a,
        f) { for (var k = $jscomp.makeIterator(b), d = k.next(); !d.done; d = k.next())g(d.value).callWhenSettled_(a, f) })
    }; c.all = function (b) { var a = $jscomp.makeIterator(b), f = a.next(); return f.done ? g([]) : new c(function (b, d) { function k (a) { return function (f) { c[a] = f; e--; 0 == e && b(c) } } var c = [], e = 0; do c.push(void 0), e++, g(f.value).callWhenSettled_(k(c.length - 1), d), f = a.next(); while (!f.done) }) }; return c
}, "es6", "es3"); function dbg (e) { }
var Zebra = function () {
  function e (c, d) { if (d instanceof g.Printer.Status && l[c.device.uid]) { if (d.offline) { if (c.errors++, c.errors < c.errorsForOffline) return } else c.errors = 0; var b = l[c.device.uid].status, a = JSON.stringify(b); c.status = d; statusStr = JSON.stringify(d); if (statusStr !== a) c.onchange(b, d) } } function h (c) { return 2 !== c.charCodeAt(0) || 3 !== c.charCodeAt(c.length - 1) ? (dbg("Response did not contain proper control characters"), !1) : !0 } var g = {}, l = {}; setInterval(function () {
    for (var c in l) l.hasOwnProperty(c) && (c =
      l[c], function (d) { d.device.getStatus(function (b) { e(d, b) }, function (b) { e(d, new g.Printer.Status("")) }) }(c))
  }, 2E3); g.Printer = function (c) {
    BrowserPrint.Device.call(this, c); g.Printer.Status = function (a) {
      this.raw = a; this.isFlagSet = function (a) { return "1" === this.raw.charAt(a) }; this.offline = !1; a || (a = ""); a = a.trim(); h(a) ? (this.offline = !1, this.paperOut = this.isFlagSet(5), this.paused = this.isFlagSet(7), this.headOpen = this.isFlagSet(43), this.ribbonOut = this.isFlagSet(45)) : (this.offline = !0, this.ribbonOut = this.headOpen = this.paused =
        this.paperOut = !1); this.isPrinterReady = function () { return !(this.paperOut || this.paused || this.headOpen || this.ribbonOut || this.offline) }; this.getMessage = function () { return this.isPrinterReady() ? "Ready" : this.offline ? "Offline" : this.paperOut ? "Paper Out" : this.headOpen ? "Head Open" : this.ribbonOut ? "Ribbon Out" : this.paused ? "Paused" : "Ready" }
    }; g.Printer.Info = function (a) { if (!a) throw "Invalid Response"; this.raw = a; a = a.trim(); if (!h(a)) throw "Invalid Response"; a = a.split(","); this.model = a[0].substring(1); this.firmware = a[1] };
    g.Printer.Configuration = function (a) {
      if (!a) throw "Invalid Response"; this.raw = a = a.trim(); this.settings = {}; if (!h(a)) throw "Invalid Response"; a = a.replace(String.fromCharCode(2), ""); a = a.replace(String.fromCharCode(3), ""); a = a.split("\n"); for (var f = 0; f < a.length; ++f) { var b = a[f].trim(), d = b.substring(20); b = b.substring(0, 20).trim(); this.settings[d] = b } this.darkness = parseFloat(this.settings.DARKNESS); this.printSpeed = parseInt(this.settings["PRINT SPEED"].replace("IPS", "").trim()); this.printWidth = parseInt(this.settings["PRINT WIDTH"]);
      this.labelLength = parseInt(this.settings["LABEL LENGTH"]); this.firmwareVersion = this.settings.FIRMWARE.replace("<-", "").trim(); this.linkOSVersion = this.settings.hasOwnProperty("LINK-OS VERSION") ? this.settings["LINK-OS VERSION"] : "0"
    }; var d = this; this.configuration = void 0; this.device_request_queue = []; this.clearRequestQueue = function () { var a = this.device_request_queue[0]; this.device_request_queue = []; a && a.started && (this.device_request_queue[0] = a) }; this.Request = function (a, f, b, c, e) {
      this.type = a; this.command = f;
      this.received = b; this.success = c; this.error = function (a) { return function (f) { a(f); d.executeNextRequest() } }(e); this.execute = function () { this.started = !0; "info" == this.type || "config" == this.type || "status" == this.type ? d.sendThenReadUntilStringReceived(this.command, String.fromCharCode(3), this.received, this.error) : d.sendThenReadAllAvailable(this.command, this.received, this.error) }
    }; this.executeNextRequest = function () { d.device_request_queue.shift(); d.executeRequest() }; this.executeRequest = function () {
      dbg("Requests in queue: " +
        d.device_request_queue.length); 0 < d.device_request_queue.length && (dbg("Executing next request..."), d.device_request_queue[0].execute())
    }; this.queueRequest = function (a) { dbg("Queueing request " + a.type + ": " + d.device_request_queue.length); d.device_request_queue.push(a); 1 === d.device_request_queue.length && a.execute() }; this.onStatusResponse = function (a) {
      dbg("received status response"); var f = void 0; try { f = new g.Printer.Status(a) } catch (k) { a = d.device_request_queue[0], a.error(k), d.executeNextRequest() } for (; 0 < d.device_request_queue.length;)if (a =
        d.device_request_queue[0], "status" === a.type) dbg("delivering status..."), a.success(f), d.device_request_queue.shift(); else { dbg("delivered to all status requests."); break } d.executeRequest()
    }; this.onResponse = function (a, f) { dbg("received info response"); var b = d.device_request_queue[0]; if (void 0 != f) try { a = new f(a) } catch (m) { b.error && b.error(m); d.executeNextRequest(); return } b.success && b.success(a); d.executeNextRequest() }; this.onSGDResponse = function (a) { dbg("received sgd response"); d.onResponse(a) }; this.onInfoResponse =
      function (a) { dbg("received info response"); d.onResponse(a, g.Printer.Info) }; this.onConfigurationResponse = function (a) { dbg("received config response"); try { d.configuration = new g.Printer.Configuration(a) } catch (f) { } d.onResponse(a, g.Printer.Configuration) }; this.setSGD = function (a, f, b, c) { if (!b && !c) return new Promise(function (b, c) { d.setSGD(a, f, b, c) }); d.send('! U1 setvar "' + a + '" "' + f + '"\r\n', b, c) }; this.getSGD = function (a, b, c) {
        if (!b && !c) return new Promise(function (b, f) { d.getSGD(a, b, f) }); b = new this.Request("sgd",
          '! U1 getvar "' + a + '"\r\n', this.onSGDResponse, b, c); this.queueRequest(b)
      }; this.setThenGetSGD = function (a, b, c, e) { if (!c && !e) return new Promise(function (f, c) { d.setThenGetSGD(a, b, f, c) }); this.setSGD(a, b, function () { d.getSGD(a, c, e) }, e) }; this.getInfo = function (a, b) { if (!a && !b) return new Promise(function (a, b) { d.getInfo(a, b) }); a = new this.Request("info", "~hi\r\n", this.onInfoResponse, a, b); this.queueRequest(a) }; this.getConfiguration = function (a, b) {
        if (!a && !b) return new Promise(function (a, b) { d.getConfiguration(a, b) });
        a = new this.Request("config", "^XA^HH^XZ", this.onConfigurationResponse, a, b); this.queueRequest(a)
      }; this.getStatus = function (a, b) { if (!a && !b) return new Promise(function (a, b) { d.getStatus(a, b) }); a = new this.Request("status", "~hs\r\n", this.onStatusResponse, a, b); d.queueRequest(a) }; this.query = function (a, b, c) { if (!b && !c) return new Promise(function (b, c) { d.query(a, b, c) }); b = new this.Request("", a, this.onResponse, b, c); this.queueRequest(b) }; this.isPrinterReady = function (a, b) {
        if (!a && !b) return new Promise(function (a, b) {
          d.isPrinterReady(a,
        }); this.getStatus().then(function (c) { c.isPrinterReady() ? a(c.getMessage()) : b(c.getMessage()) })
      }; this.printImageAsLabel = function (a, c, e, g) { if (!e && !g) return new Promise(function (b, f) { d.printImageAsLabel(a, c, b, f) }); b().then(function (b) { c.fitTo = { width: b.printWidth, height: b.labelLength }; c.action = "print"; BrowserPrint.convert(a, d, c, e, g) }).catch(g) }; this.getConvertedResource = function (a, c, e, g) {
        if (!e && !g) return new Promise(function (b, f) { d.getConvertedResource(a, c, b, f) }); b().then(function (b) {
          c.action = "return";
          BrowserPrint.convert(a, d, c, e, g)
        }).catch(g)
      }; this.storeConvertedResource = function (a, c, e, g) { if (!e && !g) return new Promise(function (b, e) { d.storeConvertedResource(a, c, b, e) }); b().then(function (b) { c.action = "store"; BrowserPrint.convert(a, d, c, e, g) }).catch(g) }; var b = function () { return new Promise(function (a, b) { if (d.configuration) a(d.configuration); else return d.getConfiguration().then(function (a) { d.configuration = a; return d.configuration }).catch(function (a) { b(a) }) }) }; this.configTimeout = function () {
        d.configuration ||
          d.getConfiguration().then(function (a) { return d.configuration = a }).catch(function () { setTimeout(d.configTimeout, 1E3) })
      }; this.configTimeout()
  }; g.watch = function (c, d, b) { b || (b = 2); l[c.uid] = { device: c, status: "", onchange: d, errors: 0, errorsForOffline: b } }; g.stopWatching = function (c) { delete l[c.uid] }; return g
}();
export default {
  data () {
    return {
      printers: null,
      printerLoading: false,
  methods: {
    initPrinters (tableData, autoPrint, callback) {
      if (BrowserPrint) {
        this.printerLoading = true;
        this.$message('正在初始化打印机,请稍等!')
        BrowserPrint.getLocalDevices(devices => {
          this.printers = devices.printer.filter(device => device.deviceType === 'printer');
          if (!this.printers || !this.printers.length) {
            this.$message.error('没有可用的打印机,请检查驱动或USB连接!')
          if (autoPrint) this.printLabel(tableData, callback)
          this.printerLoading = false;
        }, error => {
          this.printerLoading = false;
          this.$message.error('无法找到打印机,请检查驱动或USB连接!')
        });
      } else {
        this.$message.error('BrowserPrint not available')
    printLabel (tableData, callback) {
      if (!this.printers.length) {
        console.error('没有找到打印机!');
        return;
      // For simplicity, we'll use the first printer in the list.
      const printer = this.printers[0];
      let baseX = 1050;
      let baseY = 118;
      let spacingY = 512;
      let spacingX = 100;
      if (printer.manufacturer.includes("Zebra") || printer.name.includes("ZD420") || printer.name.toLowerCase().indexOf("zd420") != -1) {
        console.log("printer === ", printer);
        baseX = 820;
        baseY = 90;
      // let tableData = [
      //   {lable: '仓库',value:'11111111111111'},
      //   {lable: '条码号',value:'CPCP-CI221112-17-60'},
      //   {lable: '状态',value:'1'},
      //   {lable: '关联单号',value:'1'},
      //   {lable: '车牌号',value:'1'},
      //   {lable: '毛重',value:''},
      //   {lable: '物料代码',value:''},
      //   {lable: '过磅时间',value:''},
      //   {lable: '皮重',value:''},
      //   {lable: '规格编号',value:''},
      //   {lable: '入库时间',value:''},
      //   {lable: '净重',value:''},
      //   {lable: '供货单位',value:''},
      //   {lable: '包装规格',value:''},
      //   {lable: '扣杂',value:''},
      //   {lable: '磅单编号',value:''},
      //   {lable: '物料库位',value:''},
      //   {lable: '实际净重',value:''},
      //   {lable: '司磅员',value:''},
      //   {lable: '物料描述',value:''},
      //   {lable: '批次总号',value:''},
      let index = 1;
      let zpl = '^XA'
      let x = baseX;
      let y = baseY;
      for (let item of tableData) {
        if (item.h) {
          zpl += ' ^CI28 ^FO' + (x - spacingX * 2) + ',' + y + '^A@R,32,32,E:SIMSUN.TTF ^FB160,8,,J, ^FD' + (item.lable || '') + ':' + '^FS ';
          zpl += ' ^CI28 ^FO' + (x - spacingX * 2) + ',' + (y + 160) + '^A@R,32,32,E:SIMSUN.TTF ^FB330,8,,J, ^FD' + (item.value || '') + '^FS ';
        } else {
          zpl += ' ^CI28 ^FO' + x + ',' + y + '^A@R,32,32,E:SIMSUN.TTF ^FB160,2,,J, ^FD' + (item.lable || '') + ':' + '^FS ';
          zpl += ' ^CI28 ^FO' + x + ',' + (y + 160) + '^A@R,32,32,E:SIMSUN.TTF ^FB330,2,,J, ^FD' + (item.value || '') + '^FS ';
        if (index === 3) {
          x -= spacingX;
          y = baseY;
          index = 1;
        } else {
          index++;
          y += spacingY;
      zpl += ' ^FO' + baseY + ',' + (baseY + (spacingY * 0.9)) + '^BY3 ^BCR,100,Y,N,N ^FD' + (tableData.find(item => item.lable === '条码号').value || '') + '^FS '
      let bdbh = tableData.find(item => item.lable === '磅单编号').value || '';
      if (bdbh.length > 12) {
        this.$message.error('磅单编号长度大于12,写入RFID将不正确!')
      function stringToHexAscii (input) {
        let hexAscii = '';
        for (let i = 0; i < input.length; i++) {
          const charCode = input.charCodeAt(i);
          const hexValue = charCode.toString(16).padStart(2, '0');
          hexAscii += hexValue.toUpperCase();
        return hexAscii;
      bdbh = stringToHexAscii(bdbh)
      zpl += '^RFW,H^FD' + bdbh + 'FFFFFFFFFFFFFFFFFFFFFFFF' + '^FS'
      zpl += '^XZ'
      printer.send(zpl, _ => {
        this.$message.success('开始打印!')
        callback && callback()
      }, error => {
        this.$message.error('打印失败,请确认打印机状态!')
      });

通过使用JavaScript和BrowserPrint API,开发者可以轻松地将斑马打印机集成到Web应用中,实现从浏览器直接控制打印任务。这种方法简化了传统打印解决方案的复杂性,使得在任何支持JavaScript的平台上都可以实现高效、灵活的打印操作。

Zebra Browser Print is a set of scripts and an end-user application that allows web pages to communicate with Zebra Printers. The application lets a web page communicate to Zebra devices accessible to the client computer. Currently, Zebra Browser Print supports Macintosh OS X Yosemite and above, as well as Windows 7 and 10. Google Chrome, Mozilla Firefox, Internet Explorer, and Apple Safari browsers are supported. It can communicate to Zebra printers connected via USB and Network. For a m
前不久在做项目时,要求要实现对页面中指定内容区域的打印功能,找了很多的资料和方法,经过多次实验,最终选择了如下的方式,实现起来比较简单,对主流浏览器Chrome\Firefox\IE\Safari的支持比较好,对Opera的支持不是很好,不过这个和我的页面内容本身的处理方式有一定的关系。 这个项目类似于Microsoft的MSDN Library,如下图所示。其中左边的内容是从帮助文档htm
web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印 该资源提供了一个vue混入,通过混入提供一个可直接使用的方法执行打印。 在现代物流、仓储和零售行业中,RFID和二维码技术发挥着至关重要的作用。这些技术不仅提高了效率,还增强了追踪和管理的能力。本文将介绍如何使用JavaScript斑马打印机BrowserPrint API打印RFID二维码贴纸。 通过使用JavaScriptBrowserPrint API,开发者可以轻松地将斑马打印机集成到Web应用中,实现从浏览器直接控制打印任务。这种方法简化了传统打印解决方案的复杂性,使得在任何支持JavaScript的平台上都可以实现高效、灵活的打印操作。
斑马打印机是一款常用的热敏打印机,可以通过LabVIEW软件进行控制和打印。在使用斑马打印机之前,我们需要先将打印机连接到计算机上,并确保计算机已经安装了相应的驱动程序。 在LabVIEW中,我们可以使用通信接口(如串口或USB)与斑马打印机建立通信连接。通过串口通信时,我们需要设置好串口的参数(如波特率、数据位数、校验位等),确保与打印机的通信正常进行。 在建立了通信连接之后,我们可以通过LabVIEW编写程序来控制打印机进行打印操作。首先,我们需要设置打印机的一些参数,如打印速度、打印浓度、打印纸张大小等。然后,我们可以通过编写LabVIEW代码,发送打印指令给打印机,使其进行打印。 在LabVIEW中,我们可以使用串口或者网络通信的相关函数模块,如VISA函数库或TCP/IP函数库,来进行打印机的通信操作。通过这些函数模块,我们可以发送打印指令给打印机,如打印文本、条码、图像等。 在编写LabVIEW程序时,我们需要根据斑马打印机的协议文档,了解其支持的指令集和通信协议。通过发送正确的指令,我们可以实现各种打印要求,如打印不同字体、大小、颜色的文本、打印各种条码、打印图像等。 总之,斑马打印机可以通过LabVIEW软件进行控制和打印。我们只需要连接打印机,并编写相应的LabVIEW程序,设置打印参数并发送指令,就可以实现各种打印需求。这样的方法方便快捷,适用于许多需要打印的应用场景。