FormulaPreviewBuilder.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. using System.Text.RegularExpressions;
  2. using Admin.NET.Plugin.AiDOP.Entity;
  3. using SqlSugar;
  4. namespace Admin.NET.Plugin.AiDOP.Infrastructure.FormulaExpr;
  5. /// <summary>
  6. /// 把结构化公式替换为人读预览:
  7. /// $F_S1_001 → 统计期订单总数
  8. /// @S1_L1_001 → 订单评审周期(天)
  9. /// / → ÷, * → ×
  10. /// </summary>
  11. public static class FormulaPreviewBuilder
  12. {
  13. private static readonly Regex RefRe = new(@"([@$])([A-Za-z][A-Za-z0-9_]*)", RegexOptions.Compiled);
  14. public static async Task<string> BuildAsync(
  15. ISqlSugarClient db,
  16. long tenantId,
  17. string? expr,
  18. FormulaParser.ParseResult? parsed = null)
  19. {
  20. if (string.IsNullOrWhiteSpace(expr)) return string.Empty;
  21. parsed ??= FormulaParser.Parse(expr);
  22. var metricMap = parsed.MetricRefs.Count == 0
  23. ? new Dictionary<string, string>()
  24. : (await db.Queryable<AdoSmartOpsKpiMaster>()
  25. .Where(x => x.TenantId == tenantId && parsed.MetricRefs.Contains(x.MetricCode))
  26. .Select(x => new { x.MetricCode, x.MetricName })
  27. .ToListAsync())
  28. .ToDictionary(x => x.MetricCode, x => x.MetricName, StringComparer.OrdinalIgnoreCase);
  29. var factMap = parsed.FactRefs.Count == 0
  30. ? new Dictionary<string, string>()
  31. : (await db.Queryable<AdoSmartOpsBusinessFact>()
  32. .Where(x => x.TenantId == tenantId && parsed.FactRefs.Contains(x.FactCode))
  33. .Select(x => new { x.FactCode, x.FactName })
  34. .ToListAsync())
  35. .ToDictionary(x => x.FactCode, x => x.FactName, StringComparer.OrdinalIgnoreCase);
  36. var preview = RefRe.Replace(expr, m =>
  37. {
  38. var sym = m.Groups[1].Value;
  39. var code = m.Groups[2].Value;
  40. if (sym == "@" && metricMap.TryGetValue(code, out var mn)) return mn ?? $"@{code}";
  41. if (sym == "$" && factMap.TryGetValue(code, out var fn)) return fn ?? $"${code}";
  42. return m.Value;
  43. });
  44. preview = preview.Replace('/', '÷').Replace('*', '×');
  45. // 连续空白压缩
  46. preview = Regex.Replace(preview, @"\s+", " ").Trim();
  47. return preview;
  48. }
  49. }