Freemarker+thymeleaf应用实现打印银行小票

背景:最近项目里有个需求,需要动态配置一个模板,来打印各种不同银行或者其他行业的小票,下面小小记录一下实现过程。

关键词:Springboot, thymeleaf, Freemarker,html2image

一,引入依赖

<dependency>
	    <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
	<groupId>org.xhtmlrenderer</groupId>
	<artifactId>core-renderer</artifactId>
	<version>R8</version>
</dependency>
<dependency>
	<groupId>com.github.xuwei-k</groupId>
	<artifactId>html2image</artifactId>
	<version>0.1.0</version>
</dependency>
<!-- freemarker模板引擎-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

二,准备数据

1,动态配置的字段

2,包含所有配置信息的字段Dto
 

@Data
public class TemplateFieldDto {
    /**
     * 模板id
     */
    private long templateId;
    /**
     * 字段id
     */
    private long fieldId;
    /**
     * bankId
     */
    private long bankId;
    /**
     * 商户ID
     */
    private long merchantId;
    /**
     * 发票联类型, MERCHANT,CARDHOLDER,SETTLEMENT
     */
    private String ftlType;
    /**
     * 字段编码
     */
    private String fieldCode;
    /**
     * 字段名,多语言
     */
    private String fieldName;
    /**
     * 字段值
     */
    private String fieldValue;
    /**
     * 语言
     */
    private String languageType;
    /**
     * 顺序
     */
    private Integer fieldOrder;
    /**
     * 字体颜色,#333333
     */
    private String fontColor;
    /**
     * 标题字体大小,单位px
     */
    private String titleFontSize;
    /**
     * 字体大小,单位px
     */
    private String fontSize;
    /**
     * 是否粗体,bold
     */
    private String fontStyle;
    /**
     * 是否展示字段名标题
     */
    private boolean showTitle;
    /**
     * 是否换行, 0 否,1 是
     */
    private boolean newLine;
    /**
     * 是否合并到title
     */
    private boolean mergeToTitle;
    /**
     * 对齐方式,left,right,center
     */
    private String position;
}

3,组装成需要的数据结构

三,配置动态模板 

这里是关键,需要遍历数据,并判断数据中属性

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="utf-8"/>
    <style>
        table {
font-family: "Times New Roman", serif;
}
    </style>
    <title>FreeMarker</title>
</head>

