diff --git a/README.md b/README.md
index ca86f50..6d8de7a 100644
--- a/README.md
+++ b/README.md
@@ -106,5 +106,5 @@ dotnet build XplorePlane.sln -c Release
- [x] 相机实时影像集成(连接、采集、Live View、像素坐标显示)
- [x] 相机参数设置对话框(曝光、增益、分辨率、像素格式)
- [x] 主界面硬件栏相机设置按钮
-- [ ] 打通与硬件层的调用流程
-- [ ] 打通与图像层的调用流程
+- [x] 打通与硬件层的调用流程
+- [x] 打通与图像层的调用流程
diff --git a/XplorePlane/Doc/CNC多检测结果归档.md b/XplorePlane/Doc/CNC多检测结果归档.md
new file mode 100644
index 0000000..fd167f3
--- /dev/null
+++ b/XplorePlane/Doc/CNC多检测结果归档.md
@@ -0,0 +1,505 @@
+# CNC 多检测结果归档与报告取数说明
+
+## 1. 目标
+
+为 CNC 执行结果提供一套适合报告模块直接取数的归档结构。
+
+设计目标:
+
+- 以“一次工件检测实例”作为主归档单位
+- 同时保留到“检测节点级别”的明细
+- 支持保存:
+ - CNC 程序名
+ - 工件号 / 序列号
+ - 检测节点信息
+ - 节点使用的 Pipeline / 配方快照
+ - 原图、节点输入图、节点最终结果图
+ - 节点输出的多个数值结果
+ - 节点判定和整次实例判定
+- 方便后续报告模块直接读取,不依赖运行时最新配方
+
+当前实现采用:
+
+- SQLite 保存结构化索引数据
+- 文件系统保存图片资产和 `manifest.json`
+
+---
+
+## 2. 总体设计
+
+一次检测实例会生成:
+
+1. 一组数据库记录
+2. 一组文件目录和图像文件
+3. 一份 `manifest.json` 快照文件
+
+归档核心对象:
+
+- `InspectionRunRecord`
+ - 一次完整检测实例
+- `InspectionNodeResult`
+ - 一个 CNC 检测节点的结果
+- `InspectionMetricResult`
+ - 节点输出的数值结果
+- `InspectionAssetRecord`
+ - 图像或附件索引
+- `PipelineExecutionSnapshot`
+ - 节点执行时使用的 Pipeline 快照
+
+默认图片保留策略:
+
+- 整次实例原图
+- 每个节点的输入图
+- 每个节点的最终结果图
+
+不默认保存每个算法步骤的中间图。
+
+---
+
+## 3. 文件存储结构
+
+### 3.1 根目录
+
+默认根目录:
+
+```text
+%AppData%\XplorePlane\InspectionResults
+```
+
+每次检测实例按日期和 `RunId` 分层:
+
+```text
+Results/{yyyy}/{MM}/{dd}/{RunId}/
+```
+
+### 3.2 示例目录
+
+假设:
+
+- `ProgramName = NewCncProgram`
+- `WorkpieceId = QFN_1`
+- `SerialNumber = SN-001`
+- `RunId = 7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a`
+- 检测节点共 2 个
+
+则文件结构大致为:
+
+```text
+%AppData%\XplorePlane\InspectionResults\
+└─ Results\
+ └─ 2026\
+ └─ 04\
+ └─ 21\
+ └─ 7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a\
+ ├─ manifest.json
+ ├─ run\
+ │ └─ source.bmp
+ └─ nodes\
+ ├─ 001_检测节点1\
+ │ ├─ input.bmp
+ │ └─ result_overlay.bmp
+ └─ 002_检测节点2\
+ └─ result_overlay.bmp
+```
+
+### 3.3 文件说明
+
+- `run/source.bmp`
+ - 本次工件检测实例的原始输入图
+- `nodes/001_检测节点1/input.bmp`
+ - 节点 1 输入图
+- `nodes/001_检测节点1/result_overlay.bmp`
+ - 节点 1 最终结果图
+- `nodes/002_检测节点2/result_overlay.bmp`
+ - 节点 2 最终结果图
+- `manifest.json`
+ - 本次检测完整快照,便于离线查看、调试和导出
+
+---
+
+## 4. 数据库表设计
+
+当前实现包含 5 张主表。
+
+### 4.1 `inspection_runs`
+
+用途:保存一次完整检测实例的主记录。
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| `run_id` | `TEXT` | 主键,检测实例 ID,GUID |
+| `program_name` | `TEXT` | CNC 程序名 |
+| `workpiece_id` | `TEXT` | 工件号 |
+| `serial_number` | `TEXT` | 序列号 |
+| `started_at` | `TEXT` | 开始时间,ISO 8601 |
+| `completed_at` | `TEXT` | 结束时间,ISO 8601,可空 |
+| `overall_pass` | `INTEGER` | 整体判定,`0/1` |
+| `source_image_path` | `TEXT` | 原图相对路径 |
+| `result_root_path` | `TEXT` | 本次结果包根目录相对路径 |
+| `node_count` | `INTEGER` | 节点数量 |
+
+样例数据:
+
+| run_id | program_name | workpiece_id | serial_number | started_at | completed_at | overall_pass | source_image_path | result_root_path | node_count |
+|---|---|---|---|---|---|---:|---|---|---:|
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `NewCncProgram` | `QFN_1` | `SN-001` | `2026-04-21T10:00:00.0000000Z` | `2026-04-21T10:00:03.2000000Z` | `0` | `Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a/run/source.bmp` | `Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `2` |
+
+### 4.2 `inspection_node_results`
+
+用途:保存一次检测实例中的节点级结果。
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| `run_id` | `TEXT` | 所属检测实例 ID |
+| `node_id` | `TEXT` | 节点 ID,GUID |
+| `node_index` | `INTEGER` | 节点序号 |
+| `node_name` | `TEXT` | 节点名称 |
+| `pipeline_id` | `TEXT` | Pipeline ID,GUID |
+| `pipeline_name` | `TEXT` | Pipeline 名称 |
+| `pipeline_version_hash` | `TEXT` | Pipeline 快照 hash |
+| `node_pass` | `INTEGER` | 节点判定,`0/1` |
+| `source_image_path` | `TEXT` | 节点输入图相对路径 |
+| `result_image_path` | `TEXT` | 节点结果图相对路径 |
+| `status` | `TEXT` | 节点状态:`Succeeded / Failed / PartialSuccess / AssetMissing` |
+| `duration_ms` | `INTEGER` | 节点耗时 |
+
+样例数据:
+
+| run_id | node_id | node_index | node_name | pipeline_name | pipeline_version_hash | node_pass | source_image_path | result_image_path | status | duration_ms |
+|---|---|---:|---|---|---|---:|---|---|---|---:|
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `11111111-1111-1111-1111-111111111111` | `1` | `检测节点1` | `Recipe-A` | `A1B2C3...` | `1` | `Results/2026/04/21/.../nodes/001_检测节点1/input.bmp` | `Results/2026/04/21/.../nodes/001_检测节点1/result_overlay.bmp` | `Succeeded` | `135` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `22222222-2222-2222-2222-222222222222` | `2` | `检测节点2` | `Recipe-B` | `D4E5F6...` | `0` | `` | `Results/2026/04/21/.../nodes/002_检测节点2/result_overlay.bmp` | `Failed` | `240` |
+
+### 4.3 `inspection_metric_results`
+
+用途:保存节点输出的结构化数值结果。
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| `run_id` | `TEXT` | 所属检测实例 ID |
+| `node_id` | `TEXT` | 所属节点 ID |
+| `metric_key` | `TEXT` | 指标 key |
+| `metric_name` | `TEXT` | 指标名称 |
+| `metric_value` | `REAL` | 指标值 |
+| `unit` | `TEXT` | 单位 |
+| `lower_limit` | `REAL` | 下限,可空 |
+| `upper_limit` | `REAL` | 上限,可空 |
+| `is_pass` | `INTEGER` | 单指标判定,`0/1` |
+| `display_order` | `INTEGER` | 展示顺序 |
+
+样例数据:
+
+| run_id | node_id | metric_key | metric_name | metric_value | unit | lower_limit | upper_limit | is_pass | display_order |
+|---|---|---|---|---:|---|---:|---:|---:|---:|
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `11111111-1111-1111-1111-111111111111` | `bridge.rate` | `Bridge Rate` | `0.12` | `%` | | `0.2` | `1` | `1` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `11111111-1111-1111-1111-111111111111` | `void.area` | `Void Area` | `5.6` | `px` | | `8` | `1` | `2` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `22222222-2222-2222-2222-222222222222` | `solder.height` | `Solder Height` | `1.7` | `mm` | `1.8` | | `0` | `1` |
+
+### 4.4 `inspection_assets`
+
+用途:保存文件资产索引。
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| `run_id` | `TEXT` | 所属检测实例 ID |
+| `node_id` | `TEXT` | 所属节点 ID,可空 |
+| `asset_type` | `TEXT` | 资产类型 |
+| `relative_path` | `TEXT` | 相对路径 |
+| `file_format` | `TEXT` | 文件格式 |
+| `width` | `INTEGER` | 宽度 |
+| `height` | `INTEGER` | 高度 |
+
+约定的 `asset_type`:
+
+- `RunSourceImage`
+- `NodeInputImage`
+- `NodeResultImage`
+
+样例数据:
+
+| run_id | node_id | asset_type | relative_path | file_format | width | height |
+|---|---|---|---|---|---:|---:|
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | | `RunSourceImage` | `Results/2026/04/21/.../run/source.bmp` | `bmp` | `0` | `0` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `11111111-1111-1111-1111-111111111111` | `NodeInputImage` | `Results/2026/04/21/.../nodes/001_检测节点1/input.bmp` | `bmp` | `0` | `0` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `11111111-1111-1111-1111-111111111111` | `NodeResultImage` | `Results/2026/04/21/.../nodes/001_检测节点1/result_overlay.bmp` | `bmp` | `0` | `0` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `22222222-2222-2222-2222-222222222222` | `NodeResultImage` | `Results/2026/04/21/.../nodes/002_检测节点2/result_overlay.bmp` | `bmp` | `0` | `0` |
+
+### 4.5 `pipeline_execution_snapshots`
+
+用途:保存节点执行时的 Pipeline 快照,避免后续配方修改影响历史报告。
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| `run_id` | `TEXT` | 所属检测实例 ID |
+| `node_id` | `TEXT` | 所属节点 ID |
+| `pipeline_name` | `TEXT` | Pipeline 名称 |
+| `pipeline_definition_json` | `TEXT` | Pipeline 序列化 JSON |
+| `pipeline_hash` | `TEXT` | Pipeline JSON 的 SHA-256 |
+
+样例数据:
+
+| run_id | node_id | pipeline_name | pipeline_hash |
+|---|---|---|---|
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `11111111-1111-1111-1111-111111111111` | `Recipe-A` | `A1B2C3...` |
+| `7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a` | `22222222-2222-2222-2222-222222222222` | `Recipe-B` | `D4E5F6...` |
+
+---
+
+## 5. `manifest.json` 示例
+
+每次 `CompleteRunAsync` 后,会在结果包目录下生成 `manifest.json`。
+
+示例:
+
+```json
+{
+ "Run": {
+ "RunId": "7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a",
+ "ProgramName": "NewCncProgram",
+ "WorkpieceId": "QFN_1",
+ "SerialNumber": "SN-001",
+ "StartedAt": "2026-04-21T10:00:00.0000000Z",
+ "CompletedAt": "2026-04-21T10:00:03.2000000Z",
+ "OverallPass": false,
+ "SourceImagePath": "Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a/run/source.bmp",
+ "ResultRootPath": "Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a",
+ "NodeCount": 2
+ },
+ "Nodes": [
+ {
+ "RunId": "7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a",
+ "NodeId": "11111111-1111-1111-1111-111111111111",
+ "NodeIndex": 1,
+ "NodeName": "检测节点1",
+ "PipelineName": "Recipe-A",
+ "PipelineVersionHash": "A1B2C3...",
+ "NodePass": true,
+ "SourceImagePath": "Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a/nodes/001_检测节点1/input.bmp",
+ "ResultImagePath": "Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a/nodes/001_检测节点1/result_overlay.bmp",
+ "Status": 0,
+ "DurationMs": 135
+ },
+ {
+ "RunId": "7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a",
+ "NodeId": "22222222-2222-2222-2222-222222222222",
+ "NodeIndex": 2,
+ "NodeName": "检测节点2",
+ "PipelineName": "Recipe-B",
+ "PipelineVersionHash": "D4E5F6...",
+ "NodePass": false,
+ "SourceImagePath": "",
+ "ResultImagePath": "Results/2026/04/21/7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a/nodes/002_检测节点2/result_overlay.bmp",
+ "Status": 1,
+ "DurationMs": 240
+ }
+ ],
+ "Metrics": [
+ {
+ "RunId": "7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a",
+ "NodeId": "11111111-1111-1111-1111-111111111111",
+ "MetricKey": "bridge.rate",
+ "MetricName": "Bridge Rate",
+ "MetricValue": 0.12,
+ "Unit": "%",
+ "LowerLimit": null,
+ "UpperLimit": 0.2,
+ "IsPass": true,
+ "DisplayOrder": 1
+ },
+ {
+ "RunId": "7d7d8d7d-1234-4567-89ab-9f0e1d2c3b4a",
+ "NodeId": "22222222-2222-2222-2222-222222222222",
+ "MetricKey": "solder.height",
+ "MetricName": "Solder Height",
+ "MetricValue": 1.7,
+ "Unit": "mm",
+ "LowerLimit": 1.8,
+ "UpperLimit": null,
+ "IsPass": false,
+ "DisplayOrder": 1
+ }
+ ]
+}
+```
+
+说明:
+
+- `manifest.json` 是文件侧的完整快照
+- SQLite 是主索引
+- 报告模块可以优先查库,再按需读取文件
+
+---
+
+## 6. 报告模块如何取数
+
+### 6.1 首页列表 / 历史查询
+
+建议通过:
+
+- `inspection_runs`
+- 必要时联查 `inspection_node_results`
+
+可支持筛选条件:
+
+- 时间范围
+- 程序名
+- 工件号
+- 序列号
+- Pipeline 名称
+
+### 6.2 单份报告生成
+
+建议按 `RunId` 调用:
+
+- `GetRunDetailAsync(runId)`
+
+得到:
+
+- `Run`
+- `Nodes`
+- `Metrics`
+- `Assets`
+- `PipelineSnapshots`
+
+即可直接组装报告:
+
+- 报告首页
+ - 工件号、序列号、程序名、开始/结束时间、整体判定
+- 节点章节
+ - 节点名称
+ - 配方名
+ - 结果图
+ - 关键指标值
+ - 节点判定
+- 追溯信息
+ - Pipeline 快照 hash
+ - 原图路径
+ - 结果图路径
+
+### 6.3 离线导出
+
+若后续需要将单个检测实例导出给第三方或留档,可直接复制:
+
+- 整个 `Results/{yyyy}/{MM}/{dd}/{RunId}` 目录
+
+这样会同时带走:
+
+- `manifest.json`
+- 原图
+- 节点图
+
+---
+
+## 7. 当前实现接口
+
+当前服务接口:
+
+- `BeginRunAsync(...)`
+ - 创建实例记录和结果目录
+- `AppendNodeResultAsync(...)`
+ - 写入节点结果、指标、图片索引、Pipeline 快照
+- `CompleteRunAsync(...)`
+ - 回填结束时间、整体判定,并写出 `manifest.json`
+- `QueryRunsAsync(...)`
+ - 查询检测实例列表
+- `GetRunDetailAsync(...)`
+ - 查询单个实例的完整报告数据
+
+当前 DI 注册:
+
+- `IInspectionResultStore -> InspectionResultStore`
+
+---
+
+## 8. 设计约束与说明
+
+### 8.1 为什么不直接扩展 `MeasurementDataService`
+
+因为原有 `MeasurementRecord` 只适合:
+
+- 单值统计
+- 简单的 pass/fail 汇总
+
+它不适合承载:
+
+- 多节点
+- 多图像
+- 多指标
+- Pipeline 快照
+- 报告导出
+
+所以当前设计中:
+
+- `MeasurementDataService` 继续保留给旧统计用途
+- `InspectionResultStore` 作为报告归档主通道
+
+### 8.2 为什么图片不直接进 SQLite
+
+因为图片数据量大,直接入库会带来:
+
+- 数据库膨胀
+- 查询性能下降
+- 迁移和备份成本变高
+
+因此使用:
+
+- SQLite 存索引
+- 文件系统存图片
+
+这是更适合报告场景的折中方案。
+
+### 8.3 为什么要保存 Pipeline 快照
+
+因为报告要可追溯。
+
+如果只保存 `PipelineName`,后续配方被修改后,历史报告就无法复原当时的真实算法链。
+因此需要保存:
+
+- `pipeline_definition_json`
+- `pipeline_hash`
+
+---
+
+## 9. 后续可扩展方向
+
+后续可继续扩展:
+
+1. 增加 `manifest.json` 中的设备上下文
+ - 运动位置
+ - 射线源状态
+ - 探测器状态
+
+2. 增加中间图可选保留策略
+ - 默认关闭
+ - 调试模式开启
+
+3. 增加结果导出包
+ - ZIP 打包
+ - 单份报告 PDF
+
+4. 增加报告模板字段映射
+ - 将 `MetricKey` 映射到报告模板占位符
+
+5. 增加数据清理策略
+ - 保留天数
+ - 自动清理旧图片
+ - 保留数据库索引或同时删除
+
+---
+
+## 10. 结论
+
+当前这套归档设计的核心特点是:
+
+- 以“检测实例”为主组织数据
+- 以“检测节点”为明细展开
+- 以“结构化指标 + 图片文件 + Pipeline 快照”支撑报告
+- 通过 SQLite 和文件系统混合存储兼顾查询效率和图片落盘
+
+对于后续报告模块,这套结构已经可以直接支持:
+
+- 历史列表查询
+- 单次检测报告生成
+- 结果图展示
+- 节点级指标展示
+- 历史结果可追溯
diff --git a/XplorePlane/Views/Main/MainWindow.xaml b/XplorePlane/Views/Main/MainWindow.xaml
index 33b6ec6..2e0f475 100644
--- a/XplorePlane/Views/Main/MainWindow.xaml
+++ b/XplorePlane/Views/Main/MainWindow.xaml
@@ -472,7 +472,7 @@
-
+
@@ -500,7 +500,7 @@
-
+