package com.jeesite.modules.mes.service; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.jeesite.common.lang.StringUtils; import com.jeesite.modules.mes.entity.MesProcessParamLimit; import com.jeesite.modules.mes.entity.MesProductArcWelding; import com.jeesite.modules.mes.entity.MesProductCmt; import com.jeesite.modules.mes.entity.MesProductProd; import com.jeesite.modules.mes.entity.MesProductQm; import com.jeesite.modules.mes.entity.MesWelderParamRecord; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 工艺参数上下限校验Service * @author mes * @version 2026-09-07 */ @Service public class MesProcessParamLimitCheckService { private static final Map ARC_PARAM_ALIASES = new HashMap<>(); static { ARC_PARAM_ALIASES.put("current", new String[]{"current", "current1", "current2", "robot1Current", "robot2Current", "i1", "i2", "I1", "I2"}); ARC_PARAM_ALIASES.put("current1", new String[]{"current1", "robot1Current", "i1", "I1"}); ARC_PARAM_ALIASES.put("current2", new String[]{"current2", "robot2Current", "i2", "I2"}); ARC_PARAM_ALIASES.put("voltage", new String[]{"voltage", "voltage1", "voltage2", "robot1Voltage", "robot2Voltage", "v1", "v2", "V1", "V2"}); ARC_PARAM_ALIASES.put("voltage1", new String[]{"voltage1", "robot1Voltage", "v1", "V1"}); ARC_PARAM_ALIASES.put("voltage2", new String[]{"voltage2", "robot2Voltage", "v2", "V2"}); ARC_PARAM_ALIASES.put("speed", new String[]{"speed", "speed1", "speed2", "wireSpeed", "wireFeedSpeed", "sendWireSpeed", "robot1Speed", "robot2Speed", "feedSpeed"}); ARC_PARAM_ALIASES.put("speed1", new String[]{"speed1", "robot1Speed", "wireSpeed", "wireFeedSpeed", "sendWireSpeed"}); ARC_PARAM_ALIASES.put("speed2", new String[]{"speed2", "robot2Speed", "wireSpeed", "wireFeedSpeed", "sendWireSpeed"}); } @Autowired private MesProcessParamLimitService mesProcessParamLimitService; public void markQm(List list, String qmCategory) { Map> limitMap = loadLimitMap(); if (list == null || list.isEmpty()) { return; } String processKey = normalizeProcessKey(qmCategory); for (MesProductQm row : list) { row.setLimitFlag(checkBeanRow(row, limitMap.get(processKey)) ? "1" : "0"); } } public void markProd(List list) { Map> limitMap = loadLimitMap(); if (list == null || list.isEmpty()) { return; } for (MesProductProd row : list) { row.setLimitFlag(checkBeanRow(row, limitMap.get("prod")) ? "1" : "0"); } } public void markWelder(List list) { Map> limitMap = loadLimitMap(); if (list == null || list.isEmpty()) { return; } for (MesWelderParamRecord row : list) { row.setLimitFlag(checkBeanRow(row, limitMap.get("welder")) ? "1" : "0"); } } public void markArc(List list, String weldingCategory) { markArc(list, weldingCategory, null); } public void markArc(List list, String weldingCategory, String processName) { Map> limitMap = loadLimitMap(); if (list == null || list.isEmpty()) { return; } for (MesProductArcWelding row : list) { String processKey = resolveArcProcessKey(row, weldingCategory, processName); row.setLimitFlag(checkArcRow(row, limitMap.get(processKey)) ? "1" : "0"); } } public void markCmt(List list) { Map> limitMap = loadLimitMap(); if (list == null || list.isEmpty()) { return; } List limits = limitMap.get("arc115"); for (MesProductCmt row : list) { row.setLimitFlag(checkArcContent(row == null ? null : row.getContent(), limits) ? "1" : "0"); } } public List findArcLimitRules(MesProductArcWelding row, String weldingCategory) { return findArcLimitRules(row, weldingCategory, null); } public List findArcLimitRules(MesProductArcWelding row, String weldingCategory, String processName) { Map> limitMap = loadLimitMap(); List limits = limitMap.get(resolveArcProcessKey(row, weldingCategory, processName)); return toArcLimitRules(limits); } public List findCmtLimitRules() { Map> limitMap = loadLimitMap(); return toArcLimitRules(limitMap.get("arc115")); } private List toArcLimitRules(List limits) { List result = new ArrayList<>(); if (limits == null || limits.isEmpty()) { return result; } for (NormalizedLimit limit : limits) { result.add(new ArcLimitRule(limit.paramCode, limit.lowerLimit, limit.upperLimit)); } return result; } public boolean checkArcRecord(MesProductArcWelding row, String weldingCategory) { return checkArcRecord(row, weldingCategory, null); } public boolean checkArcRecord(MesProductArcWelding row, String weldingCategory, String processName) { Map> limitMap = loadLimitMap(); return checkArcRow(row, limitMap.get(resolveArcProcessKey(row, weldingCategory, processName))); } public boolean checkCmtRecord(MesProductCmt row) { Map> limitMap = loadLimitMap(); return checkArcContent(row == null ? null : row.getContent(), limitMap.get("arc115")); } private Map> loadLimitMap() { Map> map = new HashMap<>(); for (MesProcessParamLimit limit : mesProcessParamLimitService.findEnabledList()) { String processKey = normalizeProcessKey(StringUtils.defaultString(limit.getProcessKey(), limit.getProcessName())); String paramCode = normalizeParamCode(StringUtils.defaultString(limit.getParamCode(), limit.getParamName())); if (StringUtils.isBlank(processKey) || StringUtils.isBlank(paramCode)) { continue; } NormalizedLimit normalized = new NormalizedLimit(processKey, paramCode, limit.getLowerLimit(), limit.getUpperLimit()); map.computeIfAbsent(processKey, k -> new ArrayList<>()).add(normalized); } return map; } private boolean checkBeanRow(Object row, List limits) { if (row == null || limits == null || limits.isEmpty()) { return false; } BeanWrapperImpl wrapper = new BeanWrapperImpl(row); for (NormalizedLimit limit : limits) { if (!wrapper.isReadableProperty(limit.paramCode)) { continue; } Object value = wrapper.getPropertyValue(limit.paramCode); if (isOutOfRange(value, limit)) { return true; } } return false; } private boolean checkArcRow(MesProductArcWelding row, List limits) { return checkArcContent(row == null ? null : row.getContent(), limits); } private boolean checkArcContent(String content, List limits) { if (limits == null || limits.isEmpty() || StringUtils.isBlank(content)) { return false; } for (JSONObject sample : parseArcSamples(content)) { for (NormalizedLimit limit : limits) { for (String value : readArcValues(sample, limit.paramCode)) { if (isOutOfRange(value, limit)) { return true; } } } } return false; } private List parseArcSamples(String content) { List result = new ArrayList<>(); try { String text = StringUtils.trim(content); if (StringUtils.isBlank(text)) { return result; } if (text.startsWith("{")) { JSONObject root = JSONObject.parseObject(text); JSONArray samples = root == null ? null : root.getJSONArray("samples"); if (samples != null) { for (int i = 0; i < samples.size(); i++) { JSONObject sample = samples.getJSONObject(i); if (sample != null) { result.add(sample); } } } return result; } if (text.startsWith("[")) { JSONArray arr = JSONArray.parseArray(text); if (arr != null) { for (int i = 0; i < arr.size(); i++) { String record = arr.getString(i); appendOldArcRecord(record, result); } } return result; } appendOldArcRecord(text, result); return result; } catch (Exception ex) { return result; } } private void appendOldArcRecord(String record, List result) { if (StringUtils.isBlank(record)) { return; } String valueText = StringUtils.trim(record); if (valueText.startsWith("\"") && valueText.endsWith("\"") && valueText.length() > 1) { valueText = StringUtils.trim(valueText.substring(1, valueText.length() - 1)); } if (StringUtils.isBlank(valueText)) { return; } String[] values = valueText.split("\\|"); if (values.length < 3) { return; } JSONObject sample = new JSONObject(); for (int i = 0; i < values.length; i++) { sample.put("v" + i, values[i]); } if (values.length >= 11) { sample.put("robot1Voltage", values[0]); sample.put("robot1Current", values[1]); sample.put("robot1Speed", values[2]); sample.put("robot2Voltage", values[5]); sample.put("robot2Current", values[6]); sample.put("robot2Speed", values[7]); sample.put("time", values[values.length - 1]); } result.add(sample); } private List readArcValues(JSONObject sample, String paramCode) { List values = new ArrayList<>(); String[] aliases = ARC_PARAM_ALIASES.get(paramCode); if (aliases == null || aliases.length == 0) { String value = sample.getString(paramCode); if (StringUtils.isNotBlank(StringUtils.trim(value))) { values.add(value.toString()); } return values; } for (String alias : aliases) { Object value = sample.get(alias); if (value != null && StringUtils.isNotBlank(StringUtils.trim(value.toString()))) { String text = value.toString(); if (!values.contains(text)) { values.add(text); } } } return values; } private boolean isOutOfRange(Object value, NormalizedLimit limit) { if (value == null || limit == null) { return false; } return isOutOfRange(value.toString(), limit); } private boolean isOutOfRange(String value, NormalizedLimit limit) { if (StringUtils.isBlank(value) || limit == null) { return false; } BigDecimal actual; try { actual = new BigDecimal(normalizeNumberText(value)); } catch (Exception ex) { return false; } BigDecimal lower = parseDecimal(limit.lowerLimit); BigDecimal upper = parseDecimal(limit.upperLimit); if (lower != null && upper != null && lower.compareTo(upper) > 0) { BigDecimal tmp = lower; lower = upper; upper = tmp; } if (lower != null && actual.compareTo(lower) < 0) { return true; } return upper != null && actual.compareTo(upper) > 0; } private BigDecimal parseDecimal(String value) { if (StringUtils.isBlank(value)) { return null; } try { return new BigDecimal(normalizeNumberText(value)); } catch (Exception ex) { return null; } } private String normalizeNumberText(String value) { if (value == null) { return null; } String text = StringUtils.trim(value); if (StringUtils.isBlank(text)) { return text; } return text.replace('\u2212', '-') // minus sign .replace('\u2013', '-') // en dash .replace('\u2014', '-') // em dash .replace('\uFF0D', '-') // full-width hyphen-minus .replace('\uFE63', '-') // small hyphen-minus .replace('\uFF0B', '+') // full-width plus .replace(" ", ""); } private String resolveArcProcessKey(MesProductArcWelding row, String weldingCategory) { return resolveArcProcessKey(row, weldingCategory, null); } private String resolveArcProcessKey(MesProductArcWelding row, String weldingCategory, String processName) { String category = normalizeProcessKey(processName); if (!isArcProcessKey(category)) { category = ""; } if (StringUtils.isBlank(category)) { category = normalizeProcessKey(weldingCategory); } if (StringUtils.isBlank(category) && row != null) { category = normalizeProcessKey(row.getWeldingCategory()); } if (StringUtils.isBlank(category)) { return "arc"; } if ("arc".equals(category)) { return "arcHev"; } if ("spot".equals(category)) { return "spotHev"; } return category; } private boolean isArcProcessKey(String processKey) { return "arc115".equals(processKey) || "arcHev".equals(processKey) || "spot115".equals(processKey) || "spotHev".equals(processKey) || "arc".equals(processKey) || "spot".equals(processKey); } private String normalizeProcessKey(String value) { if (StringUtils.isBlank(value)) { return ""; } String text = StringUtils.trim(value); if ("whitePart".equalsIgnoreCase(text) || "白件气密".equals(text)) { return "whitePart"; } if ("assembly".equalsIgnoreCase(text) || "总成气密".equals(text)) { return "assembly"; } if ("prod".equalsIgnoreCase(text) || "拉铆".equals(text)) { return "prod"; } if ("welder".equalsIgnoreCase(text) || "凸焊".equals(text)) { return "welder"; } if ("arc115".equalsIgnoreCase(text) || "115弧焊".equals(text) || "115弧焊参数".equals(text)) { return "arc115"; } if ("arcHev".equalsIgnoreCase(text) || "HEV弧焊".equalsIgnoreCase(text) || "HEV弧焊参数".equals(text)) { return "arcHev"; } if ("spot115".equalsIgnoreCase(text) || "115点焊".equals(text) || "115点焊参数".equals(text)) { return "spot115"; } if ("spotHev".equalsIgnoreCase(text) || "HEV点焊".equalsIgnoreCase(text) || "HEV点焊参数".equals(text)) { return "spotHev"; } if ("spot".equalsIgnoreCase(text)) { return "spot"; } if ("arc".equalsIgnoreCase(text)) { return "arc"; } return text; } private String normalizeParamCode(String value) { if (StringUtils.isBlank(value)) { return ""; } String text = StringUtils.trim(value); if ("current1".equalsIgnoreCase(text) || "电流1".equals(text)) { return "current1"; } if ("current2".equalsIgnoreCase(text) || "电流2".equals(text)) { return "current2"; } if ("voltage1".equalsIgnoreCase(text) || "电压1".equals(text)) { return "voltage1"; } if ("voltage2".equalsIgnoreCase(text) || "电压2".equals(text)) { return "voltage2"; } if ("speed1".equalsIgnoreCase(text) || "送丝速度1".equals(text)) { return "speed1"; } if ("speed2".equalsIgnoreCase(text) || "送丝速度2".equals(text)) { return "speed2"; } if ("testPressure".equalsIgnoreCase(text) || "测试压".equals(text)) { return "testPressure"; } if ("leakVal".equalsIgnoreCase(text) || "泄漏值".equals(text)) { return "leakVal"; } if ("fout".equalsIgnoreCase(text) || "拉力".equals(text)) { return "fout"; } if ("sout".equalsIgnoreCase(text) || "行程".equals(text)) { return "sout"; } if ("current".equalsIgnoreCase(text) || "电流".equals(text)) { return "current"; } if ("voltage".equalsIgnoreCase(text) || "电压".equals(text)) { return "voltage"; } if ("speed".equalsIgnoreCase(text) || "送丝速度".equals(text)) { return "speed"; } if ("capVoltage".equalsIgnoreCase(text) || "电容电压".equals(text)) { return "capVoltage"; } if ("weldPeakCurrent".equalsIgnoreCase(text) || "焊接峰值电流".equals(text)) { return "weldPeakCurrent"; } return text; } private static class NormalizedLimit { private final String processKey; private final String paramCode; private final String lowerLimit; private final String upperLimit; private NormalizedLimit(String processKey, String paramCode, String lowerLimit, String upperLimit) { this.processKey = processKey; this.paramCode = paramCode; this.lowerLimit = lowerLimit; this.upperLimit = upperLimit; } } public static class ArcLimitRule { private final String paramCode; private final String lowerLimit; private final String upperLimit; public ArcLimitRule(String paramCode, String lowerLimit, String upperLimit) { this.paramCode = paramCode; this.lowerLimit = lowerLimit; this.upperLimit = upperLimit; } public String getParamCode() { return paramCode; } public String getLowerLimit() { return lowerLimit; } public String getUpperLimit() { return upperLimit; } } }