检验/证书

master
chenfeng 6 months ago
parent 2c8fa9ec93
commit 0da8d5faff
  1. 2
      yudao-server/src/main/java/cn/iocoder/yudao/server/controller/OcrProcessController.java
  2. 46
      yudao-server/src/main/java/cn/iocoder/yudao/server/service/CertificateOfApprovalService.java
  3. 15
      yudao-server/src/main/java/cn/iocoder/yudao/server/service/FieldMappingService.java
  4. 87
      yudao-server/src/main/java/cn/iocoder/yudao/server/service/ProductQualifiedService.java
  5. 18
      yudao-server/src/main/java/cn/iocoder/yudao/server/service/SpecialGasCylinderService.java
  6. 58
      yudao-server/src/main/java/cn/iocoder/yudao/server/service/SupervisionService.java

@ -51,7 +51,7 @@ public class OcrProcessController {
* @param param 请求参数
* @return 识别结果
*/
@PostMapping("/getIdentifyAndObtain")
@PostMapping("/admin-api//getIdentifyAndObtain")
@PermitAll
public CommonResult<Object> getIdentifyAndObtain(@RequestBody Map<String, Object> param) {
return supervisionService.getIdentifyAndObtain(param);

@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
@ -22,34 +23,37 @@ public class CertificateOfApprovalService {
* @param texts
* @return
*/
public EquipmentRegistryRespVO getCertificateOfApproval(List<String> texts) {
String keyName = extractManufacturer(texts, "燃气系统安装出厂检验质量证明书", 0);
Map<String, String> fieldMap = fieldMappingService.getCertificateMapping(keyName, texts);
public EquipmentRegistryRespVO getCertificateOfApproval(List<String> texts, String postfix) {
boolean productQualified = texts.stream().anyMatch(t -> t.equals("安装单位名称"));
Map<String, String> fieldMap = new HashMap<>();
if (productQualified) {
fieldMap = fieldMappingService.getCertificateMapping("安装单位名称", texts);
} else {
fieldMap = fieldMappingService.getCertificateMapping("安装单位", texts);
}
EquipmentRegistryRespVO equipmentRegistryRespVO = new EquipmentRegistryRespVO();
equipmentRegistryRespVO.setEquipmentType("特种气瓶");
equipmentRegistryRespVO.setProductName("车用气瓶");
equipmentRegistryRespVO.setCylinderQuantity(1);
String fillingMedium = extractManufacturer(texts, fieldMap.get("fillingMedium"), 2);
if (ObjectUtil.isNotEmpty(fillingMedium)) {
//充装介质
equipmentRegistryRespVO.setFillingMedium(fillingMedium);
}
String nominalWorkingPressure = extractManufacturer(texts, fieldMap.get("nominalWorkingPressure"), 2);
if (ObjectUtil.isNotEmpty(nominalWorkingPressure)) {
//气瓶公称工作压力
equipmentRegistryRespVO.setNominalWorkingPressure(nominalWorkingPressure);
int productIdOffset = 1;
if (!postfix.equals("pdf")) {
productIdOffset = 1;
}
String cylinderVolume = extractManufacturer(texts, fieldMap.get("cylinderVolume"), 2);
if (ObjectUtil.isNotEmpty(cylinderVolume)) {
//气瓶容积
equipmentRegistryRespVO.setCylinderVolume(cylinderVolume);
}
String productId = extractManufacturer(texts, fieldMap.get("productId"), 1);
String productId = extractManufacturer(texts, fieldMap.get("productId"), productIdOffset);
if (ObjectUtil.isNotEmpty(productId)) {
//产品编号
//气瓶编号
equipmentRegistryRespVO.setProductId(productId);
}
int contractorOffset = 1;
if (!postfix.equals("pdf")) {
contractorOffset = 1;
}
String contractor = extractManufacturer(texts, fieldMap.get("contractor"), contractorOffset);
if (ObjectUtil.isNotEmpty(contractor)) {
//安装单位
equipmentRegistryRespVO.setContractor(contractor);
}
return equipmentRegistryRespVO;
}
@ -62,7 +66,7 @@ public class CertificateOfApprovalService {
// 使用 Stream 查找关键词位置
int index = IntStream.range(0, recTexts.size())
.filter(i -> recTexts.get(i).contains(keyword))
.filter(i -> recTexts.get(i).equals(keyword))
.findFirst()
.orElse(-1); // 未找到返回-1

@ -29,7 +29,7 @@ public class FieldMappingService {
"监督检验机构", "监检机构", "监检单位", "监督检验单位"
);
private static final List<String> SUPERVISION_AGENCY_CANDIDATES_CPPH = Arrays.asList(
"产品批号","批号"
"产品批号", "批号"
);
//合格证书
//充装介质
@ -38,15 +38,19 @@ public class FieldMappingService {
);
//气瓶公称工作压力
private static final List<String> PRODUCTION_DATE_CANDIDATES_ZS = Arrays.asList(
"工作压力", "公称压力"
"工作压力", "公称压力", "公称工作压力:"
);
//气瓶容积
private static final List<String> SUPERVISION_AGENCY_CANDIDATES_ZS = Arrays.asList(
"公称容积", "气瓶容积", "容积"
"实测水容积:", "公称容积", "气瓶容积", "容积", "水容积:"
);
//产品编号
private static final List<String> SUPERVISION_AGENCY_CANDIDATES_BH_ZS = Arrays.asList(
"产品编号", "产品编码", "编号", "编码"
"产品编号", "产品编码", "气瓶编号"
);
//安装单位
private static final List<String> SUPERVISION_AGENCY_CANDIDATES_BH_AZDW = Arrays.asList(
"安装单位", "安装单位名称"
);
/**
@ -90,6 +94,7 @@ public class FieldMappingService {
fieldMap.put("nominalWorkingPressure", detectField(texts, PRODUCTION_DATE_CANDIDATES_ZS));
fieldMap.put("cylinderVolume", detectField(texts, SUPERVISION_AGENCY_CANDIDATES_ZS));
fieldMap.put("productId", detectField(texts, SUPERVISION_AGENCY_CANDIDATES_BH_ZS));
fieldMap.put("contractor", detectField(texts, SUPERVISION_AGENCY_CANDIDATES_BH_AZDW));
// 3. 存入缓存(有效期 30 天)
redisTemplate.opsForValue().set(redisKey, fieldMap, 365, TimeUnit.DAYS);
return fieldMap;
@ -101,7 +106,7 @@ public class FieldMappingService {
*/
private String detectField(List<String> texts, List<String> candidates) {
return candidates.stream()
.filter(candidate -> texts.stream().anyMatch(text -> text.contains(candidate)))
.filter(candidate -> texts.stream().anyMatch(text -> text.equals(candidate)))
.findFirst()
.orElse(candidates.get(0)); // 返回候选列表的第一个值作为默认值
}

@ -0,0 +1,87 @@
package cn.iocoder.yudao.server.service;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.special.controller.admin.equipmentregistry.vo.EquipmentRegistryRespVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
@Service
public class ProductQualifiedService {
@Autowired
private FieldMappingService fieldMappingService;
/**
* 合格证书
*
* @param texts
* @return
*/
public EquipmentRegistryRespVO getCertificateOfApproval(List<String> texts, String postfix) {
boolean productQualified = texts.stream().anyMatch(t -> t.equals("工作压力"));
Map<String, String> fieldMap = new HashMap<>();
if (productQualified) {
fieldMap = fieldMappingService.getCertificateMapping("工作压力", texts);
} else {
fieldMap = fieldMappingService.getCertificateMapping("公称工作压力:", texts);
}
EquipmentRegistryRespVO equipmentRegistryRespVO = new EquipmentRegistryRespVO();
equipmentRegistryRespVO.setEquipmentType("特种气瓶");
equipmentRegistryRespVO.setProductName("车用气瓶");
equipmentRegistryRespVO.setCylinderQuantity(1);
int fillingMediumOffset = 4;
if (!postfix.equals("pdf")) {
fillingMediumOffset = 3;
}
String fillingMedium = extractManufacturer(texts, fieldMap.get("fillingMedium"), fillingMediumOffset);
if (ObjectUtil.isNotEmpty(fillingMedium)) {
//充装介质
equipmentRegistryRespVO.setFillingMedium(fillingMedium);
}
int nominalWorkingPressureOffset = 1;
if (!postfix.equals("pdf")) {
nominalWorkingPressureOffset = 2;
}
String nominalWorkingPressure = extractManufacturer(texts, fieldMap.get("nominalWorkingPressure"), nominalWorkingPressureOffset);
if (ObjectUtil.isNotEmpty(nominalWorkingPressure)) {
//气瓶公称工作压力
equipmentRegistryRespVO.setNominalWorkingPressure(nominalWorkingPressure);
}
int cylinderVolumeOffset = 1;
if (!postfix.equals("pdf")) {
cylinderVolumeOffset = 1;
}
String cylinderVolume = extractManufacturer(texts, fieldMap.get("cylinderVolume"), cylinderVolumeOffset);
if (ObjectUtil.isNotEmpty(cylinderVolume)) {
//气瓶容积
equipmentRegistryRespVO.setCylinderVolume(cylinderVolume);
} else {
equipmentRegistryRespVO.setCylinderVolume(extractManufacturer(texts, "实测水容机: ", 1));
}
return equipmentRegistryRespVO;
}
public static String extractManufacturer(List<String> recTexts, String keyword, int offset) {
// 防御性检查:列表为空或为null时直接返回null
if (recTexts == null || recTexts.isEmpty()) {
return null;
}
// 使用 Stream 查找关键词位置
int index = IntStream.range(0, recTexts.size())
.filter(i -> recTexts.get(i).contains(keyword))
.findFirst()
.orElse(-1); // 未找到返回-1
// 检查是否找到关键词,且偏移后不越界
if (index != -1 && index + offset < recTexts.size()) {
return recTexts.get(index + offset);
}
return null; // 未找到或越界时返回null
}
}

@ -26,8 +26,13 @@ public class SpecialGasCylinderService {
* @param texts
* @return
*/
public EquipmentRegistryRespVO getSpecialGasCylinder(List<String> texts) {
String keyName = extractManufacturer(texts, "监督检验机构", 0);
public EquipmentRegistryRespVO getSpecialGasCylinder(List<String> texts, String postfix) {
int supervisionAgencyOffset = 1;
if (!postfix.equals("pdf")) {
supervisionAgencyOffset = 0;
}
//通过监督检验机构当作key
String keyName = extractManufacturer(texts, "监督检验机构", supervisionAgencyOffset);
Map<String, String> fieldMap = fieldMappingService.getFieldMapping(keyName, texts);
EquipmentRegistryRespVO equipmentRegistryRespVO = new EquipmentRegistryRespVO();
equipmentRegistryRespVO.setEquipmentType("特种气瓶");
@ -40,11 +45,16 @@ public class SpecialGasCylinderService {
if (ObjectUtil.isNotEmpty(productionDateField)) {
equipmentRegistryRespVO.setProductionDate(productionDateField);
}
String supervisionAgencyField = extractManufacturer(texts, fieldMap.get("supervisionAgencyField"), 0);
String supervisionAgencyField = extractManufacturer(texts, fieldMap.get("supervisionAgencyField"), supervisionAgencyOffset);
if (ObjectUtil.isNotEmpty(supervisionAgencyField)) {
equipmentRegistryRespVO.setSupervisionAgency(supervisionAgencyField);
}
String productBatchNumber = extractManufacturer(texts, fieldMap.get("productBatchNumber"), 1);
int productBatchNumberOffset = 1;
if (!postfix.equals("pdf")) {
productBatchNumberOffset = 2;
}
String productBatchNumber = extractManufacturer(texts, fieldMap.get("productBatchNumber"), productBatchNumberOffset);
if (ObjectUtil.isNotEmpty(productBatchNumber)) {
equipmentRegistryRespVO.setProductBatchNumber(productBatchNumber);
}

@ -50,6 +50,8 @@ public class SupervisionService {
private RedisTemplate<String, OcrResponseVo> redisTemplate;
@Autowired
private CertificateOfApprovalService certificateOfApprovalService;
@Autowired
private ProductQualifiedService productQualifiedService;
/**
* 获取识别结果
@ -63,12 +65,12 @@ public class SupervisionService {
}
try {
String fileName = param.get("filePath").toString().substring(param.get("filePath").toString().lastIndexOf('/') + 1);
OcrResponseVo redisValue = redisTemplate.opsForValue().get(fileName);
if (redisValue != null) {
return CommonResult.success(determineDocumentType(redisValue));
// return CommonResult.success(redisValue);
}
String postfix = getFileExtensionFromUrl(param.get("filePath").toString());
// OcrResponseVo redisValue = redisTemplate.opsForValue().get(fileName);
// if (redisValue != null) {
// return CommonResult.success(determineDocumentType(redisValue, postfix));
//// return CommonResult.success(redisValue);
// }
String imageBase64 = null;
if (Objects.equals(postfix, "pdf")) {
//pdf
@ -84,44 +86,66 @@ public class SupervisionService {
Map<String, Object> requestPayload = buildRequestPayload(imageBase64, postfix);
OcrResponseVo response = sendOcrRequest(requestPayload);
redisTemplate.opsForValue().set(fileName, response);
// redisTemplate.opsForValue().set(fileName, response);
// return CommonResult.success(response);
return CommonResult.success(determineDocumentType(response));
return CommonResult.success(determineDocumentType(response, postfix));
} catch (Exception e) {
LOGGER.error("OCR识别系统异常: {}", e.getMessage(), e);
return CommonResult.error(500, "系统异常");
}
}
private Object determineDocumentType(OcrResponseVo ocrResponseVo) {
private Object determineDocumentType(OcrResponseVo ocrResponseVo, String postfix) {
List<OcrResponseVo.TableRecResult> tableRecResults = ocrResponseVo.getResult().getTableRecResults();
Map<String, Object> param = new HashMap<>();
List<EquipmentRegistryRespVO> equipmentRegistryRespVOS = new ArrayList<>();
for (OcrResponseVo.TableRecResult result : tableRecResults) {
List<String> texts = new ArrayList<>();
//表格返回参数table_res_list
if (CollectionUtil.isNotEmpty(result.getPrunedResult().getTable_res_list())) {
if (CollectionUtil.isNotEmpty(result.getPrunedResult().getTable_res_list()) && result.getPrunedResult().getTable_res_list().size() == 1) {
texts = result.getPrunedResult().getTable_res_list().get(0).getTable_ocr_pred().getRec_texts();
} else {
texts = result.getPrunedResult().getOverall_ocr_res().getRec_texts();
}
EquipmentRegistryRespVO equipmentRegistryRespVO = null;
//监督检验
boolean supervisionAndInspection = texts.stream().anyMatch(t -> t.contains("监督检验"));
boolean supervisionAndInspection = texts.stream().anyMatch(t -> t.contains("设计单位名称"));
if (supervisionAndInspection) {
equipmentRegistryRespVO = specialGasCylinderService.getSpecialGasCylinder(texts);
equipmentRegistryRespVO = specialGasCylinderService.getSpecialGasCylinder(texts, postfix);
if (null == equipmentRegistryRespVO) {
continue;
}
equipmentRegistryRespVO.setType("supervisionAndInspection");
equipmentRegistryRespVOS.add(equipmentRegistryRespVO);
}
//车用气瓶安装合格证
boolean CertificateOfApproval = texts.stream().anyMatch(t -> t.contains("燃气系统安装出厂检验质量证明书") || t.contains("充装介质"));
boolean CertificateOfApproval = texts.stream().anyMatch(t -> t.contains("安装合格证") || t.contains("安装单位") || t.contains("安装单位名称"));
// || t.contains("充装介质") || t.contains("水溶机")
// || t.contains("燃气系统安装出厂检验质量证明书")
if (CertificateOfApproval) {
equipmentRegistryRespVO = certificateOfApprovalService.getCertificateOfApproval(texts);
equipmentRegistryRespVO = certificateOfApprovalService.getCertificateOfApproval(texts, postfix);
if (null == equipmentRegistryRespVO) {
continue;
}
equipmentRegistryRespVO.setType("certificateOfApproval");
equipmentRegistryRespVOS.add(equipmentRegistryRespVO);
}
if (null == equipmentRegistryRespVO) {
continue;
//车用气瓶产品合格证
boolean productQualified = texts.stream().anyMatch(t -> t.equals("产品合格证") || t.contains("公称工作压力:") || t.contains("水溶机") ||
t.equals("实测水溶机:") || t.equals("工作压力")
);
// || t.contains("燃气系统安装出厂检验质量证明书")
if (productQualified) {
equipmentRegistryRespVO = productQualifiedService.getCertificateOfApproval(texts, postfix);
if (null == equipmentRegistryRespVO) {
continue;
}
equipmentRegistryRespVO.setType("productQualified");
equipmentRegistryRespVOS.add(equipmentRegistryRespVO);
}
equipmentRegistryRespVOS.add(equipmentRegistryRespVO);
}
param.put("extractedData", equipmentRegistryRespVOS);
return param;
@ -148,6 +172,8 @@ public class SupervisionService {
Map<String, Object> payload = new HashMap<>();
payload.put("file", imageBase64);
payload.put("fileType", fileType);
payload.put("useDocOrientationClassify", false);
payload.put("useDocUnwarping", false);
return payload;
}

Loading…
Cancel
Save