NavisworksTransport/doc/bugfixes/数据库兼容性_剖面盒导出修复报告.md

106 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据库兼容性 / 剖面盒导出修复报告
## 修复目标
1. 打开旧版本数据库时崩溃schema 不兼容)
2. NWF 多文档剖面盒导出时,无命中子树泄露到导出文件
3. 反复剖面盒导出后崩溃COM 跨线程访问)
4. 导出后剖面盒被关闭,状态栏按钮不同步
---
## 问题一:数据库 schema 不兼容导致启动崩溃
### 现象
打开带有旧版本 `.db` 文件的模型时,插件初始化报错:
```
SQL logic error: no such column: DetectionRecordId
```
### 根因
`CreateTables()` 使用 `CREATE TABLE IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS` 组合。旧数据库表已存在但 schema 是旧版(缺 `DetectionRecordId` 列),`CREATE TABLE IF NOT EXISTS` 静默跳过,紧随的 `CREATE INDEX ... ON ...(DetectionRecordId)` 直接炸。
同时 `PathDatabase.InitializeDatabase()` 还有以下问题:
- `PRAGMA user_version` 只写入、从未读取
- `CreateTables()` 无异常保护
- `BatchQueueItems``ALTER TABLE ADD COLUMN` 用裸 `try-catch` 吞异常
- `PathPlanningManager.DatabaseInitialize()``catch``throw;` 导致同一错误双重日志
### 修复
**PathDatabase.cs**
- 新增 `SafeCreateIndex()` 方法:建索引前用 `PRAGMA table_info` 检查列是否存在,缺列记 warning 跳过,不崩
- 新增 `EnsureColumnExists()` 方法:用 `PRAGMA table_info` 检查列,缺了才 `ALTER TABLE ADD COLUMN`,不吞其他异常
- 删除无用的 `PRAGMA user_version` 写入
- `InitializeDatabase()` 内用 `try-catch` 包裹 `CreateTables()` + `EnsurePathRoutesTableExtended()`,失败时关闭连接
- 清理注释中重复/杂乱的编号
- `CollisionDetectionRecords` 建表处加外键依赖注释
**PathPlanningManager.cs**
- 去掉 `catch` 后的 `throw;`,外层 `OnModelsCollectionChanged` 已有独立日志
---
## 问题二NWF 多文档剖面盒导出时空白子树泄露
### 现象
NWF 文件引用多个 NWD各为一个独立 `Model`),剖面盒只覆盖其中一个子树的元素,导出后其他平行子树仍然出现在 NWD 中。
### 根因
`SectionBoxExporter.CalculateHiddenItems()` 通过"兄弟节点算法"确定隐藏项:收集可见项(剖面盒内元素及其祖先)的父节点,隐藏同父节点下的不可见兄弟。当模型有多个平行 `RootItem`(来自不同 `Model`)时,完全空白的子树没有任何节点进入 `visibleSet`,其 `RootItem` 不会出现在 `uniqueParents` 中,整棵子树被遗漏。
### 修复
**SectionBoxExporter.GetObjectsAndHiddenItems()**
`CalculateHiddenItems()` 之后补一步——遍历所有 `document.Models``RootItem`,不在 `visibleSet` 中的直接加入 `ItemsToHide`。`SetHidden` 会级联隐藏所有后代,无需递归。
---
## 问题三:反复剖面盒导出崩溃
### 现象
连续多次"设置剖面盒 → 导出"操作,前几次正常,后续某次崩溃(无 managed 异常日志)。
### 根因
`LayerManagementViewModel` 中有两处不必要的 `await Task.Run()`
- `GetObjectsAndHiddenItems()` 被包在 `Task.Run` 中,在后台线程调用 Navisworks COM API`Model.HasGeometry`、`BoundingBox()` 等)
- `NwdExportHelper.ExportToNwdWithPrecomputedHiddenItems()` 同样被包在 `Task.Run`
Navisworks COM API 要求 STA 线程访问,跨线程调用在少量使用时不崩,多次使用后触发 STA 违规导致进程崩溃。
### 修复
**LayerManagementViewModel.cs**
- 去掉 `GetObjectsAndHiddenItems` 外的 `await Task.Run()` 包装,直接在 UI 线程调用
- 去掉 `ExportToNwdWithPrecomputedHiddenItems` 外的 `await Task.Run()` 包装,该方法内部已有 `Dispatcher.Invoke`,无需外层再切换线程
---
## 涉及文件
| 文件 | 改动 |
|------|------|
| `src/Core/PathDatabase.cs` | 新增 `SafeCreateIndex`、`EnsureColumnExists``InitializeDatabase` 加 try-catch删除 user_version清理注释 |
| `src/Core/PathPlanningManager.cs` | 去掉 `DatabaseInitialize` catch 中的 re-throw |
| `src/Core/SectionBoxExporter.cs` | `GetObjectsAndHiddenItems` 补空白 RootItem 隐藏逻辑 |
| `src/Utils/NwdExportHelper.cs` | 调试日志(已清理) |
| `src/Utils/VisibilityHelper.cs` | 调试日志(已清理) |
| `src/UI/WPF/ViewModels/LayerManagementViewModel.cs` | 去掉两处 `Task.Run` |
| `deploy-plugin.bat` | `powershell``pwsh`(兼容环境) |
| `AGENTS.md` | 补充编译/部署调用方式说明 |
| `src/Utils/SectionClipHelper.cs` | 新增 `RestoreClipBox` 公开方法 |
---
## 问题四:导出后剖面盒被关闭,状态栏按钮不同步
### 现象
导出剖面盒后Navisworks `ExportToNwd` 内部会关闭剖分功能,但状态栏两个剖面盒图标按钮仍保持激活状态。
### 根因
`ExportToNwd` 是 Navisworks 内部行为,绕过我们的 `SetClipBoxState`。ViewModel 的 `IsClipBoxEnabled`/`IsSelectionClipBoxEnabled` 未感知到变化。
### 修复
**VisibilityHelper.ExecuteWithPrecomputedHiddenItems**
导出前用 `SectionClipHelper.IsClipBoxEnabled` + `TryGetCurrentClipBox` 保存剖面盒状态,导出后检查并在被关闭时恢复。
**SectionClipHelper**
新增 `RestoreClipBox(BoundingBox3D)` 公开方法。