diff --git a/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs b/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs index f6a7c59..8f6a00d 100644 --- a/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs +++ b/XplorePlane.Tests/Pipeline/PipelineEditorViewModelTests.cs @@ -1,5 +1,6 @@ using Moq; using Xunit; +using XP.Common.Logging.Interfaces; using XplorePlane.Models; using XplorePlane.Services; using XplorePlane.ViewModels; @@ -16,16 +17,19 @@ namespace XplorePlane.Tests.Pipeline private readonly Mock _mockImageSvc; private readonly Mock _mockExecSvc; private readonly Mock _mockPersistSvc; + private readonly Mock _mockLogger; public PipelineEditorViewModelTests() { _mockImageSvc = TestHelpers.CreateMockImageService(); _mockExecSvc = new Mock(); _mockPersistSvc = new Mock(); + _mockLogger = new Mock(); + _mockLogger.Setup(l => l.ForModule()).Returns(_mockLogger.Object); } private PipelineEditorViewModel CreateVm() => - new PipelineEditorViewModel(_mockImageSvc.Object, _mockExecSvc.Object, _mockPersistSvc.Object); + new PipelineEditorViewModel(_mockImageSvc.Object, _mockExecSvc.Object, _mockPersistSvc.Object, _mockLogger.Object); // ── 6.1 AddOperatorCommand ──────────────────────────────────── diff --git a/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs b/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs index ce4fad8..a6e02a9 100644 --- a/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs +++ b/XplorePlane.Tests/Pipeline/PipelinePropertyTests.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using XP.Common.Logging.Interfaces; using XplorePlane.Models; using XplorePlane.Services; using XplorePlane.ViewModels; @@ -29,7 +30,9 @@ namespace XplorePlane.Tests.Pipeline var mockImageSvc = TestHelpers.CreateMockImageService(); var mockExecSvc = new Mock(); var mockPersistSvc = new Mock(); - return new PipelineEditorViewModel(mockImageSvc.Object, mockExecSvc.Object, mockPersistSvc.Object); + var mockLogger = new Mock(); + mockLogger.Setup(l => l.ForModule()).Returns(mockLogger.Object); + return new PipelineEditorViewModel(mockImageSvc.Object, mockExecSvc.Object, mockPersistSvc.Object, mockLogger.Object); } /// diff --git a/XplorePlane.Tests/Services/AppStateServiceTests.cs b/XplorePlane.Tests/Services/AppStateServiceTests.cs index 143f0ab..b094dcc 100644 --- a/XplorePlane.Tests/Services/AppStateServiceTests.cs +++ b/XplorePlane.Tests/Services/AppStateServiceTests.cs @@ -1,7 +1,7 @@ using System; using System.Windows; using Moq; -using Serilog; +using XP.Common.Logging.Interfaces; using Xunit; using Xunit.Abstractions; using XP.Hardware.RaySource.Services; @@ -18,7 +18,7 @@ namespace XplorePlane.Tests.Services { private readonly AppStateService _service; private readonly Mock _mockRaySource; - private readonly Mock _mockLogger; + private readonly Mock _mockLogger; private readonly ITestOutputHelper _output; public AppStateServiceTests(ITestOutputHelper output) @@ -32,7 +32,8 @@ namespace XplorePlane.Tests.Services } _mockRaySource = new Mock(); - _mockLogger = new Mock(); + _mockLogger = new Mock(); + _mockLogger.Setup(l => l.ForModule()).Returns(_mockLogger.Object); _service = new AppStateService(_mockRaySource.Object, _mockLogger.Object); } diff --git a/XplorePlane.Tests/Services/RecipeServiceTests.cs b/XplorePlane.Tests/Services/RecipeServiceTests.cs index 7bde834..3a2ff6b 100644 --- a/XplorePlane.Tests/Services/RecipeServiceTests.cs +++ b/XplorePlane.Tests/Services/RecipeServiceTests.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Threading.Tasks; using Moq; -using Serilog; +using XP.Common.Logging.Interfaces; using Xunit; using Xunit.Abstractions; using XplorePlane.Models; @@ -20,7 +20,7 @@ namespace XplorePlane.Tests.Services { private readonly Mock _mockAppState; private readonly Mock _mockPipeline; - private readonly Mock _mockLogger; + private readonly Mock _mockLogger; private readonly RecipeService _service; private readonly ITestOutputHelper _output; @@ -29,7 +29,8 @@ namespace XplorePlane.Tests.Services _output = output; _mockAppState = new Mock(); _mockPipeline = new Mock(); - _mockLogger = new Mock(); + _mockLogger = new Mock(); + _mockLogger.Setup(l => l.ForModule()).Returns(_mockLogger.Object); // Setup default state returns _mockAppState.Setup(s => s.MotionState).Returns(MotionState.Default); diff --git a/XplorePlane.Tests/XplorePlane.Tests.csproj b/XplorePlane.Tests/XplorePlane.Tests.csproj index e600e9e..2c1ebf0 100644 --- a/XplorePlane.Tests/XplorePlane.Tests.csproj +++ b/XplorePlane.Tests/XplorePlane.Tests.csproj @@ -37,6 +37,10 @@ ..\XplorePlane\Libs\Hardware\XP.Hardware.RaySource.dll True + + ..\XplorePlane\Libs\Hardware\XP.Common.dll + True + ..\XplorePlane\Libs\ImageProcessing\ImageProcessing.Core.dll True diff --git a/XplorePlane/Libs/Hardware/XP.Common.dll b/XplorePlane/Libs/Hardware/XP.Common.dll index 0ef066c..d5b7a01 100644 Binary files a/XplorePlane/Libs/Hardware/XP.Common.dll and b/XplorePlane/Libs/Hardware/XP.Common.dll differ diff --git a/XplorePlane/Libs/Hardware/en-US/XP.Common.resources.dll b/XplorePlane/Libs/Hardware/en-US/XP.Common.resources.dll index 479b022..e294ebe 100644 Binary files a/XplorePlane/Libs/Hardware/en-US/XP.Common.resources.dll and b/XplorePlane/Libs/Hardware/en-US/XP.Common.resources.dll differ diff --git a/XplorePlane/Libs/Hardware/zh-CN/XP.Common.resources.dll b/XplorePlane/Libs/Hardware/zh-CN/XP.Common.resources.dll index ba2cede..22c555e 100644 Binary files a/XplorePlane/Libs/Hardware/zh-CN/XP.Common.resources.dll and b/XplorePlane/Libs/Hardware/zh-CN/XP.Common.resources.dll differ diff --git a/XplorePlane/Libs/Hardware/zh-TW/XP.Common.resources.dll b/XplorePlane/Libs/Hardware/zh-TW/XP.Common.resources.dll index 1b716cd..a2be167 100644 Binary files a/XplorePlane/Libs/Hardware/zh-TW/XP.Common.resources.dll and b/XplorePlane/Libs/Hardware/zh-TW/XP.Common.resources.dll differ diff --git a/XplorePlane/Services/AppState/AppStateService.cs b/XplorePlane/Services/AppState/AppStateService.cs index 74d127d..78822f7 100644 --- a/XplorePlane/Services/AppState/AppStateService.cs +++ b/XplorePlane/Services/AppState/AppStateService.cs @@ -3,7 +3,7 @@ using System.Threading; using System.Windows; using System.Windows.Threading; using Prism.Mvvm; -using Serilog; +using XP.Common.Logging.Interfaces; using XP.Hardware.RaySource.Services; using XplorePlane.Models; @@ -18,7 +18,7 @@ namespace XplorePlane.Services.AppState { private readonly Dispatcher _dispatcher; private readonly IRaySourceService _raySourceService; - private readonly ILogger _logger; + private readonly ILoggerService _logger; private bool _disposed; // ── 状态字段(通过 Interlocked.Exchange 原子替换)── @@ -53,17 +53,17 @@ namespace XplorePlane.Services.AppState public AppStateService( IRaySourceService raySourceService, - ILogger logger) + ILoggerService logger) { ArgumentNullException.ThrowIfNull(raySourceService); ArgumentNullException.ThrowIfNull(logger); _raySourceService = raySourceService; - _logger = logger; + _logger = logger.ForModule(); _dispatcher = Application.Current.Dispatcher; SubscribeToExistingServices(); - _logger.Information("AppStateService 已初始化"); + _logger.Info("AppStateService 已初始化"); } // ── 状态更新方法 ── @@ -71,7 +71,7 @@ namespace XplorePlane.Services.AppState public void UpdateMotionState(MotionState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateMotionState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateMotionState 调用"); return; } var old = Interlocked.Exchange(ref _motionState, newState); if (ReferenceEquals(old, newState)) return; @@ -81,7 +81,7 @@ namespace XplorePlane.Services.AppState public void UpdateRaySourceState(RaySourceState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateRaySourceState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateRaySourceState 调用"); return; } var old = Interlocked.Exchange(ref _raySourceState, newState); if (ReferenceEquals(old, newState)) return; @@ -91,7 +91,7 @@ namespace XplorePlane.Services.AppState public void UpdateDetectorState(DetectorState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateDetectorState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateDetectorState 调用"); return; } var old = Interlocked.Exchange(ref _detectorState, newState); if (ReferenceEquals(old, newState)) return; @@ -101,7 +101,7 @@ namespace XplorePlane.Services.AppState public void UpdateSystemState(SystemState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateSystemState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateSystemState 调用"); return; } var old = Interlocked.Exchange(ref _systemState, newState); if (ReferenceEquals(old, newState)) return; @@ -111,7 +111,7 @@ namespace XplorePlane.Services.AppState public void UpdateCameraState(CameraState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateCameraState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateCameraState 调用"); return; } var old = Interlocked.Exchange(ref _cameraState, newState); if (ReferenceEquals(old, newState)) return; @@ -121,7 +121,7 @@ namespace XplorePlane.Services.AppState public void UpdateCalibrationMatrix(CalibrationMatrix newMatrix) { ArgumentNullException.ThrowIfNull(newMatrix); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateCalibrationMatrix 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateCalibrationMatrix 调用"); return; } var old = Interlocked.Exchange(ref _calibrationMatrix, newMatrix); if (ReferenceEquals(old, newMatrix)) return; @@ -135,7 +135,7 @@ namespace XplorePlane.Services.AppState public void UpdateLinkedViewState(LinkedViewState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateLinkedViewState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateLinkedViewState 调用"); return; } var old = Interlocked.Exchange(ref _linkedViewState, newState); if (ReferenceEquals(old, newState)) return; @@ -145,7 +145,7 @@ namespace XplorePlane.Services.AppState public void UpdateRecipeExecutionState(RecipeExecutionState newState) { ArgumentNullException.ThrowIfNull(newState); - if (_disposed) { _logger.Warning("AppStateService 已释放,忽略 UpdateRecipeExecutionState 调用"); return; } + if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateRecipeExecutionState 调用"); return; } var old = Interlocked.Exchange(ref _recipeExecutionState, newState); if (ReferenceEquals(old, newState)) return; @@ -159,7 +159,7 @@ namespace XplorePlane.Services.AppState var matrix = _calibrationMatrix; if (matrix is null) { - _logger.Warning("CalibrationMatrix 未设置,无法执行画面联动 (pixelX={PixelX}, pixelY={PixelY})", pixelX, pixelY); + _logger.Warn("CalibrationMatrix 未设置,无法执行画面联动 (pixelX={PixelX}, pixelY={PixelY})", pixelX, pixelY); UpdateSystemState(SystemState with { HasError = true, @@ -203,10 +203,7 @@ namespace XplorePlane.Services.AppState private void SubscribeToExistingServices() { - // IRaySourceService 是基于命令的服务(没有直接的状态变更事件), - // 状态同步由外部调用者通过 UpdateRaySourceState 完成。 - // TODO: 当 IRaySourceService 添加状态变更事件时,在此处订阅并同步到 RaySourceState - _logger.Information("AppStateService 已准备好接收外部服务状态更新"); + _logger.Info("AppStateService 已准备好接收外部服务状态更新"); } // ── Dispose ── @@ -226,7 +223,7 @@ namespace XplorePlane.Services.AppState RecipeExecutionStateChanged = null; LinkedViewRequested = null; - _logger.Information("AppStateService 已释放"); + _logger.Info("AppStateService 已释放"); } } } diff --git a/XplorePlane/Services/ImageProcessing/ImageProcessingService.cs b/XplorePlane/Services/ImageProcessing/ImageProcessingService.cs index 18bba8d..a5e0f8b 100644 --- a/XplorePlane/Services/ImageProcessing/ImageProcessingService.cs +++ b/XplorePlane/Services/ImageProcessing/ImageProcessingService.cs @@ -8,19 +8,19 @@ using Emgu.CV; using Emgu.CV.Structure; using ImageProcessing.Core; using ImageProcessing.Processors; -using Serilog; +using XP.Common.Logging.Interfaces; namespace XplorePlane.Services { public class ImageProcessingService : IImageProcessingService { - private readonly ILogger _logger; + private readonly ILoggerService _logger; private readonly ConcurrentDictionary _processorRegistry; private readonly ConcurrentDictionary _processorRegistry16; - public ImageProcessingService(ILogger logger) + public ImageProcessingService(ILoggerService logger) { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _logger = logger?.ForModule() ?? throw new ArgumentNullException(nameof(logger)); _processorRegistry = new ConcurrentDictionary(); _processorRegistry16 = new ConcurrentDictionary(); RegisterBuiltInProcessors(); @@ -43,7 +43,7 @@ namespace XplorePlane.Services _processorRegistry16["GaussianBlur16"] = new GaussianBlurProcessor16(); _processorRegistry16["FlatFieldCorrection16"] = new FlatFieldCorrectionProcessor16(); - _logger.Information("Registered {Count8} 8-bit and {Count16} 16-bit built-in image processors", + _logger.Info("Registered {Count8} 8-bit and {Count16} 16-bit built-in image processors", _processorRegistry.Count, _processorRegistry16.Count); } @@ -59,7 +59,7 @@ namespace XplorePlane.Services if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Processor name cannot be empty", nameof(name)); if (processor == null) throw new ArgumentNullException(nameof(processor)); _processorRegistry[name] = processor; - _logger.Information("Registered processor: {ProcessorName}", name); + _logger.Info("Registered processor: {ProcessorName}", name); } public IReadOnlyList GetProcessorParameters(string processorName) diff --git a/XplorePlane/Services/Recipe/RecipeService.cs b/XplorePlane/Services/Recipe/RecipeService.cs index 9f7e858..351d90e 100644 --- a/XplorePlane/Services/Recipe/RecipeService.cs +++ b/XplorePlane/Services/Recipe/RecipeService.cs @@ -4,7 +4,7 @@ using System.IO; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Serilog; +using XP.Common.Logging.Interfaces; using XplorePlane.Models; using XplorePlane.Services.AppState; @@ -18,7 +18,7 @@ namespace XplorePlane.Services.Recipe { private readonly IAppStateService _appStateService; private readonly IPipelineExecutionService _pipelineExecutionService; - private readonly ILogger _logger; + private readonly ILoggerService _logger; private readonly ManualResetEventSlim _pauseHandle = new(true); // initially signaled (not paused) private static readonly JsonSerializerOptions _jsonOptions = new() @@ -29,7 +29,7 @@ namespace XplorePlane.Services.Recipe public RecipeService( IAppStateService appStateService, IPipelineExecutionService pipelineExecutionService, - ILogger logger) + ILoggerService logger) { ArgumentNullException.ThrowIfNull(appStateService); ArgumentNullException.ThrowIfNull(pipelineExecutionService); @@ -37,9 +37,9 @@ namespace XplorePlane.Services.Recipe _appStateService = appStateService; _pipelineExecutionService = pipelineExecutionService; - _logger = logger; + _logger = logger.ForModule(); - _logger.Information("RecipeService 已初始化"); + _logger.Info("RecipeService 已初始化"); } /// @@ -55,7 +55,7 @@ namespace XplorePlane.Services.Recipe UpdatedAt: DateTime.UtcNow, Steps: new List().AsReadOnly()); - _logger.Information("已创建配方: {RecipeName}, Id={RecipeId}", name, recipe.Id); + _logger.Info("已创建配方: {RecipeName}, Id={RecipeId}", name, recipe.Id); return recipe; } @@ -76,7 +76,7 @@ namespace XplorePlane.Services.Recipe DetectorState: detectorState, Pipeline: pipeline); - _logger.Information("已记录配方步骤: StepIndex={StepIndex}, Recipe={RecipeName}", + _logger.Info("已记录配方步骤: StepIndex={StepIndex}, Recipe={RecipeName}", step.StepIndex, recipe.Name); return step; } @@ -94,7 +94,7 @@ namespace XplorePlane.Services.Recipe var json = JsonSerializer.Serialize(recipe, _jsonOptions); await File.WriteAllTextAsync(filePath, json).ConfigureAwait(false); - _logger.Information("已保存配方到文件: {FilePath}, Recipe={RecipeName}", filePath, recipe.Name); + _logger.Info("已保存配方到文件: {FilePath}, Recipe={RecipeName}", filePath, recipe.Name); } /// @@ -134,7 +134,7 @@ namespace XplorePlane.Services.Recipe if (recipe.Steps is null) throw new InvalidDataException($"配方文件数据不完整,缺少步骤列表: {filePath}"); - _logger.Information("已加载配方: {FilePath}, Recipe={RecipeName}, Steps={StepCount}", + _logger.Info("已加载配方: {FilePath}, Recipe={RecipeName}, Steps={StepCount}", filePath, recipe.Name, recipe.Steps.Count); return recipe; } @@ -144,7 +144,7 @@ namespace XplorePlane.Services.Recipe { ArgumentNullException.ThrowIfNull(recipe); - _logger.Information("开始执行配方: {RecipeName}, 共 {StepCount} 步", recipe.Name, recipe.Steps.Count); + _logger.Info("开始执行配方: {RecipeName}, 共 {StepCount} 步", recipe.Name, recipe.Steps.Count); // 重置暂停状态 _pauseHandle.Set(); @@ -172,7 +172,7 @@ namespace XplorePlane.Services.Recipe Status: RecipeExecutionStatus.Running, CurrentRecipeName: recipe.Name)); - _logger.Information("执行配方步骤 {StepIndex}/{TotalSteps}: Recipe={RecipeName}", + _logger.Info("执行配方步骤 {StepIndex}/{TotalSteps}: Recipe={RecipeName}", i + 1, recipe.Steps.Count, recipe.Name); try @@ -208,11 +208,11 @@ namespace XplorePlane.Services.Recipe Status: RecipeExecutionStatus.Completed, CurrentRecipeName: recipe.Name)); - _logger.Information("配方执行完成: {RecipeName}", recipe.Name); + _logger.Info("配方执行完成: {RecipeName}", recipe.Name); } catch (OperationCanceledException) { - _logger.Information("配方执行已取消: {RecipeName}", recipe.Name); + _logger.Info("配方执行已取消: {RecipeName}", recipe.Name); _appStateService.UpdateRecipeExecutionState(new RecipeExecutionState( CurrentStepIndex: 0, @@ -238,7 +238,7 @@ namespace XplorePlane.Services.Recipe }); } - _logger.Information("配方执行已暂停"); + _logger.Info("配方执行已暂停"); } /// @@ -254,7 +254,7 @@ namespace XplorePlane.Services.Recipe } _pauseHandle.Set(); - _logger.Information("配方执行已恢复"); + _logger.Info("配方执行已恢复"); } // ── 内部辅助方法 ── @@ -271,9 +271,7 @@ namespace XplorePlane.Services.Recipe _appStateService.UpdateDetectorState(step.DetectorState); // TODO: 通过 IPipelineExecutionService 执行 Pipeline - // IPipelineExecutionService.ExecutePipelineAsync 需要 IEnumerable 和 BitmapSource, - // 而 RecipeStep 持有 PipelineModel。此处记录日志作为占位,待 ViewModel 层适配后完善。 - _logger.Information("步骤 {StepIndex}: 已更新设备状态,Pipeline '{PipelineName}' 执行待实现", + _logger.Info("步骤 {StepIndex}: 已更新设备状态,Pipeline '{PipelineName}' 执行待实现", step.StepIndex, step.Pipeline?.Name ?? "N/A"); await Task.CompletedTask; diff --git a/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs index 09722b8..9f59b84 100644 --- a/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/ImageProcessingViewModel.cs @@ -6,7 +6,7 @@ using System.Windows.Media.Imaging; using Microsoft.Win32; using Prism.Commands; using Prism.Mvvm; -using Serilog; +using XP.Common.Logging.Interfaces; using XplorePlane.Services; namespace XplorePlane.ViewModels @@ -22,7 +22,7 @@ namespace XplorePlane.ViewModels public class ImageProcessingViewModel : BindableBase { private readonly IImageProcessingService _imageProcessingService; - private readonly ILogger _logger; + private readonly ILoggerService _logger; private ProcessorItem _selectedProcessorItem; private BitmapSource _currentImage; @@ -31,10 +31,10 @@ namespace XplorePlane.ViewModels private bool _isProcessing; private string _statusMessage; - public ImageProcessingViewModel(IImageProcessingService imageProcessingService, ILogger logger) + public ImageProcessingViewModel(IImageProcessingService imageProcessingService, ILoggerService logger) { _imageProcessingService = imageProcessingService; - _logger = logger; + _logger = logger?.ForModule() ?? throw new ArgumentNullException(nameof(logger)); AvailableProcessors = new ObservableCollection(); CurrentParameters = new ObservableCollection(); @@ -119,7 +119,7 @@ namespace XplorePlane.ViewModels catch (ArgumentException ex) { StatusMessage = $"Error loading parameters: {ex.Message}"; - _logger.Warning(ex, "Failed to load parameters for processor: {ProcessorName}", processorName); + _logger.Warn("Failed to load parameters for processor: {ProcessorName}", processorName); } } private async void OnApplyProcessing() @@ -145,18 +145,18 @@ namespace XplorePlane.ViewModels CurrentImage = result; StatusMessage = $"Processing complete: {SelectedProcessor}"; - _logger.Information("Image processing completed: {ProcessorName}", SelectedProcessor); + _logger.Info("Image processing completed: {ProcessorName}", SelectedProcessor); } catch (ArgumentException ex) { StatusMessage = $"Processing error: {ex.Message}"; - _logger.Warning(ex, "Processing failed for processor: {ProcessorName}", SelectedProcessor); + _logger.Warn("Processing failed for processor: {ProcessorName}", SelectedProcessor); // CurrentImage unchanged } catch (OperationCanceledException) { StatusMessage = "Processing cancelled"; - _logger.Information("Image processing cancelled"); + _logger.Info("Image processing cancelled"); // CurrentImage unchanged } catch (ImageProcessingException ex) diff --git a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs index 16b817f..0a0a6ec 100644 --- a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs @@ -8,6 +8,7 @@ using System.Windows.Media.Imaging; using Microsoft.Win32; using Prism.Commands; using Prism.Mvvm; +using XP.Common.Logging.Interfaces; using XplorePlane.Models; using XplorePlane.Services; @@ -21,6 +22,7 @@ namespace XplorePlane.ViewModels private readonly IImageProcessingService _imageProcessingService; private readonly IPipelineExecutionService _executionService; private readonly IPipelinePersistenceService _persistenceService; + private readonly ILoggerService _logger; private PipelineNodeViewModel _selectedNode; private BitmapSource _sourceImage; @@ -37,11 +39,13 @@ namespace XplorePlane.ViewModels public PipelineEditorViewModel( IImageProcessingService imageProcessingService, IPipelineExecutionService executionService, - IPipelinePersistenceService persistenceService) + IPipelinePersistenceService persistenceService, + ILoggerService logger) { _imageProcessingService = imageProcessingService ?? throw new ArgumentNullException(nameof(imageProcessingService)); _executionService = executionService ?? throw new ArgumentNullException(nameof(executionService)); _persistenceService = persistenceService ?? throw new ArgumentNullException(nameof(persistenceService)); + _logger = logger?.ForModule() ?? throw new ArgumentNullException(nameof(logger)); PipelineNodes = new ObservableCollection(); AvailableDevices = new ObservableCollection(); @@ -153,30 +157,30 @@ namespace XplorePlane.ViewModels private void AddOperator(string operatorKey) { - Serilog.Log.Debug("AddOperator 被调用,operatorKey={OperatorKey}", operatorKey); + _logger.Debug("AddOperator 被调用,operatorKey={OperatorKey}", operatorKey); if (string.IsNullOrWhiteSpace(operatorKey)) { StatusMessage = "算子键不能为空"; - Serilog.Log.Warning("AddOperator 失败:operatorKey 为空"); + _logger.Warn("AddOperator 失败:operatorKey 为空"); return; } var available = _imageProcessingService.GetAvailableProcessors(); - Serilog.Log.Debug("可用算子数量:{Count},包含 {Key}:{Contains}", + _logger.Debug("可用算子数量:{Count},包含 {Key}:{Contains}", available.Count(), operatorKey, available.Contains(operatorKey)); if (!available.Contains(operatorKey)) { StatusMessage = $"算子 '{operatorKey}' 未注册"; - Serilog.Log.Warning("AddOperator 失败:算子 {Key} 未注册", operatorKey); + _logger.Warn("AddOperator 失败:算子 {Key} 未注册", operatorKey); return; } if (PipelineNodes.Count >= MaxPipelineLength) { StatusMessage = $"流水线节点数已达上限({MaxPipelineLength})"; - Serilog.Log.Warning("AddOperator 失败:节点数已达上限 {Max}", MaxPipelineLength); + _logger.Warn("AddOperator 失败:节点数已达上限 {Max}", MaxPipelineLength); return; } @@ -187,7 +191,7 @@ namespace XplorePlane.ViewModels }; LoadNodeParameters(node); PipelineNodes.Add(node); - Serilog.Log.Information("节点已添加到 PipelineNodes:{Key} ({DisplayName}),当前节点数={Count}", + _logger.Info("节点已添加到 PipelineNodes:{Key} ({DisplayName}),当前节点数={Count}", operatorKey, displayName, PipelineNodes.Count); StatusMessage = $"已添加算子:{displayName}"; TriggerDebouncedExecution(); @@ -457,32 +461,32 @@ namespace XplorePlane.ViewModels PipelineNodes.Add(node); } - Serilog.Log.Information("流水线已加载:{Name},节点数={Count}", model.Name, PipelineNodes.Count); + _logger.Info("流水线已加载:{Name},节点数={Count}", model.Name, PipelineNodes.Count); StatusMessage = $"已加载流水线:{model.Name}({PipelineNodes.Count} 个节点)"; } catch (Exception ex) { - Serilog.Log.Warning("加载流水线失败:{Error}", ex.Message); + _logger.Warn("加载流水线失败:{Error}", ex.Message); StatusMessage = $"加载失败:{ex.Message}"; } } private void OpenToolbox() //打开图像工具箱 { - Serilog.Log.Information("OpenToolbox 被调用"); + _logger.Info("OpenToolbox 被调用"); try { var window = new Views.OperatorToolboxWindow { Owner = System.Windows.Application.Current.MainWindow }; - Serilog.Log.Information("OperatorToolboxWindow 已创建,准备 Show()"); + _logger.Info("OperatorToolboxWindow 已创建,准备 Show()"); window.Show(); - Serilog.Log.Information("OperatorToolboxWindow.Show() 完成"); + _logger.Info("OperatorToolboxWindow.Show() 完成"); } catch (Exception ex) { - Serilog.Log.Error(ex, "OpenToolbox 打开窗口失败"); + _logger.Error(ex, "OpenToolbox 打开窗口失败"); } } diff --git a/XplorePlane/ViewModels/Main/MainViewModel.cs b/XplorePlane/ViewModels/Main/MainViewModel.cs index a7110e6..fc35b57 100644 --- a/XplorePlane/ViewModels/Main/MainViewModel.cs +++ b/XplorePlane/ViewModels/Main/MainViewModel.cs @@ -1,13 +1,13 @@ using Prism.Commands; using Prism.Mvvm; using System.Collections.ObjectModel; -using Serilog; +using XP.Common.Logging.Interfaces; namespace XplorePlane.ViewModels { public class MainViewModel : BindableBase { - private readonly ILogger _logger; + private readonly ILoggerService _logger; private string _licenseInfo = "当前时间"; public string LicenseInfo @@ -27,9 +27,9 @@ namespace XplorePlane.ViewModels public DelegateCommand OpenImageProcessingCommand { get; set; } public DelegateCommand OpenPipelineEditorCommand { get; set; } - public MainViewModel(ILogger logger) + public MainViewModel(ILoggerService logger) { - _logger = logger?.ForContext() ?? throw new System.ArgumentNullException(nameof(logger)); + _logger = logger?.ForModule() ?? throw new System.ArgumentNullException(nameof(logger)); NavigationTree = new ObservableCollection(); @@ -43,52 +43,52 @@ namespace XplorePlane.ViewModels { var window = new Views.ImageProcessingWindow(); window.Show(); - _logger.Information("图像处理窗口已打开"); + _logger.Info("图像处理窗口已打开"); }); OpenPipelineEditorCommand = new DelegateCommand(() => { var window = new Views.PipelineEditorWindow(); window.Show(); - _logger.Information("流水线编辑器窗口已打开"); + _logger.Info("流水线编辑器窗口已打开"); }); - _logger.Information("MainViewModel 已初始化"); + _logger.Info("MainViewModel 已初始化"); } private void OnNavigateHome() { - _logger.Information("导航到主页"); + _logger.Info("导航到主页"); LicenseInfo = "主页"; } private void OnNavigateInspect() { - _logger.Information("导航到检测页面"); + _logger.Info("导航到检测页面"); LicenseInfo = "检测页面"; } private void OnOpenFile() { - _logger.Information("打开文件"); + _logger.Info("打开文件"); LicenseInfo = "打开文件"; } private void OnExport() { - _logger.Information("导出数据"); + _logger.Info("导出数据"); LicenseInfo = "导出数据"; } private void OnClear() { - _logger.Information("清除数据"); + _logger.Info("清除数据"); LicenseInfo = "清除数据"; } private void OnEditProperties() { - _logger.Information("编辑属性"); + _logger.Info("编辑属性"); LicenseInfo = "编辑属性"; } } diff --git a/XplorePlane/Views/ImageProcessing/OperatorToolboxView.xaml.cs b/XplorePlane/Views/ImageProcessing/OperatorToolboxView.xaml.cs index 5f2a575..99f0049 100644 --- a/XplorePlane/Views/ImageProcessing/OperatorToolboxView.xaml.cs +++ b/XplorePlane/Views/ImageProcessing/OperatorToolboxView.xaml.cs @@ -1,7 +1,8 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Serilog; +using Prism.Ioc; +using XP.Common.Logging.Interfaces; using XplorePlane.ViewModels; namespace XplorePlane.Views @@ -10,12 +11,17 @@ namespace XplorePlane.Views { public const string DragFormat = "PipelineOperatorKey"; + private readonly ILoggerService _logger; private Point _dragStartPoint; private bool _isDragging; public OperatorToolboxView() { InitializeComponent(); + + var baseLogger = ContainerLocator.Current?.Resolve(); + _logger = baseLogger?.ForModule() ?? baseLogger; + Loaded += OnLoaded; } @@ -23,7 +29,7 @@ namespace XplorePlane.Views { ToolboxListBox.PreviewMouseLeftButtonDown += OnPreviewMouseDown; ToolboxListBox.PreviewMouseMove += OnPreviewMouseMove; - Log.Debug("OperatorToolboxView 原生拖拽源已注册, DataContext={Type}", + _logger?.Debug("OperatorToolboxView 原生拖拽源已注册, DataContext={Type}", DataContext?.GetType().Name); } @@ -46,11 +52,10 @@ namespace XplorePlane.Views { _isDragging = true; - // 从鼠标位置 HitTest 找到 OperatorDescriptor var hitResult = System.Windows.Media.VisualTreeHelper.HitTest( ToolboxListBox, e.GetPosition(ToolboxListBox)); - OperatorDescriptor? descriptor = null; + OperatorDescriptor descriptor = null; var node = hitResult?.VisualHit as DependencyObject; while (node != null) { @@ -64,11 +69,11 @@ namespace XplorePlane.Views if (descriptor == null) { - Log.Warning("拖拽初始化失败:HitTest 未命中算子项"); + _logger?.Warn("拖拽初始化失败:HitTest 未命中算子项"); return; } - Log.Information("开始拖拽算子:{OperatorKey} ({DisplayName})", descriptor.Key, descriptor.DisplayName); + _logger?.Info("开始拖拽算子:{OperatorKey} ({DisplayName})", descriptor.Key, descriptor.DisplayName); var data = new DataObject(DragFormat, descriptor.Key); DragDrop.DoDragDrop(ToolboxListBox, data, DragDropEffects.Copy); } diff --git a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml.cs b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml.cs index b9dfae5..55fb7db 100644 --- a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml.cs +++ b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml.cs @@ -1,27 +1,34 @@ using System.Windows; using System.Windows.Controls; -using Serilog; +using Prism.Ioc; +using XP.Common.Logging.Interfaces; using XplorePlane.ViewModels; namespace XplorePlane.Views { public partial class PipelineEditorView : UserControl { + private readonly ILoggerService _logger; + public PipelineEditorView() { InitializeComponent(); + + var baseLogger = ContainerLocator.Current?.Resolve(); + _logger = baseLogger?.ForModule() ?? baseLogger; + Loaded += OnLoaded; } private void OnLoaded(object sender, RoutedEventArgs e) { - Log.Information("PipelineEditorView DataContext 类型={Type}", + _logger?.Info("PipelineEditorView DataContext 类型={Type}", DataContext?.GetType().Name); PipelineListBox.AllowDrop = true; PipelineListBox.Drop += OnOperatorDropped; PipelineListBox.DragOver += OnDragOver; - Log.Debug("PipelineEditorView 原生 Drop 目标已注册"); + _logger?.Debug("PipelineEditorView 原生 Drop 目标已注册"); } private void OnDragOver(object sender, DragEventArgs e) @@ -37,27 +44,27 @@ namespace XplorePlane.Views { if (DataContext is not PipelineEditorViewModel vm) { - Log.Warning("Drop 事件触发但 DataContext 不是 PipelineEditorViewModel"); + _logger?.Warn("Drop 事件触发但 DataContext 不是 PipelineEditorViewModel"); return; } if (!e.Data.GetDataPresent(OperatorToolboxView.DragFormat)) { - Log.Warning("Drop 事件触发但数据中无 {Format}", OperatorToolboxView.DragFormat); + _logger?.Warn("Drop 事件触发但数据中无 {Format}", OperatorToolboxView.DragFormat); return; } var operatorKey = e.Data.GetData(OperatorToolboxView.DragFormat) as string; if (string.IsNullOrEmpty(operatorKey)) { - Log.Warning("Drop 事件触发但 OperatorKey 为空"); + _logger?.Warn("Drop 事件触发但 OperatorKey 为空"); return; } - Log.Information("算子已放入流水线:{OperatorKey},VM HashCode={Hash},当前节点数(执行前)={Count}", + _logger?.Info("算子已放入流水线:{OperatorKey},VM HashCode={Hash},当前节点数(执行前)={Count}", operatorKey, vm.GetHashCode(), vm.PipelineNodes.Count); vm.AddOperatorCommand.Execute(operatorKey); - Log.Information("AddOperator 执行后节点数={Count},PipelineListBox.Items.Count={ItemsCount}", + _logger?.Info("AddOperator 执行后节点数={Count},PipelineListBox.Items.Count={ItemsCount}", vm.PipelineNodes.Count, PipelineListBox.Items.Count); e.Handled = true; } diff --git a/XplorePlane/readme.txt b/XplorePlane/readme.txt index 0bbb5e8..48049df 100644 --- a/XplorePlane/readme.txt +++ b/XplorePlane/readme.txt @@ -24,26 +24,21 @@ 2、新增打开图像工具箱(修复DataContext问题) √ 3、对主界面B方案进行优化 √ - 2026.3.17 ---------------------- 1、对界面设计进行优化 ,增加了扫描模式,移除了探测器设置,增加底部工具栏 √ - - 2026.3.18 ---------------------- 1、全局数据结构的考虑与设计(多个窗体可以调用公共的数据,如射线源状态,探测器状态,运动位置,图像等) √ 2、将计划窗体默认隐藏,只有CNC状态下展开 √ -3、日志该用XP.Common库和多语言的学习 √ - 2026.3.20 ---------------------- 1、软件主界面设计讨论,暂定初稿,给出效果图设计 √ -2、 +2、日志该用XP.Common库和多语言的学习