如何统计pc端在线时长_在线签名前后端业务实现(pc端及移动端)

5ad0623367a8acd864775e98d39bd7b0.png

前言

最近做了一个需求,是一个用户在线完成个人承诺书生成并手写签字的功能,最开始的时候是需要用户自行下载附件,并打印签名后上传,但是这种方式的不好之处在于,你压根就不知道用户上传的到底是不是你要的附件。后来服务升级,客户让参照国家app的形式,在线生成承诺书,并签名。最近新需求刚上线,我来整理下实现过程。

效果图

pdf模板

072948b6e6d5ea8ca0c4db12eb0ae467.png
pc端

表单数据填写

38c20878a0e9a34207d1cca3071aaf07.png

未签名承诺书预览81bfe6d252b471a0001b5fd1488d291d.png

签名

6a8c2c00f868fc5756a6269bda452bd2.png

签名后预览

131edf38a6125e5c95edb961de1f45a4.png
微信端

填写表单数据

b40317c20b3322740b19e48c902cec7e.png

生成承诺书

1b3ce77b4e8e6700579d6c2d49301c3b.png

签名确认

9085bf99a231f588ba6b342ea7e4dcce.png

签名后预览

f7746689c910802090630e3e0d0d811e.png

需求实现过程

最开始拿到这个需求的时候,我就想到了通过js实现签名,所以在查了一些资料以后,前端确认用jSignature,后端根据用户信息,通过pdf表单的方式生成承诺书,然后返回未签名的承诺书图片,最后用户签名确认后,后端将签名和承诺书进行合成,然后返回给前端,如果用户确认办理业务,则后端保存签名后的个人承诺书。

总结一下整个流程:

70c3752580d1356513ce1c4c733d5894.png

因为项目是前后端分离的,所以图片是通过base64传输的。签名部分我是通过图片合成的,当然你也可以做成电子签章的方式,这样也更合理。

这里再补充说明下jSignature,这个js库可以直接生成base64的签名,当然它支持的格式很多,具体的可以看文档:

86db97ae4d82321996e2e0117039ac85.png

下面直接放代码了:

java接口

根据pdf模板生成pdf
  /**
     * 根据pdf模板,生成pdf
     *
     * @param pdfReader        PdfReader
     * @param saveFullFileName 保存文件的完整文件名(包含文件路径)
     * @param parameters       参数
     * @throws DocumentException
     */
    public static void exportPdf(PdfReader pdfReader, File saveFullFileName, Map parameters) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(saveFullFileName);
            byteArrayOutputStream = new ByteArrayOutputStream();
            PdfStamper pdfStamper = new PdfStamper(pdfReader, byteArrayOutputStream);
            //获取模板所有域参数
            AcroFields acroFields = pdfStamper.getAcroFields();

            //解决中文字体不显示的问题
            BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList fontArrayList = new ArrayList();
            fontArrayList.add(baseFont);
            acroFields.setSubstitutionFonts(fontArrayList);

            for (String key : parameters.keySet()) {
                acroFields.setField(key, parameters.get(key));
            }

            pdfStamper.setFormFlattening(true);//如果为false那么生成的PDF文件还能编辑,一定要设为true
            pdfStamper.flush();
            pdfStamper.close();
            //设置纸张,可以在Excel制作是设定好纸张大小
            Document doc = new Document(PageSize.A4);
            PdfCopy copy = new PdfCopy(doc, fileOutputStream);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(byteArrayOutputStream.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();
        } catch (Exception e) {
            throw new Exception("生成pdf文件失败", e);
        } finally {
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    throw new Exception("生成pdf文件失败,关闭资源失败");
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    throw new Exception("生成pdf文件失败,关闭资源失败");
                }
            }
            if (pdfReader != null) {
                pdfReader.close();
            }
        }
    }
