CNC运行与底部状态栏提醒

This commit is contained in:
zhengxuan.zhang
2026-04-28 10:28:41 +08:00
parent 2a64d48b54
commit 06714f819f
3 changed files with 84 additions and 4 deletions
@@ -42,6 +42,9 @@ namespace XplorePlane.ViewModels.Cnc
private bool _pendingInsertAfterAnchor; private bool _pendingInsertAfterAnchor;
private CancellationTokenSource _cts; private CancellationTokenSource _cts;
private bool _isRunning; private bool _isRunning;
private string _statusMessage = "就绪";
private string _executionError;
private bool _hasExecutionError;
public CncEditorViewModel( public CncEditorViewModel(
ICncProgramService cncProgramService, ICncProgramService cncProgramService,
@@ -159,6 +162,24 @@ namespace XplorePlane.ViewModels.Cnc
} }
} }
public string StatusMessage
{
get => _statusMessage;
private set => SetProperty(ref _statusMessage, value);
}
public string ExecutionError
{
get => _executionError;
private set => SetProperty(ref _executionError, value);
}
public bool HasExecutionError
{
get => _hasExecutionError;
private set => SetProperty(ref _hasExecutionError, value);
}
public DelegateCommand InsertReferencePointCommand { get; } public DelegateCommand InsertReferencePointCommand { get; }
public DelegateCommand InsertSaveNodeWithImageCommand { get; } public DelegateCommand InsertSaveNodeWithImageCommand { get; }
public DelegateCommand InsertSaveNodeCommand { get; } public DelegateCommand InsertSaveNodeCommand { get; }
@@ -435,14 +456,28 @@ namespace XplorePlane.ViewModels.Cnc
{ {
_cts = new CancellationTokenSource(); _cts = new CancellationTokenSource();
IsRunning = true; IsRunning = true;
HasExecutionError = false;
ExecutionError = null;
StatusMessage = $"正在执行:{_currentProgram?.Name ?? ""}(共 {_currentProgram?.Nodes?.Count ?? 0} 个节点)";
try try
{ {
var progress = new Progress<CncNodeExecutionProgress>(OnExecutionProgress); var progress = new Progress<CncNodeExecutionProgress>(OnExecutionProgress);
await _cncExecutionService.ExecuteAsync(_currentProgram, progress, _cts.Token); await _cncExecutionService.ExecuteAsync(_currentProgram, progress, _cts.Token);
if (_cts.IsCancellationRequested)
StatusMessage = "执行已停止";
else
StatusMessage = $"执行完成:{_currentProgram?.Name}";
}
catch (OperationCanceledException)
{
StatusMessage = "执行已取消";
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(ex, "CNC execution failed"); _logger.Error(ex, "CNC execution failed");
ExecutionError = ex.Message;
HasExecutionError = true;
StatusMessage = $"执行失败:{ex.Message}";
} }
finally finally
{ {
@@ -462,7 +497,17 @@ namespace XplorePlane.ViewModels.Cnc
{ {
var nodeVm = Nodes.FirstOrDefault(n => n.Id == progress.NodeId); var nodeVm = Nodes.FirstOrDefault(n => n.Id == progress.NodeId);
if (nodeVm != null) if (nodeVm != null)
{
nodeVm.ExecutionState = progress.State; nodeVm.ExecutionState = progress.State;
if (progress.State == NodeExecutionState.Running)
StatusMessage = $"正在执行节点:{nodeVm.Name}{nodeVm.Index + 1}/{_currentProgram?.Nodes?.Count ?? 0}";
else if (progress.State == NodeExecutionState.Failed)
{
HasExecutionError = true;
ExecutionError = $"节点 [{nodeVm.Name}] 执行失败";
StatusMessage = $"错误:节点 [{nodeVm.Name}] 执行失败";
}
}
} }
private void ResetAllNodeStates() private void ResetAllNodeStates()
+23 -2
View File
@@ -57,6 +57,20 @@ namespace XplorePlane.ViewModels
_cncPageView = new CncPageView { DataContext = _cncEditorViewModel }; _cncPageView = new CncPageView { DataContext = _cncEditorViewModel };
_mainViewportService.StateChanged += OnMainViewportStateChanged; _mainViewportService.StateChanged += OnMainViewportStateChanged;
_cncEditorViewModel.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(CncEditorViewModel.StatusMessage))
RaisePropertyChanged(nameof(CncStatusMessage));
else if (e.PropertyName == nameof(CncEditorViewModel.HasExecutionError))
RaisePropertyChanged(nameof(CncHasExecutionError));
else if (e.PropertyName == nameof(CncEditorViewModel.IsRunning))
{
RunCncCommand.RaiseCanExecuteChanged();
StopCncCommand.RaiseCanExecuteChanged();
}
};
_cncEditorViewModel.RunCncCommand.CanExecuteChanged += (s, e) => RunCncCommand.RaiseCanExecuteChanged();
_cncEditorViewModel.StopCncCommand.CanExecuteChanged += (s, e) => StopCncCommand.RaiseCanExecuteChanged();
NavigationTree = new ObservableCollection<object>(); NavigationTree = new ObservableCollection<object>();
@@ -87,8 +101,12 @@ namespace XplorePlane.ViewModels
InsertSaveNodeCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertSaveNodeCommand.Execute())); InsertSaveNodeCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertSaveNodeCommand.Execute()));
InsertPauseDialogCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertPauseDialogCommand.Execute())); InsertPauseDialogCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertPauseDialogCommand.Execute()));
InsertWaitDelayCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertWaitDelayCommand.Execute())); InsertWaitDelayCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertWaitDelayCommand.Execute()));
RunCncCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.RunCncCommand.Execute())); RunCncCommand = new DelegateCommand(
StopCncCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.StopCncCommand.Execute())); () => ExecuteCncEditorAction(vm => vm.RunCncCommand.Execute()),
() => _cncEditorViewModel.RunCncCommand.CanExecute());
StopCncCommand = new DelegateCommand(
() => ExecuteCncEditorAction(vm => vm.StopCncCommand.Execute()),
() => _cncEditorViewModel.StopCncCommand.CanExecute());
PointDistanceMeasureCommand = new DelegateCommand(ExecutePointDistanceMeasure); PointDistanceMeasureCommand = new DelegateCommand(ExecutePointDistanceMeasure);
PointLineDistanceMeasureCommand = new DelegateCommand(ExecutePointLineDistanceMeasure); PointLineDistanceMeasureCommand = new DelegateCommand(ExecutePointLineDistanceMeasure);
@@ -121,6 +139,9 @@ namespace XplorePlane.ViewModels
set => SetProperty(ref _licenseInfo, value); set => SetProperty(ref _licenseInfo, value);
} }
public string CncStatusMessage => _cncEditorViewModel.StatusMessage;
public bool CncHasExecutionError => _cncEditorViewModel.HasExecutionError;
public ObservableCollection<object> NavigationTree { get; set; } public ObservableCollection<object> NavigationTree { get; set; }
public DelegateCommand NavigateHomeCommand { get; set; } public DelegateCommand NavigateHomeCommand { get; set; }
+16 -2
View File
@@ -106,6 +106,7 @@
<StackPanel> <StackPanel>
<telerik:RadRibbonButton <telerik:RadRibbonButton
telerik:ScreenTip.Title="运行" telerik:ScreenTip.Title="运行"
Command="{Binding RunCncCommand}"
Size="Large" Size="Large"
SmallImage="/Assets/Icons/run.png" SmallImage="/Assets/Icons/run.png"
Text="运行" /> Text="运行" />
@@ -114,6 +115,7 @@
<telerik:RadRibbonButton <telerik:RadRibbonButton
telerik:ScreenTip.Description="停止" telerik:ScreenTip.Description="停止"
telerik:ScreenTip.Title="停止" telerik:ScreenTip.Title="停止"
Command="{Binding StopCncCommand}"
Size="Large" Size="Large"
SmallImage="/Assets/Icons/stop.png" SmallImage="/Assets/Icons/stop.png"
Text="停止" /> Text="停止" />
@@ -554,7 +556,19 @@
FontFamily="Microsoft YaHei UI" FontFamily="Microsoft YaHei UI"
FontSize="11" FontSize="11"
Foreground="White" Foreground="White"
Text="就绪" /> Text="{Binding CncStatusMessage}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding CncHasExecutionError}" Value="True">
<Setter Property="Foreground" Value="#FF9090" />
<Setter Property="FontWeight" Value="SemiBold" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock <TextBlock
Grid.Column="1" Grid.Column="1"
@@ -563,7 +577,7 @@
FontFamily="Consolas" FontFamily="Consolas"
FontSize="11" FontSize="11"
Foreground="White" Foreground="White"
Text="x: 0 y: 0 RGB: 0 0 0" /> Text="x: 0 y: 0" />
</Grid> </Grid>
</Border> </Border>
</Grid> </Grid>