说真的,刚接触electron,踩了不少的坑,不同版本的electron配置不一样的!!导致在百度过程中,参照他们的写法,往往没起作用,最后发现是版本不一致导致的!EXE安装包放在文章后面。
-
背景 项目中有需要用到打印标签这种功能,市面上能满足web端静默打印只有LODOP这个插件。在测试过程中,发现LODOP对兼容处理的不是很好,如果电脑的IE不是11版本(狗头,你可能会说现在谁还用IE,公司这边很多客户的电脑系统还停留在xp或win7上o(╥﹏╥)o),传的HTML给LODOP来打印,往往布局会错乱,对css的圆角属性没起作用,只能用svg代替;如果要做到兼容,可以把html先转成img,然后调用LODOP的ADD_PRINT_IMAGE方法,但是打印出来会失真,你可能会说可以先把图片放大再打印,这个是可以,但是会很大,打印很慢。然后看到了electron,也是用js编写,也可以获取到打印机,也可以静默打印,好像能满足这边的需求,入坑!!
-
代码片段 element-plus(1.0.2-beta.55)+ vue(3.0.0)+ ws(7.5.3) + electron(13.0.0) + electron-devtools-installer(3.1.0)
以上是我用到的版本,electron的版本最好对上,要不会碰到各种问题!!
为什么要用到ws?这里内容主要是用WebSocket来传输打印的,所以这里搭建了一个WebSocketServer;ws地址:ws://127.0.0.1:15978。 先看一下效果图:
electron很多坑就在入口文件配置这里,不同版本有点不一样的
首先创建窗口:
new BrowserWindow({
width: 800,
height: 600,
icon: ".\\src\\assets\\img\\logo.png",
autoHideMenuBar: true, //是否隐藏菜单栏
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
webSecurity: false, // 取消跨域限制
webviewTag: true, // 是否启用 <webview> tag标签
enableRemoteModule: true,
},
});
第一个坑:icon参数,路径问题 看了网上一些教程,可以把ison配置在package.json里面,但是我这个版本怎么试都没有效果;如果放到BrowserWindow里面,没有双斜杆打包不会显示;这里的vue脚手架是用4点多版本搭建的,最后摸索出,可以把icon放到vue.config.js,打包之后果然生效:
pluginOptions: {
electronBuilder: {
builderOptions: {
appId: 'electron-app',
productName: 'huanggua',
win: {
icon: 'public/favicon.ico'
},
nsis: {
oneClick: false, // 是否一键安装
allowToChangeInstallationDirectory: true // 允许修改安装目录
}
}
},
}
第二个坑:页面是否能调用node的一些方法和electron方法,这里有两个个关键参数nodeIntegration和contextIsolation 这里如果nodeIntegration不设置为true,contextIsolation不设置为false,页面用window.require('electron')回发生报错,参考了文档,那时候这里搞了半天才弄好,也不算是坑吧,没怎么看文档。。。
第三个坑:enableRemoteModule参数,不同版本有差异
第四个坑:webview标签,首先要在主窗口把标签开启,这个标签里面要调用electron方法,还要在标签加上nodeintegration和contextIsolation参数,要不在主窗口加上都没用:
<webview style="height: 100%;" ref="printWebview" src="print.html" nodeintegration webpreferences="contextIsolation=false" />
打印模块
1、获取打印机列表
background.js
ipcMain.on('getPrinterList', (event) => {
//主线程获取打印机列表
const list = browerWin.webContents.getPrinters();
//通过webContents发送事件到渲染线程,同时将打印机列表也传过去
browerWin.webContents.send('getPrinterList', list);
});
print.vue
const getIpcRendererPrinter = () => {
//渲染线程主动发送getPrinterList事件到主线程请求打印机列表
ipcRenderer.send('getPrinterList');
//监听主线程获取到打印机列表后的回调
ipcRenderer.once('getPrinterList', (event, data) => {
//data就是打印机列表
console.log(data);
printList.value = data || [];
const localPrintName = localStorage.getItem('localPrintName');
if (data && data.length && !localPrintName) {
leftForm.printer = data[0].displayName;
localStorage.setItem('localPrintName', data[0].displayName);
}
if (localPrintName) {
leftForm.printer = localPrintName;
}
console.log(leftForm);
console.log(printList);
});
}
这里只要原理是把打印的内容HTML放到webview里面,然后调用打印
printWebview.value.print({
//是否是静默打印
silent: true,
// printBackground: true,
//打印机的名称,就是本文一开始获得的打印机列表其中一个
deviceName: printer,
})
.then(data => {
console.log('webview success', data);
ipcRenderer.send('printSucces', true);
})
.catch(e => {
console.log('webview error', e);
ipcRenderer.send('printSucces', false);
});
- 如何调用 首先安装软件,下载地址: pan.baidu.com/s/1IdM5OzqI… 提取码: 2p5q
页面调用: 安装软件完毕,打开软件
html,内容可以自定义
<div
class="body-right-preview"
:style="{
width: canvasDesignConfig.width + canvasDesignConfig.unit,
height: canvasDesignConfig.height + canvasDesignConfig.unit,
}"
>
<previewDesign
:designConfig="canvasDesignConfig"
:fillData="fillData"
ref="printDesign"
/>
</div>
js,链接WebSocket
const _this = this
const clientWebsock = new WebSocket(`ws://127.0.0.1:15978`);
clientWebsock.onmessage = function(e) {
console.log("接受消息:", e);
if (e && e.data && count > 0) {
count = count - 1;
_this.electronPrint("again");
}
};
clientWebsock.onclose = function(e) {
console.log("连接关闭", e);
};
clientWebsock.onopen = function() {
console.log("连接成功");
};
// 连接发生错误的回调方法
clientWebsock.onerror = function(e) {
console.log("连接错误", e);
};
this.clientWebsock = clientWebsock
打印
const printDesignRef = this.$refs.printDesign;
const htmlContent = printDesignRef.$el.outerHTML
this.clientWebsock.send(htmlContent);