VUE2连接USB打印机

Vue 2 项目里用 USB 打印机,按场景选用:浏览器内 web → window.print()QZ Tray / WebUSB(限制多);桌面/自托管终端 → 用 Electron / 本地服务 最稳定。下面按优先级与场景分开讲并给出 Vue2 示例。

核心选项比较(快速)

  • window.print():最简单,适合打印页面/票据样式 HTML。优点:无需驱动、跨浏览器;缺点:用户需手动选择打印机、不能发 ESC/POS 原始指令。

  • QZ Tray(推荐用于 POS / 小票机):在客户端运行一个本地 agent(QZ Tray),浏览器 JS 调用它可以发送原始 ESC/POS、ZPL 等指令到任意本地打印机。优点:功能强、广泛支持;缺点:需用户安装 QZ Tray 客户端、HTTPS 配置。

  • WebUSB:浏览器直接访问 USB 设备(需浏览器支持 & HTTPS & 用户授权)。优点:不需要额外客户端;缺点:支持有限、实现较复杂、驱动/协议需自行实现。

  • Electron / Node 后端:如果你能做成桌面应用或有后端,可在服务器/本地进程直接调用打印驱动(node-printer、escpos 等)。最稳定、最灵活,但不是纯前端方案。


方案 A — 最简单:生成 HTML 用 window.print()(适合发票/票据)

不涉及 USB 原始指令,用户可选打印机。

Vue2 示例(SFC):

<template>
  <div>
    <div id="print-area" ref="printArea">
      <!-- 需要打印的票据 HTML -->
      <h2>收据</h2>
      <p>订单编号: 12345</p>
      <p>金额: NT$100</p>
    </div>
    <button @click="print">打印</button>
  </div>
</template>

<script>
export default {
  methods: {
    print() {
      // 简单方式:新开窗口并调用 print(可更好控制样式)
      const printContents = this.$refs.printArea.innerHTML;
      const w = window.open('', '_blank');
      w.document.write(`
        <html><head><title>打印</title>
        <style>
          /* 在这里放打印样式 @media print {...} */
        </style>
        </head><body>${printContents}</body></html>`);
      w.document.close();
      w.focus();
      w.print();
      w.close();
    }
  }
}
</script>

优点:部署快;缺点:需要用户手动选择打印机与选项,不能发送 ESC/POS。


方案 B — 推荐:使用 QZ Tray 发送原始命令(适合小票机、esc/pos)

流程概览:

  1. 客户端安装 QZ Tray(对应系统的可执行程序)。

  2. 在网页中引入 qz-tray.js(或用 npm 包)。

  3. 在 Vue 中通过 qz API 连接、查找打印机并发送 raw data(plain/hex/escpos)。

示例 Vue2 组件(关键片段):

<template>
  <div>
    <button @click="connect">连接 QZ</button>
    <button @click="printText">打印文本</button>
    <button @click="printEscPos">打印 ESC/POS</button>
    <div>选择打印机: {{ printerName }}</div>
  </div>
</template>

<script>
// 假设你在 index.html 用 <script src="https://yourcdn/qz-tray.js"></script>
// 或者通过 npm 安装并 import qz from 'qz-tray'(按 qz 提示)
export default {
  data() {
    return {
      printerName: null
    };
  },
  methods: {
    async connect() {
      try {
        await qz.websocket.connect();
        const printer = await qz.printers.find(); // 默认打印机
        this.printerName = printer;
        alert('已连接 QZ,打印机: ' + printer);
      } catch (e) {
        console.error(e);
        alert('连接 QZ 失败: ' + e);
      }
    },
    async printText() {
      try {
        const cfg = qz.configs.create(this.printerName);
        const data = [{ type: 'raw', format: 'plain', data: 'Hello from Vue2\n\n' }];
        await qz.print(cfg, data);
        alert('打印文本已发送');
      } catch (e) {
        console.error(e);
        alert('打印失败: ' + e);
      }
    },
    async printEscPos() {
      try {
        const cfg = qz.configs.create(this.printerName);
        // 示例: ESC/POS init + 打印并换纸
        const hex = '1B40' // 初始化
                 + '1B6101' // 居中
                 + this.stringToHex('小票測試\n\n')
                 + '1D5601'; // 切纸(视打印机支持)
        const data = [{ type: 'raw', format: 'hex', data: hex }];
        await qz.print(cfg, data);
        alert('ESC/POS 指令已发送');
      } catch (e) {
        console.error(e);
        alert('打印失败: ' + e);
      }
    },
    stringToHex(str) {
      return Array.from(str).map(ch => ch.charCodeAt(0).toString(16).padStart(2, '0')).join('');
    }
  },
  beforeDestroy() {
    try { qz.websocket.disconnect(); } catch(e) {}
  }
};
</script>

注意事项与配置:

  • QZ Tray 要在用户客户端安装并运行(Windows/macOS/Linux)。

  • 出于安全,网页必须走 HTTPS(localhost/127.0.0.1 在多数浏览器可例外)。

  • QZ 文档有关于证书签名、许可和 API 的详细说明(请参考 QZ 官网)。

  • qz.printers.find() 可传入字符串或查找特定打印机。


方案 C — WebUSB(实验性,浏览器限制多)

仅当你能控制客户端浏览器并接受兼容性限制时使用。流程:使用 navigator.usb 选择设备、打开、claimInterface、transferOut 发送 bytes(ESC/POS 二进制)。

示例(仅示意):

async function webusbPrint() {
  // 需要已知厂商/产品 id 或允许用户选择
  const device = await navigator.usb.requestDevice({ filters: [] }); // 空数组会让用户选择
  await device.open();
  if (device.configuration === null) await device.selectConfiguration(1);
  await device.claimInterface(0);
  // 构造 ESC/POS bytes
  const encoder = new TextEncoder();
  const data = encoder.encode('Hello WebUSB\n\n');
  // endpoint number 2 只是示意,实际需查看设备接口描述
  await device.transferOut(2, data);
  await device.close();
}

限制:仅部分 Chromium 浏览器支持;需要 HTTPS;需要开发者对 USB 协议/接口有研究;打印机可能不是直接 USB Bulk endpoint(有些需要自定义驱动)。


方案 D — Electron / 后端打印(最稳定,适合 kiosk / 自托管)

如果是内网设备或你能打包成桌面应用,Electron 结合 node-printernode-escposprinters 等库可以直接访问系统打印机与串口/USB。示例思路:

  • 主进程使用 node-escpos 打印 ESC/POS 到 USB/串口。

  • 渲染进程(Vue)向主进程发送 IPC 请求触发打印。

简短示例(伪):

// 主进程
const escpos = require('escpos');
escpos.USB = require('escpos-usb');
ipcMain.handle('print-receipt', async (event, text) => {
  const device = new escpos.USB();
  const printer = new escpos.Printer(device);
  device.open(() => {
    printer.text(text);
    printer.cut();
    printer.close();
  });
});

实践建议

  1. 只是网页式发票/单据 → 用 window.print()(最快);若要自动选择打印机或发送原始 ESC/POS 指令 → 用 QZ Tray。

  2. 小票机 / POS 场景 → 强烈推荐 QZ Tray 或 Electron(QZ 更适合浏览器端部署)。

  3. 完全浏览器并想免安装 → 尝试 WebUSB(有兼容性与实现复杂度,通常不是首选)。

  4. 若用户设备受控(公司内部) → 可以配合本地服务(如小的 Node 服务)或 Electron,部署最可控可靠。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值