package com.nq.service.impl;
|
|
import com.nq.common.ServerResponse;
|
import com.nq.pojo.User;
|
import com.nq.service.IUserAgreementService;
|
import com.nq.utils.PropertiesUtil;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.*;
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import com.itextpdf.text.*;
|
import com.itextpdf.text.pdf.*;
|
import com.itextpdf.text.pdf.BaseFont;
|
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
|
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
import org.apache.pdfbox.rendering.ImageType;
|
import javax.imageio.ImageIO;
|
import java.awt.image.BufferedImage;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.awt.Graphics2D;
|
import java.awt.RenderingHints;
|
import java.awt.Color;
|
import java.awt.FontMetrics;
|
import com.nq.pojo.ContractImage;
|
import com.nq.dao.ContractImageMapper;
|
import com.alibaba.fastjson.JSON;
|
|
@Service("iUserAgreementService")
|
public class UserAgreementServiceImpl implements IUserAgreementService {
|
private static final Logger log = LoggerFactory.getLogger(UserAgreementServiceImpl.class);
|
|
@Autowired
|
private com.nq.service.IUserService iUserService;
|
|
@Autowired
|
private ContractImageMapper contractImageMapper;
|
|
@Override
|
|
// 在generateAgreementPdf方法中修改返回逻辑
|
public ServerResponse generateAgreementPdf(HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
user = (User) iUserService.findByUserId(user.getId()).getData();
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
if (user.getIsActive()!=2 || StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()) || StringUtils.isBlank(user.getRegAddress())) {
|
return ServerResponse.createByErrorMsg("请先完成实名认证");
|
}
|
|
// 检查是否已生成PDF
|
String pdfDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
|
File dir = new File(pdfDir);
|
if (!dir.exists()) {
|
dir.mkdirs();
|
}
|
|
String pdfFileName = "contract_" + user.getId() + ".pdf";
|
File pdfFile = new File(dir, pdfFileName);
|
|
// 如果PDF已存在,删除后重新生成,确保数据是最新的
|
if (pdfFile.exists()) {
|
log.info("PDF文件已存在,删除后重新生成: {}", pdfFile.getAbsolutePath());
|
boolean deleted = pdfFile.delete();
|
if (!deleted) {
|
log.warn("删除旧PDF文件失败: {}", pdfFile.getAbsolutePath());
|
}
|
}
|
|
// 从资源中读取PDF模板文件
|
File pdfTemplate = getTemplateFile("中原证券股票分成协议(电子正式版).pdf");
|
if (pdfTemplate == null || !pdfTemplate.exists()) {
|
return ServerResponse.createByErrorMsg("PDF模板文件不存在");
|
}
|
|
// 从PDF模板生成新的PDF,替换占位符
|
generatePdfFromTemplate(pdfTemplate, pdfFile, user);
|
|
// 将PDF转换为图片并返回图片路径数组
|
List<String> imageUrls = convertPdfToImages(pdfFile, "contract", user.getId());
|
|
return ServerResponse.createBySuccess(imageUrls);
|
} catch (Exception e) {
|
log.error("生成用户协议PDF失败", e);
|
return ServerResponse.createByErrorMsg("生成PDF失败:" + e.getMessage());
|
}
|
}
|
|
/**
|
* 从PDF模板生成新的PDF,替换占位符
|
*/
|
private void generatePdfFromTemplate(File templatePdf, File outputPdf, User user) throws Exception {
|
log.info("开始生成PDF,模板路径: {}, 输出路径: {}, 用户: {}",
|
templatePdf.getAbsolutePath(), outputPdf.getAbsolutePath(), user.getId());
|
|
PdfReader reader = null;
|
PdfStamper stamper = null;
|
FileOutputStream fos = null;
|
|
try {
|
reader = new PdfReader(new FileInputStream(templatePdf));
|
fos = new FileOutputStream(outputPdf);
|
stamper = new PdfStamper(reader, fos);
|
|
// 设置中文字体,使用EMBEDDED确保字体嵌入PDF,避免转图片时乱码
|
// 使用itext-asian库提供的中文字体,必须使用EMBEDDED模式
|
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
|
Font font = new Font(baseFont, 12, Font.NORMAL);
|
|
log.info("中文字体已加载: {}", baseFont.getPostscriptFontName());
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
|
String currentDate = sdf.format(new Date());
|
|
// 准备替换的数据
|
String realName = user.getRealName() != null ? user.getRealName() : "";
|
String idCard = user.getIdCard() != null ? user.getIdCard() : "";
|
String address = user.getRegAddress() != null ? user.getRegAddress() : "";
|
|
log.info("PDF生成数据 - 姓名: {}, 身份证: {}, 地址: {}", realName, idCard, address);
|
|
// 获取PDF页数
|
int pageCount = reader.getNumberOfPages();
|
log.info("PDF模板页数: {}", pageCount);
|
|
// 在每一页上查找并替换占位符
|
for (int pageNum = 1; pageNum <= pageCount; pageNum++) {
|
PdfContentByte canvas = stamper.getOverContent(pageNum);
|
Rectangle pageSize = reader.getPageSize(pageNum);
|
|
// 提取PDF文本查找占位符位置
|
String pageText = PdfTextExtractor.getTextFromPage(reader, pageNum, new SimpleTextExtractionStrategy());
|
|
// 在PDF上查找并替换占位符
|
replacePlaceholdersInPdf(canvas, pageSize, pageText, realName, idCard, address, currentDate, font, pageNum);
|
log.info("已处理PDF第{}页", pageNum);
|
}
|
|
stamper.close();
|
stamper = null;
|
reader.close();
|
reader = null;
|
fos.close();
|
fos = null;
|
|
// 验证生成的文件
|
if (outputPdf.exists()) {
|
long fileSize = outputPdf.length();
|
log.info("PDF生成完成,文件路径: {}, 文件大小: {} 字节", outputPdf.getAbsolutePath(), fileSize);
|
if (fileSize == 0) {
|
throw new Exception("生成的PDF文件大小为0");
|
}
|
} else {
|
throw new Exception("PDF文件生成失败,文件不存在");
|
}
|
} catch (Exception e) {
|
log.error("生成PDF失败", e);
|
throw e;
|
} finally {
|
if (stamper != null) {
|
try {
|
stamper.close();
|
} catch (Exception e) {
|
log.error("关闭stamper失败", e);
|
}
|
}
|
if (reader != null) {
|
try {
|
reader.close();
|
} catch (Exception e) {
|
log.error("关闭reader失败", e);
|
}
|
}
|
if (fos != null) {
|
try {
|
fos.close();
|
} catch (Exception e) {
|
log.error("关闭输出流失败", e);
|
}
|
}
|
}
|
}
|
|
/**
|
* 在PDF上替换占位符(使用透明背景图片方式)
|
*/
|
private void replacePlaceholdersInPdf(PdfContentByte canvas, Rectangle pageSize, String pageText,
|
String realName, String idCard, String address,
|
String currentDate, Font font,int pageNum) throws Exception {
|
float margin = 50;
|
float lineHeight = 14;
|
float startY = pageSize.getHeight() - 204;
|
|
if(pageNum == 1){
|
// 生成透明背景的姓名图片并插入
|
File nameImage = createTextImage(realName, font);
|
insertImageToPdf(canvas, nameImage, margin + 75, startY);
|
startY -= lineHeight;
|
|
// 生成透明背景的地址图片并插入
|
File addressImage = createTextImage(address, font);
|
insertImageToPdf(canvas, addressImage, margin + 75, startY-2);
|
startY -= lineHeight;
|
|
// 生成透明背景的身份证号图片并插入
|
File idCardImage = createTextImage(idCard, font);
|
insertImageToPdf(canvas, idCardImage, margin + 95, startY-2);
|
}
|
if(pageNum == 3){
|
// 生成透明背景的日期图片并插入
|
File dateImage1 = createTextImage(currentDate, font);
|
insertImageToPdf(canvas, dateImage1, margin + 60, startY+32);
|
|
File dateImage2 = createTextImage(currentDate, font);
|
insertImageToPdf(canvas, dateImage2, margin + 60, startY);
|
}
|
}
|
|
/**
|
* 创建透明背景的文本图片
|
*/
|
private File createTextImage(String text, Font font) throws Exception {
|
if (StringUtils.isBlank(text)) {
|
text = "";
|
}
|
|
// 创建临时文件
|
String tempDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
File dir = new File(tempDir);
|
if (!dir.exists()) {
|
dir.mkdirs();
|
}
|
|
String tempFileName = "text_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId() + ".png";
|
File imageFile = new File(dir, tempFileName);
|
|
// 创建透明背景的BufferedImage (TYPE_INT_ARGB 默认透明)
|
BufferedImage image = new BufferedImage(500, 50, BufferedImage.TYPE_INT_ARGB);
|
Graphics2D g2d = image.createGraphics();
|
|
// 启用透明背景支持
|
g2d.setComposite(java.awt.AlphaComposite.SrcOver);
|
|
// 设置高质量渲染
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
|
|
// 设置字体和颜色
|
try {
|
java.awt.Font awtFont = new java.awt.Font("SimSun", java.awt.Font.PLAIN, 12);
|
g2d.setFont(awtFont);
|
} catch (Exception e) {
|
log.warn("无法加载SimSun字体,使用默认字体", e);
|
g2d.setFont(new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 12));
|
}
|
// 使用深黑色,RGB(0, 0, 0) 完全不透明
|
g2d.setColor(new Color(0, 0, 0, 255));
|
|
// 绘制文本
|
FontMetrics fm = g2d.getFontMetrics();
|
int textWidth = fm.stringWidth(text);
|
int textHeight = fm.getHeight();
|
|
// 调整图片大小以适应文本
|
if (textWidth > 0 && textHeight > 0) {
|
// TYPE_INT_ARGB 类型默认透明背景,不需要清除
|
BufferedImage resizedImage = new BufferedImage(textWidth + 20, textHeight + 10, BufferedImage.TYPE_INT_ARGB);
|
Graphics2D g2dResized = resizedImage.createGraphics();
|
|
// 启用透明背景支持
|
g2dResized.setComposite(java.awt.AlphaComposite.SrcOver);
|
|
// 设置高质量渲染
|
g2dResized.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2dResized.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
|
g2dResized.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
g2dResized.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
|
|
// 设置字体
|
try {
|
java.awt.Font awtFont = new java.awt.Font("SimSun", java.awt.Font.PLAIN, 12);
|
g2dResized.setFont(awtFont);
|
} catch (Exception e) {
|
g2dResized.setFont(new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 12));
|
}
|
// 使用深黑色,RGB(0, 0, 0) 完全不透明
|
g2dResized.setColor(new Color(0, 0, 0, 255));
|
|
// 绘制文本
|
g2dResized.drawString(text, 10, textHeight);
|
g2dResized.dispose();
|
|
// 保存图片
|
ImageIO.write(resizedImage, "PNG", imageFile);
|
image = resizedImage;
|
} else {
|
// 如果文本为空,创建一个小的透明图片
|
BufferedImage emptyImage = new BufferedImage(50, 20, BufferedImage.TYPE_INT_ARGB);
|
ImageIO.write(emptyImage, "PNG", imageFile);
|
image = emptyImage;
|
}
|
|
g2d.dispose();
|
|
log.info("已创建透明背景文本图片: {}, 文本: {}", imageFile.getAbsolutePath(), text);
|
return imageFile;
|
}
|
|
/**
|
* 将图片插入到PDF指定位置
|
*/
|
private void insertImageToPdf(PdfContentByte canvas, File imageFile, float x, float y) throws Exception {
|
if (imageFile == null || !imageFile.exists()) {
|
log.warn("图片文件不存在: {}", imageFile);
|
return;
|
}
|
|
try {
|
Image image = Image.getInstance(imageFile.getAbsolutePath());
|
image.setAbsolutePosition(x, y);
|
canvas.addImage(image);
|
log.info("图片已插入到PDF,位置: ({}, {})", x, y);
|
|
// 删除临时图片文件
|
try {
|
imageFile.delete();
|
} catch (Exception e) {
|
log.warn("删除临时图片文件失败: {}", imageFile.getAbsolutePath(), e);
|
}
|
} catch (Exception e) {
|
log.error("插入图片到PDF失败: {}", imageFile.getAbsolutePath(), e);
|
throw e;
|
}
|
}
|
|
@Override
|
public ServerResponse viewAgreementPdf(HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
// 从数据库查询已签名的图片
|
List<ContractImage> contractImages = contractImageMapper.selectByUserIdAndType(user.getId(), "contract");
|
List<String> imageUrls = new ArrayList<>();
|
|
if (contractImages != null && !contractImages.isEmpty()) {
|
for (ContractImage image : contractImages) {
|
imageUrls.add(image.getAddress());
|
}
|
log.info("从数据库查询到用户{}的{}张已签名合同图片", user.getId(), imageUrls.size());
|
}
|
|
return ServerResponse.createBySuccess(imageUrls);
|
} catch (Exception e) {
|
log.error("查看用户协议PDF失败", e);
|
return ServerResponse.createByErrorMsg("查看PDF失败: " + e.getMessage());
|
}
|
}
|
|
@Override
|
public ServerResponse saveAgreementSignature(MultipartFile signatureFile, HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
if (signatureFile == null || signatureFile.isEmpty()) {
|
return ServerResponse.createByErrorMsg("签名图片不能为空");
|
}
|
|
String signatureDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
File dir = new File(signatureDir);
|
if (!dir.exists()) {
|
dir.mkdirs();
|
}
|
|
String signatureFileName = "signature_" + user.getId() + ".png";
|
File signatureFileLocal = new File(dir, signatureFileName);
|
|
signatureFile.transferTo(signatureFileLocal);
|
|
log.info("用户{}的签名图片已保存: {}", user.getId(), signatureFileLocal.getAbsolutePath());
|
|
String pdfDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
String pdfFileName = "contract_" + user.getId() + ".pdf";
|
File pdfFile = new File(pdfDir, pdfFileName);
|
//删之前的图片
|
deleteFilesWithPattern(pdfDir,"contract_" + user.getId());
|
if (pdfFile.exists()) {
|
addSignatureToPdf(pdfFile, signatureFileLocal, user);
|
List<String> imageUrls = convertPdfToImages(pdfFile, "contract", user.getId());
|
for(String imageUrl : imageUrls) {
|
ContractImage contractImage = new ContractImage();
|
contractImage.setUserId(user.getId());
|
contractImage.setContractType("contract");
|
contractImage.setAddress(imageUrl);
|
contractImage.setAddTime(new Date());
|
contractImageMapper.insert(contractImage);
|
}
|
iUserService.updateSignedContract(user.getId(), "Y");
|
}
|
return ServerResponse.createBySuccessMsg("签名保存成功");
|
} catch (Exception e) {
|
log.error("保存用户协议签名失败", e);
|
return ServerResponse.createByErrorMsg("保存签名失败:" + e.getMessage());
|
}
|
}
|
|
/**
|
* 在PDF第三页插入签名图片
|
*/
|
private void addSignatureToPdf(File pdfFile, File signatureImage, User user) throws Exception {
|
PdfReader reader = new PdfReader(new FileInputStream(pdfFile));
|
File tempPdf = new File(pdfFile.getParent(), "temp_" + pdfFile.getName());
|
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(tempPdf));
|
|
int pageCount = reader.getNumberOfPages();
|
|
// 在第三页插入签名图片
|
if (pageCount >= 3) {
|
PdfContentByte canvas = stamper.getOverContent(3);
|
Rectangle pageSize = reader.getPageSize(3);
|
|
// 添加签名图片
|
if (signatureImage.exists()) {
|
Image image = Image.getInstance(signatureImage.getAbsolutePath());
|
// 设置图片大小(根据实际需要调整)
|
image.scaleToFit(100, 100);
|
// 设置图片位置(使用与addHeaderImageToPdf相同的坐标)
|
image.setAbsolutePosition(370, pageSize.getHeight() - 194);
|
canvas.addImage(image);
|
log.info("签名图片已插入到PDF第三页,位置: (370, {})", pageSize.getHeight() - 194);
|
}
|
}
|
|
stamper.close();
|
reader.close();
|
|
// 替换原PDF文件
|
if (tempPdf.exists()) {
|
pdfFile.delete();
|
tempPdf.renameTo(pdfFile);
|
log.info("PDF文件已更新,签名图片已插入");
|
}
|
}
|
|
@Override
|
public ServerResponse generateAgreementContractPdf(HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
user = (User) iUserService.findByUserId(user.getId()).getData();
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
if (user.getIsActive()!=2 || StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()) || StringUtils.isBlank(user.getRegAddress())) {
|
return ServerResponse.createByErrorMsg("用户信息不完整,请先完成实名认证");
|
}
|
|
String pdfDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
File dir = new File(pdfDir);
|
if (!dir.exists()) {
|
dir.mkdirs();
|
}
|
|
String pdfFileName = "agreement_" + user.getId() + ".pdf";
|
File pdfFile = new File(dir, pdfFileName);
|
|
if (pdfFile.exists()) {
|
boolean deleted = pdfFile.delete();
|
if (!deleted) {
|
log.warn("删除旧PDF文件失败: {}", pdfFile.getAbsolutePath());
|
}
|
}
|
|
// 从资源中读取PDF模板文件
|
File pdfTemplate = getTemplateFile("中原证券商业核心信息保密协议.pdf");
|
if (pdfTemplate == null || !pdfTemplate.exists()) {
|
return ServerResponse.createByErrorMsg("PDF模板文件不存在");
|
}
|
|
generateContractPdfFromTemplate(pdfTemplate, pdfFile, user);
|
|
// 将PDF转换为图片并返回图片路径数组
|
List<String> imageUrls = convertPdfToImages(pdfFile, "agreement", user.getId());
|
|
return ServerResponse.createBySuccess(imageUrls);
|
} catch (Exception e) {
|
log.error("生成用户合同PDF失败", e);
|
return ServerResponse.createByErrorMsg("生成PDF失败:" + e.getMessage());
|
}
|
}
|
|
@Override
|
public void viewAgreementContractPdf(HttpServletRequest request, HttpServletResponse response) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
if (user == null) {
|
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "用户未登录");
|
return;
|
}
|
|
// 从数据库查询已签名的图片
|
List<ContractImage> contractImages = contractImageMapper.selectByUserIdAndType(user.getId(), "agreement");
|
List<String> imageUrls = new ArrayList<>();
|
|
if (contractImages != null && !contractImages.isEmpty()) {
|
for (ContractImage image : contractImages) {
|
imageUrls.add(image.getAddress());
|
}
|
log.info("从数据库查询到用户{}的{}张已签名保密协议图片", user.getId(), imageUrls.size());
|
}
|
|
response.setContentType("application/json;charset=UTF-8");
|
response.getWriter().write(JSON.toJSONString(ServerResponse.createBySuccess(imageUrls)));
|
response.getWriter().flush();
|
} catch (Exception e) {
|
log.error("查看用户合同PDF失败", e);
|
try {
|
if (!response.isCommitted()) {
|
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "查看PDF失败: " + e.getMessage());
|
}
|
} catch (IOException ex) {
|
log.error("发送错误响应失败", ex);
|
}
|
}
|
}
|
|
@Override
|
public ServerResponse saveAgreementContractSignature(MultipartFile signatureFile, HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
if (signatureFile == null || signatureFile.isEmpty()) {
|
return ServerResponse.createByErrorMsg("签名图片不能为空");
|
}
|
|
String signatureDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
File dir = new File(signatureDir);
|
if (!dir.exists()) {
|
dir.mkdirs();
|
}
|
|
String signatureFileName = "agreement_signature_" + user.getId() + ".png";
|
File signatureFileLocal = new File(dir, signatureFileName);
|
|
signatureFile.transferTo(signatureFileLocal);
|
|
log.info("用户{}的合同签名图片已保存: {}", user.getId(), signatureFileLocal.getAbsolutePath());
|
|
String pdfDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
String pdfFileName = "agreement_" + user.getId() + ".pdf";
|
File pdfFile = new File(pdfDir, pdfFileName);
|
//删之前的图片
|
deleteFilesWithPattern(pdfDir,"agreement_" + user.getId());
|
if (pdfFile.exists()) {
|
addSignatureToContractPdf(pdfFile, signatureFileLocal, user);
|
|
List<String> imageUrls = convertPdfToImages(pdfFile, "agreement", user.getId());
|
for (String imageUrl : imageUrls) {
|
ContractImage contractImage = new ContractImage();
|
contractImage.setUserId(user.getId());
|
contractImage.setContractType("agreement");
|
contractImage.setAddress(imageUrl);
|
contractImage.setAddTime(new Date());
|
contractImageMapper.insert(contractImage);
|
}
|
iUserService.updateSignedAgreement(user.getId(), "Y");
|
}
|
|
return ServerResponse.createBySuccessMsg("签名保存成功");
|
} catch (Exception e) {
|
log.error("保存用户合同签名失败", e);
|
return ServerResponse.createByErrorMsg("保存签名失败:" + e.getMessage());
|
}
|
}
|
|
private void generateContractPdfFromTemplate(File templatePdf, File outputPdf, User user) throws Exception {
|
PdfReader reader = new PdfReader(new FileInputStream(templatePdf));
|
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdf));
|
|
// 设置中文字体,使用EMBEDDED确保字体嵌入PDF,避免转图片时乱码
|
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
|
Font font = new Font(baseFont, 12, Font.NORMAL);
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
|
String currentDate = sdf.format(new Date());
|
|
int pageCount = reader.getNumberOfPages();
|
|
for (int pageNum = 1; pageNum <= pageCount; pageNum++) {
|
PdfContentByte canvas = stamper.getOverContent(pageNum);
|
Rectangle pageSize = reader.getPageSize(pageNum);
|
|
replacePlaceholdersInContractPdf(canvas, pageSize, currentDate, font, pageNum);
|
}
|
|
stamper.close();
|
reader.close();
|
}
|
|
private void replacePlaceholdersInContractPdf(PdfContentByte canvas, Rectangle pageSize, String currentDate, Font font, int pageNum) throws Exception {
|
float margin = 50;
|
float startY = pageSize.getHeight() - 374;
|
if(pageNum == 2){
|
// 生成透明背景的日期图片并插入
|
File dateImage = createTextImage(currentDate, font);
|
insertImageToPdf(canvas, dateImage, margin + 320, startY);
|
}
|
}
|
|
private void addSignatureToContractPdf(File pdfFile, File signatureImage, User user) throws Exception {
|
PdfReader reader = new PdfReader(new FileInputStream(pdfFile));
|
File tempPdf = new File(pdfFile.getParent(), "temp_" + pdfFile.getName());
|
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(tempPdf));
|
|
int pageCount = reader.getNumberOfPages();
|
|
if (pageCount >= 2) {
|
PdfContentByte canvas = stamper.getOverContent(2);
|
Rectangle pageSize = reader.getPageSize(2);
|
|
if (signatureImage.exists()) {
|
Image image = Image.getInstance(signatureImage.getAbsolutePath());
|
image.scaleToFit(100, 100);
|
image.setAbsolutePosition(435, pageSize.getHeight() - 288);
|
canvas.addImage(image);
|
log.info("签名图片已插入到合同PDF第二页");
|
}
|
}
|
|
stamper.close();
|
reader.close();
|
|
if (tempPdf.exists()) {
|
pdfFile.delete();
|
tempPdf.renameTo(pdfFile);
|
log.info("合同PDF文件已更新,签名图片已插入");
|
}
|
}
|
|
/**
|
* 从固定目录获取模板文件
|
*/
|
private File getTemplateFile(String templateFileName) {
|
try {
|
String templateDir = PropertiesUtil.getProperty("pdf.template.dir");
|
if (StringUtils.isBlank(templateDir)) {
|
log.error("PDF模板目录配置不存在: pdf.template.dir");
|
return null;
|
}
|
|
File dir = new File(templateDir);
|
if (!dir.exists()) {
|
log.error("PDF模板目录不存在: {}", templateDir);
|
return null;
|
}
|
|
File templateFile = new File(dir, templateFileName);
|
if (!templateFile.exists()) {
|
log.error("PDF模板文件不存在: {}", templateFile.getAbsolutePath());
|
return null;
|
}
|
|
log.info("使用模板文件: {}", templateFile.getAbsolutePath());
|
return templateFile;
|
} catch (Exception e) {
|
log.error("获取模板文件失败: {}", templateFileName, e);
|
return null;
|
}
|
}
|
/**
|
* 将PDF转换为图片
|
*/
|
private List<String> convertPdfToImages(File pdfFile, String contractType, Integer userId) throws Exception {
|
List<String> imageUrls = new ArrayList<>();
|
String imagePrefix = PropertiesUtil.getProperty("pdf.server.http.prefix");
|
String pdfDir = PropertiesUtil.getProperty("loca.pdf.dir");
|
|
long timestamp = System.currentTimeMillis();
|
PDDocument document = null;
|
try {
|
document = PDDocument.load(pdfFile);
|
|
// 创建PDFRenderer,使用高质量渲染
|
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
|
int pageCount = document.getNumberOfPages();
|
log.info("PDF总页数: {}", pageCount);
|
|
for (int page = 0; page < pageCount; page++) {
|
// 使用RGB模式渲染,DPI设置为300确保文字清晰
|
// ImageType.RGB可以更好地处理中文字体
|
BufferedImage image = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
|
|
// 对图片进行优化处理,确保文字清晰
|
BufferedImage optimizedImage = optimizeImage(image);
|
|
String imageFileName = contractType + "_" +userId +"_" + timestamp + ".png";
|
if (page > 0) {
|
imageFileName = contractType+ "_" + userId + "_" + timestamp + "_" + (page + 1) + ".png";
|
}
|
File imageFile = new File(pdfDir, imageFileName);
|
|
ImageIO.write(optimizedImage, "png", imageFile);
|
|
String imageUrl = imagePrefix + "/" + imageFileName;
|
imageUrls.add(imageUrl);
|
|
log.info("PDF第{}页已转换为图片: {}", page + 1, imageUrl);
|
}
|
} finally {
|
if (document != null) {
|
document.close();
|
}
|
}
|
|
return imageUrls;
|
}
|
|
/**
|
* 优化图片,确保文字清晰
|
*/
|
private BufferedImage optimizeImage(BufferedImage originalImage) {
|
int width = originalImage.getWidth();
|
int height = originalImage.getHeight();
|
|
BufferedImage optimizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
Graphics2D g2d = optimizedImage.createGraphics();
|
|
// 设置高质量渲染
|
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
|
g2d.drawImage(originalImage, 0, 0, null);
|
g2d.dispose();
|
|
return optimizedImage;
|
}
|
|
@Override
|
public ServerResponse getContractImages(HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
List<ContractImage> images = contractImageMapper.selectByUserIdAndType(user.getId(), "contract");
|
List<String> imageUrls = new ArrayList<>();
|
for (ContractImage image : images) {
|
imageUrls.add(image.getAddress());
|
}
|
|
return ServerResponse.createBySuccess(imageUrls);
|
} catch (Exception e) {
|
log.error("查询合同图片列表失败", e);
|
return ServerResponse.createByErrorMsg("查询失败:" + e.getMessage());
|
}
|
}
|
|
@Override
|
public ServerResponse getAgreementImages(HttpServletRequest request) {
|
try {
|
User user = iUserService.getCurrentUser(request);
|
if (user == null) {
|
return ServerResponse.createByErrorMsg("用户未登录");
|
}
|
|
List<ContractImage> images = contractImageMapper.selectByUserIdAndType(user.getId(), "agreement");
|
List<String> imageUrls = new ArrayList<>();
|
for (ContractImage image : images) {
|
imageUrls.add(image.getAddress());
|
}
|
|
return ServerResponse.createBySuccess(imageUrls);
|
} catch (Exception e) {
|
log.error("查询保密协议图片列表失败", e);
|
return ServerResponse.createByErrorMsg("查询失败:" + e.getMessage());
|
}
|
}
|
|
public void deleteFilesWithPattern(String dirPath, String userId) {
|
File directory = new File(dirPath);
|
if (!directory.exists() || !directory.isDirectory()) {
|
System.out.println("目录不存在或路径错误: " + dirPath);
|
return;
|
}
|
|
File[] files = directory.listFiles((dir, name) -> name.contains(userId + "_"));
|
if (files != null) {
|
for (File file : files) {
|
if (file.delete()) {
|
System.out.println("已删除文件: " + file.getName());
|
} else {
|
System.out.println("删除失败: " + file.getName());
|
}
|
}
|
}
|
}
|
}
|