|
@@ -1,11 +1,17 @@
|
|
|
package com.sd.business.service.work.impl;
|
|
|
|
|
|
+import cn.hutool.core.convert.Convert;
|
|
|
+import cn.hutool.core.img.ImgUtil;
|
|
|
+import cn.hutool.core.io.IoUtil;
|
|
|
import cn.hutool.core.util.ArrayUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.google.common.collect.HashBasedTable;
|
|
|
+import com.itextpdf.text.Document;
|
|
|
+import com.itextpdf.text.Rectangle;
|
|
|
+import com.itextpdf.text.pdf.PdfWriter;
|
|
|
import com.ruoyi.common.constant.StatusConstant;
|
|
|
import com.ruoyi.common.core.domain.BaseIdPo;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
@@ -52,11 +58,23 @@ import com.sd.business.util.packing.model.Item;
|
|
|
import com.sd.framework.util.Assert;
|
|
|
import com.sd.framework.util.TransactionUtil;
|
|
|
import com.sd.framework.util.sql.Sql;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+import java.awt.Color;
|
|
|
+import java.awt.Graphics;
|
|
|
+import java.awt.Graphics2D;
|
|
|
+import java.awt.Image;
|
|
|
+import java.awt.geom.AffineTransform;
|
|
|
+import java.awt.image.AffineTransformOp;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.net.URL;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
@@ -64,6 +82,12 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
import java.util.Set;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.concurrent.CountDownLatch;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
+import java.util.concurrent.LinkedBlockingQueue;
|
|
|
+import java.util.concurrent.ThreadPoolExecutor;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
@@ -78,6 +102,7 @@ import java.util.stream.Stream;
|
|
|
* @author
|
|
|
* @since 2024-01-02
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements WorkOrderService {
|
|
|
|
|
@@ -104,6 +129,17 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
|
|
|
@Autowired
|
|
|
private OrderSkuBomService orderSkuBomService;
|
|
|
|
|
|
+ private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
|
|
|
+ 8,
|
|
|
+ 16,
|
|
|
+ 60,
|
|
|
+ TimeUnit.SECONDS,
|
|
|
+ new LinkedBlockingQueue<>(16),
|
|
|
+ Executors.defaultThreadFactory(),
|
|
|
+ new ThreadPoolExecutor.CallerRunsPolicy()
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
@Override
|
|
|
public Page<WorkOrderVo> getPage(WorkOrderSelectDto dto) {
|
|
|
|
|
@@ -351,6 +387,215 @@ public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 旋转图片
|
|
|
+ */
|
|
|
+ public static BufferedImage rotateImage(BufferedImage bi) {
|
|
|
+ // 获取原图像的宽和高
|
|
|
+ int width = bi.getWidth();
|
|
|
+ int height = bi.getHeight();
|
|
|
+
|
|
|
+ // 创建一个新图像,宽高与原图相反
|
|
|
+ BufferedImage rotatedImage = new BufferedImage(height, width, bi.getType());
|
|
|
+
|
|
|
+ // 创建 AffineTransform 对象
|
|
|
+ AffineTransform at = new AffineTransform();
|
|
|
+
|
|
|
+ // 设置旋转中心为原图像的中心点
|
|
|
+ int centerX = width / 2;
|
|
|
+ int centerY = height / 2;
|
|
|
+ at.rotate(Math.toRadians(90), centerX, centerY); // 角度转换为弧度
|
|
|
+ at.translate(centerX - centerY, centerX - centerY); // 注意这里的平移是逆向的
|
|
|
+
|
|
|
+ // 使用 AffineTransformOp 进行旋转
|
|
|
+ AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
|
|
|
+ return op.filter(bi, rotatedImage);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 缩放图片
|
|
|
+ */
|
|
|
+ public static void convert(BufferedImage imageNew, String target) {
|
|
|
+ // 宽度保持不变
|
|
|
+ int subImageWidth = imageNew.getWidth();
|
|
|
+ int subImageHeight = 14400;
|
|
|
+
|
|
|
+ Document document = new Document();
|
|
|
+ //设置文档页边距
|
|
|
+ document.setMargins(0, 0, 0, 0);
|
|
|
+ FileOutputStream fos = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ fos = new FileOutputStream(target);
|
|
|
+ PdfWriter.getInstance(document, fos);
|
|
|
+
|
|
|
+ //打开文档
|
|
|
+ document.open();
|
|
|
+
|
|
|
+ int y = 0;
|
|
|
+ while (y < imageNew.getHeight()) {
|
|
|
+
|
|
|
+ int heightToCut = Math.min(subImageHeight, imageNew.getHeight() - y);
|
|
|
+
|
|
|
+ // 截取图片的一部分
|
|
|
+ BufferedImage subImage = imageNew.getSubimage(0, y, subImageWidth, heightToCut);
|
|
|
+
|
|
|
+ // 将截取的图片转换为iTextPDF的Image对象
|
|
|
+ com.itextpdf.text.Image img = com.itextpdf.text.Image.getInstance(subImage, null);
|
|
|
+
|
|
|
+ //图片居中
|
|
|
+ img.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
|
|
|
+
|
|
|
+ //设置页面宽高与图片一致
|
|
|
+ Rectangle rectangle = new Rectangle(subImageWidth, heightToCut);
|
|
|
+ document.setPageSize(rectangle);
|
|
|
+
|
|
|
+ // 添加到PDF文档
|
|
|
+ document.newPage();
|
|
|
+ document.add(img);
|
|
|
+
|
|
|
+ y += subImageHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ //关闭文档
|
|
|
+ document.close();
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("生成pdf失败", e);
|
|
|
+ throw new ServiceException("生成pdf失败");
|
|
|
+ } finally {
|
|
|
+ IoUtil.flush(fos);
|
|
|
+ IoUtil.close(fos);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 毫米转像素
|
|
|
+ *
|
|
|
+ * @param mm 毫米
|
|
|
+ * @return 像素值
|
|
|
+ */
|
|
|
+ static int mmToPx(double mm) {
|
|
|
+ // 因为1英寸等于25.4毫米
|
|
|
+ return Convert.toInt(Math.round(mm * MaterialsConstant.DPI / 25.4));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 图片缩放
|
|
|
+ *
|
|
|
+ * @param image 图片
|
|
|
+ * @param width 缩放后的宽
|
|
|
+ * @param height 缩放后的高
|
|
|
+ * @return 缩放后的图片
|
|
|
+ */
|
|
|
+ public static BufferedImage scale(BufferedImage image, int width, int height) {
|
|
|
+
|
|
|
+ Image newImage = ImgUtil.scale(image, width, height);
|
|
|
+
|
|
|
+ // 创建一个具有相同尺寸和类型(ARGB)的新BufferedImage
|
|
|
+ BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
|
|
+
|
|
|
+ // 获取Graphics2D对象以绘制图像
|
|
|
+ Graphics2D g2d = bufferedImage.createGraphics();
|
|
|
+
|
|
|
+ // 将源图像绘制到BufferedImage上
|
|
|
+ g2d.drawImage(newImage, 0, 0, null);
|
|
|
+
|
|
|
+ // 关闭Graphics2D以释放资源
|
|
|
+ g2d.dispose();
|
|
|
+
|
|
|
+ return bufferedImage;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String pdfExport(Long id) {
|
|
|
+ WorkOrder workOrder = getById(id);
|
|
|
+ List<WorkOrderDetail> list = workOrderDetailService.list(q -> q.eq(WorkOrderDetail::getWorkOrderId, id));
|
|
|
+ Set<Long> orderSkuIdList = list.stream().map(WorkOrderDetail::getOrderSkuId).collect(Collectors.toSet());
|
|
|
+ Map<Long, String> map = orderSkuService.mapKV(BaseIdPo::getId, OrderSku::getBlueprint, q -> q.in(BaseIdPo::getId, orderSkuIdList));
|
|
|
+
|
|
|
+ int canvasWidth = mmToPx(MaterialsConstant.MASTER_WIDTH);
|
|
|
+ int canvasHeight = mmToPx(workOrder.getMaxLength().doubleValue());
|
|
|
+
|
|
|
+ // 创建一个画布,并设置白色背景
|
|
|
+ BufferedImage imageNew = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_RGB);
|
|
|
+ Graphics graphics = imageNew.getGraphics();
|
|
|
+ graphics.setColor(Color.WHITE);
|
|
|
+ graphics.fillRect(0, 0, canvasWidth, canvasHeight);
|
|
|
+
|
|
|
+ Map<String, BufferedImage> bufferedImageMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ CountDownLatch downLatch = new CountDownLatch(list.size());
|
|
|
+
|
|
|
+ for (WorkOrderDetail workOrderDetail : list) {
|
|
|
+
|
|
|
+ executor.execute(() -> {
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ // 外边框填充黑色
|
|
|
+ int marginWidth = mmToPx(workOrderDetail.getWidth().doubleValue() + MaterialsConstant.RESERVE);
|
|
|
+ int marginHeight = mmToPx(workOrderDetail.getLength().doubleValue() + MaterialsConstant.RESERVE);
|
|
|
+ int x = mmToPx(workOrderDetail.getX().doubleValue());
|
|
|
+ int y = mmToPx(workOrderDetail.getY().doubleValue());
|
|
|
+
|
|
|
+ // 设置画笔颜色
|
|
|
+ graphics.setColor(Color.BLACK);
|
|
|
+ // 填充图片背景色为黑色
|
|
|
+ graphics.fillRect(x, y, marginWidth, marginHeight);
|
|
|
+
|
|
|
+ // 中间填充图片
|
|
|
+ String filePath = map.get(workOrderDetail.getOrderSkuId());
|
|
|
+
|
|
|
+ BufferedImage bi = bufferedImageMap.computeIfAbsent(filePath, item -> {
|
|
|
+ try {
|
|
|
+ // 读取图片
|
|
|
+ URL url = new URL(filePath);
|
|
|
+ return ImageIO.read(url);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (Objects.equals(workOrderDetail.getRotate(), StatusConstant.YES)) {
|
|
|
+ bi = rotateImage(bi);
|
|
|
+ }
|
|
|
+
|
|
|
+ int width = mmToPx(workOrderDetail.getWidth().doubleValue() + MaterialsConstant.SHRINK);
|
|
|
+ int height = mmToPx(workOrderDetail.getLength().doubleValue() + MaterialsConstant.SHRINK);
|
|
|
+ bi = scale(bi, width, height);
|
|
|
+
|
|
|
+ int[] ImageArrays = bi.getRGB(0, 0, width, height, new int[width * height], 0, width);
|
|
|
+
|
|
|
+ imageNew.setRGB(
|
|
|
+ x + (marginWidth - width) / 2,
|
|
|
+ y + (marginHeight - height) / 2,
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ ImageArrays, 0, width);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } finally {
|
|
|
+ downLatch.countDown();
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ downLatch.await();
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ log.error("downLatch异常", e);
|
|
|
+ throw new ServiceException("生成pdf失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ convert(imageNew, "E:\\test2.pdf");
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 排版
|
|
|
*/
|
|
|
private void scheduling(Long bomSpecId, Long printingPaperBomSpecId, List<OrderSku> list, Map<Long, SkuSpec> skuSpecMap) {
|