feat(printer): 优化打印机大屏人脸识别接口

- 移除多余依赖和字段声明
- 简化人脸识别逻辑,复用 faceUpload 方法
- 保留人脸去重检测和自动添加打印逻辑
- 修改返回结构为 FaceRecognizeResp
- 删除旧有的照片上传与素材查询流程
This commit is contained in:
2025-12-17 23:12:49 +08:00
parent 10b39ec4c1
commit 9e6b623b0e

View File

@@ -1,36 +1,21 @@
package com.ycwl.basic.controller.printer; package com.ycwl.basic.controller.printer;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.repository.MemberRelationRepository;
import com.ycwl.basic.repository.SourceRepository;
import com.ycwl.basic.service.printer.PrinterService;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.annotation.IgnoreToken; 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.dto.device.DeviceV2DTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.SourceMapper; import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.model.pc.mp.MpConfigEntity; import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.source.entity.SourceEntity; 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.DeviceRepository;
import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.FaceService; 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.ApiResponse;
import com.ycwl.basic.utils.SnowFlakeUtil;
import com.ycwl.basic.utils.WxMpUtil; import com.ycwl.basic.utils.WxMpUtil;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -45,13 +30,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID;
import static com.ycwl.basic.constant.StorageConstant.USER_FACE;
@IgnoreToken @IgnoreToken
// 打印机大屏对接接口 // 打印机大屏对接接口
@@ -65,10 +44,6 @@ public class PrinterTvController {
private final FaceRepository faceRepository; private final FaceRepository faceRepository;
private final FaceService pcFaceService; private final FaceService pcFaceService;
private final SourceMapper sourceMapper; private final SourceMapper sourceMapper;
private final FaceMapper faceMapper;
private final MemberRelationRepository memberRelationRepository;
private final SourceRepository sourceRepository;
private final PrinterService printerService;
/** /**
* 获取景区列表 * 获取景区列表
@@ -204,71 +179,23 @@ public class PrinterTvController {
/** /**
* 打印机大屏人脸识别 * 打印机大屏人脸识别
* 上传照片,在景区人脸库中搜索匹配的人脸样本,返回识别结果和匹配到的图像素材 * 上传照片,在景区人脸库中搜索匹配的人脸样本,返回识别结果
*
* 使用 USER_FACE_DB_NAME+scenicId 对人脸进行去重检测:
* - 如果已存在相同人脸(打印机大屏用户,memberId=0),则返回已存在的 faceId
* - 否则创建新的人脸记录并添加到人脸库
* *
* @param file 人脸照片文件 * @param file 人脸照片文件
* @param scenicId 景区ID * @param scenicId 景区ID
* @return 人脸识别结果和匹配的source列表 * @return 人脸识别结果
*/ */
@PostMapping("/{scenicId}/faceRecognize") @PostMapping("/{scenicId}/faceRecognize")
public ApiResponse<FaceRecognizeWithSourcesResp> faceRecognize( public ApiResponse<FaceRecognizeResp> faceRecognize(
@RequestParam("file") MultipartFile file, @RequestParam("file") MultipartFile file,
@PathVariable Long scenicId) throws Exception { @PathVariable Long scenicId) {
// 复用 faceUpload 方法的去重逻辑
// 1. 上传人脸照片到存储 // memberId=0L 表示打印机大屏用户,scene="print" 会触发自动添加打印逻辑并等待完成
IStorageAdapter adapter = StorageFactory.use("faces"); FaceRecognizeResp resp = pcFaceService.faceUpload(file, scenicId, 0L, "print");
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. 保存人脸数据到数据库
Long faceId = SnowFlakeUtil.getLongId();
FaceEntity faceEntity = new FaceEntity();
faceEntity.setId(faceId);
faceEntity.setScenicId(scenicId);
faceEntity.setFaceUrl(faceUrl);
faceEntity.setCreateAt(new Date());
faceEntity.setMemberId(0L); // 打印机大屏端没有用户ID
faceMapper.add(faceEntity);
// 3. 在景区人脸库中搜索(注意:这里使用scenicId作为数据库名,搜索的是景区内的人脸样本)
pcFaceService.matchFaceId(faceId);
// 4. 自动添加照片到打印列表,并获取添加成功的照片列表
List<SourceEntity> addedSources = printerService.autoAddPhotosToPreferPrint(faceId);
// 5. 根据自动添加结果决定返回的sources
List<SourceEntity> sources;
if (addedSources != null && !addedSources.isEmpty()) {
// 如果自动添加成功,返回添加的照片列表
sources = addedSources;
} else {
// 如果自动添加为空,按原逻辑查询匹配到的图像素材(type=2)
sources = new ArrayList<>();
List<MemberSourceEntity> memberSourceEntities = memberRelationRepository.listSourceByFaceRelation(faceId, 2);
for (MemberSourceEntity memberSourceEntity : memberSourceEntities) {
SourceEntity source = sourceRepository.getSource(memberSourceEntity.getSourceId());
if (source != null) {
sources.add(source);
}
}
}
// 6. 构造响应
FaceRecognizeWithSourcesResp resp = new FaceRecognizeWithSourcesResp();
resp.setUrl(faceUrl);
resp.setFaceId(faceId);
resp.setScenicId(scenicId);
resp.setSources(sources);
// 只有当添加了照片时才返回二维码URL
//if (addedSources != null && !addedSources.isEmpty()) {
//resp.setQrcodeUrl("https://zhentuai.com/printer/v1/tv/face/" + faceId + "/qrcode");
//} else {
resp.setQrcodeUrl(null);
//}
return ApiResponse.success(resp); return ApiResponse.success(resp);
} }