首页 > 其他分享 >electron实现静默下载(各种踩坑解决)

electron实现静默下载(各种踩坑解决)

时间:2024-03-18 10:24:53浏览次数:22  
标签:const win 打印 静默 electron print table data 下载

前车之鉴

也是阅读了很多资料和前人踩的坑,直接使用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不出问题就完事~

标签:const,win,打印,静默,electron,print,table,data,下载
From: https://www.cnblogs.com/rion1234567/p/18075830

相关文章

  • IntelliJ IDEA 2023.3 最新发布啦!盘点精彩亮点(附带软件下载)
    IntelliJIDEA2023.3的发布标志着AIAssistant的持续发展,它现已超越技术预览阶段,并具有许多令人兴奋的改进。在其他领域,该版本包括对最新Java21功能的全面支持,引入了具有编辑操作的直观浮动工具栏,并添加了“运行到光标”嵌入选项以增强调试工作流程。IntelliJIDEAUltima......
  • 网易云如何免费下载付费歌曲?
    首先登入网页版网易云搜索要下载的歌曲将‘#/song?id’换成‘/song/media/outer/url’如下回车进入后点击三个点下载即可 ......
  • [转]【Qt-license】误操作qt下载导致只能安装商业版试用十天,无法安装社区版
    背景:原本是为了学习qml,需要下载一个designstudio,而这个需要比较新版的安装程序,但新版的安装程序官方都是online安装。于是从官网找下载链接。毕竟是英文的,又心急,误打误撞中我选择了商业版试用。  其实online安装程序是一样的(qt-unified-windows-x64-4.6.1-online.exe),一旦选......
  • 如何计算下载文件的校验和?
    一、什么是校验和?校验和是对一段数据(通常是单个文件)运行一种称为加密散列函数的算法的结果,英文名:checksum。二、为什么要计算校验和?用于“检查”数据或文件在存储或传输过程中是否被更改。从网上下载的软件通常附带校验和,这样用户可以确保文件或文件在传输过程中没有被修......
  • 如何通过web前端下载付费音乐(以qq音乐为例)
    tips:如今通过这个方式在qq音乐官网只能下载一部分啦!也就是比如试听多久,咱们就能下载多久的音乐时长,试听一分钟就只能下载一分钟!当然你去一个可以全部试听的音乐网站用这方法是可以全部下载的哦!演示PC的操作系统是windows!1.登录qq音乐官网https://y.qq.com/1.1登录自己的qq音......
  • 静默快速安装oracle 19c
    静默快速安装oracle19c1.配置yum源1.配置网络yum源1.删除redhat7.0系统自带的yum软件包;rpm-qa|grepyum>oldyum.pkg备份原信息rpm-qa|grepyum|xargsrpm-e--nodeps不检查依赖,直接删除rpm包1232.自行下载所需要的软件包。包名会更新,根据当前最新的下载。......
  • 手把手教使用静默 搭建Oracle 19c 一主一备ADG集群
    一、环境搭建主机IPora19192.168.134.239ora19std192.168.134.2401.配置yum源1.配置网络yum源1.删除redhat7.0系统自带的yum软件包;rpm-qa|grepyum>oldyum.pkg备份原信息rpm-qa|grepyum|xargsrpm-e--nodeps不检查依赖,直接删除rpm包2.自行下载所需要的软......
  • 使用Servlet实现文件下载
    一位朋友最近在学习JavaWeb开发,开始学习文件下载操作,他自己尝试着去网上看一些教程,总的来说也不是太了解,就让我和他说说,如何实现文件下载功能。我和他说了一下大致的思路,主要分为前端和后端两部分来实现文件下载操作。后台Java代码实现思路:.1.读取文件信息;.2.设置返回数据......
  • IntelliJ IDEA 2023.3 最新发布啦!盘点精彩亮点(关注公众号‘精品应用分享’,输入'idea'
    IntelliJIDEA2023.3的发布标志着AIAssistant的持续发展,它现已超越技术预览阶段,并具有许多令人兴奋的改进。在其他领域,该版本包括对最新Java21功能的全面支持,引入了具有编辑操作的直观浮动工具栏,并添加了“运行到光标”嵌入选项以增强调试工作流程。IntelliJIDEAUltima......
  • FFmpeg开发笔记(六)如何访问Github下载FFmpeg源码
    ​学习FFmpeg的时候,经常要到GitHub下载各种开源代码,比如FFmpeg的源码页面位于https://github.com/FFmpeg/FFmpeg。然而国内访问GitHub很不稳定,经常打不开该网站,比如在命令行执行下面的ping命令。pinggithub.com上面的ping结果如下所示,可见默认解析的DNS地址连接超时。正在......