From ee3057197684b10fe13ce51866de6564c88007a7 Mon Sep 17 00:00:00 2001 From: yinhuaiwei Date: Mon, 9 Nov 2026 14:41:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=AF=BB=E6=95=B0null=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E4=B8=BA=E5=BC=82=E5=B8=B8;=E7=BA=A2=E5=A4=96=E6=B8=A9?= =?UTF-8?q?=E5=BA=A6=E4=BC=A0=E6=9C=80=E9=AB=98=E6=B8=A9=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/AnalyseResponseServiceImpl.java | 1 - .../analysis/utils/ResultAnalysisUtils.java | 408 +++++++++++++++++- 2 files changed, 404 insertions(+), 5 deletions(-) diff --git a/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/service/impl/AnalyseResponseServiceImpl.java b/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/service/impl/AnalyseResponseServiceImpl.java index a3e3855..5d379f5 100644 --- a/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/service/impl/AnalyseResponseServiceImpl.java +++ b/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/service/impl/AnalyseResponseServiceImpl.java @@ -923,7 +923,6 @@ public class AnalyseResponseServiceImpl implements IAnalyseResponseService { if (avgValue != null) { String formattedAvgValue = avgValue.setScale(1, RoundingMode.HALF_UP).toPlainString(); patrolData.setAvgValue(formattedAvgValue); - patrolData.setResValue(formattedAvgValue); } } } diff --git a/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/utils/ResultAnalysisUtils.java b/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/utils/ResultAnalysisUtils.java index eb99a52..2bc6679 100644 --- a/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/utils/ResultAnalysisUtils.java +++ b/inspect-main/inspect-main-task/src/main/java/com/inspect/analysis/utils/ResultAnalysisUtils.java @@ -107,11 +107,11 @@ public class ResultAnalysisUtils { } if ("meter".equals(algType)) { - boolean hasErrorValue = Arrays.stream(correctionValue.split(StringUtils.COMMA)).anyMatch(v -> StringUtils.isEmpty(v) || "null".equals(v)) ; + boolean hasErrorValue = Arrays.stream(correctionValue.split(StringUtils.COMMA)).map(String::trim).anyMatch(v -> StringUtils.isEmpty(v) || "null".equals(v)) ; if (hasErrorValue) { - resultAnalysis.setResStatus("0"); - resultAnalysis.setPointStatus(PointStatusEnum.DEFECT.getCode()); - resultAnalysis.setResultType(ResultTypeEnum.DEFECT.getCode()); + resultAnalysis.setResStatus(ResStatusEnum.UNCONFIRM.getCode()); + resultAnalysis.setPointStatus(PointStatusEnum.ABNORMAL.getCode()); + resultAnalysis.setResultType(ResultTypeEnum.ABNORMAL.getCode()); resultAnalysis.setDescription("读数失败"); return; } @@ -472,6 +472,406 @@ public class ResultAnalysisUtils { log.info("------------------parseAlg resultAnalysis: {}", resultAnalysis); } + /** + * parseAlg 的重构版本,保留原方法用于对比。 + * + * 与 parseAlg 相比主要修复: + * 1. 原始值与 formatValue 后的值分开保存,表计类按逗号拆分后逐个判断,避免只取第一个值; + * 2. gis_meter 也纳入读数失败判断; + * 3. 修复 value == "null" 的引用比较; + * 4. correction 不再在方法末尾强制 resultType=1; + * 5. 状态赋值统一收敛到 markNormal/markDefect/markAbnormal。 + * + * 注意:本方法暂未替换调用方,便于与 parseAlg 并行对比。 + */ + public void parseAlg2(String algType, AlgValue algValue, String value, String defaultDesc, ResultAnalysis resultAnalysis) { + log.info("PARSE_ALG2 algType: {}, algValue: {}, value: {}, defaultDesc: {}", algType, algValue, value, defaultDesc); + + // 初筛红外:非 infrared 的红外算法在初筛阶段直接按正常展示 + if ("1".equals(resultAnalysis.getFilter()) + && !AlgConstants.INFRARED.equals(algType) + && AlgConstants.ALG_INFRARED_LIST.contains(algType)) { + markNormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + resultAnalysis.setResValue("--"); + resultAnalysis.setDescription("-"); + resultAnalysis.setCreateTime(new Date()); + return; + } + + String rawValue = value == null ? "" : value.trim(); + AlgValue safeAlgValue = algValue == null ? new AlgValue() : algValue; + String formattedValue = safeAlgValue.formatValue(rawValue); + formattedValue = formattedValue == null ? "" : formattedValue.trim(); + + // filter=1 时,非红外算法不再进入具体算法分支(对应原逻辑 algType="") + boolean skipAlgorithm = "1".equals(resultAnalysis.getFilter()) + && !AlgConstants.INFRARED.equals(algType); + String effectiveAlgType = skipAlgorithm ? "" : algType; + if (effectiveAlgType == null) { + log.warn("parseAlg2 algType is null!"); + return; + } + + boolean meterLike = AlgConstants.METER.equals(effectiveAlgType) + || AlgConstants.GIS_METER.equals(effectiveAlgType); + // 表计类自己处理空值和多值,其余算法沿用原来的空值哨兵 + if (!meterLike && isReadFailureValue(formattedValue)) { + applyEmptyResult(effectiveAlgType, resultAnalysis); + return; + } + + String desc; + if (skipAlgorithm) { + desc = parseDefault(formattedValue, defaultDesc, resultAnalysis); + } else if (meterLike) { + desc = parseMeterOrGisMeter(effectiveAlgType, safeAlgValue, rawValue, defaultDesc, resultAnalysis); + } else if ("qrcode".equals(effectiveAlgType) || "light".equals(effectiveAlgType)) { + markNormal(resultAnalysis, ResStatusEnum.CONFIRM.getCode()); + desc = defaultDesc; + } else if ("switch".equals(effectiveAlgType)) { + desc = parseSwitch(rawValue, resultAnalysis); + } else if (AlgConstants.GIS_METER_2.equals(effectiveAlgType)) { + desc = parseGisMeter2(safeAlgValue, rawValue, resultAnalysis); + } else if ("sound".equals(effectiveAlgType)) { + desc = parseSound(formattedValue, resultAnalysis); + } else if (AlgConstants.ALG_INFRARED_LIST.contains(effectiveAlgType) + || "xb".equals(effectiveAlgType)) { + desc = parseInfrared(safeAlgValue, formattedValue, resultAnalysis); + } else if ("isolator".equals(effectiveAlgType)) { + desc = parseIsolator(formattedValue, resultAnalysis); + } else if (AlgConstants.CORRECTION.equals(effectiveAlgType)) { + desc = parseCorrection(rawValue, resultAnalysis); + } else { + desc = parseDefault(formattedValue, defaultDesc, resultAnalysis); + } + + resultAnalysis.setDescription(desc); + resultAnalysis.setCreateTime(new Date()); + log.info("------------------parseAlg2 resultAnalysis: {}", resultAnalysis); + } + + private boolean isReadFailureValue(String value) { + return StringUtils.isEmpty(value) || "-1".equals(value) || "null".equals(value); + } + + private void applyEmptyResult(String algType, ResultAnalysis resultAnalysis) { + log.info("PARSE_ALG2_EMPTY algType: {}", algType); + String desc; + if (AlgConstants.METER.equals(algType) || AlgConstants.GIS_METER.equals(algType)) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = "读数失败"; + } else { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = AlgConstants.INFRARED.equals(algType) ? "读数失败" : "算法内部异常"; + } + resultAnalysis.setResValue("--"); + resultAnalysis.setDescription(desc); + resultAnalysis.setCreateTime(new Date()); + } + + private void markNormal(ResultAnalysis resultAnalysis, String resStatus) { + markResult(resultAnalysis, PointStatusEnum.NORMAL.getCode(), + ResultTypeEnum.NORMAL.getCode(), resStatus); + } + + private void markDefect(ResultAnalysis resultAnalysis, String resStatus) { + markResult(resultAnalysis, PointStatusEnum.DEFECT.getCode(), + ResultTypeEnum.DEFECT.getCode(), resStatus); + } + + private void markAbnormal(ResultAnalysis resultAnalysis, String resStatus) { + markResult(resultAnalysis, PointStatusEnum.ABNORMAL.getCode(), + ResultTypeEnum.ABNORMAL.getCode(), resStatus); + } + + private void markResult(ResultAnalysis resultAnalysis, String pointStatus, + String resultType, String resStatus) { + resultAnalysis.setPointStatus(pointStatus); + resultAnalysis.setResultType(resultType); + resultAnalysis.setResStatus(resStatus); + } + + private String parseMeterOrGisMeter(String algType, AlgValue algValue, String rawValue, + String defaultDesc, ResultAnalysis resultAnalysis) { + String[] rawValues = rawValue.split(StringUtils.COMMA, -1); + List descs = new ArrayList<>(rawValues.length); + boolean hasDefect = false; + boolean hasAbnormal = false; + boolean evaluatedNumeric = false; + + for (String rawItem : rawValues) { + String item = rawItem == null ? "" : rawItem.trim(); + String formatted = algValue.formatValue(item); + formatted = formatted == null ? "" : formatted.trim(); + + if (isMeterReadFailure(algType, item, formatted)) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + if (StringUtils.isEmpty(rawValue) || "null".equals(rawValue) || "-1".equals(rawValue)) { + resultAnalysis.setResValue("--"); + } + return "读数失败"; + } + + if (isNormalToken(formatted)) { + descs.add("正常"); + continue; + } + + evaluatedNumeric = true; + AlgAlarmResult alarmResult = algValue.analyze(formatted); + if (!alarmResult.isAlarm()) { + descs.add("正常"); + } else if (AlgAlarmResult.Status.PARSE_ERROR == alarmResult.getStatus()) { + hasAbnormal = true; + descs.add("异常"); + } else { + hasDefect = true; + descs.add("表计超限" + alarmResult.messageSuffix()); + } + } + + if (hasDefect) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return joinDescriptions(descs); + } + if (hasAbnormal) { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return joinDescriptions(descs); + } + + markNormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + if (evaluatedNumeric && StringUtils.isNotEmpty(defaultDesc) && defaultDesc.contains("失败")) { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return defaultDesc; + } + return "正常"; + } + + private boolean isMeterReadFailure(String algType, String rawItem, String formatted) { + if (StringUtils.isEmpty(rawItem) || "null".equals(rawItem) || "null".equals(formatted)) { + return true; + } + if ("-1".equals(rawItem) || "-1".equals(formatted)) { + return true; + } + return AlgConstants.GIS_METER.equals(algType) && "10003".equals(formatted); + } + + private boolean isNormalToken(String formatted) { + if ("open".equalsIgnoreCase(formatted) + || "closed".equalsIgnoreCase(formatted) + || "off".equalsIgnoreCase(formatted) + || "on".equalsIgnoreCase(formatted) + || "正常".equals(formatted)) { + return true; + } + return formatted.contains("分OFF") || formatted.contains("分") || formatted.contains("合"); + } + + private String joinDescriptions(List descs) { + if (descs.isEmpty()) { + return "正常"; + } + if (descs.size() == 1) { + return descs.get(0); + } + return String.join(",", descs); + } + + private String parseSwitch(String rawValue, ResultAnalysis resultAnalysis) { + String[] values = rawValue.split(StringUtils.COMMA, -1); + boolean isDefect = false; + boolean isAbnormal = false; + for (String value : values) { + String item = value == null ? "" : value.trim(); + if ("灭".equals(item)) { + isDefect = true; + } + if (StringUtils.isEmpty(item) || "null".equals(item) + || "1".equals(item) || "未识别".equals(item)) { + isAbnormal = true; + } + } + + if (isDefect) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + } else if (isAbnormal) { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + } else { + markNormal(resultAnalysis, ResStatusEnum.CONFIRM.getCode()); + } + return rawValue; + } + + private String parseGisMeter2(AlgValue algValue, String rawValue, ResultAnalysis resultAnalysis) { + log.info("parseAlg2 gis_meter2 value: {}, resCode: {}", rawValue, resultAnalysis.getResCode()); + boolean hasDefect = false; + boolean hasReadFailure = false; + try { + String[] values = JSON.parseArray(rawValue, String.class).toArray(new String[0]); + String[] descs = new String[values.length]; + for (int i = 0; i < values.length; i++) { + String item = values[i]; + if (StringUtils.isEmpty(item)) { + hasReadFailure = true; + values[i] = "--"; + descs[i] = "读数失败"; + } else { + AlgAlarmResult itemAlarm = algValue.analyze(item); + if (itemAlarm.isAlarm()) { + hasDefect = true; + descs[i] = "表计超限" + itemAlarm.messageSuffix(); + } else { + descs[i] = "正常"; + } + } + } + String valueStr = String.join(",", values); + String descStr = String.join(",", descs); + resultAnalysis.setResValue(valueStr); + // 无人机表计所有读数失败都按缺陷处理 + if (hasDefect || hasReadFailure) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + } else { + markNormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + } + return descStr; + } catch (Exception e) { + log.error("parseAlg2 gis_meter2 parse error, value: {}", rawValue, e); + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "解析异常"; + } + } + + private String parseSound(String value, ResultAnalysis resultAnalysis) { + if ("1".equals(value)) { + markNormal(resultAnalysis, ResStatusEnum.CONFIRM.getCode()); + return "正常"; + } + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "异常"; + } + + private String parseInfrared(AlgValue algValue, String value, ResultAnalysis resultAnalysis) { + AlgAlarmResult alarmResult = algValue.analyze(value); + if (!alarmResult.isAlarm()) { + markNormal(resultAnalysis, ResStatusEnum.CONFIRM.getCode()); + return "正常"; + } + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "温度异常告警" + alarmResult.messageSuffix(); + } + + private String parseIsolator(String value, ResultAnalysis resultAnalysis) { + String desc; + if ("1".equals(value)) { + markNormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = "分"; + } else if ("2".equals(value)) { + markNormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = "合"; + } else if ("3".equals(value)) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = "分位异常"; + } else if ("4".equals(value)) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = "合位异常"; + } else { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + desc = "未检测到刀闸"; + } + resultAnalysis.setResValue(desc); + return desc; + } + + private String parseCorrection(String rawValue, ResultAnalysis resultAnalysis) { + String resCode = resultAnalysis.getResCode(); + log.info("parseAlg2 correction resCode: {}, value: {}", resCode, rawValue); + if ("2000".equals(resCode)) { + List> list = readCorrectionMatrix(rawValue); + if (isValidCorrectionMatrix(list)) { + markNormal(resultAnalysis, ResStatusEnum.CANCEL.getCode()); + resultAnalysis.setResValue(""); + return "无需纠偏"; + } + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "纠偏结果异常"; + } + if ("2001".equals(resCode)) { + List> list = readCorrectionMatrix(rawValue); + if (isValidCorrectionMatrix(list)) { + if (isAllZero(list)) { + markNormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "纠偏码异常"; + } + markDefect(resultAnalysis, ResStatusEnum.CORRECT.getCode()); + return "纠偏码异常请进行纠偏"; + } + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "纠偏码和值均异常"; + } + if ("2002".equals(resCode)) { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "超出比对范围"; + } + if ("2003".equals(resCode)) { + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "图像数据错误"; + } + markAbnormal(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + return "未知异常"; + } + + private List> readCorrectionMatrix(String rawValue) { + ObjectMapper mapper = new ObjectMapper(); + try { + log.info("parseAlg2 correction value: {}", rawValue); + List> list = mapper.readValue(rawValue, new TypeReference>>() { + }); + log.info("parseAlg2 correction parsed: {}", list); + return list; + } catch (Exception e) { + log.error("parseAlg2 correction parse error, value: {}", rawValue, e); + return new ArrayList<>(); + } + } + + private boolean isValidCorrectionMatrix(List> list) { + return list != null + && list.size() == 2 + && list.get(0) != null && list.get(0).size() == 2 + && list.get(1) != null && list.get(1).size() == 2; + } + + private boolean isAllZero(List> list) { + final double epsilon = 1e-8; + for (List row : list) { + for (Double value : row) { + if (value != null && Math.abs(value) >= epsilon) { + return false; + } + } + } + return true; + } + + private String parseDefault(String value, String defaultDesc, ResultAnalysis resultAnalysis) { + String desc = defaultDesc; + if ("0".equals(value)) { + markNormal(resultAnalysis, ResStatusEnum.CANCEL.getCode()); + desc = "正常"; + resultAnalysis.setSuggestion("系统审核"); + } else if ("1".equals(value)) { + markDefect(resultAnalysis, ResStatusEnum.UNCONFIRM.getCode()); + } + + if (StringUtils.isNotEmpty(desc) && desc.contains("分析失败")) { + resultAnalysis.setPointStatus(PointStatusEnum.ABNORMAL.getCode()); + resultAnalysis.setResultType(ResultTypeEnum.ABNORMAL.getCode()); + } + return desc; + } + /** * 将分析结果的辅助值进行合并展示 *