无纸化相关

前端(客户端)

  • 使用vue-esign
<el-collapse-item title="买方签字">
            <div class="signWrapper">
              <vue-esign ref="contractBuyer" :width="300" :height="200" :isCrop="isCrop" :lineWidth="lineWidth"
                         :lineColor="lineColor" :bgColor.sync="bgColor"/>
            </div>
            <div flex="main:center cross:center" class="pt-5">
              <el-button size="mini" @click="handleResetContractBuyer">重签</el-button>
              <el-button size="mini" type="primary" @click="handleGenerateContractBuyer">确定</el-button>
            </div>
</el-collapse-item>
  • js
  handleGenerateContractBuyer() {
      let that = this
      this.$refs.contractBuyer.generate().then(res => {
        that.form.signImg = res
        that.activeCollapse = 0
      }).catch(err => {
        Toast("未签字") // 画布没有签字时会执行这里 'Not Signned'
        that.activeCollapse = 0
        return false;
      })
    },

前端将签名的base64传给后端

后端

逻辑:收到前端传的签名图片和其他参数后,用Poi-tl将参数插入word中,然后用 docx4j 将word转为pdf,如果需要,用pdfbox将pdf转为图片返回给前端展示

  • pom (注意相关包版本必须一直)
 		<!-- poi-tl -->
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.8.2</version>
        </dependency>
 		<!-- docx4j -->
        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j-JAXB-Internal</artifactId>
            <version>8.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
            <version>8.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j-export-fo</artifactId>
            <version>8.3.1</version>
        </dependency>

        <!--pdf转图片-->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>fontbox</artifactId>
            <version>2.0.15</version>
        </dependency>

word模板中对应的值{{@signImg}}、{{param}},详情见文档

 /**
     * 组装文档内容
     */
    public static ArrayList<UploadFile> generateFlie(Map param) {
        HashMap<String, Object> contentMap = new HashMap<>();
        //设置输出内容的样式,详情见poi-tl文档
        Style style = new Style();
        style.setUnderLine(true);
        contentMap.put("param", new TextRenderData(map.get("otherParam"),style));
        //签名的base64:"data:image/png;base64,iVBORw0KGgoAAAANSUhEU....." ,需要将前边的"data:image/png;base64,"截掉
        String signImg = map.get("signImg").substring(22);
        contentMap.put("signImg", new PictureRenderData(100, 40, ".png", Base64.decode(signatureSellerBase64)));
        //contentMap组装好之后,调文档转换方法
        return convert(contentMap, "Contract.docx");
    }

    /**
     * 文档转换
     *
     * @param masterId   申请表主键
     * @param contentMap 组装文档内容
     * @param template   模板
     * @return
     */
    private static ArrayList<UploadFile> convert(Map<String, Object> contentMap, String template) {
        // 取classpath下的模板
        File templateFile = null;
        try {
            templateFile = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "template/" + template);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 获得File对象,当然也可以获取输入流对象
        String templatePath = templateFile.getAbsolutePath();
        String outputPath = RuoYiConfig.getProfile() + "/download/" + templateFile.getName();
        try {
            // 生成word
            XWPFTemplate.compile(templatePath).render(contentMap).writeToFile(outputPath);
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(new File(outputPath));
            // 设置字体
            Mapper fontMapper = new IdentityPlusMapper();
            fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
            fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
            fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
            fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
            fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
            fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
            fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
            fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
            fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
            fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
            fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
            fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
            fontMapper.put("等线", PhysicalFonts.get("SimSun"));
            fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
            fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
            fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
            fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
            fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
            fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
            fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
            fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
            fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
            fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
            fontMapper.put("新細明體", PhysicalFonts.get("SimSun"));
            mlPackage.setFontMapper(fontMapper);
            // word转pdf
            File pdfPath = new File(outputPath.replace(".docx", ".pdf"));
            Docx4J.toPDF(mlPackage, new FileOutputStream(pdfPath));
            // pdf转image
            PDDocument doc = PDDocument.load(pdfPath);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            ArrayList<UploadFile> images = new ArrayList<>();
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = renderer.renderImageWithDPI(i, 296);
                UploadFile uploadFile = new UploadFile();
                uploadFile.setName("page" + (i + 1));
                uploadFile.setUrl("data:image/png;base64," + Base64.encode(ImgUtil.toBytes(image, ImgUtil.IMAGE_TYPE_PNG)));
                images.add(uploadFile);
            }
            return images;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

  • UploadFile
@Data
public class UploadFile {
    private String name;
    private String url;
    private String uid;
    private String status;
}

可能遇到的问题:word转pdf的时候中文乱码,原因可能是本机没有word中的字体

补充:有时候可能需要在word中插入特殊符号:带方框的√,空的方框等,可以通过设置字体来实现,详情见博客:使用Poi-tl 生成word文档 处理word特殊符号方框带勾选 解决方法
如果生成pdf,使用wingdings,方框带√的编码是:“\uF0FE”,不带√的编码:“\uF06F”

 Style style = new Style("Wingdings", 14);
 contentMap.put("water", new TextRenderData(bool?"\uF0FE":"\uF06F",style));

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值