Skip to content
On this page

静默打印

有两种实现打印的方式,一是electron提供的api,另一个是node实现打印

electron自带api打印

electron打印其实就是打印当前页面

js
ipcMain.on('fromRender', (_, params) => {
  switch (params.event) {
    case 'print': // 接收到来自渲染进程的打印指令
      // print参数是可选的,silent:是否静默打印,copies:打印份数
      mainWindow.webContents.print({silent:true,copies:1  },(success,failureReason)=>{
        if(success){
          console.log('打印成功')
        }else{
          console.log('打印失败',failureReason)
        }
      })
      break
  }
})

在实际项目中需要进行小票打印,我的做法是打开一个新窗口,然后将要打印的内容渲染到这个窗口内,然后打印这个窗口。创建打印窗口是非常耗资源的,所以要避免一直创建销毁。比如在登录成功的时候创建、退出登录的时候销毁。

print.js

js
import { BrowserWindow, app } from 'electron'
import path, { dirname } from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

let printWin
const otherWindowConfig = {
  height: 595,
  useContentSize: true,
  width: 800,
  autoHideMenuBar: false,
  minWidth: 100,
  show: true, // 是否显示窗口,调试的时候可以设置为true,生产false
  webPreferences: {
    // contextIsolation: true,
    nodeIntegration: true,
  }
}

function closePrintWindow() {
  if (printWin) {
    printWin.destroy()
    printWin = null
  }
}

function initPrintWindow() {
  if (printWin) {
    // win.hide() /* 测试*/
    printWin.destroy()
  }
  printWin = new BrowserWindow({
    ...Object.assign(otherWindowConfig, {})
  })
  console.log('initPrintWindow',printURLCustom());
  printWin.loadURL(printURLCustom())
  printWin.setMenu(null)

  printWin.on('closed', () => {
    printWin = null
  })
}

function executePrint(option) {
  // 这里可以通过进程通信将要打印的数据发送到打印页面
  // 打印页面接收到数据后,再发送打印指令到当前进程
  // 这里只是简单示例,直接调用打印
  printWin.webContents.print(option,(success,failureReason)=>{
    if(success){
      console.log('打印成功')
    }else{
      console.log('打印失败',failureReason)
    }
  })
}

function getUrl(devPath, proPath, hash) {
  const url = app.isPackaged ? new URL('file://') : new URL(`http://localhost:8100/`)
  url.pathname = app.isPackaged ? proPath  : devPath
  url.hash = hash
  return url.href
}

const printURLCustom = () => {
  const url = getUrl('', path.join(__dirname, '..', 'dist', 'index.html'), `#/print`)
  return url
}

export {
  initPrintWindow, executePrint, closePrintWindow
}


在主进程index.js中调导出的打印相关方法

js
import { initPrintWindow, executePrint } from './print.js'

// 页面加载完成初始打印窗口
mainWindow.webContents.on('did-finish-load', () => {
  // ……
  initPrintWindow()
});

// 接收渲染进程的指令
ipcMain.on('fromRender', (_, params) => {
  switch (params.event) {
    case 'update':
      console.log('接收到渲染进程的更新信息', params.args);
    break
    case 'print':
      // print参数是可选的,silent:是否静默打印,copies:打印份数
      mainWindow.webContents.print({silent:false,copies:1  },(success,failureReason)=>{
        if(success){
          console.log('打印成功')
        }else{
          console.log('打印失败',failureReason)
        }
      })
      break
    case 'printReceipt':
      // 小票打印
      // params.args: 
      executePrint(params.args)
      break
  }
})


渲染进程发送打印指令

tsx
 const handlePrintReceipt = () => {
    if (!isElectron()) return
    const option = {
      copies: 1,
      printerName: '打印机名称',
      landscape: false,
      margins: { marginType: 'none' },
      // dpi: { horizontal: 300, vertical: 300 }
      // pageRanges: [{ from: 0, to: 0 }]
      // pageSize: { width: 80000, height: 100000 }
    }
    window.mainAPI.sendToMain({ 'event': 'printReceipt', args: { option}})
  }

node实现打印

在node环境中直接发送打印指令到打印机实现打印,和electron框架无关,这也意味着只要支持node环境就可实现打印

可以使用这个库 Klemen1337/node-thermal-printer: Node.js module for Epson, Star, Tanca, Drauma and Brother thermal printers command line printing. (github.com)

示例

js
const { ThermalPrinter, PrinterTypes, CharacterSet, BreakLine } = require('node-thermal-printer');

async function example() {
  const printer = new ThermalPrinter({
    type: PrinterTypes.EPSON, // 'star' or 'epson'
    // interface: 'printer:auto',// 试了,没用
    // interface: '//192.168.0.97/GP-L80160 Series 58',
    // interface: '//192.168.0.97/XP-80C', // 试了,没用
    interface: 'tcp://192.168.0.61:9100', // 打印机的ip
    // driver:{},
    // options: {
    //   timeout: 1000,
    // },
    width: 48, // Number of characters in one line - default: 48
    characterSet: CharacterSet.CHINA, // Character set - default: SLOVENIA
    breakLine: BreakLine.WORD, // Break line after WORD or CHARACTERS. Disabled with NONE - default: WORD
    removeSpecialCharacters: false, // Removes special characters - default: false
    lineCharacter: '-', // Use custom character for drawing lines - default: -
  });


  // printer.alignCenter()
  // printer.setTextDoubleWidth()
  // await printer.printImage('./img.png'); // 打印图片过大时可能乱码

  // printer.setTypeFontB();
  // printer.println('Type font B');
  // printer.setTypeFontA();
  // printer.setTextSize(4, 4);
  // printer.println('Type font A');
  // printer.println('中文字体啊啊啊啊啊啊啊啊啊发光飞碟更好地给很过分好的');

  // printer.printQR('123456',{
  //   cellSize: 8, // 最大值是8
  //   correction: 'L',
  //   model: 20
  // })


  // printer.cut();

  // try {
  //   await printer.execute();
  //   console.log('Print success.');
  // } catch (error) {
  //   console.error('Print error:', error);
  // }

}

example()

Released under the MIT License.