#0025 新增加载按钮;修复线居中

This commit is contained in:
zhengxuan.zhang
2026-03-15 10:46:13 +08:00
parent 1cc4b5e4d0
commit 880cdfc937
4 changed files with 111 additions and 37 deletions
@@ -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
@@ -18,10 +18,13 @@ namespace XplorePlane.Views
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (DataContext == null)
DataContext = ContainerLocator.Container.Resolve<ImageProcessingViewModel>();
var container = ContainerLocator.Current;
if (container == null) return;
_imageProcessingService = ContainerLocator.Container.Resolve<IImageProcessingService>();
if (DataContext == null)
DataContext = container.Resolve<ImageProcessingViewModel>();
_imageProcessingService = container.Resolve<IImageProcessingService>();
}
private void OnProcessorComboChanged(object sender, SelectionChangedEventArgs e)
@@ -1,11 +1,14 @@
<Window x:Class="XplorePlane.Views.ImageProcessingWindow"
<Window
x:Class="XplorePlane.Views.ImageProcessingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:XplorePlane.Views"
Title="图像处理"
Width="1200" Height="750"
MinWidth="900" MinHeight="550"
WindowStartupLocation="CenterOwner"
ShowInTaskbar="False">
Width="1200"
Height="750"
MinWidth="900"
MinHeight="550"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner">
<views:ImageProcessingPanelView />
</Window>
@@ -123,6 +123,11 @@
Content="另存为"
Style="{StaticResource ToolbarBtn}"
ToolTip="另存为" Width="43" />
<Button
Command="{Binding LoadPipelineCommand}"
Content="加载"
Style="{StaticResource ToolbarBtn}"
ToolTip="加载流水线" Width="43" />
<Button
Command="{Binding ExecutePipelineCommand}"
Content="▶"
@@ -156,38 +161,47 @@
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid MinHeight="44">
<Grid MinHeight="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="28" />
<ColumnDefinition Width="44" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- 竖线连接 + 节点方块 -->
<Grid Grid.Column="0">
<!-- 连接线列:上半段 + 下半段 -->
<Line x:Name="TopLine"
Stroke="#5B9BD5" StrokeThickness="2"
X1="0" X2="0" Y1="0" Y2="10"
VerticalAlignment="Top"
HorizontalAlignment="Center" />
<Line Stroke="#5B9BD5" StrokeThickness="2"
X1="14" X2="14" Y1="0" Y2="44"
HorizontalAlignment="Left" />
<Border Width="16" Height="16"
Background="White"
BorderBrush="#5B9BD5" BorderThickness="1.5"
CornerRadius="2"
VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
X1="0" X2="0" Y1="0" Y2="14"
VerticalAlignment="Bottom"
HorizontalAlignment="Center" />
<!-- 节点行 -->
<Border Grid.Column="1" Padding="6,8">
<StackPanel Orientation="Horizontal">
<Border Width="28" Height="28" Margin="0,0,8,0"
Background="#E8F0FE" CornerRadius="3">
<!-- 算子图标 -->
<Border Grid.Column="0"
Width="28" Height="28"
Background="#E8F0FE"
BorderBrush="#5B9BD5" BorderThickness="1.5"
CornerRadius="4"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="13" Text="⚙" />
</Border>
<TextBlock VerticalAlignment="Center"
<!-- 算子名称 -->
<TextBlock Grid.Column="1"
VerticalAlignment="Center"
Margin="6,0,0,0"
FontFamily="Microsoft YaHei UI" FontSize="12"
Text="{Binding DisplayName}" />
</StackPanel>
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Order}" Value="0">
<Setter TargetName="TopLine" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>