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