Remember once Electron+vue realizes dynamic printing of small tickets

1. Business scenarios

    The company has a cash register product of Electron+Vue. After the cash register, the order information needs to be printed out through the receipt, and some problems and bugs encountered in this demand need to be recorded.

2. Solutions

    Render the content to be printed through webview or a new window, and then output the page content to the small ticket machine through the webcontents.print api and print it silently

 3. Code implementation

        3.1 The rendering process triggers printing

        This code is implemented using vue3+electron, but in order to facilitate the maintenance of the project and solve the problem that the client also needs to be updated when the web page is updated in the early stage, the client code and webPage are structured into two projects by me, so the ipc here is through the window. exposed. When you click Print, the configuration and the data to be printed will be sent to the main process.

// 处理点击打印的事件
const handlePrint = () => {
    const { ipcRenderer } = window.require('electron')
    ipcRenderer.invoke("my-print", JSON.stringify({
        option: {
            silent: true,
            deviceName: store.state?.config?.defaultLittlePrinter,
            printBackground: true,
            margins: {
                marginType: "none"
            },
            scaleFactor: 80,
        },
        data: {
            orderDetail: state.orderDetail
        }
    }));
}

        3.2 The main process receives and processes events

        The main process starts to create the window after receiving the my-print event

ipcMain.handle('my-print', (event, params) => {
    this.createPrintWindow(JSON.parse(params))
});

createPrintWindow code to create a window

createPrintWindow(params) {
    // 实例化一个窗口出来
    this.printWindow = new BrowserWindow({
      width: 150,
      minHeight: 100,
      frame: false,
      skipTaskbar: true,
      transparent: true,
      resizable: false,
      show: false,  //不要让窗口显示出来
      webPreferences: {
        contextIsolation: false,
        webviewTag: true,
        nodeIntegration: true,
        webSecurity: false,
      }
    })
    // 让窗口去加载webPage里面的某个路由
    this.printWindow.loadURL("http://localhost:3001/#/print")
    // 页面加载完成了就可以执行打印的流程了
    this.printWindow.once('ready-to-show', async () => {
      setTimeout(() => {
        this.printWindow.webContents.send('getPrinterData', params.data.orderDetail);
      }, 100);
      setTimeout(() => {
        this.printWindow.webContents.print(params.option, (success: boolean, failureReason: string) => {
          this.printWindow.destroy()
          this.printWindow = null
        })
      }, 1000);
    })
  }

The loaded locahost:3001/print code

<script setup>
import { ref } from "vue"
import { useStore } from "vuex"
const store = useStore()
const orderDetail = ref()
const { ipcRenderer } = window.require("electron")
ipcRenderer.once("getPrinterData", (event, data) => {
    orderDetail.value = data
});
</script>

Here, two timers are directly used to ensure that the data can be received when the page is loaded and the page can be rendered when printing. Although it is a stupid method, the main function is to realize the function. What I thought at first was that the mainWindow page and the printWindow page are both a project that can be saved directly using vuex, but after creating a new window, the vuex of the new window is re-instantiated, and the value cannot be obtained, and then directly through ipc Pass the data back to the Print page when it is passed to the main process and then printed. But how to transfer data is not very important, you can even persist a data through localStorage, database, etc., print it and then delete it.

4.bug

NOTICE: The electron version I used before was 19.0. Repeated attempts to call the print api would report an error. Later, I replaced it with the latest version 19.0.8. .

The two setTimeouts here are very eye-catching. When you have time, optimize them into promises

Why use BrowserWindow to implement instead of using webview? For webview, you also need to write a static html file as the structure you print. It is easier to print the structure of vue directly using BrowserWindow

To add, the list of printers in the project is managed through configuration, and when printing a small ticket, the name of the small ticket machine is directly passed to the main process for silent printing.

Guess you like

Origin blog.csdn.net/qq_52965813/article/details/125992424