diff --git a/src/WCTDataMiner.Core/Services/ScenarioService.cs b/src/WCTDataMiner.Core/Services/ScenarioService.cs
index c1b4b10..b070ed9 100644
--- a/src/WCTDataMiner.Core/Services/ScenarioService.cs
+++ b/src/WCTDataMiner.Core/Services/ScenarioService.cs
@@ -6,6 +6,17 @@ using WCTDataMiner.Core.Parsers;
namespace WCTDataMiner.Core.Services;
+///
+/// 篮选条件常量
+///
+public static class FilterConstants
+{
+ ///
+ /// 表示"全部"选项的常量值
+ ///
+ public const string AllOption = "全部";
+}
+
///
/// 测试场景服务 - 负责测试场景的创建和查询(并发安全版本)
///
@@ -129,6 +140,130 @@ public class ScenarioService
.FirstOrDefaultAsync(s => s.Id == scenarioId);
}
+ ///
+ /// 获取所有测试场景(含维度属性)
+ ///
+ /// 每页数量,默认50,传0表示不分页
+ /// 页码,从0开始
+ public async Task> GetAllScenariosAsync(int pageSize = 50, int pageIndex = 0)
+ {
+ var query = _context.TestScenarios
+ .Include(s => s.TxPanel)
+ .Include(s => s.TxHardware)
+ .Include(s => s.TxSoftware)
+ .Include(s => s.RxType)
+ .OrderByDescending(s => s.TestDate)
+ .ThenByDescending(s => s.TestSequence)
+ .AsNoTracking();
+
+ if (pageSize > 0)
+ {
+ query = query.Skip(pageIndex * pageSize).Take(pageSize);
+ }
+
+ return await query.ToListAsync();
+ }
+
+ ///
+ /// 获取场景总数
+ ///
+ public async Task GetScenariosCountAsync()
+ {
+ return await _context.TestScenarios.CountAsync();
+ }
+
+ ///
+ /// 获取可用的筛选选项
+ ///
+ public async Task GetFilterOptionsAsync()
+ {
+ var txPanels = await _context.TxPanels
+ .Select(p => p.Name)
+ .Distinct()
+ .OrderBy(n => n)
+ .ToListAsync();
+
+ var txHardwares = await _context.TxHardwares
+ .Select(h => h.Version)
+ .Distinct()
+ .OrderBy(v => v)
+ .ToListAsync();
+
+ var txSoftwares = await _context.TxSoftwares
+ .Select(s => s.Version)
+ .Distinct()
+ .OrderBy(v => v)
+ .ToListAsync();
+
+ var rxTypes = await _context.RxTypes
+ .Select(r => r.Name)
+ .Distinct()
+ .OrderBy(n => n)
+ .ToListAsync();
+
+ return new FilterOptions(
+ txPanels.Prepend(FilterConstants.AllOption).ToList(),
+ txHardwares.Prepend(FilterConstants.AllOption).ToList(),
+ txSoftwares.Prepend(FilterConstants.AllOption).ToList(),
+ rxTypes.Prepend(FilterConstants.AllOption).ToList());
+ }
+
+ ///
+ /// 根据筛选条件获取测试场景
+ ///
+ /// TxPanel 名称,null 或 "全部" 表示不过滤
+ /// TxHardware 版本,null 或 "全部" 表示不过滤
+ /// TxSoftware 版本,null 或 "全部" 表示不过滤
+ /// RxType 名称,null 或 "全部" 表示不过滤
+ /// 每页数量,默认50,传0表示不分页
+ /// 页码,从0开始
+ public async Task> GetScenariosByFilterAsync(
+ string? txPanel = null,
+ string? txHardware = null,
+ string? txSoftware = null,
+ string? rxType = null,
+ int pageSize = 50,
+ int pageIndex = 0)
+ {
+ var query = _context.TestScenarios
+ .Include(s => s.TxPanel)
+ .Include(s => s.TxHardware)
+ .Include(s => s.TxSoftware)
+ .Include(s => s.RxType)
+ .AsNoTracking();
+
+ if (!string.IsNullOrEmpty(txPanel) && txPanel != FilterConstants.AllOption)
+ {
+ query = query.Where(s => s.TxPanel.Name == txPanel);
+ }
+
+ if (!string.IsNullOrEmpty(txHardware) && txHardware != FilterConstants.AllOption)
+ {
+ query = query.Where(s => s.TxHardware.Version == txHardware);
+ }
+
+ if (!string.IsNullOrEmpty(txSoftware) && txSoftware != FilterConstants.AllOption)
+ {
+ query = query.Where(s => s.TxSoftware.Version == txSoftware);
+ }
+
+ if (!string.IsNullOrEmpty(rxType) && rxType != FilterConstants.AllOption)
+ {
+ query = query.Where(s => s.RxType.Name == rxType);
+ }
+
+ query = query
+ .OrderByDescending(s => s.TestDate)
+ .ThenByDescending(s => s.TestSequence);
+
+ if (pageSize > 0)
+ {
+ query = query.Skip(pageIndex * pageSize).Take(pageSize);
+ }
+
+ return await query.ToListAsync();
+ }
+
///
/// 检测 SQLite 唯一约束违反错误
///
@@ -137,4 +272,13 @@ public class ScenarioService
return ex.InnerException is Microsoft.Data.Sqlite.SqliteException sqliteEx
&& sqliteEx.SqliteErrorCode == 19; // SQLITE_CONSTRAINT
}
-}
\ No newline at end of file
+}
+
+///
+/// 筛选选项数据
+///
+public record FilterOptions(
+ List TxPanels,
+ List TxHardwares,
+ List TxSoftwares,
+ List RxTypes);
\ No newline at end of file
diff --git a/src/WCTDataMiner.Wpf/App.xaml.cs b/src/WCTDataMiner.Wpf/App.xaml.cs
index 400efe9..884a4d9 100644
--- a/src/WCTDataMiner.Wpf/App.xaml.cs
+++ b/src/WCTDataMiner.Wpf/App.xaml.cs
@@ -68,12 +68,13 @@ public partial class App : Application
services.AddDatabaseServices(context.Configuration);
services.AddApplicationServices();
- // 注册 ViewModels
- services.AddTransient();
- services.AddTransient();
+ // 注册 ViewModels(使用 Singleton 确保消息订阅正确工作)
+ services.AddSingleton();
+ services.AddSingleton();
+ // Chart ViewModels 使用 Transient,每次导航创建新实例
services.AddTransient();
services.AddTransient();
- services.AddTransient();
+ services.AddSingleton();
// 注册 Views
services.AddTransient();
@@ -85,6 +86,23 @@ public partial class App : Application
.Build();
var mainWindow = _host.Services.GetRequiredService();
+
+ // 初始化加载场景数据
+ var mainViewModel = _host.Services.GetRequiredService();
+ mainWindow.Loaded += async (s, e) =>
+ {
+ try
+ {
+ await mainViewModel.InitializeAsync();
+ }
+ catch (Exception ex)
+ {
+ _logger?.Error(ex, "主窗口初始化失败");
+ MessageBox.Show($"应用初始化失败: {ex.Message}", "错误",
+ MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ };
+
mainWindow.Show();
base.OnStartup(e);
diff --git a/src/WCTDataMiner.Wpf/Messages/DataImportedMessage.cs b/src/WCTDataMiner.Wpf/Messages/DataImportedMessage.cs
new file mode 100644
index 0000000..5f1e8b0
--- /dev/null
+++ b/src/WCTDataMiner.Wpf/Messages/DataImportedMessage.cs
@@ -0,0 +1,19 @@
+namespace WCTDataMiner.Wpf.Messages;
+
+///
+/// 数据导入完成消息
+///
+/// 导入的文件数量
+public record DataImportedMessage(int ImportedCount);
+
+///
+/// 导航到 Ploss 图表消息
+///
+/// 场景 ID
+public record NavigateToPlossChartMessage(Guid ScenarioId);
+
+///
+/// 导航到 Qfod 图表消息
+///
+/// 场景 ID
+public record NavigateToQfodChartMessage(Guid ScenarioId);
\ No newline at end of file
diff --git a/src/WCTDataMiner.Wpf/ViewModels/ImportViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/ImportViewModel.cs
index 3aeca9d..5510465 100644
--- a/src/WCTDataMiner.Wpf/ViewModels/ImportViewModel.cs
+++ b/src/WCTDataMiner.Wpf/ViewModels/ImportViewModel.cs
@@ -1,9 +1,11 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using System.Collections.ObjectModel;
using WCTDataMiner.Core.Services;
+using WCTDataMiner.Wpf.Messages;
namespace WCTDataMiner.Wpf.ViewModels;
@@ -99,6 +101,9 @@ public partial class ImportViewModel : ObservableObject
StatusMessage = $"导入完成: Qfod={report.QfodCount}, Ploss={report.PlossCount}, 错误={report.ErrorCount}";
_logger.LogInformation("单文件导入完成: {FileName}, Qfod={Qfod}, Ploss={Ploss}, 错误={Errors}",
report.FileName, report.QfodCount, report.PlossCount, report.ErrorCount);
+
+ // 发送导入完成消息,通知其他 ViewModel 刷新数据
+ WeakReferenceMessenger.Default.Send(new DataImportedMessage(1));
}
else if (System.IO.Directory.Exists(SelectedPath))
{
@@ -118,6 +123,9 @@ public partial class ImportViewModel : ObservableObject
StatusMessage = $"导入完成: {reports.Count} 个文件, Qfod={totalQfod}, Ploss={totalPloss}, 错误={totalErrors}";
_logger.LogInformation("目录导入完成: {FileCount} 个文件, Qfod={Qfod}, Ploss={Ploss}, 错误={Errors}",
reports.Count, totalQfod, totalPloss, totalErrors);
+
+ // 发送导入完成消息,通知其他 ViewModel 刷新数据
+ WeakReferenceMessenger.Default.Send(new DataImportedMessage(reports.Count));
}
else
{
diff --git a/src/WCTDataMiner.Wpf/ViewModels/MainViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/MainViewModel.cs
index aa19288..6d28e74 100644
--- a/src/WCTDataMiner.Wpf/ViewModels/MainViewModel.cs
+++ b/src/WCTDataMiner.Wpf/ViewModels/MainViewModel.cs
@@ -1,15 +1,22 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.Mvvm.Messaging;
+using Microsoft.Extensions.DependencyInjection;
+using WCTDataMiner.Core.Services;
+using WCTDataMiner.Wpf.Messages;
namespace WCTDataMiner.Wpf.ViewModels;
///
/// 主窗口 ViewModel - 导航控制
///
-public partial class MainViewModel : ObservableObject
+public partial class MainViewModel : ObservableObject,
+ IRecipient,
+ IRecipient
{
private readonly ImportViewModel _importViewModel;
private readonly ScenarioListViewModel _scenarioListViewModel;
+ private readonly IServiceProvider _serviceProvider;
[ObservableProperty]
private ObservableObject _currentView = null!;
@@ -26,17 +33,48 @@ public partial class MainViewModel : ObservableObject
[ObservableProperty]
private string? _selectedRxType;
- // 筛选选项列表
- public List TxPanels { get; } = new() { "全部", "singleMold", "dualMold" };
- public List TxHardwares { get; } = new() { "全部", "v1.0", "v2.0" };
- public List TxSoftwares { get; } = new() { "全部", "hex2_1", "hex2_2" };
- public List RxTypes { get; } = new() { "全部", "iPhone15", "iPhone16", "Android" };
+ // 筛选选项列表(动态加载)
+ [ObservableProperty]
+ private List _txPanels = new() { FilterConstants.AllOption };
- public MainViewModel(ImportViewModel importViewModel, ScenarioListViewModel scenarioListViewModel)
+ [ObservableProperty]
+ private List _txHardwares = new() { FilterConstants.AllOption };
+
+ [ObservableProperty]
+ private List _txSoftwares = new() { FilterConstants.AllOption };
+
+ [ObservableProperty]
+ private List _rxTypes = new() { FilterConstants.AllOption };
+
+ public MainViewModel(
+ ImportViewModel importViewModel,
+ ScenarioListViewModel scenarioListViewModel,
+ IServiceProvider serviceProvider)
{
_importViewModel = importViewModel;
_scenarioListViewModel = scenarioListViewModel;
+ _serviceProvider = serviceProvider;
_currentView = _scenarioListViewModel;
+
+ // 注册导航消息订阅
+ WeakReferenceMessenger.Default.Register(this);
+ WeakReferenceMessenger.Default.Register(this);
+ }
+
+ ///
+ /// 初始化加载场景数据和筛选选项
+ ///
+ public async Task InitializeAsync()
+ {
+ // 加载筛选选项
+ var filterOptions = await _scenarioListViewModel.GetFilterOptionsAsync();
+ TxPanels = filterOptions.TxPanels;
+ TxHardwares = filterOptions.TxHardwares;
+ TxSoftwares = filterOptions.TxSoftwares;
+ RxTypes = filterOptions.RxTypes;
+
+ // 加载场景列表
+ await _scenarioListViewModel.LoadScenariosAsync();
}
[RelayCommand]
@@ -46,20 +84,54 @@ public partial class MainViewModel : ObservableObject
}
[RelayCommand]
- private void NavigateToScenarios()
+ private async Task NavigateToScenarios()
{
CurrentView = _scenarioListViewModel;
+ await _scenarioListViewModel.LoadScenariosAsync();
}
[RelayCommand]
- private void NavigateToPlossChart(int scenarioId)
+ private void NavigateToPlossChart(Guid scenarioId)
{
- CurrentView = new PlossChartViewModel { ScenarioId = scenarioId };
+ var vm = _serviceProvider.GetRequiredService();
+ vm.ScenarioId = scenarioId;
+ CurrentView = vm;
}
[RelayCommand]
- private void NavigateToQfodChart(int scenarioId)
+ private void NavigateToQfodChart(Guid scenarioId)
{
- CurrentView = new QfodChartViewModel { ScenarioId = scenarioId };
+ var vm = _serviceProvider.GetRequiredService();
+ vm.ScenarioId = scenarioId;
+ CurrentView = vm;
}
-}
\ No newline at end of file
+
+ ///
+ /// 应用筛选条件并刷新场景列表
+ ///
+ public async Task ApplyFilterAsync()
+ {
+ await _scenarioListViewModel.LoadScenariosByFilterAsync(
+ SelectedTxPanel, SelectedTxHardware, SelectedTxSoftware, SelectedRxType);
+ }
+
+ ///
+ /// 接收导航到 Ploss 图表消息
+ ///
+ public void Receive(NavigateToPlossChartMessage message)
+ {
+ var vm = _serviceProvider.GetRequiredService();
+ vm.ScenarioId = message.ScenarioId;
+ CurrentView = vm;
+ }
+
+ ///
+ /// 接收导航到 Qfod 图表消息
+ ///
+ public void Receive(NavigateToQfodChartMessage message)
+ {
+ var vm = _serviceProvider.GetRequiredService();
+ vm.ScenarioId = message.ScenarioId;
+ CurrentView = vm;
+ }
+}
diff --git a/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs
index cd822a6..7b744fb 100644
--- a/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs
+++ b/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs
@@ -1,6 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
+using Microsoft.Extensions.Logging;
+using WCTDataMiner.Core.Services;
namespace WCTDataMiner.Wpf.ViewModels;
@@ -9,8 +11,11 @@ namespace WCTDataMiner.Wpf.ViewModels;
///
public partial class PlossChartViewModel : ObservableObject
{
+ private readonly ScenarioService _scenarioService;
+ private readonly ILogger _logger;
+
[ObservableProperty]
- private int _scenarioId;
+ private Guid _scenarioId;
[ObservableProperty]
private ISeries[] _series;
@@ -21,8 +26,13 @@ public partial class PlossChartViewModel : ObservableObject
[ObservableProperty]
private Axis[] _yAxes;
- public PlossChartViewModel()
+ public PlossChartViewModel(
+ ScenarioService scenarioService,
+ ILogger logger)
{
+ _scenarioService = scenarioService;
+ _logger = logger;
+
// 初始化图表配置
Series = Array.Empty();
XAxes = new Axis[] { new Axis { Name = "Trigger Count" } };
@@ -31,19 +41,26 @@ public partial class PlossChartViewModel : ObservableObject
public async Task LoadDataAsync()
{
- // TODO: 从数据库加载 Ploss 数据并构建图表
- Series = new ISeries[]
+ try
{
- new LineSeries
+ // TODO: 从数据库加载 Ploss 数据并构建图表
+ Series = new ISeries[]
{
- Name = "Ploss",
- Values = new double[] { -2882, -3500, -4200, -3800, -4500 }
- },
- new LineSeries
- {
- Name = "Threshold",
- Values = new double[] { -3000, -3000, -3000, -3000, -3000 }
- }
- };
+ new LineSeries
+ {
+ Name = "Ploss",
+ Values = new double[] { -2882, -3500, -4200, -3800, -4500 }
+ },
+ new LineSeries
+ {
+ Name = "Threshold",
+ Values = new double[] { -3000, -3000, -3000, -3000, -3000 }
+ }
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "加载 Ploss 图表数据失败: ScenarioId={ScenarioId}", ScenarioId);
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs
index 91e9b30..c61ef20 100644
--- a/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs
+++ b/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs
@@ -1,6 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
+using Microsoft.Extensions.Logging;
+using WCTDataMiner.Core.Services;
namespace WCTDataMiner.Wpf.ViewModels;
@@ -9,8 +11,11 @@ namespace WCTDataMiner.Wpf.ViewModels;
///
public partial class QfodChartViewModel : ObservableObject
{
+ private readonly ScenarioService _scenarioService;
+ private readonly ILogger _logger;
+
[ObservableProperty]
- private int _scenarioId;
+ private Guid _scenarioId;
[ObservableProperty]
private ISeries[] _series;
@@ -21,8 +26,13 @@ public partial class QfodChartViewModel : ObservableObject
[ObservableProperty]
private Axis[] _yAxes;
- public QfodChartViewModel()
+ public QfodChartViewModel(
+ ScenarioService scenarioService,
+ ILogger logger)
{
+ _scenarioService = scenarioService;
+ _logger = logger;
+
// 初始化图表配置
Series = Array.Empty();
XAxes = new Axis[] { new Axis { Name = "Coil Index" } };
@@ -31,19 +41,26 @@ public partial class QfodChartViewModel : ObservableObject
public async Task LoadDataAsync()
{
- // TODO: 从数据库加载 Qfod 数据并构建图表
- Series = new ISeries[]
+ try
{
- new LineSeries
+ // TODO: 从数据库加载 Qfod 数据并构建图表
+ Series = new ISeries[]
{
- Name = "DeltaQ",
- Values = new double[] { 25, 30, 28 }
- },
- new LineSeries
- {
- Name = "CurrentQ",
- Values = new double[] { 45.5, 50.2, 48.8 }
- }
- };
+ new LineSeries
+ {
+ Name = "DeltaQ",
+ Values = new double[] { 25, 30, 28 }
+ },
+ new LineSeries
+ {
+ Name = "CurrentQ",
+ Values = new double[] { 45.5, 50.2, 48.8 }
+ }
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "加载 Qfod 图表数据失败: ScenarioId={ScenarioId}", ScenarioId);
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/WCTDataMiner.Wpf/ViewModels/ScenarioListViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/ScenarioListViewModel.cs
index fbc0cd1..6b3f5b2 100644
--- a/src/WCTDataMiner.Wpf/ViewModels/ScenarioListViewModel.cs
+++ b/src/WCTDataMiner.Wpf/ViewModels/ScenarioListViewModel.cs
@@ -1,22 +1,163 @@
using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Messaging;
+using Microsoft.Extensions.Logging;
+using System.Collections.ObjectModel;
+using WCTDataMiner.Core.Services;
+using WCTDataMiner.Wpf.Messages;
namespace WCTDataMiner.Wpf.ViewModels;
///
/// 场景列表 ViewModel
///
-public partial class ScenarioListViewModel : ObservableObject
+public partial class ScenarioListViewModel : ObservableObject, IRecipient
{
+ private readonly ScenarioService _scenarioService;
+ private readonly ILogger _logger;
+
[ObservableProperty]
- private List _scenarios;
+ private ObservableCollection _scenarios = new();
[ObservableProperty]
private ScenarioItem? _selectedScenario;
- public ScenarioListViewModel()
+ [ObservableProperty]
+ private bool _isLoading;
+
+ [ObservableProperty]
+ private string _loadingMessage = "";
+
+ public ScenarioListViewModel(
+ ScenarioService scenarioService,
+ ILogger logger)
{
- // TODO: 从数据库加载场景列表
- _scenarios = new List();
+ _scenarioService = scenarioService;
+ _logger = logger;
+
+ // 注册消息订阅,接收导入完成通知
+ WeakReferenceMessenger.Default.Register(this);
+ }
+
+ ///
+ /// 从数据库加载场景列表
+ ///
+ public async Task LoadScenariosAsync()
+ {
+ // 避免并发加载
+ if (IsLoading)
+ {
+ _logger.LogWarning("跳过重复加载请求:当前正在加载");
+ return;
+ }
+
+ IsLoading = true;
+ LoadingMessage = "正在加载场景列表...";
+
+ try
+ {
+ var scenarios = await _scenarioService.GetAllScenariosAsync();
+
+ // 批量更新,避免逐项 Add 导致频繁 UI 刷新
+ var items = scenarios.Select(s => new ScenarioItem
+ {
+ Id = s.Id,
+ TxPanel = s.TxPanel?.Name ?? "",
+ TxHardware = s.TxHardware?.Version ?? "",
+ TxSoftware = s.TxSoftware?.Version ?? "",
+ RxType = s.RxType?.Name ?? "",
+ TestDate = s.TestDate.ToString("yyyy-MM-dd"),
+ QfodCount = s.QfodCount,
+ PlossCount = s.PlossCount
+ }).ToList();
+
+ Scenarios = new ObservableCollection(items);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "加载场景列表失败");
+ LoadingMessage = $"加载失败: {ex.Message}";
+ return;
+ }
+ finally
+ {
+ IsLoading = false;
+ LoadingMessage = "";
+ }
+ }
+
+ ///
+ /// 根据筛选条件加载场景
+ ///
+ public async Task LoadScenariosByFilterAsync(
+ string? txPanel = null,
+ string? txHardware = null,
+ string? txSoftware = null,
+ string? rxType = null)
+ {
+ // 避免并发加载
+ if (IsLoading)
+ {
+ _logger.LogWarning("跳过重复筛选请求:当前正在加载");
+ return;
+ }
+
+ IsLoading = true;
+ LoadingMessage = "正在筛选场景...";
+
+ try
+ {
+ var scenarios = await _scenarioService.GetScenariosByFilterAsync(
+ txPanel, txHardware, txSoftware, rxType);
+
+ // 批量更新,避免逐项 Add 导致频繁 UI 刷新
+ var items = scenarios.Select(s => new ScenarioItem
+ {
+ Id = s.Id,
+ TxPanel = s.TxPanel?.Name ?? "",
+ TxHardware = s.TxHardware?.Version ?? "",
+ TxSoftware = s.TxSoftware?.Version ?? "",
+ RxType = s.RxType?.Name ?? "",
+ TestDate = s.TestDate.ToString("yyyy-MM-dd"),
+ QfodCount = s.QfodCount,
+ PlossCount = s.PlossCount
+ }).ToList();
+
+ Scenarios = new ObservableCollection(items);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "筛选场景失败");
+ LoadingMessage = $"筛选失败: {ex.Message}";
+ return;
+ }
+ finally
+ {
+ IsLoading = false;
+ LoadingMessage = "";
+ }
+ }
+
+ ///
+ /// 接收数据导入完成消息,自动刷新列表
+ ///
+ public async void Receive(DataImportedMessage message)
+ {
+ try
+ {
+ await LoadScenariosAsync();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "接收数据导入消息后刷新场景列表失败");
+ }
+ }
+
+ ///
+ /// 获取可用的筛选选项
+ ///
+ public async Task GetFilterOptionsAsync()
+ {
+ return await _scenarioService.GetFilterOptionsAsync();
}
}
@@ -25,7 +166,7 @@ public partial class ScenarioListViewModel : ObservableObject
///
public class ScenarioItem
{
- public int Id { get; set; }
+ public Guid Id { get; set; }
public string TxPanel { get; set; } = "";
public string TxHardware { get; set; } = "";
public string TxSoftware { get; set; } = "";
@@ -33,4 +174,4 @@ public class ScenarioItem
public string TestDate { get; set; } = "";
public int QfodCount { get; set; }
public int PlossCount { get; set; }
-}
\ No newline at end of file
+}
diff --git a/src/WCTDataMiner.Wpf/Views/ScenarioListView.xaml.cs b/src/WCTDataMiner.Wpf/Views/ScenarioListView.xaml.cs
index 95662b6..336d03e 100644
--- a/src/WCTDataMiner.Wpf/Views/ScenarioListView.xaml.cs
+++ b/src/WCTDataMiner.Wpf/Views/ScenarioListView.xaml.cs
@@ -1,5 +1,8 @@
+using CommunityToolkit.Mvvm.Messaging;
using System.Windows;
using System.Windows.Controls;
+using WCTDataMiner.Wpf.Messages;
+using WCTDataMiner.Wpf.ViewModels;
namespace WCTDataMiner.Wpf.Views;
@@ -12,19 +15,17 @@ public partial class ScenarioListView : UserControl
private void OnViewPlossChart(object sender, RoutedEventArgs e)
{
- // TODO: 导航到 Ploss 图表页面
- if (DataContext is ViewModels.ScenarioListViewModel vm && vm.SelectedScenario != null)
+ if (DataContext is ScenarioListViewModel vm && vm.SelectedScenario != null)
{
- // Navigation logic
+ WeakReferenceMessenger.Default.Send(new NavigateToPlossChartMessage(vm.SelectedScenario.Id));
}
}
private void OnViewQfodChart(object sender, RoutedEventArgs e)
{
- // TODO: 导航到 Qfod 图表页面
- if (DataContext is ViewModels.ScenarioListViewModel vm && vm.SelectedScenario != null)
+ if (DataContext is ScenarioListViewModel vm && vm.SelectedScenario != null)
{
- // Navigation logic
+ WeakReferenceMessenger.Default.Send(new NavigateToQfodChartMessage(vm.SelectedScenario.Id));
}
}
}
\ No newline at end of file