From 687d0b2a878d5d85c1e78819e1baba68c7659622 Mon Sep 17 00:00:00 2001 From: "zhengxuan.zhang" Date: Mon, 23 Mar 2026 14:04:53 +0800 Subject: [PATCH] =?UTF-8?q?#0044=20=E4=BD=BF=E7=94=A8=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E5=BA=93=E5=B1=82=E9=9D=A2=E7=9A=84=E6=97=A5=E5=BF=97=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pipeline/PipelineEditorViewModelTests.cs | 6 ++- .../Pipeline/PipelinePropertyTests.cs | 5 ++- .../Services/AppStateServiceTests.cs | 7 ++-- .../Services/RecipeServiceTests.cs | 7 ++-- XplorePlane.Tests/XplorePlane.Tests.csproj | 4 ++ XplorePlane/Libs/Hardware/XP.Common.dll | Bin 81920 -> 88576 bytes .../Hardware/en-US/XP.Common.resources.dll | Bin 10240 -> 10752 bytes .../Hardware/zh-CN/XP.Common.resources.dll | Bin 9216 -> 10240 bytes .../Hardware/zh-TW/XP.Common.resources.dll | Bin 9728 -> 10240 bytes .../Services/AppState/AppStateService.cs | 35 ++++++++---------- .../ImageProcessing/ImageProcessingService.cs | 12 +++--- XplorePlane/Services/Recipe/RecipeService.cs | 34 ++++++++--------- .../ImageProcessingViewModel.cs | 16 ++++---- .../PipelineEditorViewModel.cs | 30 ++++++++------- XplorePlane/ViewModels/Main/MainViewModel.cs | 26 ++++++------- .../OperatorToolboxView.xaml.cs | 17 ++++++--- .../PipelineEditorView.xaml.cs | 23 ++++++++---- XplorePlane/readme.txt | 7 +--- 18 files changed, 124 insertions(+), 105 deletions(-) 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 0ef066cb9c25a98df752be8f78614e8c334dcc5e..d5b7a014cb5e8b7ef5ee378dd20406a6809d1337 100644 GIT binary patch literal 88576 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

