electron项目实战 - 打印排坑

14 阅读1分钟

electron项目实战打印排坑

一 项目背景:

前面已经实现了vue3的web端的导出PDF、打印 功能;
    需要的可以查看之前的文章:
    https://juejin.cn/post/7521356618174021674
对于频繁打印的热敏小票,很显然web打印无法满足连续打印;
所以选择 electron 桌面端实现热敏小票打印;
electron打印方式:win.webContents.print()

二 electron打印问题整理:

1 打印样式丢失

1.1 问题描述
打印内容正常显示,但是样式丢失
1.2 解决办法 (内联样式)
    // 1 构建完整 HTML(传给主进程)
    const finalHtml = `
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
          /* 模板样式 */
          ${templateStyle}
        </style>
      </head>
      <body>
        <div id="print-container">
          ${html}
        </div>
      </body>
      </html>
    `;

    // 2 调用Electron打印API
    const result = await printAPI.printHtml({
      html: finalHtml,
      options: {
        templateType,
        templateWidth,
        templateHeight
      }
    });

2 打印字体不生效

2.1 问题描述
electron打印只支持默认字体,非默认字体不生效!
打印热面小票80mm需要等宽的窄体;
推荐字体:ShareTechMono
2.2 解决办法:
2.2.1 将自定义字体转成 BASE64
// /scripts/font-to-base64.js
const fs = require('fs');
const path = require('path');

// 1 自定义字体存放路径:/src/assets/fonts/ShareTechMono-Regular.ttf
const fontPath = path.resolve(__dirname, '../src/assets/fonts/ShareTechMono-Regular.ttf');
const fontBuffer = fs.readFileSync(fontPath);
const base64Font = fontBuffer.toString('base64');

const fontCss = `
@font-face {
  font-family: 'ShareTechMono';
  src: url('data:font/ttf;base64,${base64Font}') format('truetype');
  font-weight: normal;
  font-style: normal;
}
`;
// 2 生成的路径: /src/components/Print/templates/font-face.css
fs.writeFileSync(path.resolve(__dirname, '../src/components/Print/templates/font-face.css'), fontCss);
console.log('✅ 字体 Base64 已生成 font-face.css,内容如下:\n');
console.log(fontCss.slice(0, 200) + '...'); // 打印部分内容
#在vscode编译器中执行这个工具:
node scripts/font-to-base64.js
2.2.2 内联字体样式
    // 1 vite 中的 css?raw 将文件中的样式转成 字符串 接收
    const fontCssModule = await import("@/components/Print/templates/font-face.css?raw")
    const fontCss = fontCssModule.default;

    const finalHtml = `
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
          ${templateStyle}
          /* 2 自定义字体样式 */
          ${fontCss}
        </style>
      </head>
      <body>
        <div id="print-container">
          ${html}
        </div>
      </body>
      </html>
    `;
// 模板样式中直接使用字体就好
font-family: 'ShareTechMono', 'Condensed', 'Liberation Mono', 'Microsoft YaHei', 'SimSun', 'Arial', monospace;

3 打印内容超出宽度

3.1 问题描述
80热敏打印,web打印正常,但是electron打印结果就是打印内容超出打印纸张的宽度;
3.2 解决办法
单独设置打印宽度;
实际打印机的宽度是 72mm,虽然平时叫做80mm宽度的热敏打印;
所以将模板宽度设置成 72mm就解决了,不是模板样式问题,是宽度问题!