You've already forked FrameTour-BE
							
							指定设备提前预约
This commit is contained in:
		
							
								
								
									
										192
									
								
								src/main/java/com/ycwl/basic/biz/TaskStatusBiz.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								src/main/java/com/ycwl/basic/biz/TaskStatusBiz.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | |||||||
|  | package com.ycwl.basic.biz; | ||||||
|  |  | ||||||
|  | import com.ycwl.basic.mapper.FaceMapper; | ||||||
|  | import com.ycwl.basic.mapper.TaskMapper; | ||||||
|  | import com.ycwl.basic.mapper.VideoMapper; | ||||||
|  | import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO; | ||||||
|  | import com.ycwl.basic.model.pc.face.entity.FaceEntity; | ||||||
|  | import com.ycwl.basic.model.pc.face.resp.FaceRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.task.req.TaskReqQuery; | ||||||
|  | import com.ycwl.basic.model.pc.task.resp.TaskRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.template.resp.TemplateRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.video.entity.VideoEntity; | ||||||
|  | import com.ycwl.basic.repository.FaceRepository; | ||||||
|  | import com.ycwl.basic.repository.TemplateRepository; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.data.redis.core.RedisTemplate; | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
|  | import java.util.Comparator; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Optional; | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
|  | @Component | ||||||
|  | public class TaskStatusBiz { | ||||||
|  |     public static final String TASK_STATUS_USER_CACHE_KEY = "task:status:user:%s:face:%s"; | ||||||
|  |     public static final String TASK_STATUS_FACE_CACHE_KEY = "task:status:face:%s"; | ||||||
|  |     public static final String TASK_STATUS_FACE_CACHE_KEY_CUT = "task:status:face:%s:cut"; | ||||||
|  |     public static final String TASK_STATUS_FACE_CACHE_KEY_TEMPLATE = "task:status:face:%s:tpl:%s"; | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private RedisTemplate<String, String> redisTemplate; | ||||||
|  |     @Autowired | ||||||
|  |     private FaceRepository faceRepository; | ||||||
|  |     @Autowired | ||||||
|  |     private TemplateRepository templateRepository; | ||||||
|  |     @Autowired | ||||||
|  |     private FaceMapper faceMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private TaskMapper taskMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private VideoMapper videoMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private TemplateBiz templateBiz; | ||||||
|  |  | ||||||
|  |     public boolean getUserHaveFace(Long userId, Long faceId) { | ||||||
|  |         if (userId == null || faceId == null) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (redisTemplate.hasKey(String.format(TASK_STATUS_USER_CACHE_KEY, userId, faceId))) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         FaceEntity face = faceRepository.getFace(faceId); | ||||||
|  |         if (face == null) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (face.getMemberId().equals(userId)) { | ||||||
|  |             redisTemplate.opsForValue().set(String.format(TASK_STATUS_USER_CACHE_KEY, userId, faceId), "1", 3600, TimeUnit.SECONDS); | ||||||
|  |             return true; | ||||||
|  |         } else { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setFaceCutStatus(Long faceId, int status) { | ||||||
|  |         redisTemplate.opsForValue().set(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId), String.valueOf(status), 3600, TimeUnit.SECONDS); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setFaceTemplateStatus(Long faceId, Long templateId, Long videoId) { | ||||||
|  |         redisTemplate.opsForValue().set(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId), String.valueOf(videoId), 3600, TimeUnit.SECONDS); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public VideoTaskStatusVO getScenicUserStatus(Long scenicId, Long userId) { | ||||||
|  |         FaceRespVO lastFace = faceMapper.findLastFaceByScenicAndUserId(scenicId, userId); | ||||||
|  |         VideoTaskStatusVO response = new VideoTaskStatusVO(); | ||||||
|  |         if (lastFace == null) { | ||||||
|  |             response.setStatus(-1); | ||||||
|  |             return response; | ||||||
|  |         } | ||||||
|  |         return getFaceStatus(lastFace.getId()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public VideoTaskStatusVO getFaceStatus(Long faceId) { | ||||||
|  |         FaceEntity face = faceRepository.getFace(faceId); | ||||||
|  |         VideoTaskStatusVO response = new VideoTaskStatusVO(); | ||||||
|  |         if (face == null) { | ||||||
|  |             response.setStatus(-1); | ||||||
|  |             return response; | ||||||
|  |         } | ||||||
|  |         response.setScenicId(face.getScenicId()); | ||||||
|  |         response.setFaceId(faceId); | ||||||
|  |         List<TemplateRespVO> templateList = templateRepository.getTemplateListByScenicId(face.getScenicId()); | ||||||
|  |         response.setMaxCount(templateList.size()); | ||||||
|  |         int alreadyFinished = 0; | ||||||
|  |         for (TemplateRespVO template : templateList) { | ||||||
|  |             response.setTemplateId(template.getId()); | ||||||
|  |             long videoId = getFaceTemplateVideoId(faceId, template.getId()); | ||||||
|  |             if (videoId <= 0) { | ||||||
|  |                 response.setStatus(2); | ||||||
|  |             } else { | ||||||
|  |                 response.setVideoId(videoId); | ||||||
|  |                 alreadyFinished++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         response.setCount(alreadyFinished); | ||||||
|  |         if (alreadyFinished == 0) { | ||||||
|  |             response.setStatus(0); | ||||||
|  |         } else { | ||||||
|  |             response.setStatus(1); | ||||||
|  |         } | ||||||
|  |         if (alreadyFinished == 0) { | ||||||
|  |             int faceCutStatus = getFaceCutStatus(faceId); | ||||||
|  |             if (faceCutStatus != 1) { | ||||||
|  |                 // 正在切片 | ||||||
|  |                 if (templateBiz.determineTemplateCanGenerate(templateList.get(0).getId(), faceId, false)) { | ||||||
|  |                     response.setStatus(2); | ||||||
|  |                 } else { | ||||||
|  |                     response.setStatus(0); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public VideoTaskStatusVO getFaceTemplateStatus(Long faceId, Long templateId) { | ||||||
|  |         FaceEntity face = faceRepository.getFace(faceId); | ||||||
|  |         VideoTaskStatusVO response = new VideoTaskStatusVO(); | ||||||
|  |         if (face == null) { | ||||||
|  |             response.setStatus(-1); | ||||||
|  |             return response; | ||||||
|  |         } | ||||||
|  |         response.setScenicId(face.getScenicId()); | ||||||
|  |         response.setFaceId(faceId); | ||||||
|  |         response.setTemplateId(templateId); | ||||||
|  |         long videoId = getFaceTemplateVideoId(faceId, templateId); | ||||||
|  |         if (videoId < 0) { | ||||||
|  |             int faceCutStatus = getFaceCutStatus(faceId); | ||||||
|  |             if (faceCutStatus != 1) { | ||||||
|  |                 // 正在切片 | ||||||
|  |                 response.setStatus(2); | ||||||
|  |                 return response; | ||||||
|  |             } | ||||||
|  |         } else if (videoId == 0) { | ||||||
|  |             response.setStatus(2); | ||||||
|  |         } else { | ||||||
|  |             response.setVideoId(videoId); | ||||||
|  |             response.setStatus(1); | ||||||
|  |         } | ||||||
|  |         return response; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public int getFaceCutStatus(Long faceId) { | ||||||
|  |         if (redisTemplate.hasKey(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId))) { | ||||||
|  |             String status = redisTemplate.opsForValue().get(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId)); | ||||||
|  |             if (status != null) { | ||||||
|  |                 return Integer.parseInt(status); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public long getFaceTemplateVideoId(Long faceId, Long templateId) { | ||||||
|  |         if (redisTemplate.hasKey(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId))) { | ||||||
|  |             String status = redisTemplate.opsForValue().get(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId)); | ||||||
|  |             if (status != null) { | ||||||
|  |                 return Long.parseLong(status); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         TaskReqQuery taskReqQuery = new TaskReqQuery(); | ||||||
|  |         taskReqQuery.setFaceId(faceId); | ||||||
|  |         taskReqQuery.setTemplateId(templateId); | ||||||
|  |         List<TaskRespVO> list = taskMapper.list(taskReqQuery); | ||||||
|  |         Optional<TaskRespVO> min = list.stream().min(Comparator.comparing(TaskRespVO::getCreateTime)); | ||||||
|  |         if (min.isPresent()) { | ||||||
|  |             TaskRespVO task = min.get(); | ||||||
|  |             long taskStatus = 0; | ||||||
|  |             if (task.getStatus() == 1) { | ||||||
|  |                 // 已完成 | ||||||
|  |                 VideoEntity video = videoMapper.findByTaskId(task.getId()); | ||||||
|  |                 if (video != null) { | ||||||
|  |                     taskStatus = video.getId(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             setFaceTemplateStatus(faceId, templateId, taskStatus); | ||||||
|  |         } else { | ||||||
|  |             // 从来没生成过 | ||||||
|  |             setFaceTemplateStatus(faceId, templateId, -1L); | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,6 +1,7 @@ | |||||||
| package com.ycwl.basic.controller.mobile; | package com.ycwl.basic.controller.mobile; | ||||||
|  |  | ||||||
| import com.ycwl.basic.annotation.IgnoreToken; | import com.ycwl.basic.annotation.IgnoreToken; | ||||||
|  | import com.ycwl.basic.biz.TaskStatusBiz; | ||||||
| import com.ycwl.basic.constant.BaseContextHandler; | import com.ycwl.basic.constant.BaseContextHandler; | ||||||
| import com.ycwl.basic.exception.CheckTokenException; | import com.ycwl.basic.exception.CheckTokenException; | ||||||
| import com.ycwl.basic.model.jwt.JwtInfo; | import com.ycwl.basic.model.jwt.JwtInfo; | ||||||
| @@ -31,6 +32,8 @@ public class AppGoodsController { | |||||||
|     private GoodsService goodsService; |     private GoodsService goodsService; | ||||||
|     @Autowired |     @Autowired | ||||||
|     private TaskService taskService; |     private TaskService taskService; | ||||||
|  |     @Autowired | ||||||
|  |     private TaskStatusBiz taskStatusBiz; | ||||||
|  |  | ||||||
|     @ApiOperation("商品列表") |     @ApiOperation("商品列表") | ||||||
|     @PostMapping("/goodsList") |     @PostMapping("/goodsList") | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package com.ycwl.basic.controller.mobile; | package com.ycwl.basic.controller.mobile; | ||||||
|  |  | ||||||
| import com.ycwl.basic.annotation.IgnoreLogReq; | import com.ycwl.basic.annotation.IgnoreLogReq; | ||||||
|  | import com.ycwl.basic.biz.TaskStatusBiz; | ||||||
| import com.ycwl.basic.model.jwt.JwtInfo; | import com.ycwl.basic.model.jwt.JwtInfo; | ||||||
| import com.ycwl.basic.model.mobile.goods.VideoTaskReq; | import com.ycwl.basic.model.mobile.goods.VideoTaskReq; | ||||||
| import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO; | import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO; | ||||||
| @@ -24,6 +25,8 @@ public class AppTaskController { | |||||||
|     private GoodsService goodsService; |     private GoodsService goodsService; | ||||||
|     @Autowired |     @Autowired | ||||||
|     private TaskService taskService; |     private TaskService taskService; | ||||||
|  |     @Autowired | ||||||
|  |     private TaskStatusBiz taskStatusBiz; | ||||||
|  |  | ||||||
|     @GetMapping("/face/{faceId}") |     @GetMapping("/face/{faceId}") | ||||||
|     @IgnoreLogReq |     @IgnoreLogReq | ||||||
|   | |||||||
| @@ -273,7 +273,9 @@ public class ViidController { | |||||||
|                             faceSampleMapper.add(faceSample); |                             faceSampleMapper.add(faceSample); | ||||||
|                             new Thread(() -> { |                             new Thread(() -> { | ||||||
|                                 taskFaceService.addFaceSample(faceSample.getId()); |                                 taskFaceService.addFaceSample(faceSample.getId()); | ||||||
|                                 DynamicTaskGenerator.addTask(faceSample.getId()); |                                 if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) { | ||||||
|  |                                     DynamicTaskGenerator.addTask(faceSample.getId()); | ||||||
|  |                                 } | ||||||
|                             }).start(); |                             }).start(); | ||||||
|                             for (SubImageInfoObject _subImage : type14ImageList) { |                             for (SubImageInfoObject _subImage : type14ImageList) { | ||||||
|                                 facePosition.setImgHeight(_subImage.getHeight()); |                                 facePosition.setImgHeight(_subImage.getHeight()); | ||||||
| @@ -318,7 +320,12 @@ public class ViidController { | |||||||
|                             faceSample.setFaceUrl(url); |                             faceSample.setFaceUrl(url); | ||||||
|                             faceSampleMapper.add(faceSample); |                             faceSampleMapper.add(faceSample); | ||||||
|                             DynamicTaskGenerator.addTask(faceSample.getId()); |                             DynamicTaskGenerator.addTask(faceSample.getId()); | ||||||
|                             taskFaceService.addFaceSample(faceSample.getId()); |                             new Thread(() -> { | ||||||
|  |                                 taskFaceService.addFaceSample(faceSample.getId()); | ||||||
|  |                                 if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) { | ||||||
|  |                                     DynamicTaskGenerator.addTask(faceSample.getId()); | ||||||
|  |                                 } | ||||||
|  |                             }).start(); | ||||||
|                             log.info("模式1人脸信息入库成功!设备ID:{}", deviceID); |                             log.info("模式1人脸信息入库成功!设备ID:{}", deviceID); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -12,8 +12,9 @@ public enum StatisticEnum { | |||||||
|     REFUND(5,"退款"), |     REFUND(5,"退款"), | ||||||
|     MESSAGE_PUSH(6,"消息推送"), |     MESSAGE_PUSH(6,"消息推送"), | ||||||
|     DOWNLOAD(8,"下载"), |     DOWNLOAD(8,"下载"), | ||||||
|     CLICK_ON_PAYMENT(9,"点击支付、购买"), |     CLICK_PAY(9,"点击支付"), | ||||||
|     OTHER_ENTER(10,"其他渠道进入"), |     OTHER_ENTER(10,"其他渠道进入"), | ||||||
|  |     SUBMIT_PAYMENT(11,"点击支付"), | ||||||
|     SCAN_MARKED_CODE(20,"扫描特殊标记码"), |     SCAN_MARKED_CODE(20,"扫描特殊标记码"), | ||||||
|  |  | ||||||
|     ; |     ; | ||||||
|   | |||||||
| @@ -66,7 +66,7 @@ public class AuthInterceptor extends HandlerInterceptorAdapter { | |||||||
|         // 获取 token |         // 获取 token | ||||||
|         String token = getToken(request); |         String token = getToken(request); | ||||||
|         if (StringUtils.isEmpty(token)) { |         if (StringUtils.isEmpty(token)) { | ||||||
|             log.error("==>  请求 header 缺少 Token [{}]", token); |             log.error("==>  请求 header 缺少 Token [{}], URL [{}]", token, request.getRequestURL()); | ||||||
|             throw new MissTokenException("请求头缺少token"); |             throw new MissTokenException("请求头缺少token"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,11 +24,12 @@ public interface FaceMapper { | |||||||
|     int deleteByIds(@Param("list") List<Long> ids); |     int deleteByIds(@Param("list") List<Long> ids); | ||||||
|     int update(FaceEntity face); |     int update(FaceEntity face); | ||||||
|  |  | ||||||
|     FaceRespVO getByMemberId(@Param("userId") Long userId, @Param("scenicId") Long scenicId); |     FaceRespVO getLatestByMemberId(@Param("userId") Long userId, @Param("scenicId") Long scenicId); | ||||||
|  |  | ||||||
|     int finishedJourney(Long faceId); |     int finishedJourney(Long faceId); | ||||||
|  |  | ||||||
|     FaceRespVO findLastFaceByUserId(String userId); |     FaceRespVO findLastFaceByUserId(String userId); | ||||||
|  |     FaceRespVO findLastFaceByScenicAndUserId(Long scenicId, Long userId); | ||||||
|  |  | ||||||
|     List<FaceRespVO> listByScenicAndUserId(String scenicId, Long userId); |     List<FaceRespVO> listByScenicAndUserId(String scenicId, Long userId); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,5 +26,5 @@ public interface FaceSampleMapper { | |||||||
|     List<FaceSampleEntity> listByIds(List<Long> list); |     List<FaceSampleEntity> listByIds(List<Long> list); | ||||||
|  |  | ||||||
|     FaceSampleEntity getEntity(Long faceSampleId); |     FaceSampleEntity getEntity(Long faceSampleId); | ||||||
|     List<FaceSampleEntity> listEntity(Long scenicId, Date endDate); |     List<FaceSampleEntity> listEntityBeforeDate(Long scenicId, Date endDate); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -57,4 +57,5 @@ public class DeviceConfigEntity { | |||||||
|      * 切割时,取人脸后多少秒的视频 |      * 切割时,取人脸后多少秒的视频 | ||||||
|      */ |      */ | ||||||
|     private BigDecimal cutPost; |     private BigDecimal cutPost; | ||||||
|  |     private Integer enablePreBook; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject; | |||||||
| import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest; | import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest; | ||||||
| import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse; | import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse; | ||||||
| import com.baomidou.mybatisplus.annotation.IdType; | import com.baomidou.mybatisplus.annotation.IdType; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableField; | ||||||
| import com.baomidou.mybatisplus.annotation.TableId; | import com.baomidou.mybatisplus.annotation.TableId; | ||||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||||
| import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord; | import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord; | ||||||
| @@ -31,6 +32,9 @@ public class FaceDetectLog { | |||||||
|  |  | ||||||
|     private String matchLocalRecord; |     private String matchLocalRecord; | ||||||
|  |  | ||||||
|  |     @TableField(exist = false) | ||||||
|  |     private List<SearchFaceResponse.Data.MatchListItem.FaceItemsItem> matchRawRecord; | ||||||
|  |  | ||||||
|     public static FaceDetectLog quickCreate(String reason) { |     public static FaceDetectLog quickCreate(String reason) { | ||||||
|         FaceDetectLog log = new FaceDetectLog(); |         FaceDetectLog log = new FaceDetectLog(); | ||||||
|         log.reason = reason; |         log.reason = reason; | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import java.util.Date; | |||||||
| @Data | @Data | ||||||
| public class MatchLocalRecord { | public class MatchLocalRecord { | ||||||
|     private Long faceSampleId; |     private Long faceSampleId; | ||||||
|  |     private String deviceName; | ||||||
|     private String faceUrl; |     private String faceUrl; | ||||||
|     private Float score; |     private Float score; | ||||||
|     private Float confidence; |     private Float confidence; | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ public class ScenicConfigEntity { | |||||||
|      * 预约流程,1-预约,2-在线,3-全部 |      * 预约流程,1-预约,2-在线,3-全部 | ||||||
|      */ |      */ | ||||||
|     private Integer bookRoutine; |     private Integer bookRoutine; | ||||||
|  |     private Integer forceFinishTime; | ||||||
|     /** |     /** | ||||||
|      * 样本保存时间 |      * 样本保存时间 | ||||||
|      */ |      */ | ||||||
|   | |||||||
| @@ -5,28 +5,36 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; | |||||||
| import java.util.concurrent.Semaphore; | import java.util.concurrent.Semaphore; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
| public class FixedRateLimiter { | public class FixedRateLimiter implements IRateLimiter { | ||||||
|     private final Semaphore semaphore = new Semaphore(1); |     private final Semaphore semaphore = new Semaphore(1); | ||||||
|     private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); |     private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); | ||||||
|  |  | ||||||
|     public FixedRateLimiter(int rate, TimeUnit timeUnit) { |     public FixedRateLimiter(int rate, TimeUnit timeUnit) { | ||||||
|         // 启动一个线程每0.5秒释放一个许可 |         // 启动一个线程每0.5秒释放一个许可 | ||||||
|         scheduler.scheduleAtFixedRate(() -> { |         scheduler.scheduleAtFixedRate(() -> { | ||||||
|             synchronized (semaphore) { |             if (semaphore.availablePermits() < 1) { | ||||||
|                 if (semaphore.availablePermits() < 1) { |                 semaphore.release(1); | ||||||
|                     semaphore.release(1); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         }, rate, rate, timeUnit); |         }, rate, rate, timeUnit); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|     public void acquire() throws InterruptedException { |     public void acquire() throws InterruptedException { | ||||||
|         synchronized (semaphore) { |         semaphore.acquire(); | ||||||
|             semaphore.acquire(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|     public void shutdown() { |     public void shutdown() { | ||||||
|         scheduler.shutdown(); |         scheduler.shutdown(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean tryAcquire() { | ||||||
|  |         return semaphore.tryAcquire(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { | ||||||
|  |         return semaphore.tryAcquire(timeout, unit); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								src/main/java/com/ycwl/basic/ratelimiter/IRateLimiter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/main/java/com/ycwl/basic/ratelimiter/IRateLimiter.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | package com.ycwl.basic.ratelimiter; | ||||||
|  |  | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
|  | public interface IRateLimiter { | ||||||
|  |     void acquire() throws InterruptedException; | ||||||
|  |     void shutdown(); | ||||||
|  |     boolean tryAcquire(); | ||||||
|  |     boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException; | ||||||
|  | } | ||||||
| @@ -6,25 +6,45 @@ import java.util.concurrent.Semaphore; | |||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
|  |  | ||||||
| public class SlidingWindowRateLimiter { | public class SlidingWindowRateLimiter implements IRateLimiter { | ||||||
|     private final Semaphore semaphore; |     private final Semaphore semaphore; | ||||||
|     private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); |     private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); | ||||||
|  |  | ||||||
|     public SlidingWindowRateLimiter(int maxRequestsPerSecond) { |     public SlidingWindowRateLimiter(int maxRequestsPerSecond) { | ||||||
|         this.semaphore = new Semaphore(maxRequestsPerSecond); |         this.semaphore = new Semaphore(maxRequestsPerSecond); | ||||||
|         int rate = 1000000 / maxRequestsPerSecond; |  | ||||||
|         scheduler.scheduleAtFixedRate(() -> { |         scheduler.scheduleAtFixedRate(() -> { | ||||||
|             if (semaphore.availablePermits() < maxRequestsPerSecond) { |             if (semaphore.availablePermits() < maxRequestsPerSecond) { | ||||||
|                 semaphore.release(1); |                 semaphore.release(maxRequestsPerSecond - semaphore.availablePermits()); | ||||||
|             } |             } | ||||||
|         }, rate, rate, TimeUnit.MICROSECONDS); |         }, 1, 1, TimeUnit.SECONDS); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public SlidingWindowRateLimiter(int maxRequests, int perSecond) { | ||||||
|  |         this.semaphore = new Semaphore(maxRequests); | ||||||
|  |         scheduler.scheduleAtFixedRate(() -> { | ||||||
|  |             if (semaphore.availablePermits() < maxRequests) { | ||||||
|  |                 semaphore.release(maxRequests - semaphore.availablePermits()); | ||||||
|  |             } | ||||||
|  |         }, perSecond, perSecond, TimeUnit.SECONDS); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|     public void acquire() throws InterruptedException { |     public void acquire() throws InterruptedException { | ||||||
|         semaphore.acquire(); |         semaphore.acquire(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|     public void shutdown() { |     public void shutdown() { | ||||||
|         scheduler.shutdown(); |         scheduler.shutdown(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean tryAcquire() { | ||||||
|  |         return semaphore.tryAcquire(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { | ||||||
|  |         return semaphore.tryAcquire(timeout, unit); | ||||||
|  |     } | ||||||
| } | } | ||||||
| @@ -346,7 +346,7 @@ public class GoodsServiceImpl implements GoodsService { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public VideoTaskStatusVO getTaskStatusByScenicId(Long userId, Long scenicId) { |     public VideoTaskStatusVO getTaskStatusByScenicId(Long userId, Long scenicId) { | ||||||
|         FaceRespVO faceVO = faceMapper.getByMemberId(userId, scenicId); |         FaceRespVO faceVO = faceMapper.getLatestByMemberId(userId, scenicId); | ||||||
|         VideoTaskStatusVO response = new VideoTaskStatusVO(); |         VideoTaskStatusVO response = new VideoTaskStatusVO(); | ||||||
|         response.setScenicId(scenicId); |         response.setScenicId(scenicId); | ||||||
|         if (faceVO == null) { |         if (faceVO == null) { | ||||||
|   | |||||||
| @@ -326,14 +326,6 @@ public class OrderServiceImpl implements OrderService { | |||||||
|             return ApiResponse.fail("订单添加失败"); |             return ApiResponse.fail("订单添加失败"); | ||||||
|         } |         } | ||||||
|         //点击支付按钮统计 |         //点击支付按钮统计 | ||||||
|         OrderRespVO orderRespVO = orderMapper.getById(orderId); |  | ||||||
|         StatisticsRecordAddReq statisticsRecordAddReq = new StatisticsRecordAddReq(); |  | ||||||
|         statisticsRecordAddReq.setMemberId(orderRespVO.getMemberId()); |  | ||||||
|         statisticsRecordAddReq.setType(StatisticEnum.CLICK_ON_PAYMENT.code); |  | ||||||
|         statisticsRecordAddReq.setScenicId(orderRespVO.getScenicId()); |  | ||||||
|         statisticsRecordAddReq.setMorphId(orderId); |  | ||||||
|         statisticsMapper.addStatisticsRecord(statisticsRecordAddReq); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems); |         WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems); | ||||||
|         return ApiResponse.success(wxPayRespVO); |         return ApiResponse.success(wxPayRespVO); | ||||||
|   | |||||||
| @@ -1,9 +1,7 @@ | |||||||
| package com.ycwl.basic.service.task.impl; | package com.ycwl.basic.service.task.impl; | ||||||
|  |  | ||||||
| import cn.hutool.core.date.DateUtil; |  | ||||||
| import com.alibaba.fastjson.JSON; | import com.alibaba.fastjson.JSON; | ||||||
| import com.aliyuncs.exceptions.ClientException; | import com.aliyuncs.exceptions.ClientException; | ||||||
| import com.aliyuncs.exceptions.ServerException; |  | ||||||
| import com.aliyuncs.facebody.model.v20191230.AddFaceEntityRequest; | import com.aliyuncs.facebody.model.v20191230.AddFaceEntityRequest; | ||||||
| import com.aliyuncs.facebody.model.v20191230.AddFaceRequest; | import com.aliyuncs.facebody.model.v20191230.AddFaceRequest; | ||||||
| import com.aliyuncs.facebody.model.v20191230.AddFaceResponse; | import com.aliyuncs.facebody.model.v20191230.AddFaceResponse; | ||||||
| @@ -16,7 +14,6 @@ import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesRequest; | |||||||
| import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse; | import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse; | ||||||
| import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest; | import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest; | ||||||
| import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse; | import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse; | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |  | ||||||
| import com.ycwl.basic.biz.OrderBiz; | import com.ycwl.basic.biz.OrderBiz; | ||||||
| import com.ycwl.basic.config.FaceDetectConfig; | import com.ycwl.basic.config.FaceDetectConfig; | ||||||
| import com.ycwl.basic.constant.FaceConstant; | import com.ycwl.basic.constant.FaceConstant; | ||||||
| @@ -27,22 +24,20 @@ import com.ycwl.basic.mapper.FaceSampleMapper; | |||||||
| import com.ycwl.basic.mapper.ScenicMapper; | import com.ycwl.basic.mapper.ScenicMapper; | ||||||
| import com.ycwl.basic.mapper.SourceMapper; | import com.ycwl.basic.mapper.SourceMapper; | ||||||
| import com.ycwl.basic.model.mobile.order.IsBuyRespVO; | import com.ycwl.basic.model.mobile.order.IsBuyRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.device.entity.DeviceEntity; | ||||||
| import com.ycwl.basic.model.pc.face.entity.FaceEntity; | import com.ycwl.basic.model.pc.face.entity.FaceEntity; | ||||||
| import com.ycwl.basic.model.pc.face.resp.FaceRespVO; | import com.ycwl.basic.model.pc.face.resp.FaceRespVO; | ||||||
| import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLog; | import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLog; | ||||||
| import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord; | import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord; | ||||||
| import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; | import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; | ||||||
| import com.ycwl.basic.model.pc.faceSample.req.FaceSampleReqQuery; |  | ||||||
| import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO; | import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO; | ||||||
| import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; | import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; | ||||||
| import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; |  | ||||||
| import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; |  | ||||||
| import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; | import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; | ||||||
| import com.ycwl.basic.model.pc.source.entity.SourceEntity; | import com.ycwl.basic.model.pc.source.entity.SourceEntity; | ||||||
| import com.ycwl.basic.model.task.resp.AddFaceSampleRespVo; | import com.ycwl.basic.model.task.resp.AddFaceSampleRespVo; | ||||||
| import com.ycwl.basic.model.task.resp.SearchFaceRespVo; | import com.ycwl.basic.model.task.resp.SearchFaceRespVo; | ||||||
| import com.ycwl.basic.ratelimiter.FixedRateLimiter; | import com.ycwl.basic.ratelimiter.FixedRateLimiter; | ||||||
| import com.ycwl.basic.ratelimiter.SlidingWindowRateLimiter; | 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.task.TaskFaceService; | import com.ycwl.basic.service.task.TaskFaceService; | ||||||
| @@ -55,7 +50,6 @@ import lombok.extern.slf4j.Slf4j; | |||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||||
| import org.springframework.data.redis.core.RedisTemplate; | import org.springframework.data.redis.core.RedisTemplate; | ||||||
| import org.springframework.scheduling.annotation.Scheduled; |  | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import com.aliyuncs.DefaultAcsClient; | import com.aliyuncs.DefaultAcsClient; | ||||||
| import com.aliyuncs.IAcsClient; | import com.aliyuncs.IAcsClient; | ||||||
| @@ -103,6 +97,8 @@ public class TaskFaceServiceImpl implements TaskFaceService { | |||||||
|  |  | ||||||
|     @Autowired |     @Autowired | ||||||
|     private ScenicRepository scenicRepository; |     private ScenicRepository scenicRepository; | ||||||
|  |     @Autowired | ||||||
|  |     private DeviceRepository deviceRepository; | ||||||
|  |  | ||||||
|     private IAcsClient getClient() { |     private IAcsClient getClient() { | ||||||
|         DefaultProfile profile = DefaultProfile.getProfile( |         DefaultProfile profile = DefaultProfile.getProfile( | ||||||
| @@ -195,29 +191,13 @@ public class TaskFaceServiceImpl implements TaskFaceService { | |||||||
|             if (matchList.get(0).getFaceItems().isEmpty()) { |             if (matchList.get(0).getFaceItems().isEmpty()) { | ||||||
|                 return respVo; |                 return respVo; | ||||||
|             } |             } | ||||||
|             List<MatchLocalRecord> records = matchList.get(0).getFaceItems().stream() |             List<SearchFaceResponse.Data.MatchListItem.FaceItemsItem> records = matchList.get(0).getFaceItems(); | ||||||
|                     .map(item -> { |             log.setMatchRawRecord(records); | ||||||
|                         MatchLocalRecord record = new MatchLocalRecord(); |  | ||||||
|                         record.setIdStr(item.getExtraData()); |  | ||||||
|                         record.setFaceSampleId(Long.parseLong(item.getExtraData())); |  | ||||||
|                         if (StringUtils.isNumeric(item.getDbName())) { |  | ||||||
|                             FaceSampleEntity faceSample = faceRepository.getFaceSample(record.getFaceSampleId()); |  | ||||||
|                             if (faceSample != null) { |  | ||||||
|                                 record.setFaceUrl(faceSample.getFaceUrl()); |  | ||||||
|                                 record.setShotDate(faceSample.getCreateAt()); |  | ||||||
|                             } |  | ||||||
|                         } else { |  | ||||||
|                             record.setFaceUrl(getFaceUrl(record.getFaceSampleId())); |  | ||||||
|                         } |  | ||||||
|                         record.setScore(item.getScore()); |  | ||||||
|                         record.setConfidence(item.getConfidence()); |  | ||||||
|                         return record; |  | ||||||
|                     }) |  | ||||||
|                     .collect(Collectors.toList()); |  | ||||||
|             log.matchLocalRecord(records); |  | ||||||
|             List<Long> faceSampleIds = records.stream() |             List<Long> faceSampleIds = records.stream() | ||||||
|                     .filter(record -> record.getScore() > 0.525F) |                     .filter(record -> record.getScore() > 0.525F) | ||||||
|                     .map(MatchLocalRecord::getFaceSampleId) |                     .map(SearchFaceResponse.Data.MatchListItem.FaceItemsItem::getExtraData) | ||||||
|  |                     .filter(StringUtils::isNumeric) | ||||||
|  |                     .map(Long::valueOf) | ||||||
|                     .collect(Collectors.toList()); |                     .collect(Collectors.toList()); | ||||||
|             respVo.setFirstMatchRate(matchList.get(0).getFaceItems().get(0).getScore()); |             respVo.setFirstMatchRate(matchList.get(0).getFaceItems().get(0).getScore()); | ||||||
|             respVo.setSampleListIds(faceSampleIds); |             respVo.setSampleListIds(faceSampleIds); | ||||||
| @@ -227,7 +207,33 @@ public class TaskFaceServiceImpl implements TaskFaceService { | |||||||
|             e.printStackTrace(); |             e.printStackTrace(); | ||||||
|             throw new BaseException(e.getMessage()); |             throw new BaseException(e.getMessage()); | ||||||
|         } finally { |         } finally { | ||||||
|             logMapper.insert(log); |             new Thread(() -> { | ||||||
|  |                 if (log.getMatchRawRecord() != null) { | ||||||
|  |                     List<MatchLocalRecord> collect = log.getMatchRawRecord().parallelStream().map(item -> { | ||||||
|  |                         MatchLocalRecord record = new MatchLocalRecord(); | ||||||
|  |                         record.setIdStr(item.getExtraData()); | ||||||
|  |                         record.setFaceSampleId(Long.parseLong(item.getExtraData())); | ||||||
|  |                         if (StringUtils.isNumeric(item.getDbName())) { | ||||||
|  |                             FaceSampleEntity faceSample = faceRepository.getFaceSample(record.getFaceSampleId()); | ||||||
|  |                             if (faceSample != null) { | ||||||
|  |                                 DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId()); | ||||||
|  |                                 if (device != null) { | ||||||
|  |                                     record.setDeviceName(device.getName()); | ||||||
|  |                                 } | ||||||
|  |                                 record.setFaceUrl(faceSample.getFaceUrl()); | ||||||
|  |                                 record.setShotDate(faceSample.getCreateAt()); | ||||||
|  |                             } | ||||||
|  |                         } else { | ||||||
|  |                             record.setFaceUrl(getFaceUrl(record.getFaceSampleId())); | ||||||
|  |                         } | ||||||
|  |                         record.setScore(item.getScore()); | ||||||
|  |                         record.setConfidence(item.getConfidence()); | ||||||
|  |                         return record; | ||||||
|  |                     }).collect(Collectors.toList()); | ||||||
|  |                     log.setMatchLocalRecord(JSON.toJSONString(collect)); | ||||||
|  |                 } | ||||||
|  |                 logMapper.insert(log); | ||||||
|  |             }).start(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -289,20 +295,6 @@ public class TaskFaceServiceImpl implements TaskFaceService { | |||||||
|             sampleStoreDay = 7; |             sampleStoreDay = 7; | ||||||
|         } |         } | ||||||
|         Date endDate = DateUtils.addDateDays(new Date(), -(sampleStoreDay + 1)); |         Date endDate = DateUtils.addDateDays(new Date(), -(sampleStoreDay + 1)); | ||||||
|         List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntity(scenicId, endDate); |  | ||||||
|         if (faceSampleList.isEmpty()) { |  | ||||||
|             log.info("当前景区{},人脸样本为空", scenicId); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         faceSampleList.forEach(faceSample -> { |  | ||||||
|             boolean success = deleteFaceSample(String.valueOf(scenicId), generateEntityId(faceSample)); |  | ||||||
|             if (success) { |  | ||||||
|                 log.info("当前景区{},人脸样本ID{},删除成功", scenicId, faceSample.getId()); |  | ||||||
|                 faceSampleMapper.deleteById(faceSample.getId()); |  | ||||||
|             } else { |  | ||||||
|                 log.info("当前景区{},人脸样本ID{},删除失败", scenicId, faceSample.getId()); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         ListFaceEntitiesRequest listFaceEntitiesRequest = new ListFaceEntitiesRequest(); |         ListFaceEntitiesRequest listFaceEntitiesRequest = new ListFaceEntitiesRequest(); | ||||||
|         listFaceEntitiesRequest.setDbName(String.valueOf(scenicId)); |         listFaceEntitiesRequest.setDbName(String.valueOf(scenicId)); | ||||||
|         listFaceEntitiesRequest.setOrder("asc"); |         listFaceEntitiesRequest.setOrder("asc"); | ||||||
| @@ -342,6 +334,20 @@ public class TaskFaceServiceImpl implements TaskFaceService { | |||||||
|             } |             } | ||||||
|         } catch (Exception ignored) { |         } catch (Exception ignored) { | ||||||
|         } |         } | ||||||
|  |         List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntityBeforeDate(scenicId, endDate); | ||||||
|  |         if (faceSampleList.isEmpty()) { | ||||||
|  |             log.info("当前景区{},人脸样本为空", scenicId); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         faceSampleList.forEach(faceSample -> { | ||||||
|  |             boolean success = deleteFaceSample(String.valueOf(scenicId), generateEntityId(faceSample)); | ||||||
|  |             if (success) { | ||||||
|  |                 log.info("当前景区{},人脸样本ID{},删除成功", scenicId, faceSample.getId()); | ||||||
|  |                 faceSampleMapper.deleteById(faceSample.getId()); | ||||||
|  |             } else { | ||||||
|  |                 log.info("当前景区{},人脸样本ID{},删除失败", scenicId, faceSample.getId()); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -345,7 +345,8 @@ public class TaskTaskServiceImpl implements TaskService { | |||||||
|         if (templateList == null || templateList.isEmpty()) { |         if (templateList == null || templateList.isEmpty()) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) { |         if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine()) || Integer.valueOf(4).equals(scenicConfig.getBookRoutine())) { | ||||||
|  |             // 生成全部视频的逻辑 | ||||||
|             templateList.forEach(template -> { |             templateList.forEach(template -> { | ||||||
|                 createTaskByFaceIdAndTempalteId(faceId, template.getId(), 1); |                 createTaskByFaceIdAndTempalteId(faceId, template.getId(), 1); | ||||||
|             }); |             }); | ||||||
|   | |||||||
| @@ -90,7 +90,7 @@ public class DynamicTaskGenerator { | |||||||
|         queue.add(new Task(faceSampleId, createTime)); |         queue.add(new Task(faceSampleId, createTime)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Scheduled(fixedDelay = 500L) |     @Scheduled(fixedDelay = 1000L) | ||||||
|     public void doTask() { |     public void doTask() { | ||||||
|         Task task = queue.poll(); |         Task task = queue.poll(); | ||||||
|         if (task == null) { |         if (task == null) { | ||||||
| @@ -111,7 +111,7 @@ public class DynamicTaskGenerator { | |||||||
|             log.debug("当前景区{},无配置", faceSample.getScenicId()); |             log.debug("当前景区{},无配置", faceSample.getScenicId()); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         if (!Integer.valueOf(1).equals(scenicConfig.getBookRoutine()) && !Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) { |         if (!Integer.valueOf(5).equals(scenicConfig.getBookRoutine())) { | ||||||
|             log.debug("当前景区{}未启用预约流程,跳过", faceSample.getScenicId()); |             log.debug("当前景区{}未启用预约流程,跳过", faceSample.getScenicId()); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -3,10 +3,15 @@ package com.ycwl.basic.task; | |||||||
| import com.ycwl.basic.mapper.FaceSampleMapper; | import com.ycwl.basic.mapper.FaceSampleMapper; | ||||||
| import com.ycwl.basic.mapper.ScenicMapper; | import com.ycwl.basic.mapper.ScenicMapper; | ||||||
| import com.ycwl.basic.mapper.SourceMapper; | import com.ycwl.basic.mapper.SourceMapper; | ||||||
|  | import com.ycwl.basic.mapper.VideoMapper; | ||||||
| import com.ycwl.basic.model.pc.faceSample.req.FaceSampleReqQuery; | import com.ycwl.basic.model.pc.faceSample.req.FaceSampleReqQuery; | ||||||
| import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO; | import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; | ||||||
| import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; | import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; | ||||||
| import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; | import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.video.req.VideoReqQuery; | ||||||
|  | import com.ycwl.basic.model.pc.video.resp.VideoRespVO; | ||||||
|  | import com.ycwl.basic.repository.ScenicRepository; | ||||||
| import com.ycwl.basic.service.task.TaskFaceService; | import com.ycwl.basic.service.task.TaskFaceService; | ||||||
| import com.ycwl.basic.storage.StorageFactory; | import com.ycwl.basic.storage.StorageFactory; | ||||||
| import com.ycwl.basic.storage.adapters.IStorageAdapter; | import com.ycwl.basic.storage.adapters.IStorageAdapter; | ||||||
| @@ -31,6 +36,10 @@ public class FaceCleaner { | |||||||
|     private FaceSampleMapper faceSampleMapper; |     private FaceSampleMapper faceSampleMapper; | ||||||
|     @Autowired |     @Autowired | ||||||
|     private SourceMapper sourceMapper; |     private SourceMapper sourceMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private VideoMapper videoMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private ScenicRepository scenicRepository; | ||||||
|  |  | ||||||
|     @Scheduled(cron = "0 0 4 * * ?") |     @Scheduled(cron = "0 0 4 * * ?") | ||||||
|     public void clean(){ |     public void clean(){ | ||||||
| @@ -44,11 +53,43 @@ public class FaceCleaner { | |||||||
|  |  | ||||||
|     @Scheduled(cron = "0 0 3 * * ?") |     @Scheduled(cron = "0 0 3 * * ?") | ||||||
|     public void deleteExpiredSource(){ |     public void deleteExpiredSource(){ | ||||||
|  |         ScenicReqQuery scenicQuery = new ScenicReqQuery(); | ||||||
|  |         List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery); | ||||||
|  |         scenicList.parallelStream().forEach(scenic -> { | ||||||
|  |             ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId()); | ||||||
|  |             if (scenicConfig == null) { | ||||||
|  |                 log.info("当前景区{},无配置信息", scenic.getName()); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             int imageSourceExpireDay = 7; | ||||||
|  |             int videoSourceExpireDay = 7; | ||||||
|  |             if (scenicConfig.getImageSourceStoreDay() != null) { | ||||||
|  |                 imageSourceExpireDay = scenicConfig.getImageSourceStoreDay(); | ||||||
|  |             } else { | ||||||
|  |                 log.info("当前景区{},原始素材保存天数未设置,默认7天", scenic.getName()); | ||||||
|  |             } | ||||||
|  |             if (scenicConfig.getVideoSourceStoreDay() != null) { | ||||||
|  |                 videoSourceExpireDay = scenicConfig.getVideoSourceStoreDay(); | ||||||
|  |             } else { | ||||||
|  |                 log.info("当前景区{},原始素材保存天数未设置,默认7天", scenic.getName()); | ||||||
|  |             } | ||||||
|  |             if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceVideo())) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceImage())) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             log.info("当前景区{},开始删除原始素材", scenic.getName()); | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Scheduled(cron = "0 0 5 * * ?") |     @Scheduled(cron = "0 0 5 * * ?") | ||||||
|     public void clear(){ |     public void clearOss(){ | ||||||
|  |         cleanFaceSampleOss(); | ||||||
|  |         cleanSourceOss(); | ||||||
|  |         cleanVideoOss(); | ||||||
|  |     } | ||||||
|  |     private void cleanFaceSampleOss() { | ||||||
|         log.info("开始清理人脸文件"); |         log.info("开始清理人脸文件"); | ||||||
|         List<FaceSampleRespVO> faceSampleRespVOS = faceSampleMapper.list(new FaceSampleReqQuery()); |         List<FaceSampleRespVO> faceSampleRespVOS = faceSampleMapper.list(new FaceSampleReqQuery()); | ||||||
|         IStorageAdapter adapter = StorageFactory.use("faces"); |         IStorageAdapter adapter = StorageFactory.use("faces"); | ||||||
| @@ -60,4 +101,20 @@ public class FaceCleaner { | |||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |     private void cleanSourceOss() { | ||||||
|  |     } | ||||||
|  |     private void cleanVideoOss() { | ||||||
|  |         log.info("开始清理视频文件"); | ||||||
|  |         List<VideoRespVO> videoRespVOS = videoMapper.list(new VideoReqQuery()); | ||||||
|  |         IStorageAdapter adapter = StorageFactory.use("video"); | ||||||
|  |         List<StorageFileObject> fileObjectList = adapter.listDir(""); | ||||||
|  |         fileObjectList.parallelStream().forEach(fileObject -> { | ||||||
|  |             if (videoRespVOS.parallelStream().noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){ | ||||||
|  |                 log.info("删除视频文件:{}", fileObject); | ||||||
|  |                 adapter.deleteFile(fileObject.getFullPath()); | ||||||
|  |             } else { | ||||||
|  |                 log.info("视频文件存在关系:{},未删除", fileObject); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,18 +1,17 @@ | |||||||
| package com.ycwl.basic.task; | package com.ycwl.basic.task; | ||||||
|  |  | ||||||
| import com.ycwl.basic.biz.OrderBiz; | import com.ycwl.basic.biz.OrderBiz; | ||||||
|  | import com.ycwl.basic.biz.TaskStatusBiz; | ||||||
| import com.ycwl.basic.device.DeviceFactory; | import com.ycwl.basic.device.DeviceFactory; | ||||||
| import com.ycwl.basic.device.entity.common.FileObject; | import com.ycwl.basic.device.entity.common.FileObject; | ||||||
| import com.ycwl.basic.device.operator.IDeviceStorageOperator; | import com.ycwl.basic.device.operator.IDeviceStorageOperator; | ||||||
| import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; | import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; | ||||||
| import com.ycwl.basic.repository.DeviceRepository; | import com.ycwl.basic.repository.DeviceRepository; | ||||||
| import com.ycwl.basic.mapper.DeviceMapper; |  | ||||||
| import com.ycwl.basic.mapper.FaceSampleMapper; | import com.ycwl.basic.mapper.FaceSampleMapper; | ||||||
| import com.ycwl.basic.mapper.SourceMapper; | import com.ycwl.basic.mapper.SourceMapper; | ||||||
| import com.ycwl.basic.model.mobile.order.IsBuyRespVO; | import com.ycwl.basic.model.mobile.order.IsBuyRespVO; | ||||||
| import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity; | import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity; | ||||||
| import com.ycwl.basic.model.pc.device.entity.DeviceEntity; | import com.ycwl.basic.model.pc.device.entity.DeviceEntity; | ||||||
| import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO; |  | ||||||
| import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; | import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; | ||||||
| import com.ycwl.basic.model.pc.source.entity.SourceEntity; | import com.ycwl.basic.model.pc.source.entity.SourceEntity; | ||||||
| import com.ycwl.basic.repository.TemplateRepository; | import com.ycwl.basic.repository.TemplateRepository; | ||||||
| @@ -34,7 +33,6 @@ import java.io.InputStreamReader; | |||||||
| import java.math.BigDecimal; | import java.math.BigDecimal; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Comparator; |  | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.concurrent.LinkedBlockingQueue; | import java.util.concurrent.LinkedBlockingQueue; | ||||||
| @@ -57,6 +55,8 @@ public class VideoPieceGetter { | |||||||
|     private OrderBiz orderBiz; |     private OrderBiz orderBiz; | ||||||
|     @Autowired |     @Autowired | ||||||
|     private TemplateRepository templateRepository; |     private TemplateRepository templateRepository; | ||||||
|  |     @Autowired | ||||||
|  |     private TaskStatusBiz taskStatusBiz; | ||||||
|  |  | ||||||
|     @Data |     @Data | ||||||
|     public static class Task { |     public static class Task { | ||||||
| @@ -97,6 +97,9 @@ public class VideoPieceGetter { | |||||||
|         } else { |         } else { | ||||||
|             templatePlaceholder = null; |             templatePlaceholder = null; | ||||||
|         } |         } | ||||||
|  |         if (task.faceId != null) { | ||||||
|  |             taskStatusBiz.setFaceCutStatus(task.faceId, 0); | ||||||
|  |         } | ||||||
|         AtomicBoolean invoke = new AtomicBoolean(false); |         AtomicBoolean invoke = new AtomicBoolean(false); | ||||||
|         List<String> currentPlaceholder = new ArrayList<>(); |         List<String> currentPlaceholder = new ArrayList<>(); | ||||||
|         List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds()); |         List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds()); | ||||||
| @@ -113,7 +116,7 @@ public class VideoPieceGetter { | |||||||
|                 .stream() |                 .stream() | ||||||
|                 .parallel() |                 .parallel() | ||||||
|                 .forEach(faceSampleList -> { |                 .forEach(faceSampleList -> { | ||||||
|                     faceSampleList.forEach(faceSample -> { |                     faceSampleList.parallelStream().forEach(faceSample -> { | ||||||
|                         DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId()); |                         DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId()); | ||||||
|                         DeviceConfigEntity config = deviceRepository.getDeviceConfig(faceSample.getDeviceId()); |                         DeviceConfigEntity config = deviceRepository.getDeviceConfig(faceSample.getDeviceId()); | ||||||
|  |  | ||||||
| @@ -245,6 +248,9 @@ public class VideoPieceGetter { | |||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
|                 }); |                 }); | ||||||
|  |         if (task.faceId != null) { | ||||||
|  |             taskStatusBiz.setFaceCutStatus(task.faceId, 1); | ||||||
|  |         } | ||||||
|         if (null != task.getCallback()) { |         if (null != task.getCallback()) { | ||||||
|             if (!invoke.get()) { |             if (!invoke.get()) { | ||||||
|                 invoke.set(true); |                 invoke.set(true); | ||||||
|   | |||||||
| @@ -4,10 +4,14 @@ import cn.hutool.core.date.DateUtil; | |||||||
| import com.ycwl.basic.biz.TemplateBiz; | import com.ycwl.basic.biz.TemplateBiz; | ||||||
| import com.ycwl.basic.mapper.FaceMapper; | import com.ycwl.basic.mapper.FaceMapper; | ||||||
| import com.ycwl.basic.mapper.FaceSampleMapper; | import com.ycwl.basic.mapper.FaceSampleMapper; | ||||||
|  | import com.ycwl.basic.mapper.ScenicMapper; | ||||||
| import com.ycwl.basic.mapper.TemplateMapper; | import com.ycwl.basic.mapper.TemplateMapper; | ||||||
| import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO; | import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO; | ||||||
| import com.ycwl.basic.model.pc.face.req.FaceReqQuery; | import com.ycwl.basic.model.pc.face.req.FaceReqQuery; | ||||||
| import com.ycwl.basic.model.pc.face.resp.FaceRespVO; | import com.ycwl.basic.model.pc.face.resp.FaceRespVO; | ||||||
|  | import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; | ||||||
|  | import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; | ||||||
|  | import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; | ||||||
| import com.ycwl.basic.model.task.resp.SearchFaceRespVo; | import com.ycwl.basic.model.task.resp.SearchFaceRespVo; | ||||||
| import com.ycwl.basic.repository.ScenicRepository; | import com.ycwl.basic.repository.ScenicRepository; | ||||||
| import com.ycwl.basic.repository.TemplateRepository; | import com.ycwl.basic.repository.TemplateRepository; | ||||||
| @@ -20,6 +24,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; | |||||||
| import org.springframework.scheduling.annotation.Scheduled; | import org.springframework.scheduling.annotation.Scheduled; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
|  | import java.util.Calendar; | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| @@ -38,31 +43,71 @@ public class VideoTaskGenerator { | |||||||
|     private TaskTaskServiceImpl taskTaskService; |     private TaskTaskServiceImpl taskTaskService; | ||||||
|     @Autowired |     @Autowired | ||||||
|     private TemplateMapper templateMapper; |     private TemplateMapper templateMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private ScenicMapper scenicMapper; | ||||||
|  |     @Autowired | ||||||
|  |     private ScenicRepository scenicRepository; | ||||||
|  |  | ||||||
|     // TODO: 可配置,现在赶时间暂时写死 |     // TODO: 可配置,现在赶时间暂时写死 | ||||||
|  |  | ||||||
|     @Scheduled(cron = "0 0 18 * * *") |     @Scheduled(cron = "0 0 * * * *") | ||||||
|     public void generateVideoTask() { |     public void generateVideoTask() { | ||||||
|         // 指定,获取指定日期的未完成人脸样本,并生成任务 |         List<ScenicRespVO> scenicList = scenicMapper.list(new ScenicReqQuery()); | ||||||
|         Long scenicId = 3946669713328836608L; |         if (scenicList.isEmpty()) { | ||||||
|         List<ContentPageVO> contentList = templateMapper.listFor(scenicId); |  | ||||||
|         if (contentList.isEmpty()) { |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         Long templateId = contentList.get(0).getTemplateId(); |  | ||||||
|         FaceReqQuery query = new FaceReqQuery(); |         Calendar calendar = Calendar.getInstance(); | ||||||
|         query.setScenicId(scenicId); |         calendar.setTime(new Date()); | ||||||
|         query.setStartTime(DateUtil.beginOfDay(new Date())); |         int currentHour = calendar.get(Calendar.HOUR_OF_DAY); | ||||||
|         query.setEndTime(DateUtil.endOfDay(new Date())); |         calendar.clear(); | ||||||
|         List<FaceRespVO> list = faceMapper.list(query); |         scenicList.parallelStream().forEach(scenic -> { | ||||||
|         list.stream().parallel().forEach(face -> { |             Long scenicId = scenic.getId(); | ||||||
|             taskFaceService.searchFace(face.getId()); |             ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId); | ||||||
|             boolean canAutoGenerate = templateBiz.determineTemplateCanAutoGenerate(templateId, face.getId(), false); |             if (scenicConfig == null) { | ||||||
|             if (canAutoGenerate) { |                 log.info("当前景区{},无配置信息", scenic.getName()); | ||||||
|                 log.info("task callback: 自动生成"); |                 return; | ||||||
|                 taskTaskService.forceCreateTaskByFaceIdAndTempalteId(face.getId(), templateId); |             } | ||||||
|             } else { |             if (Integer.valueOf(1).equals(scenicConfig.getBookRoutine()) || Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) { | ||||||
|                 log.info("task callback: 不自动生成"); |                 Integer hour = scenicConfig.getForceFinishTime(); | ||||||
|  |                 if (hour != currentHour) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 // 定时逻辑 | ||||||
|  |                 List<ContentPageVO> contentList = templateMapper.listFor(scenicId); | ||||||
|  |                 if (contentList.isEmpty()) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 FaceReqQuery query = new FaceReqQuery(); | ||||||
|  |                 query.setScenicId(scenicId); | ||||||
|  |                 query.setStartTime(DateUtil.beginOfDay(new Date())); | ||||||
|  |                 query.setEndTime(DateUtil.endOfDay(new Date())); | ||||||
|  |                 List<FaceRespVO> list = faceMapper.list(query); | ||||||
|  |                 list.stream().parallel().forEach(face -> { | ||||||
|  |                     taskFaceService.searchFace(face.getId()); | ||||||
|  |                     if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) { | ||||||
|  |                         // 全部生成 | ||||||
|  |                         contentList.forEach(content -> { | ||||||
|  |                             Long templateId = content.getTemplateId(); | ||||||
|  |                             boolean canAutoGenerate = templateBiz.determineTemplateCanAutoGenerate(templateId, face.getId(), false); | ||||||
|  |                             if (canAutoGenerate) { | ||||||
|  |                                 log.info("task callback: 自动生成"); | ||||||
|  |                                 taskTaskService.forceCreateTaskByFaceIdAndTempalteId(face.getId(), templateId); | ||||||
|  |                             } else { | ||||||
|  |                                 log.info("task callback: 不自动生成"); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                     } else { | ||||||
|  |                         Long templateId = contentList.get(0).getTemplateId(); | ||||||
|  |                         boolean canAutoGenerate = templateBiz.determineTemplateCanAutoGenerate(templateId, face.getId(), false); | ||||||
|  |                         if (canAutoGenerate) { | ||||||
|  |                             log.info("task callback: 自动生成"); | ||||||
|  |                             taskTaskService.forceCreateTaskByFaceIdAndTempalteId(face.getId(), templateId); | ||||||
|  |                         } else { | ||||||
|  |                             log.info("task callback: 不自动生成"); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -36,7 +36,8 @@ | |||||||
|             online_check = #{onlineCheck}, |             online_check = #{onlineCheck}, | ||||||
|             online_max_interval = #{onlineMaxInterval}, |             online_max_interval = #{onlineMaxInterval}, | ||||||
|             cut_pre = #{cutPre}, |             cut_pre = #{cutPre}, | ||||||
|             cut_post = #{cutPost} |             cut_post = #{cutPost}, | ||||||
|  |             enable_pre_book = #{enablePreBook} | ||||||
|         where id = #{id} |         where id = #{id} | ||||||
|     </update> |     </update> | ||||||
|     <update id="updateEntity"> |     <update id="updateEntity"> | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ | |||||||
|         from face |         from face | ||||||
|         where id = #{id} |         where id = #{id} | ||||||
|     </select> |     </select> | ||||||
|     <select id="getByMemberId" resultType="com.ycwl.basic.model.pc.face.resp.FaceRespVO"> |     <select id="getLatestByMemberId" resultType="com.ycwl.basic.model.pc.face.resp.FaceRespVO"> | ||||||
|         select id, scenic_id, member_id, face_url,score, match_sample_ids, first_match_rate, match_result, create_at, update_at |         select id, scenic_id, member_id, face_url,score, match_sample_ids, first_match_rate, match_result, create_at, update_at | ||||||
|         from face |         from face | ||||||
|         where member_id = #{userId} and scenic_id = #{scenicId} |         where member_id = #{userId} and scenic_id = #{scenicId} | ||||||
| @@ -100,4 +100,11 @@ | |||||||
|         where member_id = #{userId} and scenic_id = #{scenicId} |         where member_id = #{userId} and scenic_id = #{scenicId} | ||||||
|         order by update_at desc |         order by update_at desc | ||||||
|     </select> |     </select> | ||||||
|  |     <select id="findLastFaceByScenicAndUserId" resultType="com.ycwl.basic.model.pc.face.resp.FaceRespVO"> | ||||||
|  |         select id, scenic_id, member_id, face_url,score, match_sample_ids, first_match_rate, match_result, create_at, update_at | ||||||
|  |         from face | ||||||
|  |         where member_id = #{userId} and scenic_id = #{scenicId} | ||||||
|  |         order by update_at desc | ||||||
|  |         limit 1 | ||||||
|  |     </select> | ||||||
| </mapper> | </mapper> | ||||||
|   | |||||||
| @@ -101,7 +101,7 @@ | |||||||
|         from face_sample |         from face_sample | ||||||
|         where id = #{id} |         where id = #{id} | ||||||
|     </select> |     </select> | ||||||
|     <select id="listEntity" resultType="com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity"> |     <select id="listEntityBeforeDate" resultType="com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity"> | ||||||
|         select * |         select * | ||||||
|         from face_sample |         from face_sample | ||||||
|         where scenic_id = #{scenicId} and create_at <= #{endDate} |         where scenic_id = #{scenicId} and create_at <= #{endDate} | ||||||
|   | |||||||
| @@ -94,7 +94,8 @@ | |||||||
|             disable_source_video=#{disableSourceVideo}, |             disable_source_video=#{disableSourceVideo}, | ||||||
|             disable_source_image=#{disableSourceImage}, |             disable_source_image=#{disableSourceImage}, | ||||||
|             video_source_store_day=#{videoSourceStoreDay}, |             video_source_store_day=#{videoSourceStoreDay}, | ||||||
|             image_source_store_day=#{imageSourceStoreDay} |             image_source_store_day=#{imageSourceStoreDay}, | ||||||
|  |             force_finish_time=#{forceFinishTime} | ||||||
|         </set> |         </set> | ||||||
|         where id = #{id} |         where id = #{id} | ||||||
|     </update> |     </update> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user