|
|
@@ -22,6 +22,14 @@ public class S8TimeoutRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
|
|
|
private const string SqlDataSourceType = "SQL";
|
|
|
|
|
|
+ // S8-WATCH-EXPRESSION-COLUMN-CONTRACT-FIX-1:S8ConfigDraftService.BuildExpression 统一把结果列
|
|
|
+ // 别名为以下 canonical 名(无论源表真实列名为何)。evaluator 优先按 canonical 读取,仅当结果集
|
|
|
+ // 不含 canonical 列时才回退到 params_json 指定的真实列名(兼容历史未别名规则)。
|
|
|
+ private const string CanonicalDueAtColumn = "due_at";
|
|
|
+ private const string CanonicalStatusColumn = "status";
|
|
|
+ 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<S8TimeoutRuleEvaluator> _logger;
|
|
|
@@ -95,24 +103,25 @@ public class S8TimeoutRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
? rule.WatchObjectType
|
|
|
: rule.SourceObjectType!;
|
|
|
|
|
|
+ // 结果列名一次性解析(结果集列在整张 DataTable 内稳定):canonical 优先,缺失回退 params 真实列名。
|
|
|
+ var statusColumn = ResolveResultColumn(table, CanonicalStatusColumn, parameters.StatusField);
|
|
|
+ var dueAtColumn = ResolveResultColumn(table, CanonicalDueAtColumn, parameters.DueAtField);
|
|
|
+ var objectCodeColumn = ResolveResultColumn(table, CanonicalRelatedObjectCodeColumn, parameters.ObjectCodeField);
|
|
|
+ var objectIdColumn = ResolveResultColumn(table, CanonicalSourceObjectIdColumn, parameters.ObjectIdField);
|
|
|
+
|
|
|
foreach (DataRow row in table.Rows)
|
|
|
{
|
|
|
- var status = ReadString(row, parameters.StatusField!) ?? string.Empty;
|
|
|
+ var status = ReadString(row, statusColumn) ?? string.Empty;
|
|
|
if (parameters.CompletedStates.Contains(status, StringComparer.OrdinalIgnoreCase))
|
|
|
continue;
|
|
|
|
|
|
- var due = ReadDateTime(row, parameters.DueAtField!);
|
|
|
+ var due = ReadDateTime(row, dueAtColumn);
|
|
|
if (due == null || due > threshold) 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);
|
|
|
|
|
|
@@ -161,6 +170,17 @@ public class S8TimeoutRuleEvaluator : IS8RuleEvaluator, ITransient
|
|
|
return JsonSerializer.Serialize(payload);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 结果列名解析:BuildExpression 已把结果列统一别名为 canonical(due_at/status/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;
|