electron实现静默下载(各种踩坑解决)
前车之鉴
也是阅读了很多资料和前人踩的坑,直接使用webContent.print方法进行打印。其他方式要不就是Bug多,官方修复也有问题;要不就是官方升级版本后不再支持等
不赘述
需求思路
- 在
main里面实现printerHandle,暴露给渲染线程去调用打印等功能 - 点击打印后,调出打印页面(新建窗口再隐藏)
- 通过路径指向打印页面的路由地址,在此页面进行html和css编码,实现打印内容编辑
- 在
onMounted事件上直接执行打印操作,实现静默 - 打印完成后,销毁窗口(此过程用户无感)
具体实现
main
getPrinter
获取打印机列表,有array.length再继续
private async getPrinters(event: IpcMainInvokeEvent) {
const printers = await event.sender.getPrintersAsync()
return printers
}
print
打印功能,使用官方提供API
private print(event: IpcMainInvokeEvent, options: WebContentsPrintOptions) {
return new Promise(resolve => {
event.sender.print(options, (success: boolean, failureReason: string) => {
resolve({ success, failureReason })
})
})
}
createPrint
创建打印窗口(显示可预览,隐藏可静默)
这里有一个print页面要写,路径指向此页面路由
区分开发环境和生产环境
数据我是通过query传参方式通信,也可以用其他方式(store,cookie等)
private createPrint(_, data: string) {
if (win) {
win.destroy()
win = null
}
win = new BrowserWindow({
titleBarStyle: 'hidden',
width: 1240,
height: 768,
useContentSize: true,
frame: false,
show: false,
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false
}
})
const url = is.dev ? new URL(process.env.ELECTRON_RENDERER_URL!) : new URL('file://')
url.pathname = is.dev ? '' : join(__dirname, '../renderer/index.html')
url.hash = `#/print?data=${data}`
win.loadURL(url.href)
// win.webContents.openDevTools()
win.setMenu(null)
win.on('ready-to-show', () => {
// win?.show()
win?.hide()
})
win.on('closed', () => {
win = null
})
}
destroyPrint
private destroyPrint() {
if (win) {
win.destroy()
win = null
}
}
其他代码
// 在class外部定义win
let win = null as BrowserWindow | null
// 提供register
register() {
ipcMain.handle('get-printers', this.getPrinters)
ipcMain.handle('print', this.print)
ipcMain.handle('create-print-window', this.createPrint)
ipcMain.handle('destroy-print-window', this.destroyPrint)
}
preload
const api = {
printer: {
getPrinter: () => ipcRenderer.invoke('get-printers'),
print: (options: WebContentsPrintOptions) => ipcRenderer.invoke('print', options),
createPrintWindow: (data: string) => ipcRenderer.invoke('create-print-window', data),
destroyPrintWindow: () => ipcRenderer.invoke('destroy-print-window')
}
}
contextBridge.exposeInMainWorld('api', api)
renderer
触发打印功能
const printClick = ref(false)
const handlePrint = async (data: Order) => {
if (printClick.value) {
return
}
printClick.value = true
const list = await window.api.printer.getPrinter()
console.log(list)
if (!list.length) {
toast('没有检测到打印设备!', 'error')
return
}
toast('正在打印出货单...', 'info')
await window.api.printer.createPrintWindow(
JSON.stringify({ ...data, createTime: formatDate(data.createTime) })
)
printClick.value = false
}
打印窗口页面
<template>
........
// 打印内容和样式
// handle里面 win.show()和控制台功能可临时调试放开注释
</template>
<script setup name="Print" lang="ts">
import { WebContentsPrintOptions } from 'electron'
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
// 从query获取内容
const query = useRoute().query
const { data } = query
const order: Order = JSON.parse(data as string)
// 这里加了延时,后面解释...
onMounted(() => {
setTimeout(print, 100)
})
// 这里解释
// el-table看到的样式和打印出来的样式区别更大,在于style内联样式的问题
// 渲染后会在.el-table__header,.el-table__body等DOM上计算出宽度来优化样式
// 如果是用户自己点击打印按钮,再去做样式处理setTableFrame是没有问题的,因为样式是后来我们自己加上的100%
// 而为了实现静默下载,需要在页面渲染完成就立即打印,此时elementui也刚刚计算好宽度赋值,而覆盖掉我们的逻辑
// 所以延时了一波,样式没变化,但打印出来的样式就和我们看到的页面样式一样了
const setTableFrame = () => {
//el-table设置宽度100%
const tableNodes = document.querySelectorAll(
'.el-table__header,.el-table__body'
) as NodeListOf<HTMLElement>
tableNodes.forEach(table => {
table.style.width = '100%'
const children = table.children
for (let i = 0; i < children.length; i++) {
const child = children[i]
if (child.localName === 'colgroup') {
child.innerHTML = ''
}
}
})
//el-table cell设置每个宽度100%
const cells = document.querySelectorAll('.cell') as NodeListOf<HTMLElement>
cells.forEach(cell => {
cell.style.width = '100%'
cell.removeAttribute('style')
})
}
// 打印,先重置el-table样式
const print = async () => {
setTableFrame()
try {
// 设置打印参数,具体看文档
const options: WebContentsPrintOptions = {
silent: true,
margins: { marginType: 'none' },
pageSize: 'A4'
}
await window.api.printer.print(options)
} catch (error) {
console.log(error)
} finally {
// 打印完成,调用destory
await window.api.printer.destroyPrintWindow()
}
}
</script>
踩坑
如果是普通下载(非静默),到此就没有问题了
我的版本是electron@27,设置silent: true后,有问题,会缩放很小,而且居中展示
那么有问题,就肯定不止我一个人遇到,就肯定有解决方法
不过@24官方已经不支持更新维护了,但是基本没啥问题(打印功能很迷,据说时不时一个版本好,一个版本又坏,然后又好)
后期项目还要支持win7,还得降级到@21,没bug不出问题就完事~
electron实现静默下载(各种踩坑解决)的更多相关文章
- IDEA打包javaFX及踩坑解决
开门见山的说,先打包,再说坑. File-->Project Structure --> Artifacts-->(此处点加号)JAR-->From modules with ...
- EasyPoi 导入导出Excel时使用GroupName的踩坑解决过程
一.开发功能介绍: 简单的一个excel导入功能 二.Excel导入模板(大致模板没写全): 姓名 性别 生日 客户分类 联系人姓名 联系人部门 备注 材料 综合 采购 张三 男 1994/05/25 ...
- ubuntu18.04 搭建scrapy环境(连环踩坑+解决办法)
---恢复内容开始--- 预期需求: 打算搭建scrapy环境,基于python3.x的 环境描述: ubuntu18.04自带了python3.6,打算在虚拟环境vlenv中跑scrapy,装好虚拟 ...
- Idea运行支付宝网站支付demo踩坑解决及其测试注意事项
一.前言 在一些商城网上中,必不可少的是支付,支付宝和微信比较常见,最近小编也是在研究这一块,看看支付宝怎么进行支付的,支付宝给我们提供了demo和沙箱测试.减少我们的申请的麻烦,公钥和秘钥也比之前方 ...
- CompletionService用法踩坑解决优化
转自:https://blog.csdn.net/xiao__miao/article/details/86352380 1.近期工作的时候,运维通知一个系统的内存一直在增长,leader叫我去排查, ...
- 编译课设·CLion到VS踩坑·解决·备忘录
应试用,VS使用习惯和JB系差别还是蛮大的 打不过他们就加入他们 键位修改 工具-选项 键盘:改keymap 字体和颜色:宋体必改. 自动恢复:自动保存默认3分钟 CMake:自救时可以看一下 键位名 ...
- 【踩坑经历】一次Asp.NET小网站部署踩坑和解决经历
2013年给1个大学的小客户部署过一个小型的Asp.NET网站,非常小,用的sqlite数据库,今年人家说要换台服务器,要重新部署一下,好吧,虽然早就过了服务时间,但无奈谁叫人家是客户了,二话不说,上 ...
- 记一次FTP下载踩坑的故(shi)事(gu)
下班前领导忽然要求我将客户的日志服务器上一些日志拷贝到测试服务器中,不过领导只提供给我FTP的连接方式,很明显就是要我用FTP方式去做啦 一般来说FTP批量下载也就上网随便找个脚本的事,但是却成了我疯 ...
- Vue packages version mismatch的解决方法 初来乍到,踩坑日常
初来乍到,踩坑日常 这个问题也是我也是接受别人项目,出现的问题,在下载好依赖后运行的时候报这样的错误 它上面显示两个版本一个vue的版本,一个vue-template-compiler版本,我这边忘了 ...
- electron踩坑系列之一
前言 以electron作为基础框架,已经开发两个项目了.第一个项目,我主要负责用react写页面,第二项目既负责electron部分+UI部分. 做项目,就是踩坑, 一路做项目,一路踩坑,坑多不可怕 ...
随机推荐
- 火山引擎ByteHouse:如何为OLAP设计高性能向量检索能力?
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 背景 随着LLM技术应用及落地,数据库需要提高向量分析以及AI支持能力,向量数据库及向量检索等能力"异军 ...
- 2.4 资源管理器Restorator--《恶意代码分析实战》
Lab01-04.exe 实验内容: 1.将文件上传到http://www.VirusTotal.com 进行分析并查看报告.文件匹配到了已有的反病毒软件特征吗? 2.是否有这个文件被加壳或混淆的任何 ...
- electron、nodejs、typescript、idea 组合开发,安装和配置 以及错误 等 详细说明
1. 创建项目,创建时 选择 nodejs 项目,因为 开发 electron 与 开发 nodejs 基本一致. 2.安装 electron npm i -D electron@beta 看目录 ...
- Python-wxauto微信自动发送消息或文件
1.安装wxauto和pyautogui库,pip安装即可. pip install wxauto pip install pyautogui 2.登录电脑微信客户端 这里有两个注意点:(1)不能将客 ...
- JS Leetcode 1370. 上升下降字符串 题解分析,桶排序与charCodeAt fromCharCode妙用
壹 ❀ 引 本题来自LeetCode1370. 上升下降字符串,难度简单,是一道考察对于字符串遍历熟练度的题目,题目描述如下: 给你一个字符串 s ,请你根据下面的算法重新构造字符串: 从 s 中选出 ...
- JS Leetcode 26. 删除有序数组中的重复项 题解分析,字典与快慢双指针
壹 ❀ 引 本题来自LeetCode26. 删除有序数组中的重复项,是一道简单题,题目描述如下: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组 ...
- logstash4j-用于日志的输入、转换处理、输出, java 开发者自己的 logstash
项目简介 logstash4j 用于日志的输入.转换处理.输出, java 开发者自己的 logstash 特性 input output filter metric 开源地址 logstash4j ...
- 适用于Spring Boot Jar的启停部署脚本
shell脚本参数 使用-z或-n对一个变量判空时, 若直接使用[ -n ARG ]这种形式,当{ARG}中有空格将会报错, line 27: [: sd: binary operator expec ...
- 【OpenGL ES】绘制立方体
1 前言 本文主要介绍使用 OpenGL ES 绘制立方体,读者如果对 OpenGL ES 不太熟悉,请回顾以下内容: 绘制三角形 绘制彩色三角形 绘制正方形 绘制圆形 在绘制立方体的过程中, ...
- celery中异步延迟执行任务apply_anysc的用法
描述 首先说下异步任务执行delay()和apply_anysc()两者区别,其实两者都是执行异步任务的方法,delay是apply_anysc的简写.所以delay中传递的参数会比apply_any ...