diff --git a/doc/architecture/System_Architecture_Design.md b/doc/architecture/System_Architecture_Design.md new file mode 100644 index 0000000..a6a0827 --- /dev/null +++ b/doc/architecture/System_Architecture_Design.md @@ -0,0 +1,777 @@ +# NavisworksTransport 系统架构设计方案 + +## 项目概述 + +NavisworksTransport是一款专为Navisworks 2026平台开发的智能物流路径规划插件,旨在为建筑工程领域提供专业的BIM模型内运输路径优化、碰撞检测和施工模拟解决方案。 + +--- + +## 3.2.2.1 业务架构 + +### 业务目标与价值主张 + +NavisworksTransport插件致力于解决建筑施工过程中的物流运输规划难题,通过智能化的路径规划和碰撞检测技术,提升施工效率,降低运输成本,确保施工安全。 + +### 核心业务能力 + +#### 1. 智能路径规划服务 + +- **自动路径生成**: 基于A*算法的智能路径自动规划 +- **手动路径编辑**: 支持用户自定义路径调整和优化 +- **多楼层连接**: 跨楼层路径规划和垂直交通整合 +- **路径可行性分析**: 实时路径验证和可行性评估 + +#### 2. 碰撞检测与冲突管理 + +- **实时碰撞检测**: 动态监测运输路径中的潜在冲突 +- **静态障碍物识别**: 自动识别和标记固定障碍物 +- **动态冲突预警**: 多对象运输时的冲突预警机制 +- **碰撞报告生成**: 详细的碰撞分析报告和解决方案建议 + +#### 3. 动画仿真与可视化 + +- **物流运输模拟**: 真实的运输过程动画演示 +- **时间轴精确控制**: 基于TimeLiner的精确时间控制 +- **多级速度调节**: 灵活的播放速度控制 +- **多对象协同**: 支持多个物流对象的协同动画 + +#### 4. 模型智能管理 + +- **楼层智能识别**: 自动识别和分类模型楼层结构 +- **分层管理系统**: 基于属性的模型分层组织 +- **物流类别标注**: 八大物流类别的智能标注系统 +- **模型分割导出**: 按需模型分割和独立导出功能 + +### 业务流程设计 + +```mermaid +graph LR + A[选择起点] --> B[设置终点] + B --> C[自动路径规划] + C --> D[碰撞检测分析] + D --> E[路径优化调整] + E --> F[动画仿真演示] + F --> G[结果导出报告] + + D --> H[发现冲突] + H --> I[冲突解决方案] + I --> E +``` + +### 物流分类体系 + +基于建筑物流的实际需求,定义八大核心物流类别: + +1. **门 (Doors)**: 进出口通道管理 +2. **电梯 (Elevators)**: 垂直运输通道 +3. **楼梯 (Stairs)**: 人工垂直通道 +4. **通道 (Channels)**: 水平运输走廊 +5. **障碍物 (Obstacles)**: 固定阻碍物体 +6. **装卸区 (Loading Zones)**: 材料装卸区域 +7. **停车区 (Parking)**: 临时停靠区域 +8. **检查点 (Checkpoints)**: 质检和验收点 + +--- + +## 3.2.2.2 应用架构 + +### 总体架构设计 + +NavisworksTransport采用分层式架构设计,确保系统的可维护性、可扩展性和稳定性: + +``` +┌─────────────────────────────────────────────────────────┐ +│ 表现层 (Presentation) │ +│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │ +│ │ WPF MVVM │ │ WinForms │ │ Ribbon UI │ │ +│ │ 现代化界面 │ │ 传统对话框 │ │ 工具栏集成 │ │ +│ └─────────────┘ └──────────────┘ └─────────────────┘ │ +├─────────────────────────────────────────────────────────┤ +│ 业务逻辑层 (Business) │ +│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │ +│ │ 路径规划引擎 │ │ 碰撞检测器 │ │ 动画管理器 │ │ +│ │ A*算法集成 │ │ 实时冲突检测 │ │ TimeLiner集成 │ │ +│ └─────────────┘ └──────────────┘ └─────────────────┘ │ +├─────────────────────────────────────────────────────────┤ +│ 核心服务层 (Core) │ +│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │ +│ │ 状态管理器 │ │ 事件总线 │ │ 日志服务 │ │ +│ │ UI线程安全 │ │ 组件通信 │ │ 异常处理 │ │ +│ └─────────────┘ └──────────────┘ └─────────────────┘ │ +├─────────────────────────────────────────────────────────┤ +│ 数据访问层 (Data) │ +│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │ +│ │ JSON序列化 │ │ XML导出 │ │ Navisworks API │ │ +│ │ 路径数据 │ │ 配置管理 │ │ COM API集成 │ │ +│ └─────────────┘ └──────────────┘ └─────────────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +### 三重插件架构模式 + +NavisworksTransport创新性地采用三重插件协同工作模式: + +#### 1. MainPlugin (主插件) + +- **类型**: AddInPlugin +- **职责**: 主界面管理、Ribbon集成、DockPane控制 +- **特点**: 插件生命周期管理、全局状态维护 + +#### 2. PathClickToolPlugin (交互插件) + +- **类型**: ToolPlugin +- **职责**: 3D场景交互、鼠标点击事件、路径点设置 +- **特点**: 实时用户交互响应、空间坐标计算 + +#### 3. PathPointRenderPlugin (渲染插件) + +- **类型**: RenderPlugin +- **职责**: 3D路径可视化、覆盖层渲染、动画效果 +- **特点**: 高性能图形渲染、实时视觉反馈 + +### 核心管理器组件 + +#### PathPlanningManager (路径规划管理器) + +```csharp +public class PathPlanningManager +{ + // 路径规划核心功能 + public PathRoute PlanRoute(Point3D start, Point3D end); + public ValidationResult ValidatePath(PathRoute route); + public PathRoute OptimizePath(PathRoute route); + + // 事件驱动架构 + public event EventHandler PathGenerated; + public event EventHandler CollisionDetected; +} +``` + +#### LogisticsAnimationManager (动画管理器) + +- **动画控制**: 播放、暂停、停止、速度调节 +- **多对象协调**: 多个物流对象的同步动画 +- **时间轴集成**: 与Navisworks TimeLiner深度集成 +- **碰撞处理**: 动画过程中的实时碰撞检测 + +#### UIStateManager (UI状态管理器) + +```csharp +public class UIStateManager +{ + // 线程安全的UI更新 + public async Task ExecuteUIUpdateAsync(Action updateAction); + + // 批量UI更新优化 + public void QueueUIUpdate(Action updateAction, UIUpdatePriority priority); + + // 状态同步机制 + public void SynchronizeViewModels(); +} +``` + +### MVVM架构实现 + +采用标准MVVM模式实现UI与业务逻辑分离: + +- **Model**: PathRoute, PathPoint, LogisticsObject等数据模型 +- **View**: WPF用户控件、窗口、对话框 +- **ViewModel**: 数据绑定、命令处理、业务逻辑调用 + +--- + +## 3.2.2.3 数据架构 + +### 核心数据模型设计 + +#### 路径数据模型 + +```csharp +/// +/// 路径路由数据模型 +/// +public class PathRoute +{ + public Guid Id { get; set; } // 唯一标识 + public string Name { get; set; } // 路径名称 + public List Points { get; set; } // 路径点集合 + public PathValidationResult Validation { get; set; } // 验证结果 + public DateTime CreateTime { get; set; } // 创建时间 + public DateTime ModifyTime { get; set; } // 修改时间 + public Dictionary Metadata { get; set; } // 元数据扩展 + + // 路径统计信息 + public double TotalDistance { get; set; } // 总距离 + public TimeSpan EstimatedDuration { get; set; } // 预估用时 + public List Collisions { get; set; } // 碰撞信息 +} +``` + +#### 路径点模型 + +```csharp +/// +/// 路径点数据模型 +/// +public class PathPoint +{ + public Point3D Position { get; set; } // 3D坐标 + public int SequenceNumber { get; set; } // 序列号 + public string Floor { get; set; } // 所属楼层 + public PathPointType Type { get; set; } // 点类型 + public List ConnectedNodes { get; set; } // 连接节点 + + // 扩展属性 + public double Height { get; set; } // 高度信息 + public double Width { get; set; } // 通道宽度 + public Dictionary Attributes { get; set; } // 自定义属性 +} +``` + +#### 物流对象模型 + +```csharp +/// +/// 物流对象数据模型 +/// +public class LogisticsObject +{ + public string Id { get; set; } // 对象标识 + public LogisticsCategory Category { get; set; } // 物流类别 + public BoundingBox3D Bounds { get; set; } // 边界框 + public Transform3D Transform { get; set; } // 变换矩阵 + public ModelItem NavisworksItem { get; set; } // Navisworks项引用 + + // 物流属性 + public double Capacity { get; set; } // 容量 + public double MaxSpeed { get; set; } // 最大速度 + public List Restrictions { get; set; } // 使用限制 + public Dictionary Properties { get; set; } // 扩展属性 +} +``` + +### 数据持久化策略 + +#### 1. 主数据存储 (JSON格式) + +```json +{ + "projectInfo": { + "name": "物流路径规划项目", + "version": "1.0", + "createTime": "2024-01-01T00:00:00Z" + }, + "pathRoutes": [ + { + "id": "route-001", + "name": "主通道路径", + "points": [ + { + "position": {"x": 100.0, "y": 200.0, "z": 0.0}, + "sequenceNumber": 1, + "floor": "F1", + "type": "StartPoint" + } + ], + "metadata": { + "totalDistance": 150.5, + "estimatedDuration": "00:05:30" + } + } + ] +} +``` + +#### 2. 配置数据存储 (XML格式) + +```xml + + + 2.0 + 0.5 + 30 + + + Info + true + 300 + + +``` + +#### 3. 缓存数据管理 + +- **内存缓存**: 碰撞检测结果、网格地图数据 +- **会话缓存**: 用户操作历史、临时路径数据 +- **持久缓存**: 楼层识别结果、模型分析数据 + +### 数据交换标准 + +#### 导入支持格式 + +- **JSON**: 路径数据、项目配置 +- **CSV**: 批量路径点、统计数据 +- **XML**: 配置文件、报告模板 + +#### 导出支持格式 + +- **NWD**: Navisworks文档格式 +- **JSON**: 标准数据交换格式 +- **Excel**: 统计报告和分析数据 +- **PDF**: 项目报告和文档 +- **CSV**: 数据分析和进一步处理 + +### 数据安全与完整性 + +#### 数据校验机制 + +```csharp +public class DataValidator +{ + public ValidationResult ValidatePathRoute(PathRoute route) + { + // 路径完整性检查 + // 坐标有效性验证 + // 序列号连续性验证 + // 楼层一致性检查 + } + + public bool VerifyDataIntegrity(string filePath) + { + // 文件完整性校验 + // 数据格式验证 + // 版本兼容性检查 + } +} +``` + +#### 数据备份策略 + +- **自动备份**: 定时保存项目数据 +- **增量备份**: 只保存变更的数据 +- **版本控制**: 保留历史版本便于回滚 +- **云端同步**: 支持云存储备份 + +--- + +## 3.2.2.4 技术架构 + +### 技术栈选型与理由 + +#### 开发平台选择 + +- **目标平台**: Navisworks 2026 (x64) + - *理由*: 最新API支持,性能优化,功能完整 +- **运行时**: .NET Framework 4.8 + - *理由*: Navisworks 2026官方支持的运行时版本 +- **开发环境**: Visual Studio 2022 Community + - *理由*: 完整的.NET开发工具链,优秀的调试支持 + +#### 核心技术选型 + +- **编程语言**: C# 8.0 + - *理由*: 与Navisworks API完美集成,丰富的语言特性 +- **UI框架组合**: + - **WPF + MVVM**: 现代化用户界面,数据绑定优势 + - **WinForms**: 传统对话框,快速开发 + - **ElementHost**: 混合UI集成方案 + +#### 第三方库集成 + +```xml + + + + + + +``` + +### 关键技术实现 + +#### 1. 线程安全架构设计 + +**问题**: Navisworks API调用必须在主线程,多线程UI更新容易导致崩溃 + +**解决方案**: UIStateManager统一线程调度 + +```csharp +public class UIStateManager +{ + private readonly ConcurrentQueue _updateQueue; + private readonly DispatcherTimer _updateTimer; + + public async Task ExecuteUIUpdateAsync(Action updateAction) + { + if (Application.Current.Dispatcher.CheckAccess()) + { + // 已在UI线程,直接执行 + ExecuteWithExceptionHandling(updateAction); + } + else + { + // 切换到UI线程执行 + await Application.Current.Dispatcher.InvokeAsync(() => + { + ExecuteWithExceptionHandling(updateAction); + }, DispatcherPriority.Normal); + } + } + + private void ExecuteWithExceptionHandling(Action updateAction) + { + try + { + updateAction?.Invoke(); + } + catch (Exception ex) + { + GlobalExceptionHandler.HandleException(ex, "UI更新异常"); + } + } +} +``` + +#### 2. 异步编程模式 + +**事件驱动异步处理**: + +```csharp +public class PathPlanningManager +{ + public async Task PlanRouteAsync(Point3D start, Point3D end) + { + return await Task.Run(() => + { + // CPU密集型的A*算法计算 + var pathfinder = new PathFinder(gridMap); + var result = pathfinder.FindPath(start, end); + + // 在UI线程更新进度 + await uiStateManager.ExecuteUIUpdateAsync(() => + { + OnPathGenerated(new PathPlanningEventArgs(result)); + }); + + return result; + }); + } +} +``` + +#### 3. 内存管理与性能优化 + +**对象池模式**: + +```csharp +public class PathPointPool +{ + private readonly ConcurrentQueue _pool; + + public PathPoint Rent() + { + if (_pool.TryDequeue(out var point)) + { + return point; + } + return new PathPoint(); + } + + public void Return(PathPoint point) + { + point.Reset(); // 重置状态 + _pool.Enqueue(point); + } +} +``` + +**空间索引优化**: + +```csharp +public class TriangleSpatialHash +{ + private readonly Dictionary> _spatialGrid; + private readonly double _cellSize; + + public List GetNearbyTriangles(Point3D point, double radius) + { + var result = new List(); + var minCell = GetCellIndex(point.X - radius, point.Y - radius); + var maxCell = GetCellIndex(point.X + radius, point.Y + radius); + + for (int x = minCell.X; x <= maxCell.X; x++) + { + for (int y = minCell.Y; y <= maxCell.Y; y++) + { + var key = GetHashKey(x, y); + if (_spatialGrid.TryGetValue(key, out var triangles)) + { + result.AddRange(triangles); + } + } + } + + return result; + } +} +``` + +#### 4. API集成策略 + +**双API协同模式**: + +```csharp +public class NavisworksIntegration +{ + // Native API - 核心功能 + private readonly Application _nativeApp; + + // COM API - 属性持久化 + private readonly ComApi.Application _comApp; + + public void SetPersistentAttribute(ModelItem item, string key, string value) + { + try + { + // 使用COM API设置持久化属性 + var comItem = _comApp.ActiveDocument.Models.RootItem.FindItem(item.InstanceGuid); + comItem.PropertyCategories.FindPropertyByDisplayName("User", key).Value = value; + } + catch (Exception ex) + { + // 降级到Native API内存属性 + item.PropertyCategories.FindCategoryByDisplayName("User") + .Properties.FindPropertyByDisplayName(key).Value = new VariantData(value); + } + } +} +``` + +### 部署架构设计 + +#### 文件组织结构 + +``` +%ProgramFiles%\Autodesk\Navisworks Manage 2026\Plugins\ +└── NavisworksTransportPlugin\ + ├── NavisworksTransportPlugin.dll # 主程序集 + ├── RoyT.AStar.dll # A*算法库 + ├── Newtonsoft.Json.dll # JSON处理库 + ├── Resources\ # 资源文件 + │ ├── Icons\ # 图标资源 + │ ├── Templates\ # 模板文件 + │ └── Localization\ # 本地化资源 + ├── Config\ # 配置文件 + │ ├── DefaultSettings.xml # 默认设置 + │ └── LoggingConfig.xml # 日志配置 + └── Documentation\ # 文档 + ├── UserGuide.pdf # 用户指南 + └── API_Reference.pdf # API参考 +``` + +#### 安装部署流程 + +1. **环境检测**: 验证Navisworks 2026安装 +2. **权限检查**: 确认插件目录写入权限 +3. **文件部署**: 复制程序集和资源文件 +4. **注册插件**: 更新Navisworks插件注册表 +5. **配置初始化**: 创建默认配置文件 +6. **完整性验证**: 验证安装完整性 + +### 安全性架构设计 + +#### 1. 数据安全 + +```csharp +public class DataSecurity +{ + // 数据加密存储 + public void SaveEncryptedData(string filePath, object data) + { + var json = JsonConvert.SerializeObject(data); + var encrypted = EncryptionHelper.Encrypt(json, GetMachineKey()); + File.WriteAllText(filePath, encrypted); + } + + // 完整性校验 + public bool VerifyDataIntegrity(string filePath) + { + var hash = ComputeFileHash(filePath); + var storedHash = GetStoredHash(filePath + ".hash"); + return hash == storedHash; + } +} +``` + +#### 2. 运行时安全 + +- **输入验证**: 所有用户输入严格验证 +- **边界检查**: 数组访问和集合操作边界检查 +- **异常处理**: 完整的异常捕获和恢复机制 +- **资源管理**: 及时释放非托管资源 + +### 可扩展性设计 + +#### 插件化架构 + +```csharp +public interface IPathPlanningAlgorithm +{ + string Name { get; } + PathRoute PlanPath(Point3D start, Point3D end, GridMap map); +} + +public class AlgorithmManager +{ + private readonly Dictionary _algorithms; + + public void RegisterAlgorithm(IPathPlanningAlgorithm algorithm) + { + _algorithms[algorithm.Name] = algorithm; + } + + public PathRoute PlanPath(string algorithmName, Point3D start, Point3D end) + { + if (_algorithms.TryGetValue(algorithmName, out var algorithm)) + { + return algorithm.PlanPath(start, end, _currentMap); + } + throw new ArgumentException($"未找到算法: {algorithmName}"); + } +} +``` + +#### 配置驱动架构 + +```csharp +public class ConfigurationManager +{ + public T GetConfiguration(string sectionName) where T : class, new() + { + var section = _config.GetSection(sectionName); + return section.Get() ?? new T(); + } + + public void UpdateConfiguration(string sectionName, T config) + { + _config.SetSection(sectionName, config); + SaveConfiguration(); + NotifyConfigurationChanged(sectionName); + } +} +``` + +### 监控与运维架构 + +#### 1. 日志系统设计 + +```csharp +public class LogManager +{ + private static readonly ILogger _logger = LoggerFactory.CreateLogger(); + + public static void Info(string message, [CallerMemberName] string caller = "") + { + _logger.LogInformation($"[{caller}] {message}"); + } + + public static void Error(string message, Exception ex = null, [CallerMemberName] string caller = "") + { + _logger.LogError(ex, $"[{caller}] {message}"); + } + + // 性能监控 + public static IDisposable BeginScope(string operationName) + { + return _logger.BeginScope($"Operation: {operationName}"); + } +} +``` + +#### 2. 性能监控 + +```csharp +public class PerformanceMonitor +{ + private readonly Dictionary _counters; + + public void RecordOperation(string operation, TimeSpan duration) + { + var counter = GetOrCreateCounter(operation); + counter.Record(duration.TotalMilliseconds); + } + + public PerformanceReport GenerateReport() + { + return new PerformanceReport + { + Timestamp = DateTime.Now, + MemoryUsage = GC.GetTotalMemory(false), + OperationStats = _counters.ToDictionary( + kvp => kvp.Key, + kvp => kvp.Value.GetStatistics() + ) + }; + } +} +``` + +#### 3. 错误报告系统 + +```csharp +public class ErrorReporting +{ + public void ReportError(Exception ex, Dictionary context) + { + var report = new ErrorReport + { + Exception = ex, + Context = context, + Environment = GetEnvironmentInfo(), + Timestamp = DateTime.Now + }; + + // 本地保存 + SaveErrorReport(report); + + // 可选:发送到服务器 + if (UserConsents && IsOnline) + { + SendErrorReport(report); + } + } +} +``` + +--- + +## 架构优势与创新点 + +### 技术创新 + +1. **三重插件协同**: 创新的插件架构模式,各司其职,协同工作 +2. **线程安全UI管理**: 统一的UI状态管理器,解决多线程UI更新难题 +3. **双API集成**: Native API与COM API协同,功能完整性与兼容性并重 +4. **空间索引优化**: 高效的空间数据结构,提升大模型处理性能 + +### 架构优势 + +1. **高可维护性**: 分层架构,职责清晰,便于团队协作开发 +2. **强扩展性**: 插件化设计,支持功能模块热插拔 +3. **高性能**: 内存管理优化,空间索引,异步处理 +4. **高稳定性**: 完整的异常处理,线程安全设计,资源管理 + +### 商业价值 + +1. **降本增效**: 智能化路径规划,减少人工设计时间 +2. **风险控制**: 碰撞预警机制,避免施工冲突 +3. **决策支持**: 可视化动画演示,辅助方案决策 +4. **标准化**: 统一的物流分类体系,规范管理流程 + +--- + +## 结论 + +NavisworksTransport系统架构方案充分考虑了建筑工程物流管理的实际需求,结合Navisworks平台的技术特点,设计了完整的四层架构体系。该方案不仅满足当前业务需求,更具备良好的扩展性和维护性,为未来的功能增强和技术演进提供了坚实的基础。 + +通过创新的三重插件协同模式、线程安全的UI管理机制、以及高效的数据处理架构,NavisworksTransport将为建筑工程领域的数字化转型提供强有力的技术支撑。 diff --git a/doc/architecture/architecture_diagram.py b/doc/architecture/architecture_diagram.py new file mode 100644 index 0000000..7dafcd5 --- /dev/null +++ b/doc/architecture/architecture_diagram.py @@ -0,0 +1,162 @@ +import matplotlib.pyplot as plt +import matplotlib.patches as patches +from matplotlib.patches import FancyBboxPatch +import numpy as np + +# 设置中文字体 - 优先使用Microsoft YaHei +plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'DejaVu Sans'] +plt.rcParams['axes.unicode_minus'] = False + +# 创建图形 - 调整尺寸和DPI +fig, ax = plt.subplots(1, 1, figsize=(16, 12)) + +# 定义颜色方案 +colors = { + 'presentation': '#E3F2FD', # 淡蓝色 + 'business': '#E8F5E8', # 淡绿色 + 'core': '#FFF3E0', # 淡橙色 + 'data': '#F3E5F5', # 淡紫色 + 'border': '#2C3E50', # 深灰色边框 + 'text': '#2C3E50' # 深蓝灰色文字 +} + +# 层级高度和间距 - 增加高度以容纳更多文字 +layer_height = 2.2 +layer_spacing = 0.4 +component_width = 3.8 +component_height = 1.4 +component_spacing = 0.5 + +# 总宽度 +total_width = 13 +start_x = 1 + +# 绘制四个主要层级 +# 调整层级Y位置以适应新的高度 +layers = [ + { + 'name': '表现层 (Presentation)', + 'color': colors['presentation'], + 'y': 8.5, + 'components': [ + {'name': 'WPF MVVM\n现代化界面', 'desc': ''}, + {'name': 'WinForms\n传统对话框', 'desc': ''}, + {'name': 'Ribbon UI\n工具栏集成', 'desc': ''} + ] + }, + { + 'name': '业务逻辑层 (Business)', + 'color': colors['business'], + 'y': 6.0, + 'components': [ + {'name': '路径规划引擎\nA*算法集成', 'desc': ''}, + {'name': '碰撞检测器\n实时冲突检测', 'desc': ''}, + {'name': '动画管理器\nTimeLiner集成', 'desc': ''} + ] + }, + { + 'name': '核心服务层 (Core)', + 'color': colors['core'], + 'y': 3.5, + 'components': [ + {'name': '状态管理器\nUI线程安全', 'desc': ''}, + {'name': '事件总线\n组件通信', 'desc': ''}, + {'name': '日志服务\n异常处理', 'desc': ''} + ] + }, + { + 'name': '数据访问层 (Data)', + 'color': colors['data'], + 'y': 1.0, + 'components': [ + {'name': 'JSON序列化\n路径数据', 'desc': ''}, + {'name': 'XML导出\n配置管理', 'desc': ''}, + {'name': 'Navisworks API\nCOM API集成', 'desc': ''} + ] + } +] + +# 绘制每个层级 +for layer in layers: + # 绘制层级背景 + layer_rect = FancyBboxPatch( + (start_x, layer['y']), total_width, layer_height, + boxstyle="round,pad=0.1", + facecolor=layer['color'], + edgecolor=colors['border'], + linewidth=2 + ) + ax.add_patch(layer_rect) + + # 绘制层级标题 - 调整位置确保文字在框内正确显示 + ax.text(start_x + total_width/2, layer['y'] + layer_height - 0.4, + layer['name'], + ha='center', va='center', + fontsize=15, fontweight='bold', + color=colors['text']) + + # 计算组件起始位置 + total_components_width = len(layer['components']) * component_width + (len(layer['components']) - 1) * component_spacing + components_start_x = start_x + (total_width - total_components_width) / 2 + + # 绘制组件 + for i, component in enumerate(layer['components']): + comp_x = components_start_x + i * (component_width + component_spacing) + comp_y = layer['y'] + 0.2 + + # 绘制组件框 + comp_rect = FancyBboxPatch( + (comp_x, comp_y), component_width, component_height, + boxstyle="round,pad=0.05", + facecolor='white', + edgecolor=colors['border'], + linewidth=1.5 + ) + ax.add_patch(comp_rect) + + # 绘制组件文字 - 调整字体大小和位置 + ax.text(comp_x + component_width/2, comp_y + component_height/2, + component['name'], + ha='center', va='center', + fontsize=11, fontweight='normal', + color=colors['text'], + linespacing=1.2) + +# 绘制层级之间的连接线 +for i in range(len(layers) - 1): + y_start = layers[i]['y'] + y_end = layers[i+1]['y'] + layer_height + + # 绘制多条连接线表示数据流 + for j in range(3): + x_pos = start_x + total_width * (j + 1) / 4 + ax.annotate('', xy=(x_pos, y_start), xytext=(x_pos, y_end), + arrowprops=dict(arrowstyle='->', color=colors['border'], + lw=1.5, alpha=0.7)) + +# 添加架构说明 - 调整位置和字体 +ax.text(start_x + total_width + 0.5, 6.5, + '特点:\n• 分层解耦\n• 职责清晰\n• 易于维护\n• 支持扩展', + ha='left', va='center', + fontsize=12, fontweight='normal', + bbox=dict(boxstyle="round,pad=0.5", facecolor='#F8F9FA', edgecolor=colors['border']), + color=colors['text'], + linespacing=1.3) + +# 设置图形属性 - 调整范围以适应新的布局 +ax.set_xlim(0, 17) +ax.set_ylim(0, 12) +ax.set_aspect('equal') +ax.axis('off') + +# 添加标题 +plt.title('NavisworksTransport 分层架构设计', + fontsize=18, fontweight='bold', pad=20, color=colors['text']) + +# 保存图形 +plt.tight_layout() +plt.savefig(r'C:\Users\Tellme\apps\NavisworksTransport\doc\architecture\system_architecture.png', + dpi=300, bbox_inches='tight', facecolor='white', edgecolor='none') + +print("架构图已生成: system_architecture.png") +plt.show() \ No newline at end of file diff --git a/doc/architecture/system_architecture.png b/doc/architecture/system_architecture.png new file mode 100644 index 0000000..afb2e40 Binary files /dev/null and b/doc/architecture/system_architecture.png differ diff --git a/doc/design/Design_Plan.md b/doc/design/Design_Plan.md index f2cddac..cbe5a8e 100644 --- a/doc/design/Design_Plan.md +++ b/doc/design/Design_Plan.md @@ -5,16 +5,17 @@ 日期:2025-08-29 本方案依据以下输入编制: + - 需求文档:doc/requirement/user_requiement.md(以 Navisworks 2017/Windows 7 为基线) - 项目上下文与结构参考:QWEN.md(包含 Navisworks 2026 的说明,仅作补充参考) - 源代码:src 目录(核心模块:Core、PathPlanning、UI/WPF、Utils 等) 重要说明:如需求文档与 QWEN.md 在版本目标存在差异(2017 vs 2026),本方案默认以需求文档为准(Navisworks 2017)。若需面向 Navisworks 2026 的兼容性与增强功能,请在部署与验证环节中选配“2026 兼容模式”。 - 一、总体设计 1.1 背景与目标 + - 背景:在 Autodesk Navisworks 环境中进行物流路径规划、动画仿真与碰撞检查,需高效的交互式工具,支持路径点编辑、自动路径规划(复杂场景)、导航输出与结构化结果文件(XML/JSON/CSV)。 - 目标: - 快速完成通道选择与路径点规划(起点/路径点/终点),支持多路径管理与编辑; @@ -24,6 +25,7 @@ - 支持结构化结果文件输出,并满足 DELMIA 导入(按需求文档约束)。 1.2 需求综述(与需求文档对应) + - 通道选择及路径点规划:模型切分、通道选择、路径点规划、多路径管理、编辑保存与导入、路径点自动贴合; - 物流“类别”设置:新增物流属性类别、设置可通行性/速度/宽度/优先级等属性,筛选与清除; - 层级创建与显示:自动隐藏/淡化非关键层,物流元素筛选,路径时间标签; @@ -31,6 +33,7 @@ - 碰撞检查:动画生成与播放、碰撞检查/记录导出、路径规划分析与最优路径建议。 1.3 设计原则 + - 实用优先:在 Navisworks 2017 环境中保证稳定运行与较好性能; - 解耦分层:UI(WPF+MVVM)与核心逻辑(Core、PathPlanning)分离,便于后续扩展; - 向后兼容:在自动规划/碰撞集成等关键能力上提供降级路径(如 BoundingBox 模式回退); @@ -38,6 +41,7 @@ - 数据可移植:路径/结果提供 XML/JSON/CSV 序列化能力(JSON 加载简化,建议 XML 为主)。 1.4 核心用例流程概览 + - 路径编辑(手动): 1) 用户通道选择(手动/属性筛选/自动查找可通行),计算通道边界; 2) 进入编辑模式,3D 点击添加“起点/路径点/终点”,路线渲染与校验; @@ -52,10 +56,10 @@ 1) 导航控件交互产生路径; 2) 输出视频/图片与结构化结果(XML/JSON/CSV),满足 DELMIA 导入约束。 - 二、系统架构 2.1 分层架构与模块 + - UI 层(WPF + MVVM,少量 WinForms 遗留): - Views: UI/WPF/Views/*(含 PathEditingView、AnimationControlView 等) - ViewModels: UI/WPF/ViewModels/*(LogisticsControlViewModel、PathEditingViewModel 等) @@ -64,6 +68,7 @@ - PathPlanningManager:路径规划主控(事件驱动、状态机、路径可视化) - CategoryAttributeManager:物流属性管理(COM API + .NET API) - VisibilityManager:可见性与层级控制 + - Animation:TimeLinerIntegrationManager、PathAnimationManager(动画控制) - Collision:ClashDetectiveIntegration(碰撞集成,动画期缓存 + 结束时统一测试) - ModelSplitterManager:模型切分(含简化实现) @@ -74,10 +79,12 @@ - Utils:日志、坐标/单位转换、Navisworks API 辅助 2.2 系统架构图(截图占位) + - [截图占位] 系统架构图 - 要求:体现 UI(WPF+MVVM)/Core/PathPlanning/Utils 分层,以及 TimeLiner、Clash 的集成位置与事件流(PathPlanningManager 事件:StatusChanged、EditStateChanged、RouteGenerated 等)。 2.3 模块关系与数据流 + - UI 通过 ViewModel 调用 PathPlanningManager 与其他 Core 服务; - PathPlanningManager 根据通道选择与编辑状态,驱动网格生成与 A* 求解,并渲染路径标记; - Animation/Collision 订阅路径与动画状态,按批次创建 TimeLiner 任务与 Clash 测试; @@ -85,6 +92,7 @@ - VisibilityManager 提供“仅显示物流元素/隔离显示”等能力。 2.4 技术路线与选型 + - 语言/框架:C#,.NET Framework 4.8; - UI:WPF + MVVM(WinForms 仅用于部分对话框/遗留界面); - 外部 API:Autodesk Navisworks API(2017 目标),COM API(属性写入)、TimeLiner API、Clash API; @@ -93,15 +101,16 @@ - 日志/异常:LogManager、GlobalExceptionHandler。 2.5 关键数据模型(摘自源码) + - PathPoint、PathRoute:路径点/路径集合,支持类型(Start/End/WayPoint)、长度/时间统计、XML/JSON 序列化; - ChannelBounds:通道边界与 2D 投影; - PathHistoryEntry/Manager:路径历史; - 事件模型:PathPlanningStatusChangedEventArgs、PathEditStateChangedEventArgs、RouteGeneratedEventArgs 等。 - 三、功能设计方案(逐模块) 3.1 模型切分 + - 目标:对大型模型按楼层/属性进行切分,提升性能与操作体验; - UI:ModelSplitterDialog(WinForms); - Core:ModelSplitterManager、SimplifiedModelSplitterManager; @@ -111,6 +120,7 @@ - 与可见性/筛选配合以限定工作区域。 3.2 通道选择 + - 能力: - 手动选择:基于 Navisworks 选择; - 属性筛选:通过 CategoryAttributeManager.FilterByLogisticsType(FilterTraversableItems); @@ -118,6 +128,7 @@ - PathPlanningManager.SelectChannels:计算组合边界 CombinedChannelBounds 并事件广播。 3.3 路径点规划(手动 + 自动) + - 手动规划: - 工具:PathClickToolPlugin(精确拾取),PathPointRenderPlugin(3D 渲染); - 流程:切换到 Creating/Editing 状态 -> 添加点 -> 渲染 -> 校验; @@ -130,33 +141,39 @@ - 路径优化(去冗余点、直线可达校验)、2.5D 高度插值与起终点原位修正; 3.4 路径管理、编辑、保存与导入 + - 编辑:创建/编辑/取消/完成编辑(FinishEditing 自动将末点设为终点并触发渲染与事件); - 文件:PathFileSerializer(XML 主,JSON 简化,不建议作为主格式),支持多路径容器; - 历史:PathHistoryManager(Created/Edited/ManualSave 等),提供查看历史 UI; - 导入:DetectFileFormat -> LoadFromXml/LoadFromJson(JSON 加载简化,优先 XML)。 3.5 物流“类别”设置 + - 类别:为模型添加“物流属性”类别(类型、可通行、优先级、车辆尺寸、速度限制、宽度限制等); - 批量处理:Add/Update/Remove,使用 COM API 正确索引方式避免覆盖错误; - 识别筛选:FilterTraversableItems/FilterByLogisticsType/FilterPassableAreas,供通道选择与可见性使用。 3.6 层级创建与显示 + - 隐藏/淡化非关键层:VisibilityManager.HideNonLogisticsItems/ShowAllItems/IsolateSpecificItems; - 物流元素筛选:ShowLogisticsItemsOnly; - 路径时间标签:在 PathPlanningManager.CalculateEstimatedTime(当前简单估算,后续可接入速度限制)。 3.7 交互式导航 + - 交互控件:UI/WPF 侧的主面板与路径/起终点选择; - 导出:支持视频/图片占位(由用户录屏或快照)、结构化文件(XML/JSON/CSV); - DELMIA 导入:以 XML/CSV 为主,JSON 仅作参考(需要与 DELMIA 侧字段约定)。 3.8 动画生成与播放 + - TimeLinerIntegrationManager:创建运输任务(将路径关联到对象)、更新进度与状态文本、清理任务; - PathAnimationManager:具体的路径关键帧/移动输出(见 Core/Animation); - 设计要点: - 以 TimelinerTask 为主线(Navisworks 2017 可用 API 能力有限,使用显示名/选择集传递状态)。 3.9 碰撞检查 + - ClashDetectiveIntegration: - 动画过程“实时缓存”碰撞(包围盒快速判定 + 去重 + 位置快照); - 动画结束“统一创建并运行”测试(避免过程频繁创建); @@ -164,29 +181,33 @@ - 兼容性:优先 .NET Clash API,必要时绕过繁重的 COM 插件枚举。 3.10 路径规划分析 + - 汇总多条路径的碰撞结果,统计次数/距离/受影响对象; - 以“最小碰撞/最短距离/最小转弯次数”等指标推荐最优路径; - 输出分析报告(可选 CSV/XML)。 3.11 结果输出 + - 地图/路径可视化:3D 渲染 + 可截屏; - 结构化结果:XML/JSON/CSV(建议 XML/CSV 作为主导入格式到 DELMIA)。 - 四、系统部署方案 4.1 部署环境要求 + - 操作系统:Windows 7(需求文档基准),建议 Windows 10 及以上(更佳兼容性与性能); - Autodesk Navisworks:Manage 2017(需求基线)。如需 2026,请切换引用与验证用例(见下文兼容模式); - .NET Framework:4.8; - 开发工具:Visual Studio(建议 2019/2022)。 4.2 构建与产物 + - 解决方案:NavisworksTransport.sln; - 项目:NavisworksTransportPlugin.csproj; - 产物:NavisworksTransportPlugin.dll(bin/Debug 或 bin/Release)。 4.3 安装与部署流程 + - 自动安装(一键安装): 1) 识别 Navisworks 安装目录; 2) 将插件 DLL 与必要资源复制到 [Navisworks安装路径]\Plugins\NavisworksTransportPlugin\; @@ -196,12 +217,14 @@ 2) 重启 Navisworks,在“附加模块”中查看“物流路径规划”。 4.4 运行配置 + - 日志输出:%AppData%\Autodesk Navisworks Manage 2017\PluginsData\NavisworksTransportPlugin(按 QWEN 中 2026 路径作适配); - 配置切换: - 自动路径规划模式网格参数(cellSize、vehicleSize、safetyMargin、vehicleHeight); - 2.5D/BoundingBox 模式选择(自动/强制选项)。 4.5 验证计划 + - 功能验证(最小可行用例): - 通道选择(手动/自动),边界计算; - 路径编辑:起点/若干路径点/终点,渲染正确; @@ -222,20 +245,22 @@ - 如需 Navisworks 2026,切换引用并复测 TimeLiner/Clash API 行为差异。 4.6 2026 兼容模式(可选) + - 若目标为 Navisworks 2026: - 切换引用到 2026 API; - 复核 QWEN.md 所述运行路径与日志输出位置; - 回归 TimeLiner 与 Clash API 可用性和接口差异; - 扩展安装器适配多版本并行安装。 - 五、非功能与质量保证 5.1 日志与异常处理 + - GlobalExceptionHandler:应用级异常捕获(线程/任务/未处理),尝试恢复组件,提供用户友好提示; - LogManager:Info/Warning/Error/Debug 统一记录,关键路径设充分日志(网格生成、A*、碰撞快照)。 5.2 性能优化要点 + - 网格生成: - ChannelBased 2.5D 优先(垂直扫描、空间哈希、通道优先),失败回退 BoundingBox; - 车辆膨胀:距离变换 O(n*m) 优化,跳过无障碍场景; @@ -246,11 +271,11 @@ - Search API 替代全量遍历,尤其在通道/楼层检索时。 5.3 可维护性 + - 分层清晰,事件驱动,保留向后兼容事件(_Legacy); - 路径文件以 XML 为主,便于第三方集成; - 关键类职责单一(PathPlanningManager/CategoryAttributeManager/GridMapGenerator 等)。 - 六、风险与边界 - Navisworks 版本差异:2017 与 2026 API 行为差异需要回归验证; @@ -259,7 +284,6 @@ - COM 属性写入:需严格使用相对索引覆盖逻辑(源码已修复),防止属性覆盖错乱; - 动画碰撞“位置恢复”:测试期间会短暂移动对象做验证,并在结束后恢复。 - 七、里程碑建议(示例) - M1(1 周):路径编辑闭环(手动)、物流属性标注、可见性隔离; @@ -268,7 +292,6 @@ - M4(1 周):导航输出与 DELMIA 结果结构; - M5(1 周):性能与兼容性回归(2017 基线,若选 2026 追加一轮)。 - 八、截图占位与要求 - [截图占位] 系统架构图: @@ -286,8 +309,8 @@ - [截图占位] 结果文件样例: - 要求:XML/CSV 字段示意,可用于 DELMIA 导入对齐。 - 附录 A:代码与模块清单(节选) + - Core/MainPlugin、UI/WPF/LogisticsControlPanel.xaml:主入口与面板; - Core/PathPlanningManager:路径规划主控(状态、事件、可视化、导入导出) - PathPlanning/GridMapGenerator、AutoPathFinder:网格生成与 A* 路径; @@ -296,4 +319,3 @@ - Core/Collision/ClashDetectiveIntegration:动画期缓存 + 结束创建测试; - Core/VisibilityManager:可见性隔离与统计; - UI/WPF/ViewModels/*:MVVM 视图模型与命令绑定。 - diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs index 5fbdb52..b84d38c 100644 --- a/src/Core/PathPointRenderPlugin.cs +++ b/src/Core/PathPointRenderPlugin.cs @@ -886,7 +886,7 @@ namespace NavisworksTransport { StartPoint = prevPoint.Position, EndPoint = previewPoint.Position, - Color = Color.White, // 使用白色作为预览连线颜色(灰色在Navisworks API中不可用) + Color = Color.FromByteRGB(128, 128, 128), // 统一使用灰色预览连线 Radius = GetLineRadius() // 使用与正常连线相同的直径 }; _previewLines.Add(line1); @@ -896,7 +896,7 @@ namespace NavisworksTransport { StartPoint = previewPoint.Position, EndPoint = nextPoint.Position, - Color = Color.White, + Color = Color.FromByteRGB(128, 128, 128), // 统一使用灰色预览连线 Radius = GetLineRadius() }; _previewLines.Add(line2); @@ -961,25 +961,63 @@ namespace NavisworksTransport { LogManager.WriteLog($"[预览路径渲染] 开始渲染预览路径: {previewRoute.Name}, 点数: {previewRoute.Points.Count}"); - // 清理现有预览 - ClearPreview(); + // 只清理预览元素,不影响原有路径 + ClearPreviewPoint(); + ClearPreviewLines(); - // 渲染预览路径点 + // 找到预览点及其索引 + var previewPointIndex = -1; + PathPoint previewPoint = null; + for (int i = 0; i < previewRoute.Points.Count; i++) { - var point = previewRoute.Points[i]; - - // 对于修改中的点,使用特殊颜色(白色) - if (point.Name.Contains("_预览")) + if (previewRoute.Points[i].Name.Contains("_预览")) { - RenderPreviewPoint(point); + previewPointIndex = i; + previewPoint = previewRoute.Points[i]; + break; } } - - // 渲染预览连线 - if (previewRoute.Points.Count > 1) + + if (previewPoint != null && previewPointIndex >= 0) { - RenderPreviewPathLines(previewRoute); + // 只渲染预览点 + RenderPreviewPoint(previewPoint); + + // 只渲染与预览点相关的连线 + // 连接前一个点到预览点 + if (previewPointIndex > 0) + { + var prevPoint = previewRoute.Points[previewPointIndex - 1]; + var line1 = new LineMarker + { + StartPoint = prevPoint.Position, + EndPoint = previewPoint.Position, + Color = Color.FromByteRGB(128, 128, 128), // 灰色预览连线 + Radius = GetLineRadius() + }; + _previewLines.Add(line1); + } + + // 连接预览点到下一个点 + if (previewPointIndex < previewRoute.Points.Count - 1) + { + var nextPoint = previewRoute.Points[previewPointIndex + 1]; + var line2 = new LineMarker + { + StartPoint = previewPoint.Position, + EndPoint = nextPoint.Position, + Color = Color.FromByteRGB(128, 128, 128), // 灰色预览连线 + Radius = GetLineRadius() + }; + _previewLines.Add(line2); + } + + LogManager.WriteLog($"[预览路径渲染] 已渲染编辑预览: 预览点 + {_previewLines.Count} 条连线"); + } + else + { + LogManager.WriteLog("[预览路径渲染] 未找到预览点,跳过渲染"); } RequestViewRefresh(); @@ -1012,7 +1050,7 @@ namespace NavisworksTransport { StartPoint = startPoint.Position, EndPoint = endPoint.Position, - Color = Color.FromByteRGB(128, 128, 128), // 预览连线使用灰色 + Color = Color.FromByteRGB(128, 128, 128), // 统一使用灰色预览连线 Radius = GetLineRadius() }; diff --git a/src/UI/WPF/LogisticsControlPanel.xaml.cs b/src/UI/WPF/LogisticsControlPanel.xaml.cs index 8456a72..bcab159 100644 --- a/src/UI/WPF/LogisticsControlPanel.xaml.cs +++ b/src/UI/WPF/LogisticsControlPanel.xaml.cs @@ -315,6 +315,12 @@ namespace NavisworksTransport.UI.WPF // 清理PathEditingView PathEditingView?.Cleanup(); + // 🔧 修复:清理ModelSettingsView(会调用ViewModel的Dispose) + _modelSettingsView?.Cleanup(); + + // 🔧 修复:清理LayerManagementView(会调用ViewModel的Dispose) + _layerManagementView?.Cleanup(); + // 清理SystemManagementViewModel SystemManagementViewModel?.Cleanup(); diff --git a/src/UI/WPF/ViewModels/LayerManagementViewModel.cs b/src/UI/WPF/ViewModels/LayerManagementViewModel.cs index 60151e6..1f7638f 100644 --- a/src/UI/WPF/ViewModels/LayerManagementViewModel.cs +++ b/src/UI/WPF/ViewModels/LayerManagementViewModel.cs @@ -47,6 +47,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 选择事件订阅管理器 private SelectionEventSubscription _selectionEventSubscription; + + // 资源释放状态标志 + private bool _disposed; #endregion @@ -2815,27 +2818,45 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// public void Dispose() { - try - { - // 取消正在进行的操作 - _cancellationTokenSource?.Cancel(); - _cancellationTokenSource?.Dispose(); + Dispose(true); + GC.SuppressFinalize(this); + } - // 取消事件订阅 - if (_modelSplitterManager != null) + /// + /// 释放资源的具体实现 + /// + /// 是否正在释放托管资源 + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) { - _modelSplitterManager.ProgressChanged -= OnProgressChanged; - _modelSplitterManager.StatusChanged -= OnStatusChanged; + try + { + // 取消正在进行的操作 + _cancellationTokenSource?.Cancel(); + _cancellationTokenSource?.Dispose(); + + // 取消事件订阅 + if (_modelSplitterManager != null) + { + _modelSplitterManager.ProgressChanged -= OnProgressChanged; + _modelSplitterManager.StatusChanged -= OnStatusChanged; + } + + // 取消Navisworks选择变化事件订阅 + UnsubscribeFromSelectionEvents(); + + LogManager.Info("[LayerManagementViewModel] 资源清理完成"); + } + catch (Exception ex) + { + LogManager.Error($"[LayerManagementViewModel] 资源清理失败: {ex.Message}"); + } } - // 取消Navisworks选择变化事件订阅 - UnsubscribeFromSelectionEvents(); - - LogManager.Info("[LayerManagementViewModel] 资源清理完成"); - } - catch (Exception ex) - { - LogManager.Error($"[LayerManagementViewModel] 资源清理失败: {ex.Message}"); + _disposed = true; } } @@ -2916,6 +2937,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// private async Task OnSelectionChangedAsync(SelectionStateResult selectionResult) { + // 如果已经释放,直接返回 + if (_disposed) return; + try { // 更新楼层属性相关的选择状态(使用新的选择结果) @@ -2934,6 +2958,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// private async Task UpdateFloorAttributeSelectionStateAsync(SelectionStateResult selectionResult = null) { + // 如果已经释放,直接返回 + if (_disposed) return; + try { // 如果没有提供选择结果,则获取当前选择状态 diff --git a/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs b/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs index e179a8e..2454650 100644 --- a/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs +++ b/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs @@ -35,6 +35,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 选择事件订阅管理器 private SelectionEventSubscription _selectionEventSubscription; + + // 资源释放状态标志 + private bool _disposed; #endregion @@ -766,6 +769,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// private async Task OnSelectionChangedAsync(SelectionStateResult selectionResult) { + // 如果已经释放,直接返回 + if (_disposed) return; + try { // 更新物流属性相关的选择状态(使用新的选择结果) @@ -784,6 +790,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// private async Task UpdateModelSelectionStateAsync(SelectionStateResult selectionResult = null) { + // 如果已经释放,直接返回 + if (_disposed) return; + try { // 如果没有提供选择结果,则获取当前选择状态 @@ -1245,16 +1254,34 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// public void Dispose() { - try - { - // 取消选择事件订阅 - UnsubscribeFromSelectionEvents(); + Dispose(true); + GC.SuppressFinalize(this); + } - LogManager.Info("[ModelSettingsViewModel] 资源清理完成"); - } - catch (Exception ex) + /// + /// 释放资源的具体实现 + /// + /// 是否正在释放托管资源 + protected virtual void Dispose(bool disposing) + { + if (!_disposed) { - LogManager.Error($"[ModelSettingsViewModel] 资源清理失败: {ex.Message}"); + if (disposing) + { + try + { + // 取消选择事件订阅 + UnsubscribeFromSelectionEvents(); + + LogManager.Info("[ModelSettingsViewModel] 资源清理完成"); + } + catch (Exception ex) + { + LogManager.Error($"[ModelSettingsViewModel] 资源清理失败: {ex.Message}"); + } + } + + _disposed = true; } } diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs index 75fd9eb..36f5a60 100644 --- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs +++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs @@ -34,6 +34,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels private string _runningTime = "00:00:00"; private string _performanceInfo = "性能监控就绪"; + // 🔧 修复:添加定时器字段以便在清理时停止 + private System.Windows.Threading.DispatcherTimer _performanceTimer; + + // 🔧 修复:添加释放状态标志 + private bool _disposed = false; + #endregion #region 公共属性 @@ -277,15 +283,30 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// private void StartPerformanceMonitoring() { + // 🔧 修复:如果已经释放,不启动定时器 + if (_disposed) + { + LogManager.Info("SystemManagementViewModel已释放,跳过性能监控启动"); + return; + } + var startTime = DateTime.Now; - // 使用定时器更新性能信息 - var timer = new System.Windows.Threading.DispatcherTimer(); - timer.Interval = TimeSpan.FromSeconds(5); - timer.Tick += (s, e) => + // 🔧 修复:保存定时器引用以便在清理时停止 + _performanceTimer = new System.Windows.Threading.DispatcherTimer(); + _performanceTimer.Interval = TimeSpan.FromSeconds(5); + _performanceTimer.Tick += (s, e) => { try { + // 🔧 修复:检查释放状态,避免在释放后继续更新UI + if (_disposed) + { + LogManager.Info("SystemManagementViewModel已释放,停止性能监控更新"); + _performanceTimer?.Stop(); + return; + } + // 更新内存使用 var process = System.Diagnostics.Process.GetCurrentProcess(); var memoryMB = process.WorkingSet64 / (1024 * 1024); @@ -301,9 +322,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels catch (Exception ex) { LogManager.Error($"性能监控更新失败: {ex.Message}"); + + // 🔧 修复:发生异常时也停止定时器 + if (!_disposed) + { + _performanceTimer?.Stop(); + } } }; - timer.Start(); + _performanceTimer.Start(); + + LogManager.Info("SystemManagementViewModel性能监控已启动"); } #endregion @@ -552,6 +581,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels { try { + // 🔧 修复:检查释放状态,避免在释放后更新UI + if (_disposed) + { + LogManager.Info("SystemManagementViewModel已释放,跳过更新检查UI更新"); + return; + } + SystemStatus = "当前版本已是最新版本"; } catch (Exception ex) @@ -583,6 +619,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels { try { + // 🔧 修复:检查释放状态,避免在释放后更新UI + if (_disposed) + { + LogManager.Info("SystemManagementViewModel已释放,跳过性能报告UI更新"); + return; + } + SystemStatus = "性能报告生成完成"; PerformanceInfo = $"报告已生成 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}"; } @@ -662,7 +705,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels { LogManager.Info("开始清理SystemManagementViewModel资源"); - // 目前没有需要特别清理的资源 + // 🔧 修复:标记为已释放 + _disposed = true; + + // 🔧 修复:停止性能监控定时器 + if (_performanceTimer != null) + { + _performanceTimer.Stop(); + _performanceTimer.Tick -= null; // 取消事件订阅 + _performanceTimer = null; + LogManager.Info("SystemManagementViewModel性能监控定时器已停止"); + } LogManager.Info("SystemManagementViewModel资源清理完成"); } diff --git a/src/UI/WPF/Views/LayerManagementView.xaml.cs b/src/UI/WPF/Views/LayerManagementView.xaml.cs index a813495..b8aaf51 100644 --- a/src/UI/WPF/Views/LayerManagementView.xaml.cs +++ b/src/UI/WPF/Views/LayerManagementView.xaml.cs @@ -70,5 +70,22 @@ namespace NavisworksTransport.UI.WPF.Views LogManager.Error($"[LayerManagementView] 页面卸载失败: {ex.Message}"); } } + + /// + /// 清理资源 + /// + public void Cleanup() + { + try + { + // 清理ViewModel + ViewModel?.Dispose(); + LogManager.Info("LayerManagementView资源清理完成"); + } + catch (Exception ex) + { + LogManager.Error($"LayerManagementView清理失败: {ex.Message}"); + } + } } } \ No newline at end of file diff --git a/src/UI/WPF/Views/ModelSettingsView.xaml.cs b/src/UI/WPF/Views/ModelSettingsView.xaml.cs index a1e13a2..f9caebc 100644 --- a/src/UI/WPF/Views/ModelSettingsView.xaml.cs +++ b/src/UI/WPF/Views/ModelSettingsView.xaml.cs @@ -1,3 +1,4 @@ +using System; using System.Windows.Controls; using NavisworksTransport.UI.WPF.ViewModels; using NavisworksTransport.Utils; @@ -24,5 +25,25 @@ namespace NavisworksTransport.UI.WPF.Views LogManager.Error($"ModelSettingsView初始化失败: {ex.Message}", ex); } } + + /// + /// 清理资源 + /// + public void Cleanup() + { + try + { + // 清理ViewModel + if (DataContext is ModelSettingsViewModel viewModel) + { + viewModel.Dispose(); + LogManager.Info("ModelSettingsView资源清理完成"); + } + } + catch (Exception ex) + { + LogManager.Error($"ModelSettingsView清理失败: {ex.Message}"); + } + } } } \ No newline at end of file