1900 lines
79 KiB
C#
1900 lines
79 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 系统管理ViewModel - 处理插件系统管理功能
|
||
/// </summary>
|
||
public class SystemManagementViewModel : ViewModelBase, IDisposable
|
||
{
|
||
#region 私有字段
|
||
|
||
private readonly UIStateManager _uiStateManager;
|
||
|
||
// 日志管理字段
|
||
private ObservableCollection<string> _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 公共属性
|
||
|
||
/// <summary>
|
||
/// 日志级别集合
|
||
/// </summary>
|
||
public ObservableCollection<string> LogLevels
|
||
{
|
||
get => _logLevels;
|
||
set => SetProperty(ref _logLevels, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选中的日志级别
|
||
/// </summary>
|
||
public string SelectedLogLevel
|
||
{
|
||
get => _selectedLogLevel;
|
||
set
|
||
{
|
||
if (SetProperty(ref _selectedLogLevel, value))
|
||
{
|
||
// 将字符串转换为LogLevel枚举并设置
|
||
if (Enum.TryParse<LogLevel>(value, out var level))
|
||
{
|
||
LogManager.SetLogLevel(level);
|
||
LogManager.Info($"日志级别已更改为: {value}");
|
||
UpdateMainStatus($"日志级别已设置为: {value}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 插件版本
|
||
/// </summary>
|
||
public string PluginVersion
|
||
{
|
||
get => _pluginVersion;
|
||
set => SetProperty(ref _pluginVersion, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Navisworks版本
|
||
/// </summary>
|
||
public string NavisworksVersion
|
||
{
|
||
get => _navisworksVersion;
|
||
set => SetProperty(ref _navisworksVersion, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内存使用情况
|
||
/// </summary>
|
||
public string MemoryUsage
|
||
{
|
||
get => _memoryUsage;
|
||
set => SetProperty(ref _memoryUsage, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 运行时间
|
||
/// </summary>
|
||
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<int> BackupKeepCountOptions { get; } = new ObservableCollection<int> { 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<string> 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<string>();
|
||
|
||
// 初始化命令
|
||
InitializeCommands();
|
||
|
||
// 初始化系统管理设置
|
||
_ = InitializeSystemManagementSettingsAsync();
|
||
|
||
// 订阅文档切换事件,以便重新检测坐标系
|
||
SubscribeToDocumentEvents();
|
||
|
||
LogManager.Info("SystemManagementViewModel构造函数执行完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
|
||
|
||
// 在构造函数中尽量保证对象处于可用状态
|
||
UpdateMainStatus("初始化失败,请检查日志");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 带主ViewModel参数的构造函数,支持统一状态栏
|
||
/// </summary>
|
||
/// <param name="mainViewModel">主ViewModel,用于统一状态栏</param>
|
||
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<string>();
|
||
|
||
// 初始化命令
|
||
InitializeCommands();
|
||
|
||
// 初始化系统管理设置
|
||
_ = InitializeSystemManagementSettingsAsync();
|
||
|
||
LogManager.Info("SystemManagementViewModel构造函数执行完成 - 支持统一状态栏");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
|
||
|
||
// 在构造函数中尽量保证对象处于可用状态
|
||
UpdateMainStatus("初始化失败,请检查日志");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 初始化
|
||
|
||
/// <summary>
|
||
/// 初始化命令
|
||
/// </summary>
|
||
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<string> { "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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取路径规划管理器实例
|
||
/// </summary>
|
||
/// <returns>路径规划管理器或null</returns>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化坐标系
|
||
/// </summary>
|
||
private void InitializeCoordinateSystem()
|
||
{
|
||
try
|
||
{
|
||
// 解析配置类型
|
||
if (!Enum.TryParse<CoordinateSystemType>(_selectedCoordinateSystem, out var configType))
|
||
{
|
||
configType = CoordinateSystemType.AutoDetect;
|
||
}
|
||
|
||
// 初始化坐标系管理器
|
||
CoordinateSystemManager.Instance.Initialize(configType);
|
||
|
||
// 更新显示信息
|
||
UpdateCoordinateSystemInfo();
|
||
|
||
LogManager.Info($"坐标系初始化完成: {configType}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"坐标系初始化失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 坐标系选择改变时调用
|
||
/// </summary>
|
||
private void OnCoordinateSystemChanged(string newValue)
|
||
{
|
||
try
|
||
{
|
||
if (!Enum.TryParse<CoordinateSystemType>(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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新坐标系显示信息
|
||
/// </summary>
|
||
private void UpdateCoordinateSystemInfo()
|
||
{
|
||
var info = CoordinateSystemManager.Instance.GetCurrentInfo();
|
||
CurrentCoordinateSystemInfo = $"当前坐标系: {info}";
|
||
}
|
||
|
||
#region 文档事件处理
|
||
|
||
/// <summary>
|
||
/// 订阅文档切换事件
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消订阅文档事件
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 文档切换事件处理
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 模型集合变化事件处理(SDI架构下的真正文档变化)
|
||
/// </summary>
|
||
private void OnModelsCollectionChanged(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
LogManager.Info("[系统管理] 检测到模型集合变化");
|
||
HandleDocumentChange();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[系统管理] 模型集合变化处理失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理文档变化,重新检测坐标系
|
||
/// </summary>
|
||
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
|
||
|
||
/// <summary>
|
||
/// 初始化系统管理设置
|
||
/// </summary>
|
||
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 命令实现
|
||
|
||
|
||
/// <summary>
|
||
/// 查看日志
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}, "查看日志");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打开设置
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}, "打开设置");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查更新 (已优化为Idle事件监听)
|
||
/// </summary>
|
||
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事件监听)");
|
||
}, "检查更新");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成性能报告 (已优化为Idle事件监听)
|
||
/// </summary>
|
||
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事件监听)");
|
||
}, "生成性能报告");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行环境诊断
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}, "环境诊断");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 环境诊断方法 - 快速检查API是否可用
|
||
/// </summary>
|
||
/// <returns>诊断报告</returns>
|
||
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 数据管理方法
|
||
|
||
/// <summary>
|
||
/// 刷新数据库状态信息
|
||
/// </summary>
|
||
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 = "错误";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行数据备份
|
||
/// </summary>
|
||
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("数据备份失败");
|
||
}
|
||
}, "数据备份");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行数据恢复
|
||
/// </summary>
|
||
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("数据恢复失败");
|
||
}
|
||
}, "数据恢复");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行数据库修复
|
||
/// </summary>
|
||
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("数据库修复失败");
|
||
}
|
||
}, "数据库修复");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行清空所有数据
|
||
/// </summary>
|
||
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
|
||
|
||
/// <summary>
|
||
/// 执行体素网格 SDF 测试(使用 MeshSignedDistanceGrid)
|
||
/// </summary>
|
||
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 测试");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行体素路径规划测试(3D A*)
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}, "体素路径规划测试");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取选中对象的Transform信息,并测试旋转
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行坐标系探索命令
|
||
/// </summary>
|
||
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 辅助方法
|
||
|
||
/// <summary>
|
||
/// 安全执行异步操作
|
||
/// </summary>
|
||
private async Task SafeExecuteAsync(Func<Task> action, string operationName = "未知操作")
|
||
{
|
||
try
|
||
{
|
||
await action();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
|
||
UpdateMainStatus($"{operationName}失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全执行同步操作
|
||
/// </summary>
|
||
private void SafeExecute(Action action, string operationName = "未知操作")
|
||
{
|
||
try
|
||
{
|
||
action();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
|
||
UpdateMainStatus($"{operationName}失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证ViewModel状态是否正常
|
||
/// </summary>
|
||
public bool IsValidState()
|
||
{
|
||
return _uiStateManager != null && LogLevels != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取ViewModel状态信息
|
||
/// </summary>
|
||
public string GetStateInfo()
|
||
{
|
||
return $"UIStateManager: {(_uiStateManager != null ? "已初始化" : "未初始化")}, " +
|
||
$"日志级别数量: {LogLevels?.Count ?? 0}";
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 清理资源和IDisposable实现
|
||
|
||
/// <summary>
|
||
/// 释放资源
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
Dispose(true);
|
||
GC.SuppressFinalize(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放资源的具体实现
|
||
/// </summary>
|
||
/// <param name="disposing">是否正在释放托管资源</param>
|
||
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
|
||
}
|
||
} |