8

前段时间,客户提了个需求,想把订单合同做成线上签名并在线生成合同,生成的合同还要打印出来,还要我两天做完,WTF,接到需求的那一刻我是懵逼的,我只是个瑟瑟发抖的小前端啊,话说这也需要研究一下怎么做的吧。

瑟瑟发抖之余,我就在考虑具体实现的步骤,简单划分了下 --->

  1. 用canvas实现手写签名
  2. 将签名展示在合同上
  3. 提交合同的同时生成pdf(合同内容+签名)
  4. 将生成的合同保存到服务端

看完是不是觉得很简单,不用两天,给我三五个小时就搞定了。事实证明我还是太年轻了,我google了几个案例后,发现最佳实现方案是用signature_pad实现签名,然后用(html2canvas+jsPdf)生成pdf文档。
于是我便开始动手写demo,签名没啥问题,我之前自己也写过canvas实现写字,但是懒得再去重构项目和做模块化扩展。html2canvas也没问题,用网页生成的图片文件很清晰,还原度很高,至于生成pdf嘛,效果就一般了。

主要问题是如下:

  1. 生成的pdf及其不清晰,
  2. 分页打印的位置裁切也存在问题
  3. 手机端展示的合同的dom结构布局和打印的A4纸上的布局有很大不同

我也尝试过多种方案,依旧没能解决,期间想过用一个隐藏dom来写一套A4纸的样式用于打印,后来发现清晰度和裁剪问题不好解决,于是便换了种思路,想通过服务端来解决。
在github上逛了逛,发现了pdfmake这个神器,立马看了文档,开始写demo,实践了一遍后发现,这个比较靠谱,生成的文档也很清晰。

具体能实现的如下:

  • 自定义样式(字体,颜色,下划线,对齐方式,边距)
  • 插入图片
  • 定位(相对定位,绝对定位)
  • 水印,页眉页脚

这些就够了,可是还存在一些问题(不知道是不是打开的方式不对)

  • 对中文的支持很差,目前只能用微软雅黑
  • 原始文档需要自己手动去设置,当然也可以使用js去生成

最终我还是用这个插件实现了想要的效果。
项目上线后,我自己撸了个demo,放在github上,有兴趣的可以下载下来看一看

//项目结构
├── README.md
├── app
│   ├── fonts
│   │   └── msyh.ttf  //字体文件
│   ├── images
│   │   ├── qrcode.png //用到的图片
│   │   └── snh.jpg  
│   ├── middleware
│   │   └── generatePdf.middleware.js //生成文档js
│   ├── models
│   │   └── doc.model.js //文档原型
│   └── routers
│       └── index.js //路由文件
├── app.js  
├── package.json
└── tempFiles  //缓存目录

效果截图(截图效果太渣,文档很清晰,打印完全没问题)
图片描述

有需要的可以自取

git clone https://github.com/zangse/GeneratePDF

npm install 

npm run start

在浏览器打开

http://localhost:3000/pdf

这个pdfmake也可以在浏览器端实现,鉴于需要加载的字体太大(微软雅黑.ttf ---> 10M+),我放弃了这个操作。


臧瑟
401 声望9 粉丝

不务正业的程序猿。