diff --git a/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs index 7b744fb..5da65be 100644 --- a/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs +++ b/src/WCTDataMiner.Wpf/ViewModels/PlossChartViewModel.cs @@ -1,8 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; using LiveChartsCore; using LiveChartsCore.SkiaSharpView; using Microsoft.Extensions.Logging; using WCTDataMiner.Core.Services; +using WCTDataMiner.Wpf.Messages; namespace WCTDataMiner.Wpf.ViewModels; @@ -26,6 +29,12 @@ public partial class PlossChartViewModel : ObservableObject [ObservableProperty] private Axis[] _yAxes; + [ObservableProperty] + private bool _isLoading; + + [ObservableProperty] + private string _loadingMessage = ""; + public PlossChartViewModel( ScenarioService scenarioService, ILogger logger) @@ -39,28 +48,93 @@ public partial class PlossChartViewModel : ObservableObject YAxes = new Axis[] { new Axis { Name = "Power Loss (mW)" } }; } + /// + /// ScenarioId 属性变更时自动触发数据加载 + /// + partial void OnScenarioIdChanged(Guid value) + { + if (value != Guid.Empty) + { + _ = LoadDataAsync().ContinueWith(t => + { + if (t.Exception != null) + { + _logger.LogError(t.Exception, "LoadDataAsync 失败: ScenarioId={ScenarioId}", value); + } + }, TaskContinuationOptions.OnlyOnFaulted); + } + } + + [RelayCommand] + private void SwitchToTable() + { + WeakReferenceMessenger.Default.Send(new NavigateToPlossTableMessage(ScenarioId)); + } + public async Task LoadDataAsync() { + if (IsLoading) return; // 防并发 + + IsLoading = true; + LoadingMessage = "正在加载数据..."; + try { - // TODO: 从数据库加载 Ploss 数据并构建图表 + var records = await _scenarioService.GetPlossRecordsByScenarioIdAsync(ScenarioId); + + if (records.Count == 0) + { + Series = Array.Empty(); + _logger.LogWarning("未找到 Ploss 数据: ScenarioId={ScenarioId}", ScenarioId); + LoadingMessage = "无数据"; + return; + } + + // 构建 Ploss 曲线 (Field7) 和 Threshold 阈值线 (Field8) + var plossValues = records.Select(r => (double)r.Field7).ToArray(); + var thresholdValues = records.Select(r => (double)r.Field8).ToArray(); + var triggerLabels = records.Select(r => r.Field9.ToString()).ToArray(); + Series = new ISeries[] { new LineSeries { Name = "Ploss", - Values = new double[] { -2882, -3500, -4200, -3800, -4500 } + Values = plossValues, + Fill = null, + GeometrySize = 5 }, new LineSeries { Name = "Threshold", - Values = new double[] { -3000, -3000, -3000, -3000, -3000 } + Values = thresholdValues, + Fill = null, + GeometrySize = 0, + LineSmoothness = 0 // 直线 } }; + + // 更新 X 轴标签 + XAxes = new Axis[] + { + new Axis + { + Name = "Trigger Count", + Labels = triggerLabels + } + }; + + _logger.LogInformation("加载 Ploss 图表数据成功: ScenarioId={ScenarioId}, 记录数={Count}", ScenarioId, records.Count); + LoadingMessage = ""; } catch (Exception ex) { _logger.LogError(ex, "加载 Ploss 图表数据失败: ScenarioId={ScenarioId}", ScenarioId); + LoadingMessage = $"加载失败: {ex.Message}"; + } + finally + { + IsLoading = false; } } -} +} \ No newline at end of file diff --git a/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs b/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs index c61ef20..8073f0e 100644 --- a/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs +++ b/src/WCTDataMiner.Wpf/ViewModels/QfodChartViewModel.cs @@ -1,8 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; using LiveChartsCore; using LiveChartsCore.SkiaSharpView; using Microsoft.Extensions.Logging; using WCTDataMiner.Core.Services; +using WCTDataMiner.Wpf.Messages; namespace WCTDataMiner.Wpf.ViewModels; @@ -26,6 +29,12 @@ public partial class QfodChartViewModel : ObservableObject [ObservableProperty] private Axis[] _yAxes; + [ObservableProperty] + private bool _isLoading; + + [ObservableProperty] + private string _loadingMessage = ""; + public QfodChartViewModel( ScenarioService scenarioService, ILogger logger) @@ -39,28 +48,97 @@ public partial class QfodChartViewModel : ObservableObject YAxes = new Axis[] { new Axis { Name = "Q Value" } }; } + /// + /// ScenarioId 属性变更时自动触发数据加载 + /// + partial void OnScenarioIdChanged(Guid value) + { + if (value != Guid.Empty) + { + _ = LoadDataAsync().ContinueWith(t => + { + if (t.Exception != null) + { + _logger.LogError(t.Exception, "LoadDataAsync 失败: ScenarioId={ScenarioId}", value); + } + }, TaskContinuationOptions.OnlyOnFaulted); + } + } + + [RelayCommand] + private void SwitchToTable() + { + WeakReferenceMessenger.Default.Send(new NavigateToQfodTableMessage(ScenarioId)); + } + public async Task LoadDataAsync() { + if (IsLoading) return; // 防并发 + + IsLoading = true; + LoadingMessage = "正在加载数据..."; + try { - // TODO: 从数据库加载 Qfod 数据并构建图表 + var records = await _scenarioService.GetQfodRecordsByScenarioIdAsync(ScenarioId); + + if (records.Count == 0) + { + Series = Array.Empty(); + _logger.LogWarning("未找到 Qfod 数据: ScenarioId={ScenarioId}", ScenarioId); + LoadingMessage = "无数据"; + return; + } + + // 构建 DeltaQ、CurrentQ、RawQ 三条曲线 + var deltaQValues = records.Select(r => (double)r.DeltaQ).ToArray(); + var currentQValues = records.Select(r => (double)r.CurrentQ).ToArray(); + var rawQValues = records.Select(r => (double)r.RawQ).ToArray(); + var coilLabels = records.Select(r => $"{r.ChargerIndex}-{r.CoilIndex}").ToArray(); + Series = new ISeries[] { new LineSeries { Name = "DeltaQ", - Values = new double[] { 25, 30, 28 } + Values = deltaQValues, + GeometrySize = 5 }, new LineSeries { Name = "CurrentQ", - Values = new double[] { 45.5, 50.2, 48.8 } + Values = currentQValues, + GeometrySize = 5 + }, + new LineSeries + { + Name = "RawQ", + Values = rawQValues, + GeometrySize = 5 } }; + + // 更新 X 轴标签 + XAxes = new Axis[] + { + new Axis + { + Name = "Charger-Coil Index", + Labels = coilLabels + } + }; + + _logger.LogInformation("加载 Qfod 图表数据成功: ScenarioId={ScenarioId}, 记录数={Count}", ScenarioId, records.Count); + LoadingMessage = ""; } catch (Exception ex) { _logger.LogError(ex, "加载 Qfod 图表数据失败: ScenarioId={ScenarioId}", ScenarioId); + LoadingMessage = $"加载失败: {ex.Message}"; + } + finally + { + IsLoading = false; } } -} +} \ No newline at end of file diff --git a/src/WCTDataMiner.Wpf/Views/PlossChartView.xaml b/src/WCTDataMiner.Wpf/Views/PlossChartView.xaml index 6fae7bc..55e03e2 100644 --- a/src/WCTDataMiner.Wpf/Views/PlossChartView.xaml +++ b/src/WCTDataMiner.Wpf/Views/PlossChartView.xaml @@ -9,16 +9,21 @@ d:DesignHeight="400" d:DesignWidth="600"> + - + - +