using CommunityToolkit.Mvvm.ComponentModel; using FluidExplorer.Models; using FluidExplorer.Services.Operations; namespace FluidExplorer.ViewModels; /// /// 操作队列面板里的一行。作业对象是在后台线程上更新并抛 PropertyChanged 的, /// 直接绑定会跨线程更新 UI 而崩溃,因此这里在 UI 线程维护一份快照,由定时器按 250ms 刷新。 /// public sealed partial class JobRowViewModel : ObservableObject { [ObservableProperty] private string _title = string.Empty; [ObservableProperty] private string _stateText = string.Empty; [ObservableProperty] private string _progressText = string.Empty; [ObservableProperty] private string _currentItem = string.Empty; [ObservableProperty] private double _progress; [ObservableProperty] private bool _isIndeterminate; [ObservableProperty] private bool _canPause; [ObservableProperty] private bool _canCancel; [ObservableProperty] private bool _isFinished; [ObservableProperty] private string _pauseGlyph = "\uE769"; public JobRowViewModel(FileOperationJob job) { Job = job; Refresh(); } public FileOperationJob Job { get; } public void Refresh() { Title = Job.Title; StateText = Job.State switch { JobState.Queued => "排队中", JobState.Running => "进行中", JobState.Paused => "已暂停", JobState.Completed => "已完成", JobState.CompletedWithErrors => "已完成(部分出错)", JobState.Cancelled => "已取消", JobState.Failed => "失败", _ => Job.State.ToString() }; var parts = new List { $"{Job.CompletedItems:N0} / {Job.TotalItems:N0} 个项目" }; if (Job.TotalBytes > 0) parts.Add($"{FileEntry.FormatSize(Job.CompletedBytes)} / {FileEntry.FormatSize(Job.TotalBytes)}"); if (Job.BytesPerSecond > 1) parts.Add($"{FileEntry.FormatSize((long)Job.BytesPerSecond)}/s"); if (Job.Eta is { } eta && eta.TotalSeconds > 1 && eta.TotalHours < 24) parts.Add($"剩余 {eta:mm\\:ss}"); ProgressText = string.Join(" · ", parts); CurrentItem = Job.CurrentItem ?? string.Empty; if (!string.IsNullOrEmpty(Job.Error)) CurrentItem = Job.Error!; Progress = Job.Progress; IsIndeterminate = Job.IsIndeterminate; CanPause = Job.CanPause; CanCancel = Job.CanCancel; IsFinished = Job.IsFinished; PauseGlyph = Job.State == JobState.Paused ? "\uE768" : "\uE769"; } }