From 9278d4479f664555c9ace44ae17b06df4496a663 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sat, 22 Nov 2025 00:07:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(printer):=20=E4=BC=98=E5=8C=96=E6=8B=BC?= =?UTF-8?q?=E5=9B=BE=E6=89=93=E5=8D=B0=E5=81=8F=E7=A7=BB=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加白边框并向上偏移内容以避免打印机偏移 - 替换原有的单纯向上偏移方法 - 弃用 shiftImageUp 方法,新增 addBorderAndShiftUp 方法 - 更新临时文件命名及清理逻辑 - 修改日志记录内容以反映新的处理方式 --- .../service/pc/impl/FaceServiceImpl.java | 14 +- .../printer/impl/PrinterServiceImpl.java | 22 ++-- .../java/com/ycwl/basic/utils/ImageUtils.java | 124 ++++++++++++++++++ 3 files changed, 143 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java index adc9e6b1..de16622f 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java @@ -471,16 +471,18 @@ public class FaceServiceImpl implements FaceService { sfpContent.setTemplateCoverUrl(template.getCoverImage()); sfpContent.setGoodsType(3); sfpContent.setSort(0); - IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getScenicId(), face.getMemberId(), faceId, 5, records.getFirst().getTemplateId()); - if (isBuyRespVO.isBuy()) { - sfpContent.setIsBuy(1); - } else { - sfpContent.setIsBuy(0); + if (optionalRecord.isPresent()) { + IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getScenicId(), face.getMemberId(), faceId, 5, optionalRecord.get().getTemplateId()); + if (isBuyRespVO.isBuy()) { + sfpContent.setIsBuy(1); + } else { + sfpContent.setIsBuy(0); + } } PriceCalculationRequest calculationRequest = new PriceCalculationRequest(); ProductItem productItem = new ProductItem(); productItem.setProductType(ProductType.PHOTO_LOG); - productItem.setProductId(records.getFirst().getTemplateId().toString()); + productItem.setProductId(template.getId().toString()); productItem.setPurchaseCount(1); productItem.setScenicId(face.getScenicId().toString()); calculationRequest.setProducts(Collections.singletonList(productItem)); diff --git a/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java b/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java index 20294d37..b6621250 100644 --- a/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java @@ -864,19 +864,19 @@ public class PrinterServiceImpl implements PrinterService { log.error("获取景区配置失败,使用原始照片进行打印。景区ID: {}, 照片ID: {}", item.getScenicId(), item.getId(), e); } } else if (item.getSourceId() != null && item.getSourceId() == 0) { - // 拼图:向上移动40像素以避免打印机偏移 + // 拼图:添加白边框并向上偏移以避免打印机偏移 try { // 生成唯一的处理标识符,避免多线程环境下的文件冲突 String processId = item.getId() + "_" + UUID.randomUUID().toString(); File originalFile = new File("puzzle_" + processId + ".png"); - File shiftedFile = new File("puzzle_" + processId + "_shifted.png"); + File processedFile = new File("puzzle_" + processId + "_processed.png"); try { // 下载原图 HttpUtil.downloadFile(item.getCropUrl(), originalFile); - // 向上偏移40像素 - ImageUtils.shiftImageUp(originalFile, shiftedFile, 40); + // 添加白边框(左右20px,上下30px)并向上偏移15px + ImageUtils.addBorderAndShiftUp(originalFile, processedFile, 20, 30, 15); // 上传处理后的图片 IStorageAdapter adapter; @@ -892,21 +892,21 @@ public class PrinterServiceImpl implements PrinterService { adapter = StorageFactory.use("assets-ext"); } - String shiftedUrl = adapter.uploadFile(null, shiftedFile, StorageConstant.PHOTO_WATERMARKED_PATH, shiftedFile.getName()); - adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, shiftedFile.getName()); + String processedUrl = adapter.uploadFile(null, processedFile, StorageConstant.PHOTO_WATERMARKED_PATH, processedFile.getName()); + adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, processedFile.getName()); - printUrl = shiftedUrl; - log.info("拼图照片向上偏移40像素成功,照片ID: {}, 新URL: {}", item.getId(), shiftedUrl); + printUrl = processedUrl; + log.info("拼图照片添加白边框并向上偏移成功,照片ID: {}, 新URL: {}", item.getId(), processedUrl); } catch (Exception e) { - log.error("拼图照片向上偏移处理失败,使用原始照片进行打印。照片ID: {}", item.getId(), e); + log.error("拼图照片处理失败,使用原始照片进行打印。照片ID: {}", item.getId(), e); } finally { // 清理临时文件 if (originalFile != null && originalFile.exists()) { originalFile.delete(); } - if (shiftedFile != null && shiftedFile.exists()) { - shiftedFile.delete(); + if (processedFile != null && processedFile.exists()) { + processedFile.delete(); } } } catch (Exception e) { diff --git a/src/main/java/com/ycwl/basic/utils/ImageUtils.java b/src/main/java/com/ycwl/basic/utils/ImageUtils.java index 7a07d4e0..96381cc3 100644 --- a/src/main/java/com/ycwl/basic/utils/ImageUtils.java +++ b/src/main/java/com/ycwl/basic/utils/ImageUtils.java @@ -448,6 +448,130 @@ public class ImageUtils { return cropped; } + /** + * 为图片添加白边框并向上偏移内容 + * 用于拼图打印场景,避免打印机偏移问题 + * + * @param sourceFile 源图片文件 + * @param targetFile 目标图片文件 + * @param horizontalBorder 左右白边框宽度(像素) + * @param verticalBorder 上下白边框高度(像素) + * @param upwardShift 内容向上偏移的像素数 + * @throws IOException 读取或写入文件失败 + */ + public static void addBorderAndShiftUp(File sourceFile, File targetFile, + int horizontalBorder, int verticalBorder, int upwardShift) throws IOException { + BufferedImage sourceImage = null; + BufferedImage resultImage = null; + try { + sourceImage = ImageIO.read(sourceFile); + if (sourceImage == null) { + throw new IOException("无法读取图片文件: " + sourceFile.getPath()); + } + + int srcWidth = sourceImage.getWidth(); + int srcHeight = sourceImage.getHeight(); + + // 计算新图片尺寸(原图 + 左右边框 + 上下边框) + int newWidth = srcWidth + horizontalBorder * 2; + int newHeight = srcHeight + verticalBorder * 2; + + // 创建新图片 + resultImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = resultImage.createGraphics(); + + try { + // 填充白色背景 + g2d.setColor(java.awt.Color.WHITE); + g2d.fillRect(0, 0, newWidth, newHeight); + + // 绘制原图到新图中 + // 原图应该绘制在: x=horizontalBorder, y=verticalBorder-upwardShift 的位置 + // 这样图片内容会向上偏移upwardShift像素 + int drawX = horizontalBorder; + int drawY = verticalBorder - upwardShift; + + g2d.drawImage(sourceImage, drawX, drawY, null); + + log.info("图片添加白边框并向上偏移: 原始尺寸={}x{}, 边框=(左右{}px,上下{}px), 向上偏移={}px, 结果尺寸={}x{}", + srcWidth, srcHeight, horizontalBorder, verticalBorder, upwardShift, newWidth, newHeight); + } finally { + g2d.dispose(); + } + + // 保存处理后的图片 + ImageIO.write(resultImage, "png", targetFile); + } finally { + if (sourceImage != null) { + sourceImage.flush(); + } + if (resultImage != null) { + resultImage.flush(); + } + } + } + + /** + * 向上偏移图片以避免打印机偏移问题 + * 舍弃顶部指定像素,整体向上移动,并在底部补充白底 + * + * @param sourceFile 源图片文件 + * @param targetFile 目标图片文件 + * @param offsetPixels 向上偏移的像素数(舍弃顶部的像素数,底部补充相同像素的白底) + * @throws IOException 读取或写入文件失败 + * @deprecated 使用 addBorderAndShiftUp 代替 + */ + @Deprecated + public static void shiftImageUp(File sourceFile, File targetFile, int offsetPixels) throws IOException { + BufferedImage sourceImage = null; + BufferedImage shiftedImage = null; + try { + sourceImage = ImageIO.read(sourceFile); + if (sourceImage == null) { + throw new IOException("无法读取图片文件: " + sourceFile.getPath()); + } + + int width = sourceImage.getWidth(); + int height = sourceImage.getHeight(); + + if (offsetPixels <= 0 || offsetPixels >= height) { + throw new IllegalArgumentException("偏移像素必须大于0且小于图片高度,当前值: " + offsetPixels + ", 图片高度: " + height); + } + + // 创建新图片,保持原始宽度和高度 + shiftedImage = new BufferedImage(width, height, sourceImage.getType()); + Graphics2D g2d = shiftedImage.createGraphics(); + + try { + // 先填充白色背景 + g2d.setColor(java.awt.Color.WHITE); + g2d.fillRect(0, 0, width, height); + + // 从源图的offsetPixels位置开始截取到底部,绘制到目标图的顶部 + // 源图: 从(0, offsetPixels)到(width, height)的区域 + // 目标图: 绘制到(0, 0)到(width, height-offsetPixels)的区域 + g2d.drawImage(sourceImage, 0, 0, width, height - offsetPixels, + 0, offsetPixels, width, height, null); + + // 底部的offsetPixels像素保持白色(已通过fillRect填充) + } finally { + g2d.dispose(); + } + + // 保存处理后的图片 + ImageIO.write(shiftedImage, "png", targetFile); + log.info("图片向上偏移成功,原始尺寸: {}x{}, 偏移: {}px, 结果尺寸: {}x{} (底部补充{}px白底)", + width, height, offsetPixels, width, height, offsetPixels); + } finally { + if (sourceImage != null) { + sourceImage.flush(); + } + if (shiftedImage != null) { + shiftedImage.flush(); + } + } + } + /** * 裁切策略内部类 */