<body>
    <table border="0" width="300">
        <#if data??>
            <#list data as item>
                <#if item.showTitle>
                    <#if item.newLine>
                        <tr>
                            <td colspan="3" style="text-align: left; font-size: ${item.titleFontSize};">${item.fieldName}:</td>
                        </tr>
                        <tr>
                            <td colspan="3" style="text-align: ${item.position}; font-weight: ${item.fontStyle}; font-size:${item.fontSize};">${item.fieldValue}</td>
                        </tr>
                    <#else>
                        <#if item.mergeToTitle>
                            <tr>
                                <td colspan="3" style="text-align: ${item.position}; font-weight: ${item.fontStyle};font-size: ${item.fontSize};">${item.fieldName}: ${item.fieldValue}</td>
                            </tr>
                        <#else>
                            <tr>
                                <td style="text-align: left; font-weight: ${item.fontStyle};font-size: ${item.titleFontSize};">${item.fieldName}:</td>
                                <td colspan="2" style="text-align: ${item.position}; font-weight: ${item.fontStyle}; font-size: ${item.fontSize};">${item.fieldValue}</td>
                            </tr>
                        </#if>
                    </#if>
                <#else>
                    <#if item.fieldCode=='amountTitleLine'>
                        <tr>
                            <td style="text-align: left; font-size: 12px; width: 20%">TYPE</td>
                            <td style="text-align: center; font-size: 12px; width: 60%">SUM</td>
                            <td style="text-align: right; font-size: 12px; width: 20%">AMOUNT</td>
                        </tr>
                    <#elseif item.fieldCode=='creditCard'>
                        <tr>
                            <td colspan="3" style="text-align: left; font-size: ${item.fontSize}; width: 20%">${item.fieldName}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">SALE</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${creditCard.creditSaleCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${creditCard.creditSaleAmount}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">VOID</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${creditCard.creditVoidCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${creditCard.creditVoidAmount}</td>
                        </tr>
                    <#elseif item.fieldCode=='debitCard'>
                        <tr>
                            <td colspan="3" style="text-align: left; font-size: ${item.fontSize}; width: 20%">${item.fieldName}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">SALE</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${debitCard.debitSaleCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${debitCard.debitSaleAmount}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">REFUND</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${debitCard.debitRefundCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${debitCard.debitRefundAmount}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">CASHBACK</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${debitCard.debitCashbackCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${debitCard.debitCashbackAmount}</td>
                        </tr>
                    <#elseif item.fieldCode=='allCards'>
                        <tr>
                            <td colspan="3" style="text-align: left; font-size: ${item.fontSize}; width: 20%">${item.fieldName}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">SALE</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${allCards.totalSaleCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${allCards.totalSaleAmount}</td>
                        </tr>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">REFUND</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${allCards.totalRefundCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${allCards.totalRefundAmount}</td>
                        </tr>
                    <#elseif item.fieldCode=='totalAmoutEnd'>
                        <tr>
                            <td style="text-align: left; font-size: ${item.fontSize}; width: 20%">${item.fieldName}</td>
                            <td style="text-align: center; font-size: ${item.fontSize}; width: 60%">${totalAmoutEnd.totalCount}</td>
                            <td style="text-align: right; font-size: ${item.fontSize}; width: 20%">${totalAmoutEnd.totalAmount}</td>
                        </tr>
                    <#else>
                        <#if item.fieldCode=='bankLogo'>
                            <tr>
                                <td colspan="3" style="text-align: ${item.position};">
                                    <img src="${item.fieldValue}" width="250" height="100" alt="BankLogo"/>
                                </td>
                            </tr>
                        <#elseif item.fieldCode='emptyLine'>
                            <tr>
                                <td colspan="3" style="height:15px;">
                                </td>
                            </tr>
                        <#elseif item.fieldCode='grayLine'>
                            <tr>
                                <td colspan="3">
                                    <hr style="border: none; border-bottom:1px solid black"/>
                                </td>
                            </tr>
                        <#else>
                            <tr>
                                <td colspan="3" style="text-align: ${item.position}; font-weight: ${item.fontStyle}; font-size: ${item.fontSize};">${item.fieldValue}</td>
                            </tr>
                        </#if>
                    </#if>
                </#if>
            </#list>
        <#else>
        </#if>
    </table>
</body>

</html>

四,结果展示

码字不易,记得点赞关注哟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/75306.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法——双指针】LeetCode 202 快乐数

题目描述&#xff1a; 思路&#xff1a;快慢指针 看到循环&#xff0c;我就想起了快慢指针的方法&#xff0c;从题目我们可以看出&#xff0c;我们需要模拟一个过程&#xff1a;不断用当前的数去生成下一个数&#xff0c;生成的规则就是将当前数的各位的平方累加&#xff1b; …

项目:基于UDP的TFTP文件传输

1&#xff09;tftp协议概述 简单文件传输协议&#xff0c;适用于在网络上进行文件传输的一套标准协议&#xff0c;使用UDP传输特点&#xff1a; 是应用层协议 基于UDP协议实现 数据传输模式 octet&#xff1a;二进制模式&#xff08;常用&#xff09; mail&#xff1a;已经不再…

C++RAII内存管理技术

文章目录 一.什么是RAII内存管理技术&#xff1f;二.智能指针unique_ptrshared_ptr循环引用问题weak_ptr 一.什么是RAII内存管理技术&#xff1f; C在引入异常机制后,代码执行流的跳转变得难以预料,如果使用普通的指针进行内存管理,很难避免内存泄漏的问题(执行流跳转导致堆区…

【Java 集合框架API接口】Collection,List,Set,Map,Queue,Deque

博主&#xff1a;_LJaXi Or 東方幻想郷 专栏&#xff1a; Java | 从跨行业到跨平台 开发工具&#xff1a;IntelliJ IDEA 2021.1.3 Java集合框架 API接口 Collection接口List接口HashSet&#xff0c; TreeSetSet接口使用 HashSet 实现使用 TreeSet 实现 HashMap、TreeMapMap接口…

MySQL高可用MHA

目录 前言 一、概述 二、配置免密、组从复制 三、MHA配置 四、测试 总结 前言 MySQL高可用管理工具&#xff08;MHA&#xff0c;Master High Availability&#xff09;是一个用于自动管理MySQL主从复制的工具&#xff0c;它可以提供高可用性和自动故障转移。MHA由原版的MHA工具…

Debian/Ubuntu清理硬盘空间

Debian/Ubuntu清理硬盘空间_debian清理磁盘空间_weixin_43606319的博客-CSDN博客 1. 删除残余的配置文件 通常Debian/Ubuntu删除软件包可以用两条命令 sudo apt-get remove <package-name> sudo apt-get purge <package-name> remove将会删除软件包&#xff0…

1.SpringMVC接收请求参数及数据回显:前端url地址栏传递参数通过转发显示在网页

1、SpringMVC 处理前端提交的数据 1.1 提交的域名和处理方法的参数不一致&#xff0c;使用注解解决 1.2 提交的域名和处理方法的参数不一致&#xff0c;使用注解解决 1.3 提交的是一个对象 2、前端url地址栏传递的是一个参数 请求地址url&#xff1a;http://localhost:8080/s…

5_docker-compose多服务统一编排管理

系列文章目录 第1章 Linux安装Docker 第2章 Docker安装jdk1.8和MySql 第3章 Docker安装redis 第4章 Jar包部署Docker 第5章 Docker-compose多服务统一编排管理 第6章 AccessKeyId和AccessKeySecret的环境变量配置 文章目录 系列文章目录前言 一、编写docker-compose.yml二、上…

计算机网络核心-数据交换

1 概述 计算机网络的核心即数据交换。通过数据交换将数据从源主机发送到目的主机。 2 为什么需要数据交换 如果不是数据交换的方式&#xff0c;而是每两台主机直接连接&#xff0c;则会产生N^2链路问题。 即&#xff0c;假设有N台主机&#xff0c;两两间建立连接&#xff0c…

软件测试基础篇——Linux

1、Linux系统的特征 开源免费&#xff1a; 开源&#xff1a;开放源代码&#xff0c;指的是底层的源代码是可以开放出来&#xff0c;给相关的开发者&#xff0c;根据实际的需求做出修改的。 免费&#xff1a;不花钱&#xff0c;自由传播。 ​ Linux是一种免费使用和自由传播的…

pytest数据驱动(最简单)

目录 第一种&#xff1a;通过yaml文件获取数据&#xff08;一维列表&#xff09; 第二种&#xff1a;通过yaml文件获取数据&#xff08;二维列表&#xff09; 第三种&#xff1a;通过yaml文件获取数据&#xff08;pytest.fixture&#xff09; 资料获取方法 第一种&#xff…

RTC实验

一、RTC简介 RTC(Real Time Clock)即实时时钟&#xff0c;它是一个可以为系统提供精确的时间基准的元器件&#xff0c;RTC一般采用精度较高的晶振作为时钟源&#xff0c;有些RTC为了在主电源掉电时还可以工作&#xff0c;需要外加电池供电BCD码&#xff0c;四位二进制表示一位…

【潮州饶平】联想 IBM x3850 x6 io主板故障 服务器维修

哈喽 最近比较忙也好久没有更新服务器维修案例了&#xff0c;这次分享一例潮州市饶平县某企业工厂一台IBM System x3850 x6服务器亮黄灯告警且无法正常开机的服务器故障问题。潮州饶平ibm服务器维修IO主板故障问题 故障如下图所示&#xff1a; 故障服务器型号&#xff1a;IBM 或…

CI/CD流水线实战

不知道为什么&#xff0c;现在什么技术都想学&#xff0c;因为我觉得我遇到了技术的壁垒&#xff0c;大的项目接触不到&#xff0c;做的项目一个字辣*。所以&#xff0c;整个人心浮气躁&#xff0c;我已经得通过每天的骑行和长跑缓解这种浮躁了。一个周末&#xff0c;我再次宅在…

2011-2021年数字普惠金融指数Bartik工具变量法(含原始数据和Bartik工具变量法代码)

2011-2021年数字普惠金融指数Bartik工具变量法&#xff08;含原始数据和Bartik工具变量法代码&#xff09; 1、时间&#xff1a;2011-2020&#xff08;省级、城市&#xff09;&#xff0c;2014-2020&#xff08;区县&#xff09; 2、原始数据来源&#xff1a;北大金融研究中心…

【数据结构】双链表

【数据结构】双链表 一. 前言二. 带头双向链表接口实现1.准备工作2. 创建一个节点 三. 初始化4. 打印5. 尾插6. 尾删7. 头插8. 头删9. 计算节点个数10. 查找数据11. 在任意位置插入数据12. 在任意位置删除数据13. 销毁 四. 如何10分钟内完成一个完整双链表 一. 前言 带头双向循…

通达OA SQL注入漏洞【CVE-2023-4165】

通达OA SQL注入漏洞【CVE-2023-4165】 一、产品简介二、漏洞概述三、影响范围四、复现环境POC小龙POC检测工具: 五、修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损…

元宇宙时代超高清视音频技术白皮书关于流媒体协议和媒体传输解读

流媒体协议 元宇宙业务场景对流媒体传输的实时性和互动性提出了更高的要求&#xff0c;这就需要在传统的 RTMP、SRT、 HLS 等基础上增加实时互动的支持。实时互动&#xff0c;指在远程条件下沟通、协作&#xff0c;可随时随地接入、实时地传递虚实融合的多维信息&#xff0c;身…

uni-app日期选择器

写个简单的日期选择器&#xff0c;还没搞样式&#xff0c;所以有点丑 大概长这样吧 首先是这个picker选择器&#xff0c;mode选择日期&#xff0c;end是写一个范围前日期&#xff0c;:end就是这个日期是动态变化的&#xff0c;还有change函数 <template><view>&l…

Mybatis 初识

目录 1. MyBatis入门 1.1 MyBatis的定义 1.2 MyBatis的核心 MyBatis的核心 JDBC 的操作回顾 1.3 MyBatis的执行流程 MyBatis基本工作原理 2. MyBatis的使用 2.1 MyBatis环境搭建 2.1.1 创建数据库和表 2.1.2 添加MyBatis框架支持 老项目添加MyBatis 新项目添加MyBatis 2.1.3 设…