В проекте electronic+vue реализована функция печати чеков

Electron

Предисловие: Для этой статьи требуются некоторые изучающие основы электроники. Для получения дополнительной информации перейдите наэлектронная официальная документация.

1. Требования:

公司项目需要通过electron调用系统打印机,实现打印小票的功能。

2. Анализ:

electron打印大概有两种:

第一种:通过window的webcontent对象,使用此种方式需要单独开出一个打印的窗口,可以将该窗口隐藏,但是通信调用相对复杂。
第二种:使用页面的webview元素调用打印,可以将webview隐藏在调用的页面中,通信方式比较简单。

两个对象调用打印方法的使用方式都一样。

本文是通过第二种方法实现静默打印。

3. Процесс реализации:

1. Чтобы реализовать функцию печати, мы должны сначала узнать, какие принтеры есть на нашем устройстве. Метод такой: в потоке рендеринга событие отправляется в основной поток через объект ipcRenderer электрона. (Поток рендеринга в этой статье можно рассматривать как файл print.vue)

(1)主线程(electron.js)伪代码如下:
//引入electron
import electron from 'electron';

//创建一个浏览器对象
const window = new electron.BrowserWindow({
    width,
    height,
    frame: false,
    show: false,
    backgroundColor: '#4b5b79',
    minWidth: 1024,
    minHeight: 768,
    webPreferences: { webSecurity: false },
  });
  
//在主线程下,通过ipcMain对象监听渲染线程传过来的getPrinterList事件
electron.ipcMain.on('getPrinterList', (event) => {
    //主线程获取打印机列表
    const list = window.webContents.getPrinters();
    
    //通过webContents发送事件到渲染线程,同时将打印机列表也传过去
    window.webContents.send('getPrinterList', list);
});

===============================================================================

файл print.vue

(2)渲染线程(print.vue文件)伪代码如下:
<template>
</template>
<script>
    //引入ipcRenderer对象,该对象和主线程的ipcMain通讯
    import { ipcRenderer } from 'electron';
    
    //渲染线程主动发送getPrinterList事件到主线程请求打印机列表
    ipcRenderer.send('getPrinterList'); 
    
    //监听主线程获取到打印机列表后的回调
      ipcRenderer.once('getPrinterList', (event, data) => {
        //data就是打印机列表
        this.printList = data;
      });
</script>

//获取打印机列表完成

2. (Основное событие здесь) После получения списка принтеров вам нужно использовать тег «webview», который поставляется с электроном, чтобы добиться набора квитанций. Что такое "веб-просмотр"? Думайте об этом как о теге «iframe», который показывает, что вам нужно напечатать.

(1) Перед использованием «webview» вам необходимо создать новый файл print.html для отображения содержимого, которое вы хотите распечатать через print.html. Требование нашего проекта состоит в том, чтобы нарисовать содержимое для печати через холст, затем преобразовать холст в ресурс изображения (base64), а затем поместить его в «веб-просмотр» для отображения. Конкретный метод: в потоке рендеринга (print.vue) выполнить серию логических операций, наконец, сгенерировать ресурсы base64, а затем определить событие «webview-print-render» через webview.send(), которое может взаимодействовать со страницей print.html, передавать base64 в print.html страница для отображения, псевдокод print.vue показан ниже:

<template>
  <div v-show="false">
    <webview ref="printWebview" src="./xxxx/print.html" nodeintegration/>
  </div>
</template>

 <script>
 methods: {
    printRender(imgsrc) {
      // 获取<webview>节点
      const webview = this.$refs.printWebview;
      // 发送信息到<webview>里的页面
      webview.send('webview-print-render', {
        printName: this.printDeviceName, //打印机名称
        imgSource: imgsrc, // base64图片
      });
    },
}
</script>

print.html Код:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
  //@page样式是用来设置打印机打印出来的样式,例如设置小票外边距样式
    @page {
      margin: 0px;
    }
  </style>
</head>
<body id='bd'>
</body>
<script>
    //引入ipcRenderer对象
  const {ipcRenderer} = require('electron')
  
  //监听渲染线程传过来的webview-print-render事件
  ipcRenderer.on('webview-print-render', (event, deviceInfo) => {
    // 动态创建一个img标签,然后插入到<body>中。deviceInfo是渲染线程传过来的数据
    let html = '';
    html = `<img src="${deviceInfo.imgSource}"
     width="${deviceInfo.imgWidth}px"
     height="${deviceInfo.imgHeight}px">`;
    document.getElementById('bd').innerHTML = html;
    
    //当图片插入到页面后,通过ipcRenderer对象的sendToHost方法和渲染线程通讯,告诉渲染线程打印的内容已经准备完毕,请开始打印操作
    ipcRenderer.sendToHost('webview-print-do');
  });
</script>
</html>

(2) После создания html-файла импортируйте print.html в "webview src="./xxxx/print.html"". «Веб-представление» должно быть явно определено в файле print.vue, но его нужно скрыть с помощью v-show = «false», а не v-if, потому что нам нужно, чтобы узел dom «веб-представления» существовал на страницу, просто не показывайте ее.

<template>
  <div v-show="false">
    <webview ref="printWebview" src="./xxxx/print.html" nodeintegration/>
  </div>
</template>

<script>
mounted() {
    //当vue节点渲染完成后,获取<webview>节点
    const webview = this.$refs.printWebview;
    
    //监听<webview>里面的消息,也就是监听print.html里面的ipcRenderer.sendToHost发送的事件,当该事件发送成功后就会进入下面的回调事件中执行打印操作。
    webview.addEventListener('ipc-message', (event) => {
      if (event.channel === 'webview-print-do') {
        //如果收到<webview>传过来的事件,名为"webview-print-do",就执行 webview.print打印方法,打印<webview>里面的内容。
        webview.print(
          {
            //是否是静默打印
            silent: true,
            printBackground: true,
            //打印机的名称,就是本文一开始获得的打印机列表其中一个
            deviceName: 'xxx',
          },
          (data) => {
            //这个回调是打印后的回调事件,data为true就是打印成功,为false就打印失败
            console.log('webview success', data);
          },
        );
      }
    });
},
</script>

В этот момент реализуется функция этого электрона по вызову принтера. Однако в этой статье много деталей, которые не упоминаются, а лишь дают общее представление, если что-то не так с написанием, прошу меня простить.