feat(printer): 实现人脸样本使用功能

- 新增人脸样本使用逻辑,支持查询或创建face记录
- 集成人脸识别相关实体和映射器
- 添加人脸样本URL校验和重复检测机制
- 返回包含人脸URL、ID及景区ID的响应对象
- 引入雪花算法生成唯一face ID
- 记录创建新face或使用已有face的日志信息
This commit is contained in:
2025-11-08 01:17:39 +08:00
parent 616ab217e4
commit 747081901f
2 changed files with 80 additions and 1 deletions

View File

@@ -6,4 +6,5 @@ import lombok.Data;
public class FaceRecognizeResp {
private String url;
private Long faceId;
private Long scenicId;
}

View File

@@ -2,21 +2,29 @@ package com.ycwl.basic.service.printer.impl;
import cn.hutool.http.HttpUtil;
import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.constant.FaceConstant;
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.facebody.adapter.IFaceBodyAdapter;
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.operator.IOperator;
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.MemberMapper;
import com.ycwl.basic.mapper.OrderMapper;
import com.ycwl.basic.mapper.PrintTaskMapper;
import com.ycwl.basic.mapper.PrinterMapper;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
import com.ycwl.basic.model.mobile.order.PriceObj;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
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;
@@ -36,11 +44,15 @@ import com.ycwl.basic.model.printer.req.FromSourceReq;
import com.ycwl.basic.model.printer.req.PrinterSyncReq;
import com.ycwl.basic.model.printer.req.WorkerAuthReqVo;
import com.ycwl.basic.model.printer.resp.PrintTaskResp;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.OrderRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.WxPayService;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.printer.PrinterService;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl;
@@ -67,12 +79,15 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
@Slf4j
@Service
public class PrinterServiceImpl implements PrinterService {
@@ -97,6 +112,16 @@ public class PrinterServiceImpl implements PrinterService {
private ScenicRepository scenicRepository;
@Autowired
private OrderRepository orderRepository;
@Autowired
private FaceSampleMapper faceSampleMapper;
@Autowired
private FaceMapper faceMapper;
@Autowired
private FaceRepository faceRepository;
@Autowired
private ScenicService scenicService;
@Autowired
private TaskFaceService faceService;
@Override
public List<PrinterResp> listByScenicId(Long scenicId) {
@@ -720,7 +745,60 @@ public class PrinterServiceImpl implements PrinterService {
@Override
public Object useSample(Long userId, Long sampleId) {
return null;
// 1. 查询 faceSample 获取其 URL
FaceSampleEntity faceSample = faceSampleMapper.getEntity(sampleId);
if (faceSample == null) {
throw new BaseException("人脸样本不存在");
}
String faceUrl = faceSample.getFaceUrl();
if (StringUtils.isBlank(faceUrl)) {
throw new BaseException("人脸样本URL为空");
}
Long scenicId = faceSample.getScenicId();
// 2. 检查face数据库中有没有同用户、同URL的face记录
FaceEntity existingFace = null;
Long faceId = null;
// 查询该用户在该景区的所有人脸记录
List<FaceRespVO> userFaces = faceMapper.listByScenicAndUserId(scenicId.toString(), userId);
// 查找是否存在相同URL的记录
for (FaceRespVO faceResp : userFaces) {
if (faceUrl.equals(faceResp.getFaceUrl())) {
existingFace = faceMapper.get(faceResp.getId());
faceId = existingFace.getId();
break;
}
}
// 3. 如果不存在,则新建一个face记录
if (existingFace == null) {
faceId = SnowFlakeUtil.getLongId();
FaceEntity newFace = new FaceEntity();
newFace.setId(faceId);
newFace.setCreateAt(new Date());
newFace.setScenicId(scenicId);
newFace.setMemberId(userId);
newFace.setFaceUrl(faceUrl);
faceMapper.add(newFace);
log.info("创建新的face记录, userId: {}, sampleId: {}, faceId: {}, faceUrl: {}",
userId, sampleId, faceId, faceUrl);
} else {
log.info("使用已存在的face记录, userId: {}, sampleId: {}, faceId: {}, faceUrl: {}",
userId, sampleId, faceId, faceUrl);
}
// 4. 返回结果
FaceRecognizeResp resp = new FaceRecognizeResp();
resp.setUrl(faceUrl);
resp.setFaceId(faceId);
resp.setScenicId(scenicId);
return resp;
}
/**