首页 web前端 前端问答 react打印样式丢失怎么办

react打印样式丢失怎么办

Dec 21, 2022 pm 03:45 PM
react

react打印样式丢失的解决办法:1、通过“npm install --save html2canvas npm install jspdf --save”命令安装jspdf;2、使用jspdf将需要打印的div转成pdf;3、使用react重新打印即可。

react打印样式丢失怎么办

本教程操作环境:Windows10系统、react18版、Dell G3电脑。

react打印样式丢失怎么办?

vue print打印div样式丢失 (react通用)

使用网上的print.js插件,打印发现样式丢失。

解决方案 > 将html转成pdf,再打印pdf

使用jspdf将需要打印的div转成pdf(转成的pdf样式不会丢失,因为pdf.js是将div转成canvas)

安装jspdf

npm install --save html2canvas
登录后复制
npm install jspdf --save
登录后复制

上代码

utli.js 直接复制,注意outPutPdf方法入参即可

import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
// base64转blob
export function toBlob(base64Data) {
  let byteString = base64Data
  if (base64Data.split(',')[0].indexOf('base64') >= 0) {
    byteString = atob(base64Data.split(',')[1]); // base64 解码
  } else {
    byteString = unescape(base64Data.split(',')[1]);
  }
  // 获取文件类型
  const mimeString = base64Data.split(';')[0].split(":")[1]; // mime类型
  // ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区
  // let arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组
  // let uintArr = new Uint8Array(arrayBuffer) // 创建视图
  const uintArr = new Uint8Array(byteString.length); // 创建视图
  for (let i = 0; i < byteString.length; i += 1) {
    uintArr[i] = byteString.charCodeAt(i);
  }
  // 生成blob
  const blob = new Blob([uintArr], {
    type: mimeString
  })
  // 使用 Blob 创建一个指向类型化数组的URL, URL.createObjectURL是new Blob文件的方法,可以生成一个普通的url,可以直接使用,比如用在img.src上
  return blob;
};
/**
 * 输出pdf
 * @param {*} idName  html元素
 * @param {*} pdfName  输出pdf文件名
 * @param {*} isDownload  是否直接下载
 * @param {*} isPrint 是否直接打印
 * @param {*} callback  执行后的回调  
 */
 export function outPutPdf(idName, pdfName, isDownload = false, isPrint = false, callback) {
  const element = document.getElementById(idName);  // 这个dom元素是要导出的pdf的div容器
  const w = element.offsetWidth;  // 获得该容器的宽
  const h = element.offsetHeight;  // 获得该容器的高
  const offsetTop = element.offsetTop; // 获得该容器到文档顶部的距离  
  const offsetLeft = element.offsetLeft; // 获得该容器到文档最左的距离
  const canvas = document.createElement("canvas");
  let abs = 0;
  const winI = document.body.clientWidth; // 获得当前可视窗口的宽度(不包含滚动条)
  const winO = window.innerWidth; // 获得当前窗口的宽度(包含滚动条)
  if (winO > winI) {
    abs = (winO - winI) / 2; // 获得滚动条宽度的一半
  }
  canvas.width = w * 2; // 将画布宽&&高放大两倍
  canvas.height = h * 2;
  const context = canvas.getContext(&#39;2d&#39;);
  context.scale(2, 2);
  context.translate(-offsetLeft - abs, -offsetTop);
  // 这里默认横向没有滚动条的情况,因为offset.left(),有无滚动条的时候存在差值,因此translate的时候,要把这个差值去掉
  html2canvas(element, {
    useCORS: true, // 允许加载跨域的图片
    allowTaint: true,
    scale: 2 // 提升画面质量,但是会增加文件大小
  }).then(cs => {
    const contentWidth = cs.width;
    const contentHeight = cs.height;
    // 一页pdf显示html页面生成的canvas高度
    const pageHeight = contentWidth / 592.28 * 841.89;
    // 未生成pdf的html页面高度
    let leftHeight = contentHeight;
    // 页面偏移
    let position = 0;
    // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
    const imgWidth = 595.28;
    const imgHeight = 592.28 / contentWidth * contentHeight;
    const pageDate = cs.toDataURL(&#39;image/jpeg&#39;, 1.0);
    const pdf = new jsPDF(&#39;&#39;, &#39;pt&#39;, &#39;a4&#39;);
    // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面的高度(841.89)
    // 当内容未超过pdf一页显示的范围,无需分页
    if (leftHeight < pageHeight) {
      pdf.addImage(pageDate, &#39;JPEG&#39;, 0, position, imgWidth, imgHeight);
    } else { // 分页
      while (leftHeight > 0) {
        pdf.addImage(pageDate, &#39;JPEG&#39;, 0, position, imgWidth, imgHeight)
        leftHeight -= pageHeight;
        position -= 841.89;
        // 避免添加空白页
        if (leftHeight > 0) {
          pdf.addPage()
        }
      }
    }
    if (isDownload) {
      pdf.save(`${pdfName}.pdf`);
    } 
    if (isPrint) {
      const link = window.URL.createObjectURL(toBlob(pdf.output(&#39;datauristring&#39;)));
            const myWindow = window.open(link);
      myWindow.print();
    }
    callback && callback(pdf);
  })
}
登录后复制

需要打印部分

<div id="printDiv"></div>
登录后复制

vue 全部代码

<template>
  <a-modal
    v-model="visible"
    :title="title"
    :maskClosable="false"
    centered
    :width="1000"
    @cancel="close"
  >
    <div id="printDiv">
      <div v-if="!pdfing">
        <span></span>
        <span>入库单</span>
        <a @click="printChart">打印报表</a>
      </div>
      <div class="maintain-view-title pdfing" v-else>
        <span>入库单</span>
      </div>
      <a-form :colon="true" :label-col="{ span: 8 }" :wrapper-col="{ span: 15 }">
        <a-row>
          <a-col :span="8">
            <a-form-item label="入库单号">
              <span>{{ viewInfo.accessNumber }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="供应商">
              <span>{{ viewInfo.supplier }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="入库日期">
              <span>{{ viewInfo.accessDate && $moment(viewInfo.accessDate).format(&#39;YYYY-MM-DD HH:mm:ss&#39;) }}</span>
            </a-form-item>
          </a-col>
        </a-row>
        <a-row>
          <a-col :span="8">
            <a-form-item label="仓库">
              <span>{{ viewInfo.warehouse }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="来源">
              <span>{{ viewInfo.source }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="经办人">
              <span>{{ viewInfo.handledBy }}</span>
            </a-form-item>
          </a-col>
        </a-row>
        <a-row>
          <a-col :span="8">
            <a-form-item label="采购单号">
              <span>{{ viewInfo.purchaseOrderNo }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="发票号">
              <span>{{ viewInfo.invoiceNo }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="合同号">
              <span>{{ viewInfo.contractNo }}</span>
            </a-form-item>
          </a-col>
        </a-row>
        <a-row>
          <a-col :span="8">
            <a-form-item label="入库类型">
              <span>{{ viewInfo.accessType }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="创建时间">
              <span>{{ viewInfo.addTime }}</span>
            </a-form-item>
          </a-col>
          <a-col :span="8">
            <a-form-item label="备注">
              <span>{{ viewInfo.content }}</span>
            </a-form-item>
          </a-col>
        </a-row>
      </a-form>
      <a-table
        style="marginTop: 10px;"
       
        :columns="columns"
        :data-source="data"
        :pagination="false"
        :loading="loading"
        row-key="id"
      >
      </a-table>
    </div>
    <template slot="footer">
      <a-button key="back" type="primary" @click="close">取消</a-button>
    </template>
  </a-modal>
</template>
<script>
import { outPutPdf } from "@/utils/util";
import { getStorageOrderTopDetail, getStorageOrderBottomListNoPage } from "@/api/stock";
export default {
  name: "StockStorageOrderViewModal",
  components: {},
  data() {
    return {
      visible: false,
      form: null,
      title: "出库确认",
      loading: false,
      viewInfo: {},
      columns: [
        {
          title: "序号",
          key: "index",
          customRender: (text, render, index) => {
            return index + 1
          },
          align: "center"
        },
        {
          title: "产品编号",
          key: "productNumber",
          dataIndex: "productNumber"
        },
        {
          title: "类别",
          key: "type",
          dataIndex: "type"
        },
        {
          title: "产品名称",
          key: "productName",
          dataIndex: "productName"
        },
        {
          title: "规格型号",
          dataIndex: "specifications",
          dataIndex: "specifications"
        },
        {
          title: "计量单位",
          key: "unit",
          dataIndex: "unit"
        },
        {
          title: "批次",
          key: "batch",
          dataIndex: "batch"
        },
        {
          title: "数量",
          key: "number",
          dataIndex: "number"
        },
        {
          title: "单价",
          key: "price",
          dataIndex: "price"
        },
        {
          title: "金额",
          key: "total",
          dataIndex: "total"
        },
        {
          title: "已入库",
          key: "inbound",
          dataIndex: "inbound"
        },
        {
          title: "未入库",
          key: "notInbound",
          dataIndex: "notInbound"
        }
      ],
      data: [],
      pdfing: false, // 打印中
    };
  },
  methods: {
    // 显示弹框
    show(id) {
      this.visible = true;
      // 获取上方数据
      getStorageOrderTopDetail({ id }).then(res => {
        if (res.code === 0) {
          this.viewInfo = res.data;
        }
      });
      // 获取下方表格数据
      this.getTableData(id);
    },
    /**
     * 关闭弹框
     */
    close() {
      this.visible = false;
      this.$emit("cancel");
    },
    // 获取表格数据
    getTableData(warehouseRegisterId) {
       const params = {
        warehouseRegisterId
      };
      getStorageOrderBottomListNoPage(params).then(res => {
        this.loading = false;
        if (res.code === 0) {
          this.data = res.data;
        } else {
          this.$common.showErrorMessage(res.msg || "请求出现错误,请稍后再试");
        }
      });
    },
    // 打印
    printChart() {
      this.pdfing = true;
      this.$nextTick(() => {
        outPutPdf(&#39;printDiv&#39;, &#39;入库单&#39;, false, true, () => {
          this.pdfing = false;
        });
      });
    }
  }
};
</script>
<style scoped>
.maintain-view-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  &.pdfing {
    justify-content: center;
  }
  .maintain-view-title-label {
    font-weight: bold;
    font-size: 1.5em;
  }
}
.container-title-block {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}
.viewForm {
  /deep/.ant-form-item {
    margin-bottom: 0;
  }
}
</style>
登录后复制

推荐学习:《react视频教程

以上是react打印样式丢失怎么办的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何利用React和WebSocket构建实时聊天应用 如何利用React和WebSocket构建实时聊天应用 Sep 26, 2023 pm 07:46 PM

如何利用React和WebSocket构建实时聊天应用引言:随着互联网的快速发展,实时通讯越来越受到人们的关注。实时聊天应用已经成为现代社交和工作生活中不可或缺的一部分。本文将介绍如何利用React和WebSocket构建一个简单的实时聊天应用,并提供具体的代码示例。一、技术准备在开始构建实时聊天应用之前,我们需要准备以下技术和工具:React:一个用于构建

React前后端分离指南:如何实现前后端的解耦和独立部署 React前后端分离指南:如何实现前后端的解耦和独立部署 Sep 28, 2023 am 10:48 AM

React前后端分离指南:如何实现前后端的解耦和独立部署,需要具体代码示例在当今的Web开发环境中,前后端分离已经成为一种趋势。通过将前端和后端代码分开,可以使得开发工作更加灵活、高效,并且方便进行团队协作。本文将介绍如何使用React实现前后端分离,从而实现解耦和独立部署的目标。首先,我们需要理解什么是前后端分离。传统的Web开发模式中,前端和后端是耦合在

如何利用React和Flask构建简单易用的网络应用 如何利用React和Flask构建简单易用的网络应用 Sep 27, 2023 am 11:09 AM

如何利用React和Flask构建简单易用的网络应用引言:随着互联网的发展,网络应用的需求也越来越多样化和复杂化。为了满足用户对于易用性和性能的要求,使用现代化的技术栈来构建网络应用变得越来越重要。React和Flask是两种在前端和后端开发中非常受欢迎的框架,它们可以很好的结合在一起,用来构建简单易用的网络应用。本文将详细介绍如何利用React和Flask

如何利用React和RabbitMQ构建可靠的消息传递应用 如何利用React和RabbitMQ构建可靠的消息传递应用 Sep 28, 2023 pm 08:24 PM

如何利用React和RabbitMQ构建可靠的消息传递应用引言:现代化的应用程序需要支持可靠的消息传递,以实现实时更新和数据同步等功能。React是一种流行的JavaScript库,用于构建用户界面,而RabbitMQ是一种可靠的消息传递中间件。本文将介绍如何结合React和RabbitMQ构建可靠的消息传递应用,并提供具体的代码示例。RabbitMQ概述:

React响应式设计指南:如何实现自适应的前端布局效果 React响应式设计指南:如何实现自适应的前端布局效果 Sep 26, 2023 am 11:34 AM

React响应式设计指南:如何实现自适应的前端布局效果随着移动设备的普及和用户对多屏幕体验的需求增加,响应式设计成为了现代前端开发的重要考量之一。而React作为目前最流行的前端框架之一,提供了丰富的工具和组件,能够帮助开发人员实现自适应的布局效果。本文将分享一些关于使用React实现响应式设计的指南和技巧,并提供具体的代码示例供参考。使用React的Fle

React代码调试指南:如何快速定位和解决前端bug React代码调试指南:如何快速定位和解决前端bug Sep 26, 2023 pm 02:25 PM

React代码调试指南:如何快速定位和解决前端bug引言:在开发React应用程序时,经常会遇到各种各样的bug,这些bug可能使应用程序崩溃或导致不正确的行为。因此,掌握调试技巧是每个React开发者必备的能力。本文将介绍一些定位和解决前端bug的实用技巧,并提供具体的代码示例,帮助读者快速定位和解决React应用程序中的bug。一、调试工具的选择:在Re

React Router使用指南:如何实现前端路由控制 React Router使用指南:如何实现前端路由控制 Sep 29, 2023 pm 05:45 PM

ReactRouter使用指南:如何实现前端路由控制随着单页应用的流行,前端路由成为了一个不可忽视的重要部分。ReactRouter作为React生态系统中最受欢迎的路由库,提供了丰富的功能和易用的API,使得前端路由的实现变得非常简单和灵活。本文将介绍ReactRouter的使用方法,并提供一些具体的代码示例。安装ReactRouter首先,我们需

如何利用React和Google BigQuery构建快速的数据分析应用 如何利用React和Google BigQuery构建快速的数据分析应用 Sep 26, 2023 pm 06:12 PM

如何利用React和GoogleBigQuery构建快速的数据分析应用引言:在当今信息爆炸的时代,数据分析已经成为了各个行业中不可或缺的环节。而其中,构建快速、高效的数据分析应用则成为了许多企业和个人追求的目标。本文将介绍如何利用React和GoogleBigQuery结合起来构建快速的数据分析应用,并提供详细的代码示例。一、概述React是一个用于构建

See all articles