diff --git a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs index 370c9f6..e75220d 100644 --- a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs @@ -55,6 +55,7 @@ namespace XplorePlane.ViewModels SavePipelineCommand = new DelegateCommand(async () => await SavePipelineAsync()); SaveAsPipelineCommand = new DelegateCommand(async () => await SaveAsPipelineAsync()); DeletePipelineCommand = new DelegateCommand(async () => await DeletePipelineAsync()); + LoadPipelineCommand = new DelegateCommand(async () => await LoadPipelineAsync()); } // ── State Properties ────────────────────────────────────────── @@ -133,6 +134,7 @@ namespace XplorePlane.ViewModels public DelegateCommand SavePipelineCommand { get; } public DelegateCommand SaveAsPipelineCommand { get; } public DelegateCommand DeletePipelineCommand { get; } + public DelegateCommand LoadPipelineCommand { get; } // ── Command Implementations ─────────────────────────────────── @@ -383,6 +385,58 @@ namespace XplorePlane.ViewModels await Task.CompletedTask; } + private async Task LoadPipelineAsync() + { + var dialog = new OpenFileDialog + { + Filter = "流水线文件 (*.pipeline.json)|*.pipeline.json", + InitialDirectory = GetPipelineDirectory() + }; + + if (dialog.ShowDialog() != true) return; + + try + { + var model = await _persistenceService.LoadAsync(dialog.FileName); + + PipelineNodes.Clear(); + SelectedNode = null; + + PipelineName = model.Name; + SelectedDevice = model.DeviceId; + _currentFilePath = dialog.FileName; + + foreach (var nodeModel in model.Nodes) + { + var displayName = _imageProcessingService.GetProcessorDisplayName(nodeModel.OperatorKey) + ?? nodeModel.OperatorKey; + var node = new PipelineNodeViewModel(nodeModel.OperatorKey, displayName) + { + Order = nodeModel.Order, + IsEnabled = nodeModel.IsEnabled + }; + LoadNodeParameters(node); + + // 恢复已保存的参数值 + foreach (var param in node.Parameters) + { + if (nodeModel.Parameters.TryGetValue(param.Name, out var savedValue)) + param.Value = savedValue; + } + + PipelineNodes.Add(node); + } + + Serilog.Log.Information("流水线已加载:{Name},节点数={Count}", model.Name, PipelineNodes.Count); + StatusMessage = $"已加载流水线:{model.Name}({PipelineNodes.Count} 个节点)"; + } + catch (Exception ex) + { + Serilog.Log.Warning("加载流水线失败:{Error}", ex.Message); + StatusMessage = $"加载失败:{ex.Message}"; + } + } + private PipelineModel BuildPipelineModel() { return new PipelineModel diff --git a/XplorePlane/Views/ImageProcessing/ImageProcessingPanelView.xaml.cs b/XplorePlane/Views/ImageProcessing/ImageProcessingPanelView.xaml.cs index b2942eb..f454a61 100644 --- a/XplorePlane/Views/ImageProcessing/ImageProcessingPanelView.xaml.cs +++ b/XplorePlane/Views/ImageProcessing/ImageProcessingPanelView.xaml.cs @@ -18,10 +18,13 @@ namespace XplorePlane.Views private void OnLoaded(object sender, RoutedEventArgs e) { - if (DataContext == null) - DataContext = ContainerLocator.Container.Resolve(); + var container = ContainerLocator.Current; + if (container == null) return; - _imageProcessingService = ContainerLocator.Container.Resolve(); + if (DataContext == null) + DataContext = container.Resolve(); + + _imageProcessingService = container.Resolve(); } private void OnProcessorComboChanged(object sender, SelectionChangedEventArgs e) diff --git a/XplorePlane/Views/ImageProcessing/ImageProcessingWindow.xaml b/XplorePlane/Views/ImageProcessing/ImageProcessingWindow.xaml index 5281dc0..cec64ed 100644 --- a/XplorePlane/Views/ImageProcessing/ImageProcessingWindow.xaml +++ b/XplorePlane/Views/ImageProcessing/ImageProcessingWindow.xaml @@ -1,11 +1,14 @@ - + diff --git a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml index 17dfad5..6ff726d 100644 --- a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml +++ b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml @@ -123,6 +123,11 @@ Content="另存为" Style="{StaticResource ToolbarBtn}" ToolTip="另存为" Width="43" /> +