From 24e0489cdee1b47aad70c2427b10a72aea4447ff Mon Sep 17 00:00:00 2001 From: "zhengxuan.zhang" Date: Thu, 23 Apr 2026 17:29:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=98=BE=E7=A4=BAxmp=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=EF=BC=9B=E5=8F=96=E6=B6=88=E5=AE=9E=E6=97=B6=E5=9B=BE?= =?UTF-8?q?=E5=83=8F=E5=BA=95=E9=83=A8=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CncInspectionModulePipelineViewModel.cs | 31 +++++++++++++++++++ .../IPipelineEditorHostViewModel.cs | 4 +++ .../PipelineEditorViewModel.cs | 18 +++++++++++ .../ImageProcessing/PipelineEditorView.xaml | 28 +++++++++++++++-- .../Main/NavigationPropertyPanelView.xaml | 11 ++++--- XplorePlane/Views/Main/ViewportPanelView.xaml | 6 +--- 6 files changed, 86 insertions(+), 12 deletions(-) diff --git a/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs b/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs index 879bbb4..d119c0c 100644 --- a/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs +++ b/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs @@ -26,6 +26,7 @@ namespace XplorePlane.ViewModels.Cnc private CncNodeViewModel _activeModuleNode; private PipelineNodeViewModel _selectedNode; private string _statusMessage = "请选择检测模块以编辑其流水线。"; + private string _pipelineFileDisplayName = "未命名模块.xpm"; private string _currentFilePath; private bool _isSynchronizing; @@ -71,6 +72,14 @@ namespace XplorePlane.ViewModels.Cnc private set => SetProperty(ref _statusMessage, value); } + public bool IsStatusError => false; + + public string PipelineFileDisplayName + { + get => _pipelineFileDisplayName; + private set => SetProperty(ref _pipelineFileDisplayName, value); + } + public bool HasActiveModule => _activeModuleNode?.IsInspectionModule == true; public Visibility EditorVisibility => HasActiveModule ? Visibility.Visible : Visibility.Collapsed; @@ -113,6 +122,7 @@ namespace XplorePlane.ViewModels.Cnc _activeModuleNode = null; PipelineNodes.Clear(); SelectedNode = null; + PipelineFileDisplayName = "未命名模块.xpm"; StatusMessage = "请选择检测模块以编辑其流水线。"; RaiseModuleVisibilityChanged(); RaiseCommandCanExecuteChanged(); @@ -120,6 +130,7 @@ namespace XplorePlane.ViewModels.Cnc } _activeModuleNode = selected; + _currentFilePath = null; LoadPipelineModel(_activeModuleNode.Pipeline ?? new PipelineModel { Name = _activeModuleNode.Name @@ -234,6 +245,7 @@ namespace XplorePlane.ViewModels.Cnc PipelineNodes.Clear(); SelectedNode = null; _currentFilePath = null; + PipelineFileDisplayName = GetActivePipelineFileDisplayName(); PersistActiveModule("已为当前检测模块新建空流水线。"); } @@ -264,6 +276,7 @@ namespace XplorePlane.ViewModels.Cnc var model = BuildPipelineModel(); await _persistenceService.SaveAsync(model, dialog.FileName); _currentFilePath = dialog.FileName; + PipelineFileDisplayName = FormatPipelinePath(dialog.FileName); StatusMessage = $"已导出模块流水线:{Path.GetFileName(dialog.FileName)}"; } @@ -283,6 +296,7 @@ namespace XplorePlane.ViewModels.Cnc var model = await _persistenceService.LoadAsync(dialog.FileName); _currentFilePath = dialog.FileName; + PipelineFileDisplayName = FormatPipelinePath(dialog.FileName); LoadPipelineModel(model); PersistActiveModule($"已加载模块流水线:{model.Name}"); } @@ -314,6 +328,8 @@ namespace XplorePlane.ViewModels.Cnc } SelectedNode = PipelineNodes.FirstOrDefault(); + if (string.IsNullOrEmpty(_currentFilePath)) + PipelineFileDisplayName = GetActivePipelineFileDisplayName(); StatusMessage = HasActiveModule ? $"正在编辑检测模块:{_activeModuleNode.Name}" : "请选择检测模块以编辑其流水线。"; @@ -389,6 +405,21 @@ namespace XplorePlane.ViewModels.Cnc : _activeModuleNode.Pipeline.Name; } + private string GetActivePipelineFileDisplayName() + { + var pipelineName = GetActivePipelineName(); + return pipelineName.EndsWith(".xpm", StringComparison.OrdinalIgnoreCase) + ? pipelineName + : $"{pipelineName}.xpm"; + } + + private static string FormatPipelinePath(string filePath) + { + return string.IsNullOrWhiteSpace(filePath) + ? "未命名模块.xpm" + : Path.GetFullPath(filePath).Replace('\\', '/'); + } + private void RenumberNodes() { for (var i = 0; i < PipelineNodes.Count; i++) diff --git a/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs index 8460667..9883ca8 100644 --- a/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs @@ -11,6 +11,10 @@ namespace XplorePlane.ViewModels string StatusMessage { get; } + bool IsStatusError { get; } + + string PipelineFileDisplayName { get; } + ICommand AddOperatorCommand { get; } ICommand RemoveOperatorCommand { get; } diff --git a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs index e2aeb21..517e231 100644 --- a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs @@ -21,6 +21,7 @@ namespace XplorePlane.ViewModels { private const int MaxPipelineLength = 20; private const int DebounceDelayMs = 300; + private const string DefaultPipelineFileDisplayName = "未命名模块.xpm"; private readonly IImageProcessingService _imageProcessingService; private readonly IPipelineExecutionService _executionService; @@ -36,6 +37,7 @@ namespace XplorePlane.ViewModels private bool _isExecuting; private bool _isStatusError; private string _statusMessage = string.Empty; + private string _pipelineFileDisplayName = DefaultPipelineFileDisplayName; private string _currentFilePath; private CancellationTokenSource _executionCts; @@ -155,6 +157,12 @@ namespace XplorePlane.ViewModels private set => SetProperty(ref _isStatusError, value); } + public string PipelineFileDisplayName + { + get => _pipelineFileDisplayName; + private set => SetProperty(ref _pipelineFileDisplayName, value); + } + // ── Commands ────────────────────────────────────────────────── public DelegateCommand AddOperatorCommand { get; } @@ -526,6 +534,7 @@ namespace XplorePlane.ViewModels PipelineName = "新建流水线"; PreviewImage = null; _currentFilePath = null; + PipelineFileDisplayName = DefaultPipelineFileDisplayName; StatusMessage = "已新建流水线"; } @@ -576,6 +585,7 @@ namespace XplorePlane.ViewModels { var model = BuildPipelineModel(); await _persistenceService.SaveAsync(model, filePath); + PipelineFileDisplayName = FormatPipelinePath(filePath); StatusMessage = $"流水线已保存:{Path.GetFileName(filePath)}"; } catch (IOException ex) @@ -624,6 +634,7 @@ namespace XplorePlane.ViewModels PipelineName = model.Name; SelectedDevice = model.DeviceId; _currentFilePath = dialog.FileName; + PipelineFileDisplayName = FormatPipelinePath(dialog.FileName); foreach (var nodeModel in model.Nodes) { @@ -702,5 +713,12 @@ namespace XplorePlane.ViewModels Directory.CreateDirectory(dir); return dir; } + + private static string FormatPipelinePath(string filePath) + { + return string.IsNullOrWhiteSpace(filePath) + ? DefaultPipelineFileDisplayName + : Path.GetFullPath(filePath).Replace('\\', '/'); + } } } diff --git a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml index c54f6ad..151340d 100644 --- a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml +++ b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml @@ -68,7 +68,14 @@ Background="#F5F5F5" BorderBrush="{StaticResource PanelBorder}" BorderThickness="0,1,0,1"> - + + + + + +