using System.Text.Json; using System.Text.Json.Serialization; namespace FixedAssetPrintAgent; internal sealed class AgentConfiguration { public string ServerUrl { get; set; } = "https://www.jsgdzc.cn"; public string TerminalName { get; set; } = Environment.MachineName; public string MachineName { get; set; } = Environment.MachineName; public string Platform { get; set; } = "windows"; public string DeviceToken { get; set; } = string.Empty; public int TerminalId { get; set; } public string SelectedPrinterName { get; set; } = string.Empty; public int HeartbeatIntervalSeconds { get; set; } = 30; public int PollIntervalSeconds { get; set; } = 3; public bool RunAtStartup { get; set; } = true; public string PairedAt { get; set; } = string.Empty; public AgentConfiguration Clone() { return new AgentConfiguration { ServerUrl = ServerUrl, TerminalName = TerminalName, MachineName = MachineName, Platform = Platform, DeviceToken = DeviceToken, TerminalId = TerminalId, SelectedPrinterName = SelectedPrinterName, HeartbeatIntervalSeconds = HeartbeatIntervalSeconds, PollIntervalSeconds = PollIntervalSeconds, RunAtStartup = RunAtStartup, PairedAt = PairedAt }; } } internal sealed class PrinterInfo { [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; [JsonPropertyName("driver_name")] public string? DriverName { get; set; } [JsonPropertyName("port_name")] public string? PortName { get; set; } [JsonPropertyName("is_default")] public bool IsDefault { get; set; } [JsonPropertyName("is_available")] public bool IsAvailable { get; set; } = true; } internal sealed class PrintLabelProfile { [JsonPropertyName("paper_size")] public string PaperSize { get; set; } = "60x40mm"; [JsonPropertyName("width_mm")] public int WidthMillimeters { get; set; } = 60; [JsonPropertyName("height_mm")] public int HeightMillimeters { get; set; } = 40; [JsonPropertyName("orientation")] public string Orientation { get; set; } = "landscape"; [JsonPropertyName("scale_mode")] public string ScaleMode { get; set; } = "fit"; } internal sealed class DepartmentInfo { [JsonPropertyName("name")] public string? Name { get; set; } } internal sealed class AssetLabelItem { [JsonPropertyName("id")] public int Id { get; set; } [JsonPropertyName("equipment_code")] public string EquipmentCode { get; set; } = string.Empty; [JsonPropertyName("equipment_name")] public string EquipmentName { get; set; } = string.Empty; [JsonPropertyName("equipment_model")] public string? EquipmentModel { get; set; } [JsonPropertyName("equipment_type")] public string EquipmentType { get; set; } = string.Empty; [JsonPropertyName("purchase_date")] public string? PurchaseDate { get; set; } [JsonPropertyName("department")] public DepartmentInfo? Department { get; set; } } internal sealed class AssetLabelRenderedImage { [JsonPropertyName("equipment_id")] public int EquipmentId { get; set; } [JsonPropertyName("image_data_url")] public string ImageDataUrl { get; set; } = string.Empty; } internal sealed class AssetLabelPayload { [JsonPropertyName("items")] public List Items { get; set; } = []; [JsonPropertyName("rendered_labels")] public List RenderedLabels { get; set; } = []; } internal sealed class PrintJobDto { [JsonPropertyName("claim_token")] public string ClaimToken { get; set; } = string.Empty; [JsonPropertyName("id")] public int Id { get; set; } [JsonPropertyName("job_type")] public string JobType { get; set; } = string.Empty; [JsonPropertyName("payload")] public AssetLabelPayload? Payload { get; set; } [JsonPropertyName("payload_json")] public JsonElement PayloadJson { get; set; } } internal sealed class PrintJobState { [JsonPropertyName("id")] public int Id { get; set; } [JsonPropertyName("status")] public string Status { get; set; } = string.Empty; [JsonPropertyName("claim_token")] public string? ClaimToken { get => _claimToken; set { _claimToken = value; ClaimTokenWasProvided = true; } } private string? _claimToken; [JsonIgnore] public bool ClaimTokenWasProvided { get; private set; } public bool HasValidState() => ClaimTokenWasProvided && Status is "queued" or "claimed" or "printing" or "result_unknown" or "completed" or "cancelled" or "failed"; } internal sealed class PrintJobClaimData { [JsonPropertyName("job")] public PrintJobDto? Job { get; set; } [JsonPropertyName("message")] public string? Message { get; set; } } internal sealed class PairResponse { [JsonPropertyName("terminal_id")] public int TerminalId { get; set; } [JsonPropertyName("device_token")] public string DeviceToken { get; set; } = string.Empty; [JsonPropertyName("paired_at")] public string? PairedAt { get; set; } [JsonPropertyName("is_default")] public bool IsDefault { get; set; } } internal sealed class PrintAgentReleaseCollection { [JsonPropertyName("latest_version")] public string? LatestVersion { get; set; } [JsonPropertyName("latest_download_url")] public string? LatestDownloadUrl { get; set; } [JsonPropertyName("releases")] public List Releases { get; set; } = []; } internal sealed class PrintAgentReleaseInfo { [JsonPropertyName("version")] public string Version { get; set; } = string.Empty; [JsonPropertyName("published_at")] public string? PublishedAt { get; set; } [JsonPropertyName("filename")] public string? FileName { get; set; } [JsonPropertyName("notes")] public string? Notes { get; set; } [JsonPropertyName("download_url")] public string? DownloadUrl { get; set; } } internal sealed class DriverLatestInfo { [JsonPropertyName("title")] public string Title { get; set; } = string.Empty; [JsonPropertyName("official_url")] public string OfficialUrl { get; set; } = string.Empty; [JsonPropertyName("source_url")] public string? SourceUrl { get; set; } [JsonPropertyName("checked_at")] public string? CheckedAt { get; set; } [JsonPropertyName("notes")] public string? Notes { get; set; } } internal sealed class DriverArchiveRelease { [JsonPropertyName("version")] public string Version { get; set; } = string.Empty; [JsonPropertyName("published_at")] public string? PublishedAt { get; set; } [JsonPropertyName("filename")] public string? FileName { get; set; } [JsonPropertyName("notes")] public string? Notes { get; set; } [JsonPropertyName("download_url")] public string? DownloadUrl { get; set; } } internal sealed class PrintAgentRuntimeState { public AgentConfiguration Configuration { get; set; } = new(); public List Printers { get; set; } = []; public List Releases { get; set; } = []; public DriverLatestInfo? LatestDriver { get; set; } public List ArchivedDrivers { get; set; } = []; public string UpdateStatusMessage { get; set; } = "尚未检查版本"; public string LastHeartbeatAt { get; set; } = string.Empty; public string LastClaimAt { get; set; } = string.Empty; public string LastJobResult { get; set; } = string.Empty; public string LastError { get; set; } = string.Empty; public List LogLines { get; set; } = []; public bool IsPaired => Configuration.TerminalId > 0 && !string.IsNullOrWhiteSpace(Configuration.DeviceToken); public PrintAgentRuntimeState Clone() { return new PrintAgentRuntimeState { Configuration = Configuration.Clone(), Printers = Printers .Select(item => new PrinterInfo { Name = item.Name, DriverName = item.DriverName, PortName = item.PortName, IsDefault = item.IsDefault, IsAvailable = item.IsAvailable }) .ToList(), Releases = Releases .Select(item => new PrintAgentReleaseInfo { Version = item.Version, PublishedAt = item.PublishedAt, FileName = item.FileName, Notes = item.Notes, DownloadUrl = item.DownloadUrl }) .ToList(), LatestDriver = LatestDriver is null ? null : new DriverLatestInfo { Title = LatestDriver.Title, OfficialUrl = LatestDriver.OfficialUrl, SourceUrl = LatestDriver.SourceUrl, CheckedAt = LatestDriver.CheckedAt, Notes = LatestDriver.Notes }, ArchivedDrivers = ArchivedDrivers .Select(item => new DriverArchiveRelease { Version = item.Version, PublishedAt = item.PublishedAt, FileName = item.FileName, Notes = item.Notes, DownloadUrl = item.DownloadUrl }) .ToList(), UpdateStatusMessage = UpdateStatusMessage, LastHeartbeatAt = LastHeartbeatAt, LastClaimAt = LastClaimAt, LastJobResult = LastJobResult, LastError = LastError, LogLines = [.. LogLines] }; } }