electron開發 - 打印流程(僅支持6.0.0版本以上)

Electron打印

標籤打印

標籤打印通常有兩種方式:html

  1. 驅動打印,與普通打印機同樣經過驅動方式打印。
  2. 經過指令打印,不一樣廠家的的打印機指令集不同,可查看廠家提供的手冊。

electron 打印方式

  1. 直接調用打印機打印
  2. 打印到pdf

打印流程

  1. 本機安裝打印機驅動
  2. 配置打印機名稱
  3. 調用打印前判斷打印機是否可用
  4. 打印

打印機返回狀態參考node

status爲0時表示打印機可用react

調用方式web

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

webcontent打印

  1. 主進程建立一個打印窗口(print.html)
  2. 經過主進程和組件(渲染進程)交互,確認打印機可用
  3. 組件選擇打印機,推送打印機詳情和須要打印的信息到獨立的print.html(打印窗口)
  4. 打印窗口通知主進程打印

// 主進程

// 建立窗口
function createPrintWindow() {
  printWindow = new BrowserWindow({
    title: '打印',
    // show: false,
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
    }
  })
  printWindow.loadURL(`file://${path.join(__dirname, '../electron/print/print.html')}`);
  electronHelper.initPrintEvent(printWindow, mainWindow)
}

// 初始化打印機

function initPrintEvent(printWindow, mainWindow) {
  ipcMain.on('print-start', (event, obj) => {
    console.log('print-start')
    printWindow.webContents.send('print-edit', obj);
  })
  // 得到打印機列表
  ipcMain.on('getPrinters', () => {
    console.log('received getPrinters msg');
    const printers = printWindow.webContents.getPrinters();
    mainWindow.send('printerList', printers)
  })
  // 驗證打印機狀態並打印
  ipcMain.on('tagPrint', (event, deviceName) => {
    const printers = printWindow.webContents.getPrinters();
    console.log('printers:', printers)
    printers.forEach(element => {
      if (element.name === deviceName && element.status !== 0) {
        mainWindow.send('print-error', deviceName + '打印機異常');
        printWindow.webContents.print({
          silent: false,
          printBackground: false,
          deviceName: ''
        },
          (data) => {
            console.log("回調", data);
          });
      } else if (element.name === deviceName && !element.status) { // 打印機正常
        console.log(element.status + '-' + deviceName)
        printWindow.webContents.print({
          silent: true,
          printBackground: false,
          deviceName: element.name
        }, (success, failureReason) => {
          if (success) {
            console.log('print success')
          }
          if (failureReason === 'cancelled') {
            console.log('print cancelled');
          }
          if (failureReason === 'failed') {
            console.log('print failed');
          }
        });
      }
    });

  })
}
// 組件(渲染進程)
/**
 * 經營管理 - 商品價籤打印
 */

import React, { useState } from 'react'
import CommonWrap from '@cpsCommon/CommonWrap'
import { withRouter, RouteComponentProps } from 'react-router-dom'
import { ipcRenderer as ipc } from 'electron'
import { Button, Select } from 'antd'

const { Option } = Select;

const TagPrint = (props: any & RouteComponentProps) => {

  const [state, setState] = useState({
    printMsg: '這是我要打印的測試內容: TAG_PRINT',
    dataItem: [],
    currentPrinter: ''
  })

  const changeLoginInfo = (type: string, value: any) => {
    setState({ ...state, [type]: value })
  }

  const handleChange = (value) => {
    console.log(`selected ${value}`);
    changeLoginInfo('currentPrinter', value)
  }

  const getPrint = () => {
    console.log('發送獲取打印機列表消息');
    if (!ipc) return;
    ipc.send('getPrinters');
    ipc.on('printerList', (event, data: []) => {
      console.log(data); // data就是返回的打印機數據列表
      changeLoginInfo('dataItem', data)
    });
  }
  const startPrint = () => {
    if (!ipc) return;
    ipc.send('print-start', {
        html: state.printMsg,
        deviceName: state.currentPrinter
    });
  }
  return (
    <CommonWrap id='logincomwrap'>
      <div>商品價籤打印</div>
      <div>{state.printMsg}</div>
      <Button onClick={getPrint}>
        獲取打印機列表
      </Button>
      <Button onClick={startPrint}>
        開始打印
      </Button>
      <h5>打印機選擇</h5>
      <Select defaultValue="" style={{ width: 120 }} onChange={handleChange}>
        {state.dataItem.map((item: any) => {
          // eslint-disable-next-line react/jsx-key
          return (<Option value={item}>{item}</Option>);
        })}
      </Select>
    </CommonWrap>
  )
}

