diff --git a/.gitignore b/.gitignore
index 36df3d3..a43465f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,5 +68,8 @@ XplorePlane/data/
XplorePlane.Tests/bin_codex/
DataBase/XP.db
+DetectorImages/
+Dump/
+Report/
XplorePlane.Tests/TestResults/
ReleaseFiles/win-x64/
diff --git a/README.md b/README.md
index 4ac9fcd..cae0509 100644
--- a/README.md
+++ b/README.md
@@ -17,17 +17,65 @@ XplorePlane 系统用于控制平面 CT 设备的各个子系统(射线源、
```
XplorePlane.sln
-├── XplorePlane/ # 主应用程序(WPF)
-├── XP.Camera/ # 相机控制库(Basler)
-├── ImageProcessing/ # 独立图像处理应用
-├── ImageProcessing.Core/ # 图像处理算子基类
-├── ImageProcessing.Processors/ # 具体算子实现
-├── ImageProcessing.Controls/ # 图像显示控件(ImageCanvasControl)
-├── ImageROIControl/ # ROI 绘制控件
-├── XplorePlane.Tests/ # 单元测试
-└── ExternalLibraries/ # 外部 DLL 和 ONNX 模型
+├── XplorePlane/ # 主应用程序(WPF + Prism)
+├── XP.Common/ # 公共基础库:日志、数据库、Dump、通用控件等
+├── XP.Camera/ # 相机控制库(Basler / Hikvision 等)
+├── XP.Hardware.Detector/ # 探测器硬件抽象与实现
+├── XP.Hardware.MotionControl/ # 运动控制模块
+├── XP.Hardware.PLC/ # PLC 通信模块
+├── XP.Hardware.PLC.Sentry/ # PLC 信号监控 / Sentry 工具
+├── XP.Hardware.RaySource/ # 射线源控制模块
+├── XP.Hardware.RaySource.Comet.Host/ # Comet 射线源独立 Host 进程
+├── XP.Hardware.RaySource.Comet.Messages/# Comet Host 通信消息定义
+├── XP.ImageProcessing.Core/ # 图像处理算子基类与核心模型
+├── XP.ImageProcessing.Processors/ # 具体图像处理算子实现
+├── XP.ImageProcessing.CfgControl/ # 图像处理配置控件
+├── XP.ImageProcessing.RoiControl/ # ROI 绘制与测量控件
+├── XP.Scan/ # 扫描模式相关模块
+├── XP.Calibration/ # 校准模块
+├── XP.ReportEngine/ # 报告生成模块
+├── XP.ImageProcessing.SmokeTest/ # 图像处理冒烟测试程序
+├── XplorePlane.Tests/ # 单元测试项目(不一定参与当前 sln 构建)
+├── ExternalLibraries/ # 外部 DLL、模板、模型等运行依赖
+├── ReleaseFiles/ # 已整理的发布文件快照
+└── bin/ # 当前主程序构建输出目录(由 XplorePlane.csproj 配置)
```
+> 当前主程序 [XplorePlane/XplorePlane.csproj](XplorePlane/XplorePlane.csproj) 通过 `BaseOutputPath=..\bin\` 将输出放在解决方案根目录的 `bin/` 下,而不是 `XplorePlane/bin/` 下。`XP.App/` 是旧输出路径,不再作为当前主程序输出目录使用。
+
+### 运行时目录与数据存储
+
+运行时产生的数据统一放在源码仓库外的 `D:\XPData`,避免数据库、日志、采集图像、Dump 和报告污染 `D:\XplorePlane` 源码目录。
+
+默认配置见 [XplorePlane/App.config](XplorePlane/App.config):
+
+```xml
+
+
+
+
+
+
+```
+
+推荐目录结构:
+
+```
+D:\XPData
+├── DataBase\ # SQLite 数据库,例如 XP.db
+├── DetectorImages\ # 探测器采集图像
+├── Logs\ # Serilog 运行日志
+├── Dump\ # 异常 Dump 文件
+├── Report\ # 报告输出目录
+├── Plan\ # 工艺 / CNC / 检测程序数据
+├── Tools\ # 工具相关数据
+└── Data\ # 其他运行数据
+```
+
+`XplorePlane.Services.Storage.XpDataPathService` 会确保上述受管目录存在。发布目录 [ReleaseFiles/](ReleaseFiles/) 中的 `App.config` 与 `XplorePlane.dll.config` 也应保持同样的运行时路径。
+
+源码目录下旧的运行数据目录(如 `DataBase/XP.db`、`DetectorImages/`、`Dump/`、`Report/`、`Logs/`)不应提交到 Git,已在 [.gitignore](.gitignore) 中忽略。
+
### XplorePlane 主项目结构
```
@@ -86,7 +134,7 @@ XplorePlane/
- NavigationPropertyPanelViewModel(单例,相机预览共享实例)
- 各 Service 和 ViewModel(按需注册)
-### 构建
+### 构建与输出
```bash
# Debug
@@ -94,8 +142,25 @@ dotnet build XplorePlane.sln -c Debug
# Release
dotnet build XplorePlane.sln -c Release
+
+# 只构建主程序
+dotnet build XplorePlane/XplorePlane.csproj -c Release
```
+当前主程序输出目录由 [XplorePlane/XplorePlane.csproj](XplorePlane/XplorePlane.csproj) 配置为:
+
+```text
+D:\XplorePlane\bin\\net8.0-windows\win-x64\
+```
+
+Comet Host 编译后会复制到当前主程序输出目录的 `Host/` 子目录:
+
+```text
+D:\XplorePlane\bin\\net8.0-windows\win-x64\Host\
+```
+
+[ReleaseFiles/](ReleaseFiles/) 是发布文件快照,不是普通编译输出目录;清理或更新运行依赖时需要同步检查该目录。
+
### TO-DO List
- [x] 软件基于 WPF + Prism 基础的框架
diff --git a/ReleaseFiles/App.config b/ReleaseFiles/App.config
index dfda658..f19af76 100644
--- a/ReleaseFiles/App.config
+++ b/ReleaseFiles/App.config
@@ -18,7 +18,7 @@
-
+
@@ -26,7 +26,7 @@
-
+
@@ -69,7 +69,7 @@
-
+
@@ -101,7 +101,7 @@
-
+
@@ -172,7 +172,7 @@
-
+
diff --git a/ReleaseFiles/XplorePlane.dll.config b/ReleaseFiles/XplorePlane.dll.config
index ff77769..3463479 100644
--- a/ReleaseFiles/XplorePlane.dll.config
+++ b/ReleaseFiles/XplorePlane.dll.config
@@ -13,13 +13,13 @@
-
+
-
+
@@ -47,7 +47,7 @@
-
+
@@ -68,7 +68,7 @@
-
+
@@ -123,7 +123,7 @@
value="1.0" />
-
+
diff --git a/XP.ReportEngine/ViewModels/ReportDemoViewModel.cs b/XP.ReportEngine/ViewModels/ReportDemoViewModel.cs
index f7d75b6..8de4436 100644
--- a/XP.ReportEngine/ViewModels/ReportDemoViewModel.cs
+++ b/XP.ReportEngine/ViewModels/ReportDemoViewModel.cs
@@ -426,7 +426,7 @@ namespace XP.ReportEngine.ViewModels
///
/// 模拟图像目录路径 | Mock image directory path
///
- private const string MockImageDirectory = @"D:\XplorePlane\DetectorImages";
+ private const string MockImageDirectory = @"D:\XPData\DetectorImages";
///
/// 创建模拟处理器输出数据(演示用,覆盖所有检测类型)
diff --git a/XplorePlane/App.config b/XplorePlane/App.config
index 091a1fa..2a04d1c 100644
--- a/XplorePlane/App.config
+++ b/XplorePlane/App.config
@@ -18,7 +18,7 @@
-
+
@@ -26,7 +26,7 @@
-
+
@@ -69,7 +69,7 @@
-
+
@@ -105,7 +105,7 @@
-
+
@@ -188,7 +188,7 @@
-
+
diff --git a/XplorePlane/Services/Storage/XpDataPathService.cs b/XplorePlane/Services/Storage/XpDataPathService.cs
index 4d261c2..1298c9a 100644
--- a/XplorePlane/Services/Storage/XpDataPathService.cs
+++ b/XplorePlane/Services/Storage/XpDataPathService.cs
@@ -139,6 +139,10 @@ namespace XplorePlane.Services.Storage
Directory.CreateDirectory(Path.Combine(rootPath, "Plan"));
Directory.CreateDirectory(Path.Combine(rootPath, "Tools"));
Directory.CreateDirectory(Path.Combine(rootPath, "Data"));
+ Directory.CreateDirectory(Path.Combine(rootPath, "DataBase"));
+ Directory.CreateDirectory(Path.Combine(rootPath, "DetectorImages"));
+ Directory.CreateDirectory(Path.Combine(rootPath, "Logs"));
+ Directory.CreateDirectory(Path.Combine(rootPath, "Dump"));
Directory.CreateDirectory(Path.Combine(rootPath, "Report"));
}
}
diff --git a/XplorePlane/ViewModels/Setting/SettingsViewModel.cs b/XplorePlane/ViewModels/Setting/SettingsViewModel.cs
index 4609ff4..9a2aa49 100644
--- a/XplorePlane/ViewModels/Setting/SettingsViewModel.cs
+++ b/XplorePlane/ViewModels/Setting/SettingsViewModel.cs
@@ -301,7 +301,7 @@ namespace XplorePlane.ViewModels.Setting
_logger.Debug("Loaded Language: {Language}", Language);
// Serilog日志配置
- SerilogLogPath = GetAppSetting("Serilog:LogPath", "D:\\XplorePlane\\Logs");
+ SerilogLogPath = GetAppSetting("Serilog:LogPath", "D:\\XPData\\Logs");
SerilogMinimumLevel = GetAppSetting("Serilog:MinimumLevel", "Debug");
SerilogEnableConsole = GetBoolAppSetting("Serilog:EnableConsole", true);
SerilogRollingInterval = GetAppSetting("Serilog:RollingInterval", "Day");
@@ -309,7 +309,7 @@ namespace XplorePlane.ViewModels.Setting
SerilogRetainedFileCountLimit = GetIntAppSetting("Serilog:RetainedFileCountLimit", 365);
// SQLite配置
- SqliteDbFilePath = GetAppSetting("Sqlite:DbFilePath", "D:\\XplorePlane\\DataBase\\XP.db");
+ SqliteDbFilePath = GetAppSetting("Sqlite:DbFilePath", "D:\\XPData\\DataBase\\XP.db");
SqliteConnectionTimeout = GetIntAppSetting("Sqlite:ConnectionTimeout", 10);
SqliteCreateIfNotExists = GetBoolAppSetting("Sqlite:CreateIfNotExists", true);
SqliteEnableWalMode = GetBoolAppSetting("Sqlite:EnableWalMode", true);
@@ -325,7 +325,7 @@ namespace XplorePlane.ViewModels.Setting
DetectorType = GetAppSetting("Detector:Type", "Simulated");
DetectorIP = GetAppSetting("Detector:IP", "192.168.1.200");
DetectorPort = GetIntAppSetting("Detector:Port", 5000);
- DetectorSavePath = GetAppSetting("Detector:SavePath", "D:\\XplorePlane\\DetectorImages");
+ DetectorSavePath = GetAppSetting("Detector:SavePath", "D:\\XPData\\DetectorImages");
DetectorAutoSave = GetBoolAppSetting("Detector:AutoSave", true);
MainViewportRealtimeEnabledDefault = GetBoolAppSetting("MainViewport:RealtimeEnabledDefault", true);
@@ -337,7 +337,7 @@ namespace XplorePlane.ViewModels.Setting
PlcBulkReadIntervalMs = GetIntAppSetting("Plc:BulkReadIntervalMs", 250);
// Dump配置
- DumpStoragePath = GetAppSetting("Dump:StoragePath", "D:\\XplorePlane\\Dump");
+ DumpStoragePath = GetAppSetting("Dump:StoragePath", "D:\\XPData\\Dump");
DumpEnableScheduledDump = GetBoolAppSetting("Dump:EnableScheduledDump", false);
DumpScheduledIntervalMinutes = GetIntAppSetting("Dump:ScheduledIntervalMinutes", 60);
DumpRetentionDays = GetIntAppSetting("Dump:RetentionDays", 7);