feat(printer): 添加打印照片水印处理功能

- 引入图片水印处理相关依赖和工具类
- 实现根据景区配置动态添加水印逻辑
- 支持从配置中读取存储类型和水印类型
- 下载原始图片并应用水印处理
- 将处理后的水印图片上传至指定存储服务
- 打印任务使用水印图片URL替代原始URL
- 增加异常失败时回处理确保水印退到原始图片- 清理处理过程中产生的临时文件
This commit is contained in:
2025-10-15 17:37:26 +08:00
parent a7ede3303d
commit 645afbaf0c

View File

@@ -1,9 +1,17 @@
package com.ycwl.basic.service.printer.impl;
import cn.hutool.http.HttpUtil;
import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.constant.NumberConstant;
import com.ycwl.basic.constant.StorageConstant;
import com.ycwl.basic.enums.OrderStateEnum;
import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.image.watermark.ImageWatermarkFactory;
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
import com.ycwl.basic.image.watermark.enums.ImageWatermarkOperatorEnum;
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
import com.ycwl.basic.image.watermark.operator.IOperator;
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.mapper.MemberMapper;
import com.ycwl.basic.mapper.OrderMapper;
import com.ycwl.basic.mapper.PrintTaskMapper;
@@ -31,9 +39,14 @@ import com.ycwl.basic.model.printer.req.WorkerAuthReqVo;
import com.ycwl.basic.model.printer.resp.PrintTaskResp;
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
import com.ycwl.basic.repository.PriceRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.WxPayService;
import com.ycwl.basic.service.printer.PrinterService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.JacksonUtil;
import com.ycwl.basic.utils.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -43,6 +56,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
@@ -75,6 +89,8 @@ public class PrinterServiceImpl implements PrinterService {
private PrintTaskMapper printTaskMapper;
@Autowired
private IPriceCalculationService priceCalculationService;
@Autowired
private ScenicRepository scenicRepository;
@Override
public List<PrinterResp> listByScenicId(Long scenicId) {
@@ -421,10 +437,74 @@ public class PrinterServiceImpl implements PrinterService {
List<MemberPrintResp> userPhotoListByOrderId = getUserPhotoListByOrderId(orderId);
userPhotoListByOrderId.forEach(item -> {
PrinterEntity printer = printerMapper.getById(item.getPrinterId());
// 水印处理逻辑
String printUrl = item.getCropUrl();
try {
ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(item.getScenicId());
String printWatermarkType = scenicConfig.getString("print_watermark_type");
if (printWatermarkType != null && StringUtils.isNotBlank(printWatermarkType)) {
ImageWatermarkOperatorEnum watermarkType = ImageWatermarkOperatorEnum.getByCode(printWatermarkType);
if (watermarkType != null) {
// 准备存储适配器
IStorageAdapter adapter;
String storeType = scenicConfig.getString("store_type");
if (storeType != null) {
adapter = StorageFactory.get(storeType);
String storeConfigJson = scenicConfig.getString("store_config_json");
if (StringUtils.isNotBlank(storeConfigJson)) {
adapter.loadConfig(JacksonUtil.parseObject(storeConfigJson, Map.class));
}
} else {
adapter = StorageFactory.use("assets-ext");
}
// 准备水印处理器
IOperator operator = ImageWatermarkFactory.get(watermarkType);
// 下载原图
File originalFile = new File("print_" + item.getId() + ".jpg");
File watermarkedFile = new File("print_" + item.getId() + "_" + watermarkType.getType() + "." + watermarkType.getPreferFileType());
try {
HttpUtil.downloadFile(item.getCropUrl().replace("oss.zhentuai.com", "frametour-assets.oss-cn-shanghai-internal.aliyuncs.com"), originalFile);
// 处理水印
WatermarkInfo watermarkInfo = new WatermarkInfo();
watermarkInfo.setOriginalFile(originalFile);
watermarkInfo.setWatermarkedFile(watermarkedFile);
operator.process(watermarkInfo);
// 上传水印图片
String watermarkedUrl = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
printUrl = watermarkedUrl;
log.info("水印处理成功,打印照片ID: {}, 水印URL: {}", item.getId(), watermarkedUrl);
} catch (Exception e) {
log.error("水印处理失败,使用原始照片进行打印。照片ID: {}", item.getId(), e);
} finally {
// 清理临时文件
if (originalFile.exists()) {
originalFile.delete();
}
if (watermarkedFile.exists()) {
watermarkedFile.delete();
}
}
}
}
} catch (Exception e) {
log.error("获取景区配置失败,使用原始照片进行打印。景区ID: {}, 照片ID: {}", item.getScenicId(), item.getId(), e);
}
PrintTaskEntity task = new PrintTaskEntity();
task.setPrinterId(printer.getId());
task.setStatus(0);
task.setUrl(item.getCropUrl());
task.setUrl(printUrl);
task.setHeight(printer.getPreferH());
task.setWidth(printer.getPreferW());
task.setCreateTime(new Date());