|
|
|
@ -2,9 +2,11 @@ package org.jeecg.module.custom.ocr.api.thread;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
|
import com.google.common.collect.Sets;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.jeecg.module.custom.ocr.api.entity.TaskCompletionRequest;
|
|
|
|
|
import org.jeecg.module.custom.ocr.common.entity.RequestData;
|
|
|
|
@ -18,7 +20,9 @@ import org.jeecg.module.custom.ocr.dataobject.*;
|
|
|
|
|
import org.jeecg.module.custom.ocr.service.OcrPictureInfoService;
|
|
|
|
|
import org.jeecg.module.custom.ocr.service.OcrPictureService;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.ApiHelper;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.HashCompareUtil;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.ImageClassUtil;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.StringUtils;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.httputil.HttpClient;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.httputil.HttpMethod;
|
|
|
|
|
import org.jeecg.module.custom.ocr.utils.httputil.HttpParamers;
|
|
|
|
@ -30,10 +34,7 @@ import org.springframework.util.CollectionUtils;
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
@ -70,6 +71,9 @@ public class DuplicateTaskRunner {
|
|
|
|
|
@Value("${image.classifyBaseUrl}")
|
|
|
|
|
private String classifyBaseUrl;
|
|
|
|
|
|
|
|
|
|
@Value("${image.classifyPath}")
|
|
|
|
|
private String classifyPath;
|
|
|
|
|
|
|
|
|
|
private ScheduledExecutorService executor;
|
|
|
|
|
@Autowired
|
|
|
|
|
private OcrPictureInfoService ocrPictureInfoService;
|
|
|
|
@ -95,12 +99,24 @@ public class DuplicateTaskRunner {
|
|
|
|
|
// // 调用 OcrPictureService.listPage 查询图片
|
|
|
|
|
// List<OcrPicture> pictures = ocrPictureService.listPage(queryWrapper);
|
|
|
|
|
|
|
|
|
|
List<Task> tasks = taskMapper.selectByAccountNoAndQueryConfig(duplicateTask.getAccountNo(), duplicateTask.getQueryConfig());
|
|
|
|
|
List<Task> tasks = taskMapper.selectByAccountNoAndQueryConfig(duplicateTask.getTenantNo(), duplicateTask.getQueryConfig());
|
|
|
|
|
if (StringUtils.isNotEmpty(duplicateTask.getTaskNos())) {
|
|
|
|
|
List<String> taskNos = Arrays.asList(duplicateTask.getTaskNos().split(","));
|
|
|
|
|
if (!CollectionUtils.isEmpty(taskNos)) {
|
|
|
|
|
tasks = tasks.stream().filter(item -> taskNos.contains(String.valueOf(item.getTaskNo()))).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean result = true;
|
|
|
|
|
DuplicateTask.QueryConfig queryConfig = JSONObject.parseObject(duplicateTask.getQueryConfig(), DuplicateTask.QueryConfig.class);
|
|
|
|
|
List<TaskCompletionRequest.HisPictureRepeat> historyLists = Lists.newArrayList();
|
|
|
|
|
Set<Long> pictureIds = Sets.newHashSet();
|
|
|
|
|
if (!CollectionUtils.isEmpty(tasks)) {
|
|
|
|
|
List<Long> taskIds = tasks.stream().map(Task::getId).collect(Collectors.toList());
|
|
|
|
|
List<OcrPictureInfo> pictures = ocrPictureInfoMapper.selectByTaskIds(taskIds);
|
|
|
|
|
List<Long> taskNoList = tasks.stream().map(Task::getTaskNo).collect(Collectors.toList());
|
|
|
|
|
List<OcrPictureInfo> pictures = ocrPictureInfoMapper.selectByTaskNos(taskNoList);
|
|
|
|
|
if (!CollectionUtils.isEmpty(pictures)) {
|
|
|
|
|
pictures = pictures.stream().filter(item -> queryConfig.getValidateColumn().contains(item.getType())).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果图片数量大于 1,进行两两对比
|
|
|
|
|
double maxSimilarity = 0.0;
|
|
|
|
|
if (pictures != null && pictures.size() > 1) {
|
|
|
|
@ -110,8 +126,18 @@ public class DuplicateTaskRunner {
|
|
|
|
|
OcrPictureInfo second = pictures.get(j);
|
|
|
|
|
|
|
|
|
|
// 计算相似度
|
|
|
|
|
String similarityScore = ImageClassUtil.getSimilarity(first.getImageUrl(), second.getImageUrl(), classifyBaseUrl);
|
|
|
|
|
String similarityScore = HashCompareUtil.cmpHash(first.getImgHash(), second.getImgHash());
|
|
|
|
|
// String similarityScore = ImageClassUtil.getSimilarity(first.getImageUrl(), second.getImageUrl(), classifyBaseUrl);
|
|
|
|
|
double similarityValue = Double.parseDouble(similarityScore);
|
|
|
|
|
if (!pictureIds.contains(first.getId()) && similarityValue > queryConfig.getConfidenceLevel()) {
|
|
|
|
|
TaskCompletionRequest.HisPictureRepeat hisPictureRepeat = new TaskCompletionRequest.HisPictureRepeat();
|
|
|
|
|
hisPictureRepeat.setHisTaskNo(first.getTaskNo());
|
|
|
|
|
hisPictureRepeat.setHisRepeatImgUrl(first.getImageUrl());
|
|
|
|
|
hisPictureRepeat.setHisRepeatImgNo(first.getId());
|
|
|
|
|
pictureIds.add(first.getId());
|
|
|
|
|
historyLists.add(hisPictureRepeat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maxSimilarity = Math.max(maxSimilarity, similarityValue);
|
|
|
|
|
|
|
|
|
|
// 保存对比结果到 PictureCompare
|
|
|
|
@ -138,12 +164,12 @@ public class DuplicateTaskRunner {
|
|
|
|
|
|
|
|
|
|
String[] taskNos = duplicateTask.getTaskNos().split(",");
|
|
|
|
|
for (String taskNo : taskNos) {
|
|
|
|
|
notifyTaskCompletion(taskNo, duplicateTask.getTenantNo(), duplicateTask.getAccountNo(), maxSimilarity, pictures);
|
|
|
|
|
notifyTaskCompletion(taskNo, duplicateTask.getTenantNo(), duplicateTask.getAccountNo(), maxSimilarity, pictures, historyLists);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
String[] taskNos = duplicateTask.getTaskNos().split(",");
|
|
|
|
|
for (String taskNo : taskNos) {
|
|
|
|
|
notifyTaskCompletion(taskNo, duplicateTask.getTenantNo(), duplicateTask.getAccountNo(), 0, Lists.newArrayList());
|
|
|
|
|
notifyTaskCompletion(taskNo, duplicateTask.getTenantNo(), duplicateTask.getAccountNo(), 0, Lists.newArrayList(), historyLists);
|
|
|
|
|
}
|
|
|
|
|
duplicateTaskMapper.updateCompletedAndMaxSimilarity(duplicateTask.getId(), 1, "0");
|
|
|
|
|
}
|
|
|
|
@ -160,130 +186,7 @@ public class DuplicateTaskRunner {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private QueryWrapper<OcrPicture> toQueryWrapper(DuplicateTask task) {
|
|
|
|
|
QueryWrapper<OcrPicture> queryWrapper = new QueryWrapper<>();
|
|
|
|
|
|
|
|
|
|
// 解析 queryConfig JSON
|
|
|
|
|
if (task.getQueryConfig() != null && !task.getQueryConfig().isEmpty()) {
|
|
|
|
|
try {
|
|
|
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
|
Map<String, Object> queryMap = objectMapper.readValue(task.getQueryConfig(), Map.class);
|
|
|
|
|
|
|
|
|
|
// 映射 OcrPicture 的数据库列名
|
|
|
|
|
Map<String, String> fieldToColumnMap = new HashMap<>();
|
|
|
|
|
fieldToColumnMap.put("id", "ID");
|
|
|
|
|
fieldToColumnMap.put("createBy", "create_by");
|
|
|
|
|
fieldToColumnMap.put("createTime", "create_time");
|
|
|
|
|
fieldToColumnMap.put("updateBy", "update_by");
|
|
|
|
|
fieldToColumnMap.put("updateTime", "update_time");
|
|
|
|
|
fieldToColumnMap.put("classificationid", "classificationid");
|
|
|
|
|
fieldToColumnMap.put("pictureclassid", "pictureclassid");
|
|
|
|
|
fieldToColumnMap.put("pictureclassscores", "pictureclassscores");
|
|
|
|
|
fieldToColumnMap.put("iztrueorfalse", "iztrueorfalse");
|
|
|
|
|
fieldToColumnMap.put("judgeid", "judgeid");
|
|
|
|
|
fieldToColumnMap.put("judgedesc", "judgedesc");
|
|
|
|
|
fieldToColumnMap.put("tenantId", "tenant_id");
|
|
|
|
|
fieldToColumnMap.put("tenantstatus", "tenantstatus");
|
|
|
|
|
fieldToColumnMap.put("plantcode", "plantCode");
|
|
|
|
|
fieldToColumnMap.put("tenantname", "tenantname");
|
|
|
|
|
fieldToColumnMap.put("pictureid", "pictureid");
|
|
|
|
|
fieldToColumnMap.put("picturename", "picturename");
|
|
|
|
|
fieldToColumnMap.put("imgname", "imgName");
|
|
|
|
|
fieldToColumnMap.put("imgurl", "imgUrl");
|
|
|
|
|
fieldToColumnMap.put("picturestatus", "picturestatus");
|
|
|
|
|
fieldToColumnMap.put("projectid", "projectId");
|
|
|
|
|
fieldToColumnMap.put("projectidname", "projectIdName");
|
|
|
|
|
fieldToColumnMap.put("projectstatus", "projectstatus");
|
|
|
|
|
fieldToColumnMap.put("planid", "planId");
|
|
|
|
|
fieldToColumnMap.put("planname", "planName");
|
|
|
|
|
fieldToColumnMap.put("planstatus", "planstatus");
|
|
|
|
|
fieldToColumnMap.put("planchildid", "planchildid");
|
|
|
|
|
fieldToColumnMap.put("planchildname", "planchildname");
|
|
|
|
|
fieldToColumnMap.put("planchildstatus", "planchildstatus");
|
|
|
|
|
fieldToColumnMap.put("uptime", "upTime");
|
|
|
|
|
fieldToColumnMap.put("gentime", "genTime");
|
|
|
|
|
fieldToColumnMap.put("space", "space");
|
|
|
|
|
fieldToColumnMap.put("source", "source");
|
|
|
|
|
fieldToColumnMap.put("uphead", "upHead");
|
|
|
|
|
fieldToColumnMap.put("upuserid", "upuserid");
|
|
|
|
|
fieldToColumnMap.put("upname", "upName");
|
|
|
|
|
fieldToColumnMap.put("releasearea", "releaseArea");
|
|
|
|
|
fieldToColumnMap.put("releaseprovince", "releaseProvince");
|
|
|
|
|
fieldToColumnMap.put("remark", "remark");
|
|
|
|
|
fieldToColumnMap.put("taskname", "taskName");
|
|
|
|
|
fieldToColumnMap.put("taskstatus", "taskstatus");
|
|
|
|
|
fieldToColumnMap.put("workStatus", "work_status");
|
|
|
|
|
fieldToColumnMap.put("categoryid", "categoryid");
|
|
|
|
|
fieldToColumnMap.put("taskchildpictureid", "taskchildpictureid");
|
|
|
|
|
fieldToColumnMap.put("field1", "field1");
|
|
|
|
|
fieldToColumnMap.put("field2", "field2");
|
|
|
|
|
fieldToColumnMap.put("field3", "field3");
|
|
|
|
|
fieldToColumnMap.put("field4", "field4");
|
|
|
|
|
fieldToColumnMap.put("field5", "field5");
|
|
|
|
|
fieldToColumnMap.put("field6", "field6");
|
|
|
|
|
fieldToColumnMap.put("field7", "field7");
|
|
|
|
|
fieldToColumnMap.put("field8", "field8");
|
|
|
|
|
fieldToColumnMap.put("field9", "field9");
|
|
|
|
|
fieldToColumnMap.put("field10", "field10");
|
|
|
|
|
fieldToColumnMap.put("field11", "field11");
|
|
|
|
|
fieldToColumnMap.put("field12", "field12");
|
|
|
|
|
fieldToColumnMap.put("field13", "field13");
|
|
|
|
|
fieldToColumnMap.put("field14", "field14");
|
|
|
|
|
fieldToColumnMap.put("field15", "field15");
|
|
|
|
|
fieldToColumnMap.put("field16", "field16");
|
|
|
|
|
fieldToColumnMap.put("field17", "field17");
|
|
|
|
|
fieldToColumnMap.put("field18", "field18");
|
|
|
|
|
fieldToColumnMap.put("localpictrueurl", "local_pictrue_url");
|
|
|
|
|
fieldToColumnMap.put("isdownload", "is_download");
|
|
|
|
|
fieldToColumnMap.put("imgHash", "img_hash");
|
|
|
|
|
fieldToColumnMap.put("similarityscore", "similarity_score");
|
|
|
|
|
fieldToColumnMap.put("downloadErrorCount", "download_error_count");
|
|
|
|
|
fieldToColumnMap.put("localThumbnailUrl", "local_thumbnail_url");
|
|
|
|
|
fieldToColumnMap.put("serverThumbnailUrl", "server_thumbnail_url");
|
|
|
|
|
fieldToColumnMap.put("submitDateTimestamp", "submit_date_timestamp");
|
|
|
|
|
fieldToColumnMap.put("isRepeat", "is_repeat");
|
|
|
|
|
fieldToColumnMap.put("suspiciousfile", "suspiciousfile");
|
|
|
|
|
fieldToColumnMap.put("location", "location");
|
|
|
|
|
fieldToColumnMap.put("comment", "comment");
|
|
|
|
|
fieldToColumnMap.put("photoDateTimestamp", "photo_date_timestamp");
|
|
|
|
|
fieldToColumnMap.put("completeSimilarGroupId", "complete_similar_group_id");
|
|
|
|
|
fieldToColumnMap.put("history", "history");
|
|
|
|
|
|
|
|
|
|
// 动态添加查询条件
|
|
|
|
|
for (Map.Entry<String, Object> entry : queryMap.entrySet()) {
|
|
|
|
|
String fieldName = entry.getKey();
|
|
|
|
|
Object value = entry.getValue();
|
|
|
|
|
String columnName = fieldToColumnMap.get(fieldName);
|
|
|
|
|
|
|
|
|
|
if (columnName != null && value != null) {
|
|
|
|
|
queryWrapper.eq(columnName, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException("Failed to parse queryConfig", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加 DuplicateTask 的其他字段作为查询条件
|
|
|
|
|
if (task.getTenantNo() != null) {
|
|
|
|
|
queryWrapper.eq("tenant_id", task.getTenantNo());
|
|
|
|
|
}
|
|
|
|
|
if (task.getAccountNo() != null) {
|
|
|
|
|
queryWrapper.eq("pictureid", task.getAccountNo()); // 假设 pictureid 对应 accountNo
|
|
|
|
|
}
|
|
|
|
|
if (task.getTaskNos() != null && !task.getTaskNos().isEmpty()) {
|
|
|
|
|
// 假设 taskNos 是逗号分隔的字符串,转换为 List<Long>
|
|
|
|
|
String[] taskNosArray = task.getTaskNos().split(",");
|
|
|
|
|
List<Long> taskNosList = Arrays.asList(taskNosArray).stream()
|
|
|
|
|
.map(Long::parseLong)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
queryWrapper.in("remark", taskNosList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return queryWrapper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean notifyTaskCompletion(String taskNo, Long tenantNo, Long accountNo, double maxSimilarity, List<OcrPictureInfo> pictures) {
|
|
|
|
|
private boolean notifyTaskCompletion(String taskNo, Long tenantNo, Long accountNo, double maxSimilarity, List<OcrPictureInfo> pictures, List<TaskCompletionRequest.HisPictureRepeat> historyLists) {
|
|
|
|
|
try {
|
|
|
|
|
// 构造任务完成数据
|
|
|
|
|
TaskCompletionRequest.TaskCompletionData data = new TaskCompletionRequest.TaskCompletionData();
|
|
|
|
@ -305,7 +208,7 @@ public class DuplicateTaskRunner {
|
|
|
|
|
repeat.setImgNo(p.getId());
|
|
|
|
|
repeat.setImgUrl(p.getImageUrl());
|
|
|
|
|
repeat.setDynamicFields(new HashMap<>()); // 动态字段待补充
|
|
|
|
|
repeat.setHisPictureRepeatList(Arrays.asList());
|
|
|
|
|
repeat.setHisPictureRepeatList(historyLists);
|
|
|
|
|
return repeat;
|
|
|
|
|
})
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
@ -317,19 +220,26 @@ public class DuplicateTaskRunner {
|
|
|
|
|
data.setApproveDetailList(Arrays.asList());
|
|
|
|
|
|
|
|
|
|
// 序列化 data 为 JSON
|
|
|
|
|
String jsonData = JSONObject.toJSONString(data);
|
|
|
|
|
String jsonData = JSONObject.toJSONString(data, SerializerFeature.DisableCircularReferenceDetect);
|
|
|
|
|
|
|
|
|
|
// 加密请求参数
|
|
|
|
|
RequestData requestData = ApiHelper.buildRequest(
|
|
|
|
|
tenantNo.toString(),
|
|
|
|
|
apiConfig.getAccessKey(),
|
|
|
|
|
apiConfig.getAccessCode(),
|
|
|
|
|
jsonData
|
|
|
|
|
);
|
|
|
|
|
// RequestData requestData = ApiHelper.buildResponse(
|
|
|
|
|
// RequestData requestData = ApiHelper.buildRequest(
|
|
|
|
|
// tenantNo.toString(),
|
|
|
|
|
// apiConfig.getAccessKey(),
|
|
|
|
|
// apiConfig.getAccessCode(),
|
|
|
|
|
// jsonData
|
|
|
|
|
// );
|
|
|
|
|
ResultData<String> stringResultData = ApiHelper.buildResponse(
|
|
|
|
|
apiConfig.getAccessCode(),
|
|
|
|
|
jsonData
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
RequestData requestData = new RequestData();
|
|
|
|
|
requestData.setAccessKey(apiConfig.getAccessKey());
|
|
|
|
|
requestData.setSignature(stringResultData.getSignature());
|
|
|
|
|
requestData.setTimestamp(stringResultData.getTimestamp());
|
|
|
|
|
requestData.setTenantCode(tenantNo.toString());
|
|
|
|
|
requestData.setData(stringResultData.getData());
|
|
|
|
|
|
|
|
|
|
// 组装请求
|
|
|
|
|
// TODO: 需提供实际路径
|
|
|
|
|