前段時間,公司有個需求,要實現前端靜默(點擊按鈕直接打印,不須要預覽),本想着直接用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 設置、托盤右鍵菜單設置、縮小托盤、閃爍、氣泡提示的坑,就不在這裏贅述了,有問題能夠下方評論討論