HomeGridDisplayPolicy.cs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. namespace Admin.NET.Plugin.AiDOP.SmartOps;
  2. /// <summary>
  3. /// 九宫格卡片同时保留最后可用值和最新一次计算。展示状态只看行主键,不看日期是否相同。
  4. /// </summary>
  5. public static class HomeGridDisplayPolicy
  6. {
  7. public sealed class Row
  8. {
  9. public long Id { get; init; }
  10. public decimal? MetricValue { get; init; }
  11. public decimal? TargetValue { get; init; }
  12. public string? ResultStatus { get; init; }
  13. public string? ResultReason { get; init; }
  14. public DateTime BizDate { get; init; }
  15. }
  16. public sealed class Card
  17. {
  18. public decimal? CurrentValue { get; init; }
  19. public decimal? TargetValue { get; init; }
  20. public string? ResultStatus { get; init; }
  21. public string? ResultReason { get; init; }
  22. public DateTime? BizDate { get; init; }
  23. public string? LatestResultStatus { get; init; }
  24. public string? LatestResultReason { get; init; }
  25. public DateTime? LatestBizDate { get; init; }
  26. public string DisplayState { get; init; } = "NO_DATA";
  27. public string FreshnessState { get; init; } = "NO_VALUE";
  28. public int? ValueAgeDays { get; init; }
  29. public int? FreshnessSlaDays { get; init; }
  30. public bool FutureBizDate { get; init; }
  31. }
  32. public static Card Decide(Row? usable, Row? latest, int? slaDays, DateTime today)
  33. {
  34. string displayState;
  35. if (usable == null)
  36. {
  37. displayState = string.Equals(latest?.ResultStatus, "SOURCE_UNSUPPORTED", StringComparison.OrdinalIgnoreCase)
  38. ? "SOURCE_UNSUPPORTED"
  39. : "NO_DATA";
  40. }
  41. else if (latest != null && usable.Id == latest.Id)
  42. {
  43. displayState = "CURRENT_VALUE";
  44. }
  45. else
  46. {
  47. displayState = "LAST_KNOWN_VALUE";
  48. }
  49. var freshness = "NO_VALUE";
  50. int? age = null;
  51. var future = false;
  52. if (usable != null)
  53. {
  54. if (slaDays is null or <= 0)
  55. {
  56. freshness = "POLICY_MISSING";
  57. }
  58. else
  59. {
  60. var rawAge = (today.Date - usable.BizDate.Date).Days;
  61. if (rawAge < 0)
  62. {
  63. future = true;
  64. age = 0;
  65. }
  66. else
  67. {
  68. age = rawAge;
  69. }
  70. freshness = age > slaDays ? "STALE" : "FRESH";
  71. }
  72. }
  73. return new Card
  74. {
  75. CurrentValue = usable?.MetricValue,
  76. TargetValue = usable?.TargetValue,
  77. ResultStatus = usable == null ? latest?.ResultStatus : NormalizeUsableStatus(usable.ResultStatus),
  78. ResultReason = usable?.ResultReason,
  79. BizDate = usable?.BizDate,
  80. LatestResultStatus = latest?.ResultStatus,
  81. LatestResultReason = latest?.ResultReason,
  82. LatestBizDate = latest?.BizDate,
  83. DisplayState = displayState,
  84. FreshnessState = freshness,
  85. ValueAgeDays = age,
  86. FreshnessSlaDays = slaDays,
  87. FutureBizDate = future,
  88. };
  89. }
  90. private static string NormalizeUsableStatus(string? status) =>
  91. string.IsNullOrWhiteSpace(status) ? "OK" : status;
  92. }