export default withRouter(TagPrint)
// 打印窗口(print.html)
const { ipcRenderer } = require('electron');
const _mockDevice = {
    pageUrl: 'http://192.168.2.205:8042/cw?defaultLogin=true&deviceCode=8011',
    deviceName: 'Printer001'
}
ipcRenderer.on('print-edit', (event, obj) => {
    console.log('打印頁接收到print-edit', obj);
    let html = '';
    html += `<div>${obj.html}</div>`
    document.body.innerHTML = html;
    ipcRenderer.send('tagPrint', obj.deviceName);
    // ipcRenderer.send('do', _mockDevice.deviceName);
});

這個窗口不能隨時打印隨時建立,比較耗費性能。能夠將它在程序運行時啓動好,並作好事件監聽。api

// 主進程
function createPrintWindow() {
  printWindow = new BrowserWindow({
    title: '打印',
    // show: false,
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
    }
  })
  printWindow.loadURL(`file://${path.join(__dirname, '../electron/print/print.html')}`);
  electronHelper.initPrintEvent(printWindow, mainWindow)
}


app.whenReady().then(() => {
  createPrintWindow()
});

webview打印

渲染進程和打印的webview頁面作通訊,無需經過主進程,性能較好;antd

流程react-router

  1. 從主進程獲取打印機列表(和上一個方式一致)
  2. 組件初始化時,經過webview發送 ipc-message事件創建鏈接
  3. 處理須要打印的信息
  4. 點擊打印,經過webview.send發送事件和打印信息,引用的頁面(webview src)接收通知
  5. 引用的頁面渲染打印信息,經過ipcRenderer.sendToHost通知組件能夠打印了
  6. webview.print()打印
// 組件
  useEffect(() => {
    console.log('htmlURl', state.printHtmlUrl);
    const webview: any = document.getElementById("printWebview");
    console.log('webview',webview);
    if (webview) {
      webview.addEventListener('ipc-message', (event: any) => {
        console.log('進入webview打印');
        if (event.channel === 'webview-print-do' && state.currentPrinter) {
          // if (event.channel === 'webview-print-do') {
          webview.print(
            {
              silent: false,
              printBackground: true,
              deviceName: state.currentPrinter
            },
            (data) => {
              console.log('打印結果:', data);
            },
          )
        }
      })
    }
  }, [])

  const startPrintWebview = () => {
    const webview: any = document.getElementById("printWebview");
    webview.send('webview-print-render', {
      printName: state.currentPrinter,
      html: state.printMsg
    })
  }
// webview
const { ipcRenderer } = require('electron');
const _mockDevice = {
    pageUrl: 'http://192.168.2.205:8042/cw?defaultLogin=true&deviceCode=8011',
    deviceName: 'Microsoft Print to PDF'
}
ipcRenderer.on('print-edit', (event, obj) => {
    console.log('打印頁接收到print-edit', obj);
    let html = '';
    html += `<div>${obj.html}</div>`
    document.body.innerHTML = html;
    ipcRenderer.send('tagPrint', obj.deviceName);
    // ipcRenderer.send('do', _mockDevice.deviceName);
});

ipcRenderer.on('webview-print-render', (event, info) => {
    console.log('webview-print-render')
    // 執行渲染
    document.body.innerHTML = info.html
    ipcRenderer.sendToHost('webview-print-do')
})
注意事項

默認狀況下,Electron >= 5禁用 webview 標籤。 在構造 BrowserWindow 時,須要經過設置 webviewTag webPreferences選項來啓用標籤。 更多信息請參看 BrowserWindows 的構造器文檔。app

相關文章
相關標籤/搜索