You've already forked FrameTour-BE
feat(printer): 实现带图像增强选项的重新打印功能
- 在 ReprintRequest 中新增 needEnhance 字段以支持图像增强 - 将 reprint 接口的实现从 controller 下移到 printerService - 实现 handleReprint 方法,支持根据 needEnhance 条件性添加图像增强阶段 - 重构 reprint 流程,引入 Pipeline 处理图像下载、旋转、增强、水印等步骤 - 增强 reprint 异常处理,失败时回退到原始裁剪图 - 移除 ImageEnhanceStage 中对 TODO 占位符的判断逻辑 - 提供 updateTaskStatusAndPrinter 兜底方法用于无 MemberPrint 场景
This commit is contained in:
@@ -71,7 +71,7 @@ public class PrinterController {
|
||||
// 重新打印(将状态设置为0-未开始,并更新打印机名称)
|
||||
@PostMapping("/task/reprint/{id}")
|
||||
public ApiResponse<Integer> reprint(@PathVariable("id") Integer id, @RequestBody ReprintRequest request) {
|
||||
int result = printTaskMapper.updateStatusAndPrinter(id, 0, request.getPrinterName());
|
||||
int result = printerService.handleReprint(id, request);
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ImageEnhanceStage extends AbstractPipelineStage<PhotoProcessContext
|
||||
|
||||
File currentFile = context.getCurrentFile();
|
||||
if (currentFile == null || !currentFile.exists()) {
|
||||
return StageResult.failed("当前文件不存在");
|
||||
return StageResult.skipped("当前文件不存在");
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -137,10 +137,9 @@ public class ImageEnhanceStage extends AbstractPipelineStage<PhotoProcessContext
|
||||
String apiKey = enhancerConfig.getApiKey();
|
||||
String secretKey = enhancerConfig.getSecretKey();
|
||||
|
||||
// 检查是否还是TODO占位符
|
||||
if (appId == null || appId.startsWith("TODO_") ||
|
||||
apiKey == null || apiKey.startsWith("TODO_") ||
|
||||
secretKey == null || secretKey.startsWith("TODO_")) {
|
||||
if (appId == null ||
|
||||
apiKey == null ||
|
||||
secretKey == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,4 +11,8 @@ public class ReprintRequest {
|
||||
* 打印机名称
|
||||
*/
|
||||
private String printerName;
|
||||
/**
|
||||
* 是否增强打印
|
||||
*/
|
||||
private Boolean needEnhance;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
|
||||
import com.ycwl.basic.model.mobile.order.PriceObj;
|
||||
import com.ycwl.basic.model.pc.printer.entity.PrintTaskEntity;
|
||||
import com.ycwl.basic.model.pc.printer.entity.PrinterEntity;
|
||||
import com.ycwl.basic.model.pc.printer.req.ReprintRequest;
|
||||
import com.ycwl.basic.model.pc.printer.resp.MemberPrintResp;
|
||||
import com.ycwl.basic.model.pc.printer.resp.PrinterResp;
|
||||
import com.ycwl.basic.model.printer.req.FromSourceReq;
|
||||
@@ -101,4 +102,6 @@ public interface PrinterService {
|
||||
* @return 添加成功的MemberPrint记录ID
|
||||
*/
|
||||
Integer addUserPhotoFromPuzzle(Long memberId, Long scenicId, Long faceId, String resultImageUrl, Long puzzleRecordId);
|
||||
|
||||
int handleReprint(Integer id, ReprintRequest request);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.ycwl.basic.biz.OrderBiz;
|
||||
import com.ycwl.basic.constant.NumberConstant;
|
||||
import com.ycwl.basic.enums.OrderStateEnum;
|
||||
import com.ycwl.basic.exception.BaseException;
|
||||
import com.ycwl.basic.image.enhancer.entity.BceEnhancerConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.Pipeline;
|
||||
import com.ycwl.basic.image.pipeline.core.PipelineBuilder;
|
||||
@@ -13,6 +14,7 @@ import com.ycwl.basic.image.pipeline.enums.PipelineScene;
|
||||
import com.ycwl.basic.image.pipeline.stages.CleanupStage;
|
||||
import com.ycwl.basic.image.pipeline.stages.ConditionalRotateStage;
|
||||
import com.ycwl.basic.image.pipeline.stages.DownloadStage;
|
||||
import com.ycwl.basic.image.pipeline.stages.ImageEnhanceStage;
|
||||
import com.ycwl.basic.image.pipeline.stages.ImageOrientationStage;
|
||||
import com.ycwl.basic.image.pipeline.stages.PuzzleBorderStage;
|
||||
import com.ycwl.basic.image.pipeline.stages.RestoreOrientationStage;
|
||||
@@ -39,6 +41,7 @@ import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
|
||||
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
|
||||
import com.ycwl.basic.model.pc.order.entity.OrderEntity;
|
||||
import com.ycwl.basic.model.pc.order.entity.OrderItemEntity;
|
||||
import com.ycwl.basic.model.pc.printer.req.ReprintRequest;
|
||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||
import com.ycwl.basic.pricing.dto.PriceCalculationRequest;
|
||||
import com.ycwl.basic.pricing.dto.PriceCalculationResult;
|
||||
@@ -83,6 +86,7 @@ import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -1317,4 +1321,156 @@ public class PrinterServiceImpl implements PrinterService {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int handleReprint(Integer id, ReprintRequest request) {
|
||||
// 1. 参数校验和任务获取
|
||||
if (id == null) {
|
||||
log.error("handleReprint: 任务ID为空");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintTaskEntity task = printTaskMapper.selectById(id);
|
||||
if (task == null) {
|
||||
log.error("handleReprint: 打印任务不存在, taskId={}", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. 获取 MemberPrint 记录
|
||||
Integer mpId = task.getMpId();
|
||||
if (mpId == null) {
|
||||
log.warn("handleReprint: 任务的mpId为空, taskId={}, 直接更新状态和打印机名称", id);
|
||||
return updateTaskStatusAndPrinter(task, request);
|
||||
}
|
||||
|
||||
List<Long> ids = Arrays.asList(mpId.longValue());
|
||||
List<MemberPrintResp> memberPrints = printerMapper.getUserPhotoByIds(ids);
|
||||
if (memberPrints == null || memberPrints.isEmpty()) {
|
||||
log.warn("handleReprint: MemberPrint记录不存在, mpId={}, taskId={}, 直接更新状态和打印机名称", mpId, id);
|
||||
return updateTaskStatusAndPrinter(task, request);
|
||||
}
|
||||
|
||||
MemberPrintResp memberPrint = memberPrints.get(0);
|
||||
|
||||
// 3. 重新处理照片(带增强选项)
|
||||
Boolean needEnhance = request.getNeedEnhance();
|
||||
if (needEnhance == null) {
|
||||
needEnhance = false; // 默认不增强
|
||||
}
|
||||
|
||||
// 3.1 创建图片处理上下文
|
||||
PrinterOrderItem orderItem = PrinterOrderItem.fromMemberPrintResp(memberPrint);
|
||||
PhotoProcessContext context = PhotoProcessContext.fromPrinterOrderItem(orderItem, memberPrint.getScenicId());
|
||||
|
||||
// 3.2 设置景区配置和场景
|
||||
ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(memberPrint.getScenicId());
|
||||
context.setScenicConfigManager(scenicConfig);
|
||||
context.setScene(PipelineScene.IMAGE_PRINT);
|
||||
|
||||
// 3.3 判断图片来源
|
||||
if (memberPrint.getSourceId() != null && memberPrint.getSourceId() > 0) {
|
||||
context.setSource(ImageSource.IPC);
|
||||
} else if (memberPrint.getSourceId() == null) {
|
||||
context.setSource(ImageSource.PHONE);
|
||||
} else {
|
||||
context.setSource(ImageSource.UNKNOWN);
|
||||
}
|
||||
|
||||
// 3.4 构建管线(关键:条件性添加 ImageEnhanceStage)
|
||||
Pipeline<PhotoProcessContext> pipeline;
|
||||
String newPrintUrl = null;
|
||||
|
||||
try {
|
||||
if (context.getImageType() == ImageType.NORMAL_PHOTO) {
|
||||
// 准备水印配置(重打印不需要二维码,传 null)
|
||||
WatermarkConfig watermarkConfig = prepareWatermarkConfig(context, null);
|
||||
prepareStorageAdapter(context);
|
||||
|
||||
BceEnhancerConfig config = new BceEnhancerConfig();
|
||||
config.setQps(1);
|
||||
config.setAppId("119554288");
|
||||
config.setApiKey("OX6QoijgKio3eVtA0PiUVf7f");
|
||||
config.setSecretKey("dYatXReVriPeiktTjUblhfubpcmYfuMk");
|
||||
// 创建管线,条件性添加增强 Stage
|
||||
pipeline = new PipelineBuilder<PhotoProcessContext>("ReprintPipeline")
|
||||
.addStage(new DownloadStage())
|
||||
.addStage(new ImageOrientationStage())
|
||||
.addStage(new ConditionalRotateStage())
|
||||
.addStageIf(needEnhance, new ImageEnhanceStage(config))
|
||||
.addStage(new WatermarkStage(watermarkConfig))
|
||||
.addStage(new RestoreOrientationStage())
|
||||
.addStage(new UploadStage())
|
||||
.addStage(new CleanupStage())
|
||||
.build();
|
||||
} else {
|
||||
// 拼图
|
||||
prepareStorageAdapter(context);
|
||||
pipeline = createPuzzlePipeline();
|
||||
}
|
||||
|
||||
// 3.5 执行管线
|
||||
boolean success = pipeline.execute(context);
|
||||
if (success && context.getResultUrl() != null) {
|
||||
newPrintUrl = context.getResultUrl();
|
||||
log.info("handleReprint: 照片重新处理成功, taskId={}, mpId={}, enhance={}, newUrl={}",
|
||||
id, mpId, needEnhance, newPrintUrl);
|
||||
} else {
|
||||
log.warn("handleReprint: 照片重新处理失败, taskId={}, 使用原图", id);
|
||||
newPrintUrl = memberPrint.getCropUrl(); // 使用原裁剪图
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("handleReprint: 照片重新处理异常, taskId={}, 使用原图", id, e);
|
||||
newPrintUrl = memberPrint.getCropUrl();
|
||||
} finally {
|
||||
context.cleanup();
|
||||
}
|
||||
|
||||
// 4. 更新打印任务
|
||||
String printerName = request.getPrinterName();
|
||||
if (StringUtils.isBlank(printerName)) {
|
||||
// 如果请求中未指定,使用轮询逻辑获取
|
||||
PrinterEntity printer = printerMapper.getById(task.getPrinterId());
|
||||
if (printer != null) {
|
||||
printerName = getNextPrinter(printer);
|
||||
} else {
|
||||
printerName = task.getPrinterName(); // 保持原有打印机
|
||||
}
|
||||
}
|
||||
|
||||
task.setStatus(TASK_STATUS_PENDING); // 状态设置为待处理(0)
|
||||
task.setPrinterName(printerName);
|
||||
task.setUrl(newPrintUrl);
|
||||
task.setUpdateTime(new Date());
|
||||
|
||||
int rows = printTaskMapper.updateById(task);
|
||||
|
||||
log.info("handleReprint: 任务更新完成, taskId={}, printerName={}, status=0, rows={}",
|
||||
id, printerName, rows);
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当无法获取 MemberPrint 时,直接更新任务状态和打印机名称
|
||||
*/
|
||||
private int updateTaskStatusAndPrinter(PrintTaskEntity task, ReprintRequest request) {
|
||||
String printerName = request.getPrinterName();
|
||||
if (StringUtils.isBlank(printerName)) {
|
||||
// 如果请求中未指定,使用轮询逻辑获取
|
||||
PrinterEntity printer = printerMapper.getById(task.getPrinterId());
|
||||
if (printer != null) {
|
||||
printerName = getNextPrinter(printer);
|
||||
} else {
|
||||
printerName = task.getPrinterName(); // 保持原有打印机
|
||||
}
|
||||
}
|
||||
|
||||
// 使用现有的 updateStatusAndPrinter 方法
|
||||
int rows = printTaskMapper.updateStatusAndPrinter(task.getId(), TASK_STATUS_PENDING, printerName);
|
||||
|
||||
log.info("handleReprint: 无MemberPrint记录,直接更新任务, taskId={}, printerName={}, status=0, rows={}",
|
||||
task.getId(), printerName, rows);
|
||||
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user