前段时间,公司有个需求,要实现前端静默(点击按钮直接打印,不须要预览),本想着直接用window.print()来实现,让用户多点击一下按钮的事儿,无奈咱们的产品: css
最后发现同事以前用过 clodop.js 来实现前端打印;一顿操做猛如虎以后发现打印出来会有水印,最终也是选择放弃。html
偶然的机会在Electron文档中找到了前端
webview.print({
silent Boolean (可选) - 不询问用户打印信息,默认为 false。
})
就开始一顿操做如虎了
复制代码
目录结构vue
my-project
├─ .electron-vue
├── package-lock.json
├── package.json
├── src
│ ├── index.ejs
│ ├── main
│ │ ├── index.dev.js
│ │ ├── index.js
│ │ └── server.js
│ └── renderer
│ ├── App.vue
│ ├── components
│ ├── main.js
│ ├── router
│ ├── store
│ └── view
├── static
│ ├── PDFtoPrinter.exe //打印pdf插件
│ ├── config.txt
│ ├── icon.ico
│ ├── icon2.ico
│ ├── pdf
│ │ └── report.pdf //准备打印的pdf
│ └── print.html //准备打印的html
├── test
│ └── e2e
│ ├── index.js
│ ├── specs
│ └── utils.js
└── yarn.lock
复制代码
动态html 打印node
<!-- 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>Document</title>
<style>
body,
html {
padding: 0;
margin: 0;
font-size: 30px;
}
/*打印页样式*/
@page {
margin: 0px;
}
/*自定义打印样式,能够提早放入样式,减小传入内容*/
</style>
</head>
<body id="bd"></body>
<script>
const { ipcRenderer } = require('electron')
ipcRenderer.on('webview-print-render', (event, info) => {
// 执行渲染
document.getElementById('bd').innerHTML = info.html
ipcRenderer.sendToHost('webview-print-do')
})
</script>
</html>
复制代码
<!-- print.vue-->
<template>
<div class="guide-print">
<button @click="print">打印</button>
<webview
id="printWebview"
ref="printWebview"
src="static/print.html"
nodeintegration
/>
</div>
</template>
<script>
import { ipcRenderer } from 'electron'
export default {
data() {
return {
printName:''
}
},
mounted() {
const webview = this.$refs.printWebview
webview.addEventListener('ipc-message', event => {
if (event.channel === 'webview-print-do') {
webview.print(
{
silent: true,
printBackground: true,
deviceName: this.printName
},
status => {
console.log('打印发送到打印机')
}
)
}
})
this.getPrintListHandle()
},
methods: {
print() {
const webview = this.$refs.printWebview
webview.send('webview-print-render', {
printName: this.printName,
html: "<p>我是打印内容</p>"
})
},
//获取打印机
getPrintListHandle() {
ipcRenderer.send('getPrinterList')
ipcRenderer.once('getPrinterList', (event, data) => {
// 过滤可用打印机
this.printName = data.filter(e => e.isDefault)[0].name
})
}
}
}
</script>
<style lang="scss">
#printWebview {
height: 0;
width: 0;
visibility: hidden;
}
</style>
复制代码
远程&本地pdf打印git
安装依赖 npm i node-pdf-printer
复制代码
下载打印包 PDFtoPrinter.exegithub
//main.js 本地pdf文件打印
import NodePdfPrinter from 'node-pdf-printer'
let url1 = path.join(__static,'/pdf/test1.pdf')pipe(fs.createWriteStream(pdfPath))
let url2 = path.join(__static,'/pdf/test2.pdf')
NodePdfPrinter.printFiles([url1,url2,...],'你的打印机名字,不填/默认')
复制代码
//main.js 远程pdf文件打印
import NodePdfPrinter from 'node-pdf-printer'
import request from 'request'
let url ='http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf'
let pdfPath = path.join(
__static,
'pdf/' + url.slice(url.lastIndexOf('/')+1)
)
//下载远程pdf资源到/static/pdf目录
request(url, err => {
if(!err){
NodePdfPrinter.printFiles([pdfPath])
}
}).pipe(fs.createWriteStream(pdfPath))
复制代码
若是批量下载多个pdf,能够下载完全部pdf资源在执行NodePdfPrinter.printFiles进行批量打印,打印完成执行删除本地pdf。web
function deleteDir(url) {
var files = []
if (fs.existsSync(url)) {
//判断给定的路径是否存在
files = fs.readdirSync(url) //返回文件和子目录的数组
files.forEach(function(file, index) {
var curPath = path.join(url, file)
if (fs.statSync(curPath).isDirectory()) {
//同步读取文件夹文件,若是是文件夹,则函数回调
deleteDir(curPath)
} else {
fs.unlinkSync(curPath) //是指定文件,则删除
}
})
// fs.rmdirSync(url) //清除文件夹
} else {
console.log('给定的路径不存在!')
}
}
复制代码
打包static目录的文件没有打包进去
须要在package.json 里面添加extraResources 额外资源npm
"win": {
"icon": "dist/electron/static/icon2.ico",
"extraResources": [
"./static/*.html",
"./static/*.txt",
"./static/*.exe",
"./static/pdf/*.pdf"
],
}
复制代码
html打印偶尔遇到图片没有打印出来
缘由是document.getElementById('bd').innerHTML = info.html 以后就直接向print.vue通知打印,致使webview没有彻底加载完成
做者找了很久,没有找到合适的监听,目前是在重定向资源的时候作短暂的延时,有知道的小伙伴谢谢分享🙏🙏json
远程下载pdf没法放入/static/pdf下
缘由是electron-vue 默认是用asar打包,而asar只能读取不能写入,因此须要远程打印pdf就不能打包成asar
"win": {
"asar": false,
]
复制代码
还有一些icon 设置、托盘右键菜单设置、缩小托盘、闪烁、气泡提示的坑,就不在这里赘述了,有问题能够下方评论讨论