electron20 打印

1,235 阅读2分钟

背景

使用 electron 静默打印二维码。

框架

  • electron-forge
  • webpack
  • TypeScript

一、使用electron-pos-printer(不推荐)

准备

  • @electron/remote
  • electron-pos-printer

安装

npm install @electron/remote --save

npm install electron-pos-printer --save

效果如下:

"dependencies": {
    ...
    "@electron/remote": "^2.0.8",
    "electron-pos-printer": "^1.2.4",
}

操作

1. index.ts 页面修改

import { app, BrowserWindow, ipcMain } from 'electron';
import * as _electronRemote from '@electron/remote/main';

...

const createWindow = (): void => {
    ...
    _electronRemote.initialize();
    _electronRemote.enable(mainWindow.webContents);
    ...
    //获得打印机列表
  ipcMain.on('allPrinters', async (event) => {
    const printers = await mainWindow.webContents.getPrintersAsync();
    event.sender.send('printers', printers);
  });
};

2. preload.ts 页面修改

import { ipcRenderer, contextBridge, PrinterInfo } from 'electron';
import { toPrint } from './lib/print'

let printers:PrinterInfo[] = [];

ipcRenderer.send('allPrinters');
ipcRenderer.on('printers', (event, _printers) => {
  printers = _printers;
});

function print (value: string, printerName?:string): void {
  toPrint(value, printers.some((printer)=>{return printer.name==printerName}) ? printerName : '');
}

contextBridge.exposeInMainWorld('electronAPI', {
  print: print
});

3. lib/print.ts 页面修改

// 打印
import { PosPrintData, PosPrintOptions } from 'electron-pos-printer';
import * as remote from '@electron/remote';
const { PosPrinter } = remote.require("electron-pos-printer");

let printOptions: PosPrintOptions = {
  preview: false,               // 打印预览
  width: '90px',               //  宽度
  margin: '0 0 0 0',            // 外边距
  printerName: '',        // 打印机名称
  timeOutPerLine: 400,    //超时时间
  pageSize: { height: 301000, width: 71000 }  // 页面大小
}

/**
 * 去打印
 * value:二维码数据
 */
function toPrint (value: string, printerName: string) {
  const silent = !!printerName;
  const data: PosPrintData[] = [
    {
      type: 'qrCode',
      value,
      height: '90',
      width: '90',
      displayValue: true,
      style: `margin-left:20px;`,
    }
  ];
  printOptions = { ...printOptions, printerName, silent }
  PosPrinter.print(data, printOptions)
    .then(() => {
      console.log('打印成功');
    })
    .catch((error: any) => {
      console.error('打印错误', error);
    })
}

export { toPrint }

4. window.d.ts 页面修改

增加全局变量

export interface IElectronAPI {
  getPrint?: function,
}

declare global {
  interface Window {
    electronAPI: IElectronAPI
  }
}

5. electron-pos-printer bug 修改

以上的代码写完了后发现点击打印TimedOut,在node_modules/electron-pos-printer/pos-printer.js的91行修改代码如下:

webPreferences: { 
    nodeIntegration: true, 
    contextIsolation: false, 
 }

6.总结

以上方法完成打印,但是remote已经被electron遗弃,electron-pos-printer还有已知的bug,所以不推荐大家使用。下面介绍我总结的方法。

二、使用webContents.print

思想

创建一个打印窗口,打印完后关掉。

1. index.ts 修改

// 打印
  ipcMain.on('toPrint', (event, url, printerName) => {
    const printWindow = new BrowserWindow({
      height: 10,
      width: 10,
      webPreferences: {
        preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
        nodeIntegration: true, // 允许浏览器环境使用Node API
      },
    });
    printWindow.loadURL(`${EDC_URL}${url}`);
    printWindow.once('ready-to-show', () => {
      printWindow.webContents.print({
        silent: true,
        deviceName: printerName
      }, (success, errorType) => {
        if (!success) console.log(errorType);
        printWindow.close();
      });
    });
  });

2. preload.ts 修改

import { ipcRenderer, contextBridge, PrinterInfo } from 'electron';

let printers:PrinterInfo[] = [];

ipcRenderer.send('allPrinters');
ipcRenderer.on('printers', (event, _printers) => {
  printers = _printers;
});

function print (url: string, printerName?:string): void {
  ipcRenderer.send('toPrint', url, printers.some((printer)=>{return printer.name==printerName}) ? printerName : '');
}

contextBridge.exposeInMainWorld('electronAPI', {
  print: print
});

3. window.d.ts 页面修改(同上)