|
|
@@ -1,16 +1,7 @@
|
|
|
-/*
|
|
|
- * 文 件 名: ConditionEvaluator
|
|
|
- * 版 权: 华设设计集团股份有限公司
|
|
|
- * 描 述: <描述>
|
|
|
- * 修 改 人: lvwenbin
|
|
|
- * 修改时间: 2025/11/27
|
|
|
- * 跟踪单号: <跟踪单号>
|
|
|
- * 修改单号: <修改单号>
|
|
|
- * 修改内容: <修改内容>
|
|
|
- */
|
|
|
package com.ruoyi.ems.strategy.evaluator;
|
|
|
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
+import com.alibaba.fastjson2.JSONArray;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
@@ -18,19 +9,15 @@ import org.springframework.stereotype.Component;
|
|
|
import java.util.Map;
|
|
|
|
|
|
/**
|
|
|
- * 条件表达式求值器
|
|
|
- * <功能详细描述>
|
|
|
- *
|
|
|
- * @author lvwenbin
|
|
|
- * @version [版本号, 2025/11/27]
|
|
|
- * @see [相关类/方法]
|
|
|
- * @since [产品/模块版本]
|
|
|
+ * 条件表达式求值器(支持前端简单和复杂格式)
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Component
|
|
|
public class ConditionEvaluator {
|
|
|
+
|
|
|
/**
|
|
|
* 评估条件表达式
|
|
|
+ *
|
|
|
* @param conditionExpr 条件表达式JSON
|
|
|
* @param context 上下文变量
|
|
|
* @return 是否满足条件
|
|
|
@@ -42,27 +29,94 @@ public class ConditionEvaluator {
|
|
|
|
|
|
try {
|
|
|
JSONObject condition = JSON.parseObject(conditionExpr);
|
|
|
- return evaluateCondition(condition, context);
|
|
|
+
|
|
|
+ // ✅ 支持简单格式: {"left":"Switch","op":"==","right":"1"}
|
|
|
+ if (condition.containsKey("left") && condition.containsKey("op")) {
|
|
|
+ return evaluateSimple(condition, context);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ✅ 支持复杂格式: {"logic":"AND","conditions":[...]}
|
|
|
+ if (condition.containsKey("logic")) {
|
|
|
+ return evaluateComplex(condition, context);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ✅ 支持旧格式: {"operator":"AND","conditions":[...]}
|
|
|
+ if (condition.containsKey("operator")) {
|
|
|
+ return evaluateLegacy(condition, context);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.warn("未识别的条件格式: {}", conditionExpr);
|
|
|
+ return false;
|
|
|
+
|
|
|
} catch (Exception e) {
|
|
|
log.error("条件表达式解析失败: {}", conditionExpr, e);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private boolean evaluateCondition(JSONObject condition, Map<String, Object> context) {
|
|
|
+ /**
|
|
|
+ * 评估简单条件
|
|
|
+ * 格式: {"left":"Switch","op":"==","right":"1"}
|
|
|
+ */
|
|
|
+ private boolean evaluateSimple(JSONObject condition, Map<String, Object> context) {
|
|
|
+ String left = condition.getString("left");
|
|
|
+ String op = condition.getString("op");
|
|
|
+ Object right = condition.get("right");
|
|
|
+
|
|
|
+ // 从上下文获取左侧值
|
|
|
+ Object leftValue = getValueFromContext(left, context);
|
|
|
+
|
|
|
+ return compare(leftValue, op, right);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 评估复杂条件(AND/OR)
|
|
|
+ * 格式: {"logic":"AND","conditions":[...]}
|
|
|
+ */
|
|
|
+ private boolean evaluateComplex(JSONObject condition, Map<String, Object> context) {
|
|
|
+ String logic = condition.getString("logic");
|
|
|
+ JSONArray conditions = condition.getJSONArray("conditions");
|
|
|
+
|
|
|
+ if ("AND".equals(logic)) {
|
|
|
+ return conditions.stream()
|
|
|
+ .allMatch(c -> evaluateSimple((JSONObject) c, context));
|
|
|
+ } else if ("OR".equals(logic)) {
|
|
|
+ return conditions.stream()
|
|
|
+ .anyMatch(c -> evaluateSimple((JSONObject) c, context));
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 评估旧格式条件(兼容)
|
|
|
+ * 格式: {"operator":"AND","conditions":[...]}
|
|
|
+ */
|
|
|
+ private boolean evaluateLegacy(JSONObject condition, Map<String, Object> context) {
|
|
|
String operator = condition.getString("operator");
|
|
|
+ JSONArray conditions = condition.getJSONArray("conditions");
|
|
|
|
|
|
if ("AND".equals(operator)) {
|
|
|
- return condition.getJSONArray("conditions").stream()
|
|
|
+ return conditions.stream()
|
|
|
.allMatch(c -> evaluateCondition((JSONObject) c, context));
|
|
|
} else if ("OR".equals(operator)) {
|
|
|
- return condition.getJSONArray("conditions").stream()
|
|
|
+ return conditions.stream()
|
|
|
.anyMatch(c -> evaluateCondition((JSONObject) c, context));
|
|
|
} else {
|
|
|
return evaluateSimpleCondition(condition, context);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private boolean evaluateCondition(JSONObject condition, Map<String, Object> context) {
|
|
|
+ String operator = condition.getString("operator");
|
|
|
+
|
|
|
+ if ("AND".equals(operator) || "OR".equals(operator)) {
|
|
|
+ return evaluateLegacy(condition, context);
|
|
|
+ } else {
|
|
|
+ return evaluateSimpleCondition(condition, context);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private boolean evaluateSimpleCondition(JSONObject condition, Map<String, Object> context) {
|
|
|
String field = condition.getString("field");
|
|
|
String operator = condition.getString("operator");
|
|
|
@@ -73,50 +127,104 @@ public class ConditionEvaluator {
|
|
|
return compare(actualValue, operator, expectedValue);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 从上下文获取值(支持嵌套路径)
|
|
|
+ *
|
|
|
+ * 支持格式:
|
|
|
+ * - "Switch" → context.get("Switch")
|
|
|
+ * - "context.Switch" → context.get("Switch")
|
|
|
+ * - "newValue" → context.get("newValue")(用于属性变化触发)
|
|
|
+ * - "data.temperature" → context.get("data").temperature
|
|
|
+ */
|
|
|
private Object getValueFromContext(String field, Map<String, Object> context) {
|
|
|
+ if (field == null || field.trim().isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除 "context." 前缀
|
|
|
+ if (field.startsWith("context.")) {
|
|
|
+ field = field.substring(8);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 支持嵌套路径
|
|
|
if (field.contains(".")) {
|
|
|
String[] parts = field.split("\\.");
|
|
|
- Object current = context;
|
|
|
- for (String part : parts) {
|
|
|
+ Object current = context.get(parts[0]);
|
|
|
+
|
|
|
+ for (int i = 1; i < parts.length && current != null; i++) {
|
|
|
if (current instanceof Map) {
|
|
|
- current = ((Map<?, ?>) current).get(part);
|
|
|
+ current = ((Map<?, ?>) current).get(parts[i]);
|
|
|
+ } else if (current instanceof JSONObject) {
|
|
|
+ current = ((JSONObject) current).get(parts[i]);
|
|
|
} else {
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
return current;
|
|
|
}
|
|
|
+
|
|
|
return context.get(field);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 比较两个值
|
|
|
+ */
|
|
|
private boolean compare(Object actual, String operator, Object expected) {
|
|
|
if (actual == null) return false;
|
|
|
|
|
|
+ // 数值类型统一转字符串比较(去除小数点后的0)
|
|
|
+ String actualStr = String.valueOf(actual).replaceAll("\\.0+$", "");
|
|
|
+ String expectedStr = String.valueOf(expected).replaceAll("\\.0+$", "");
|
|
|
+
|
|
|
switch (operator) {
|
|
|
case "==":
|
|
|
- return actual.equals(expected);
|
|
|
+ case "equals":
|
|
|
+ return actualStr.equals(expectedStr);
|
|
|
+
|
|
|
case "!=":
|
|
|
- return !actual.equals(expected);
|
|
|
+ case "notEquals":
|
|
|
+ return !actualStr.equals(expectedStr);
|
|
|
+
|
|
|
case ">":
|
|
|
+ case "greaterThan":
|
|
|
return compareNumeric(actual, expected) > 0;
|
|
|
+
|
|
|
case ">=":
|
|
|
+ case "greaterThanOrEqual":
|
|
|
return compareNumeric(actual, expected) >= 0;
|
|
|
+
|
|
|
case "<":
|
|
|
+ case "lessThan":
|
|
|
return compareNumeric(actual, expected) < 0;
|
|
|
+
|
|
|
case "<=":
|
|
|
+ case "lessThanOrEqual":
|
|
|
return compareNumeric(actual, expected) <= 0;
|
|
|
+
|
|
|
case "contains":
|
|
|
- return actual.toString().contains(expected.toString());
|
|
|
+ return actualStr.contains(expectedStr);
|
|
|
+
|
|
|
case "in":
|
|
|
- return expected.toString().contains(actual.toString());
|
|
|
+ return expectedStr.contains(actualStr);
|
|
|
+
|
|
|
default:
|
|
|
+ log.warn("未知的比较运算符: {}", operator);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 数值比较
|
|
|
+ */
|
|
|
private int compareNumeric(Object a, Object b) {
|
|
|
- double va = Double.parseDouble(a.toString());
|
|
|
- double vb = Double.parseDouble(b.toString());
|
|
|
- return Double.compare(va, vb);
|
|
|
+ try {
|
|
|
+ double va = Double.parseDouble(String.valueOf(a));
|
|
|
+ double vb = Double.parseDouble(String.valueOf(b));
|
|
|
+ return Double.compare(va, vb);
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ log.warn("数值比较失败: {} vs {}", a, b);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
}
|