|
|
@@ -25,6 +25,14 @@ public class S8OutOfRangeRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
private const string SqlDataSourceType = "SQL";
|
|
|
private const string DefaultExceptionTypeCode = "EQUIP_FAULT";
|
|
|
|
|
|
+ // S8-WATCH-EXPRESSION-COLUMN-CONTRACT-SHORTAGE-OUTOFRANGE-FIX-1:S8ConfigDraftService.BuildExpression
|
|
|
+ // 把 VALUE_RANGE 结果列统一别名为以下 canonical 名(无论源表真实列名为何)。evaluator 优先按 canonical
|
|
|
+ // 读取,仅当结果集不含 canonical 列时才回退到 params_json 指定的真实列名(兼容历史/手工规则)。
|
|
|
+ // 上下限为行内可选字段、无 canonical 契约,沿用 params 既有逻辑不变。
|
|
|
+ private const string CanonicalMeasuredValueColumn = "measured_value";
|
|
|
+ private const string CanonicalSourceObjectIdColumn = "source_object_id";
|
|
|
+ private const string CanonicalRelatedObjectCodeColumn = "related_object_code";
|
|
|
+
|
|
|
private readonly SqlSugarRepository<AdoS8DataSource> _dataSourceRep;
|
|
|
private readonly S8SqlSugarScopeFactory _scopeFactory;
|
|
|
private readonly ILogger<S8OutOfRangeRuleEvaluator> _logger;
|
|
|
@@ -98,9 +106,14 @@ public class S8OutOfRangeRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
? rule.WatchObjectType
|
|
|
: rule.SourceObjectType!;
|
|
|
|
|
|
+ // 结果列名一次性解析(结果集列在整张 DataTable 内稳定):canonical 优先,缺失回退 params 真实列名。
|
|
|
+ var measuredValueColumn = ResolveResultColumn(table, CanonicalMeasuredValueColumn, parameters.MeasuredValueField);
|
|
|
+ var objectCodeColumn = ResolveResultColumn(table, CanonicalRelatedObjectCodeColumn, parameters.ObjectCodeField);
|
|
|
+ var objectIdColumn = ResolveResultColumn(table, CanonicalSourceObjectIdColumn, parameters.ObjectIdField);
|
|
|
+
|
|
|
foreach (DataRow row in table.Rows)
|
|
|
{
|
|
|
- var measured = ReadDecimal(row, parameters.MeasuredValueField!);
|
|
|
+ var measured = ReadDecimal(row, measuredValueColumn);
|
|
|
if (measured == null) continue;
|
|
|
|
|
|
// 行内上下限优先;缺失时回退到固定上下限。
|
|
|
@@ -135,15 +148,10 @@ public class S8OutOfRangeRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
}
|
|
|
if (direction == null) continue;
|
|
|
|
|
|
- var objectCodeField = string.IsNullOrWhiteSpace(parameters.ObjectCodeField)
|
|
|
- ? "related_object_code"
|
|
|
- : parameters.ObjectCodeField!;
|
|
|
- var relatedObjectCode = ReadString(row, objectCodeField) ?? string.Empty;
|
|
|
+ var relatedObjectCode = ReadString(row, objectCodeColumn) ?? string.Empty;
|
|
|
if (string.IsNullOrWhiteSpace(relatedObjectCode)) continue;
|
|
|
|
|
|
- var sourceObjectId = string.IsNullOrWhiteSpace(parameters.ObjectIdField)
|
|
|
- ? relatedObjectCode
|
|
|
- : ReadString(row, parameters.ObjectIdField!) ?? relatedObjectCode;
|
|
|
+ var sourceObjectId = ReadString(row, objectIdColumn) ?? relatedObjectCode;
|
|
|
|
|
|
var dedupKey = BuildDedupKey(tenantId, factoryId, rule.RuleCode, sourceObjectType, sourceObjectId);
|
|
|
|
|
|
@@ -202,6 +210,18 @@ public class S8OutOfRangeRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
return JsonSerializer.Serialize(payload);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 结果列名解析:BuildExpression 已把 VALUE_RANGE 结果列统一别名为 canonical(measured_value/
|
|
|
+ /// source_object_id/related_object_code)。优先返回 canonical 列名;仅当结果集不含 canonical 列时,
|
|
|
+ /// 回退到 params_json 指定的真实列名(兼容历史/手工规则)。仅在 canonical 与 params 字段之间二选一,
|
|
|
+ /// 不新增无依据兜底字段。
|
|
|
+ /// </summary>
|
|
|
+ private static string ResolveResultColumn(DataTable table, string canonicalColumn, string? paramsColumn)
|
|
|
+ {
|
|
|
+ if (table.Columns.Contains(canonicalColumn)) return canonicalColumn;
|
|
|
+ return string.IsNullOrWhiteSpace(paramsColumn) ? canonicalColumn : paramsColumn!;
|
|
|
+ }
|
|
|
+
|
|
|
private static string? ReadString(DataRow row, string columnName)
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(columnName)) return null;
|