From dec83ac3db7a9986bdc405d6d9464ce9205be418 Mon Sep 17 00:00:00 2001 From: ggxl <194689125@qq.com> Date: Mon, 19 May 2025 14:32:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=AE=E6=97=85=E6=8A=A5=E9=94=80=E5=8D=95?= =?UTF-8?q?=E5=8F=91=E7=A5=A8=E3=80=81=E9=99=84=E4=BB=B6=E6=89=93=E5=8D=B0?= =?UTF-8?q?-=E9=BE=9A=E5=AE=87=E6=9D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../print/TripReimbursePrintPlugin.java | 296 ++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 src/main/java/zf47/jdgz1/fi/em/plugin/print/TripReimbursePrintPlugin.java diff --git a/src/main/java/zf47/jdgz1/fi/em/plugin/print/TripReimbursePrintPlugin.java b/src/main/java/zf47/jdgz1/fi/em/plugin/print/TripReimbursePrintPlugin.java new file mode 100644 index 0000000..16e7bab --- /dev/null +++ b/src/main/java/zf47/jdgz1/fi/em/plugin/print/TripReimbursePrintPlugin.java @@ -0,0 +1,296 @@ +package zf47.jdgz1.fi.em.plugin.print; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.fileservice.FileItem; +import kd.bos.fileservice.FileService; +import kd.bos.fileservice.FileServiceFactory; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.print.core.data.DataRowSet; +import kd.bos.print.core.data.field.ImageField; +import kd.bos.print.core.plugin.AbstractPrintPlugin; +import kd.bos.print.core.plugin.event.CustomDataLoadEvent; +import kd.bos.print.core.plugin.event.EndExportEvent; +import kd.bos.service.attachment.FilePathService; +import kd.bos.servicehelper.AttachmentServiceHelper; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.url.UrlService; +import kd.sdk.plugin.Plugin; +import org.apache.commons.lang3.StringUtils; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.ImageType; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.ofdrw.converter.ImageMaker; +import org.ofdrw.reader.OFDReader; + +import javax.imageio.ImageIO; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.*; + +/** + * 新的打印插件 + */ +public class TripReimbursePrintPlugin extends AbstractPrintPlugin implements Plugin { + + /* + * 差旅报销单-发票、附件打印 + * */ + + private static final Log log = LogFactory.getLog(TripReimbursePrintPlugin.class); + private final String PrintNum = null;//单据打印模板编号 + private static HashSet deleteUrl = new HashSet<>(); + //自定义数据源标识 + private static final String CUSTOM_DS = "imageDs"; + //主数据源标识(差旅报销单formId) + private static final String MAIN_DS = "er_tripreimbursebill"; + + @Override + public void loadCustomData(CustomDataLoadEvent evt) { + List customDataRows = evt.getCustomDataRows(); + //加载自定义数据源,根据关联关系查询出上游单据中图片地址,构造自定义数据源数据包 + if (CUSTOM_DS.equals(evt.getDataSource().getDsName())) { + log.info(evt.getDataSource().getDsName()); + //拿源单类型 + Object pkId = evt.getDataSource().getPkId(); + DynamicObject bill = BusinessDataServiceHelper.loadSingle(pkId, MAIN_DS); + if (bill != null) { + long billId = bill.getLong("id"); + //发票信息分录 + DynamicObjectCollection srcInvEntries = bill.getDynamicObjectCollection("invoiceentry"); + if (srcInvEntries != null && !srcInvEntries.isEmpty()) { + for (DynamicObject srcInvEntry : srcInvEntries) { + String serialNo = srcInvEntry.getString("serialno");//发票序列号 + QFilter qInvFile = new QFilter("serial_no", QCP.equals, serialNo); + DynamicObject[] invFiles = BusinessDataServiceHelper.load("rim_invoice_file", + "image_url", new QFilter[]{qInvFile}); + for (DynamicObject invFile : invFiles) { + String url = invFile.getString("image_url"); + if (StringUtils.isNotBlank(url)) { + ArrayList handleUrls = handlePicAttUrl(url); + for (String handleUrl : handleUrls) { + DataRowSet dataRowSet = new DataRowSet(); + ImageField imageField = new ImageField(handleUrl); + dataRowSet.put("imageUrl", imageField); + customDataRows.add(dataRowSet); + } + } + } + } + } + //获取源单的附件 + List> attachments = AttachmentServiceHelper.getAttachments(MAIN_DS, billId, "attachmentpanel"); + //遍历文件 + for (Map att : attachments) { + String relativeUrl = (String) att.get("relativeUrl"); + String attType = (String) att.get("type"); + if ("jpg".equalsIgnoreCase(attType) || "jpeg".equalsIgnoreCase(attType) || "png".equalsIgnoreCase(attType) + || "bmp".equalsIgnoreCase(attType) || "gif".equalsIgnoreCase(attType)) { + ArrayList urls = handlePicAttUrl(relativeUrl); + if (!urls.isEmpty()) { + for (String s : urls) { + DataRowSet dataRowSet = new DataRowSet(); + //根据图片地址信息构造图片字段,图片字段使用ImageField + ImageField imageField = new ImageField(s); + dataRowSet.put("imageUrl", imageField); + customDataRows.add(dataRowSet); + } + } + } else if ("pdf".equalsIgnoreCase(attType)) {//PDF转图片 + try { + ArrayList pic = PDFtoPic(relativeUrl, ""); + if (!pic.isEmpty()) { + for (String u : pic) { + DataRowSet dataRowSet = new DataRowSet(); + //根据图片地址信息构造图片字段,图片字段使用ImageField + ImageField imageField = new ImageField(u); + dataRowSet.put("imageUrl", imageField); + customDataRows.add(dataRowSet); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if ("ofd".equalsIgnoreCase(attType)) {//OFD转图片 + try { + ArrayList pic = OFDtoPic(relativeUrl); + if (!pic.isEmpty()) { + for (String u : pic) { + DataRowSet dataRowSet = new DataRowSet(); + //根据图片地址信息构造图片字段,图片字段使用ImageField + ImageField imageField = new ImageField(u); + dataRowSet.put("imageUrl", imageField); + customDataRows.add(dataRowSet); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } + } + } + + private ArrayList PDFtoPic(String url, String type) throws Exception { + ArrayList resUrls = new ArrayList<>(); + try { + FileService fs = FileServiceFactory.getAttachmentFileService(); + FilePathService fps = new FilePathService(); + String realPath = fps.getRealPath(url); + String fileserver = System.getProperty("fileserver"); + String abUrl = fileserver + realPath; + String abEncreptUrl = AttachmentServiceHelper.getEncreptURL(abUrl); + abEncreptUrl = abEncreptUrl.replaceAll("\\s", "%20").replaceAll("'", "%27"); + //处理存储路径 + String[] pathSplit = realPath.split("/"); + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < pathSplit.length - 1; i++) { + sb.append("/").append(pathSplit[i]); + } + String oldFileName = pathSplit[pathSplit.length - 1]; + String newFileName = ""; + int index = oldFileName.lastIndexOf("."); + + + URL Url = new URL(abEncreptUrl); + HttpURLConnection conn = (HttpURLConnection) Url.openConnection(); + InputStream inputStream = conn.getInputStream(); + if (inputStream.available() > 0) { + PDDocument document = PDDocument.load(inputStream); + PDFRenderer pdfRenderer = new PDFRenderer(document); + for (int page = 0; page < document.getNumberOfPages(); ++page) { + if (index != -1) { + String oldFileNameSub = oldFileName.substring(0, index); + newFileName = oldFileNameSub + "-" + page + ".jpg"; + } + BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 1000, ImageType.RGB); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + // 输出格式可以是 "jpg", "png" 等 + if ("att".equals(type)) { + // 计算放大后的尺寸 + int newWidth = bim.getWidth(); + int newHeight = bim.getHeight(); + // 高度大于宽度的图像进行90度旋转 + if (newHeight > newWidth) { + BufferedImage rotatedImage = new BufferedImage(newHeight, newWidth, bim.getType()); + AffineTransform tx = new AffineTransform(); + tx.translate(newHeight / 2.0, newWidth / 2.0); + tx.rotate(Math.toRadians(90)); + tx.translate(-newWidth / 2.0, -newHeight / 2.0); + + AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); + op.filter(bim, rotatedImage); + ImageIO.write(rotatedImage, "JPG", outputStream); + } + } else { + ImageIO.write(bim, "jpg", outputStream); + } + inputStream.close(); + StringBuilder newStBuild = new StringBuilder(); + newStBuild.append(sb); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray()); + FileItem fileItem = new FileItem(newFileName, newStBuild.append("/").append(newFileName).toString(), byteArrayInputStream); + String upload = fs.upload(fileItem); + deleteUrl.add(upload); + String uploadUrl = UrlService.getAttachmentDownloadUrl(upload); + String uploadEncreptURL = AttachmentServiceHelper.getEncreptURL(uploadUrl); + byteArrayInputStream.close(); + resUrls.add(uploadEncreptURL); + } + document.close(); + } + } catch (Exception e) { + log.error("message" + e.getMessage()); + } + return resUrls; + } + + private ArrayList OFDtoPic(String url) throws Exception { + ArrayList resUrls = new ArrayList<>(); + FileService fs = FileServiceFactory.getAttachmentFileService(); + FilePathService fps = new FilePathService(); + String realPath = fps.getRealPath(url); + String fileserver = System.getProperty("fileserver"); + String abUrl = fileserver + realPath; + String abEncreptUrl = AttachmentServiceHelper.getEncreptURL(abUrl); + abEncreptUrl = abEncreptUrl.replaceAll("\\s", "%20").replaceAll("'", "%27"); + //处理存储路径 + String[] pathSplit = realPath.split("/"); + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < pathSplit.length - 1; i++) { + sb.append("/").append(pathSplit[i]); + } + String oldFileName = pathSplit[pathSplit.length - 1]; + String newFileName = ""; + int index = oldFileName.lastIndexOf("."); + + URL Url = new URL(abEncreptUrl); + HttpURLConnection conn = (HttpURLConnection) Url.openConnection(); + InputStream inputStream = conn.getInputStream(); + if (inputStream.available() > 0) { + try (OFDReader reader = new OFDReader(inputStream);) { + inputStream.close(); + ImageMaker imageMaker = new ImageMaker(reader, 15); + for (int i = 0; i < imageMaker.pageSize(); i++) { + if (index != -1) { + String oldFileNameSub = oldFileName.substring(0, index); + newFileName = oldFileNameSub + "-" + i + ".jpg"; + } + // 4. 指定页码转换图片 + BufferedImage image = imageMaker.makePage(i); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + // 5. 存储为指定格式图片 + ImageIO.write(image, "JPG", outputStream); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray()); + outputStream.close(); + StringBuilder newStBuild = new StringBuilder(); + newStBuild.append(sb); + FileItem fileItem = new FileItem(newFileName, newStBuild.append("/").append(newFileName).toString(), byteArrayInputStream); + String upload = fs.upload(fileItem); + deleteUrl.add(upload); + String uploadUrl = UrlService.getAttachmentDownloadUrl(upload); + String uploadEncreptURL = AttachmentServiceHelper.getEncreptURL(uploadUrl); + byteArrayInputStream.close(); + resUrls.add(uploadEncreptURL); + } + } catch (Exception e) { + log.error("message" + e.getMessage()); + } + } + return resUrls; + } + + private ArrayList handlePicAttUrl(String url) { + ArrayList urls = new ArrayList<>(); + FilePathService fps = new FilePathService(); + String realPath = fps.getRealPath(url); + String fileserver = System.getProperty("imageServer.external.url"); + String abUrl = fileserver + realPath; + String abEncreptUrl = AttachmentServiceHelper.getEncreptURL(abUrl); + abEncreptUrl = abEncreptUrl.replaceAll("\\s", "%20").replaceAll("'", "%27"); + urls.add(abEncreptUrl); + return urls; + } + + @Override + public void endExport(EndExportEvent evt) { + super.endExport(evt); + FileService fs = FileServiceFactory.getAttachmentFileService(); + if (!deleteUrl.isEmpty()) { + for (String url : deleteUrl) { + fs.delete(url); + } + deleteUrl = new HashSet<>(); + } + } +} \ No newline at end of file