开发了线上合同电子协议得功能模块

This commit is contained in:
XinYi Song 2022-01-11 15:11:23 +08:00
parent 6e2d97368a
commit a2653507d2
7 changed files with 358 additions and 4 deletions

29
pom.xml
View File

@ -242,14 +242,31 @@
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>3.3.0</version> <version>3.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.zxing</groupId> <groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId> <artifactId>javase</artifactId>
<version>3.3.0</version> <version>3.3.0</version>
</dependency> </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> </dependencies>
@ -282,5 +299,13 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<repositories>
<repository>
<id>aspose-maven-repository</id>
<url>http://artifact.aspose.com/repo/</url>
</repository>
</repositories>
</project> </project>

BIN
simyou.TTF Normal file

Binary file not shown.

View File

@ -317,7 +317,7 @@ public class SysUserController {
} }
/** /**
* 用户修改密码 * 用户修改账号密码
* @param map * @param map
* @param token * @param token
* @return * @return

View 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);
}
}

View 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;
}
}

View File

@ -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 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

View 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