uniapp项目使用JSPDF实现文档PDF生成
黑猫 2022-01-25 00:37 367

本文所的例子是本博主在uniapp项目中结合JSDPF以及官方editor组件做电子合同编辑功能时所实现的功能,并且在vue项目内通过iframe的方式让uniapp项目与PC端vue-cli项目实现互通,且在pc端也能进行编辑,话不多说直接开始

 

一、uniapp官方editor使用

这个咱们可以不用多写,可以通过HubilderX新建一个uni-app组件库项目,通过该项目找到editor页面,直接想里面的代码复制你自己的项目使用就行。

 

二、安装jspdf 和 html2Canvas

1. 使用安装好模块

 npm install  jspdf --save 
 npm install --save html2canvas@1.0.0-rc.4  

html2canvase最好安装@1.0.0-rc.4 其他搞版本对手机的兼容性不好,有可能生成白屏,或者生成的图片不全

2. 在第一步复制好的editor代码页面内引入模块

import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';

3.重新修改onEditorReady方法,创建编辑器成功后,给编辑器设置默认内容

onEditorReady() { //创建编辑器
    uni.createSelectorQuery().select('#editor').context((res) => {
     //设置编辑器实例
     this.editorCtx = res.context;
     //给编辑器填入默认html内容
     this.editorCtx.setContents({
      html: ‘’
     });
    }).exec()
 },

4.创建生成pdf的方法,本方法生成的pdf为base64,并且生成pdf时已经计算好了每页的上下左右的边距,所以可以直接使用

4.1 在页面上先弄一个存放pdf对应html的容器,把编辑器生成的内容放到此容器里面,如果直接拿编辑器作为示例的话,pdf是不能够完成生成了,因为编辑器会有高度限制,所以要弄一个没有高度限制的html容器在放置内容,最后在生成pdf

<!--生成pdf前存放编辑器内容所需要容器,html必须放在 ql-container和ql-editor里面,不然样式不生效-->
<view id="pdfDom" class="editor-wrapper canvas-wrapper">
   <view class="ql-container" style="padding: 0;height: 100%;">
    <view class="ql-editor" v-html="canvasHtml"></view>
   </view>
</view>

4.2 正式生成pdf的方法

savePdf() {
    let _this = this;
    const query = uni.createSelectorQuery().in(this);
    _this.editorCtx.getContents({
        success: (res) => {
         _this.canvasHtml = res.html;
          if (_this.$props.propsCallBackHtml) {
           //返回html代码出去
            _this.$emit('callback', _this.canvasHtml);
           return;
      }
         //生成pdf的base64内容
      if (_this.$props.propsUseLodding) {
       _this.$CommonFunc.$ShowLoading("正在生成PDF..");
      }
      //放在定时里面是为了保证生成pdf前,html容器已经成功渲染了样式
      setTimeout(() => {
       html2Canvas(document.getElementById('pdfDom'), {
        allowTaint: true
       }).then(function(canvas) {
        let PDF = new jsPDF("p", "mm", "a4");
        var ctx = canvas.getContext("2d");
        var a4w = 190; //a4纸宽
        var a4h = 277; //a4纸高
        var imgHeight = Math.floor(a4h * canvas.width / a4w);
        var renderedHeight = 0;
        while (renderedHeight < canvas.height) {
         var page = document.createElement("canvas");
         page.width = canvas.width;
         page.height = _this.getMinNumber(imgHeight, canvas.height -
          renderedHeight);
         page.getContext('2d').putImageData(ctx.getImageData(0,
          renderedHeight, canvas.width, _this
          .getMinNumber(
           imgHeight, canvas.Height - renderedHeight)
         ), 0, 0);
         PDF.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10,
          10, a4w, _this.getMinNumber(a4h, a4w * page
           .height / page
           .width));

         renderedHeight += imgHeight;
         if (renderedHeight < canvas.height) {
          PDF.addPage();
         }

            page = null;
        }
        _this.$emit('callback', {
         PdfHtml: _this.canvasHtml, //这是通过编辑器生成的html
         PdfBaseUrl: PDF.output('datauristring') //这是最终生成的base64格式的pdf
        });
       });
      }, 2000);
     },
     fail: (res) => {
     
     }
    });
   },

三、电脑端vue项目使用uni-app的编辑器修改内容

由于uni-app的使用的html标签与传统的vue项目使用的标签不一致,并且其他的vue编辑器无法在uni-app上使用,因此在做某些电脑端后台管理时,为了在后台可以管理和编辑内容,那么就需要让电脑vue项目可以使用uni-app项目内的编辑器,此时咱们在电脑端vue项目内通过iframe的方式来互通使用。

1.  电脑端vue项目页面内,使用iframe,iframe访问的地址为uni-app h5端的编辑器地址

 

<iframe ref="refIfram" :src="editorWebsiteUrl" width="388px" height="670px" frameborder="0" style="vertical-align: top;"></iframe>

1.1 在mounted方法内写好监听事件

_this.$nextTick(() => {
        //监听文本编辑器返回的内容
        window.addEventListener("message", (event) => {
          //这里写监听成功后,接着要做的业务
        }, false);
 });

1.2  在电脑可以通过postMessage方法给uni-app项目的编辑器发送信息,发送您需要给过去的内容

this.$refs.refIfram.contentWindow.postMessage({
          type: 'getpdfhtml'
 }, '*');

2. 在uni-app项目的编辑器内写入接收PC端发来的消息监听

onLoad() {
    _this.$nextTick(() => {
     // #ifdef H5
     window.addEventListener("message", (event) => {
         //这里写业务逻辑处理
     });
     // #endif
    });
  },

最后uni-app也是通过postMessage将编辑器生成的html和base64返回给PC端进行保存

window.parent.postMessage({
     type: 'getpdfhtml',
     paramData: event 
    }, '*');

要传递的参数自己定义,这只是个例子,最终只要将html和base64返回给pc端就是了

 

建议将PDF交给后台去生成,因为前端会有很多问题要考虑,例如:不同品牌手机的兼容性,前端生成PDF断层、生成空白等。

dotnetcode webapi后台生成PDF可以参考 "dotnet使用DinkToPdf生成PDF文件"

本文出自kcblogv博客,转载请表明出处。

本网站提供的文章除原创外均转载自其他网站,本网站只为更好的记录及学习技术经验
若网站内转载的文章侵犯了您的版权,请通过 意见反馈 告知本网站,我们会尽快删除相关信息
Copyright©2021-2021 kcBlog博客 版权所有 粤ICP备2021119076号 v1.0.0 栈谷统计