electron打印大概有两种:
第一种:通过window的webcontent对象,使用此种方式需要单独开出一个打印的窗口,可以将该窗口隐藏,但是通信调用相对复杂。
第二种:使用页面的webview元素调用打印,可以将webview隐藏在调用的页面中,通信方式比较简单。
两个对象调用打印方法的使用方式都一样。
本文是通过第二种方法实现静默打印。
注意: 渲染进程通信需要使用ipcRenderer,页面只能通过require引入ipcRenderer,必须得支持node,如果你的electron版本 > 6.0的话使用webview需要配置webviewTag。我的配置如下
new BrowserWindow({
webPreferences: {
// 允许使用node
nodeIntegration: true,
contextIsolation: false,
// 允许使用remote
enableRemoteModule: true,
// 允许跨域
webSecurity: false,
// 允许使用webview
webviewTag: true
}
})
1. 首先获取打印机列表
在需要获取打印机列表的页面请求获取
const { ipcRenderer } = require("electron") // 发送给主进程消息 ipcRenderer.send('allPrint') ipcRenderer.once('printName',(event,data)=>{ console.log(data) // data就是返回的打印机数据列表 })
主进程 main.js 中2
// 监听渲染进程发送的消息 ipcMain.on('allPrint',()=>{ // 获取到打印机列表 const printers = win.webContents.getPrinters() // 把获取的打印机列表发送给渲染进程 win.webContents.send('printName',printers) })
由于我是再page1渲染进程中又打开的子渲染进程page2 (若只有page1渲染进程可以跳过这一步)
// 监听获取打印机列表中发送给page2 ipcRenderer.on('printName',(event, data)=>{ page2Win.webContents.send('printName', data) })
2.页面引用webview
<template>
<el-button @click="printView">开始打印</el-button>
<webview ref="printWebview" :src="url" nodeintegration hidden>
</template>
<script>
import { defineComponent, reactive, toRefs, onMounted, ref, unref} from "vue"
import config from "@/common/lib/config"
const { ipcRenderer } = require("electron")
export default defineComponent({
setup(){
let data = reactive({
url: process.env.CVE_ENV === 'development' ? config.dev_url.print : config.pro_url.print
})
const printWebview = ref(null)
onMounted(()=>{
getPrint()
})
const printView = () =>{
unref(printWebview).print({
//是否是静默打印
silent: true,
printBackground: true,
deviceName: '你的获取的打印机列表的打印机名称',
})
}
//获取打印机列表
const getPrint = () => {
ipcRenderer.send('allPrint')
ipcRenderer.once('printName',(event,data)=>{
console.log(data) //data就是返回的打印机数据列表
})
}
return {
...toRefs(data),
printWebview,
printView
}
}
})
</script>
当然看完上面的你可能不知道webview引入的页面从哪里来,接着往下看
3.配置vite.config.js
export default defineConfig({
// publicDir,
resolve: {
// 目录别名配置
alias: {
"@": path.resolve(__dirname, "src")
},
},
build:{
rollupOptions: {
// 多页应用配置
input: {
main: path.resolve(__dirname, 'index.html'), // 主应用入口
// 这里这个打印页面需要再vite中配置多页面应用
settle: path.resolve(__dirname, 'projects/settle/index.html'), // 结算中心
print: path.resolve(__dirname, 'projects/settle/print.html') // 小票打印页面
},
external: ['electron'], // 告诉 Rollup 不要去打包 electron
}
},
optimizeDeps: {
exclude: ['electron'], // 告诉 Vite 不要转换 electron
},
plugins: [
vue({
script: {
refSugar: true
}
})
]
})
然后再你的根目录下创建projects文件夹,再projects文件夹下面创建settle文件夹 settle文件夹下面创建print.html 这个入口文件地址和你vite配置的多页应用入口文件地址对应就行
附上我上面使用webview开发环境和编译后的环境地址
// 开发环境运行地址
dev_url: {
print: `http://localhost:${process.env.CVE_PORT || 3000}/projects/settle/print.html`,
},
// 生产环境运行地址
pro_url:{
print: "app://./projects/settle/print.html"
}
最后附上print.html内容
<!DOCTYPE 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>电子小票</title>
</head>
<body id='bd'>
张三
</body>
<script>
//引入ipcRenderer对象
const {ipcRenderer} = require('electron')
//监听渲染线程传过来的webview-print-render事件
ipcRenderer.on('webview-print-render', (event, deviceInfo) => {
console.log(deviceInfo)
//当图片插入到页面后,通过ipcRenderer对象的sendToHost方法和渲染线程通讯,告诉渲染线程打印的内容已经准备完毕,请开始打印操作
ipcRenderer.sendToHost('webview-print-do')
})
</script>
</html>