开发了线上合同电子协议得功能模块
This commit is contained in:
parent
6e2d97368a
commit
a2653507d2
29
pom.xml
29
pom.xml
@ -242,14 +242,31 @@
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.docx4j</groupId>
|
||||
<artifactId>docx4j</artifactId>
|
||||
<version>6.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itextpdf</artifactId>
|
||||
<version>5.5.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itext-asian</artifactId>
|
||||
<version>5.2.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
@ -282,5 +299,13 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>aspose-maven-repository</id>
|
||||
<url>http://artifact.aspose.com/repo/</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
|
BIN
simyou.TTF
Normal file
BIN
simyou.TTF
Normal file
Binary file not shown.
@ -317,7 +317,7 @@ public class SysUserController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户修改密码
|
||||
* 用户修改账号密码
|
||||
* @param map
|
||||
* @param token
|
||||
* @return
|
||||
|
130
src/main/java/com/xkrs/utils/ElectronicContractUtil.java
Normal file
130
src/main/java/com/xkrs/utils/ElectronicContractUtil.java
Normal file
@ -0,0 +1,130 @@
|
||||
package com.xkrs.utils;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.itextpdf.text.Image;
|
||||
import com.itextpdf.text.Rectangle;
|
||||
import com.itextpdf.text.pdf.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @Author: XinYi Song
|
||||
* @Date: 2022/1/6 15:45
|
||||
*/
|
||||
public class ElectronicContractUtil {
|
||||
|
||||
/**
|
||||
* 根据PDF模版生成PDF文件
|
||||
* @param templateFilePath PDF模版文件路径
|
||||
* @param data 表单数据
|
||||
* @param imageData 图片数据 VALUE为图片文件路径
|
||||
* @param formFlattening false:生成后的PDF文件表单域仍然可编辑 true:生成后的PDF文件表单域不可编辑
|
||||
* @param pdfFilePath 生成PDF的文件路径
|
||||
*/
|
||||
private static void createPDF(String templateFilePath, HashMap<String,String> data, HashMap<String,String> imageData,
|
||||
boolean formFlattening, String pdfFilePath) throws Exception{
|
||||
PdfReader reader = null;
|
||||
ByteArrayOutputStream bos = null;
|
||||
PdfStamper pdfStamper = null;
|
||||
FileOutputStream fos = null;
|
||||
try{
|
||||
// 读取PDF模版文件
|
||||
reader = new PdfReader(templateFilePath);
|
||||
// 输出流
|
||||
bos = new ByteArrayOutputStream();
|
||||
// 构建PDF对象
|
||||
pdfStamper = new PdfStamper(reader, bos);
|
||||
|
||||
// 获取表单数据
|
||||
AcroFields form = pdfStamper.getAcroFields();
|
||||
|
||||
// 使用中文字体 使用 AcroFields填充值的不需要在程序中设置字体,在模板文件中设置字体为中文字体 Adobe 宋体 std L
|
||||
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
|
||||
form.addSubstitutionFont(bfChinese);
|
||||
|
||||
// 表单赋值
|
||||
for(String key : data.keySet()){
|
||||
form.setField(key,data.get(key));
|
||||
// 也可以指定字体
|
||||
form.setFieldProperty(key, "textfont", bfChinese, null);
|
||||
}
|
||||
|
||||
if(null != imageData && imageData.size() > 0){
|
||||
for(String key : imageData.keySet()){
|
||||
int pageNo = form.getFieldPositions(key).get(0).page;
|
||||
Rectangle signRect = form.getFieldPositions(key).get(0).position;
|
||||
float x = signRect.getLeft();
|
||||
float y = signRect.getBottom();
|
||||
// 读图片
|
||||
Image image = Image.getInstance(imageData.get(key));
|
||||
// 获取操作的页面
|
||||
PdfContentByte under = pdfStamper.getOverContent(pageNo);
|
||||
// 根据域的大小缩放图片
|
||||
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
|
||||
// 添加图片
|
||||
image.setAbsolutePosition(x, y);
|
||||
under.addImage(image);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果为false那么生成的PDF文件还能编辑,一定要设为true
|
||||
pdfStamper.setFormFlattening(formFlattening);
|
||||
pdfStamper.close();
|
||||
|
||||
// 保存文件
|
||||
fos = new FileOutputStream(pdfFilePath);
|
||||
fos.write(bos.toByteArray());
|
||||
fos.flush();
|
||||
}finally {
|
||||
if(null != fos){
|
||||
try {fos.close(); }catch (Exception e){e.printStackTrace();}
|
||||
}
|
||||
|
||||
if(null != bos){
|
||||
try {bos.close(); }catch (Exception e){e.printStackTrace();}
|
||||
}
|
||||
|
||||
if(null != reader){
|
||||
try {reader.close(); }catch (Exception e){e.printStackTrace();}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// 模版文件
|
||||
String templateFilePath = "E:/shop/乐益播联盟商家入驻协议(APP版)(1).pdf";
|
||||
// 保存PDF文件
|
||||
String fileCode = System.currentTimeMillis()+"";
|
||||
String pdfFilePath = "E:/shoptest/"+fileCode+".pdf";
|
||||
// 电子签名图片
|
||||
String signImg = "E:/shop/1.jpg";
|
||||
|
||||
// 表单数据
|
||||
HashMap<String,String> data = new HashMap<>();
|
||||
data.put("contacts","宋");
|
||||
data.put("telephone","15315526196");
|
||||
data.put("name","星科瑞升");
|
||||
|
||||
data.put("discount","2");
|
||||
|
||||
data.put("monthone","01");
|
||||
data.put("dayone","11");
|
||||
data.put("year","3");
|
||||
|
||||
data.put("monthtwo","01");
|
||||
|
||||
data.put("daytwo","23");
|
||||
data.put("monththree","03");
|
||||
data.put("daythree","01");
|
||||
|
||||
// 图片数据
|
||||
HashMap<String,String> imageData = new HashMap<>();
|
||||
imageData.put("sign",signImg);
|
||||
|
||||
// 根据PDF模版生成PDF文件
|
||||
createPDF(templateFilePath,data,imageData,true,pdfFilePath);
|
||||
}
|
||||
}
|
174
src/main/java/com/xkrs/utils/Graphics2DUtil.java
Normal file
174
src/main/java/com/xkrs/utils/Graphics2DUtil.java
Normal file
@ -0,0 +1,174 @@
|
||||
package com.xkrs.utils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
|
||||
public class Graphics2DUtil {
|
||||
|
||||
private static final int WIDTH = 500;//图片宽度
|
||||
private static final int HEIGHT = 500;//图片高度
|
||||
private static String message = "芜羡科技有限公司";
|
||||
private static String centerName = "测试章";
|
||||
private static String year = "2018年06月11日";
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
BufferedImage image = startGraphics2D();
|
||||
try {
|
||||
String filePath = "D:\\"+System.currentTimeMillis()+".png";
|
||||
ImageIO.write(image, "png", new File(filePath)); //将其保存在D:\\下,得有这个目录
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static BufferedImage startGraphics2D(){
|
||||
// 定义图像buffer
|
||||
BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = buffImg.createGraphics();
|
||||
// 增加下面代码使得背景透明
|
||||
buffImg = g.getDeviceConfiguration().createCompatibleImage(WIDTH, HEIGHT, Transparency.TRANSLUCENT);
|
||||
g.dispose();
|
||||
g = buffImg.createGraphics();
|
||||
// 背景透明代码结束
|
||||
|
||||
g.setColor(Color.RED);
|
||||
//设置锯齿圆滑
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
//绘制圆
|
||||
int radius = HEIGHT/3;//周半径
|
||||
int CENTERX = WIDTH/2;//画图所出位置
|
||||
int CENTERY = HEIGHT/2;//画图所处位置
|
||||
|
||||
Ellipse2D circle = new Ellipse2D.Double();
|
||||
circle.setFrameFromCenter(CENTERX, CENTERY, CENTERX + radius, CENTERY + radius);
|
||||
g.setStroke(new BasicStroke(10));//设置圆的宽度
|
||||
g.draw(circle);
|
||||
|
||||
//绘制中间的五角星
|
||||
g.setFont(new Font("宋体", Font.BOLD, 120));
|
||||
g.drawString("★", CENTERX-(120/2), CENTERY+(120/3));
|
||||
|
||||
//添加姓名
|
||||
g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 30));// 写入签名
|
||||
g.drawString(centerName, CENTERX -(40), CENTERY +(30+50));
|
||||
|
||||
//添加年份
|
||||
g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 20));// 写入签名
|
||||
g.drawString(year, CENTERX -(60), CENTERY +(30+80));
|
||||
|
||||
//根据输入字符串得到字符数组
|
||||
String[] messages2 = message.split("",0);
|
||||
String[] messages = new String[messages2.length-1];
|
||||
System.arraycopy(messages2,1,messages,0,messages2.length-1);
|
||||
|
||||
//输入的字数
|
||||
int ilength = messages.length;
|
||||
|
||||
//设置字体属性
|
||||
int fontsize = 40;
|
||||
Font f = new Font("Serif", Font.BOLD, fontsize);
|
||||
|
||||
FontRenderContext context = g.getFontRenderContext();
|
||||
Rectangle2D bounds = f.getStringBounds(message, context);
|
||||
|
||||
//字符宽度=字符串长度/字符数
|
||||
double char_interval = (bounds.getWidth() / ilength);
|
||||
//上坡度
|
||||
double ascent = -bounds.getY();
|
||||
|
||||
int first = 0,second = 0;
|
||||
boolean odd = false;
|
||||
if (ilength%2 == 1)
|
||||
{
|
||||
first = (ilength-1)/2;
|
||||
odd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
first = (ilength)/2-1;
|
||||
second = (ilength)/2;
|
||||
odd = false;
|
||||
}
|
||||
|
||||
double radius2 = radius - ascent;
|
||||
double x0 = CENTERX;
|
||||
double y0 = CENTERY - radius + ascent;
|
||||
//旋转角度
|
||||
double a = 2*Math.asin(char_interval/(2*radius2));
|
||||
|
||||
if (odd)
|
||||
{
|
||||
g.setFont(f);
|
||||
g.drawString(messages[first], (float)(x0 - char_interval/2), (float)y0);
|
||||
|
||||
//中心点的右边
|
||||
for (int i=first+1;i<ilength;i++)
|
||||
{
|
||||
double aa = (i - first) * a;
|
||||
double ax = radius2 * Math.sin(aa);
|
||||
double ay = radius2 - radius2 * Math.cos(aa);
|
||||
AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);
|
||||
Font f2 = f.deriveFont(transform);
|
||||
g.setFont(f2);
|
||||
g.drawString(messages[i], (float)(x0 + ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay - char_interval/2* Math.sin(aa)));
|
||||
}
|
||||
//中心点的左边
|
||||
for (int i=first-1;i>-1;i--)
|
||||
{
|
||||
double aa = (first - i) * a;
|
||||
double ax = radius2 * Math.sin(aa);
|
||||
double ay = radius2 - radius2 * Math.cos(aa);
|
||||
AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);
|
||||
Font f2 = f.deriveFont(transform);
|
||||
g.setFont(f2);
|
||||
g.drawString(messages[i], (float)(x0 - ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay + char_interval/2* Math.sin(aa)));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//中心点的右边
|
||||
for (int i=second;i<ilength;i++)
|
||||
{
|
||||
double aa = (i - second + 0.5) * a;
|
||||
double ax = radius2 * Math.sin(aa);
|
||||
double ay = radius2 - radius2 * Math.cos(aa);
|
||||
AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);
|
||||
Font f2 = f.deriveFont(transform);
|
||||
g.setFont(f2);
|
||||
g.drawString(messages[i], (float)(x0 + ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay - char_interval/2* Math.sin(aa)));
|
||||
}
|
||||
|
||||
//中心点的左边
|
||||
for (int i=first;i>-1;i--)
|
||||
{
|
||||
double aa = (first - i + 0.5) * a;
|
||||
double ax = radius2 * Math.sin(aa);
|
||||
double ay = radius2 - radius2 * Math.cos(aa);
|
||||
AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);
|
||||
Font f2 = f.deriveFont(transform);
|
||||
g.setFont(f2);
|
||||
g.drawString(messages[i], (float)(x0 - ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay + char_interval/2* Math.sin(aa)));
|
||||
}
|
||||
}
|
||||
|
||||
return buffImg;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
server.port = 6801
|
||||
server.port = 6802
|
||||
|
||||
## 数据源配置
|
||||
spring.datasource.url = jdbc:mysql://rm-bp160630z03x880745o.mysql.rds.aliyuncs.com:3306/leyibo_business?useSSL=false&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&serverTimezone=Asia/Shanghai
|
||||
|
25
src/main/resources/docx4j.properties
Normal file
25
src/main/resources/docx4j.properties
Normal file
@ -0,0 +1,25 @@
|
||||
# Page size: use a value from org.docx4j.model.structure.PageSizePaper enum
|
||||
# eg A4, LETTER
|
||||
docx4j.PageSize=LETTER
|
||||
# Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum
|
||||
docx4j.PageMargins=NORMAL
|
||||
docx4j.PageOrientationLandscape=false
|
||||
# Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum
|
||||
# eg A4, LETTER
|
||||
pptx4j.PageSize=LETTER
|
||||
pptx4j.PageOrientationLandscape=false
|
||||
# These will be injected into docProps/app.xml
|
||||
# if App.Write=true
|
||||
docx4j.App.write=true
|
||||
docx4j.Application=docx4j
|
||||
docx4j.AppVersion=6.1.2
|
||||
# of the form XX.YYYY where X and Y represent numerical values
|
||||
# These will be injected into docProps/core.xml
|
||||
docx4j.dc.write=true
|
||||
docx4j.dc.creator.value=docx4j
|
||||
docx4j.dc.lastModifiedBy.value=docx4j
|
||||
#
|
||||
#docx4j.McPreprocessor=true
|
||||
# If you haven't configured log4j yourself
|
||||
# docx4j will autoconfigure it. Set this to true to disable that
|
||||
docx4j.Log4j.Configurator.disabled=false
|
Loading…
Reference in New Issue
Block a user