using Volo.Abp; namespace FoodLabeling.Application.Helpers; /// /// Label Report 统计区间解析(App 7d / 30d / 90d / 自定义)。 /// public static class LabelReportDateRangeHelper { /// 趋势按日汇总允许的最大天数 public const int MaxRangeDays = 366; /// /// 解析查询区间。结束日包含当天(闭区间),内部以次日 0 点为区间上界(不含)。 /// public static LabelReportResolvedRange Resolve(string? period, DateTime? startDate, DateTime? endDate) { var normalized = NormalizePeriod(period); var endDay = (endDate ?? DateTime.Today).Date; var endExcl = endDay.AddDays(1); DateTime startDay; switch (normalized) { case "7d": startDay = endDay.AddDays(-6); break; case "30d": startDay = endDay.AddDays(-29); break; case "90d": startDay = endDay.AddDays(-89); break; case "custom": if (!startDate.HasValue || !endDate.HasValue) { throw new UserFriendlyException("自定义日期须同时传入 startDate 与 endDate"); } startDay = startDate.Value.Date; endDay = endDate.Value.Date; endExcl = endDay.AddDays(1); if (startDay > endDay) { throw new UserFriendlyException("开始日期不能晚于结束日期"); } break; default: startDay = (startDate ?? endDay.AddDays(-6)).Date; normalized = startDate.HasValue || endDate.HasValue ? "custom" : "7d"; break; } if (startDay >= endExcl) { startDay = endExcl.AddDays(-1); } var dayCount = Math.Max(1, (int)Math.Ceiling((endExcl - startDay).TotalDays)); if (dayCount > MaxRangeDays) { throw new UserFriendlyException($"统计区间不能超过 {MaxRangeDays} 天"); } return new LabelReportResolvedRange { Period = normalized, RangeStart = startDay, RangeEndExcl = endExcl, RangeEndInclusive = endDay, DayCount = dayCount }; } private static string NormalizePeriod(string? period) { var p = (period ?? "7d").Trim().ToLowerInvariant(); return p switch { "7" or "7d" or "last7days" or "last_7_days" => "7d", "30" or "30d" or "last30days" or "last_30_days" => "30d", "90" or "90d" or "last90days" or "last_90_days" => "90d", "custom" => "custom", _ => p }; } } /// /// Label Report 已解析的日期区间。 /// public sealed class LabelReportResolvedRange { public string Period { get; init; } = "7d"; public DateTime RangeStart { get; init; } public DateTime RangeEndExcl { get; init; } public DateTime RangeEndInclusive { get; init; } public int DayCount { get; init; } }