R7F 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 M@&Et*KgWUp3nGniU;qFB literal 81920 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 diff --git a/XplorePlane/Libs/Hardware/en-US/XP.Common.resources.dll b/XplorePlane/Libs/Hardware/en-US/XP.Common.resources.dll index 479b022bf00a38b65ddc7b49b2431937efc4cc4c..e294ebe8a32f62723b4875d608d4c41a27bb247c 100644 GIT binary patch delta 2192 zcmZWpeN2>f9RL0fo&%11KR9q890w{Po+#-I$aqr_MG>%cntGg%cy-*dyXR2UJgm0L z%EGU0t!(PFriNSWn%UAVm%7^ADyM5|FJ^1CT50~_6f65Y&mExa_w4)n`+Q%1Z_hy6 zK2_F-M83WKzfJ*s$;hwyz z7Ai(FNJkR2xqt&$s7?%}1eNlTxr`4^EQwXXU%ZWI59B#j?@+@2V0T1?Zb(U#DPGn= z0q9ovikp@#XoTDf`;cna2SQzt>Od1BEsH2atu-Pl$(bl?fT_ANlBDWMib2g4s-bS+ ztF%(+X+-0N)GRD?5>tBmkt*OntML|%cWeBp#w)?q_(T=~nL+i)X#>~O1aJdA1a74n z8h=FNbsCQ?(8N-Wdnl6%$U_dA0-i_n!HaP`9-2z4!7E7yuck0~gXUido;omE8a-&^ zFbbxR8j#uA&LtdblUov<*0hG!RYwEzT#|#+u*Dty5k>Ctv`2%AzelDu7`NAo@voM`|3k#eLp`KoUz^nK}!FD;|-K1#|o>w@v zwjtEpANF@|Q2w7sjq(Qj$0w4-HNWET@(27%KkqMew~RI?uMfyRwF-HBN+>+qbfe$f z9SlVjzb`WCN~ZE8I+Md4a=6d$lOz0X;q=(@Hr3w~3VOnFBoqz9pIk65ANB>NI(EnR z?tJ6+&n@qtK5;_HS(-`a4o~`D%2_F=g|kxaUT^-BvVy%0%=G0+)c+gU*2t z;1wP)6E)$T1c2Lu_izb%4(4t{Uc+2QCQ&*K5%>cFbKtuR-{&A7!0#bJCgf%$i2`>AR0A77EDC_`g8C7+3;xfbKZ!!a z(0>D7U3DDvJA51Q@P~jq1Wc}IAo>Xthq2mCpk_>5hWrl24+882xECvJ0KJPw%CQp? z8mU8*&!KT6utPj7Ia+g3rU|qXh*v-(pvMt?9BZ8gIT`X#w0j;c*^zA$WCWRxA zWjDGA1EY@Bag)AJ&mS7I^Xh0F^^uo?)AB_qLjQ7+d8U}eo#18sg1JUa z=hNnL(Zqk5AC}tDY8juj<#N5nu3MGL+l@K=rA5yXm>Wk;BOkFCrMJegUs==nip8Ki zJPt5ejnXgxv$bR@pxWxxeL4m(uc3MP7lpC5FkKjP+t%R6;=MQdgVLdb?RSP1067 z&7LdTc)op(Sk5uKTY4HG4_~qu@M*hMw><&+1E4|HJ3P952}i3VS30C#Pu}Zr@eYSo z9OJhgb95IZj+t_Jn?uhx9i`$1=Vet%23!O;Z_jdz0)8fIt~3MoT-YUi$6z)s#-1qT z*G_B&-^(fy?{G0e+X4I^FtI+;&mSv5Cd;Jx)tXdRpDOK5x(`$B#@HN%17^WrE`}KQP*A z$IYiy-8ER`)UB$GpLI10wiYRDc2|qF@fP<^op?5Wsiah70EX8@TPxzW$=AhTMcRKt CjmWbA delta 1774 zcmZ8i3v5$m6h8mmz1`ZC(f7SAqx40YGnC5aB5W>`*I>NH3Pu9qHOidX*4cLGrm_(< z0updJ7!hMIN|YELk|HB2(FCI;Xhb5yh|DP%gNa}WMv2Dw-P$Q-&T?Znv8M;Iy8|J@~`ufksO7;Mq&?9w3 zdkXr4PI(QHl{befdAXQmx#dSFpc8KwVRIccy-tXaiwWj6&`_A7JS0NVvwB~wxgd!Y z+Fwm{3t?e+i5de$P2*6xTrA=)(|)lw=PTSKf^ROicb*?;$t<}4uT1%+;jX8SXL~Fb zqCp&MA#!)}$s)D4vxKM~)uvg|!Hg($wSedk$Rmh-gN!D$nvPr859%o*x&XNg@edTD z3dC-JyvQv=4RtKhJmeijm#e^@hVLa%Gq4%t6+_m;KLfZ=#}X&Z_TD+bu7-UIyDBdv z+5~+7m@4ce2RZ@YEE`cba0h_V(C-TT8?m?9AUFJPL%xGOJPzy?+fx>8f0*93#qmb8efPHA-0RAQl z9!J4#$lr|(r4iRxI5*9*(ZoO4CW{KT*{3Qq5M0FH+XLKUkBQZM*&gBd?IH03v^mNV zM9UC$agDx&?0PhS(W~~GN!nTc)H6XUN_>ch#x?_ zYP6yr-|O;-0mS3t40v>`-k}Q}vUKi$wH(SIJk$S^ZRN+@9`PM-cE_b(WVYK?);BuE zZQ+YcmE3zffw;5lOGWa4258G7U;n9?Oz$%TlCp`hN zn1?(ev5tj0ReCZHTA*sm*3nwes2=I%eBhv}N&6ID;#B#vTB;lxEp%D6vR`vaXA~a7 zuIFnpLoW73{il(kC2*H(L0vf2YRqO5)_Uru3%uCp7en0P3y5pH3;ZU( z>kCPLnsQ(JstR&W|Lp>9lp+sa)dz4B-USS%{!0lbvgy{2mW)1_k77VE-xOY!pibzR zX$sdbn>P!x4|bN1O5=McR*)zEzTl9?JEO}xI!cbbJp&`sL=(x0XL5$YR~S5N@V(&r z(sOh!$V@dff$RqN8a!z5dkh|Qbt?z0})>3<>IhAf}T}O%TOg7mbYf5ftOEza)QyuhBCX;Mm*TzxV zro@`FsWg8s`}h?($SY(&SIOg9Ry6M;jj@@j_V!dqES=1xy3)w*5D$CUqn$TfxL3NDFMi@IDx cWTzya%?(D&gc)gg{pi=)oW1OZ=#Llv1Ev&cfB*mh diff --git a/XplorePlane/Libs/Hardware/zh-CN/XP.Common.resources.dll b/XplorePlane/Libs/Hardware/zh-CN/XP.Common.resources.dll index ba2cede95b90a3758cfe84db075aa88119a7dde2..22c555ed36fe83852858cc7aed31727db7ab9c0f 100644 GIT binary patch delta 2660 zcmZWr3s6+o8UD}R2e9mu#odKvU_l;Tie^%|8ib*|IIgPa@?alS1Kzda>1ZY7++g8@YW_{?JA-MVOULcOf`^e z)jv<9$GjK|S^R!hG2hCHbU(;}$t8&QvH2{IUtmS7kblhb3ikjgMlDDp4K=!m^3_C4 z7%?LGM3*uVX&&E~k>67a``m964MN@)dQ&9i3wXlLHEK}CX(UXZnn2D`I+rkr zB6lY$U0xsDRu=WkD{0q`lFIee)E$nfSX;%oK!eUWay*O|9&syKPOUv3jw$lVqRhNg%997m zTJ+<#gQRvbmaK9S(?GFU#MGF4Zq;)=mJ!{uWH#CMY;g#hCEMnZr(=CEP~FugcZiys zcZ7nSVV2CEpd{rT7;#pnOTkHlp9|j`qojrIQt|M`Sx@5=h-LB((vWrPpf{FRiNCVC zrM+COs!d%#e)+X8%Z|RjHTWOipvow2Isf>_zx-MKaC=|%wcmc|davbP+j}PqGe0=J zJNw3#+~qf<{i8Q07QAr#tvjFpg7>Ok&e2cYTky&Yre!77)hoBJ=wJD0{?YP=_J`$9 z{e4NrQxDE?r@Ex)&DAx5p$1FG$VG3sZt<7ld3WzccVCF?T7l0?k1L`c{d(U(^eudu z4WR9y+n^!TKV&4T!RP4*ZZ|%|JJ9V|`zPcdv6hlbv;iGihRf)8pffnWx+J2*Sihnn zTEwV_#sR2_yhu^LheG4C~%KK%Q44&M}E*3plyKj#P(8n)}Dq?pM#GWY|`5*{xH?f)kcSO zBcUEM=?#^lIQYou%7+RTR{c!jkEWr`}7me{bU(4UD3#Aq{A28VY&rRu)UqmaB_9?CzP1KFOi9WW^>dN2|i-Q-LU7F)K zLD{11{CTrZI4ohu&V~zj_0c<_VZ?k<`Hs~ zDmfe$Js&rl*}soimPj@Yf1pPTEoSbqWJ_)hI=WP<(C}ePfo3a?_%eRolE;(N92zfX zE0tMIT9)*ZhRbPl*>!#(ZC>^*EIFF6MR8oB*z9vO)9(@ftF&zP5r3HGVsUP<7P8Oz z5^Gj2eugP?wo?-V>{QO0mr}GmYR!@CTK+0Tj+S4v=1N7{*j?)zQd&y{brln6B)o|)o`_p~8qb$pYR;QE;wxMgOIj>-Sv pgt1TPu7O;ev}YARku?}IX5W(7cVc&33z#&xDrU(WX9J~4{{>O3n>7Fc delta 1734 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 delta 1714 zcmY*aeQZ-z6hHT^uie%%*7oi7wQOC#7_doK*_d%`1e{?aARFV$KoGW-F|w`Lj~Hfj zMZ~yCoXb%o3z~>T(GW9I`G^Vz(ZmQSM#+G%Wymz5iTlR{V@UM(-o}Lc@;mpubAIRJ z-gkSOZb+|u?d8C^$nkcX8e=5+t-?y=g~2>&{H}K3qxE^|TA~%YVF}S&Sp$BjX)BS9 z&-yF*Niiq)ry{s~fS3D3neg!mF-L@WR0K+f5UG#H0EuMUUrqFvL?jF=QG<_Ykq4Pd z#Y3Dj9~N8LV`GZx7xnz^2xTu%7u3lrPsz%&z?wjU(6voh!$5NzL8I7yLu|} zi0YB?4y;yquR?ca5&exh4&Q-XqBSU2jTIdRhJk+gK9h+mV4nc4XA_-A{59}xKn(f^ zu)Sg<+6c6On?Rfub3N?xOrl<(Mkd~nGovR5`~cq1p{r60(NgH$;8mfI3~&lIOFsDE z9RWu}&6}`4jNY<=E5J^m6a7C8?)!+}Wg@Br7NY*=fQ(jw^6jpXiP7n69*Ml%-~~6L`3W7T!&l%OZ7b#8}BSo#UkEQ5WymaYqIt7f?U2*U=xk^S*)r}-i-LkZHcIgyz`#? z*)y9^wFOU<5_n!fFCKnXRpmjjDvg?_Ri8M-qiR45A@c(9B{&+dbZPRB)0v)gsbbu) zA9ZQcgozuSE*^0e%6F#IjJRy<)f7pQ@zGqoLJP|e;0#Re$_g!?4`~j02`m8~(*j}x zU)L7PQM@n4dx-1Y9twn1~ot)tI(b)=lSiB3+{haRI#K{-@I#bh_6 z+mL=k&NF0~tQ6{@Fv3ERvkV!e3g~6jMyB-LRLEwG@98Gtn@tZvxDgCYGH>1W)U1lN zraGdFsWZ_Mi+8j)Q`7E5GTIql6W!hsZArGrx@c)45$$a5;1W~59BxU*;(Wp6;R7Z= zZ!&qg%2dQAS#xh}2-n3rJ7Znpcr+19#ap5Y>fSMb?FQa1mp@LFep9ud;*(bXbxCN*F7xesRblo@LSEZp^e$(HY$qRfdi5D|hL*+ucRGYDvOo)Mq(); _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库和多语言的学习