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 1478d465..1dfb99b6 100644 --- a/src/main/java/com/ycwl/basic/controller/printer/PrinterTvController.java +++ b/src/main/java/com/ycwl/basic/controller/printer/PrinterTvController.java @@ -1,34 +1,48 @@ package com.ycwl.basic.controller.printer; +import cn.hutool.core.date.DateUtil; +import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter; +import com.ycwl.basic.model.task.resp.SearchFaceRespVo; +import com.ycwl.basic.service.task.TaskFaceService; +import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.annotation.IgnoreToken; +import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO; -import com.ycwl.basic.integration.device.service.DeviceIntegrationService; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; +import com.ycwl.basic.mapper.SourceMapper; import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; import com.ycwl.basic.model.pc.mp.MpConfigEntity; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; +import com.ycwl.basic.model.pc.source.entity.SourceEntity; +import com.ycwl.basic.model.printer.FaceRecognizeWithSourcesResp; import com.ycwl.basic.repository.DeviceRepository; import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.ScenicRepository; +import com.ycwl.basic.service.pc.FaceService; import com.ycwl.basic.service.pc.ScenicService; +import com.ycwl.basic.storage.utils.StorageUtil; import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.WxMpUtil; -import jakarta.websocket.server.PathParam; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.FileInputStream; -import java.io.IOException; import java.io.OutputStream; -import jakarta.servlet.http.HttpServletResponse; - +import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.UUID; + +import static com.ycwl.basic.constant.StorageConstant.USER_FACE; @IgnoreToken // 打印机大屏对接接口 @@ -40,6 +54,9 @@ public class PrinterTvController { private final DeviceRepository deviceRepository; private final ScenicRepository scenicRepository; private final FaceRepository faceRepository; + private final TaskFaceService faceService; + private final ScenicService scenicService; + private final SourceMapper sourceMapper; /** * 获取景区列表 @@ -100,4 +117,75 @@ public class PrinterTvController { } } } + + /** + * 根据人脸样本ID查询图像素材 + * + * @param faceSampleId 人脸样本ID + * @return type=2且face_sample_id匹配的source记录 + */ + @GetMapping("/{faceSampleId}/source") + public ApiResponse getSourceByFaceSampleId(@PathVariable Long faceSampleId) { + SourceEntity source = sourceMapper.getBySampleIdAndType(faceSampleId, 2); + if (source == null) { + return ApiResponse.fail("未找到对应的图像素材"); + } + return ApiResponse.success(source); + } + + /** + * 打印机大屏人脸识别 + * 上传照片,在景区人脸库中搜索匹配的人脸样本,返回识别结果和匹配到的图像素材 + * + * @param file 人脸照片文件 + * @param scenicId 景区ID + * @return 人脸识别结果和匹配的source列表 + */ + @PostMapping("/{scenicId}/faceRecognize") + public ApiResponse faceRecognize( + @RequestParam("file") MultipartFile file, + @PathVariable Long scenicId) throws Exception { + + // 1. 上传人脸照片到存储 + IStorageAdapter adapter = StorageFactory.use("faces"); + String filePath = StorageUtil.joinPath(USER_FACE, DateUtil.format(new Date(), "yyyy-MM-dd")); + String originalFilename = file.getOriginalFilename(); + String suffix = originalFilename.split("\\.", 2)[1]; + String fileName = UUID.randomUUID() + "." + suffix; + String faceUrl = adapter.uploadFile(file, filePath, fileName); + + // 2. 获取景区人脸识别适配器 + IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(scenicId); + + // 3. 在景区人脸库中搜索(注意:这里使用scenicId作为数据库名,搜索的是景区内的人脸样本) + SearchFaceRespVo searchResult = faceService.searchFace( + faceBodyAdapter, + String.valueOf(scenicId), + faceUrl, + "大屏端人脸识别" + ); + + // 4. 查询匹配到的图像素材(type=2) + List sources = new ArrayList<>(); + if (searchResult != null && searchResult.getSampleListIds() != null && !searchResult.getSampleListIds().isEmpty()) { + // 遍历匹配到的人脸样本ID,查询对应的图像素材 + for (Long sampleId : searchResult.getSampleListIds()) { + SourceEntity source = sourceMapper.getBySampleIdAndType(sampleId, 2); + if (source != null) { + sources.add(source); + } + } + } + + // 5. 构造响应 + FaceRecognizeWithSourcesResp resp = new FaceRecognizeWithSourcesResp(); + resp.setUrl(faceUrl); + resp.setFaceId(null); // 不保存人脸,所以没有faceId + resp.setScenicId(scenicId); + resp.setSources(sources); + + return ApiResponse.success(resp); + } + + } diff --git a/src/main/java/com/ycwl/basic/model/printer/FaceRecognizeWithSourcesResp.java b/src/main/java/com/ycwl/basic/model/printer/FaceRecognizeWithSourcesResp.java new file mode 100644 index 00000000..1a37eceb --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/printer/FaceRecognizeWithSourcesResp.java @@ -0,0 +1,34 @@ +package com.ycwl.basic.model.printer; + +import com.ycwl.basic.model.pc.source.entity.SourceEntity; +import lombok.Data; + +import java.util.List; + +/** + * @Author:longbinbin + * @Date:2024/12/3 + * 打印机大屏人脸识别响应(包含匹配的source列表) + */ +@Data +public class FaceRecognizeWithSourcesResp { + /** + * 人脸照片URL + */ + private String url; + + /** + * 人脸ID + */ + private Long faceId; + + /** + * 景区ID + */ + private Long scenicId; + + /** + * 匹配到的图像素材列表(type=2) + */ + private List sources; +}