#CNC检测模块概念设计

This commit is contained in:
zhengxuan.zhang
2026-04-21 12:56:22 +08:00
parent 238e97d110
commit b966e0b8e8
10 changed files with 134 additions and 301 deletions
@@ -261,6 +261,18 @@ namespace XplorePlane.ViewModels.Cnc
} }
} }
public PipelineModel Pipeline
{
get => _model is InspectionModuleNode im ? im.Pipeline : null;
set
{
if (_model is InspectionModuleNode im)
{
UpdateModel(im with { Pipeline = value ?? new PipelineModel() });
}
}
}
public string MarkerType public string MarkerType
{ {
get => _model is InspectionMarkerNode mk ? mk.MarkerType : string.Empty; get => _model is InspectionMarkerNode mk ? mk.MarkerType : string.Empty;
@@ -508,6 +520,7 @@ namespace XplorePlane.ViewModels.Cnc
RaisePropertyChanged(nameof(FrameRate)); RaisePropertyChanged(nameof(FrameRate));
RaisePropertyChanged(nameof(Resolution)); RaisePropertyChanged(nameof(Resolution));
RaisePropertyChanged(nameof(ImageFileName)); RaisePropertyChanged(nameof(ImageFileName));
RaisePropertyChanged(nameof(Pipeline));
RaisePropertyChanged(nameof(PipelineName)); RaisePropertyChanged(nameof(PipelineName));
RaisePropertyChanged(nameof(MarkerType)); RaisePropertyChanged(nameof(MarkerType));
RaisePropertyChanged(nameof(MarkerX)); RaisePropertyChanged(nameof(MarkerX));
@@ -8,6 +8,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using XP.Common.Logging.Interfaces; using XP.Common.Logging.Interfaces;
using XplorePlane.Events; using XplorePlane.Events;
@@ -16,7 +17,7 @@ using XplorePlane.Services;
namespace XplorePlane.ViewModels namespace XplorePlane.ViewModels
{ {
public class PipelineEditorViewModel : BindableBase public class PipelineEditorViewModel : BindableBase, IPipelineEditorHostViewModel
{ {
private const int MaxPipelineLength = 20; private const int MaxPipelineLength = 20;
private const int DebounceDelayMs = 300; private const int DebounceDelayMs = 300;
@@ -165,6 +166,15 @@ namespace XplorePlane.ViewModels
public DelegateCommand<PipelineNodeViewModel> MoveNodeUpCommand { get; } public DelegateCommand<PipelineNodeViewModel> MoveNodeUpCommand { get; }
public DelegateCommand<PipelineNodeViewModel> MoveNodeDownCommand { get; } public DelegateCommand<PipelineNodeViewModel> MoveNodeDownCommand { get; }
ICommand IPipelineEditorHostViewModel.AddOperatorCommand => AddOperatorCommand;
ICommand IPipelineEditorHostViewModel.RemoveOperatorCommand => RemoveOperatorCommand;
ICommand IPipelineEditorHostViewModel.MoveNodeUpCommand => MoveNodeUpCommand;
ICommand IPipelineEditorHostViewModel.MoveNodeDownCommand => MoveNodeDownCommand;
ICommand IPipelineEditorHostViewModel.NewPipelineCommand => NewPipelineCommand;
ICommand IPipelineEditorHostViewModel.SavePipelineCommand => SavePipelineCommand;
ICommand IPipelineEditorHostViewModel.SaveAsPipelineCommand => SaveAsPipelineCommand;
ICommand IPipelineEditorHostViewModel.LoadPipelineCommand => LoadPipelineCommand;
// ── Command Implementations ─────────────────────────────────── // ── Command Implementations ───────────────────────────────────
private bool CanAddOperator(string operatorKey) => private bool CanAddOperator(string operatorKey) =>
+16 -4
View File
@@ -21,6 +21,7 @@ namespace XplorePlane.ViewModels
{ {
public class MainViewModel : BindableBase public class MainViewModel : BindableBase
{ {
private const double CncEditorHostWidth = 1162d;
private readonly ILoggerService _logger; private readonly ILoggerService _logger;
private readonly IContainerProvider _containerProvider; private readonly IContainerProvider _containerProvider;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
@@ -92,6 +93,13 @@ namespace XplorePlane.ViewModels
set => SetProperty(ref _imagePanelWidth, value); set => SetProperty(ref _imagePanelWidth, value);
} }
/// <summary>主视图区宽度 | Main viewport width</summary>
public GridLength ViewportPanelWidth
{
get => _viewportPanelWidth;
set => SetProperty(ref _viewportPanelWidth, value);
}
// 窗口引用(单例窗口防止重复打开) // 窗口引用(单例窗口防止重复打开)
private Window _motionDebugWindow; private Window _motionDebugWindow;
private Window _detectorConfigWindow; private Window _detectorConfigWindow;
@@ -100,7 +108,8 @@ namespace XplorePlane.ViewModels
private Window _toolboxWindow; private Window _toolboxWindow;
private Window _raySourceConfigWindow; private Window _raySourceConfigWindow;
private object _imagePanelContent; private object _imagePanelContent;
private GridLength _imagePanelWidth = new GridLength(350); private GridLength _viewportPanelWidth = new GridLength(1, GridUnitType.Star);
private GridLength _imagePanelWidth = new GridLength(320);
private bool _isCncEditorMode; private bool _isCncEditorMode;
public MainViewModel(ILoggerService logger, IContainerProvider containerProvider, IEventAggregator eventAggregator) public MainViewModel(ILoggerService logger, IContainerProvider containerProvider, IEventAggregator eventAggregator)
@@ -156,7 +165,8 @@ namespace XplorePlane.ViewModels
OpenRealTimeLogViewerCommand = new DelegateCommand(ExecuteOpenRealTimeLogViewer); OpenRealTimeLogViewerCommand = new DelegateCommand(ExecuteOpenRealTimeLogViewer);
ImagePanelContent = new PipelineEditorView(); ImagePanelContent = new PipelineEditorView();
ImagePanelWidth = new GridLength(350); ViewportPanelWidth = new GridLength(1, GridUnitType.Star);
ImagePanelWidth = new GridLength(320);
_logger.Info("MainViewModel 已初始化"); _logger.Info("MainViewModel 已初始化");
} }
@@ -207,7 +217,8 @@ namespace XplorePlane.ViewModels
if (_isCncEditorMode) if (_isCncEditorMode)
{ {
ImagePanelContent = new PipelineEditorView(); ImagePanelContent = new PipelineEditorView();
ImagePanelWidth = new GridLength(350); ViewportPanelWidth = new GridLength(1, GridUnitType.Star);
ImagePanelWidth = new GridLength(320);
_isCncEditorMode = false; _isCncEditorMode = false;
_logger.Info("已退出 CNC 编辑模式"); _logger.Info("已退出 CNC 编辑模式");
return; return;
@@ -227,7 +238,8 @@ namespace XplorePlane.ViewModels
private void ShowCncEditor() private void ShowCncEditor()
{ {
ImagePanelContent = _cncPageView; ImagePanelContent = _cncPageView;
ImagePanelWidth = new GridLength(720); ViewportPanelWidth = new GridLength(1, GridUnitType.Star);
ImagePanelWidth = new GridLength(CncEditorHostWidth);
_isCncEditorMode = true; _isCncEditorMode = true;
_logger.Info("CNC 编辑器已切换到主界面图像区域"); _logger.Info("CNC 编辑器已切换到主界面图像区域");
} }
+2 -2
View File
@@ -4,9 +4,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cnc="clr-namespace:XplorePlane.Views.Cnc" xmlns:cnc="clr-namespace:XplorePlane.Views.Cnc"
Title="CNC 编辑器" Title="CNC 编辑器"
Width="1180" Width="1040"
Height="780" Height="780"
MinWidth="1040" MinWidth="960"
MinHeight="720" MinHeight="720"
ResizeMode="CanResize" ResizeMode="CanResize"
ShowInTaskbar="False" ShowInTaskbar="False"
+43 -273
View File
@@ -6,9 +6,10 @@
xmlns:local="clr-namespace:XplorePlane.Views.Cnc" xmlns:local="clr-namespace:XplorePlane.Views.Cnc"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/" xmlns:prism="http://prismlibrary.com/"
xmlns:views="clr-namespace:XplorePlane.Views"
xmlns:vm="clr-namespace:XplorePlane.ViewModels.Cnc" xmlns:vm="clr-namespace:XplorePlane.ViewModels.Cnc"
d:DesignHeight="760" d:DesignHeight="760"
d:DesignWidth="1180" d:DesignWidth="600"
prism:ViewModelLocator.AutoWireViewModel="True" prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"> mc:Ignorable="d">
@@ -20,36 +21,8 @@
<SolidColorBrush x:Key="PanelBorder" Color="#CDCBCB" /> <SolidColorBrush x:Key="PanelBorder" Color="#CDCBCB" />
<SolidColorBrush x:Key="SeparatorBrush" Color="#E5E5E5" /> <SolidColorBrush x:Key="SeparatorBrush" Color="#E5E5E5" />
<SolidColorBrush x:Key="HeaderBg" Color="#F7F7F7" /> <SolidColorBrush x:Key="HeaderBg" Color="#F7F7F7" />
<SolidColorBrush x:Key="SoftBlue" Color="#E8F0FE" />
<SolidColorBrush x:Key="SoftBlueBorder" Color="#5B9BD5" />
<FontFamily x:Key="UiFont">Microsoft YaHei UI</FontFamily> <FontFamily x:Key="UiFont">Microsoft YaHei UI</FontFamily>
<Style x:Key="ToolbarBtn" TargetType="Button">
<Setter Property="Height" Value="26" />
<Setter Property="MinWidth" Value="40" />
<Setter Property="Margin" Value="2,0" />
<Setter Property="Padding" Value="8,0" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="#CDCBCB" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="FontFamily" Value="{StaticResource UiFont}" />
<Setter Property="FontSize" Value="11" />
<Setter Property="Cursor" Value="Hand" />
</Style>
<Style x:Key="InsertBtn" TargetType="Button">
<Setter Property="Height" Value="28" />
<Setter Property="Margin" Value="0,0,0,6" />
<Setter Property="Padding" Value="8,0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="#D7D7D7" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="FontFamily" Value="{StaticResource UiFont}" />
<Setter Property="FontSize" Value="11" />
<Setter Property="Cursor" Value="Hand" />
</Style>
<Style x:Key="TreeItemStyle" TargetType="TreeViewItem"> <Style x:Key="TreeItemStyle" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="Padding" Value="0" /> <Setter Property="Padding" Value="0" />
@@ -96,18 +69,20 @@
</UserControl.Resources> </UserControl.Resources>
<Border <Border
MinWidth="980" Width="1162"
MinWidth="1162"
HorizontalAlignment="Left"
Background="{StaticResource PanelBg}" Background="{StaticResource PanelBg}"
BorderBrush="{StaticResource PanelBorder}" BorderBrush="{StaticResource PanelBorder}"
BorderThickness="1" BorderThickness="1"
CornerRadius="4"> CornerRadius="4">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="280" MinWidth="240" /> <ColumnDefinition Width="248" />
<ColumnDefinition Width="1" /> <ColumnDefinition Width="1" />
<ColumnDefinition Width="430" MinWidth="360" /> <ColumnDefinition Width="292" />
<ColumnDefinition Width="1" /> <ColumnDefinition Width="1" />
<ColumnDefinition Width="*" MinWidth="260" /> <ColumnDefinition Width="620" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid Grid.Column="0"> <Grid Grid.Column="0">
@@ -127,7 +102,7 @@
FontFamily="{StaticResource UiFont}" FontFamily="{StaticResource UiFont}"
FontSize="14" FontSize="14"
FontWeight="SemiBold" FontWeight="SemiBold"
Text="{Binding ProgramName, TargetNullValue=NewCncProgram}" /> Text="{Binding ProgramName, TargetNullValue=CNC编辑}" />
<TextBlock <TextBlock
Margin="0,3,0,0" Margin="0,3,0,0"
FontFamily="{StaticResource UiFont}" FontFamily="{StaticResource UiFont}"
@@ -203,7 +178,7 @@
BorderThickness="1" BorderThickness="1"
Command="{Binding DataContext.MoveNodeUpCommand, RelativeSource={RelativeSource AncestorType=TreeView}}" Command="{Binding DataContext.MoveNodeUpCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Content="" Content=""
Cursor="Hand" Cursor="Hand"
FontSize="10" FontSize="10"
ToolTip="上移" /> ToolTip="上移" />
@@ -216,7 +191,7 @@
BorderThickness="1" BorderThickness="1"
Command="{Binding DataContext.MoveNodeDownCommand, RelativeSource={RelativeSource AncestorType=TreeView}}" Command="{Binding DataContext.MoveNodeDownCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Content="" Content=""
Cursor="Hand" Cursor="Hand"
FontSize="10" FontSize="10"
ToolTip="下移" /> ToolTip="下移" />
@@ -228,7 +203,7 @@
BorderBrush="#E05050" BorderBrush="#E05050"
BorderThickness="1" BorderThickness="1"
Command="{Binding DataContext.DeleteNodeCommand, RelativeSource={RelativeSource AncestorType=TreeView}}" Command="{Binding DataContext.DeleteNodeCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
Content="×" Content=""
Cursor="Hand" Cursor="Hand"
FontSize="10" FontSize="10"
ToolTip="删除" /> ToolTip="删除" />
@@ -253,7 +228,7 @@
Fill="{StaticResource SeparatorBrush}" /> Fill="{StaticResource SeparatorBrush}" />
<ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto"> <ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto">
<Grid Margin="14,12,16,12"> <Grid Margin="10">
<StackPanel Visibility="{Binding SelectedNode, Converter={StaticResource NullToVisibilityConverter}}"> <StackPanel Visibility="{Binding SelectedNode, Converter={StaticResource NullToVisibilityConverter}}">
<TextBlock Style="{StaticResource EditorTitle}" Text="节点属性" /> <TextBlock Style="{StaticResource EditorTitle}" Text="节点属性" />
@@ -261,7 +236,7 @@
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Name, UpdateSourceTrigger=PropertyChanged}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Name, UpdateSourceTrigger=PropertyChanged}" />
<UniformGrid Columns="2" Margin="0,0,0,8"> <UniformGrid Columns="2" Margin="0,0,0,8">
<StackPanel Margin="0,0,8,0"> <StackPanel Margin="0,0,6,0">
<TextBlock Style="{StaticResource LabelStyle}" Text="索引" /> <TextBlock Style="{StaticResource LabelStyle}" Text="索引" />
<TextBox Style="{StaticResource EditorBox}" IsReadOnly="True" Text="{Binding SelectedNode.Index, Mode=OneWay}" /> <TextBox Style="{StaticResource EditorBox}" IsReadOnly="True" Text="{Binding SelectedNode.Index, Mode=OneWay}" />
</StackPanel> </StackPanel>
@@ -275,8 +250,8 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="运动参数" Header="运动参数"
Visibility="{Binding SelectedNode.IsMotionSnapshotNode, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsMotionSnapshotNode, Converter={StaticResource BoolToVisibilityConverter}}">
<UniformGrid Margin="10,8,10,6" Columns="2"> <UniformGrid Margin="8,8,8,6" Columns="2">
<StackPanel Margin="0,0,8,0"> <StackPanel Margin="0,0,6,0">
<TextBlock Style="{StaticResource LabelStyle}" Text="XM" /> <TextBlock Style="{StaticResource LabelStyle}" Text="XM" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.XM, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.XM, UpdateSourceTrigger=LostFocus}" />
</StackPanel> </StackPanel>
@@ -284,7 +259,7 @@
<TextBlock Style="{StaticResource LabelStyle}" Text="YM" /> <TextBlock Style="{StaticResource LabelStyle}" Text="YM" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.YM, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.YM, UpdateSourceTrigger=LostFocus}" />
</StackPanel> </StackPanel>
<StackPanel Margin="0,0,8,0"> <StackPanel Margin="0,0,6,0">
<TextBlock Style="{StaticResource LabelStyle}" Text="ZT" /> <TextBlock Style="{StaticResource LabelStyle}" Text="ZT" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.ZT, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.ZT, UpdateSourceTrigger=LostFocus}" />
</StackPanel> </StackPanel>
@@ -292,7 +267,7 @@
<TextBlock Style="{StaticResource LabelStyle}" Text="ZD" /> <TextBlock Style="{StaticResource LabelStyle}" Text="ZD" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.ZD, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.ZD, UpdateSourceTrigger=LostFocus}" />
</StackPanel> </StackPanel>
<StackPanel Margin="0,0,8,0"> <StackPanel Margin="0,0,6,0">
<TextBlock Style="{StaticResource LabelStyle}" Text="TiltD" /> <TextBlock Style="{StaticResource LabelStyle}" Text="TiltD" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.TiltD, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.TiltD, UpdateSourceTrigger=LostFocus}" />
</StackPanel> </StackPanel>
@@ -307,7 +282,7 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="射线源" Header="射线源"
Visibility="{Binding SelectedNode.IsReferencePoint, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsReferencePoint, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Margin="10,8,10,6"> <StackPanel Margin="8,8,8,6">
<CheckBox Style="{StaticResource EditorCheck}" Content="射线源开启" IsChecked="{Binding SelectedNode.IsRayOn}" /> <CheckBox Style="{StaticResource EditorCheck}" Content="射线源开启" IsChecked="{Binding SelectedNode.IsRayOn}" />
<TextBlock Style="{StaticResource LabelStyle}" Text="电压 (kV)" /> <TextBlock Style="{StaticResource LabelStyle}" Text="电压 (kV)" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Voltage, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Voltage, UpdateSourceTrigger=LostFocus}" />
@@ -320,7 +295,7 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="采集参数" Header="采集参数"
Visibility="{Binding SelectedNode.IsSaveNode, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsSaveNode, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Margin="10,8,10,6"> <StackPanel Margin="8,8,8,6">
<CheckBox Style="{StaticResource EditorCheck}" Content="射线源开启" IsChecked="{Binding SelectedNode.IsRayOn}" /> <CheckBox Style="{StaticResource EditorCheck}" Content="射线源开启" IsChecked="{Binding SelectedNode.IsRayOn}" />
<TextBlock Style="{StaticResource LabelStyle}" Text="电压 (kV)" /> <TextBlock Style="{StaticResource LabelStyle}" Text="电压 (kV)" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Voltage, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Voltage, UpdateSourceTrigger=LostFocus}" />
@@ -339,7 +314,7 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="采集参数" Header="采集参数"
Visibility="{Binding SelectedNode.IsSaveNodeWithImage, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsSaveNodeWithImage, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Margin="10,8,10,6"> <StackPanel Margin="8,8,8,6">
<CheckBox Style="{StaticResource EditorCheck}" Content="射线源开启" IsChecked="{Binding SelectedNode.IsRayOn}" /> <CheckBox Style="{StaticResource EditorCheck}" Content="射线源开启" IsChecked="{Binding SelectedNode.IsRayOn}" />
<TextBlock Style="{StaticResource LabelStyle}" Text="电压 (kV)" /> <TextBlock Style="{StaticResource LabelStyle}" Text="电压 (kV)" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Voltage, UpdateSourceTrigger=LostFocus}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Voltage, UpdateSourceTrigger=LostFocus}" />
@@ -360,7 +335,7 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="检测模块" Header="检测模块"
Visibility="{Binding SelectedNode.IsInspectionModule, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsInspectionModule, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Margin="10,8,10,6"> <StackPanel Margin="8,8,8,6">
<TextBlock Style="{StaticResource LabelStyle}" Text="Pipeline 名称" /> <TextBlock Style="{StaticResource LabelStyle}" Text="Pipeline 名称" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.PipelineName, UpdateSourceTrigger=PropertyChanged}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.PipelineName, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel> </StackPanel>
@@ -370,7 +345,7 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="标记参数" Header="标记参数"
Visibility="{Binding SelectedNode.IsInspectionMarker, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsInspectionMarker, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Margin="10,8,10,6"> <StackPanel Margin="8,8,8,6">
<TextBlock Style="{StaticResource LabelStyle}" Text="标记类型" /> <TextBlock Style="{StaticResource LabelStyle}" Text="标记类型" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.MarkerType, UpdateSourceTrigger=PropertyChanged}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.MarkerType, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Style="{StaticResource LabelStyle}" Text="MarkerX" /> <TextBlock Style="{StaticResource LabelStyle}" Text="MarkerX" />
@@ -384,7 +359,7 @@
Style="{StaticResource CompactGroupBox}" Style="{StaticResource CompactGroupBox}"
Header="消息弹窗" Header="消息弹窗"
Visibility="{Binding SelectedNode.IsPauseDialog, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding SelectedNode.IsPauseDialog, Converter={StaticResource BoolToVisibilityConverter}}">
<StackPanel Margin="10,8,10,6"> <StackPanel Margin="8,8,8,6">
<TextBlock Style="{StaticResource LabelStyle}" Text="标题" /> <TextBlock Style="{StaticResource LabelStyle}" Text="标题" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.DialogTitle, UpdateSourceTrigger=PropertyChanged}" /> <TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.DialogTitle, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Style="{StaticResource LabelStyle}" Text="消息内容" /> <TextBlock Style="{StaticResource LabelStyle}" Text="消息内容" />
@@ -414,7 +389,7 @@
</StackPanel> </StackPanel>
<Border <Border
Padding="18" Padding="12"
Background="#FAFAFA" Background="#FAFAFA"
BorderBrush="#E6E6E6" BorderBrush="#E6E6E6"
BorderThickness="1" BorderThickness="1"
@@ -443,237 +418,32 @@
Fill="{StaticResource SeparatorBrush}" /> Fill="{StaticResource SeparatorBrush}" />
<Grid Grid.Column="4"> <Grid Grid.Column="4">
<Grid.RowDefinitions> <views:PipelineEditorView
<RowDefinition Height="Auto" /> x:Name="InspectionModulePipelineEditor"
<RowDefinition Height="Auto" /> Visibility="{Binding EditorVisibility}" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border <Border
Grid.Row="0" x:Name="InspectionModulePipelineEmptyState"
Padding="8,6" Margin="12"
Background="{StaticResource HeaderBg}" Padding="16"
BorderBrush="{StaticResource SeparatorBrush}" Background="#FAFAFA"
BorderThickness="0,0,0,1"> BorderBrush="#E6E6E6"
<TextBlock BorderThickness="1"
FontFamily="{StaticResource UiFont}" CornerRadius="6"
FontSize="12" Visibility="{Binding EmptyStateVisibility}">
FontWeight="SemiBold" <StackPanel>
Text="图像" />
</Border>
<Border
Grid.Row="1"
Padding="6,4"
BorderBrush="{StaticResource SeparatorBrush}"
BorderThickness="0,0,0,1">
<WrapPanel>
<Button Command="{Binding NewProgramCommand}" Content="新建" Style="{StaticResource ToolbarBtn}" />
<Button Command="{Binding SaveProgramCommand}" Content="保存" Style="{StaticResource ToolbarBtn}" />
<Button Command="{Binding ExportCsvCommand}" Content="另存为" Style="{StaticResource ToolbarBtn}" />
<Button Command="{Binding LoadProgramCommand}" Content="加载" Style="{StaticResource ToolbarBtn}" />
</WrapPanel>
</Border>
<Border
Grid.Row="2"
Margin="8,8,8,6"
Padding="10"
Background="#FBFBFB"
BorderBrush="#DDDDDD"
BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock <TextBlock
FontFamily="{StaticResource UiFont}" FontFamily="{StaticResource UiFont}"
FontSize="11" FontSize="14"
FontWeight="SemiBold" FontWeight="SemiBold"
Foreground="#D90000" Text="未选择检测模块" />
Text="{Binding ProgramName, StringFormat='配方名:{0}.xpm'}" />
<Border
Grid.Row="1"
Margin="0,8,0,10"
Height="140"
Background="Black">
<Grid>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{StaticResource UiFont}"
FontSize="11"
Foreground="White"
Opacity="0.72"
Text="图像预览区域" />
</Grid>
</Border>
<StackPanel Grid.Row="2">
<Button Command="{Binding InsertReferencePointCommand}" Style="{StaticResource InsertBtn}">
<StackPanel Orientation="Horizontal">
<Border
Width="20"
Height="20"
Margin="0,0,8,0"
Background="{StaticResource SoftBlue}"
BorderBrush="{StaticResource SoftBlueBorder}"
BorderThickness="1"
CornerRadius="4">
<Image Width="13" Height="13" Source="/Assets/Icons/reference.png" Stretch="Uniform" />
</Border>
<TextBlock VerticalAlignment="Center" Text="参考点" />
</StackPanel>
</Button>
<Button Command="{Binding InsertInspectionModuleCommand}" Style="{StaticResource InsertBtn}">
<StackPanel Orientation="Horizontal">
<Border
Width="20"
Height="20"
Margin="0,0,8,0"
Background="{StaticResource SoftBlue}"
BorderBrush="{StaticResource SoftBlueBorder}"
BorderThickness="1"
CornerRadius="4">
<Image Width="13" Height="13" Source="/Assets/Icons/Module.png" Stretch="Uniform" />
</Border>
<TextBlock VerticalAlignment="Center" Text="检测模块" />
</StackPanel>
</Button>
<Button Command="{Binding InsertInspectionMarkerCommand}" Style="{StaticResource InsertBtn}">
<StackPanel Orientation="Horizontal">
<Border
Width="20"
Height="20"
Margin="0,0,8,0"
Background="{StaticResource SoftBlue}"
BorderBrush="{StaticResource SoftBlueBorder}"
BorderThickness="1"
CornerRadius="4">
<Image Width="13" Height="13" Source="/Assets/Icons/mark.png" Stretch="Uniform" />
</Border>
<TextBlock VerticalAlignment="Center" Text="标记节点" />
</StackPanel>
</Button>
<Button Command="{Binding InsertSaveNodeCommand}" Style="{StaticResource InsertBtn}" Content="插入保存节点" />
<Button Command="{Binding InsertSaveNodeWithImageCommand}" Style="{StaticResource InsertBtn}" Content="插入带图像保存节点" />
<Button Command="{Binding InsertSavePositionCommand}" Style="{StaticResource InsertBtn}" Content="插入保存位置" />
<Button Command="{Binding InsertPauseDialogCommand}" Style="{StaticResource InsertBtn}" Content="插入消息节点" />
<Button Command="{Binding InsertWaitDelayCommand}" Style="{StaticResource InsertBtn}" Content="插入等待节点" />
<Button Command="{Binding InsertCompleteProgramCommand}" Style="{StaticResource InsertBtn}" Content="插入结束节点" />
</StackPanel>
</Grid>
</Border>
<Border
Grid.Row="3"
Padding="8,6"
Background="{StaticResource HeaderBg}"
BorderBrush="{StaticResource SeparatorBrush}"
BorderThickness="0,1,0,1">
<TextBlock
FontFamily="{StaticResource UiFont}"
FontSize="12"
FontWeight="SemiBold"
Text="参数配置" />
</Border>
<StackPanel Grid.Row="4" Margin="8,8,8,0">
<TextBlock Style="{StaticResource LabelStyle}" Text="节点名称" />
<TextBox Style="{StaticResource EditorBox}" Text="{Binding SelectedNode.Name, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<StackPanel Grid.Row="5" Margin="8,4,8,8">
<Grid Margin="0,0,0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="84" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Column="0" Margin="0,6,0,0"
VerticalAlignment="Center"
FontFamily="{StaticResource UiFont}" FontFamily="{StaticResource UiFont}"
FontSize="11" FontSize="11"
Text="节点类型" /> Foreground="#666666"
<TextBox Text="请选择一个检测模块节点后,在这里拖拽算子并配置参数。" />
Grid.Column="1" </StackPanel>
Height="26"
Padding="6,3"
BorderBrush="#CFCFCF"
BorderThickness="1"
FontFamily="{StaticResource UiFont}"
FontSize="11"
IsReadOnly="True"
Text="{Binding SelectedNode.NodeTypeDisplay}" />
</Grid>
<Grid Margin="0,0,0,6" Visibility="{Binding SelectedNode.IsMotionSnapshotNode, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="84" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
VerticalAlignment="Center"
FontFamily="{StaticResource UiFont}"
FontSize="11"
Text="Dist" />
<TextBox
Grid.Column="1"
Height="26"
Padding="6,3"
BorderBrush="#CFCFCF"
BorderThickness="1"
FontFamily="{StaticResource UiFont}"
FontSize="11"
Text="{Binding SelectedNode.Dist, UpdateSourceTrigger=LostFocus}" />
</Grid>
<Grid Margin="0,0,0,6" Visibility="{Binding SelectedNode.IsReferencePoint, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="84" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
VerticalAlignment="Center"
FontFamily="{StaticResource UiFont}"
FontSize="11"
Text="标准差" />
<TextBox
Grid.Column="1"
Height="26"
Padding="6,3"
BorderBrush="#CFCFCF"
BorderThickness="1"
FontFamily="{StaticResource UiFont}"
FontSize="11"
Text="{Binding SelectedNode.Current, UpdateSourceTrigger=LostFocus}" />
</Grid>
</StackPanel>
<Border
Grid.Row="6"
Padding="8,4"
Background="{StaticResource HeaderBg}"
BorderBrush="{StaticResource SeparatorBrush}"
BorderThickness="0,1,0,0">
<TextBlock
FontFamily="{StaticResource UiFont}"
FontSize="10.5"
Foreground="#555555"
Text="Status: 编辑界面已更新为紧凑布局" />
</Border> </Border>
</Grid> </Grid>
</Grid> </Grid>
+31 -2
View File
@@ -4,6 +4,8 @@ using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using XP.Common.Logging.Interfaces;
using XplorePlane.Services;
using XplorePlane.ViewModels.Cnc; using XplorePlane.ViewModels.Cnc;
namespace XplorePlane.Views.Cnc namespace XplorePlane.Views.Cnc
@@ -13,6 +15,8 @@ namespace XplorePlane.Views.Cnc
/// </summary> /// </summary>
public partial class CncPageView : UserControl public partial class CncPageView : UserControl
{ {
private CncInspectionModulePipelineViewModel _inspectionModulePipelineViewModel;
public CncPageView() public CncPageView()
{ {
InitializeComponent(); InitializeComponent();
@@ -21,17 +25,42 @@ namespace XplorePlane.Views.Cnc
private void OnLoaded(object sender, RoutedEventArgs e) private void OnLoaded(object sender, RoutedEventArgs e)
{ {
if (DataContext is not CncEditorViewModel) CncEditorViewModel editorViewModel = DataContext as CncEditorViewModel;
if (editorViewModel == null)
{ {
try try
{ {
DataContext = ContainerLocator.Current?.Resolve<CncEditorViewModel>(); editorViewModel = ContainerLocator.Current?.Resolve<CncEditorViewModel>();
DataContext = editorViewModel;
} }
catch (Exception) catch (Exception)
{ {
// keep existing DataContext if resolution fails // keep existing DataContext if resolution fails
} }
} }
if (editorViewModel == null || _inspectionModulePipelineViewModel != null)
return;
try
{
var imageProcessingService = ContainerLocator.Current.Resolve<IImageProcessingService>();
var persistenceService = ContainerLocator.Current.Resolve<IPipelinePersistenceService>();
var logger = ContainerLocator.Current.Resolve<ILoggerService>();
_inspectionModulePipelineViewModel = new CncInspectionModulePipelineViewModel(
editorViewModel,
imageProcessingService,
persistenceService,
logger);
InspectionModulePipelineEditor.DataContext = _inspectionModulePipelineViewModel;
InspectionModulePipelineEmptyState.DataContext = _inspectionModulePipelineViewModel;
}
catch (Exception)
{
// keep page usable even if pipeline editor host setup fails
}
} }
private void CncTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) private void CncTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
@@ -1,5 +1,5 @@
using System;
using Prism.Ioc; using Prism.Ioc;
using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using XP.Common.Logging.Interfaces; using XP.Common.Logging.Interfaces;
@@ -23,7 +23,7 @@ namespace XplorePlane.Views
private void OnLoaded(object sender, RoutedEventArgs e) private void OnLoaded(object sender, RoutedEventArgs e)
{ {
if (DataContext is not PipelineEditorViewModel) if (DataContext is not IPipelineEditorHostViewModel)
{ {
try try
{ {
@@ -46,36 +46,35 @@ namespace XplorePlane.Views
private void OnDragOver(object sender, DragEventArgs e) private void OnDragOver(object sender, DragEventArgs e)
{ {
if (e.Data.GetDataPresent(OperatorToolboxView.DragFormat)) e.Effects = e.Data.GetDataPresent(OperatorToolboxView.DragFormat)
e.Effects = DragDropEffects.Copy; ? DragDropEffects.Copy
else : DragDropEffects.None;
e.Effects = DragDropEffects.None;
e.Handled = true; e.Handled = true;
} }
private void OnOperatorDropped(object sender, DragEventArgs e) private void OnOperatorDropped(object sender, DragEventArgs e)
{ {
if (DataContext is not PipelineEditorViewModel vm) if (DataContext is not IPipelineEditorHostViewModel vm)
{ {
_logger?.Warn("Drop 事件触发但 DataContext 不是 PipelineEditorViewModel"); _logger?.Warn("Drop 事件触发但 DataContext 不是流水线宿主 ViewModel");
return; return;
} }
if (!e.Data.GetDataPresent(OperatorToolboxView.DragFormat)) if (!e.Data.GetDataPresent(OperatorToolboxView.DragFormat))
{ {
_logger?.Warn("Drop 事件触发但数据中没有 {Format}", OperatorToolboxView.DragFormat); _logger?.Warn("Drop 事件触发但数据中没有 {Format}", OperatorToolboxView.DragFormat);
return; return;
} }
var operatorKey = e.Data.GetData(OperatorToolboxView.DragFormat) as string; var operatorKey = e.Data.GetData(OperatorToolboxView.DragFormat) as string;
if (string.IsNullOrEmpty(operatorKey)) if (string.IsNullOrWhiteSpace(operatorKey))
{ {
_logger?.Warn("Drop 事件触发但 OperatorKey 为空"); _logger?.Warn("Drop 事件触发但 OperatorKey 为空");
return; return;
} }
_logger?.Info("算子已放入流水线:{OperatorKey}VM HashCode={Hash}当前节点数(执行前)={Count}", _logger?.Info("算子已放入流水线:{OperatorKey},当前节点数(执行前)={Count}",
operatorKey, vm.GetHashCode(), vm.PipelineNodes.Count); operatorKey, vm.PipelineNodes.Count);
vm.AddOperatorCommand.Execute(operatorKey); vm.AddOperatorCommand.Execute(operatorKey);
_logger?.Info("AddOperator 执行后节点数={Count}PipelineListBox.Items.Count={ItemsCount}", _logger?.Info("AddOperator 执行后节点数={Count}PipelineListBox.Items.Count={ItemsCount}",
vm.PipelineNodes.Count, PipelineListBox.Items.Count); vm.PipelineNodes.Count, PipelineListBox.Items.Count);
+1 -1
View File
@@ -13,7 +13,7 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1"> <Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1">
<TextBlock Margin="8,4" HorizontalAlignment="Left" VerticalAlignment="Center" <TextBlock Margin="4,2" HorizontalAlignment="Left" VerticalAlignment="Center"
FontWeight="SemiBold" Foreground="#333333" Text="图像" /> FontWeight="SemiBold" Foreground="#333333" Text="图像" />
</Border> </Border>
<ContentControl Grid.Row="1" Content="{Binding ImagePanelContent}" /> <ContentControl Grid.Row="1" Content="{Binding ImagePanelContent}" />
+3 -3
View File
@@ -400,7 +400,7 @@
Size="Large" Size="Large"
SmallImage="/Assets/Icons/spiral.png" /> SmallImage="/Assets/Icons/spiral.png" />
</telerik:RadRibbonGroup> </telerik:RadRibbonGroup>
<!-- <!--
<telerik:RadRibbonGroup Header="图像处理"> <telerik:RadRibbonGroup Header="图像处理">
<telerik:RadRibbonGroup.Variants> <telerik:RadRibbonGroup.Variants>
<telerik:GroupVariant Priority="0" Variant="Large" /> <telerik:GroupVariant Priority="0" Variant="Large" />
@@ -470,9 +470,9 @@
Margin="0"> Margin="0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition x:Name="NavColumn" Width="0" /> <ColumnDefinition x:Name="NavColumn" Width="0" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="{Binding ViewportPanelWidth}" />
<ColumnDefinition Width="{Binding ImagePanelWidth}" /> <ColumnDefinition Width="{Binding ImagePanelWidth}" />
<ColumnDefinition Width="350" /> <ColumnDefinition Width="300" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- 左侧: 计划导航 (默认隐藏,点击CNC AccountingNumberFormatButton显示) --> <!-- 左侧: 计划导航 (默认隐藏,点击CNC AccountingNumberFormatButton显示) -->
@@ -19,7 +19,7 @@
<!-- 标题栏 --> <!-- 标题栏 -->
<Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1"> <Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1">
<TextBlock Margin="8,4" HorizontalAlignment="Left" VerticalAlignment="Center" <TextBlock Margin="4,2" HorizontalAlignment="Left" VerticalAlignment="Center"
FontWeight="SemiBold" Foreground="#333333" Text="实时图像" /> FontWeight="SemiBold" Foreground="#333333" Text="实时图像" />
</Border> </Border>
@@ -30,7 +30,7 @@
<!-- 图像信息栏 --> <!-- 图像信息栏 -->
<Border Grid.Row="2" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,1,0,0"> <Border Grid.Row="2" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,1,0,0">
<TextBlock Margin="8,2" FontSize="11" Foreground="#666666" <TextBlock Margin="4,2" FontSize="11" Foreground="#666666"
Text="{Binding ImageInfo}" /> Text="{Binding ImageInfo}" />
</Border> </Border>
</Grid> </Grid>