electron + vue項目實現打印小票功能

前言:該文章須要必定的electron基礎同窗。如需瞭解更多相關信息,請移步electron官方文檔html

1、需求:

公司項目須要經過electron調用系統打印機,實現打印小票的功能。
複製代碼

2、分析:

electron打印大概有兩種:

第一種:經過window的webcontent對象,使用此種方式須要單獨開出一個打印的窗口,能夠將該窗口隱藏,可是通訊調用相對複雜。
第二種:使用頁面的webview元素調用打印,能夠將webview隱藏在調用的頁面中,通訊方式比較簡單。

兩個對象調用打印方法的使用方式都同樣。

本文是經過第二種方法實現靜默打印。
複製代碼

3、實現過程:

一、要實現打印功能,首先要知道咱們的設備上有哪些打印機。方法是:在渲染線程經過electron的ipcRenderer對象發送事件到主線程獲取。(本文的渲染線程能夠當作爲一個print.vue文件)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文件node

(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>

//獲取打印機列表完成
複製代碼

二、(重頭戲來了)獲取打印機列表後,就須要經過electron自帶的"webview"標籤實現小票排版。"webview"是什麼?能夠把它當作"iframe"標籤,它裏面顯示的是你須要打印的內容。web

(1)使用"webview"以前,須要新建一個print.html文件,把你要打印的內容經過print.html顯示出來。咱們項目的需求是將要打印的內容經過canvas畫出後,再將canvas轉成圖片資源(base64),而後放到"webview"裏面顯示.具體作法是:在渲染線程(print.vue)作一系列邏輯,最終生成base64資源,而後經過webview.send()定義一個'webview-print-render'事件,該事件能夠和print.html頁面通信,將base64傳給print.html頁面作展現,print.vue僞代碼以下:canvas

<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"》。該"webview"須要顯式的定義在print.vue文件中,但須要將它用v-show="false"隱藏,不能用v-if,由於咱們須要"webview"的dom節點存在於頁面上,只是不展現而已。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>
複製代碼

到這裏本electron調用打印機的功能就實現了。但本文章有不少細節沒有講到,只是大概的給了一個思路,若是寫的有不對之處,還望見諒。electron

相關文章
相關標籤/搜索