赞
踩
也是阅读了很多资料和前人踩的坑,直接使用webContent.print方法进行打印。其他方式要不就是Bug多,官方修复也有问题;要不就是官方升级版本后不再支持等
不赘述
main
里面实现printerHandle
,暴露给渲染线程去调用打印等功能onMounted
事件上直接执行打印操作,实现静默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)
- }
- 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)
- 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不出问题就完事~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。