diff --git a/pom.xml b/pom.xml index 7cee79e..b641ab6 100644 --- a/pom.xml +++ b/pom.xml @@ -210,6 +210,12 @@ 4.16.19 + + + com.aliyun + mts20140618 + 5.0.0 + @@ -269,6 +275,17 @@ true + + sonatype-nexus-staging + Sonatype Nexus Staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + true + + + true + + diff --git a/src/main/java/com/ycwl/basic/controller/extern/CustomDeviceController.java b/src/main/java/com/ycwl/basic/controller/extern/CustomDeviceController.java new file mode 100644 index 0000000..6afecdc --- /dev/null +++ b/src/main/java/com/ycwl/basic/controller/extern/CustomDeviceController.java @@ -0,0 +1,83 @@ +package com.ycwl.basic.controller.extern; + +import com.ycwl.basic.annotation.IgnoreToken; +import com.ycwl.basic.model.custom.req.AliyunCallbackReq; +import com.ycwl.basic.model.custom.req.CreateUploadTaskReq; +import com.ycwl.basic.model.custom.req.UploadCompleteReq; +import com.ycwl.basic.model.custom.req.UploadFailedReq; +import com.ycwl.basic.model.custom.resp.CreateUploadTaskResp; +import com.ycwl.basic.service.custom.CustomUploadTaskService; +import com.ycwl.basic.utils.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@RestController +@RequestMapping("/extern/custom-device") +@IgnoreToken +public class CustomDeviceController { + + @Autowired + private CustomUploadTaskService customUploadTaskService; + + @PostMapping("/upload/create") + public ApiResponse createUploadTask(@RequestBody CreateUploadTaskReq req) { + try { + CreateUploadTaskResp resp = customUploadTaskService.createUploadTask(req); + return ApiResponse.success(resp); + } catch (Exception e) { + log.error("创建上传任务失败", e); + return ApiResponse.fail(e.getMessage()); + } + } + + @PostMapping("/upload/complete") + public ApiResponse uploadComplete(@RequestBody UploadCompleteReq req) { + try { + customUploadTaskService.completeUpload(req.getAccessKey(), req.getTaskId()); + return ApiResponse.success("上传完成,人脸识别任务已提交"); + } catch (Exception e) { + log.error("上传完成处理失败", e); + return ApiResponse.fail(e.getMessage()); + } + } + + @PostMapping("/upload/failed") + public ApiResponse uploadFailed(@RequestBody UploadFailedReq req) { + try { + customUploadTaskService.markTaskFailed(req.getAccessKey(), req.getTaskId(), req.getErrorMsg()); + return ApiResponse.success("任务已标记为失败"); + } catch (Exception e) { + log.error("标记任务失败处理异常", e); + return ApiResponse.fail(e.getMessage()); + } + } + + @PostMapping("/aliyun/mps/callback") + public ApiResponse aliyunCallback(@RequestBody AliyunCallbackReq req) { + try { + customUploadTaskService.handleAliyunCallback(req.getJobId(), req.getStatus()); + return ApiResponse.success("回调处理完成"); + } catch (Exception e) { + log.error("阿里云回调处理失败", e); + return ApiResponse.fail(e.getMessage()); + } + } + + @GetMapping("/aliyun/mps/callback") + public ApiResponse aliyunCallback(@RequestParam("jobId") String jobId, @RequestParam("status") String status) { + try { + customUploadTaskService.handleAliyunCallback(jobId, status); + return ApiResponse.success("回调处理完成"); + } catch (Exception e) { + log.error("阿里云回调处理失败", e); + return ApiResponse.fail(e.getMessage()); + } + } +} diff --git a/src/main/java/com/ycwl/basic/mapper/CustomUploadTaskMapper.java b/src/main/java/com/ycwl/basic/mapper/CustomUploadTaskMapper.java new file mode 100644 index 0000000..0abaf8b --- /dev/null +++ b/src/main/java/com/ycwl/basic/mapper/CustomUploadTaskMapper.java @@ -0,0 +1,10 @@ +package com.ycwl.basic.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ycwl.basic.model.custom.entity.CustomUploadTaskEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CustomUploadTaskMapper extends BaseMapper { + CustomUploadTaskEntity getByJobId(String jobId); +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/entity/CustomUploadTaskEntity.java b/src/main/java/com/ycwl/basic/model/custom/entity/CustomUploadTaskEntity.java new file mode 100644 index 0000000..b03d444 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/entity/CustomUploadTaskEntity.java @@ -0,0 +1,32 @@ +package com.ycwl.basic.model.custom.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("custom_upload_task") +public class CustomUploadTaskEntity { + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + private Long scenicId; + + private Long deviceId; + + private String savePath; + + private String status; + + private String jobId; + + private String errorMsg; + + private Date createTime; + + private Date updateTime; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/entity/FaceData.java b/src/main/java/com/ycwl/basic/model/custom/entity/FaceData.java new file mode 100644 index 0000000..12eba7c --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/entity/FaceData.java @@ -0,0 +1,145 @@ +package com.ycwl.basic.model.custom.entity; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class FaceData { + private String category; + private String name; + private List occurrences; + private Double ratio; + + // Getters and setters + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getOccurrences() { + return occurrences; + } + + public void setOccurrences(List occurrences) { + this.occurrences = occurrences; + } + + public Double getRatio() { + return ratio; + } + + public void setRatio(Double ratio) { + this.ratio = ratio; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Occurrence { + @JsonProperty("faceUrl") + private String faceUrl; + + private Double from; + private Position position; + private String scene; + private Double score; + private Double timestamp; + private Double to; + + // Getters and setters + public String getFaceUrl() { + return faceUrl; + } + + public void setFaceUrl(String faceUrl) { + this.faceUrl = faceUrl; + } + + public Double getFrom() { + return from; + } + + public void setFrom(Double from) { + this.from = from; + } + + public Position getPosition() { + return position; + } + + public void setPosition(Position position) { + this.position = position; + } + + public String getScene() { + return scene; + } + + public void setScene(String scene) { + this.scene = scene; + } + + public Double getScore() { + return score; + } + + public void setScore(Double score) { + this.score = score; + } + + public Double getTimestamp() { + return timestamp; + } + + public void setTimestamp(Double timestamp) { + this.timestamp = timestamp; + } + + public Double getTo() { + return to; + } + + public void setTo(Double to) { + this.to = to; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Position { + @JsonProperty("leftTop") + private List leftTop; + + @JsonProperty("rightBottom") + private List rightBottom; + + // Getters and setters + public List getLeftTop() { + return leftTop; + } + + public void setLeftTop(List leftTop) { + this.leftTop = leftTop; + } + + public List getRightBottom() { + return rightBottom; + } + + public void setRightBottom(List rightBottom) { + this.rightBottom = rightBottom; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/req/AliyunCallbackReq.java b/src/main/java/com/ycwl/basic/model/custom/req/AliyunCallbackReq.java new file mode 100644 index 0000000..97830b3 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/req/AliyunCallbackReq.java @@ -0,0 +1,13 @@ +package com.ycwl.basic.model.custom.req; + +import lombok.Data; + +@Data +public class AliyunCallbackReq { + + private String jobId; + + private String pipelineId; + + private String status; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/req/CreateUploadTaskReq.java b/src/main/java/com/ycwl/basic/model/custom/req/CreateUploadTaskReq.java new file mode 100644 index 0000000..2deb79b --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/req/CreateUploadTaskReq.java @@ -0,0 +1,13 @@ +package com.ycwl.basic.model.custom.req; + +import lombok.Data; + +@Data +public class CreateUploadTaskReq { + + private String accessKey; + + private String fileName; + + private String type; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/req/UploadCompleteReq.java b/src/main/java/com/ycwl/basic/model/custom/req/UploadCompleteReq.java new file mode 100644 index 0000000..9adbbe9 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/req/UploadCompleteReq.java @@ -0,0 +1,11 @@ +package com.ycwl.basic.model.custom.req; + +import lombok.Data; + +@Data +public class UploadCompleteReq { + + private String accessKey; + + private Long taskId; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/req/UploadFailedReq.java b/src/main/java/com/ycwl/basic/model/custom/req/UploadFailedReq.java new file mode 100644 index 0000000..737c6ac --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/req/UploadFailedReq.java @@ -0,0 +1,13 @@ +package com.ycwl.basic.model.custom.req; + +import lombok.Data; + +@Data +public class UploadFailedReq { + + private String accessKey; + + private Long taskId; + + private String errorMsg; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/model/custom/resp/CreateUploadTaskResp.java b/src/main/java/com/ycwl/basic/model/custom/resp/CreateUploadTaskResp.java new file mode 100644 index 0000000..bd7547a --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/custom/resp/CreateUploadTaskResp.java @@ -0,0 +1,13 @@ +package com.ycwl.basic.model.custom.resp; + +import lombok.Data; + +@Data +public class CreateUploadTaskResp { + + private Long taskId; + + private String uploadUrl; + + private String savePath; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/service/custom/CustomUploadTaskService.java b/src/main/java/com/ycwl/basic/service/custom/CustomUploadTaskService.java new file mode 100644 index 0000000..14251de --- /dev/null +++ b/src/main/java/com/ycwl/basic/service/custom/CustomUploadTaskService.java @@ -0,0 +1,339 @@ +package com.ycwl.basic.service.custom; + +import com.aliyun.credentials.Client; +import com.aliyun.credentials.models.Config; +import com.aliyun.mts20140618.models.QuerySmarttagJobRequest; +import com.aliyun.mts20140618.models.QuerySmarttagJobResponse; +import com.aliyun.mts20140618.models.QuerySmarttagJobResponseBody; +import com.aliyun.mts20140618.models.SubmitSmarttagJobRequest; +import com.aliyun.mts20140618.models.SubmitSmarttagJobResponse; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter; +import com.ycwl.basic.facebody.entity.AddFaceResp; +import com.ycwl.basic.mapper.DeviceMapper; +import com.ycwl.basic.mapper.CustomUploadTaskMapper; +import com.ycwl.basic.mapper.FaceSampleMapper; +import com.ycwl.basic.mapper.ScenicMapper; +import com.ycwl.basic.mapper.SourceMapper; +import com.ycwl.basic.model.pc.device.entity.DeviceEntity; +import com.ycwl.basic.model.custom.entity.CustomUploadTaskEntity; +import com.ycwl.basic.model.custom.entity.FaceData; +import com.ycwl.basic.model.custom.req.CreateUploadTaskReq; +import com.ycwl.basic.model.custom.resp.CreateUploadTaskResp; +import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; +import com.ycwl.basic.model.pc.source.entity.SourceEntity; +import com.ycwl.basic.service.pc.ScenicService; +import com.ycwl.basic.storage.StorageFactory; +import com.ycwl.basic.storage.adapters.IStorageAdapter; +import com.ycwl.basic.utils.JacksonUtil; +import com.ycwl.basic.utils.SnowFlakeUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Strings; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static com.ycwl.basic.constant.StorageConstant.VIID_FACE; + +@Slf4j +@Service +public class CustomUploadTaskService { + + @Autowired + private CustomUploadTaskMapper customUploadTaskMapper; + + @Autowired + private DeviceMapper deviceMapper; + + @Autowired + private ScenicService scenicService; + @Autowired + private FaceSampleMapper faceSampleMapper; + @Autowired + private SourceMapper sourceMapper; + + private static final ThreadPoolExecutor executor; + static { + executor = new ThreadPoolExecutor(16, 32, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024)); + } + + public CreateUploadTaskResp createUploadTask(CreateUploadTaskReq req) { + if (StringUtils.isBlank(req.getAccessKey())) { + throw new RuntimeException("设备访问密钥不能为空"); + } + + if (StringUtils.isBlank(req.getFileName())) { + throw new RuntimeException("文件名不能为空"); + } + + if (StringUtils.isBlank(req.getType())) { + throw new RuntimeException("上传类型不能为空"); + } + + // 验证设备访问权限 + DeviceEntity device = validateDeviceAccess(req.getAccessKey(), req.getType()); + + long taskId = SnowFlakeUtil.getLongId(); + String savePath = generateSavePath(device.getScenicId(), req.getFileName()); + + CustomUploadTaskEntity task = new CustomUploadTaskEntity(); + task.setId(taskId); + task.setScenicId(device.getScenicId()); + task.setDeviceId(device.getId()); + task.setSavePath(savePath); + task.setStatus("PENDING"); + task.setCreateTime(new Date()); + task.setUpdateTime(new Date()); + + customUploadTaskMapper.insert(task); + + String uploadUrl = generateUploadUrl(savePath); + + CreateUploadTaskResp resp = new CreateUploadTaskResp(); + resp.setTaskId(taskId); + resp.setUploadUrl(uploadUrl); + resp.setSavePath(savePath); + + return resp; + } + + public void completeUpload(String accessKey, Long taskId) { + // 验证设备访问权限 + DeviceEntity device = validateDeviceAccess(accessKey, null); + + CustomUploadTaskEntity task = customUploadTaskMapper.selectById(taskId); + if (task == null) { + throw new RuntimeException("任务不存在"); + } + + // 验证任务属于该设备的景区 + if (!device.getScenicId().equals(task.getScenicId())) { + throw new RuntimeException("无权限操作该任务"); + } + + task.setStatus("UPLOADING"); + task.setUpdateTime(new Date()); + customUploadTaskMapper.updateById(task); + + try { + String jobId = submitSmarttagJob(task.getSavePath()); + + task.setJobId(jobId); + task.setStatus("COMPLETED"); + task.setUpdateTime(new Date()); + customUploadTaskMapper.updateById(task); + + log.info("人脸识别任务提交成功,taskId: {}, jobId: {}", taskId, jobId); + } catch (Exception e) { + task.setStatus("FAILED"); + task.setErrorMsg("人脸识别任务提交失败: " + e.getMessage()); + task.setUpdateTime(new Date()); + customUploadTaskMapper.updateById(task); + + log.error("人脸识别任务提交失败,taskId: {}", taskId, e); + throw new RuntimeException("人脸识别任务提交失败"); + } + } + + public void markTaskFailed(String accessKey, Long taskId, String errorMsg) { + // 验证设备访问权限 + DeviceEntity device = validateDeviceAccess(accessKey, null); + + CustomUploadTaskEntity task = customUploadTaskMapper.selectById(taskId); + if (task == null) { + throw new RuntimeException("任务不存在"); + } + + // 验证任务属于该设备的景区 + if (!device.getScenicId().equals(task.getScenicId())) { + throw new RuntimeException("无权限操作该任务"); + } + + task.setStatus("FAILED"); + task.setErrorMsg(errorMsg); + task.setUpdateTime(new Date()); + customUploadTaskMapper.updateById(task); + + log.info("任务标记为失败,taskId: {}, errorMsg: {}", taskId, errorMsg); + } + + public void handleAliyunCallback(String jobId, String status) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(CustomUploadTaskEntity::getJobId, jobId); + + CustomUploadTaskEntity task = customUploadTaskMapper.selectOne(wrapper); + if (task == null) { + log.warn("未找到对应的上传任务,jobId: {}", jobId); + return; + } + + log.info("收到阿里云回调,jobId: {}, status: {}, taskId: {}", jobId, status, task.getId()); + + handleAliyunMpsJobComplete(jobId); + } + + private String generateSavePath(Long scenicId, String fileName) { + String timestamp = String.valueOf(System.currentTimeMillis()); + String extension = ""; + if (fileName.contains(".")) { + extension = fileName.substring(fileName.lastIndexOf(".")); + } + return String.format("custom-device/%d/%s%s", scenicId, timestamp, extension); + } + + private String generateUploadUrl(String savePath) { + try { + IStorageAdapter adapter = StorageFactory.use(); + + Date expireDate = new Date(System.currentTimeMillis() + 3600 * 1000); + return adapter.getUrlForUpload(expireDate, null, savePath); + } catch (Exception e) { + log.error("生成上传URL失败,savePath: {}", savePath, e); + throw new RuntimeException("生成上传URL失败"); + } + } + + private String submitSmarttagJob(String inputPath) { + try { + log.info("提交人脸识别任务,inputPath: {}", inputPath); + String jobId = createAliyunMtsTask(inputPath); + executor.execute(() -> loopQueryJobStatus(jobId)); + return jobId; + } catch (Exception e) { + log.error("提交人脸识别任务失败,inputPath: {}", inputPath, e); + throw new RuntimeException("提交人脸识别任务失败: " + e.getMessage()); + } + } + + private DeviceEntity validateDeviceAccess(String accessKey, String type) { + if (StringUtils.isBlank(accessKey)) { + throw new RuntimeException("设备访问密钥不能为空"); + } + + DeviceEntity device = deviceMapper.getByDeviceNo(accessKey); + if (device == null || device.getStatus() != 1) { + throw new RuntimeException("无效的设备访问密钥或设备已被禁用"); + } + + return device; + } + + private String createAliyunMtsTask(String inputPath) { + try { + // 创建任务 + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() + .setAccessKeyId("LTAI5tCWgYJz9kZvvh2KVhkH") + .setAccessKeySecret("RObb3EZ1YsmR63ul1gh7tnIfT1foOc"); + config.endpoint = "mts.cn-shanghai.aliyuncs.com"; + com.aliyun.mts20140618.Client client = new com.aliyun.mts20140618.Client(config); + SubmitSmarttagJobRequest request = new SubmitSmarttagJobRequest(); + request.setPipelineId("d791f854652e466bad66301e5c97b7bb"); + request.setTemplateId("a004e08402bd496a8a9adbb2ba920973"); + request.setTitle(String.valueOf(System.currentTimeMillis())); + request.setNotifyUrl("https://zhentuai.com/extern/custom-device/aliyun/mps/callback"); + request.setInput(String.format("oss://frametour-assets/user-assets/%s", inputPath)); + com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions(); + SubmitSmarttagJobResponse submitSmarttagJobResponse = client.submitSmarttagJobWithOptions(request, runtime); + return submitSmarttagJobResponse.getBody().jobId; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void loopQueryJobStatus(String jobId) { + try { + Thread.sleep(10000L); + } catch (InterruptedException e) { + return; + } + handleAliyunMpsJobComplete(jobId); + } + + + public void handleAliyunMpsJobComplete(String jobId) { + CustomUploadTaskEntity task = customUploadTaskMapper.getByJobId(jobId); + try { + // 查询任务 + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() + .setAccessKeyId("LTAI5tCWgYJz9kZvvh2KVhkH") + .setAccessKeySecret("RObb3EZ1YsmR63ul1gh7tnIfT1foOc"); + config.endpoint = "mts.cn-shanghai.aliyuncs.com"; + com.aliyun.mts20140618.Client client = new com.aliyun.mts20140618.Client(config); + QuerySmarttagJobRequest request = new QuerySmarttagJobRequest(); + request.setJobId(jobId); + QuerySmarttagJobResponse response = client.querySmarttagJob(request); + if (Strings.CI.equals(response.getBody().jobStatus, "Fail")) { + log.error("智能标签任务失败"); + return; + } + if (!Strings.CI.equals(response.getBody().jobStatus, "Success")) { + log.info("jobId:{} 智能标签任务等待查询!", jobId); + executor.execute(() -> loopQueryJobStatus(jobId)); + return; + } + List result = response.getBody().results.getResult(); + QuerySmarttagJobResponseBody.QuerySmarttagJobResponseBodyResultsResult first = result.stream() + .filter(r -> "VideoLabel".equals(r.getType())) + .findFirst() + .orElse(null); + if (first == null) { + return; + } + List persons = JacksonUtil.getArray(first.getData(), "persons", FaceData.class); + if (persons == null || persons.isEmpty()) { + return; + } + IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(task.getScenicId()); + IStorageAdapter storageAdapter = StorageFactory.use(); + persons.stream() + .filter(p -> p.getRatio() > 0.1) + .map(FaceData::getOccurrences) + .filter(Objects::nonNull) + .forEach(occurrences -> { + if (occurrences.isEmpty()) { + return; + } + Long newFaceSampleId = SnowFlakeUtil.getLongId(); + String faceUrl = occurrences.getFirst().getFaceUrl(); + FaceSampleEntity faceSample = new FaceSampleEntity(); + faceSample.setId(newFaceSampleId); + faceSample.setScenicId(task.getScenicId()); + faceSample.setDeviceId(task.getDeviceId()); + faceSample.setStatus(1); + faceSample.setCreateAt(task.getCreateTime()); + faceSample.setFaceUrl(faceUrl); + faceSampleMapper.add(faceSample); + faceBodyAdapter.assureFaceDb(task.getScenicId().toString()); + AddFaceResp addFaceResp = faceBodyAdapter.addFace(task.getScenicId().toString(), newFaceSampleId.toString(), faceUrl, newFaceSampleId.toString()); + if (addFaceResp != null) { + faceSample.setScore(addFaceResp.getScore()); + faceSampleMapper.updateScore(faceSample.getId(), addFaceResp.getScore()); + } + SourceEntity source = new SourceEntity(); + source.setId(SnowFlakeUtil.getLongId()); + source.setDeviceId(task.getDeviceId()); + source.setScenicId(task.getScenicId()); + source.setFaceSampleId(newFaceSampleId); + source.setCreateTime(task.getCreateTime()); + source.setType(1); + source.setUrl(faceUrl); + source.setVideoUrl(storageAdapter.getUrl(task.getSavePath())); + sourceMapper.add(source); + }); + System.out.println(JacksonUtil.toJson(persons)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} \ No newline at end of file diff --git a/src/main/resources/mapper/CustomUploadTaskMapper.xml b/src/main/resources/mapper/CustomUploadTaskMapper.xml new file mode 100644 index 0000000..7c34521 --- /dev/null +++ b/src/main/resources/mapper/CustomUploadTaskMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceTest.java b/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceTest.java new file mode 100644 index 0000000..dae2229 --- /dev/null +++ b/src/test/java/com/ycwl/basic/service/custom/CustomUploadTaskServiceTest.java @@ -0,0 +1,13 @@ +package com.ycwl.basic.service.custom; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CustomUploadTaskServiceTest { + + @Test + void handleAliyunMpsJobComplete() { + new CustomUploadTaskService().handleAliyunMpsJobComplete("2b9142e3efa73d3ea8edd707e0a70db3"); + } +} \ No newline at end of file