diff --git a/pom.xml b/pom.xml index 0553bb8..cd0760d 100644 --- a/pom.xml +++ b/pom.xml @@ -242,14 +242,31 @@ core 3.3.0 - - com.google.zxing javase 3.3.0 + + org.docx4j + docx4j + 6.1.2 + + + + + com.itextpdf + itextpdf + 5.5.13 + + + com.itextpdf + itext-asian + 5.2.0 + + + @@ -282,5 +299,13 @@ + + + + aspose-maven-repository + http://artifact.aspose.com/repo/ + + + diff --git a/simyou.TTF b/simyou.TTF new file mode 100644 index 0000000..4a8f27e Binary files /dev/null and b/simyou.TTF differ diff --git a/src/main/java/com/xkrs/controller/SysUserController.java b/src/main/java/com/xkrs/controller/SysUserController.java index af97cd6..f81546a 100644 --- a/src/main/java/com/xkrs/controller/SysUserController.java +++ b/src/main/java/com/xkrs/controller/SysUserController.java @@ -317,7 +317,7 @@ public class SysUserController { } /** - * 用户修改密码 + * 用户修改账号密码 * @param map * @param token * @return diff --git a/src/main/java/com/xkrs/utils/ElectronicContractUtil.java b/src/main/java/com/xkrs/utils/ElectronicContractUtil.java new file mode 100644 index 0000000..054ab52 --- /dev/null +++ b/src/main/java/com/xkrs/utils/ElectronicContractUtil.java @@ -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 data, HashMap 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 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 imageData = new HashMap<>(); + imageData.put("sign",signImg); + + // 根据PDF模版生成PDF文件 + createPDF(templateFilePath,data,imageData,true,pdfFilePath); + } +} diff --git a/src/main/java/com/xkrs/utils/Graphics2DUtil.java b/src/main/java/com/xkrs/utils/Graphics2DUtil.java new file mode 100644 index 0000000..959b148 --- /dev/null +++ b/src/main/java/com/xkrs/utils/Graphics2DUtil.java @@ -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-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-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; + } + + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6650003..26db9cf 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -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 diff --git a/src/main/resources/docx4j.properties b/src/main/resources/docx4j.properties new file mode 100644 index 0000000..54827b8 --- /dev/null +++ b/src/main/resources/docx4j.properties @@ -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 \ No newline at end of file