SSPC-Tester/SSPCTester.Logic/Report/ReportFileHelper.cs
2026-06-30 12:10:29 +08:00

166 lines
5.7 KiB
C#

using SSPCTester.Logic.Models;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SSPCTester.Logic.Report;
public enum ReportOutputFormat
{
Pdf,
Word,
Both
}
public static class ReportFileHelper
{
public const string DefaultTemplate = "report_{yyyyMMdd_HHmmss}.pdf";
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
public static string ResolveFileName(Project project, DateTime now)
=> ResolveFileName(project, now, ".pdf");
public static string ResolveFileName(Project project, DateTime now, string extension)
{
string template = string.IsNullOrWhiteSpace(project.Report.FileName)
? DefaultTemplate
: project.Report.FileName.Trim();
extension = NormalizeExtension(extension);
string date = now.ToString("yyyyMMdd");
string dateTime = now.ToString("yyyyMMdd_HHmmss");
string value = template
.Replace("{ProjectName}", project.Name ?? "", StringComparison.OrdinalIgnoreCase)
.Replace("{ProductName}", project.Dut.ProductName ?? "", StringComparison.OrdinalIgnoreCase)
.Replace("{Model}", project.Dut.Model ?? "", StringComparison.OrdinalIgnoreCase)
.Replace("{SerialNumber}", project.Dut.SerialNumber ?? "", StringComparison.OrdinalIgnoreCase)
.Replace("{yyyyMMdd_HHmmss}", dateTime, StringComparison.OrdinalIgnoreCase)
.Replace("{DateTime}", dateTime, StringComparison.OrdinalIgnoreCase)
.Replace("{yyyyMMdd}", date, StringComparison.OrdinalIgnoreCase)
.Replace("{Date}", date, StringComparison.OrdinalIgnoreCase);
value = MakeSafeFileName(value);
if (string.IsNullOrWhiteSpace(value))
value = $"report_{dateTime}{extension}";
value = Path.ChangeExtension(value, extension);
return value;
}
public static ReportOutputFormat ParseFormat(string? value)
{
if (Enum.TryParse<ReportOutputFormat>(value, ignoreCase: true, out var format))
return format;
return ReportOutputFormat.Pdf;
}
public static IReadOnlyList<ReportFileDescriptor> EnumerateReportFiles(
string? directory,
ReportOutputFormat format)
{
if (string.IsNullOrWhiteSpace(directory) || !Directory.Exists(directory))
return Array.Empty<ReportFileDescriptor>();
string[] patterns = format switch
{
ReportOutputFormat.Word => new[] { "*.docx" },
ReportOutputFormat.Both => new[] { "*.pdf", "*.docx" },
_ => new[] { "*.pdf" }
};
return patterns
.SelectMany(pattern => Directory.EnumerateFiles(directory, pattern, SearchOption.TopDirectoryOnly))
.Select(path => new FileInfo(path))
.OrderByDescending(file => file.LastWriteTime)
.Select(file => new ReportFileDescriptor(
file.FullName,
file.Name,
file.LastWriteTime,
file.Extension.Equals(".pdf", StringComparison.OrdinalIgnoreCase)
? ReportFileKind.Pdf
: ReportFileKind.Word))
.ToArray();
}
public static IReadOnlyList<ReportFileDescriptor> EnumeratePdfFiles(string? directory)
{
return EnumerateReportFiles(directory, ReportOutputFormat.Pdf);
}
public static string BuildInfoPath(string outputPath) =>
Path.Combine(
Path.GetDirectoryName(outputPath) ?? "",
Path.GetFileNameWithoutExtension(outputPath) + ".reportinfo.json");
public static void SaveInfo(ReportInfo info, string infoPath)
{
Directory.CreateDirectory(Path.GetDirectoryName(infoPath)!);
File.WriteAllText(infoPath, JsonSerializer.Serialize(info, JsonOptions));
}
public static ReportInfo? LoadInfoForReport(string reportPath)
{
string infoPath = BuildInfoPath(reportPath);
if (!File.Exists(infoPath)) return null;
return JsonSerializer.Deserialize<ReportInfo>(File.ReadAllText(infoPath), JsonOptions);
}
private static string MakeSafeFileName(string value)
{
var invalid = Path.GetInvalidFileNameChars();
var chars = value
.Select(c => invalid.Contains(c) ? '_' : c)
.ToArray();
return new string(chars).Trim(' ', '.');
}
private static string NormalizeExtension(string extension)
{
if (string.IsNullOrWhiteSpace(extension)) return ".pdf";
extension = extension.Trim();
return extension.StartsWith('.') ? extension : "." + extension;
}
}
public enum ReportFileKind
{
Pdf,
Word
}
public sealed record ReportFileDescriptor(
string FullPath,
string DisplayName,
DateTime LastWriteTime,
ReportFileKind Kind = ReportFileKind.Pdf)
{
public bool IsPdf => Kind == ReportFileKind.Pdf;
public bool IsWord => Kind == ReportFileKind.Word;
}
public sealed class ReportInfo
{
public string ProjectName { get; set; } = "";
public string ProductName { get; set; } = "";
public string Model { get; set; } = "";
public string SerialNumber { get; set; } = "";
public DateTime GeneratedAt { get; set; }
public string Format { get; set; } = "";
public string? PdfPath { get; set; }
public string? WordPath { get; set; }
public string OverallStatus { get; set; } = "";
public ReportSectionInfo Sections { get; set; } = new();
}
public sealed class ReportSectionInfo
{
public bool Cover { get; set; }
public bool Basic { get; set; }
public bool Curve { get; set; }
public bool Power { get; set; }
public bool Protect { get; set; }
}