From d6780ccb7ad7e0f67c2bf5548d19ea60fd023254 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Mon, 29 Dec 2025 11:34:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(face):=20=E6=B7=BB=E5=8A=A0=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E6=9C=BA=E5=A4=A7=E5=B1=8F=E4=BA=BA=E8=84=B8=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E8=AF=95=E7=82=B9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在PrinterTvController中添加tv场景参数,用于触发打印机大屏识别试点逻辑 - 在FaceMatchingScene枚举中新增PRINTER_TV_RECOGNIZE场景,支持仅执行识别补救落库建关系 - 在FaceMatchingPipelineFactory中创建打印机大屏识别试点Pipeline,包含识别补救落库建关系等阶段 - 在FaceServiceImpl中添加打印机大屏人脸识别的专门处理方法matchFaceIdForPrinterTv - 通过scene参数区分普通人脸识别和打印机大屏识别试点流程 --- .../printer/PrinterTvController.java | 2 +- .../pipeline/enums/FaceMatchingScene.java | 8 +++- .../factory/FaceMatchingPipelineFactory.java | 35 ++++++++++++++++++ .../service/pc/impl/FaceServiceImpl.java | 37 ++++++++++++++++++- 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ycwl/basic/controller/printer/PrinterTvController.java b/src/main/java/com/ycwl/basic/controller/printer/PrinterTvController.java index 575fe967..98747bea 100644 --- a/src/main/java/com/ycwl/basic/controller/printer/PrinterTvController.java +++ b/src/main/java/com/ycwl/basic/controller/printer/PrinterTvController.java @@ -198,7 +198,7 @@ public class PrinterTvController { @RequestParam("file") MultipartFile file, @PathVariable Long scenicId) { // 复用 faceUpload 方法的去重逻辑 - // memberId=0L 表示打印机大屏用户,scene="print" 会触发自动添加打印逻辑并等待完成 + // memberId=0L 表示打印机大屏用户,scene="tv" 为试点场景:仅执行识别/补救/落库/建关系 FaceRecognizeResp resp = pcFaceService.faceUpload(file, scenicId, 0L, "tv"); return ApiResponse.success(resp); } diff --git a/src/main/java/com/ycwl/basic/face/pipeline/enums/FaceMatchingScene.java b/src/main/java/com/ycwl/basic/face/pipeline/enums/FaceMatchingScene.java index 78cea793..584ecf94 100644 --- a/src/main/java/com/ycwl/basic/face/pipeline/enums/FaceMatchingScene.java +++ b/src/main/java/com/ycwl/basic/face/pipeline/enums/FaceMatchingScene.java @@ -21,5 +21,11 @@ public enum FaceMatchingScene { * 仅识别 * 只执行人脸识别,不处理后续业务逻辑(源文件关联、任务创建等) */ - RECOGNITION_ONLY + RECOGNITION_ONLY, + + /** + * 打印机大屏识别试点 + * 仅执行:识别、补救、落库、建关系 + */ + PRINTER_TV_RECOGNIZE } diff --git a/src/main/java/com/ycwl/basic/face/pipeline/factory/FaceMatchingPipelineFactory.java b/src/main/java/com/ycwl/basic/face/pipeline/factory/FaceMatchingPipelineFactory.java index b1af037d..33c10927 100644 --- a/src/main/java/com/ycwl/basic/face/pipeline/factory/FaceMatchingPipelineFactory.java +++ b/src/main/java/com/ycwl/basic/face/pipeline/factory/FaceMatchingPipelineFactory.java @@ -71,6 +71,40 @@ public class FaceMatchingPipelineFactory { @Autowired private ScenicConfigFacade scenicConfigFacade; + /** + * 创建打印机大屏识别试点Pipeline + * 仅执行:识别、补救、落库、建关系 + * + * 说明: + * - “准备上下文”属于基础能力,默认包含 + * - “建关系”包含构建关联与持久化两步 + */ + public Pipeline createPrinterTvRecognizePipeline() { + PipelineBuilder builder = new PipelineBuilder<>("PrinterTvRecognize"); + + // 1. 准备上下文 + builder.addStage(prepareContextStage); + + // 2. 执行人脸识别 + builder.addStage(faceRecognitionStage); + + // 3. 人脸识别补救 + builder.addStage(faceRecoveryStage); + + // 4. 更新人脸结果(落库) + builder.addStage(updateFaceResultStage); + + // 5. 构建源文件关联(建关系) + builder.addStage(buildSourceRelationStage); + + // 6. 持久化关联关系(建关系) + builder.addStage(persistRelationsStage); + + log.debug("创建打印机大屏识别试点Pipeline: stageCount={}", builder.build().getStageCount()); + + return builder.build(); + } + /** * 创建自动人脸匹配Pipeline * @@ -219,6 +253,7 @@ public class FaceMatchingPipelineFactory { case AUTO_MATCHING -> createAutoMatchingPipeline(isNew); case CUSTOM_MATCHING -> createCustomMatchingPipeline(); case RECOGNITION_ONLY -> createRecognitionOnlyPipeline(); + case PRINTER_TV_RECOGNIZE -> createPrinterTvRecognizePipeline(); }; } 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 624ba92e..99e17a78 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 @@ -7,6 +7,9 @@ import com.ycwl.basic.biz.OrderBiz; import com.ycwl.basic.biz.TemplateBiz; import com.ycwl.basic.constant.BaseContextHandler; import com.ycwl.basic.exception.BaseException; +import com.ycwl.basic.face.pipeline.core.FaceMatchingContext; +import com.ycwl.basic.face.pipeline.enums.FaceMatchingScene; +import com.ycwl.basic.face.pipeline.factory.FaceMatchingPipelineFactory; import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter; import com.ycwl.basic.facebody.entity.SearchFaceResultItem; import com.ycwl.basic.mapper.FaceSampleMapper; @@ -85,6 +88,8 @@ import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.enums.StorageAcl; import com.ycwl.basic.storage.utils.StorageUtil; import com.ycwl.basic.utils.*; +import com.ycwl.basic.pipeline.core.Pipeline; +import com.ycwl.basic.pipeline.exception.PipelineException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Strings; @@ -119,6 +124,8 @@ import static com.ycwl.basic.constant.StorageConstant.USER_FACE; @Slf4j @Service public class FaceServiceImpl implements FaceService { + private static final String FACE_UPLOAD_SCENE_PRINTER_TV = "tv"; + @Autowired private FaceMapper faceMapper; @Autowired @@ -176,6 +183,8 @@ public class FaceServiceImpl implements FaceService { // 编排器 @Autowired private FaceMatchingOrchestrator faceMatchingOrchestrator; + @Autowired + private FaceMatchingPipelineFactory faceMatchingPipelineFactory; // 防重复服务 @Autowired @@ -311,7 +320,7 @@ public class FaceServiceImpl implements FaceService { resp.setUrl(faceUrl); resp.setFaceId(newFaceId); resp.setScenicId(scenicId); - matchFaceId(newFaceId, oldFaceId == null); + matchFaceId(newFaceId, oldFaceId == null, scene); // 异步执行自动添加打印 Long finalFaceId = newFaceId; @@ -368,9 +377,35 @@ public class FaceServiceImpl implements FaceService { } @Override public SearchFaceRespVo matchFaceId(Long faceId, boolean isNew, String scene) { + if (Strings.CI.equals(FACE_UPLOAD_SCENE_PRINTER_TV, scene)) { + return matchFaceIdForPrinterTv(faceId, isNew); + } return faceMatchingOrchestrator.orchestrateMatching(faceId, isNew, scene); } + private SearchFaceRespVo matchFaceIdForPrinterTv(Long faceId, boolean isNew) { + FaceMatchingContext context = FaceMatchingContext.builder() + .faceId(faceId) + .isNew(isNew) + .scene(FaceMatchingScene.PRINTER_TV_RECOGNIZE) + .build(); + + Pipeline pipeline = faceMatchingPipelineFactory.createPrinterTvRecognizePipeline(); + try { + boolean success = pipeline.execute(context); + if (!success) { + throw new BaseException("打印机大屏人脸识别失败"); + } + return context.getSearchResult(); + } catch (PipelineException e) { + Throwable rootCause = e.getCause(); + if (rootCause instanceof BaseException baseException) { + throw baseException; + } + throw new BaseException("打印机大屏人脸识别失败"); + } + } + /** * 更新人脸实体结果信息 * 仅用于 handleCustomFaceMatching 方法