pdf转图片
 /**
     * pdf转图片
     *
     * @param pdfFullName pdf完整文件名
     * @param imgSavePath 图片保存路径
     * @throws Exception
     */
    public static void pdf2Pic(String pdfFullName, String imgSavePath) throws Exception {
        org.icepdf.core.pobjects.Document document = new org.icepdf.core.pobjects.Document();
        document.setFile(pdfFullName);
        //缩放比例
        float scale = 2.5f;
        //旋转角度
        float rotation = 0f;
        // 文件名
        String pdfFileName = new File(pdfFullName).getName();
        try {
            for (int i = 0; i                 BufferedImage image = (BufferedImage)
                        document.getPageImage(i, GraphicsRenderingHints.SCREEN, org.icepdf.core.pobjects.Page.BOUNDARY_CROPBOX, rotation, scale);

                String imgName = pdfFileName + i + ".png";
                System.out.println(imgName);
                File file = new File(imgSavePath + imgName);
                ImageIO.write(image, "png", file);

                image.flush();
            }
        } catch (Exception e) {
            throw new Exception("pdf文件转图片失败", e);
        }
        document.dispose();
    }
合成签名
 /**
     *
     * @Title: 构造图片
     * @Description: 生成水印并返回java.awt.image.BufferedImage
     * @param buffImg 源文件(BufferedImage)
     * @param waterImg 水印文件(BufferedImage)
     * @param x 距离右下角的X偏移量
     * @param y  距离右下角的Y偏移量
     * @param alpha  透明度, 选择值从0.0~1.0: 完全透明~完全不透明
     * @param scale  缩放比例,整数,如50表示缩放为0.5
     * @return BufferedImage
     * @throws IOException
     */
    public static BufferedImage overlyingImage(BufferedImage buffImg, BufferedImage waterImg,int x, int y, float alpha, int scale) {

        // 创建Graphics2D对象,用在底图对象上绘图
        Graphics2D g2d = buffImg.createGraphics();
        int waterImgWidth = waterImg.getWidth()*scale/100;// 获取层图的宽度
        int waterImgHeight = waterImg.getHeight()*scale/100;// 获取层图的高度
        logger.debug("图片宽度" + waterImgWidth);
        logger.debug("图片高度" + waterImgHeight);
        // 在图形和图像中实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 绘制
        g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
        g2d.dispose();// 释放图形上下文使用的系统资源
        return buffImg;
    }

js核心代码

  function signInit() {
        $("#signature").html('');
        // This is the part where jSignature is initialized.
        var $sigdiv = $("#signature").jSignature({'height': '300px', 'width': '100%'})

        $('#sign-make-sure').click(function () {
            notice();
            var data = $sigdiv.jSignature('getData', 'image');

            var datas = sessionStorage.getItem("apply-record-datas");
            var signSourceImg = sessionStorage.getItem("sign-source-img");
            var parseJSON = JSON.parse(datas);
            parseJSON['FILENAME'] = signSourceImg;
            parseJSON['sign'] = data[1];

            var requestParameter = {"datas": JSON.stringify(parseJSON)};
            var url = "/signTest/signPersonalCommitment";
            aj(url, requestParameter, function (result) {
                if (result.success) {
                    swal.close();
                    var modal_body_html = " + result.obj.datas + "' >"
                    $("#ydjyrecodSignModal .modal-body").html(modal_body_html);var modal_footer_html = "\n" +" 重新签名\n\n" +" \n" +" 保存并提交\n\n";
                    $("#ydjyrecodSignModal .modal-footer").html(modal_footer_html);
                    $("#ydjyrecodSignModal").modal({backdrop: "static",//点击空白处不关闭对话框show: true
                    });
                } else {
                    swal("生成个人承诺书失败", result.msg, "error");
                }
            }, function (err) {console.log(err);
            });
        });
        $('#rest').click(function () {
            $sigdiv.jSignature('reset')
        });
    }

签名区html

<div id = "sign-tips" style="margin-bottom: 5px; text-align:center">
 <p>请用鼠标在虚线框内绘制签名p>
div>
<div id=\"content\">
    <div id=\"signatureparent\">
        <div id=\"signature\">div>
    div>
div>

完整的示例,请看文末链接。

结语

今天的分享,只是提供一种解决方案的思路,如果能帮到你或者能够给你一些启发,那一切都值得。这里是本文的项目地址,感兴趣的小伙伴可以去了解下:web-sign-demo

项目源码:https://github.com/Syske/learning-dome-code/tree/dev/web-sign-demo

- END -
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值