using System; using System.Collections.ObjectModel; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using NavisworksTransport.UI.WPF.Collections; using NavisworksTransport.Core; using NavisworksTransport.Core.Config; using NavisworksTransport.Utils; using NavisworksTransport.Utils.CoordinateSystem; using NavisworksTransport.Commands; namespace NavisworksTransport.UI.WPF.ViewModels { /// /// 系统管理ViewModel - 处理插件系统管理功能 /// public class SystemManagementViewModel : ViewModelBase, IDisposable { #region 私有字段 private readonly UIStateManager _uiStateManager; // 日志管理字段 private ObservableCollection _logLevels; private string _selectedLogLevel = "Info"; private string _pluginVersion = "v1.0"; private string _navisworksVersion = "2026"; private string _memoryUsage = "0 MB"; private string _runningTime = "00:00:00"; // 数据管理字段 private string _databaseVersion = "--"; private string _pathCount = "--"; private string _collisionRecordCount = "--"; private bool _autoBackupEnabled = true; private int _selectedBackupKeepCount = 10; private string _lastBackupInfo = "暂无备份记录"; // 🔧 修复:添加释放状态标志 private bool _disposed = false; #endregion #region 公共属性 /// /// 日志级别集合 /// public ObservableCollection LogLevels { get => _logLevels; set => SetProperty(ref _logLevels, value); } /// /// 选中的日志级别 /// public string SelectedLogLevel { get => _selectedLogLevel; set { if (SetProperty(ref _selectedLogLevel, value)) { // 将字符串转换为LogLevel枚举并设置 if (Enum.TryParse(value, out var level)) { LogManager.SetLogLevel(level); LogManager.Info($"日志级别已更改为: {value}"); UpdateMainStatus($"日志级别已设置为: {value}"); } } } } /// /// 插件版本 /// public string PluginVersion { get => _pluginVersion; set => SetProperty(ref _pluginVersion, value); } /// /// Navisworks版本 /// public string NavisworksVersion { get => _navisworksVersion; set => SetProperty(ref _navisworksVersion, value); } /// /// 内存使用情况 /// public string MemoryUsage { get => _memoryUsage; set => SetProperty(ref _memoryUsage, value); } /// /// 运行时间 /// public string RunningTime { get => _runningTime; set => SetProperty(ref _runningTime, value); } // 数据管理属性 public string DatabaseVersion { get => _databaseVersion; set => SetProperty(ref _databaseVersion, value); } public string PathCount { get => _pathCount; set => SetProperty(ref _pathCount, value); } public string CollisionRecordCount { get => _collisionRecordCount; set => SetProperty(ref _collisionRecordCount, value); } public bool AutoBackupEnabled { get => _autoBackupEnabled; set => SetProperty(ref _autoBackupEnabled, value); } public ObservableCollection BackupKeepCountOptions { get; } = new ObservableCollection { 5, 10, 20, 50 }; public int SelectedBackupKeepCount { get => _selectedBackupKeepCount; set => SetProperty(ref _selectedBackupKeepCount, value); } public string LastBackupInfo { get => _lastBackupInfo; set => SetProperty(ref _lastBackupInfo, value); } #endregion #region 命令 public ICommand ViewLogCommand { get; private set; } public ICommand OpenSettingsCommand { get; private set; } public ICommand CheckUpdateCommand { get; private set; } public ICommand GeneratePerformanceReportCommand { get; private set; } public ICommand DiagnosticCommand { get; private set; } // 数据管理命令 public ICommand BackupDataCommand { get; private set; } public ICommand RestoreDataCommand { get; private set; } public ICommand RepairDatabaseCommand { get; private set; } public ICommand ClearAllDataCommand { get; private set; } // 功能测试命令 public ICommand TestVoxelGridSDFCommand { get; private set; } public ICommand TestVoxelPathFindingCommand { get; private set; } public ICommand ReadTransformTestCommand { get; private set; } public ICommand CoordinateSystemExplorerCommand { get; private set; } // 坐标系设置 public ObservableCollection CoordinateSystemOptions { get; private set; } private string _selectedCoordinateSystem = "AutoDetect"; public string SelectedCoordinateSystem { get => _selectedCoordinateSystem; set { if (SetProperty(ref _selectedCoordinateSystem, value)) { OnCoordinateSystemChanged(value); } } } private string _currentCoordinateSystemInfo = "当前坐标系: 未初始化"; public string CurrentCoordinateSystemInfo { get => _currentCoordinateSystemInfo; set => SetProperty(ref _currentCoordinateSystemInfo, value); } #endregion #region 构造函数 public SystemManagementViewModel() : base() { try { // 获取UI状态管理器实例 _uiStateManager = UIStateManager.Instance; // 验证关键组件是否正常初始化 if (_uiStateManager == null) { LogManager.Error("UIStateManager初始化失败"); throw new InvalidOperationException("UIStateManager初始化失败"); } // 初始化日志级别集合 LogLevels = new ThreadSafeObservableCollection(); // 初始化命令 InitializeCommands(); // 初始化系统管理设置 _ = InitializeSystemManagementSettingsAsync(); // 订阅文档切换事件,以便重新检测坐标系 SubscribeToDocumentEvents(); LogManager.Info("SystemManagementViewModel构造函数执行完成"); } catch (Exception ex) { LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex); // 在构造函数中尽量保证对象处于可用状态 UpdateMainStatus("初始化失败,请检查日志"); throw; } } /// /// 带主ViewModel参数的构造函数,支持统一状态栏 /// /// 主ViewModel,用于统一状态栏 public SystemManagementViewModel(LogisticsControlViewModel mainViewModel) : base() { try { // 设置主ViewModel引用到基类 SetMainViewModel(mainViewModel); // 获取UI状态管理器实例 _uiStateManager = UIStateManager.Instance; // 验证关键组件是否正常初始化 if (_uiStateManager == null) { LogManager.Error("UIStateManager初始化失败"); throw new InvalidOperationException("UIStateManager初始化失败"); } // 初始化日志级别集合 LogLevels = new ThreadSafeObservableCollection(); // 初始化命令 InitializeCommands(); // 初始化系统管理设置 _ = InitializeSystemManagementSettingsAsync(); LogManager.Info("SystemManagementViewModel构造函数执行完成 - 支持统一状态栏"); } catch (Exception ex) { LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex); // 在构造函数中尽量保证对象处于可用状态 UpdateMainStatus("初始化失败,请检查日志"); throw; } } #endregion #region 初始化 /// /// 初始化命令 /// private void InitializeCommands() { try { // 系统管理命令 ViewLogCommand = new RelayCommand(() => ExecuteViewLog()); OpenSettingsCommand = new RelayCommand(() => ExecuteOpenSettings()); CheckUpdateCommand = new RelayCommand(() => ExecuteCheckUpdate()); GeneratePerformanceReportCommand = new RelayCommand(() => ExecuteGeneratePerformanceReport()); DiagnosticCommand = new RelayCommand(() => ExecuteDiagnostic()); // 数据管理命令 BackupDataCommand = new RelayCommand(() => ExecuteBackupData()); RestoreDataCommand = new RelayCommand(() => ExecuteRestoreData()); RepairDatabaseCommand = new RelayCommand(() => ExecuteRepairDatabase()); ClearAllDataCommand = new RelayCommand(() => ExecuteClearAllData()); // 功能测试命令 TestVoxelGridSDFCommand = new RelayCommand(() => ExecuteTestVoxelGridSDF()); TestVoxelPathFindingCommand = new RelayCommand(() => ExecuteTestVoxelPathFinding()); ReadTransformTestCommand = new RelayCommand(() => ExecuteReadTransformTest()); CoordinateSystemExplorerCommand = new RelayCommand(() => ExecuteCoordinateSystemExplorer()); // 初始化坐标系选项 CoordinateSystemOptions = new ObservableCollection { "AutoDetect", "ZUp", "YUp" }; // 从配置加载当前坐标系设置 var configType = ConfigManager.Instance.Current.CoordinateSystem?.Type ?? "AutoDetect"; _selectedCoordinateSystem = configType; // 订阅文档事件(用于自动检测坐标系) SubscribeToDocumentEvents(); // 检查当前是否已有活动文档,如果有立即检测 if (Autodesk.Navisworks.Api.Application.ActiveDocument != null) { InitializeCoordinateSystem(); } else { // 没有活动文档,显示等待状态 CurrentCoordinateSystemInfo = "当前坐标系: 等待文档加载..."; } LogManager.Info("系统管理命令初始化完成"); } catch (Exception ex) { LogManager.Error($"初始化命令失败: {ex.Message}", ex); throw; } } /// /// 获取路径规划管理器实例 /// /// 路径规划管理器或null private PathPlanningManager GetPathPlanningManager() { try { // 使用PathPlanningManager的静态方法获取活动实例 var pathManager = PathPlanningManager.GetActivePathManager(); if (pathManager != null) { LogManager.Info("成功获取到活动的PathPlanningManager实例"); return pathManager; } else { LogManager.Warning("当前没有活动的PathPlanningManager实例"); return null; } } catch (Exception ex) { LogManager.Error($"获取PathPlanningManager失败: {ex.Message}", ex); return null; } } /// /// 初始化坐标系 /// private void InitializeCoordinateSystem() { try { // 解析配置类型 if (!Enum.TryParse(_selectedCoordinateSystem, out var configType)) { configType = CoordinateSystemType.AutoDetect; } // 初始化坐标系管理器 CoordinateSystemManager.Instance.Initialize(configType); // 更新显示信息 UpdateCoordinateSystemInfo(); LogManager.Info($"坐标系初始化完成: {configType}"); } catch (Exception ex) { LogManager.Error($"坐标系初始化失败: {ex.Message}"); } } /// /// 坐标系选择改变时调用 /// private void OnCoordinateSystemChanged(string newValue) { try { if (!Enum.TryParse(newValue, out var type)) { type = CoordinateSystemType.AutoDetect; } // 设置新坐标系 CoordinateSystemManager.Instance.SetCoordinateSystem(type); // 更新显示信息 UpdateCoordinateSystemInfo(); // 更新配置 ConfigManager.Instance.Current.CoordinateSystem.Type = newValue; UpdateMainStatus($"坐标系已切换为: {newValue}"); LogManager.Info($"坐标系已手动切换为: {newValue}"); } catch (Exception ex) { LogManager.Error($"切换坐标系失败: {ex.Message}"); UpdateMainStatus($"切换坐标系失败: {ex.Message}"); } } /// /// 更新坐标系显示信息 /// private void UpdateCoordinateSystemInfo() { var info = CoordinateSystemManager.Instance.GetCurrentInfo(); CurrentCoordinateSystemInfo = $"当前坐标系: {info}"; } #region 文档事件处理 /// /// 订阅文档切换事件 /// private void SubscribeToDocumentEvents() { try { // 订阅文档切换后事件(文档已完全加载) Autodesk.Navisworks.Api.Application.ActiveDocumentChanged += OnActiveDocumentChanged; // 同时订阅模型集合变化事件(SDI架构下的真正文档变化) if (Autodesk.Navisworks.Api.Application.ActiveDocument != null) { Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged; } LogManager.Info("[系统管理] 已订阅文档相关事件"); } catch (Exception ex) { LogManager.Error($"[系统管理] 订阅文档事件失败: {ex.Message}"); } } /// /// 取消订阅文档事件 /// private void UnsubscribeFromDocumentEvents() { try { // 取消订阅文档切换事件 Autodesk.Navisworks.Api.Application.ActiveDocumentChanged -= OnActiveDocumentChanged; // 取消订阅模型集合变化事件 if (Autodesk.Navisworks.Api.Application.ActiveDocument != null) { Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged -= OnModelsCollectionChanged; } LogManager.Info("[系统管理] 已取消订阅文档相关事件"); } catch (Exception ex) { LogManager.Warning($"[系统管理] 取消订阅文档事件时出现警告: {ex.Message}"); } } /// /// 文档切换事件处理 /// private void OnActiveDocumentChanged(object sender, EventArgs e) { try { LogManager.Info("[系统管理] 检测到文档切换"); // 订阅新文档的 Models.CollectionChanged if (Autodesk.Navisworks.Api.Application.ActiveDocument != null) { try { Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged; LogManager.Info("[系统管理] 已订阅新文档的模型集合变化事件"); } catch (Exception ex) { LogManager.Warning($"[系统管理] 订阅模型集合变化事件失败: {ex.Message}"); } } // 执行坐标系检测 HandleDocumentChange(); } catch (Exception ex) { LogManager.Error($"[系统管理] 文档切换处理失败: {ex.Message}"); } } /// /// 模型集合变化事件处理(SDI架构下的真正文档变化) /// private void OnModelsCollectionChanged(object sender, EventArgs e) { try { LogManager.Info("[系统管理] 检测到模型集合变化"); HandleDocumentChange(); } catch (Exception ex) { LogManager.Error($"[系统管理] 模型集合变化处理失败: {ex.Message}"); } } /// /// 处理文档变化,重新检测坐标系 /// private void HandleDocumentChange() { // 检查文档是否已完全加载 var doc = Autodesk.Navisworks.Api.Application.ActiveDocument; if (doc == null || string.IsNullOrEmpty(doc.FileName)) { LogManager.Debug("[系统管理] 文档尚未完全加载,跳过坐标系检测"); return; } // 如果配置为自动检测,重新检测坐标系 if (_selectedCoordinateSystem == "AutoDetect") { // 在 UI 线程执行 _ = _uiStateManager.ExecuteUIUpdateAsync(() => { try { InitializeCoordinateSystem(); UpdateMainStatus("坐标系已根据新文档重新检测"); } catch (Exception ex) { LogManager.Error($"[系统管理] 坐标系检测失败: {ex.Message}"); } }); } } #endregion /// /// 初始化系统管理设置 /// private async Task InitializeSystemManagementSettingsAsync() { await SafeExecuteAsync(async () => { await _uiStateManager.ExecuteUIUpdateAsync(() => { // 初始化日志级别 LogLevels.Clear(); LogLevels.Add("Debug"); LogLevels.Add("Info"); LogLevels.Add("Warning"); LogLevels.Add("Error"); // 获取当前日志级别 var currentLevel = LogManager.GetLogLevel(); SelectedLogLevel = currentLevel.ToString(); // 初始化系统信息 PluginVersion = "v1.0"; NavisworksVersion = "2026"; // 初始化数据库状态(如果数据库已连接) RefreshDatabaseStatus(); UpdateMainStatus("系统管理初始化完成"); }); LogManager.Info("系统管理设置初始化完成"); }, "初始化系统管理设置"); } #endregion #region 命令实现 /// /// 查看日志 /// private void ExecuteViewLog() { SafeExecute(() => { try { // 创建并显示日志查看器对话框 var logViewerDialog = new NavisworksTransport.UI.WPF.Views.LogViewerDialog(); // 尝试设置窗口所有者,使用更安全的方式 try { // 查找当前活动的主窗口 var mainWindow = System.Windows.Application.Current.MainWindow; if (mainWindow != null && mainWindow.IsLoaded) { logViewerDialog.Owner = mainWindow; } else { // 如果主窗口不可用,查找当前活动的窗口 foreach (System.Windows.Window window in System.Windows.Application.Current.Windows) { if (window.IsActive && window.IsLoaded) { logViewerDialog.Owner = window; break; } } } } catch (Exception ownerEx) { // 如果设置Owner失败,记录警告但继续显示窗口 LogManager.Warning($"设置日志查看器Owner失败: {ownerEx.Message}"); } // 显示对话框(使用Show而不是ShowDialog以避免阻塞) logViewerDialog.Show(); UpdateMainStatus("日志查看器已打开"); LogManager.Info("通过系统管理打开日志查看器"); } catch (Exception ex) { UpdateMainStatus("打开日志查看器失败"); LogManager.Error($"打开日志查看器失败: {ex.Message}", ex); // 显示错误消息给用户 System.Windows.MessageBox.Show($"打开日志查看器失败: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } }, "查看日志"); } /// /// 打开设置 /// private void ExecuteOpenSettings() { SafeExecute(() => { try { // 创建并显示配置编辑器对话框 var configEditorDialog = new NavisworksTransport.UI.WPF.Views.ConfigEditorDialog(); // 尝试设置窗口所有者 try { var mainWindow = System.Windows.Application.Current.MainWindow; if (mainWindow != null && mainWindow.IsLoaded) { configEditorDialog.Owner = mainWindow; } else { foreach (System.Windows.Window window in System.Windows.Application.Current.Windows) { if (window.IsActive && window.IsLoaded) { configEditorDialog.Owner = window; break; } } } } catch (Exception ownerEx) { LogManager.Warning($"设置配置编辑器Owner失败: {ownerEx.Message}"); } // 显示对话框 bool? result = configEditorDialog.ShowDialog(); if (result == true) { UpdateMainStatus("配置已更新"); LogManager.Info("配置编辑器:用户保存了配置"); } else { UpdateMainStatus("配置编辑已取消"); LogManager.Info("配置编辑器:用户取消了修改"); } } catch (Exception ex) { UpdateMainStatus("打开配置编辑器失败"); LogManager.Error($"打开配置编辑器失败: {ex.Message}", ex); System.Windows.MessageBox.Show($"打开配置编辑器失败: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } }, "打开设置"); } /// /// 检查更新 (已优化为Idle事件监听) /// private void ExecuteCheckUpdate() { SafeExecute(() => { UpdateMainStatus("正在检查更新..."); // 使用Idle事件监听替代Thread.Sleep(2000) const string taskId = "SystemManagement_CheckUpdate"; var startTime = DateTime.Now; IdleEventManager.Instance.RegisterOnceTask( taskId, () => (DateTime.Now - startTime).TotalMilliseconds >= 2000, // 2秒后条件满足 () => { try { // 检查释放状态,避免在释放后更新UI if (_disposed) { LogManager.Info("SystemManagementViewModel已释放,跳过更新检查UI更新"); return; } UpdateMainStatus("当前版本已是最新版本"); } catch (Exception ex) { LogManager.Error($"更新检查UI更新失败: {ex.Message}"); } }, 8 // 高优先级 ); LogManager.Info("检查更新 (使用Idle事件监听)"); }, "检查更新"); } /// /// 生成性能报告 (已优化为Idle事件监听) /// private void ExecuteGeneratePerformanceReport() { SafeExecute(() => { UpdateMainStatus("正在生成性能报告..."); // 使用Idle事件监听替代Thread.Sleep(1500) const string taskId = "SystemManagement_GenerateReport"; var startTime = DateTime.Now; IdleEventManager.Instance.RegisterOnceTask( taskId, () => (DateTime.Now - startTime).TotalMilliseconds >= 1500, // 1.5秒后条件满足 () => { try { // 检查释放状态,避免在释放后更新UI if (_disposed) { LogManager.Info("SystemManagementViewModel已释放,跳过性能报告UI更新"); return; } UpdateMainStatus("性能报告生成完成"); // 性能信息更新已合并到统一状态栏 } catch (Exception ex) { LogManager.Error($"性能报告UI更新失败: {ex.Message}"); } }, 8 // 高优先级 ); LogManager.Info("生成性能报告 (使用Idle事件监听)"); }, "生成性能报告"); } /// /// 执行环境诊断 /// private void ExecuteDiagnostic() { SafeExecute(() => { try { LogManager.Info("开始环境诊断"); // 直接调用本地的环境诊断方法 string diagnosticReport = DiagnoseEnvironment(); // 显示诊断结果对话框 System.Windows.MessageBox.Show( diagnosticReport, "环境诊断结果", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); LogManager.Info("环境诊断完成"); } catch (Exception ex) { LogManager.Error($"环境诊断失败: {ex.Message}", ex); System.Windows.MessageBox.Show( $"环境诊断失败: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } }, "环境诊断"); } /// /// 环境诊断方法 - 快速检查API是否可用 /// /// 诊断报告 private string DiagnoseEnvironment() { var report = new System.Text.StringBuilder(); report.AppendLine("=== Navisworks API环境诊断报告 ==="); try { // 1. 线程状态 var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState(); report.AppendLine($"线程状态: {apartmentState} {(apartmentState == System.Threading.ApartmentState.STA ? "✓" : "✗")}"); // 2. API可用性 try { var app = Autodesk.Navisworks.Api.Application.ActiveDocument; report.AppendLine("API可用性: 可用 ✓"); } catch (Exception apiEx) { report.AppendLine($"API可用性: 异常 - {apiEx.Message} ✗"); } // 3. 文档状态 try { var document = Autodesk.Navisworks.Api.Application.ActiveDocument; if (document != null) { report.AppendLine($"活动文档: {document.FileName ?? "未命名"} ✓"); report.AppendLine($"模型数量: {document.Models?.Count ?? 0}"); } else { report.AppendLine("活动文档: 无 ✗"); } } catch (Exception docEx) { report.AppendLine($"活动文档: 异常 - {docEx.Message} ✗"); } // 4. 内存状态 long memoryMB = GC.GetTotalMemory(false) / 1024 / 1024; report.AppendLine($"当前内存: {memoryMB} MB"); // 5. 系统信息 report.AppendLine($"插件版本: {PluginVersion}"); report.AppendLine($"Navisworks版本: {NavisworksVersion}"); report.AppendLine("系统状态: 正常"); report.AppendLine("=== 诊断完成 ==="); string result = report.ToString(); LogManager.Info($"[SystemManagement] 环境诊断报告:\n{result}"); return result; } catch (Exception ex) { string error = $"诊断过程出错: {ex.Message}"; report.AppendLine(error); LogManager.Error($"[SystemManagement] {error}"); return report.ToString(); } } #region 数据管理方法 /// /// 刷新数据库状态信息 /// private void RefreshDatabaseStatus() { try { var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase(); if (pathDatabase != null) { // 获取数据库信息 var dbInfo = pathDatabase.Backup.GetDatabaseInfo(); DatabaseVersion = dbInfo.VersionFormatted; PathCount = dbInfo.PathRoutesCount.ToString(); CollisionRecordCount = dbInfo.ClashResultsCount.ToString(); LogManager.Debug($"数据库状态: 版本{dbInfo.VersionFormatted}, 路径{dbInfo.PathRoutesCount}, 点{dbInfo.PathPointsCount}, 边{dbInfo.PathEdgesCount}, 碰撞{dbInfo.ClashResultsCount}"); } else { DatabaseVersion = "未连接"; PathCount = "--"; CollisionRecordCount = "--"; } } catch (Exception ex) { LogManager.Error($"刷新数据库状态失败: {ex.Message}"); DatabaseVersion = "错误"; } } /// /// 执行数据备份 /// private void ExecuteBackupData() { SafeExecute(() => { try { var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase(); if (pathDatabase == null) { System.Windows.MessageBox.Show( "未找到数据库连接,请确保已加载模型", "备份数据", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); return; } UpdateMainStatus("正在备份数据库..."); LogManager.Info("开始数据库文件备份"); string backupPath = pathDatabase.Backup.BackupDatabase(); if (!string.IsNullOrEmpty(backupPath)) { var info = pathDatabase.Backup.GetDatabaseInfo(); LastBackupInfo = $"上次备份: {DateTime.Now:yyyy-MM-dd HH:mm:ss}, 版本{info.VersionFormatted}, {info.FileSizeFormatted}"; System.Windows.MessageBox.Show( $"数据库备份完成!\n\n" + $"版本: {info.VersionFormatted}\n" + $"文件: {backupPath}\n\n" + $"包含数据:\n" + $"- 路径: {info.PathRoutesCount} 条\n" + $"- 路径点: {info.PathPointsCount} 个\n" + $"- 碰撞记录: {info.ClashResultsCount} 条\n" + $"- 截图: {info.ScreenshotsCount} 张", "备份成功", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); UpdateMainStatus("数据库备份完成"); LogManager.Info($"数据库备份完成: {backupPath}, 版本{info.VersionFormatted}"); } } catch (Exception ex) { LogManager.Error($"数据备份失败: {ex.Message}"); System.Windows.MessageBox.Show( $"数据备份失败: {ex.Message}", "备份失败", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus("数据备份失败"); } }, "数据备份"); } /// /// 执行数据恢复 /// private void ExecuteRestoreData() { SafeExecute(() => { try { var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase(); if (pathDatabase == null) { System.Windows.MessageBox.Show( "未找到数据库连接,请确保已加载模型", "恢复数据", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); return; } // 选择备份文件 var openFileDialog = new Microsoft.Win32.OpenFileDialog { Title = "选择数据库备份文件", Filter = "数据库备份文件 (*.db)|*.db", InitialDirectory = System.IO.Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NavisworksTransport", "Backups") }; if (openFileDialog.ShowDialog() != true) { return; } // 确认恢复 var result = System.Windows.MessageBox.Show( "恢复数据将覆盖现有数据,建议先备份当前数据。\n\n是否继续?", "确认恢复", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Warning); if (result != System.Windows.MessageBoxResult.Yes) { return; } UpdateMainStatus("正在恢复数据库..."); LogManager.Info($"开始数据库恢复: {openFileDialog.FileName}"); pathDatabase.Backup.RestoreDatabase(openFileDialog.FileName); // 恢复成功 bool restoreSuccess = true; if (restoreSuccess) { // 刷新数据库状态 RefreshDatabaseStatus(); var info = pathDatabase.Backup.GetDatabaseInfo(); System.Windows.MessageBox.Show( $"数据库恢复完成!\n\n" + $"当前数据:\n" + $"- 路径: {info.PathRoutesCount} 条\n" + $"- 路径点: {info.PathPointsCount} 个\n" + $"- 碰撞记录: {info.ClashResultsCount} 条\n" + $"- 截图: {info.ScreenshotsCount} 张\n\n" + $"请重新启动 Navisworks 以加载恢复的数据。", "恢复成功", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); UpdateMainStatus("数据恢复完成"); LogManager.Info("数据恢复完成"); // 刷新显示 RefreshDatabaseStatus(); } } catch (Exception ex) { LogManager.Error($"数据恢复失败: {ex.Message}"); System.Windows.MessageBox.Show( $"数据恢复失败: {ex.Message}", "恢复失败", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus("数据恢复失败"); } }, "数据恢复"); } /// /// 执行数据库修复 /// private void ExecuteRepairDatabase() { SafeExecute(() => { try { var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase(); if (pathDatabase == null) { System.Windows.MessageBox.Show( "未找到数据库连接", "修复数据库", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); return; } UpdateMainStatus("正在检查数据库..."); LogManager.Info("开始数据库修复检查"); // 获取数据库信息 var info = pathDatabase.Backup.GetDatabaseInfo(); System.Windows.MessageBox.Show( $"数据库检查结果:\n\n" + $"版本: {info.VersionFormatted}\n" + $"文件大小: {info.FileSizeFormatted}\n" + $"路径数量: {info.PathRoutesCount} 条\n" + $"路径点: {info.PathPointsCount} 个\n" + $"路径边: {info.PathEdgesCount} 条\n" + $"碰撞记录: {info.ClashResultsCount} 条\n" + $"截图: {info.ScreenshotsCount} 张", "检查结果", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); // 刷新状态 RefreshDatabaseStatus(); UpdateMainStatus("数据库检查完成"); } catch (Exception ex) { LogManager.Error($"数据库修复失败: {ex.Message}"); System.Windows.MessageBox.Show( $"数据库修复失败: {ex.Message}", "修复失败", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus("数据库修复失败"); } }, "数据库修复"); } /// /// 执行清空所有数据 /// private void ExecuteClearAllData() { SafeExecute(() => { try { var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase(); if (pathDatabase == null) { System.Windows.MessageBox.Show( "未找到数据库连接", "清空数据", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); return; } // 双重确认 var result1 = System.Windows.MessageBox.Show( "⚠️ 警告:此操作将永久删除所有路径和碰撞记录!\n\n" + "建议先备份数据。\n\n" + "是否继续?", "确认清空数据", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Warning); if (result1 != System.Windows.MessageBoxResult.Yes) { return; } var result2 = System.Windows.MessageBox.Show( "请再次确认:是否永久删除所有数据?\n\n" + "此操作不可恢复!", "最终确认", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Warning); if (result2 != System.Windows.MessageBoxResult.Yes) { return; } UpdateMainStatus("正在清空数据..."); LogManager.Info("开始清空所有数据"); // 清空所有表 pathDatabase.ClearAllData(); System.Windows.MessageBox.Show( "所有数据已清空!", "清空完成", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); UpdateMainStatus("数据已清空"); LogManager.Info("所有数据已清空"); // 刷新状态 RefreshDatabaseStatus(); } catch (Exception ex) { LogManager.Error($"清空数据失败: {ex.Message}"); System.Windows.MessageBox.Show( $"清空数据失败: {ex.Message}", "操作失败", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus("清空数据失败"); } }, "清空数据"); } #endregion /// /// 执行体素网格 SDF 测试(使用 MeshSignedDistanceGrid) /// private async void ExecuteTestVoxelGridSDF() { await SafeExecuteAsync(async () => { try { UpdateMainStatus("正在执行体素网格 SDF 测试..."); LogManager.Info("开始体素网格 SDF 测试(使用 MeshSignedDistanceGrid)"); // 获取当前文档 var document = Autodesk.Navisworks.Api.Application.ActiveDocument; if (document == null) { System.Windows.MessageBox.Show( "未找到活动文档,请先打开一个 Navisworks 模型", "体素网格 SDF 测试", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); UpdateMainStatus("体素网格 SDF 测试取消:无活动文档"); return; } // 创建并执行体素网格 SDF 测试命令 // 使用系统配置的网格大小参数 double cellSizeMeters = ConfigManager.Instance.Current.PathEditing.CellSizeMeters; LogManager.Info($"使用系统配置的体素大小: {cellSizeMeters}米"); var testCommand = new VoxelGridSDFTestCommand( document, cellSize: cellSizeMeters, // 使用系统配置的体素大小 samplingRate: 1, // 采样率 1(显示所有体素) vehicleRadius: 0.6, // 车辆半径 0.6米(必须 >= 体素大小才能看到膨胀效果) vehicleHeight: 1.8 // 车辆高度 1.8米 ); var result = await testCommand.ExecuteAsync(); if (result.IsSuccess) { // 显示测试结果 System.Windows.MessageBox.Show( $"体素网格 SDF 测试成功!\n\n{result.Message}\n\n详细信息请查看日志。", "体素网格 SDF 测试结果", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); UpdateMainStatus("体素网格 SDF 测试完成"); LogManager.Info($"体素网格 SDF 测试成功: {result.Message}"); } else { System.Windows.MessageBox.Show( $"体素网格 SDF 测试失败:\n{result.Message}", "体素网格 SDF 测试", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus($"体素网格 SDF 测试失败: {result.Message}"); LogManager.Error($"体素网格 SDF 测试失败: {result.Message}"); } } catch (Exception ex) { LogManager.Error($"体素网格 SDF 测试异常: {ex.Message}", ex); System.Windows.MessageBox.Show( $"体素网格 SDF 测试出现异常:\n{ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus($"体素网格 SDF 测试异常: {ex.Message}"); } }, "体素网格 SDF 测试"); } /// /// 执行体素路径规划测试(3D A*) /// private async void ExecuteTestVoxelPathFinding() { await SafeExecuteAsync(async () => { try { UpdateMainStatus("正在执行体素路径规划测试..."); LogManager.Info("开始体素路径规划测试(3D A*)"); // 获取当前文档 var document = Autodesk.Navisworks.Api.Application.ActiveDocument; if (document == null) { System.Windows.MessageBox.Show( "未找到活动文档,请先打开一个 Navisworks 模型", "体素路径规划测试", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning); UpdateMainStatus("体素路径规划测试取消:无活动文档"); return; } // 使用系统配置的网格大小参数 double cellSizeMeters = ConfigManager.Instance.Current.PathEditing.CellSizeMeters; LogManager.Info($"使用系统配置的体素大小: {cellSizeMeters}米"); // 根据可通行体素样本选择测试起点和终点 // 起点:体素(77, 41, 9) -> 世界(-116.35, 4.94, 50.16) - 模型中心、最高层 // 终点:体素(107, 11, 8) -> 世界(-67.13, -44.27, 48.52) - 偏右下、低一层 // 注意:VoxelToWorld返回的是体素左下角坐标,需要加上半个体素尺寸偏移到中心点 double voxelSizeInModelUnits = cellSizeMeters * UnitsConverter.GetMetersToUnitsConversionFactor(document.Units); double halfVoxel = voxelSizeInModelUnits / 2.0; // 起点:模型中心、最高层Z=9 var startPoint = new Autodesk.Navisworks.Api.Point3D(-200 + halfVoxel, -24.27 + halfVoxel, 42 + halfVoxel); // 终点:偏右下、低一层Z=8 var endPoint = new Autodesk.Navisworks.Api.Point3D(-116.35 + halfVoxel, 0 + halfVoxel, 45 + halfVoxel); LogManager.Info($"测试起点: ({startPoint.X:F2}, {startPoint.Y:F2}, {startPoint.Z:F2})"); LogManager.Info($"测试终点: ({endPoint.X:F2}, {endPoint.Y:F2}, {endPoint.Z:F2})"); // 创建并执行体素路径规划测试命令 var testCommand = new VoxelPathFindingTestCommand( document, cellSize: cellSizeMeters, // 体素大小(米) vehicleRadius: 0.6, // 车辆半径 0.6米 vehicleHeight: 1.8, // 车辆高度 1.8米 startPoint: startPoint, // 起点 endPoint: endPoint // 终点 ); var result = await testCommand.ExecuteAsync(); if (result.IsSuccess) { // 显示测试结果 System.Windows.MessageBox.Show( $"体素路径规划测试成功!\n\n{result.Message}\n\n详细信息请查看日志和3D视图中的路径可视化。", "体素路径规划测试结果", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); UpdateMainStatus("体素路径规划测试完成"); LogManager.Info($"体素路径规划测试成功: {result.Message}"); } else { System.Windows.MessageBox.Show( $"体素路径规划测试失败:\n{result.Message}", "体素路径规划测试", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus($"体素路径规划测试失败: {result.Message}"); LogManager.Error($"体素路径规划测试失败: {result.Message}"); } } catch (Exception ex) { LogManager.Error($"体素路径规划测试异常: {ex.Message}", ex); System.Windows.MessageBox.Show( $"体素路径规划测试出现异常:\n{ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus($"体素路径规划测试异常: {ex.Message}"); } }, "体素路径规划测试"); } /// /// 读取选中对象的Transform信息,并测试旋转 /// private void ExecuteReadTransformTest() { try { var doc = Autodesk.Navisworks.Api.Application.ActiveDocument; var selection = doc.CurrentSelection.SelectedItems; if (selection.Count == 0) { System.Windows.MessageBox.Show("请先选择一个对象!", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); return; } var item = selection[0]; var modelItems = new Autodesk.Navisworks.Api.ModelItemCollection { item }; // === 读取初始状态 === var transform1 = item.Transform; var components1 = transform1.Factor(); var bbox1 = item.BoundingBox(); var center1 = bbox1.Center; var info = $"=== 初始状态 ===\n"; info += $"对象: {item.DisplayName}\n"; info += $"包围盒中心: ({center1.X:F3}, {center1.Y:F3}, {center1.Z:F3})\n"; info += $"Transform.Translation: ({components1.Translation.X:F3}, {components1.Translation.Y:F3}, {components1.Translation.Z:F3})\n"; info += $"Transform.Rotation: {components1.Rotation}\n\n"; // === 应用旋转override === // 绕Z轴旋转45度(π/4弧度) double angle = Math.PI / 4; // 45度 var rotationTransform = new Autodesk.Navisworks.Api.Transform3D( new Autodesk.Navisworks.Api.Rotation3D( new Autodesk.Navisworks.Api.UnitVector3D(0, 0, 1), angle ) ); // 应用override(false=增量模式) doc.Models.OverridePermanentTransform(modelItems, rotationTransform, false); info += $"=== 应用旋转后(绕Z轴45度)===\n"; // === 重新读取状态 === var transform2 = item.Transform; var components2 = transform2.Factor(); var bbox2 = item.BoundingBox(); var center2 = bbox2.Center; info += $"包围盒中心: ({center2.X:F3}, {center2.Y:F3}, {center2.Z:F3})\n"; info += $"Transform.Translation: ({components2.Translation.X:F3}, {components2.Translation.Y:F3}, {components2.Translation.Z:F3})\n"; info += $"Transform.Rotation: {components2.Rotation}\n\n"; info += $"=== 对比 ===\n"; info += $"包围盒中心变化: ({center2.X - center1.X:F3}, {center2.Y - center1.Y:F3}, {center2.Z - center1.Z:F3})\n"; info += $"item.Transform是否变化: {!transform1.Equals(transform2)}\n"; LogManager.Info(info); System.Windows.MessageBox.Show(info, "Transform测试", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information); } catch (Exception ex) { System.Windows.MessageBox.Show($"错误: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); LogManager.Error($"读取Transform失败: {ex.Message}\n{ex.StackTrace}"); } } /// /// 执行坐标系探索命令 /// private void ExecuteCoordinateSystemExplorer() { SafeExecute(() => { try { UpdateMainStatus("正在执行坐标系探索..."); LogManager.Info("开始坐标系探索"); var doc = Autodesk.Navisworks.Api.Application.ActiveDocument; if (doc == null || doc.IsClear) { System.Windows.MessageBox.Show( "没有活动的文档!请先打开一个模型。", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus("坐标系探索失败:无活动文档"); return; } var sb = new StringBuilder(); sb.AppendLine("=== Navisworks 坐标系探索 ===\n"); // 1. Document 级别信息 sb.AppendLine("【1. Document 级别信息】"); sb.AppendLine($"文档名称: {doc.FileName}"); sb.AppendLine($"文档标题: {doc.Title}"); sb.AppendLine($"模型数量: {doc.Models.Count}"); sb.AppendLine(); // 2. Model 级别信息 sb.AppendLine("【2. Model 级别信息】"); int modelIndex = 0; foreach (var model in doc.Models) { sb.AppendLine($"模型 [{modelIndex}]:"); var rootItem = model.RootItem; if (rootItem != null) { sb.AppendLine($" - RootItem.DisplayName: {rootItem.DisplayName}"); var components = rootItem.Transform.Factor(); sb.AppendLine($" - Transform.Translation: ({components.Translation.X:F4}, {components.Translation.Y:F4}, {components.Translation.Z:F4})"); var rotation = components.Rotation; // Rotation3D 使用 ToAxisAndAngle() 方法获取轴和角度 var axisAngle = rotation.ToAxisAndAngle(); sb.AppendLine($" - Transform.Rotation.Axis: ({axisAngle.Axis.X:F4}, {axisAngle.Axis.Y:F4}, {axisAngle.Axis.Z:F4})"); sb.AppendLine($" - Transform.Rotation.Angle: {axisAngle.Angle:F6} rad ({axisAngle.Angle * 180 / Math.PI:F2}°)"); sb.AppendLine($" - Transform.Scale: ({components.Scale.X:F4}, {components.Scale.Y:F4}, {components.Scale.Z:F4})"); var bbox = rootItem.BoundingBox(); sb.AppendLine($" - 包围盒 Min: ({bbox.Min.X:F4}, {bbox.Min.Y:F4}, {bbox.Min.Z:F4})"); sb.AppendLine($" - 包围盒 Max: ({bbox.Max.X:F4}, {bbox.Max.Y:F4}, {bbox.Max.Z:F4})"); double xSpan = bbox.Max.X - bbox.Min.X; double ySpan = bbox.Max.Y - bbox.Min.Y; double zSpan = bbox.Max.Z - bbox.Min.Z; sb.AppendLine($" - 跨度: X={xSpan:F2}, Y={ySpan:F2}, Z={zSpan:F2}"); sb.AppendLine($" - 坐标系推测: {(ySpan > zSpan * 2 ? "可能是 Y-Up" : "可能是 Z-Up")}"); } sb.AppendLine(); modelIndex++; } // 3. Document 坐标系向量 (直接来自模型) sb.AppendLine("【3. Document 坐标系向量 (模型原始)】"); var docUp = doc.UpVector; var docRight = doc.RightVector; var docFront = doc.FrontVector; if (docUp.IsZero) { sb.AppendLine("UpVector: (0, 0, 0) - 未定义"); } else { sb.AppendLine($"UpVector: ({docUp.X:F4}, {docUp.Y:F4}, {docUp.Z:F4})"); } if (docRight.IsZero) { sb.AppendLine("RightVector: (0, 0, 0) - 未定义"); } else { sb.AppendLine($"RightVector: ({docRight.X:F4}, {docRight.Y:F4}, {docRight.Z:F4})"); } if (docFront.IsZero) { sb.AppendLine("FrontVector: (0, 0, 0) - 未定义"); } else { sb.AppendLine($"FrontVector: ({docFront.X:F4}, {docFront.Y:F4}, {docFront.Z:F4})"); } sb.AppendLine(); // 4. Viewpoint 信息 (Navisworks 处理后的) sb.AppendLine("【4. Viewpoint 信息 (Navisworks 处理后)】"); var vp = doc.CurrentViewpoint.Value; sb.AppendLine($"WorldUpVector: ({vp.WorldUpVector.X:F4}, {vp.WorldUpVector.Y:F4}, {vp.WorldUpVector.Z:F4})"); sb.AppendLine($"Position: ({vp.Position.X:F4}, {vp.Position.Y:F4}, {vp.Position.Z:F4})"); var vpRotation = vp.Rotation.ToAxisAndAngle(); sb.AppendLine($"Rotation.Axis: ({vpRotation.Axis.X:F4}, {vpRotation.Axis.Y:F4}, {vpRotation.Axis.Z:F4})"); sb.AppendLine($"Rotation.Angle: {vpRotation.Angle:F6} rad"); sb.AppendLine(); // 5. 坐标系推测总结 sb.AppendLine("【5. 坐标系推测总结】"); // 方法1: 优先使用 Document.UpVector 判断(模型原始定义) sb.AppendLine($"方法1 - Document.UpVector (原始):"); if (!docUp.IsZero) { sb.AppendLine($" 值: ({docUp.X:F4}, {docUp.Y:F4}, {docUp.Z:F4})"); if (Math.Abs(docUp.Z) > 0.9) { sb.AppendLine($" ✅ 判定: Z-Up 坐标系 (原始)"); } else if (Math.Abs(docUp.Y) > 0.9) { sb.AppendLine($" ✅ 判定: Y-Up 坐标系 (原始)"); } else if (Math.Abs(docUp.X) > 0.9) { sb.AppendLine($" ⚠️ 判定: X-Up 坐标系 (罕见)"); } } else { sb.AppendLine($" 未定义 (Zero),需使用 Viewpoint.WorldUpVector"); } sb.AppendLine(); // 方法2: 使用 WorldUpVector 判断(Navisworks 处理后的,最可靠) var worldUp = doc.CurrentViewpoint.Value.WorldUpVector; sb.AppendLine($"方法2 - Viewpoint.WorldUpVector (推荐):"); sb.AppendLine($" 值: ({worldUp.X:F4}, {worldUp.Y:F4}, {worldUp.Z:F4})"); string detectedCoordinateSystem = "Unknown"; if (Math.Abs(worldUp.Z) > 0.9) { sb.AppendLine($" ✅ 判定: Z-Up 坐标系 (Z轴向上)"); sb.AppendLine($" 说明: 这是 Navisworks 默认坐标系,插件无需特殊配置"); detectedCoordinateSystem = "ZUp"; } else if (Math.Abs(worldUp.Y) > 0.9) { sb.AppendLine($" ✅ 判定: Y-Up 坐标系 (Y轴向上)"); sb.AppendLine($" 说明: 通常是 Revit 等软件导出的模型"); sb.AppendLine($" 建议: 在 default_config.toml 中设置坐标系为 YUp"); detectedCoordinateSystem = "YUp"; } else if (Math.Abs(worldUp.X) > 0.9) { sb.AppendLine($" ⚠️ 判定: X-Up 坐标系 (罕见)"); sb.AppendLine($" 说明: 非标准坐标系,需要手动适配"); detectedCoordinateSystem = "XUp"; } else { sb.AppendLine($" ❓ 判定: 无法确定(非标准向上向量)"); } sb.AppendLine(); // 方法3: 通过模型 Transform 旋转判断(辅助验证) sb.AppendLine($"方法3 - 模型 Transform 旋转:"); if (doc.Models.Count > 0) { var rootItem = doc.Models[0].RootItem; if (rootItem != null) { var components = rootItem.Transform.Factor(); var rotation = components.Rotation.ToAxisAndAngle(); double angleDegrees = rotation.Angle * 180 / Math.PI; sb.AppendLine($" 旋转轴: ({rotation.Axis.X:F4}, {rotation.Axis.Y:F4}, {rotation.Axis.Z:F4})"); sb.AppendLine($" 旋转角: {angleDegrees:F2}°"); // 检查是否有 90° 或 270° 绕 X 轴旋转(Y-Up 模型的典型特征) if (Math.Abs(rotation.Axis.X) > 0.9 && (Math.Abs(angleDegrees - 90) < 5 || Math.Abs(angleDegrees - 270) < 5)) { sb.AppendLine($" ✅ 发现 X 轴旋转 ~{angleDegrees:F0}°,这是 Y-Up 导入的典型特征"); } else if (Math.Abs(angleDegrees) < 1) { sb.AppendLine($" 无显著旋转,符合 Z-Up 模型特征"); } } } sb.AppendLine(); // 方法4: 包围盒跨度分析(启发式) sb.AppendLine($"方法4 - 包围盒跨度分析(启发式):"); if (doc.Models.Count > 0) { var rootBounds = doc.Models[0].RootItem.BoundingBox(); double xSpan = rootBounds.Max.X - rootBounds.Min.X; double ySpan = rootBounds.Max.Y - rootBounds.Min.Y; double zSpan = rootBounds.Max.Z - rootBounds.Min.Z; sb.AppendLine($" X 跨度: {xSpan:F2} 单位"); sb.AppendLine($" Y 跨度: {ySpan:F2} 单位"); sb.AppendLine($" Z 跨度: {zSpan:F2} 单位"); // 注意:经过旋转后,Y-Up 模型在 Navisworks 中显示为 Z-Up // 所以这里看到的是转换后的坐标 if (zSpan > ySpan * 1.5) { sb.AppendLine($" Z 跨度大于 Y 跨度,显示为 Z-Up 方向"); } else if (ySpan > zSpan * 1.5) { sb.AppendLine($" Y 跨度大于 Z 跨度,可能未完全转换"); } } sb.AppendLine(); // 最终建议 sb.AppendLine($"【最终建议】"); if (detectedCoordinateSystem == "YUp") { sb.AppendLine($"⚠️ 检测到 Y-Up 坐标系!"); sb.AppendLine($"当前插件使用 Z-Up 假设,在此模型上可能出现问题。"); sb.AppendLine($"建议:实施坐标系动态适配功能。"); } else if (detectedCoordinateSystem == "ZUp") { sb.AppendLine($"✅ 标准 Z-Up 坐标系,插件应正常工作。"); } // 显示和记录结果 string result = sb.ToString(); LogManager.Info(result); // 使用可复制的对话框显示结果 var resultDialog = new NavisworksTransport.UI.WPF.Views.CoordinateSystemResultDialog { Title = "坐标系探索结果", ResultText = result }; // 尝试设置对话框所有者 try { var mainWindow = System.Windows.Application.Current?.MainWindow; if (mainWindow != null && mainWindow.IsLoaded) { resultDialog.Owner = mainWindow; } else { foreach (System.Windows.Window window in System.Windows.Application.Current.Windows) { if (window.IsActive && window.IsLoaded) { resultDialog.Owner = window; break; } } } } catch { } resultDialog.ShowDialog(); UpdateMainStatus("坐标系探索完成"); LogManager.Info("坐标系探索成功完成"); } catch (Exception ex) { LogManager.Error($"坐标系探索异常: {ex.Message}", ex); System.Windows.MessageBox.Show( $"坐标系探索出现异常:\n{ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); UpdateMainStatus($"坐标系探索异常: {ex.Message}"); } }, "坐标系探索"); } #endregion #region 辅助方法 /// /// 安全执行异步操作 /// private async Task SafeExecuteAsync(Func action, string operationName = "未知操作") { try { await action(); } catch (Exception ex) { LogManager.Error($"{operationName}发生异常: {ex.Message}", ex); UpdateMainStatus($"{operationName}失败: {ex.Message}"); } } /// /// 安全执行同步操作 /// private void SafeExecute(Action action, string operationName = "未知操作") { try { action(); } catch (Exception ex) { LogManager.Error($"{operationName}发生异常: {ex.Message}", ex); UpdateMainStatus($"{operationName}失败: {ex.Message}"); } } /// /// 验证ViewModel状态是否正常 /// public bool IsValidState() { return _uiStateManager != null && LogLevels != null; } /// /// 获取ViewModel状态信息 /// public string GetStateInfo() { return $"UIStateManager: {(_uiStateManager != null ? "已初始化" : "未初始化")}, " + $"日志级别数量: {LogLevels?.Count ?? 0}"; } #endregion #region 清理资源和IDisposable实现 /// /// 释放资源 /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// 释放资源的具体实现 /// /// 是否正在释放托管资源 protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { try { // 调用现有的清理逻辑 Cleanup(); LogManager.Info("SystemManagementViewModel已正确释放资源 (IDisposable)"); } catch (Exception ex) { LogManager.Error($"SystemManagementViewModel释放资源时发生异常: {ex.Message}", ex); } } _disposed = true; } } public void Cleanup() { try { LogManager.Info("开始清理SystemManagementViewModel资源"); // 取消订阅文档相关事件 UnsubscribeFromDocumentEvents(); // 停止性能监控Idle任务,替代DispatcherTimer清理 try { IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor"); LogManager.Info("SystemManagementViewModel性能监控Idle任务已停止"); } catch (Exception ex) { LogManager.Warning($"停止性能监控Idle任务时出现警告: {ex.Message}"); } // 清理可能的一次性任务 try { IdleEventManager.Instance.UnregisterTask("SystemManagement_CheckUpdate"); IdleEventManager.Instance.UnregisterTask("SystemManagement_GenerateReport"); LogManager.Debug("SystemManagementViewModel一次性Idle任务已清理"); } catch (Exception ex) { LogManager.Debug($"清理一次性Idle任务时出现提示: {ex.Message}"); } LogManager.Info("SystemManagementViewModel资源清理完成"); } catch (Exception ex) { LogManager.Error($"SystemManagementViewModel清理失败: {ex.Message}"); } } #endregion } }