From 1ecf45fd04c1973e944da3de77a7e102c7260842 Mon Sep 17 00:00:00 2001 From: zhouwentao <1577701412@qq.com> Date: Tue, 22 Aug 2023 16:06:22 +0800 Subject: [PATCH] updates --- .../ocr/controller/OcrIdentifyController.java | 1 + .../controller/OcrSimulatorController.java | 114 +++++ .../modules/ocr/entity/OcrIdentifyDetail.java | 8 + .../jeecg/modules/ocr/model/OcrResult.java | 2 + .../ocr/service/IOcrIdentifyService.java | 7 + .../service/impl/OcrIdentifyServiceImpl.java | 389 +++++++++++++----- .../modules/ocr/vo/SimulateChecksVO.java | 31 ++ .../system/controller/CommonController.java | 2 +- .../src/main/resources/application-dev.yml | 2 +- .../src/main/resources/application-prod.yml | 2 +- .../src/main/resources/application-test.yml | 2 +- 11 files changed, 447 insertions(+), 113 deletions(-) create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrSimulatorController.java create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/vo/SimulateChecksVO.java diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrIdentifyController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrIdentifyController.java index 810c177..148de96 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrIdentifyController.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrIdentifyController.java @@ -114,6 +114,7 @@ public class OcrIdentifyController extends JeecgController queryWrapper = QueryGenerator.initQueryWrapper(ocrIdentify, req.getParameterMap()); + queryWrapper.ne("task_source","模拟实验");//排除模拟实验的数据 if (startTime!=null&&endTime!=null) { endTime.setTime(endTime.getTime()+86400000l); queryWrapper.between("end_time",startTime,endTime); diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrSimulatorController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrSimulatorController.java new file mode 100644 index 0000000..67f070f --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/controller/OcrSimulatorController.java @@ -0,0 +1,114 @@ +package org.jeecg.modules.ocr.controller; + +import java.math.BigDecimal; +import java.util.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.constant.OcrConstant; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.AssertUtils; +import org.jeecg.common.util.RestUtil; +import org.jeecg.modules.ocr.entity.OcrIdentify; +import org.jeecg.modules.ocr.entity.OcrIdentifyDetail; +import org.jeecg.modules.ocr.service.IOcrIdentifyDetailService; +import org.jeecg.modules.ocr.service.IOcrIdentifyService; +import org.jeecg.modules.ocr.service.IOcrRuleCheckService; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.modules.ocr.vo.SimulateChecksVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.apache.shiro.authz.annotation.RequiresPermissions; + +/** + * @Description: 模拟识别器 + * @Author: jeecg-boot + * @Date: 2023-08-22 + * @Version: V1.0 + */ +@Api(tags = "模拟识别器") +@RestController +@RequestMapping("/ocrSimulator") +@Slf4j +public class OcrSimulatorController{ + @Resource + private IOcrIdentifyService ocrIdentifyService; + @Resource + private IOcrIdentifyDetailService ocrIdentifyDetailService; + + @Value("${jeecg.path.upload}") + private String uploadFilePath; + String ss = "{\"Inputs\":{\"RequestJson\":{\"Header\":{\"InterfaceCode\":\"QMS-MES-001\",\"RequestTime\":\"20230731163802\"},\"RequestInfo\":{\"Containers\":[\"M500000000002806\",\"M500000000002805\",\"M500000000002390\"],\"SerialNos\":[],\"Characteristics\":[{\"Characteristic\":\"N1SHP_PR019\",\"OprSequenceNo\":\"N1SHP01\"}],\"ProductionType\":\"C\"}}}}"; + + @ApiOperation(value = "场景识别") + @PostMapping(value = "/identify") + public Result identify(@RequestBody JSONObject requestBody) { + JSONObject responseBody = new JSONObject(); + JSONArray images = requestBody.getJSONArray("images"); + AssertUtils.hasSize(images,"请先上传图片"); + List imageList = images.toJavaList(String.class); + OcrIdentify ocrIdentify=new OcrIdentify(); + ocrIdentify.setTaskSource("模拟实验");//模拟实验-场景识别 + ocrIdentifyService.save(ocrIdentify); + int i = 1; + List ocrIdentifyDetailList=new ArrayList<>(); + Double nluTimeSum=0d; + Double ocrTimeSum=0d; + for (String image : imageList) { + long time = new Date().getTime(); + //执行识别 + JSONObject semanticRequestBody = new JSONObject(); + semanticRequestBody.put("task_id", time+""); + semanticRequestBody.put("img_path", uploadFilePath + "/" + image); + JSONObject semanticResponseJson = RestUtil.post(OcrConstant.api_test2_identify_url, semanticRequestBody); + //执行时间 调整小数点 + Double nluTime = semanticResponseJson.getDouble("nlu_time"); + Double ocrTime = semanticResponseJson.getDouble("ocr_time"); + nluTime = nluTime != null && nluTime != 0 ? new BigDecimal(nluTime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() : 0; + ocrTime = ocrTime != null && ocrTime != 0 ? new BigDecimal(ocrTime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() : 0; + //入库 + OcrIdentifyDetail ocrIdentifyDetail=new OcrIdentifyDetail(); + ocrIdentifyDetail.setIdentifyId(ocrIdentify.getId()); + ocrIdentifyDetail.setOcrTime(ocrTime); + ocrIdentifyDetail.setNluTime(nluTime); + ocrIdentifyDetail.setImageName(image);//图片名称 + ocrIdentifyDetail.setImageUrl(uploadFilePath + "/" + image);//图片地址 + ocrIdentifyDetail.setSemanticResult(semanticResponseJson.toJSONString());//ocr识别结果 + ocrIdentifyDetailList.add(ocrIdentifyDetail); + //累计时间 + nluTimeSum+=nluTime; + ocrTimeSum+=ocrTime; + } + //保存明细信息 + ocrIdentifyDetailService.saveBatch(ocrIdentifyDetailList); + + //返回前端的json + JSONObject responseObject=new JSONObject(); + responseObject.put("ocrTime",ocrTimeSum); + responseObject.put("nluTime",nluTimeSum); + responseObject.put("detailList",ocrIdentifyDetailList); + return Result.OK(responseBody); + } + + @ApiOperation(value = "模拟检查") + @PostMapping(value = "/simulateChecks") + public Result simulateChecks(@RequestBody SimulateChecksVO simulateChecksVO) { + //规则检查配置id + String ruleCheckId = simulateChecksVO.getRuleCheckId(); + List identifyDetailIdList = simulateChecksVO.getIdentifyDetailIdList(); + AssertUtils.notEmpty(ruleCheckId, "请选择[规则扫描器]"); + AssertUtils.hasSize(identifyDetailIdList,"请先上传图片"); + ocrIdentifyService.simulateChecks(simulateChecksVO); + //图片明细的id + return Result.OK(); + } + +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/entity/OcrIdentifyDetail.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/entity/OcrIdentifyDetail.java index 6f55bec..51c2dbd 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/entity/OcrIdentifyDetail.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/entity/OcrIdentifyDetail.java @@ -78,6 +78,14 @@ public class OcrIdentifyDetail implements Serializable { @Excel(name = "数据结构化", width = 15) @ApiModelProperty(value = "数据结构化") private java.lang.String dataStructured; + /**OCR扫描时长*/ + @Excel(name = "OCR扫描时长", width = 15) + @ApiModelProperty(value = "OCR扫描时长") + private java.lang.Double ocrTime; + /**NLU处理时长*/ + @Excel(name = "NLU处理时长", width = 15) + @ApiModelProperty(value = "NLU处理时长") + private java.lang.Double nluTime; /**执行识别时长(秒)*/ @Excel(name = "执行识别时长(秒)", width = 15) @ApiModelProperty(value = "执行识别时长(秒)") diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/model/OcrResult.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/model/OcrResult.java index b17239c..3f800e2 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/model/OcrResult.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/model/OcrResult.java @@ -29,4 +29,6 @@ public class OcrResult { @ApiModelProperty(value = "文本匹配度") private Double textRate; + @ApiModelProperty(value = "检查要求") + private String ruleValidationText; } diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/IOcrIdentifyService.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/IOcrIdentifyService.java index de74439..cc5bd4e 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/IOcrIdentifyService.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/IOcrIdentifyService.java @@ -6,6 +6,7 @@ import org.checkerframework.checker.units.qual.A; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.ocr.entity.OcrIdentify; import org.jeecg.modules.ocr.vo.OcrIdentifyVo; +import org.jeecg.modules.ocr.vo.SimulateChecksVO; import org.springframework.scheduling.annotation.Async; import java.util.List; @@ -56,4 +57,10 @@ public interface IOcrIdentifyService extends IService { * @return */ List findNeNoticeList(Integer autoPushNoticeMaxNum); + + /** + * 模拟检查 + * @param simulateChecksVO + */ + void simulateChecks(SimulateChecksVO simulateChecksVO); } diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/impl/OcrIdentifyServiceImpl.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/impl/OcrIdentifyServiceImpl.java index 0447f09..5e8f741 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/impl/OcrIdentifyServiceImpl.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/service/impl/OcrIdentifyServiceImpl.java @@ -24,6 +24,7 @@ import org.jeecg.modules.ocr.utils.ImageUtils; import org.jeecg.modules.ocr.utils.StrCharUtil; import org.jeecg.modules.ocr.vo.OcrIdentifyVo; import org.jeecg.modules.ocr.vo.OcrRuleCheckVo; +import org.jeecg.modules.ocr.vo.SimulateChecksVO; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Service; @@ -60,6 +61,7 @@ public class OcrIdentifyServiceImpl extends ServiceImpl> resultToPoints = ImageUtils.semanticResultToPoints(semanticResult); - if (resultToPoints.size()>0) { - ImageUtils.drawDashedRectangleOnImages(file.getAbsolutePath(),resultToPoints,outputImagePath); + if (resultToPoints.size() > 0) { + ImageUtils.drawDashedRectangleOnImages(file.getAbsolutePath(), resultToPoints, outputImagePath); ocrIdentifyDetail.setDrawDashedImageUrl(outputImagePath); } } @@ -140,7 +142,7 @@ public class OcrIdentifyServiceImpl extends ServiceImpl checkSemanticModelMap = getCheckSemanticModelMap(ocrRuleCheckVo.getConfigRuleMap(), ocrRuleCheckVo.getFieldMap(), ocrIdentifyVo.getSourceJsonObjects()); - String text=null;//ocr 识别的文本 + String text = null;//ocr 识别的文本 Double probability = 0d; //用于数据结构化的对象 List ocrResultList = new ArrayList<>(); StringBuffer rMessage = new StringBuffer(); Map fieldRightMap = new LinkedHashMap<>();//存放 字段判断正确map //========================== + //========================== checkSemanticFor: for (CheckSemanticModel value : checkSemanticModelMap.values()) { String field = value.getField(); String fieldName = value.getFieldName();//校验的字段名称 @@ -174,8 +177,9 @@ public class OcrIdentifyServiceImpl extends ServiceImpl0) { - ocrArrayFor: for (int i = 0; i < ocrArray.size(); i++) { + if (ocrArray.size() > 0) { + ocrArrayFor: + for (int i = 0; i < ocrArray.size(); i++) { JSONObject ocrItem = ocrArray.get(i); text = null; text = ocrItem.getString("text");//ocr 识别的文本 @@ -185,82 +189,82 @@ public class OcrIdentifyServiceImpl extends ServiceImpl"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v,ruleInfo); } } - }else{ + } else { if (StringUtils.isBlank(text)) { //ocr识别参数为空,不通过 rMessage.append(value.getFieldName() + "参数未获取到结果
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false); - } else if(StringUtils.isBlank(inputText)){ + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false,ruleInfo); + } else if (StringUtils.isBlank(inputText)) { //没有输入值. fieldRightMap.put(field, true); - ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "没有输入值不做匹配", true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "没有输入值不做匹配", true,null); } else if ("0".equals(ruleInfo)) { //不必校验,有识别到就行,通过 fieldRightMap.put(field, true); - ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true); - } else if(Double.valueOf(ruleInfo)>=1 && Double.valueOf(ruleInfo)<=99){ + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true,ruleInfo); + } else if (Double.valueOf(ruleInfo) >= 1 && Double.valueOf(ruleInfo) <= 99) { //在1~99之间,根据精准度匹配 double v = StrCharUtil.similarityRatio(inputText, text); - if (v>=Double.valueOf(ruleInfo)) { + if (v >= Double.valueOf(ruleInfo)) { //准确度 可靠 fieldRightMap.put(field, true); - ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true,v); - }else{ + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v,ruleInfo); + } else { rMessage.append(value.getFieldName() + "参数不匹配
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v,ruleInfo); } } else if ("100".equals(ruleInfo)) { //必定验证参数,必须有值且匹配 double v = StrCharUtil.similarityRatio(inputText, text); if (text.equals(inputText)) { fieldRightMap.put(field, true); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, "", true,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v,ruleInfo); } else { rMessage.append(value.getFieldName() + "参数不匹配
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v,ruleInfo); } } } } - }else{ + } else { rMessage.append(value.getFieldName() + "参数未获取到结果
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false,ruleInfo); } } else { - rMessage.append(value.getFieldName() + "参数未获取到结果
"); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, null, 0d, imgPath, value.getFieldName() + "参数未获取到结果", false); + rMessage.append(value.getFieldName() + "参数未获取到结果
"); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, 0d, imgPath, value.getFieldName() + "参数未获取到结果", false,ruleInfo); fieldRightMap.put(field, false); } } - if (fieldRightMap != null && fieldRightMap.values().size()>0) { + if (fieldRightMap != null && fieldRightMap.values().size() > 0) { if (!fieldRightMap.containsValue(false)) { ocrIdentifyDetail.setStatus("1");//全部通过 - } else if(fieldRightMap.containsValue(false) && fieldRightMap.containsValue(true)){ + } else if (fieldRightMap.containsValue(false) && fieldRightMap.containsValue(true)) { ocrIdentifyDetail.setStatus("2");//有成功,有失败(部分) ocrIdentifyDetail.setMessage(rMessage.toString()); - } else{ + } else { ocrIdentifyDetail.setStatus("0");//有失败的 ocrIdentifyDetail.setMessage(rMessage.toString()); } - }else{ + } else { ocrIdentifyDetail.setStatus("0");//有失败的 ocrIdentifyDetail.setMessage(rMessage.toString()); } @@ -317,7 +321,7 @@ public class OcrIdentifyServiceImpl extends ServiceImpl updateWrapper = new LambdaUpdateWrapper(); updateWrapper.eq(OcrIdentify::getId, id); List identifyDetailList = ocrIdentifyDetailService.listByIdentifyId(id); - if(true) { + if (true) { if (identifyDetailList != null && identifyDetailList.size() > 0) { Map fieldRightMap = new LinkedHashMap<>(); String tag = null; @@ -336,7 +340,7 @@ public class OcrIdentifyServiceImpl extends ServiceImpl e.getFailureReason()).collect(Collectors.joining(";")); // if (configRuleTypeMap.containsKey(OcrConstant.ruleCheckSplitChar)) { - if (errorResults.size() > 0) { - //匹配失败. - updateWrapper.set(OcrIdentify::getErrorMsg, errorMsg); - updateWrapper.set(OcrIdentify::getTaskResult, 0); - } else { - //匹配成功. - updateWrapper.set(OcrIdentify::getTaskResult, 1); - } + if (errorResults.size() > 0) { + //匹配失败. + updateWrapper.set(OcrIdentify::getErrorMsg, errorMsg); + updateWrapper.set(OcrIdentify::getTaskResult, 0); + } else { + //匹配成功. + updateWrapper.set(OcrIdentify::getTaskResult, 1); + } String taskResultInfo = JSONArray.toJSONString(ocrResults); - updateWrapper.set(OcrIdentify::getStatus,"1"); - updateWrapper.set(OcrIdentify::getEndTime,new Date()); - updateWrapper.set(OcrIdentify::getTaskResultInfo,taskResultInfo); + updateWrapper.set(OcrIdentify::getStatus, "1"); + updateWrapper.set(OcrIdentify::getEndTime, new Date()); + updateWrapper.set(OcrIdentify::getTaskResultInfo, taskResultInfo); } } super.update(updateWrapper); @@ -369,11 +373,10 @@ public class OcrIdentifyServiceImpl extends ServiceImpl identifyDetails = ocrIdentifyDetailService.listByIdentifyId(ocrIdentifyVo.getId()); - - for (OcrIdentifyDetail identifyDetail : identifyDetails) { + /*for (OcrIdentifyDetail identifyDetail : identifyDetails) { JSONObject semanticResult = JSONObject.parseObject(identifyDetail.getSemanticResult()); String imgPath = identifyDetail.getImageUrl(); // 进行数据化 结构 @@ -381,7 +384,7 @@ public class OcrIdentifyServiceImpl extends ServiceImpl checkSemanticModelMap = getCheckSemanticModelMap(ocrRuleCheckVo.getConfigRuleMap(), ocrRuleCheckVo.getFieldMap(), ocrIdentifyVo.getSourceJsonObjects()); //// - String text=null;//ocr 识别的文本, + String text = null;//ocr 识别的文本, Double probability = 0d; //用于数据结构化的对象 List ocrResultList = new ArrayList<>(); @@ -389,7 +392,8 @@ public class OcrIdentifyServiceImpl extends ServiceImpl fieldRightMap = new LinkedHashMap<>();//存放 字段判断正确map //========================== - checkSemanticFor: for (CheckSemanticModel value : checkSemanticModelMap.values()) { + checkSemanticFor: + for (CheckSemanticModel value : checkSemanticModelMap.values()) { String field = value.getField(); String fieldName = value.getFieldName();//校验的字段名称 String ruleInfo = value.getRuleInfo();//是否绝对判断 0-绝对判断,1-不绝对判断 @@ -407,8 +411,9 @@ public class OcrIdentifyServiceImpl extends ServiceImpl0) { - ocrArrayFor: for (int i = 0; i < ocrArray.size(); i++) { + if (ocrArray.size() > 0) { + ocrArrayFor: + for (int i = 0; i < ocrArray.size(); i++) { JSONObject ocrItem = ocrArray.get(i); text = null; text = ocrItem.getString("text");//ocr 识别的文本 @@ -418,26 +423,26 @@ public class OcrIdentifyServiceImpl extends ServiceImpl"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v); } } - }else{ + } else { if (StringUtils.isBlank(text)) { //ocr识别参数为空,不通过 rMessage.append(value.getFieldName() + "参数未获取到结果
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false); - } else if(StringUtils.isBlank(inputText)){ + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false); + } else if (StringUtils.isBlank(inputText)) { //没有输入值. fieldRightMap.put(field, true); ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "没有输入值不做匹配", true); @@ -445,67 +450,65 @@ public class OcrIdentifyServiceImpl extends ServiceImpl=1 && Double.valueOf(ruleInfo)<=99){ + } else if (Double.valueOf(ruleInfo) >= 1 && Double.valueOf(ruleInfo) <= 99) { //在1~99之间,根据精准度匹配 double v = StrCharUtil.similarityRatio(inputText, text); - if (v>=Double.valueOf(ruleInfo)) { + if (v >= Double.valueOf(ruleInfo)) { //准确度 可靠 fieldRightMap.put(field, true); - ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true,v); - }else{ + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v); + } else { rMessage.append(value.getFieldName() + "参数不匹配
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v); } } else if ("100".equals(ruleInfo)) { //必定验证参数,必须有值且匹配 double v = StrCharUtil.similarityRatio(inputText, text); if (text.equals(inputText)) { fieldRightMap.put(field, true); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, "", true,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v); } else { rMessage.append(value.getFieldName() + "参数不匹配
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false,v); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v); } } } } - }else{ + } else { rMessage.append(value.getFieldName() + "参数未获取到结果
"); mapPutIfTrue(fieldRightMap, field, false); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false); } } else { - rMessage.append(value.getFieldName() + "参数未获取到结果
"); - ocrResultAdd(ocrResultList,value.getFieldName(), field, inputText, null, 0d, imgPath, value.getFieldName() + "参数未获取到结果", false); + rMessage.append(value.getFieldName() + "参数未获取到结果
"); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, 0d, imgPath, value.getFieldName() + "参数未获取到结果", false); fieldRightMap.put(field, false); } } //其中有一个字段 全部都是 失败,则该图片失败. - if (fieldRightMap != null && fieldRightMap.values().size()>0) { + if (fieldRightMap != null && fieldRightMap.values().size() > 0) { if (!fieldRightMap.containsValue(false)) { identifyDetail.setStatus("1");//全部通过 - } else if(fieldRightMap.containsValue(false) && fieldRightMap.containsValue(true)){ + } else if (fieldRightMap.containsValue(false) && fieldRightMap.containsValue(true)) { identifyDetail.setStatus("2");//有成功,有失败(部分) identifyDetail.setMessage(rMessage.toString()); - } else{ + } else { identifyDetail.setStatus("0");//有失败的 identifyDetail.setMessage(rMessage.toString()); } - }else{ + } else { identifyDetail.setStatus("0");//有失败的 identifyDetail.setMessage(rMessage.toString()); } identifyDetail.setDataStructured(JSONArray.toJSONString(ocrResultList));//数据结构化 ocrIdentifyDetailService.updateById(identifyDetail); } - } - + }*/ //=======规则检查配置 OcrRuleCheckVo ocrRuleCheckVo = ocrIdentifyVo.getOcrRuleCheckVo(); Map> configRuleTypeMap = ocrRuleCheckVo.getConfigRuleTypeMap(); - //=================== //4.更新主任务状态 /*LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper(); @@ -568,13 +571,13 @@ public class OcrIdentifyServiceImpl extends ServiceImpl=i){ + if (textSplit.length >= i) { for (int p = 0; p < textSplit.length; p++) { trueNum++; } - }else{ + } else { break; } } @@ -582,8 +585,8 @@ public class OcrIdentifyServiceImpl extends ServiceImpl ocrResultList,String fieldName, String field, String inputText, String ocrText, Double ocrPrecisionRate, String imgPath, String failureReason, Boolean ruleValidation,Double d) { + /** + * + * @param ocrResultList + * @param fieldName + * @param field + * @param inputText + * @param ocrText + * @param ocrPrecisionRate + * @param imgPath + * @param failureReason + * @param ruleValidation + * @param d + * @param ruleValidationValue 检查要求 + */ + public static void ocrResultAdd(List ocrResultList, String fieldName, String field, String inputText, String ocrText, Double ocrPrecisionRate, String imgPath, String failureReason, Boolean ruleValidation, Double d,String ruleValidationValue) { OcrResult ocrResult = new OcrResult(); ocrResult.setTag(field); ocrResult.setTagName(fieldName); ocrResult.setOcrText(ocrText); ocrResult.setInputText(inputText); ocrResult.setOcrPrecisionRate(ocrPrecisionRate == null ? 0d : ocrPrecisionRate); - if (d==null) { + if (d == null) { ocrResult.setTextRate(0d); - }else{ - ocrResult.setTextRate(new BigDecimal(d).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue()); + } else { + ocrResult.setTextRate(new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); } System.out.println("-----------------"); System.out.println(failureReason); @@ -707,6 +724,18 @@ public class OcrIdentifyServiceImpl extends ServiceImpl(); } ocrResult.setRuleValidation(ruleValidation); + if ("0".equals(ruleValidationValue)) { + ocrResult.setRuleValidationText("有名称就算过"); + }else if(Double.valueOf(ruleValidationValue)>0 &&Double.valueOf(ruleValidationValue)<=99){ + ocrResult.setRuleValidationText("匹配度>="+ruleValidationValue); + }else if("100".equals(ruleValidation)){ + ocrResult.setRuleValidationText("名称必须与参数完全一致"); + }else if("101".equals(ruleValidationValue)){ + ocrResult.setRuleValidationText("有值必须匹配无值算过"); + }else if("isrule=1".equals(ruleValidationValue)){ + ocrResult.setRuleValidationText("依据输入参数必须一致判断"); + } + ocrResultList.add(ocrResult); } @@ -721,11 +750,11 @@ public class OcrIdentifyServiceImpl extends ServiceImpl ocrResultList,String fieldName, String field, String inputText, String ocrText, Double ocrPrecisionRate, String imgPath, String failureReason, Boolean ruleValidation) { + public static void ocrResultAdd(List ocrResultList, String fieldName, String field, String inputText, String ocrText, Double ocrPrecisionRate, String imgPath, String failureReason, Boolean ruleValidation,String ruleValidationValue) { if (ruleValidation) { - ocrResultAdd(ocrResultList,fieldName,field,inputText,ocrText,ocrPrecisionRate,imgPath,failureReason,ruleValidation,100d); - }else{ - ocrResultAdd(ocrResultList,fieldName,field,inputText,ocrText,ocrPrecisionRate,imgPath,failureReason,ruleValidation,0d); + ocrResultAdd(ocrResultList, fieldName, field, inputText, ocrText, ocrPrecisionRate, imgPath, failureReason, ruleValidation, 100d,ruleValidationValue); + } else { + ocrResultAdd(ocrResultList, fieldName, field, inputText, ocrText, ocrPrecisionRate, imgPath, failureReason, ruleValidation, 0d,ruleValidationValue); } } @@ -757,7 +786,7 @@ public class OcrIdentifyServiceImpl extends ServiceImpl updateWrapper=new LambdaUpdateWrapper<>(); - updateWrapper.set(OcrIdentify::getStartTime,new Date()); - updateWrapper.set(OcrIdentify::getStatus,"2"); + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.set(OcrIdentify::getStartTime, new Date()); + updateWrapper.set(OcrIdentify::getStatus, "2"); updateWrapper.isNull(OcrIdentify::getStartTime); - updateWrapper.eq(OcrIdentify::getId,id); + updateWrapper.eq(OcrIdentify::getId, id); super.update(updateWrapper); } @@ -873,15 +902,157 @@ public class OcrIdentifyServiceImpl extends ServiceImpl identifyIdList = ocrIdentifyCallbackLogService.findIdentifyIdGroupGtCount(autoPushNoticeMaxNum); //获取 待通知的任务,排除已达到指定次数的任务 - LambdaQueryWrapper queryWrapper=new LambdaQueryWrapper<>(); - if (identifyIdList!=null&&identifyIdList.size()>0) { - queryWrapper.notIn(OcrIdentify::getId,identifyIdList); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (identifyIdList != null && identifyIdList.size() > 0) { + queryWrapper.notIn(OcrIdentify::getId, identifyIdList); } - queryWrapper.eq(OcrIdentify::getNoticeStatus,0); + queryWrapper.eq(OcrIdentify::getNoticeStatus, 0); List list = super.list(queryWrapper); return list; } + @Override + public void simulateChecks(SimulateChecksVO simulateChecksVO) { + List identifyDetailList = ocrIdentifyDetailService.listByIds(simulateChecksVO.getIdentifyDetailIdList()); + //遍历任务,做匹配 + int i1=1; + for (OcrIdentifyDetail ocrIdentifyDetail : identifyDetailList) { + if (i1==1) { + ocrIdentifyDetail.setSemanticResult("{\"ocr_res\":[[[[1282.0,1576.0],[2764.0,1594.0],[2763.0,1671.0],[1281.0,1653.0]],[\"北京市朝阳区三里屯社区卫生服务中心\",0.9670220613479614]],[[[132.0,2244.0],[1062.0,2214.0],[1069.0,2455.0],[140.0,2485.0]],[\"儿科专家门诊\",0.984556257724762]],[[[117.0,2496.0],[1036.0,2473.0],[1038.0,2577.0],[119.0,2600.0]],[\"Pediatric srecialistclinic\",0.8756008148193359]]],\"其他\":[{\"area\":[[117.0,2496.0],[1036.0,2473.0],[1038.0,2577.0],[119.0,2600.0]],\"end\":26,\"ocrText\":\"Pediatric srecialistclinic\",\"probability\":0.9925054592526585,\"start\":0,\"text\":\"Pediatric srecialistclinic\"}],\"医院名称\":[{\"area\":[[1282.0,1576.0],[2764.0,1594.0],[2763.0,1671.0],[1281.0,1653.0]],\"end\":17,\"ocrText\":\"北京市朝阳区三里屯社区卫生服务中心\",\"probability\":0.9681764264135495,\"start\":0,\"text\":\"北京市朝阳区三里屯社区卫生服务中心\"},{\"area\":[[1282.0,1576.0],[2764.0,1594.0],[2763.0,1671.0],[1281.0,1653.0]],\"end\":17,\"ocrText\":\"北京市朝阳区农光里医院\",\"probability\":0.95,\"start\":0,\"text\":\"北京市朝阳区农光里医院\"}],\"姓名\":[],\"时间\":[],\"科室\":[{\"area\":[[132.0,2244.0],[1062.0,2214.0],[1069.0,2455.0],[140.0,2485.0]],\"end\":6,\"ocrText\":\"儿科专家门诊\",\"probability\":0.9836859327676066,\"start\":0,\"text\":\"儿科专家门诊\"}]}"); + } + i1++; + String semanticResultJson = ocrIdentifyDetail.getSemanticResult(); + String imgPath = ocrIdentifyDetail.getImageUrl(); + if (StringUtils.isBlank(semanticResultJson)) continue; + String doctorName = simulateChecksVO.getDoctorName(); + String hospitalName = simulateChecksVO.getHospitalName(); + String departmentName = simulateChecksVO.getDepartmentName(); + String time = simulateChecksVO.getTime(); + List sourceJson = new ArrayList<>(); + if (StringUtils.isNotBlank(doctorName)) { + sourceJson.add(JSONObject.parseObject(String.format("{\"tag\":\"doctorName\", \"inputText\":\"%s\"}", doctorName))); + } + if (StringUtils.isNotBlank(hospitalName)) { + sourceJson.add(JSONObject.parseObject(String.format("{\"tag\":\"hospitalName\", \"inputText\":\"%s\"}", hospitalName))); + } + if (StringUtils.isNotBlank(departmentName)) { + sourceJson.add(JSONObject.parseObject(String.format("{\"tag\":\"departmentName\", \"inputText\":\"%s\"}", departmentName))); + } + if (StringUtils.isNotBlank(time)) { + sourceJson.add(JSONObject.parseObject(String.format("{\"tag\":\"time\", \"inputText\":\"%s\"}", time))); + } + JSONObject semanticResult = JSONObject.parseObject(semanticResultJson); + OcrRuleCheckVo ocrRuleCheckVo = ocrRuleCheckService.findById(simulateChecksVO.getRuleCheckId()); + Map checkSemanticModelMap = getCheckSemanticModelMap(ocrRuleCheckVo.getConfigRuleMap(), ocrRuleCheckVo.getFieldMap(), sourceJson); + String text = null;//ocr 识别的文本 + Double probability = 0d; + //用于数据结构化的对象 + List ocrResultList = new ArrayList<>(); + StringBuffer rMessage = new StringBuffer(); + Map fieldRightMap = new LinkedHashMap<>();//存放 字段判断正确map + //========================== + checkSemanticFor: for (CheckSemanticModel value : checkSemanticModelMap.values()) { + String field = value.getField(); + String fieldName = value.getFieldName();//校验的字段名称 + String ruleInfo = value.getRuleInfo();//是否绝对判断 0-绝对判断,1-不绝对判断 + String inputText = value.getInputText();//校验文本 ,ocr识别的文本如果不包含该内容,则算作失败 + List fieldNameList = Arrays.asList(fieldName.split(",")); + text = null; + boolean b = ArrayOUtils.containsStringList(fieldNameList, semanticResult.keySet().stream().collect(Collectors.toList())); + //查看ocr识别返回的字段名称中是否有当前这个字段名称 + if (b) { + //TODO 注意,ocr 识别返回的 字段是多个结果(数组),有一个值匹配上即为正确 + List ocrArray = new ArrayList<>(); + for (String s : fieldNameList) { + JSONArray jsonArray = semanticResult.getJSONArray(s); + if (jsonArray != null && jsonArray.size() > 0) { + ocrArray.addAll(jsonArray.toJavaList(JSONObject.class)); + } + } + if (ocrArray.size() > 0) { + ocrArrayFor: + for (int i = 0; i < ocrArray.size(); i++) { + JSONObject ocrItem = ocrArray.get(i); + text = null; + text = ocrItem.getString("text");//ocr 识别的文本 + probability = ocrItem.getDouble("probability");//置信度 + log.info("ocrItem:"); + log.info(ocrItem.toJSONString()); + if ("101".equals(ruleInfo)) { + if (StringUtils.isBlank(text) || StringUtils.isBlank(inputText)) { + //没识别值 + mapPutIfTrue(fieldRightMap, field, true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数不判断", true,ruleInfo); + } else { + double v = StrCharUtil.similarityRatio(inputText, text); + if (text.contains(inputText)) { + mapPutIfTrue(fieldRightMap, field, true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v,"101"); + } else { + rMessage.append(value.getFieldName() + "参数不匹配
"); + mapPutIfTrue(fieldRightMap, field, false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v,ruleInfo); + } + } + } else { + if (StringUtils.isBlank(text)) { + //ocr识别参数为空,不通过 + rMessage.append(value.getFieldName() + "参数未获取到结果
"); + mapPutIfTrue(fieldRightMap, field, false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false,ruleInfo); + } else if (StringUtils.isBlank(inputText)) { + //没有输入值. + fieldRightMap.put(field, true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "没有输入值不做匹配", true,null); + } else if ("0".equals(ruleInfo)) { + //不必校验,有识别到就行,通过 + fieldRightMap.put(field, true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true,ruleInfo); + } else if (Double.valueOf(ruleInfo) >= 1 && Double.valueOf(ruleInfo) <= 99) { + //在1~99之间,根据精准度匹配 + double v = StrCharUtil.similarityRatio(inputText, text); + if (v >= Double.valueOf(ruleInfo)) { + //准确度 可靠 + fieldRightMap.put(field, true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v,ruleInfo); + } else { + rMessage.append(value.getFieldName() + "参数不匹配
"); + mapPutIfTrue(fieldRightMap, field, false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v,ruleInfo); + } + } else if ("100".equals(ruleInfo)) { + //必定验证参数,必须有值且匹配 + double v = StrCharUtil.similarityRatio(inputText, text); + if (text.equals(inputText)) { + fieldRightMap.put(field, true); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, "", true, v,ruleInfo); + } else { + rMessage.append(value.getFieldName() + "参数不匹配
"); + mapPutIfTrue(fieldRightMap, field, false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, text, probability, imgPath, value.getFieldName() + "参数不匹配", false, v,ruleInfo); + } + } + } + } + } else { + rMessage.append(value.getFieldName() + "参数未获取到结果
"); + mapPutIfTrue(fieldRightMap, field, false); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, probability, imgPath, value.getFieldName() + "参数未获取到结果", false,ruleInfo); + } + } else { + rMessage.append(value.getFieldName() + "参数未获取到结果
"); + ocrResultAdd(ocrResultList, value.getFieldName(), field, inputText, null, 0d, imgPath, value.getFieldName() + "参数未获取到结果", false,ruleInfo); + fieldRightMap.put(field, false); + } + } + System.out.println("----------------------"); + for (OcrResult result : ocrResultList) { + System.out.println(result.toString()); + } + + } + } + @Transactional(rollbackFor = Exception.class) public void executeTask() { //获取任务 diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/vo/SimulateChecksVO.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/vo/SimulateChecksVO.java new file mode 100644 index 0000000..7d74e13 --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/ocr/vo/SimulateChecksVO.java @@ -0,0 +1,31 @@ +package org.jeecg.modules.ocr.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @Description 模拟实验-模拟检查 + * @Author ZhouWenTao + * @Date 2023/8/22 15:06 + */ +@ApiModel(value = "模拟检查对象") +@Data +public class SimulateChecksVO { + @ApiModelProperty(value = "识别任务id") + private String identifyId; + @ApiModelProperty(value = "明细信息id") + private List identifyDetailIdList; + @ApiModelProperty(value = "规则检查配置id") + private String ruleCheckId; + @ApiModelProperty(value = "医院名称") + private String hospitalName; + @ApiModelProperty(value = "医生名称") + private String doctorName; + @ApiModelProperty(value = "科室名称") + private String departmentName; + @ApiModelProperty(value = "时间") + private String time; +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java index 21e4bdf..a0f23ad 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java @@ -136,7 +136,7 @@ public class CommonController { try { String ctxPath = uploadpath; String fileName = null; - File file = new File(ctxPath + File.separator + bizPath + File.separator ); + File file = new File(ctxPath + File.separator + bizPath + File.separator); if (!file.exists()) { // 创建文件根目录 file.mkdirs(); diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml index f96ff5e..b7af88c 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml @@ -185,7 +185,7 @@ jeecg: app: http://localhost:8051 path: #文件上传根目录 设置 - upload: /opt/upFiles + upload: /data/ocr/upFiles #webapp文件路径 webapp: /opt/webapp shiro: diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml index b10769f..0f6f5fe 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml @@ -181,7 +181,7 @@ jeecg: app: http://localhost:8051 path: #文件上传根目录 设置 - upload: /opt/jeecg-boot/upload + upload: /data/ocr/upload #webapp文件路径 webapp: /opt/jeecg-boot/webapp shiro: diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml index 8b142c7..ae22210 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml @@ -185,7 +185,7 @@ jeecg: app: http://localhost:8051 path: #文件上传根目录 设置 - upload: /opt/upFiles + upload: /data/ocr/upFiles #webapp文件路径 webapp: /opt/webapp shiro: