feat: 初始功能

This commit is contained in:
Shiqvlizi Name
2026-05-23 18:16:50 +08:00
parent a5bfd8792e
commit 9a51259e9e
63 changed files with 5377 additions and 1 deletions

14
Models/AdminSession.cs Normal file
View File

@@ -0,0 +1,14 @@
namespace CloudPrint.Client.Models;
public sealed class AdminSession
{
public int AdminId { get; init; }
public string Username { get; init; } = string.Empty;
public string Nickname { get; init; } = string.Empty;
public int Role { get; init; }
public string AccessToken { get; init; } = string.Empty;
public bool IsAuthenticated => !string.IsNullOrWhiteSpace(AccessToken);
public string DisplayName => string.IsNullOrWhiteSpace(Nickname) ? Username : Nickname;
}

39
Models/AppLogEntry.cs Normal file
View File

@@ -0,0 +1,39 @@
namespace CloudPrint.Client.Models;
public enum AppLogLevel
{
Info,
Success,
Warning,
Error
}
public sealed class AppLogEntry
{
public DateTime Timestamp { get; init; } = DateTime.Now;
public AppLogLevel Level { get; init; } = AppLogLevel.Info;
public string Message { get; init; } = string.Empty;
public string ExceptionText { get; init; } = string.Empty;
public string LevelText => Level switch
{
AppLogLevel.Success => "成功",
AppLogLevel.Warning => "警告",
AppLogLevel.Error => "错误",
_ => "信息"
};
public string DisplayText => string.IsNullOrWhiteSpace(ExceptionText)
? $"[{Timestamp:HH:mm:ss}] [{LevelText}] {Message}"
: $"[{Timestamp:HH:mm:ss}] [{LevelText}] {Message}(详见本地日志)";
public static AppLogEntry FromException(string message, Exception exception)
{
return new AppLogEntry
{
Level = AppLogLevel.Error,
Message = message,
ExceptionText = exception.ToString()
};
}
}

77
Models/ClientSettings.cs Normal file
View File

@@ -0,0 +1,77 @@
using CloudPrint.Client.Infrastructure;
namespace CloudPrint.Client.Models;
public sealed class ClientSettings : ObservableObject
{
private string _serverAddress = "http://localhost:8080";
private string _apiKey = string.Empty;
private string _adminUsername = string.Empty;
private string _adminAccessToken = string.Empty;
private string _storeName = "默认打印店";
private bool _allowInsecureGrpc = true;
private string _libraryRoot = string.Empty;
private string _printCacheRoot = string.Empty;
private int _maxUploadSizeMb = 50;
private int _heartbeatIntervalSeconds = 15;
public string ServerAddress
{
get => _serverAddress;
set => SetProperty(ref _serverAddress, value);
}
public string ApiKey
{
get => _apiKey;
set => SetProperty(ref _apiKey, value);
}
public string AdminUsername
{
get => _adminUsername;
set => SetProperty(ref _adminUsername, value);
}
public string AdminAccessToken
{
get => _adminAccessToken;
set => SetProperty(ref _adminAccessToken, value);
}
public string StoreName
{
get => _storeName;
set => SetProperty(ref _storeName, value);
}
public bool AllowInsecureGrpc
{
get => _allowInsecureGrpc;
set => SetProperty(ref _allowInsecureGrpc, value);
}
public string LibraryRoot
{
get => _libraryRoot;
set => SetProperty(ref _libraryRoot, value);
}
public string PrintCacheRoot
{
get => _printCacheRoot;
set => SetProperty(ref _printCacheRoot, value);
}
public int MaxUploadSizeMb
{
get => _maxUploadSizeMb;
set => SetProperty(ref _maxUploadSizeMb, Math.Clamp(value, 1, 1024));
}
public int HeartbeatIntervalSeconds
{
get => _heartbeatIntervalSeconds;
set => SetProperty(ref _heartbeatIntervalSeconds, Math.Clamp(value, 5, 300));
}
}

11
Models/ConnectionState.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace CloudPrint.Client.Models;
public enum ConnectionState
{
Disconnected,
Connecting,
Connected,
Subscribing,
Subscribed,
Error
}

71
Models/Document.cs Normal file
View File

@@ -0,0 +1,71 @@
using CloudPrint.Client.Infrastructure;
namespace CloudPrint.Client.Models;
public sealed class CloudPrintDocument : ObservableObject
{
private string _title = string.Empty;
private string _description = string.Empty;
private string _categoryName = "未分类";
private bool _isUploaded;
private string _syncStatus = "本地";
public int Id { get; init; }
public string FileName { get; init; } = string.Empty;
public string FilePath { get; init; } = string.Empty;
public string FileType { get; init; } = string.Empty;
public long FileSize { get; init; }
public string UploaderType { get; init; } = "admin";
public int UploaderId { get; init; }
public int CategoryId { get; init; }
public int PageCount { get; init; }
public DateTime CreatedAt { get; init; } = DateTime.Now;
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
public string CategoryName
{
get => _categoryName;
set => SetProperty(ref _categoryName, value);
}
public bool IsUploaded
{
get => _isUploaded;
set => SetProperty(ref _isUploaded, value);
}
public string SyncStatus
{
get => _syncStatus;
set => SetProperty(ref _syncStatus, value);
}
public string FileSizeText
{
get
{
if (FileSize >= 1024 * 1024)
{
return $"{FileSize / 1024d / 1024d:F2} MB";
}
if (FileSize >= 1024)
{
return $"{FileSize / 1024d:F2} KB";
}
return $"{FileSize} B";
}
}
}

View File

@@ -0,0 +1,9 @@
namespace CloudPrint.Client.Models;
public sealed class FilePreparationResult
{
public string SourcePath { get; init; } = string.Empty;
public string PreparedPath { get; init; } = string.Empty;
public bool Converted { get; init; }
public string Message { get; init; } = string.Empty;
}

View File

@@ -0,0 +1,17 @@
namespace CloudPrint.Client.Models;
public sealed class FileValidationResult
{
public bool IsValid { get; init; }
public string Message { get; init; } = string.Empty;
public static FileValidationResult Success(string message = "文件可用")
{
return new FileValidationResult { IsValid = true, Message = message };
}
public static FileValidationResult Failure(string message)
{
return new FileValidationResult { IsValid = false, Message = message };
}
}

View File

@@ -0,0 +1,9 @@
namespace CloudPrint.Client.Models;
public sealed class LibraryCategory
{
public int Id { get; init; }
public string Name { get; init; } = string.Empty;
public string Icon { get; init; } = string.Empty;
public int SortOrder { get; init; }
}

110
Models/PrintJob.cs Normal file
View File

@@ -0,0 +1,110 @@
using CloudPrint.Client.Infrastructure;
namespace CloudPrint.Client.Models;
public enum PrintJobStatus
{
Pending,
Printing,
Completed,
Failed,
Cancelled
}
public sealed class PrintJob : ObservableObject
{
private PrintJobStatus _status = PrintJobStatus.Pending;
private int _progress;
private string _errorMessage = string.Empty;
private int? _windowsJobId;
private string _windowsJobStatus = string.Empty;
public int Id { get; init; }
public string JobNo { get; init; } = string.Empty;
public int PrinterId { get; set; }
public string PrinterName { get; set; } = string.Empty;
public int OrderItemId { get; init; }
public int FileId { get; init; }
public string FileName { get; init; } = string.Empty;
public string FilePath { get; set; } = string.Empty;
public int Copies { get; init; } = 1;
public bool Color { get; init; }
public bool Duplex { get; init; }
public string PageRange { get; init; } = "all";
public DateTime? StartedAt { get; set; }
public DateTime? CompletedAt { get; set; }
public int? WindowsJobId
{
get => _windowsJobId;
set => SetProperty(ref _windowsJobId, value);
}
public string WindowsJobStatus
{
get => _windowsJobStatus;
set => SetProperty(ref _windowsJobStatus, value);
}
public PrintJobStatus Status
{
get => _status;
set
{
if (SetProperty(ref _status, value))
{
OnPropertyChanged(nameof(StatusText));
}
}
}
public int Progress
{
get => _progress;
set => SetProperty(ref _progress, Math.Clamp(value, 0, 100));
}
public string ErrorMessage
{
get => _errorMessage;
set => SetProperty(ref _errorMessage, value);
}
public string StatusText => Status switch
{
PrintJobStatus.Pending => "待打印",
PrintJobStatus.Printing => "打印中",
PrintJobStatus.Completed => "已完成",
PrintJobStatus.Failed => "失败",
PrintJobStatus.Cancelled => "已取消",
_ => "未知"
};
public void MarkPrinting()
{
StartedAt ??= DateTime.Now;
Status = PrintJobStatus.Printing;
Progress = Math.Max(Progress, 1);
}
public void MarkCompleted()
{
Status = PrintJobStatus.Completed;
Progress = 100;
CompletedAt = DateTime.Now;
ErrorMessage = string.Empty;
}
public void MarkFailed(string message)
{
Status = PrintJobStatus.Failed;
ErrorMessage = message;
CompletedAt = DateTime.Now;
}
public void MarkCancelled()
{
Status = PrintJobStatus.Cancelled;
CompletedAt = DateTime.Now;
}
}

82
Models/Printer.cs Normal file
View File

@@ -0,0 +1,82 @@
using CloudPrint.Client.Infrastructure;
namespace CloudPrint.Client.Models;
public enum PrinterStatus
{
Idle = 0,
Printing = 1,
Offline = 2,
Error = 3,
Unknown = 99
}
public sealed class PrinterInfo : ObservableObject
{
private PrinterStatus _status;
private int _queueCount;
private string _statusMessage = string.Empty;
public int Id { get; init; }
public string Name { get; init; } = string.Empty;
public string DisplayName { get; init; } = string.Empty;
public bool IsActive { get; init; } = true;
public string ApiKey { get; init; } = string.Empty;
public DateTime? LastHeartbeat { get; set; }
public int QueueCount
{
get => _queueCount;
set
{
if (SetProperty(ref _queueCount, Math.Max(0, value)))
{
OnPropertyChanged(nameof(DisplayText));
}
}
}
public string StatusMessage
{
get => _statusMessage;
set
{
if (SetProperty(ref _statusMessage, value))
{
OnPropertyChanged(nameof(DisplayText));
}
}
}
public PrinterStatus Status
{
get => _status;
set
{
if (SetProperty(ref _status, value))
{
OnPropertyChanged(nameof(StatusText));
OnPropertyChanged(nameof(DisplayText));
}
}
}
public string StatusText => Status switch
{
PrinterStatus.Idle => "空闲",
PrinterStatus.Printing => "打印中",
PrinterStatus.Offline => "离线",
PrinterStatus.Error => "异常",
_ => "未知"
};
public string DisplayText
{
get
{
var queueText = QueueCount > 0 ? $",队列 {QueueCount}" : string.Empty;
var messageText = string.IsNullOrWhiteSpace(StatusMessage) ? string.Empty : $"{StatusMessage}";
return $"{DisplayName}{StatusText}{queueText}{messageText}";
}
}
}