diff --git a/XplorePlane.Tests/GlobalUsings.Services.cs b/XplorePlane.Tests/GlobalUsings.Services.cs index 3874a256..8e2bc139 100644 --- a/XplorePlane.Tests/GlobalUsings.Services.cs +++ b/XplorePlane.Tests/GlobalUsings.Services.cs @@ -1,3 +1,2 @@ -global using XplorePlane.Services.ImageProcessing; -global using XplorePlane.Services.Logging; -global using XplorePlane.Services.Pipeline; +global using XplorePlane.Services.ImageProcessing; +global using XplorePlane.Services.Pipeline; diff --git a/XplorePlane.Tests/Inspection/RealInspectionAcquisitionServiceTests.cs b/XplorePlane.Tests/Inspection/RealInspectionAcquisitionServiceTests.cs index 08ca1331..688ae374 100644 --- a/XplorePlane.Tests/Inspection/RealInspectionAcquisitionServiceTests.cs +++ b/XplorePlane.Tests/Inspection/RealInspectionAcquisitionServiceTests.cs @@ -32,7 +32,7 @@ namespace XplorePlane.Tests.Inspection Assert.Equal("Detector", result.Source); Assert.Equal(2, result.Image.PixelWidth); - harness.Motion.Verify(x => x.MoveAllToTarget(It.IsAny>()), Times.Once); + harness.Motion.Verify(x => x.MoveAllToTarget(It.IsAny>(), false), Times.Once); harness.Detector.Verify(x => x.ApplyParametersAsync(0, 1, 10m, 2, It.IsAny()), Times.Once); harness.Detector.Verify(x => x.AcquireSingleFrameAsync(It.IsAny()), Times.Once); harness.Ray.Verify(x => x.SetVoltage(120), Times.Once); @@ -70,7 +70,7 @@ namespace XplorePlane.Tests.Inspection harness.Service.AcquireAsync(Machine(), Acquisition(), CancellationToken.None)); Assert.Contains("安全门", error.Message); - harness.Motion.Verify(x => x.MoveAllToTarget(It.IsAny>()), Times.Never); + harness.Motion.Verify(x => x.MoveAllToTarget(It.IsAny>(), false), Times.Never); harness.Ray.Verify(x => x.TurnOn(), Times.Never); harness.Motion.Verify(x => x.StopAll(), Times.Once); } @@ -84,7 +84,7 @@ namespace XplorePlane.Tests.Inspection harness.Service.AcquireAsync(Machine(), Acquisition(), CancellationToken.None)); Assert.Contains("探测器未连接", error.Message); - harness.Motion.Verify(x => x.MoveAllToTarget(It.IsAny>()), Times.Never); + harness.Motion.Verify(x => x.MoveAllToTarget(It.IsAny>(), false), Times.Never); harness.Ray.Verify(x => x.TurnOn(), Times.Never); } @@ -113,7 +113,7 @@ namespace XplorePlane.Tests.Inspection bool detectorConnected = true) { var motion = new Mock(); - motion.Setup(x => x.MoveAllToTarget(It.IsAny>())) + motion.Setup(x => x.MoveAllToTarget(It.IsAny>(), false)) .Returns(MotionResult.Ok()); motion.Setup(x => x.MoveRotaryToTarget(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(MotionResult.Ok()); diff --git a/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs b/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs index 3bd7affd..246064b1 100644 --- a/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs +++ b/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs @@ -7,7 +7,7 @@ using XP.Common.Logging.Interfaces; using XplorePlane.Models; using XplorePlane.Services; using XplorePlane.Services.Storage; -using XplorePlane.Services.Dialogs; +using XplorePlane.Views.Dialogs; using XplorePlane.Tests.Helpers; using XplorePlane.ViewModels; using Xunit; diff --git a/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs b/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs index 264689bc..cd7be7dd 100644 --- a/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs +++ b/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs @@ -14,7 +14,7 @@ using XplorePlane.Models; using XplorePlane.Services; using XplorePlane.Services.Security; using XplorePlane.Services.Storage; -using XplorePlane.Services.Dialogs; +using XplorePlane.Views.Dialogs; using XplorePlane.Tests.Helpers; using XplorePlane.ViewModels; diff --git a/XplorePlane.Tests/Services/DependencyVersionProviderTests.cs b/XplorePlane.Tests/Services/DependencyVersionProviderTests.cs index 365eaf31..94f7969e 100644 --- a/XplorePlane.Tests/Services/DependencyVersionProviderTests.cs +++ b/XplorePlane.Tests/Services/DependencyVersionProviderTests.cs @@ -1,5 +1,5 @@ using System.Linq; -using XplorePlane.Services.Diagnostics; +using XplorePlane.Services.Helpers; using Xunit; namespace XplorePlane.Tests.Services diff --git a/XplorePlane.Tests/Services/Reporting/CncReportPipelineIntegrationTests.cs b/XplorePlane.Tests/Services/Reporting/CncReportPipelineIntegrationTests.cs index 41438157..838c048e 100644 --- a/XplorePlane.Tests/Services/Reporting/CncReportPipelineIntegrationTests.cs +++ b/XplorePlane.Tests/Services/Reporting/CncReportPipelineIntegrationTests.cs @@ -168,7 +168,7 @@ namespace XplorePlane.Tests.Services.Reporting new JsonTemplateEngine(Logger().Object), new ExpressionDataBinder(Logger().Object, loc.Object), new PageLayoutEngine(Logger().Object, new JsonTemplateEngine(Logger().Object)), - new ITextPdfRenderer(Logger().Object, loc.Object)); + new ITextPdfRenderer(Logger().Object, loc.Object, new XP.ReportEngine.Configs.ReportConfig())); var outputPath = Path.Combine(Path.GetTempPath(), $"cnc_report_test_{Guid.NewGuid():N}.pdf"); diff --git a/XplorePlane.Tests/ViewModels/CncEditorViewModelTests.cs b/XplorePlane.Tests/ViewModels/CncEditorViewModelTests.cs index f7132ded..8d3d3380 100644 --- a/XplorePlane.Tests/ViewModels/CncEditorViewModelTests.cs +++ b/XplorePlane.Tests/ViewModels/CncEditorViewModelTests.cs @@ -16,7 +16,7 @@ using XP.Common.Logging.Interfaces; using XplorePlane.Models; using XplorePlane.Services.AppState; using XplorePlane.Services.Cnc; -using XplorePlane.Services.Dialogs; +using XplorePlane.Views.Dialogs; using XplorePlane.Services.Storage; using XplorePlane.Services; using XplorePlane.Services.Security; diff --git a/XplorePlane.Tests/ViewModels/MatrixEditorViewModelTests.cs b/XplorePlane.Tests/ViewModels/MatrixEditorViewModelTests.cs index 725cd5de..d72645dc 100644 --- a/XplorePlane.Tests/ViewModels/MatrixEditorViewModelTests.cs +++ b/XplorePlane.Tests/ViewModels/MatrixEditorViewModelTests.cs @@ -10,7 +10,7 @@ using Xunit; using XplorePlane.Models; using XplorePlane.Services.Cnc; using XplorePlane.Services.Cnc.Matrix; -using XplorePlane.Services.Dialogs; +using XplorePlane.Views.Dialogs; using XplorePlane.ViewModels.Cnc; namespace XplorePlane.Tests.ViewModels diff --git a/XplorePlane/Services/Hardware/Camera/CameraService.cs b/XplorePlane/Services/Hardware/Camera/CameraService.cs index fb44293e..a1e8dfb3 100644 --- a/XplorePlane/Services/Hardware/Camera/CameraService.cs +++ b/XplorePlane/Services/Hardware/Camera/CameraService.cs @@ -224,7 +224,7 @@ namespace XplorePlane.Services.Hardware.Camera app?.Dispatcher.BeginInvoke(() => FrameArrived?.Invoke(this, bitmap)); // 链式触发下一帧 - TriggerNextLiveViewFrameAsync(); + _ = TriggerNextLiveViewFrameAsync(); } catch (Exception ex) { @@ -237,7 +237,7 @@ namespace XplorePlane.Services.Hardware.Camera _logger.Warn($"相机采集错误: ErrorCode={e.ErrorCode}, {e.ErrorDescription}"); } - private async void TriggerNextLiveViewFrameAsync() + private async Task TriggerNextLiveViewFrameAsync() { if (!_liveViewRunning || _disposed) return; @@ -284,4 +284,4 @@ namespace XplorePlane.Services.Hardware.Camera _logger.Info("CameraService 已释放"); } } -} \ No newline at end of file +} diff --git a/XplorePlane/Services/Inspection/Definition/InspectionDefinitionSnapshot.cs b/XplorePlane/Services/Inspection/Definition/InspectionDefinitionSnapshot.cs new file mode 100644 index 00000000..f54f46e9 --- /dev/null +++ b/XplorePlane/Services/Inspection/Definition/InspectionDefinitionSnapshot.cs @@ -0,0 +1,20 @@ +using System; +using System.Text.Json; +using XplorePlane.Models.Inspection; + +namespace XplorePlane.Services.Inspection +{ + /// + /// 检测定义快照工具。用于在执行前冻结包含可变 PipelineModel 的定义,避免后续编辑影响运行快照。 + /// + public static class InspectionDefinitionSnapshot + { + public static InspectionDefinition Clone(InspectionDefinition source) + { + ArgumentNullException.ThrowIfNull(source); + var json = JsonSerializer.Serialize(source); + return JsonSerializer.Deserialize(json) + ?? throw new InvalidOperationException("无法创建检测定义快照。"); + } + } +} diff --git a/XplorePlane/Services/Reporting/CncReportContextBuilder.cs b/XplorePlane/Services/Reporting/CncReportContextBuilder.cs index c83efc3a..366f54a1 100644 --- a/XplorePlane/Services/Reporting/CncReportContextBuilder.cs +++ b/XplorePlane/Services/Reporting/CncReportContextBuilder.cs @@ -32,9 +32,10 @@ namespace XplorePlane.Services.Reporting /// /// CNC 报告上下文构建器实现 | CNC report context builder implementation /// - public sealed class CncReportContextBuilder : ICncReportContextBuilder - { - private const string PassText = "PASS"; + public sealed class CncReportContextBuilder : ICncReportContextBuilder + { + public const string CncTemplateRelativePath = @"Templates\CncInspectionReportTemplate.json"; + private const string PassText = "PASS"; private const string FailText = "FAIL"; private const string EmptyText = "-"; @@ -595,4 +596,4 @@ namespace XplorePlane.Services.Reporting #endregion 私有辅助 | Private helpers } -} \ No newline at end of file +} diff --git a/XplorePlane/ViewModels/Cnc/Editor/CncEditorViewModel.cs b/XplorePlane/ViewModels/Cnc/Editor/CncEditorViewModel.cs index 69511969..43c12ec4 100644 --- a/XplorePlane/ViewModels/Cnc/Editor/CncEditorViewModel.cs +++ b/XplorePlane/ViewModels/Cnc/Editor/CncEditorViewModel.cs @@ -201,6 +201,9 @@ namespace XplorePlane.ViewModels.Cnc } private async void OnManualImageLoaded(ManualImageLoadedPayload payload) + => await OnManualImageLoadedAsync(payload); + + private async Task OnManualImageLoadedAsync(ManualImageLoadedPayload payload) { if (payload?.Image == null || _currentProgram == null || IsRunning) return; diff --git a/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs index 04c51be6..37d05d79 100644 --- a/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs @@ -4,6 +4,7 @@ using Prism.Commands; using Prism.Mvvm; using System; +using System.Threading.Tasks; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -51,7 +52,7 @@ namespace XplorePlane.ViewModels.ImageProcessing AvailableProcessors.Add(new ProcessorItem(key, _imageProcessingService.GetProcessorDisplayName(key))); SelectProcessorCommand = new DelegateCommand(OnSelectProcessor); - ApplyProcessingCommand = new DelegateCommand(OnApplyProcessing); + ApplyProcessingCommand = new DelegateCommand(async () => await OnApplyProcessingAsync()); ResetImageCommand = new DelegateCommand(OnResetImage); LoadImageCommand = new DelegateCommand(OnLoadImage); SaveResultCommand = new DelegateCommand(OnSaveResult, () => CurrentImage != null); @@ -131,7 +132,7 @@ namespace XplorePlane.ViewModels.ImageProcessing } } - private async void OnApplyProcessing() + private async Task OnApplyProcessingAsync() { if (CurrentImage == null || string.IsNullOrEmpty(SelectedProcessor)) return; @@ -240,4 +241,4 @@ namespace XplorePlane.ViewModels.ImageProcessing } } } -} \ No newline at end of file +} diff --git a/XplorePlane/ViewModels/ImageProcessing/TemplateMatchBatchViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/TemplateMatchBatchViewModel.cs index fcd2ad37..1cf21b81 100644 --- a/XplorePlane/ViewModels/ImageProcessing/TemplateMatchBatchViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/TemplateMatchBatchViewModel.cs @@ -74,7 +74,7 @@ public class TemplateMatchBatchViewModel : BindableBase, IDisposable _assistant.PropertyChanged += OnAssistantPropertyChanged; PickFolderCommand = new DelegateCommand(ExecutePickFolder); - StartBatchCommand = new DelegateCommand(ExecuteStartBatch, CanStartBatch); + StartBatchCommand = new DelegateCommand(async () => await ExecuteStartBatchAsync(), CanStartBatch); StopBatchCommand = new DelegateCommand(ExecuteStopBatch, () => _isRunning); OpenSelectedInMainViewportCommand = new DelegateCommand(ExecuteOpenSelectedInMainViewport, () => SelectedRow != null); } @@ -180,7 +180,7 @@ public class TemplateMatchBatchViewModel : BindableBase, IDisposable StartBatchCommand.RaiseCanExecuteChanged(); } - private async void ExecuteStartBatch() + private async Task ExecuteStartBatchAsync() { if (!CanStartBatch()) return; @@ -347,4 +347,4 @@ public class TemplateMatchBatchViewModel : BindableBase, IDisposable _batchCts?.Dispose(); _batchCts = null; } -} \ No newline at end of file +} diff --git a/XplorePlane/ViewModels/Main/MainViewModel.Cnc.cs b/XplorePlane/ViewModels/Main/MainViewModel.Cnc.cs index 4d6e09cc..105594a9 100644 --- a/XplorePlane/ViewModels/Main/MainViewModel.Cnc.cs +++ b/XplorePlane/ViewModels/Main/MainViewModel.Cnc.cs @@ -53,7 +53,7 @@ namespace XplorePlane.ViewModels.Main #region CNC 编辑动作分发(单例嵌入式面板) - private async void ExecuteCncEditorAction(Action action) + private void ExecuteCncEditorAction(Action action) { ArgumentNullException.ThrowIfNull(action); try @@ -116,6 +116,9 @@ namespace XplorePlane.ViewModels.Main /// 响应"把实时流水线作为检测模块加入 CNC"请求。 private async void OnAddPipelineToCncRequested(XplorePlane.Models.ImageProcessing.PipelineModel pipeline) + => await OnAddPipelineToCncRequestedAsync(pipeline); + + private async Task OnAddPipelineToCncRequestedAsync(XplorePlane.Models.ImageProcessing.PipelineModel pipeline) { try { @@ -181,4 +184,4 @@ namespace XplorePlane.ViewModels.Main #endregion 内置检测模块插入 } -} \ No newline at end of file +} diff --git a/XplorePlane/ViewModels/Main/MainViewModel.cs b/XplorePlane/ViewModels/Main/MainViewModel.cs index 41de4050..3aedcbe9 100644 --- a/XplorePlane/ViewModels/Main/MainViewModel.cs +++ b/XplorePlane/ViewModels/Main/MainViewModel.cs @@ -3,6 +3,7 @@ using Prism.Events; using Prism.Ioc; using Prism.Mvvm; using System; +using System.Threading.Tasks; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; @@ -733,7 +734,7 @@ namespace XplorePlane.ViewModels.Main OpenOverlaySettingsCommand = new DelegateCommand(ExecuteOpenOverlaySettings); OpenLibraryVersionsCommand = new DelegateCommand(() => _windowLauncher.Show(new Views.Help.LibraryVersionsWindow(), "关于")); OpenUserManualCommand = new DelegateCommand(ExecuteOpenUserManual); - CheckForUpdateCommand = new DelegateCommand(ExecuteCheckForUpdate); + CheckForUpdateCommand = new DelegateCommand(async () => await ExecuteCheckForUpdateAsync()); OpenCameraSettingsCommand = new DelegateCommand(ExecuteOpenCameraSettings); OpenCameraChessboardCalibrationCommand = new DelegateCommand(ExecuteOpenCameraChessboardCalibration); OpenCameraCalibrationCommand = new DelegateCommand(ExecuteOpenCameraCalibration); @@ -798,8 +799,8 @@ namespace XplorePlane.ViewModels.Main BlackBackgroundDetectionCommand = new DelegateCommand(ExecuteBlackBackgroundDetection); OpenTemplateMatchAssistantCommand = new DelegateCommand(ExecuteOpenTemplateMatchAssistant); GrayscaleCommand = new DelegateCommand(ExecuteGrayscale); - SharpenCommand = new DelegateCommand(ExecuteSharpen); - EnhanceCommand = new DelegateCommand(ExecuteEnhance); + SharpenCommand = new DelegateCommand(async () => await ExecuteSharpenAsync()); + EnhanceCommand = new DelegateCommand(async () => await ExecuteEnhanceAsync()); EdgeLineFitCommand = new DelegateCommand(ExecuteEdgeLineFit); EdgeCircleFitCommand = new DelegateCommand(ExecuteEdgeCircleFit); @@ -810,7 +811,7 @@ namespace XplorePlane.ViewModels.Main OpenMotionDebugCommand = new DelegateCommand(ExecuteOpenMotionDebug); RandomMoveAxesCommand = new DelegateCommand(ExecuteRandomMoveAxes); OpenCalibrationWizardCommand = new DelegateCommand(ExecuteOpenCalibrationWizard); - OneClickInitializeCommand = new DelegateCommand(ExecuteOneClickInitialize); + OneClickInitializeCommand = new DelegateCommand(async () => await ExecuteOneClickInitializeAsync()); OpenPlcAddrConfigCommand = new DelegateCommand(ExecuteOpenPlcAddrConfig); OpenRaySourceConfigCommand = new DelegateCommand(ExecuteOpenRaySourceConfig); OpenReportConfigCommand = new DelegateCommand(ExecuteOpenReportConfig); @@ -957,7 +958,7 @@ namespace XplorePlane.ViewModels.Main } } - private async void ExecuteCheckForUpdate() + private async Task ExecuteCheckForUpdateAsync() { try { @@ -1289,7 +1290,7 @@ namespace XplorePlane.ViewModels.Main throw new InvalidOperationException("导航相机有效视野与 StageX/StageY 轴行程没有可用交集。"); } - private async void ExecuteOneClickInitialize() + private async Task ExecuteOneClickInitializeAsync() { try { @@ -1468,7 +1469,7 @@ namespace XplorePlane.ViewModels.Main } } - private async void ExecuteSharpen() + private async Task ExecuteSharpenAsync() { if (!CheckImageLoaded()) return; @@ -1503,7 +1504,7 @@ namespace XplorePlane.ViewModels.Main } } - private async void ExecuteEnhance() + private async Task ExecuteEnhanceAsync() { if (!CheckImageLoaded()) return; diff --git a/XplorePlane/ViewModels/Main/NavigationPropertyPanelViewModel.cs b/XplorePlane/ViewModels/Main/NavigationPropertyPanelViewModel.cs index 6b7548c4..2a917226 100644 --- a/XplorePlane/ViewModels/Main/NavigationPropertyPanelViewModel.cs +++ b/XplorePlane/ViewModels/Main/NavigationPropertyPanelViewModel.cs @@ -479,7 +479,7 @@ namespace XplorePlane.ViewModels.Main /// /// 图像像素 X /// 图像像素 Y - public async void NavigateToPixel(double pixelX, double pixelY) + public async Task NavigateToPixel(double pixelX, double pixelY) { if (!IsCalibrated) { diff --git a/XplorePlane/Views/Main/NavigationPropertyPanelView.xaml.cs b/XplorePlane/Views/Main/NavigationPropertyPanelView.xaml.cs index e6cc6311..5ca134c2 100644 --- a/XplorePlane/Views/Main/NavigationPropertyPanelView.xaml.cs +++ b/XplorePlane/Views/Main/NavigationPropertyPanelView.xaml.cs @@ -387,7 +387,7 @@ namespace XplorePlane.Views.Main return; } - _viewModel.NavigateToPixel(px, py); + _ = _viewModel.NavigateToPixel(px, py); } #region PiP (Picture-in-Picture) - 青框画中画