524 lines
14 KiB
C#
524 lines
14 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using Microsoft.Extensions.Logging;
|
|
using OrpaonVision.Core.Results;
|
|
using OrpaonVision.Model.Training;
|
|
using OrpaonVision.ConfigApp.Infrastructure.Services;
|
|
using System.Collections.ObjectModel;
|
|
using System.Windows.Threading;
|
|
|
|
namespace OrpaonVision.ConfigApp.ViewModels;
|
|
|
|
/// <summary>
|
|
/// 训练任务管理视图模型。
|
|
/// </summary>
|
|
public partial class TrainingTaskManagementViewModel : ObservableObject
|
|
{
|
|
private readonly ILogger<TrainingTaskManagementViewModel> _logger;
|
|
private readonly ITrainingTaskService _trainingTaskService;
|
|
private readonly DispatcherTimer _refreshTimer;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<TrainingTaskModel> _tasks = new();
|
|
|
|
[ObservableProperty]
|
|
private TrainingTaskModel? _selectedTask;
|
|
|
|
[ObservableProperty]
|
|
private TrainingTaskStatus? _selectedStatus;
|
|
|
|
[ObservableProperty]
|
|
private string _searchKeyword = string.Empty;
|
|
|
|
[ObservableProperty]
|
|
private int _currentPageIndex = 1;
|
|
|
|
[ObservableProperty]
|
|
private int _pageSize = 20;
|
|
|
|
[ObservableProperty]
|
|
private int _totalCount;
|
|
|
|
[ObservableProperty]
|
|
private int _totalPages;
|
|
|
|
[ObservableProperty]
|
|
private bool _isLoading;
|
|
|
|
[ObservableProperty]
|
|
private bool _isRefreshing;
|
|
|
|
[ObservableProperty]
|
|
private TrainingTaskStatistics _statistics = new();
|
|
|
|
[ObservableProperty]
|
|
private string _statusMessage = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 构造函数。
|
|
/// </summary>
|
|
public TrainingTaskManagementViewModel(
|
|
ILogger<TrainingTaskManagementViewModel> logger,
|
|
ITrainingTaskService trainingTaskService)
|
|
{
|
|
_logger = logger;
|
|
_trainingTaskService = trainingTaskService;
|
|
|
|
// 初始化刷新定时器
|
|
_refreshTimer = new DispatcherTimer
|
|
{
|
|
Interval = TimeSpan.FromSeconds(30) // 30秒刷新一次
|
|
};
|
|
_refreshTimer.Tick += async (sender, e) => await RefreshDataAsync();
|
|
|
|
// 初始化状态选项
|
|
StatusOptions = new ObservableCollection<TrainingTaskStatus?>
|
|
{
|
|
null, // 全部
|
|
TrainingTaskStatus.Draft,
|
|
TrainingTaskStatus.Pending,
|
|
TrainingTaskStatus.Running,
|
|
TrainingTaskStatus.Paused,
|
|
TrainingTaskStatus.Completed,
|
|
TrainingTaskStatus.Failed,
|
|
TrainingTaskStatus.Cancelled
|
|
};
|
|
|
|
// 加载数据
|
|
_ = Task.Run(async () => await LoadDataAsync());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 状态选项。
|
|
/// </summary>
|
|
public ObservableCollection<TrainingTaskStatus?> StatusOptions { get; }
|
|
|
|
/// <summary>
|
|
/// 是否有选中的任务。
|
|
/// </summary>
|
|
public bool HasSelectedTask => SelectedTask != null;
|
|
|
|
/// <summary>
|
|
/// 选中任务是否可以启动。
|
|
/// </summary>
|
|
public bool CanStartTask => SelectedTask != null &&
|
|
(SelectedTask.Status == TrainingTaskStatus.Pending || SelectedTask.Status == TrainingTaskStatus.Paused);
|
|
|
|
/// <summary>
|
|
/// 选中任务是否可以暂停。
|
|
/// </summary>
|
|
public bool CanPauseTask => SelectedTask != null && SelectedTask.Status == TrainingTaskStatus.Running;
|
|
|
|
/// <summary>
|
|
/// 选中任务是否可以停止。
|
|
/// </summary>
|
|
public bool CanStopTask => SelectedTask != null &&
|
|
(SelectedTask.Status == TrainingTaskStatus.Running || SelectedTask.Status == TrainingTaskStatus.Paused);
|
|
|
|
/// <summary>
|
|
/// 选中任务是否可以取消。
|
|
/// </summary>
|
|
public bool CanCancelTask => SelectedTask != null &&
|
|
SelectedTask.Status != TrainingTaskStatus.Completed &&
|
|
SelectedTask.Status != TrainingTaskStatus.Cancelled;
|
|
|
|
/// <summary>
|
|
/// 选中任务是否可以重新启动。
|
|
/// </summary>
|
|
public bool CanRestartTask => SelectedTask != null &&
|
|
(SelectedTask.Status == TrainingTaskStatus.Failed || SelectedTask.Status == TrainingTaskStatus.Cancelled);
|
|
|
|
/// <summary>
|
|
/// 选中任务是否可以删除。
|
|
/// </summary>
|
|
public bool CanDeleteTask => SelectedTask != null && SelectedTask.Status != TrainingTaskStatus.Running;
|
|
|
|
/// <summary>
|
|
/// 刷新数据命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task RefreshDataAsync()
|
|
{
|
|
if (IsRefreshing) return;
|
|
|
|
try
|
|
{
|
|
IsRefreshing = true;
|
|
StatusMessage = "正在刷新数据...";
|
|
|
|
await LoadDataAsync();
|
|
await LoadStatisticsAsync();
|
|
|
|
StatusMessage = $"数据已更新 - {DateTime.Now:HH:mm:ss}";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "刷新数据失败");
|
|
StatusMessage = "刷新数据失败";
|
|
}
|
|
finally
|
|
{
|
|
IsRefreshing = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 搜索命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public async Task SearchAsync()
|
|
{
|
|
CurrentPageIndex = 1;
|
|
await LoadTasksAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 页面变化命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task PageChangedAsync(int pageIndex)
|
|
{
|
|
CurrentPageIndex = pageIndex;
|
|
await LoadTasksAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动任务命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task StartTaskAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
try
|
|
{
|
|
IsLoading = true;
|
|
StatusMessage = "正在启动任务...";
|
|
|
|
var result = await _trainingTaskService.StartTask(SelectedTask.Id, "当前用户");
|
|
if (result.Succeeded)
|
|
{
|
|
StatusMessage = "任务启动成功";
|
|
await LoadTasksAsync();
|
|
await LoadStatisticsAsync();
|
|
}
|
|
else
|
|
{
|
|
StatusMessage = $"任务启动失败: {result.Message}";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "启动任务失败");
|
|
StatusMessage = "任务启动失败";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 暂停任务命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task PauseTaskAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
try
|
|
{
|
|
IsLoading = true;
|
|
StatusMessage = "正在暂停任务...";
|
|
|
|
var result = await _trainingTaskService.PauseTask(SelectedTask.Id, "当前用户");
|
|
if (result.Succeeded)
|
|
{
|
|
StatusMessage = "任务暂停成功";
|
|
await LoadTasksAsync();
|
|
await LoadStatisticsAsync();
|
|
}
|
|
else
|
|
{
|
|
StatusMessage = $"任务暂停失败: {result.Message}";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "暂停任务失败");
|
|
StatusMessage = "任务暂停失败";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止任务命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task StopTaskAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
try
|
|
{
|
|
IsLoading = true;
|
|
StatusMessage = "正在停止任务...";
|
|
|
|
var result = await _trainingTaskService.StopTask(SelectedTask.Id, "当前用户");
|
|
if (result.Succeeded)
|
|
{
|
|
StatusMessage = "任务停止成功";
|
|
await LoadTasksAsync();
|
|
await LoadStatisticsAsync();
|
|
}
|
|
else
|
|
{
|
|
StatusMessage = $"任务停止失败: {result.Message}";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "停止任务失败");
|
|
StatusMessage = "任务停止失败";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 取消任务命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task CancelTaskAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
try
|
|
{
|
|
IsLoading = true;
|
|
StatusMessage = "正在取消任务...";
|
|
|
|
var result = await _trainingTaskService.CancelTask(SelectedTask.Id, "当前用户");
|
|
if (result.Succeeded)
|
|
{
|
|
StatusMessage = "任务取消成功";
|
|
await LoadTasksAsync();
|
|
await LoadStatisticsAsync();
|
|
}
|
|
else
|
|
{
|
|
StatusMessage = $"任务取消失败: {result.Message}";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "取消任务失败");
|
|
StatusMessage = "任务取消失败";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 重新启动任务命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task RestartTaskAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
try
|
|
{
|
|
IsLoading = true;
|
|
StatusMessage = "正在重新启动任务...";
|
|
|
|
var result = await _trainingTaskService.RestartTask(SelectedTask.Id, "当前用户");
|
|
if (result.Succeeded)
|
|
{
|
|
StatusMessage = "任务重新启动成功";
|
|
await LoadTasksAsync();
|
|
await LoadStatisticsAsync();
|
|
}
|
|
else
|
|
{
|
|
StatusMessage = $"任务重新启动失败: {result.Message}";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "重新启动任务失败");
|
|
StatusMessage = "任务重新启动失败";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除任务命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task DeleteTaskAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
try
|
|
{
|
|
IsLoading = true;
|
|
StatusMessage = "正在删除任务...";
|
|
|
|
var result = await _trainingTaskService.DeleteTask(SelectedTask.Id);
|
|
if (result.Succeeded)
|
|
{
|
|
StatusMessage = "任务删除成功";
|
|
SelectedTask = null;
|
|
await LoadTasksAsync();
|
|
await LoadStatisticsAsync();
|
|
}
|
|
else
|
|
{
|
|
StatusMessage = $"任务删除失败: {result.Message}";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "删除任务失败");
|
|
StatusMessage = "任务删除失败";
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 查看任务详情命令。
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task ViewTaskDetailsAsync()
|
|
{
|
|
if (SelectedTask == null) return;
|
|
|
|
// TODO: 实现查看任务详情功能
|
|
StatusMessage = $"查看任务详情: {SelectedTask.Name}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载数据。
|
|
/// </summary>
|
|
private async Task LoadDataAsync()
|
|
{
|
|
await Task.WhenAll(LoadTasksAsync(), LoadStatisticsAsync());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载任务列表。
|
|
/// </summary>
|
|
private async Task LoadTasksAsync()
|
|
{
|
|
try
|
|
{
|
|
var result = await _trainingTaskService.GetTaskPagedList(
|
|
CurrentPageIndex,
|
|
PageSize,
|
|
SelectedStatus,
|
|
string.IsNullOrWhiteSpace(SearchKeyword) ? null : SearchKeyword);
|
|
|
|
if (result.Succeeded)
|
|
{
|
|
var tasks = result.Data.Items.ToList();
|
|
await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
Tasks.Clear();
|
|
foreach (var task in tasks)
|
|
{
|
|
Tasks.Add(task);
|
|
}
|
|
TotalCount = result.Data.TotalCount;
|
|
TotalPages = result.Data.TotalPages;
|
|
});
|
|
}
|
|
else
|
|
{
|
|
_logger.LogError("加载任务列表失败: {Message}", result.Message);
|
|
StatusMessage = "加载任务列表失败";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "加载任务列表异常");
|
|
StatusMessage = "加载任务列表异常";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载统计信息。
|
|
/// </summary>
|
|
private async Task LoadStatisticsAsync()
|
|
{
|
|
try
|
|
{
|
|
var result = await _trainingTaskService.GetTaskStatistics();
|
|
if (result.Succeeded)
|
|
{
|
|
Statistics = result.Data;
|
|
}
|
|
else
|
|
{
|
|
_logger.LogError("加载统计信息失败: {Message}", result.Message);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "加载统计信息异常");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 选中任务变化时更新命令状态。
|
|
/// </summary>
|
|
partial void OnSelectedTaskChanged(TrainingTaskModel? value)
|
|
{
|
|
OnPropertyChanged(nameof(HasSelectedTask));
|
|
OnPropertyChanged(nameof(CanStartTask));
|
|
OnPropertyChanged(nameof(CanPauseTask));
|
|
OnPropertyChanged(nameof(CanStopTask));
|
|
OnPropertyChanged(nameof(CanCancelTask));
|
|
OnPropertyChanged(nameof(CanRestartTask));
|
|
OnPropertyChanged(nameof(CanDeleteTask));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动自动刷新。
|
|
/// </summary>
|
|
public void StartAutoRefresh()
|
|
{
|
|
_refreshTimer.Start();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止自动刷新。
|
|
/// </summary>
|
|
public void StopAutoRefresh()
|
|
{
|
|
_refreshTimer.Stop();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 释放资源。
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
_refreshTimer?.Stop();
|
|
_refreshTimer?.Stop();
|
|
}
|
|
}
|