重新设计了路径可视化机制,重构了系统管理UI
This commit is contained in:
parent
1add8c6410
commit
0e20be9e86
Binary file not shown.
@ -193,6 +193,7 @@
|
||||
<Compile Include="src\UI\WPF\ViewModels\ModelSettingsViewModel.cs" />
|
||||
<Compile Include="src\UI\WPF\ViewModels\AnimationControlViewModel.cs" />
|
||||
<Compile Include="src\UI\WPF\ViewModels\PathEditingViewModel.cs" />
|
||||
<Compile Include="src\UI\WPF\ViewModels\SystemManagementViewModel.cs" />
|
||||
|
||||
<!-- UI - WPF Simplified Controls -->
|
||||
<Compile Include="src\UI\WPF\SimpleLogisticsControlPanel.cs" />
|
||||
|
||||
897
SystemManagementViewModel_Design.cs
Normal file
897
SystemManagementViewModel_Design.cs
Normal file
@ -0,0 +1,897 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统管理ViewModel - 参照PathEditingViewModel的设计模式
|
||||
/// 专门负责系统管理相关功能,包括:日志管理、设置管理、性能监控、版本控制、配置管理等
|
||||
/// </summary>
|
||||
public class SystemManagementViewModel : ViewModelBase
|
||||
{
|
||||
#region 私有字段
|
||||
|
||||
// 依赖注入的核心服务
|
||||
private readonly UIStateManager _uiStateManager;
|
||||
|
||||
// 系统管理相关的管理器实例(通过依赖注入)
|
||||
private ISystemLogManager _logManager;
|
||||
private ISystemConfigManager _configManager;
|
||||
private IPerformanceMonitor _performanceMonitor;
|
||||
private IModelSplitterManager _modelSplitterManager;
|
||||
|
||||
// 日志管理相关字段
|
||||
private ObservableCollection<string> _logLevels;
|
||||
private string _selectedLogLevel = "Info";
|
||||
private string _logStatus = "日志系统正常";
|
||||
private int _logEntryCount = 0;
|
||||
private string _logFilePath = "未设置";
|
||||
|
||||
// 系统设置相关字段
|
||||
private bool _isAutoSaveEnabled = true;
|
||||
private bool _isDebugModeEnabled = false;
|
||||
private string _settingsStatus = "设置已加载";
|
||||
private int _autoSaveInterval = 300; // 秒
|
||||
private string _workingDirectory = "";
|
||||
|
||||
// 版本和系统信息相关字段
|
||||
private string _pluginVersion = "v1.0";
|
||||
private string _navisworksVersion = "2026";
|
||||
private string _systemStatus = "正常";
|
||||
private string _systemStatusColor = "Green";
|
||||
private string _lastUpdateCheck = "未检查";
|
||||
|
||||
// 性能监控相关字段
|
||||
private string _memoryUsage = "0 MB";
|
||||
private string _runningTime = "00:00:00";
|
||||
private string _performanceInfo = "性能监控就绪";
|
||||
private double _cpuUsage = 0.0;
|
||||
private int _threadsCount = 0;
|
||||
private DispatcherTimer _performanceTimer;
|
||||
|
||||
// 模型分割器相关字段
|
||||
private string _modelSplitterStatus = "就绪";
|
||||
private bool _canRunModelSplitter = true;
|
||||
private string _lastSplitResult = "未执行";
|
||||
|
||||
// 配置管理相关字段
|
||||
private string _currentConfigProfile = "默认配置";
|
||||
private ObservableCollection<string> _availableProfiles;
|
||||
private bool _hasUnsavedChanges = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共属性
|
||||
|
||||
#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))
|
||||
{
|
||||
OnLogLevelChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志系统状态
|
||||
/// </summary>
|
||||
public string LogStatus
|
||||
{
|
||||
get => _logStatus;
|
||||
set => SetProperty(ref _logStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志条目数量
|
||||
/// </summary>
|
||||
public int LogEntryCount
|
||||
{
|
||||
get => _logEntryCount;
|
||||
set => SetProperty(ref _logEntryCount, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志文件路径
|
||||
/// </summary>
|
||||
public string LogFilePath
|
||||
{
|
||||
get => _logFilePath;
|
||||
set => SetProperty(ref _logFilePath, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 系统设置属性
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用自动保存
|
||||
/// </summary>
|
||||
public bool IsAutoSaveEnabled
|
||||
{
|
||||
get => _isAutoSaveEnabled;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isAutoSaveEnabled, value))
|
||||
{
|
||||
OnAutoSaveSettingChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用调试模式
|
||||
/// </summary>
|
||||
public bool IsDebugModeEnabled
|
||||
{
|
||||
get => _isDebugModeEnabled;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isDebugModeEnabled, value))
|
||||
{
|
||||
OnDebugModeChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置状态
|
||||
/// </summary>
|
||||
public string SettingsStatus
|
||||
{
|
||||
get => _settingsStatus;
|
||||
set => SetProperty(ref _settingsStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动保存间隔(秒)
|
||||
/// </summary>
|
||||
public int AutoSaveInterval
|
||||
{
|
||||
get => _autoSaveInterval;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _autoSaveInterval, value))
|
||||
{
|
||||
OnAutoSaveIntervalChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 工作目录
|
||||
/// </summary>
|
||||
public string WorkingDirectory
|
||||
{
|
||||
get => _workingDirectory;
|
||||
set => SetProperty(ref _workingDirectory, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 版本和系统信息属性
|
||||
|
||||
/// <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 SystemStatus
|
||||
{
|
||||
get => _systemStatus;
|
||||
set => SetProperty(ref _systemStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态颜色
|
||||
/// </summary>
|
||||
public string SystemStatusColor
|
||||
{
|
||||
get => _systemStatusColor;
|
||||
set => SetProperty(ref _systemStatusColor, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新检查时间
|
||||
/// </summary>
|
||||
public string LastUpdateCheck
|
||||
{
|
||||
get => _lastUpdateCheck;
|
||||
set => SetProperty(ref _lastUpdateCheck, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 性能监控属性
|
||||
|
||||
/// <summary>
|
||||
/// 内存使用情况
|
||||
/// </summary>
|
||||
public string MemoryUsage
|
||||
{
|
||||
get => _memoryUsage;
|
||||
set => SetProperty(ref _memoryUsage, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行时间
|
||||
/// </summary>
|
||||
public string RunningTime
|
||||
{
|
||||
get => _runningTime;
|
||||
set => SetProperty(ref _runningTime, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能信息
|
||||
/// </summary>
|
||||
public string PerformanceInfo
|
||||
{
|
||||
get => _performanceInfo;
|
||||
set => SetProperty(ref _performanceInfo, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CPU使用率
|
||||
/// </summary>
|
||||
public double CpuUsage
|
||||
{
|
||||
get => _cpuUsage;
|
||||
set => SetProperty(ref _cpuUsage, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 线程数量
|
||||
/// </summary>
|
||||
public int ThreadsCount
|
||||
{
|
||||
get => _threadsCount;
|
||||
set => SetProperty(ref _threadsCount, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 模型分割器属性
|
||||
|
||||
/// <summary>
|
||||
/// 模型分层拆分状态
|
||||
/// </summary>
|
||||
public string ModelSplitterStatus
|
||||
{
|
||||
get => _modelSplitterStatus;
|
||||
set => SetProperty(ref _modelSplitterStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以运行模型分割器
|
||||
/// </summary>
|
||||
public bool CanRunModelSplitter
|
||||
{
|
||||
get => _canRunModelSplitter;
|
||||
set => SetProperty(ref _canRunModelSplitter, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最后分割结果
|
||||
/// </summary>
|
||||
public string LastSplitResult
|
||||
{
|
||||
get => _lastSplitResult;
|
||||
set => SetProperty(ref _lastSplitResult, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 配置管理属性
|
||||
|
||||
/// <summary>
|
||||
/// 当前配置档案
|
||||
/// </summary>
|
||||
public string CurrentConfigProfile
|
||||
{
|
||||
get => _currentConfigProfile;
|
||||
set => SetProperty(ref _currentConfigProfile, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 可用配置档案
|
||||
/// </summary>
|
||||
public ObservableCollection<string> AvailableProfiles
|
||||
{
|
||||
get => _availableProfiles;
|
||||
set => SetProperty(ref _availableProfiles, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否有未保存的更改
|
||||
/// </summary>
|
||||
public bool HasUnsavedChanges
|
||||
{
|
||||
get => _hasUnsavedChanges;
|
||||
set => SetProperty(ref _hasUnsavedChanges, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令定义
|
||||
|
||||
// 日志管理命令
|
||||
public ICommand ViewLogCommand { get; private set; }
|
||||
public ICommand ClearLogCommand { get; private set; }
|
||||
public ICommand ExportLogCommand { get; private set; }
|
||||
public ICommand RefreshLogStatusCommand { get; private set; }
|
||||
|
||||
// 设置管理命令
|
||||
public ICommand OpenSettingsCommand { get; private set; }
|
||||
public ICommand ResetSettingsCommand { get; private set; }
|
||||
public ICommand SaveSettingsCommand { get; private set; }
|
||||
public ICommand LoadSettingsCommand { get; private set; }
|
||||
|
||||
// 配置管理命令
|
||||
public ICommand ImportConfigCommand { get; private set; }
|
||||
public ICommand ExportConfigCommand { get; private set; }
|
||||
public ICommand CreateProfileCommand { get; private set; }
|
||||
public ICommand DeleteProfileCommand { get; private set; }
|
||||
public ICommand SwitchProfileCommand { get; private set; }
|
||||
|
||||
// 系统管理命令
|
||||
public ICommand CheckUpdateCommand { get; private set; }
|
||||
public ICommand RestartSystemCommand { get; private set; }
|
||||
public ICommand SystemDiagnosticsCommand { get; private set; }
|
||||
|
||||
// 性能管理命令
|
||||
public ICommand GeneratePerformanceReportCommand { get; private set; }
|
||||
public ICommand StartPerformanceMonitoringCommand { get; private set; }
|
||||
public ICommand StopPerformanceMonitoringCommand { get; private set; }
|
||||
public ICommand ClearPerformanceDataCommand { get; private set; }
|
||||
|
||||
// 模型分割器命令
|
||||
public ICommand RunModelSplitterCommand { get; private set; }
|
||||
public ICommand ConfigureModelSplitterCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数 - 参照PathEditingViewModel的设计模式
|
||||
/// </summary>
|
||||
/// <param name="logManager">日志管理器(可选,用于依赖注入)</param>
|
||||
/// <param name="configManager">配置管理器(可选,用于依赖注入)</param>
|
||||
/// <param name="performanceMonitor">性能监控器(可选,用于依赖注入)</param>
|
||||
/// <param name="modelSplitterManager">模型分割器管理器(可选,用于依赖注入)</param>
|
||||
public SystemManagementViewModel(
|
||||
ISystemLogManager logManager = null,
|
||||
ISystemConfigManager configManager = null,
|
||||
IPerformanceMonitor performanceMonitor = null,
|
||||
IModelSplitterManager modelSplitterManager = null) : base()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取UI状态管理器
|
||||
_uiStateManager = UIStateManager.Instance;
|
||||
if (_uiStateManager == null)
|
||||
{
|
||||
throw new InvalidOperationException("UIStateManager初始化失败");
|
||||
}
|
||||
|
||||
// 设置依赖(如果为null则使用默认实现)
|
||||
_logManager = logManager ?? CreateDefaultLogManager();
|
||||
_configManager = configManager ?? CreateDefaultConfigManager();
|
||||
_performanceMonitor = performanceMonitor ?? CreateDefaultPerformanceMonitor();
|
||||
_modelSplitterManager = modelSplitterManager ?? CreateDefaultModelSplitterManager();
|
||||
|
||||
// 初始化集合
|
||||
LogLevels = new ThreadSafeObservableCollection<string>();
|
||||
AvailableProfiles = new ThreadSafeObservableCollection<string>();
|
||||
|
||||
// 初始化命令
|
||||
InitializeCommands();
|
||||
|
||||
// 初始化系统管理设置(异步)
|
||||
InitializeSystemManagementAsync();
|
||||
|
||||
LogManager.Info("SystemManagementViewModel构造函数执行完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
|
||||
SystemStatus = "初始化失败,请检查日志";
|
||||
SystemStatusColor = "Red";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 初始化方法
|
||||
|
||||
/// <summary>
|
||||
/// 初始化命令
|
||||
/// </summary>
|
||||
private void InitializeCommands()
|
||||
{
|
||||
// 日志管理命令
|
||||
ViewLogCommand = new RelayCommand(async () => await ExecuteViewLogAsync());
|
||||
ClearLogCommand = new RelayCommand(async () => await ExecuteClearLogAsync());
|
||||
ExportLogCommand = new RelayCommand(async () => await ExecuteExportLogAsync());
|
||||
RefreshLogStatusCommand = new RelayCommand(async () => await ExecuteRefreshLogStatusAsync());
|
||||
|
||||
// 设置管理命令
|
||||
OpenSettingsCommand = new RelayCommand(async () => await ExecuteOpenSettingsAsync());
|
||||
ResetSettingsCommand = new RelayCommand(async () => await ExecuteResetSettingsAsync());
|
||||
SaveSettingsCommand = new RelayCommand(async () => await ExecuteSaveSettingsAsync());
|
||||
LoadSettingsCommand = new RelayCommand(async () => await ExecuteLoadSettingsAsync());
|
||||
|
||||
// 配置管理命令
|
||||
ImportConfigCommand = new RelayCommand(async () => await ExecuteImportConfigAsync());
|
||||
ExportConfigCommand = new RelayCommand(async () => await ExecuteExportConfigAsync());
|
||||
CreateProfileCommand = new RelayCommand(async () => await ExecuteCreateProfileAsync());
|
||||
DeleteProfileCommand = new RelayCommand(async () => await ExecuteDeleteProfileAsync());
|
||||
SwitchProfileCommand = new RelayCommand<string>(async (profile) => await ExecuteSwitchProfileAsync(profile));
|
||||
|
||||
// 系统管理命令
|
||||
CheckUpdateCommand = new RelayCommand(async () => await ExecuteCheckUpdateAsync());
|
||||
RestartSystemCommand = new RelayCommand(async () => await ExecuteRestartSystemAsync());
|
||||
SystemDiagnosticsCommand = new RelayCommand(async () => await ExecuteSystemDiagnosticsAsync());
|
||||
|
||||
// 性能管理命令
|
||||
GeneratePerformanceReportCommand = new RelayCommand(async () => await ExecuteGeneratePerformanceReportAsync());
|
||||
StartPerformanceMonitoringCommand = new RelayCommand(async () => await ExecuteStartPerformanceMonitoringAsync());
|
||||
StopPerformanceMonitoringCommand = new RelayCommand(async () => await ExecuteStopPerformanceMonitoringAsync());
|
||||
ClearPerformanceDataCommand = new RelayCommand(async () => await ExecuteClearPerformanceDataAsync());
|
||||
|
||||
// 模型分割器命令
|
||||
RunModelSplitterCommand = new RelayCommand(async () => await ExecuteRunModelSplitterAsync(), () => CanRunModelSplitter);
|
||||
ConfigureModelSplitterCommand = new RelayCommand(async () => await ExecuteConfigureModelSplitterAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步初始化系统管理设置
|
||||
/// </summary>
|
||||
private async void InitializeSystemManagementAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
// 初始化日志级别
|
||||
LogLevels.Clear();
|
||||
var logLevels = new[] { "Debug", "Info", "Warning", "Error" };
|
||||
foreach (var level in logLevels)
|
||||
{
|
||||
LogLevels.Add(level);
|
||||
}
|
||||
SelectedLogLevel = "Info";
|
||||
|
||||
// 初始化配置档案
|
||||
AvailableProfiles.Clear();
|
||||
var profiles = new[] { "默认配置", "开发配置", "生产配置", "测试配置" };
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
AvailableProfiles.Add(profile);
|
||||
}
|
||||
CurrentConfigProfile = "默认配置";
|
||||
|
||||
// 初始化系统信息
|
||||
PluginVersion = GetPluginVersion();
|
||||
NavisworksVersion = GetNavisworksVersion();
|
||||
SystemStatus = "正常";
|
||||
SystemStatusColor = "Green";
|
||||
WorkingDirectory = GetWorkingDirectory();
|
||||
LogFilePath = GetLogFilePath();
|
||||
});
|
||||
|
||||
// 启动性能监控
|
||||
await StartPerformanceMonitoring();
|
||||
|
||||
LogManager.Info("系统管理设置初始化完成");
|
||||
}, "初始化系统管理设置");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令实现
|
||||
|
||||
// 这里只展示架构框架,具体实现方法将在后续详细说明
|
||||
|
||||
#region 日志管理命令实现
|
||||
|
||||
private async Task ExecuteViewLogAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
// TODO: 实现日志查看功能
|
||||
await _logManager.OpenLogViewerAsync();
|
||||
LogStatus = "日志查看器已打开";
|
||||
}, "查看日志");
|
||||
}
|
||||
|
||||
private async Task ExecuteClearLogAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
// TODO: 实现日志清空功能
|
||||
await _logManager.ClearLogsAsync();
|
||||
LogEntryCount = 0;
|
||||
LogStatus = "日志已清空";
|
||||
}, "清空日志");
|
||||
}
|
||||
|
||||
private async Task ExecuteExportLogAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
// TODO: 实现日志导出功能
|
||||
var exportPath = await _logManager.ExportLogsAsync();
|
||||
LogStatus = $"日志已导出到: {exportPath}";
|
||||
}, "导出日志");
|
||||
}
|
||||
|
||||
private async Task ExecuteRefreshLogStatusAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
// TODO: 实现日志状态刷新功能
|
||||
var status = await _logManager.GetLogStatusAsync();
|
||||
LogStatus = status.Message;
|
||||
LogEntryCount = status.EntryCount;
|
||||
LogFilePath = status.FilePath;
|
||||
}, "刷新日志状态");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// 其他命令实现方法...
|
||||
// (这里省略具体实现,在实际代码中会完整实现)
|
||||
|
||||
#endregion
|
||||
|
||||
#region 事件处理
|
||||
|
||||
/// <summary>
|
||||
/// 处理日志级别改变事件
|
||||
/// </summary>
|
||||
private void OnLogLevelChanged()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
_logManager?.SetLogLevel(SelectedLogLevel);
|
||||
LogStatus = $"日志级别已设置为: {SelectedLogLevel}";
|
||||
}, "设置日志级别");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理自动保存设置改变事件
|
||||
/// </summary>
|
||||
private void OnAutoSaveSettingChanged()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
_configManager?.SetAutoSaveEnabled(IsAutoSaveEnabled);
|
||||
SettingsStatus = $"自动保存: {(IsAutoSaveEnabled ? "已启用" : "已禁用")}";
|
||||
HasUnsavedChanges = true;
|
||||
}, "设置自动保存");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理调试模式改变事件
|
||||
/// </summary>
|
||||
private void OnDebugModeChanged()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
_configManager?.SetDebugMode(IsDebugModeEnabled);
|
||||
SettingsStatus = $"调试模式: {(IsDebugModeEnabled ? "已启用" : "已禁用")}";
|
||||
HasUnsavedChanges = true;
|
||||
}, "设置调试模式");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理自动保存间隔改变事件
|
||||
/// </summary>
|
||||
private void OnAutoSaveIntervalChanged()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
_configManager?.SetAutoSaveInterval(AutoSaveInterval);
|
||||
SettingsStatus = $"自动保存间隔: {AutoSaveInterval}秒";
|
||||
HasUnsavedChanges = true;
|
||||
}, "设置自动保存间隔");
|
||||
}
|
||||
|
||||
#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);
|
||||
SystemStatus = $"{operationName}失败: {ex.Message}";
|
||||
SystemStatusColor = "Red";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全执行同步操作
|
||||
/// </summary>
|
||||
private void SafeExecute(Action action, string operationName = "未知操作")
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
|
||||
SystemStatus = $"{operationName}失败: {ex.Message}";
|
||||
SystemStatusColor = "Red";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 性能监控
|
||||
|
||||
/// <summary>
|
||||
/// 启动性能监控
|
||||
/// </summary>
|
||||
private async Task StartPerformanceMonitoring()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
// 使用定时器更新性能信息
|
||||
_performanceTimer = new DispatcherTimer();
|
||||
_performanceTimer.Interval = TimeSpan.FromSeconds(5);
|
||||
_performanceTimer.Tick += async (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdatePerformanceInfo(startTime);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"性能监控更新失败: {ex.Message}");
|
||||
}
|
||||
};
|
||||
_performanceTimer.Start();
|
||||
|
||||
PerformanceInfo = "性能监控已启动";
|
||||
}, "启动性能监控");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新性能信息
|
||||
/// </summary>
|
||||
private async Task UpdatePerformanceInfo(DateTime startTime)
|
||||
{
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
// 更新内存使用
|
||||
var process = Process.GetCurrentProcess();
|
||||
var memoryMB = process.WorkingSet64 / (1024 * 1024);
|
||||
MemoryUsage = $"{memoryMB} MB";
|
||||
|
||||
// 更新运行时间
|
||||
var runTime = DateTime.Now - startTime;
|
||||
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
|
||||
|
||||
// 更新线程数
|
||||
ThreadsCount = process.Threads.Count;
|
||||
|
||||
// 更新性能信息
|
||||
PerformanceInfo = $"CPU: 正常, 内存: {memoryMB}MB, 线程: {ThreadsCount}, 运行时间: {RunningTime}";
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 默认实现创建方法
|
||||
|
||||
private ISystemLogManager CreateDefaultLogManager()
|
||||
{
|
||||
// TODO: 创建默认日志管理器实现
|
||||
return new DefaultSystemLogManager();
|
||||
}
|
||||
|
||||
private ISystemConfigManager CreateDefaultConfigManager()
|
||||
{
|
||||
// TODO: 创建默认配置管理器实现
|
||||
return new DefaultSystemConfigManager();
|
||||
}
|
||||
|
||||
private IPerformanceMonitor CreateDefaultPerformanceMonitor()
|
||||
{
|
||||
// TODO: 创建默认性能监控器实现
|
||||
return new DefaultPerformanceMonitor();
|
||||
}
|
||||
|
||||
private IModelSplitterManager CreateDefaultModelSplitterManager()
|
||||
{
|
||||
// TODO: 创建默认模型分割器管理器实现
|
||||
return new DefaultModelSplitterManager();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 系统信息获取方法
|
||||
|
||||
private string GetPluginVersion()
|
||||
{
|
||||
// TODO: 从程序集获取插件版本
|
||||
return "v1.0";
|
||||
}
|
||||
|
||||
private string GetNavisworksVersion()
|
||||
{
|
||||
// TODO: 从Navisworks API获取版本信息
|
||||
return "2026";
|
||||
}
|
||||
|
||||
private string GetWorkingDirectory()
|
||||
{
|
||||
// TODO: 获取当前工作目录
|
||||
return Environment.CurrentDirectory;
|
||||
}
|
||||
|
||||
private string GetLogFilePath()
|
||||
{
|
||||
// TODO: 获取日志文件路径
|
||||
return Path.Combine(GetWorkingDirectory(), "Logs", "NavisworksTransport.log");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 资源清理
|
||||
|
||||
/// <summary>
|
||||
/// 清理资源
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("开始清理SystemManagementViewModel资源");
|
||||
|
||||
// 停止性能监控定时器
|
||||
if (_performanceTimer != null)
|
||||
{
|
||||
_performanceTimer.Stop();
|
||||
_performanceTimer = null;
|
||||
}
|
||||
|
||||
// 清理管理器资源
|
||||
_logManager?.Dispose();
|
||||
_configManager?.Dispose();
|
||||
_performanceMonitor?.Dispose();
|
||||
_modelSplitterManager?.Dispose();
|
||||
|
||||
LogManager.Info("SystemManagementViewModel资源清理完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"SystemManagementViewModel清理失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
// 接口定义(这些接口将在单独的文件中定义)
|
||||
|
||||
/// <summary>
|
||||
/// 系统日志管理器接口
|
||||
/// </summary>
|
||||
public interface ISystemLogManager : IDisposable
|
||||
{
|
||||
Task OpenLogViewerAsync();
|
||||
Task ClearLogsAsync();
|
||||
Task<string> ExportLogsAsync();
|
||||
Task<LogStatus> GetLogStatusAsync();
|
||||
void SetLogLevel(string level);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统配置管理器接口
|
||||
/// </summary>
|
||||
public interface ISystemConfigManager : IDisposable
|
||||
{
|
||||
void SetAutoSaveEnabled(bool enabled);
|
||||
void SetDebugMode(bool enabled);
|
||||
void SetAutoSaveInterval(int seconds);
|
||||
Task SaveConfigAsync();
|
||||
Task LoadConfigAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能监控器接口
|
||||
/// </summary>
|
||||
public interface IPerformanceMonitor : IDisposable
|
||||
{
|
||||
Task<PerformanceData> GetCurrentPerformanceAsync();
|
||||
Task StartMonitoringAsync();
|
||||
Task StopMonitoringAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模型分割器管理器接口
|
||||
/// </summary>
|
||||
public interface IModelSplitterManager : IDisposable
|
||||
{
|
||||
Task<bool> RunModelSplitterAsync();
|
||||
Task ConfigureAsync();
|
||||
bool CanRun { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志状态数据结构
|
||||
/// </summary>
|
||||
public class LogStatus
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public int EntryCount { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能数据结构
|
||||
/// </summary>
|
||||
public class PerformanceData
|
||||
{
|
||||
public double CpuUsage { get; set; }
|
||||
public long MemoryUsage { get; set; }
|
||||
public int ThreadCount { get; set; }
|
||||
public TimeSpan RunningTime { get; set; }
|
||||
}
|
||||
457
SystemManagement_Integration_Plan.md
Normal file
457
SystemManagement_Integration_Plan.md
Normal file
@ -0,0 +1,457 @@
|
||||
# SystemManagementViewModel 集成方案
|
||||
|
||||
## 1. 与LogisticsControlViewModel的解耦策略
|
||||
|
||||
### 1.1 依赖关系处理
|
||||
|
||||
**原始依赖关系问题:**
|
||||
- LogisticsControlViewModel 直接包含所有系统管理代码
|
||||
- UI更新、状态管理、业务逻辑混合在一起
|
||||
- 违反单一职责原则
|
||||
|
||||
**解耦方案:**
|
||||
|
||||
```csharp
|
||||
// 在LogisticsControlViewModel中
|
||||
public class LogisticsControlViewModel : ViewModelBase
|
||||
{
|
||||
// 移除所有系统管理相关的字段和属性
|
||||
// private string _modelSplitterStatus; // 删除
|
||||
// private ObservableCollection<string> _logLevels; // 删除
|
||||
// ... 其他系统管理相关代码
|
||||
|
||||
// 添加SystemManagementViewModel的引用
|
||||
private SystemManagementViewModel _systemManagementViewModel;
|
||||
|
||||
public SystemManagementViewModel SystemManagement
|
||||
{
|
||||
get => _systemManagementViewModel;
|
||||
private set => SetProperty(ref _systemManagementViewModel, value);
|
||||
}
|
||||
|
||||
public LogisticsControlViewModel() : base()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 原有初始化代码...
|
||||
|
||||
// 初始化系统管理ViewModel
|
||||
SystemManagement = new SystemManagementViewModel();
|
||||
|
||||
// 订阅系统管理事件(如果需要)
|
||||
SubscribeToSystemManagementEvents();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 错误处理
|
||||
}
|
||||
}
|
||||
|
||||
// 移除所有系统管理相关的方法
|
||||
// private async Task InitializeSystemManagementSettingsAsync() // 删除
|
||||
// private void ExecuteClearLog() // 删除
|
||||
// private void ExecuteExportLog() // 删除
|
||||
// ... 其他系统管理方法
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 事件通信机制
|
||||
|
||||
```csharp
|
||||
// 定义系统管理事件接口
|
||||
public interface ISystemManagementEvents
|
||||
{
|
||||
event EventHandler<SystemStatusChangedEventArgs> SystemStatusChanged;
|
||||
event EventHandler<PerformanceAlertEventArgs> PerformanceAlert;
|
||||
event EventHandler<ConfigurationChangedEventArgs> ConfigurationChanged;
|
||||
}
|
||||
|
||||
// 在SystemManagementViewModel中实现事件发布
|
||||
public class SystemManagementViewModel : ViewModelBase, ISystemManagementEvents
|
||||
{
|
||||
public event EventHandler<SystemStatusChangedEventArgs> SystemStatusChanged;
|
||||
public event EventHandler<PerformanceAlertEventArgs> PerformanceAlert;
|
||||
public event EventHandler<ConfigurationChangedEventArgs> ConfigurationChanged;
|
||||
|
||||
// 触发系统状态变更事件
|
||||
private void OnSystemStatusChanged(string newStatus, string color)
|
||||
{
|
||||
SystemStatusChanged?.Invoke(this, new SystemStatusChangedEventArgs
|
||||
{
|
||||
Status = newStatus,
|
||||
StatusColor = color,
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
|
||||
// 触发性能警告事件
|
||||
private void OnPerformanceAlert(PerformanceAlertType alertType, string message)
|
||||
{
|
||||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||||
{
|
||||
AlertType = alertType,
|
||||
Message = message,
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 在LogisticsControlViewModel中订阅事件
|
||||
private void SubscribeToSystemManagementEvents()
|
||||
{
|
||||
if (SystemManagement != null)
|
||||
{
|
||||
SystemManagement.SystemStatusChanged += OnSystemStatusChanged;
|
||||
SystemManagement.PerformanceAlert += OnPerformanceAlert;
|
||||
SystemManagement.ConfigurationChanged += OnConfigurationChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSystemStatusChanged(object sender, SystemStatusChangedEventArgs e)
|
||||
{
|
||||
// 处理系统状态变更(如果主ViewModel需要知道)
|
||||
// 例如:更新主界面的状态指示器
|
||||
StatusText = $"系统状态: {e.Status}";
|
||||
}
|
||||
```
|
||||
|
||||
## 2. UI集成策略
|
||||
|
||||
### 2.1 XAML绑定方案
|
||||
|
||||
```xml
|
||||
<!-- 原始的SystemManagementView.xaml -->
|
||||
<!-- 通过DataContext绑定到LogisticsControlViewModel.SystemManagement -->
|
||||
<UserControl x:Class="NavisworksTransport.UI.WPF.Views.SystemManagementView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<!-- 原有的UI控件绑定路径需要调整 -->
|
||||
|
||||
<!-- 原来: -->
|
||||
<!-- <ComboBox ItemsSource="{Binding LogLevels}" SelectedItem="{Binding SelectedLogLevel}" /> -->
|
||||
|
||||
<!-- 现在: -->
|
||||
<!-- 通过父级LogisticsControlViewModel的SystemManagement属性访问 -->
|
||||
<ComboBox ItemsSource="{Binding SystemManagement.LogLevels}"
|
||||
SelectedItem="{Binding SystemManagement.SelectedLogLevel}" />
|
||||
|
||||
<Button Content="查看日志" Command="{Binding SystemManagement.ViewLogCommand}" />
|
||||
<Button Content="清空日志" Command="{Binding SystemManagement.ClearLogCommand}" />
|
||||
<Button Content="导出日志" Command="{Binding SystemManagement.ExportLogCommand}" />
|
||||
|
||||
<!-- 性能监控控件 -->
|
||||
<TextBlock Text="{Binding SystemManagement.MemoryUsage}" />
|
||||
<TextBlock Text="{Binding SystemManagement.RunningTime}" />
|
||||
<TextBlock Text="{Binding SystemManagement.PerformanceInfo}" />
|
||||
|
||||
<!-- 系统状态控件 -->
|
||||
<TextBlock Text="{Binding SystemManagement.SystemStatus}"
|
||||
Foreground="{Binding SystemManagement.SystemStatusColor}" />
|
||||
</UserControl>
|
||||
```
|
||||
|
||||
### 2.2 ViewModelLocator调整
|
||||
|
||||
```csharp
|
||||
// 在ViewModelLocator中注册SystemManagementViewModel
|
||||
public class ViewModelLocator
|
||||
{
|
||||
public LogisticsControlViewModel LogisticsControl => ServiceLocator.Current.GetInstance<LogisticsControlViewModel>();
|
||||
|
||||
// 可以选择直接注册SystemManagementViewModel
|
||||
public SystemManagementViewModel SystemManagement => ServiceLocator.Current.GetInstance<SystemManagementViewModel>();
|
||||
|
||||
static ViewModelLocator()
|
||||
{
|
||||
// 注册服务
|
||||
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
|
||||
|
||||
// 注册SystemManagementViewModel及其依赖
|
||||
SimpleIoc.Default.Register<ISystemLogManager, DefaultSystemLogManager>();
|
||||
SimpleIoc.Default.Register<ISystemConfigManager, DefaultSystemConfigManager>();
|
||||
SimpleIoc.Default.Register<IPerformanceMonitor, DefaultPerformanceMonitor>();
|
||||
SimpleIoc.Default.Register<IModelSplitterManager, DefaultModelSplitterManager>();
|
||||
|
||||
SimpleIoc.Default.Register<SystemManagementViewModel>();
|
||||
SimpleIoc.Default.Register<LogisticsControlViewModel>();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 初始化和生命周期管理
|
||||
|
||||
### 3.1 初始化顺序
|
||||
|
||||
```csharp
|
||||
public class LogisticsControlViewModel : ViewModelBase
|
||||
{
|
||||
private async void InitializeViewModelAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
// 1. 先初始化核心组件
|
||||
await UpdateInstructionTextAsync();
|
||||
await UpdateSelectionDisplayAsync();
|
||||
await InitializeCategoriesAsync();
|
||||
|
||||
// 2. 初始化系统管理ViewModel
|
||||
await InitializeSystemManagementAsync();
|
||||
|
||||
// 3. 最后更新UI状态
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
StatusText = "插件已就绪";
|
||||
AnimationStatus = "动画状态: 就绪";
|
||||
AnimationProgress = 0;
|
||||
WidthLimit = 3.0;
|
||||
});
|
||||
|
||||
// 4. 初始化动画设置
|
||||
await InitializeAnimationSettingsAsync();
|
||||
|
||||
LogManager.Info("LogisticsControlViewModel 初始化完成");
|
||||
}, "初始化ViewModel");
|
||||
}
|
||||
|
||||
private async Task InitializeSystemManagementAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
// 创建SystemManagementViewModel实例
|
||||
SystemManagement = new SystemManagementViewModel(
|
||||
logManager: ServiceProvider.GetService<ISystemLogManager>(),
|
||||
configManager: ServiceProvider.GetService<ISystemConfigManager>(),
|
||||
performanceMonitor: ServiceProvider.GetService<IPerformanceMonitor>(),
|
||||
modelSplitterManager: ServiceProvider.GetService<IModelSplitterManager>()
|
||||
);
|
||||
|
||||
// 订阅系统管理事件
|
||||
SubscribeToSystemManagementEvents();
|
||||
|
||||
LogManager.Info("系统管理ViewModel初始化完成");
|
||||
}, "初始化系统管理");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 清理机制
|
||||
|
||||
```csharp
|
||||
public class LogisticsControlViewModel : ViewModelBase
|
||||
{
|
||||
// 添加清理方法
|
||||
public void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("开始清理LogisticsControlViewModel资源");
|
||||
|
||||
// 清理系统管理ViewModel
|
||||
if (SystemManagement != null)
|
||||
{
|
||||
UnsubscribeFromSystemManagementEvents();
|
||||
SystemManagement.Cleanup();
|
||||
SystemManagement = null;
|
||||
}
|
||||
|
||||
// 原有的清理代码...
|
||||
|
||||
LogManager.Info("LogisticsControlViewModel资源清理完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"LogisticsControlViewModel清理失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromSystemManagementEvents()
|
||||
{
|
||||
if (SystemManagement != null)
|
||||
{
|
||||
SystemManagement.SystemStatusChanged -= OnSystemStatusChanged;
|
||||
SystemManagement.PerformanceAlert -= OnPerformanceAlert;
|
||||
SystemManagement.ConfigurationChanged -= OnConfigurationChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 命令重定向机制
|
||||
|
||||
### 4.1 保持向后兼容性
|
||||
|
||||
```csharp
|
||||
public class LogisticsControlViewModel : ViewModelBase
|
||||
{
|
||||
// 保持原有命令接口,但重定向到SystemManagementViewModel
|
||||
public ICommand ViewLogCommand => SystemManagement?.ViewLogCommand;
|
||||
public ICommand ClearLogCommand => SystemManagement?.ClearLogCommand;
|
||||
public ICommand ExportLogCommand => SystemManagement?.ExportLogCommand;
|
||||
public ICommand OpenSettingsCommand => SystemManagement?.OpenSettingsCommand;
|
||||
public ICommand ResetSettingsCommand => SystemManagement?.ResetSettingsCommand;
|
||||
public ICommand ImportConfigCommand => SystemManagement?.ImportConfigCommand;
|
||||
public ICommand CheckUpdateCommand => SystemManagement?.CheckUpdateCommand;
|
||||
public ICommand GeneratePerformanceReportCommand => SystemManagement?.GeneratePerformanceReportCommand;
|
||||
|
||||
// 或者使用代理模式
|
||||
private void InitializeCommandProxies()
|
||||
{
|
||||
ViewLogCommand = new RelayCommand(async () =>
|
||||
{
|
||||
if (SystemManagement != null)
|
||||
await SystemManagement.ViewLogCommand.ExecuteAsync(null);
|
||||
});
|
||||
|
||||
ClearLogCommand = new RelayCommand(async () =>
|
||||
{
|
||||
if (SystemManagement != null)
|
||||
await SystemManagement.ClearLogCommand.ExecuteAsync(null);
|
||||
});
|
||||
|
||||
// ... 其他命令代理
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 测试策略
|
||||
|
||||
### 5.1 单元测试
|
||||
|
||||
```csharp
|
||||
[TestFixture]
|
||||
public class SystemManagementViewModelTests
|
||||
{
|
||||
private SystemManagementViewModel _viewModel;
|
||||
private Mock<ISystemLogManager> _mockLogManager;
|
||||
private Mock<ISystemConfigManager> _mockConfigManager;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_mockLogManager = new Mock<ISystemLogManager>();
|
||||
_mockConfigManager = new Mock<ISystemConfigManager>();
|
||||
|
||||
_viewModel = new SystemManagementViewModel(
|
||||
_mockLogManager.Object,
|
||||
_mockConfigManager.Object
|
||||
);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExecuteViewLogAsync_ShouldCallLogManager()
|
||||
{
|
||||
// Arrange
|
||||
_mockLogManager.Setup(x => x.OpenLogViewerAsync()).Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
await _viewModel.ViewLogCommand.ExecuteAsync(null);
|
||||
|
||||
// Assert
|
||||
_mockLogManager.Verify(x => x.OpenLogViewerAsync(), Times.Once);
|
||||
Assert.AreEqual("日志查看器已打开", _viewModel.LogStatus);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 集成测试
|
||||
|
||||
```csharp
|
||||
[TestFixture]
|
||||
public class SystemManagementIntegrationTests
|
||||
{
|
||||
[Test]
|
||||
public void LogisticsControlViewModel_ShouldInitializeSystemManagement()
|
||||
{
|
||||
// Arrange & Act
|
||||
var logisticsVM = new LogisticsControlViewModel();
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(logisticsVM.SystemManagement);
|
||||
Assert.IsInstanceOf<SystemManagementViewModel>(logisticsVM.SystemManagement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SystemManagementEvents_ShouldPropagateToMainViewModel()
|
||||
{
|
||||
// Arrange
|
||||
var logisticsVM = new LogisticsControlViewModel();
|
||||
var systemManagementVM = logisticsVM.SystemManagement;
|
||||
string receivedStatus = null;
|
||||
|
||||
logisticsVM.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(LogisticsControlViewModel.StatusText))
|
||||
receivedStatus = logisticsVM.StatusText;
|
||||
};
|
||||
|
||||
// Act
|
||||
systemManagementVM.SystemStatus = "测试状态";
|
||||
// 触发SystemStatusChanged事件
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(receivedStatus?.Contains("测试状态"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 迁移计划
|
||||
|
||||
### 6.1 分阶段迁移
|
||||
|
||||
**阶段1:创建基础架构**
|
||||
1. 创建SystemManagementViewModel类
|
||||
2. 定义所需接口
|
||||
3. 创建默认实现类
|
||||
4. 设置依赖注入
|
||||
|
||||
**阶段2:迁移核心功能**
|
||||
1. 迁移日志管理功能
|
||||
2. 迁移设置管理功能
|
||||
3. 迁移性能监控功能
|
||||
4. 测试基本功能
|
||||
|
||||
**阶段3:集成和优化**
|
||||
1. 集成到LogisticsControlViewModel
|
||||
2. 调整UI绑定
|
||||
3. 实现事件通信
|
||||
4. 性能优化
|
||||
|
||||
**阶段4:测试和部署**
|
||||
1. 全面测试
|
||||
2. 修复问题
|
||||
3. 文档更新
|
||||
4. 部署验证
|
||||
|
||||
### 6.2 兼容性保证
|
||||
|
||||
```csharp
|
||||
// 在迁移期间,保持旧接口可用
|
||||
public class LogisticsControlViewModel : ViewModelBase
|
||||
{
|
||||
// 新的系统管理ViewModel
|
||||
private SystemManagementViewModel _systemManagement;
|
||||
|
||||
// 保持旧属性兼容性(标记为过时)
|
||||
[Obsolete("请使用SystemManagement.LogLevels", false)]
|
||||
public ObservableCollection<string> LogLevels => SystemManagement?.LogLevels;
|
||||
|
||||
[Obsolete("请使用SystemManagement.SelectedLogLevel", false)]
|
||||
public string SelectedLogLevel
|
||||
{
|
||||
get => SystemManagement?.SelectedLogLevel;
|
||||
set { if (SystemManagement != null) SystemManagement.SelectedLogLevel = value; }
|
||||
}
|
||||
|
||||
// 保持旧命令兼容性
|
||||
[Obsolete("请使用SystemManagement.ViewLogCommand", false)]
|
||||
public ICommand ViewLogCommand => SystemManagement?.ViewLogCommand;
|
||||
}
|
||||
```
|
||||
|
||||
这个解耦方案确保了:
|
||||
1. **清晰的职责分离**:系统管理功能完全独立
|
||||
2. **向后兼容性**:现有UI和代码不会立即失效
|
||||
3. **渐进式迁移**:可以分步骤进行迁移
|
||||
4. **良好的测试性**:每个组件都可以独立测试
|
||||
5. **事件驱动通信**:组件间通过事件解耦
|
||||
744
SystemManagement_Services.cs
Normal file
744
SystemManagement_Services.cs
Normal file
@ -0,0 +1,744 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace NavisworksTransport.Core.SystemManagement
|
||||
{
|
||||
#region 事件参数定义
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态变更事件参数
|
||||
/// </summary>
|
||||
public class SystemStatusChangedEventArgs : EventArgs
|
||||
{
|
||||
public string Status { get; set; }
|
||||
public string StatusColor { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public string Details { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能警告事件参数
|
||||
/// </summary>
|
||||
public class PerformanceAlertEventArgs : EventArgs
|
||||
{
|
||||
public PerformanceAlertType AlertType { get; set; }
|
||||
public string Message { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public double Value { get; set; }
|
||||
public double Threshold { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置变更事件参数
|
||||
/// </summary>
|
||||
public class ConfigurationChangedEventArgs : EventArgs
|
||||
{
|
||||
public string ConfigKey { get; set; }
|
||||
public object OldValue { get; set; }
|
||||
public object NewValue { get; set; }
|
||||
public string ProfileName { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能警告类型枚举
|
||||
/// </summary>
|
||||
public enum PerformanceAlertType
|
||||
{
|
||||
MemoryHigh,
|
||||
CpuHigh,
|
||||
ThreadCountHigh,
|
||||
ResponseTimeLow
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 数据模型
|
||||
|
||||
/// <summary>
|
||||
/// 日志状态数据模型
|
||||
/// </summary>
|
||||
public class LogStatus
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public int EntryCount { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public DateTime LastUpdate { get; set; }
|
||||
public long FileSizeBytes { get; set; }
|
||||
public string CurrentLevel { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能数据模型
|
||||
/// </summary>
|
||||
public class PerformanceData
|
||||
{
|
||||
public double CpuUsage { get; set; }
|
||||
public long MemoryUsageMB { get; set; }
|
||||
public int ThreadCount { get; set; }
|
||||
public TimeSpan RunningTime { get; set; }
|
||||
public int HandleCount { get; set; }
|
||||
public double ResponseTimeMs { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置档案数据模型
|
||||
/// </summary>
|
||||
public class ConfigProfile
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, object> Settings { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public bool IsDefault { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 系统日志管理器实现
|
||||
|
||||
/// <summary>
|
||||
/// 默认系统日志管理器实现
|
||||
/// </summary>
|
||||
public class DefaultSystemLogManager : ISystemLogManager
|
||||
{
|
||||
private readonly string _logDirectory;
|
||||
private readonly string _logFilePath;
|
||||
private string _currentLogLevel = "Info";
|
||||
|
||||
public DefaultSystemLogManager()
|
||||
{
|
||||
_logDirectory = Path.Combine(Environment.CurrentDirectory, "Logs");
|
||||
_logFilePath = Path.Combine(_logDirectory, "NavisworksTransport.log");
|
||||
|
||||
// 确保日志目录存在
|
||||
if (!Directory.Exists(_logDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(_logDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OpenLogViewerAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查是否存在自定义日志查看器
|
||||
var logViewerPath = Path.Combine(Environment.CurrentDirectory, "tools", "LogViewer.exe");
|
||||
|
||||
if (File.Exists(logViewerPath))
|
||||
{
|
||||
// 使用自定义日志查看器
|
||||
Process.Start(logViewerPath, $"\"{_logFilePath}\"");
|
||||
}
|
||||
else if (File.Exists(_logFilePath))
|
||||
{
|
||||
// 使用默认文本编辑器打开
|
||||
Process.Start("notepad.exe", _logFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("日志文件不存在", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"打开日志查看器失败: {ex.Message}", ex);
|
||||
MessageBox.Show($"打开日志查看器失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task ClearLogsAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(_logFilePath))
|
||||
{
|
||||
// 备份当前日志文件
|
||||
var backupPath = Path.Combine(_logDirectory, $"backup_{DateTime.Now:yyyyMMdd_HHmmss}.log");
|
||||
File.Move(_logFilePath, backupPath);
|
||||
|
||||
LogManager.Info("日志已清空,备份文件已创建");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"清空日志失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<string> ExportLogsAsync()
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var exportDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "NavisworksTransport_Logs");
|
||||
if (!Directory.Exists(exportDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(exportDirectory);
|
||||
}
|
||||
|
||||
var exportFileName = $"NavisworksTransport_Log_{DateTime.Now:yyyyMMdd_HHmmss}.zip";
|
||||
var exportPath = Path.Combine(exportDirectory, exportFileName);
|
||||
|
||||
// 这里可以使用System.IO.Compression.ZipFile来创建压缩包
|
||||
// 包含主日志文件和任何相关的日志文件
|
||||
if (File.Exists(_logFilePath))
|
||||
{
|
||||
var singleLogExportPath = Path.Combine(exportDirectory, $"NavisworksTransport_Log_{DateTime.Now:yyyyMMdd_HHmmss}.log");
|
||||
File.Copy(_logFilePath, singleLogExportPath);
|
||||
return singleLogExportPath;
|
||||
}
|
||||
|
||||
return exportPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"导出日志失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<LogStatus> GetLogStatusAsync()
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = new LogStatus
|
||||
{
|
||||
FilePath = _logFilePath,
|
||||
CurrentLevel = _currentLogLevel,
|
||||
LastUpdate = DateTime.Now
|
||||
};
|
||||
|
||||
if (File.Exists(_logFilePath))
|
||||
{
|
||||
var fileInfo = new FileInfo(_logFilePath);
|
||||
status.FileSizeBytes = fileInfo.Length;
|
||||
status.LastUpdate = fileInfo.LastWriteTime;
|
||||
|
||||
// 估算日志条目数量(简单实现)
|
||||
var lines = File.ReadAllLines(_logFilePath);
|
||||
status.EntryCount = lines.Length;
|
||||
status.Message = $"日志文件正常,共 {status.EntryCount} 条记录";
|
||||
}
|
||||
else
|
||||
{
|
||||
status.EntryCount = 0;
|
||||
status.FileSizeBytes = 0;
|
||||
status.Message = "日志文件不存在";
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取日志状态失败: {ex.Message}", ex);
|
||||
return new LogStatus
|
||||
{
|
||||
Message = $"获取日志状态失败: {ex.Message}",
|
||||
EntryCount = 0,
|
||||
FilePath = _logFilePath,
|
||||
CurrentLevel = _currentLogLevel
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SetLogLevel(string level)
|
||||
{
|
||||
try
|
||||
{
|
||||
_currentLogLevel = level;
|
||||
// 这里需要与实际的日志系统集成
|
||||
LogManager.SetLogLevel(level);
|
||||
LogManager.Info($"日志级别已设置为: {level}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"设置日志级别失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// 清理资源
|
||||
LogManager.Info("SystemLogManager已清理");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 系统配置管理器实现
|
||||
|
||||
/// <summary>
|
||||
/// 默认系统配置管理器实现
|
||||
/// </summary>
|
||||
public class DefaultSystemConfigManager : ISystemConfigManager
|
||||
{
|
||||
private readonly string _configDirectory;
|
||||
private readonly string _configFilePath;
|
||||
private Dictionary<string, object> _currentSettings;
|
||||
private ConfigProfile _currentProfile;
|
||||
|
||||
public event EventHandler<ConfigurationChangedEventArgs> ConfigurationChanged;
|
||||
|
||||
public DefaultSystemConfigManager()
|
||||
{
|
||||
_configDirectory = Path.Combine(Environment.CurrentDirectory, "Config");
|
||||
_configFilePath = Path.Combine(_configDirectory, "settings.json");
|
||||
_currentSettings = new Dictionary<string, object>();
|
||||
|
||||
// 确保配置目录存在
|
||||
if (!Directory.Exists(_configDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(_configDirectory);
|
||||
}
|
||||
|
||||
// 加载默认配置
|
||||
LoadDefaultSettings();
|
||||
}
|
||||
|
||||
private void LoadDefaultSettings()
|
||||
{
|
||||
_currentSettings = new Dictionary<string, object>
|
||||
{
|
||||
{ "AutoSaveEnabled", true },
|
||||
{ "AutoSaveInterval", 300 },
|
||||
{ "DebugModeEnabled", false },
|
||||
{ "LogLevel", "Info" },
|
||||
{ "WorkingDirectory", Environment.CurrentDirectory },
|
||||
{ "MaxMemoryUsageMB", 1024 },
|
||||
{ "PerformanceMonitoringEnabled", true }
|
||||
};
|
||||
|
||||
_currentProfile = new ConfigProfile
|
||||
{
|
||||
Name = "默认配置",
|
||||
Settings = new Dictionary<string, object>(_currentSettings),
|
||||
CreatedAt = DateTime.Now,
|
||||
LastModified = DateTime.Now,
|
||||
IsDefault = true,
|
||||
Description = "系统默认配置档案"
|
||||
};
|
||||
}
|
||||
|
||||
public void SetAutoSaveEnabled(bool enabled)
|
||||
{
|
||||
SetSetting("AutoSaveEnabled", enabled);
|
||||
}
|
||||
|
||||
public void SetDebugMode(bool enabled)
|
||||
{
|
||||
SetSetting("DebugModeEnabled", enabled);
|
||||
}
|
||||
|
||||
public void SetAutoSaveInterval(int seconds)
|
||||
{
|
||||
SetSetting("AutoSaveInterval", seconds);
|
||||
}
|
||||
|
||||
private void SetSetting(string key, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var oldValue = _currentSettings.ContainsKey(key) ? _currentSettings[key] : null;
|
||||
_currentSettings[key] = value;
|
||||
|
||||
// 触发配置变更事件
|
||||
ConfigurationChanged?.Invoke(this, new ConfigurationChangedEventArgs
|
||||
{
|
||||
ConfigKey = key,
|
||||
OldValue = oldValue,
|
||||
NewValue = value,
|
||||
ProfileName = _currentProfile?.Name,
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
|
||||
LogManager.Info($"配置项已更新: {key} = {value}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"设置配置项失败 {key}: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveConfigAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里应该实现JSON序列化保存
|
||||
// var json = JsonConvert.SerializeObject(_currentSettings, Formatting.Indented);
|
||||
// File.WriteAllText(_configFilePath, json);
|
||||
|
||||
LogManager.Info("配置已保存到文件");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"保存配置失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task LoadConfigAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(_configFilePath))
|
||||
{
|
||||
// var json = File.ReadAllText(_configFilePath);
|
||||
// _currentSettings = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
|
||||
LogManager.Info("配置已从文件加载");
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadDefaultSettings();
|
||||
LogManager.Info("使用默认配置");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"加载配置失败: {ex.Message}", ex);
|
||||
LoadDefaultSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public T GetSetting<T>(string key, T defaultValue = default(T))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentSettings.ContainsKey(key))
|
||||
{
|
||||
return (T)Convert.ChangeType(_currentSettings[key], typeof(T));
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取配置项失败 {key}: {ex.Message}", ex);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 自动保存配置
|
||||
SaveConfigAsync().Wait(5000); // 等待最多5秒
|
||||
LogManager.Info("SystemConfigManager已清理");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"SystemConfigManager清理失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 性能监控器实现
|
||||
|
||||
/// <summary>
|
||||
/// 默认性能监控器实现
|
||||
/// </summary>
|
||||
public class DefaultPerformanceMonitor : IPerformanceMonitor
|
||||
{
|
||||
private readonly Process _currentProcess;
|
||||
private bool _isMonitoring;
|
||||
private readonly List<PerformanceData> _performanceHistory;
|
||||
private readonly object _lockObject = new object();
|
||||
|
||||
public event EventHandler<PerformanceAlertEventArgs> PerformanceAlert;
|
||||
|
||||
public DefaultPerformanceMonitor()
|
||||
{
|
||||
_currentProcess = Process.GetCurrentProcess();
|
||||
_performanceHistory = new List<PerformanceData>();
|
||||
_isMonitoring = false;
|
||||
}
|
||||
|
||||
public async Task<PerformanceData> GetCurrentPerformanceAsync()
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_currentProcess.Refresh();
|
||||
|
||||
var performanceData = new PerformanceData
|
||||
{
|
||||
MemoryUsageMB = _currentProcess.WorkingSet64 / (1024 * 1024),
|
||||
ThreadCount = _currentProcess.Threads.Count,
|
||||
HandleCount = _currentProcess.HandleCount,
|
||||
RunningTime = DateTime.Now - _currentProcess.StartTime,
|
||||
Timestamp = DateTime.Now,
|
||||
CpuUsage = GetCpuUsage(), // 需要实现CPU使用率获取
|
||||
ResponseTimeMs = GetResponseTime() // 需要实现响应时间测量
|
||||
};
|
||||
|
||||
// 检查性能阈值
|
||||
CheckPerformanceThresholds(performanceData);
|
||||
|
||||
lock (_lockObject)
|
||||
{
|
||||
_performanceHistory.Add(performanceData);
|
||||
|
||||
// 保持历史记录在合理范围内(最多保留1000条记录)
|
||||
if (_performanceHistory.Count > 1000)
|
||||
{
|
||||
_performanceHistory.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
return performanceData;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取性能数据失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private double GetCpuUsage()
|
||||
{
|
||||
// 简单实现,实际应该使用PerformanceCounter或更准确的方法
|
||||
try
|
||||
{
|
||||
return _currentProcess.TotalProcessorTime.TotalMilliseconds / Environment.TickCount * 100;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private double GetResponseTime()
|
||||
{
|
||||
// 这里应该实现响应时间测量逻辑
|
||||
// 可以通过测试关键操作的执行时间来获得
|
||||
return 50.0; // 模拟值
|
||||
}
|
||||
|
||||
private void CheckPerformanceThresholds(PerformanceData data)
|
||||
{
|
||||
// 内存使用率检查(超过512MB警告)
|
||||
if (data.MemoryUsageMB > 512)
|
||||
{
|
||||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||||
{
|
||||
AlertType = PerformanceAlertType.MemoryHigh,
|
||||
Message = $"内存使用量较高: {data.MemoryUsageMB}MB",
|
||||
Value = data.MemoryUsageMB,
|
||||
Threshold = 512,
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
|
||||
// 线程数量检查(超过50个线程警告)
|
||||
if (data.ThreadCount > 50)
|
||||
{
|
||||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||||
{
|
||||
AlertType = PerformanceAlertType.ThreadCountHigh,
|
||||
Message = $"线程数量较多: {data.ThreadCount}个",
|
||||
Value = data.ThreadCount,
|
||||
Threshold = 50,
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
|
||||
// CPU使用率检查(超过80%警告)
|
||||
if (data.CpuUsage > 80)
|
||||
{
|
||||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||||
{
|
||||
AlertType = PerformanceAlertType.CpuHigh,
|
||||
Message = $"CPU使用率较高: {data.CpuUsage:F1}%",
|
||||
Value = data.CpuUsage,
|
||||
Threshold = 80,
|
||||
Timestamp = DateTime.Now
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StartMonitoringAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
_isMonitoring = true;
|
||||
LogManager.Info("性能监控已启动");
|
||||
});
|
||||
}
|
||||
|
||||
public async Task StopMonitoringAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
_isMonitoring = false;
|
||||
LogManager.Info("性能监控已停止");
|
||||
});
|
||||
}
|
||||
|
||||
public List<PerformanceData> GetPerformanceHistory(TimeSpan? timeRange = null)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
if (timeRange.HasValue)
|
||||
{
|
||||
var cutoffTime = DateTime.Now - timeRange.Value;
|
||||
return _performanceHistory.Where(p => p.Timestamp >= cutoffTime).ToList();
|
||||
}
|
||||
return new List<PerformanceData>(_performanceHistory);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
_isMonitoring = false;
|
||||
_currentProcess?.Dispose();
|
||||
LogManager.Info("PerformanceMonitor已清理");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"PerformanceMonitor清理失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 模型分割器管理器实现
|
||||
|
||||
/// <summary>
|
||||
/// 默认模型分割器管理器实现
|
||||
/// </summary>
|
||||
public class DefaultModelSplitterManager : IModelSplitterManager
|
||||
{
|
||||
private bool _isRunning;
|
||||
private string _outputDirectory;
|
||||
|
||||
public bool CanRun => !_isRunning && HasValidModel();
|
||||
|
||||
public DefaultModelSplitterManager()
|
||||
{
|
||||
_outputDirectory = Path.Combine(Environment.CurrentDirectory, "ModelSplitter", "Output");
|
||||
if (!Directory.Exists(_outputDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(_outputDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasValidModel()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查Navisworks中是否有已加载的模型
|
||||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
return document != null && document.Models != null && document.Models.Count > 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> RunModelSplitterAsync()
|
||||
{
|
||||
if (!CanRun)
|
||||
{
|
||||
LogManager.Warning("模型分割器无法运行:条件不满足");
|
||||
return false;
|
||||
}
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_isRunning = true;
|
||||
LogManager.Info("开始模型分层拆分");
|
||||
|
||||
// 这里应该实现实际的模型分割逻辑
|
||||
// 1. 获取当前Navisworks文档
|
||||
// 2. 按照楼层、区域或其他标准进行分割
|
||||
// 3. 导出各个分割后的模型
|
||||
|
||||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
if (document?.Models != null)
|
||||
{
|
||||
// 模拟分割过程
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
|
||||
// 实际实现中,这里会调用ModelSplitterManager的分割逻辑
|
||||
// var splitterResult = ModelSplitterManager.SplitByFloors(document);
|
||||
|
||||
LogManager.Info("模型分层拆分完成");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"模型分割器运行失败: {ex.Message}", ex);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task ConfigureAsync()
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里可以打开模型分割器的配置对话框
|
||||
// 或者加载配置设置
|
||||
LogManager.Info("模型分割器配置界面已打开");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"配置模型分割器失败: {ex.Message}", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_isRunning = false;
|
||||
LogManager.Info("ModelSplitterManager已清理");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -482,7 +482,132 @@ public void BatchNavisworksOperations(List<ModelItem> items)
|
||||
8. **线程状态检查**:在关键操作前验证线程状态(STA)
|
||||
9. **Dispatcher 模式**:后台线程中需要调用 API 时,始终使用 Dispatcher.Invoke
|
||||
|
||||
## 11. 参考官方示例
|
||||
## 11. Transform 变换操作
|
||||
|
||||
### 11.1 Transform 相关 API 概念
|
||||
|
||||
**核心概念**:
|
||||
- `ModelItem.Transform` - 返回设计文件中的原始变换,只读属性
|
||||
- `OverridePermanentTransform()` - 应用增量变换(与现有变换叠加)
|
||||
- `ResetPermanentTransform()` - 清除所有增量变换,恢复到设计文件原始位置
|
||||
|
||||
### 11.2 Transform 操作的正确用法
|
||||
|
||||
```csharp
|
||||
// ✅ 获取物体的原始Transform(设计文件中的位置)
|
||||
Transform3D originalTransform = modelItem.Transform;
|
||||
|
||||
// ✅ 应用增量变换(累积变换)
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { modelItem };
|
||||
doc.Models.OverridePermanentTransform(modelItems, newTransform, false);
|
||||
|
||||
// ✅ 重置到原始位置(清除所有增量变换)
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
```
|
||||
|
||||
### 11.3 Transform 操作的关键区别
|
||||
|
||||
| API方法 | 作用 | 使用场景 | 注意事项 |
|
||||
|---------|------|---------|---------|
|
||||
| `ModelItem.Transform` | 获取原始变换 | 记录物体初始位置 | 只读属性,返回设计文件位置 |
|
||||
| `OverridePermanentTransform()` | 应用增量变换 | 动画中移动物体 | 与现有变换累积,不是绝对位置 |
|
||||
| `ResetPermanentTransform()` | 重置到原始位置 | 清除所有移动,恢复初始状态 | 忽略所有之前的变换 |
|
||||
|
||||
### 11.4 实际应用案例
|
||||
|
||||
**案例1:动画系统中的Transform管理**
|
||||
```csharp
|
||||
// 动画开始时记录原始位置
|
||||
private Transform3D _originalTransform;
|
||||
|
||||
public void StartAnimation(ModelItem animatedObject)
|
||||
{
|
||||
// 记录原始Transform
|
||||
_originalTransform = animatedObject.Transform;
|
||||
|
||||
// 移动到路径起点(增量变换)
|
||||
var startTransform = Transform3D.CreateTranslation(startPosition);
|
||||
var modelItems = new ModelItemCollection { animatedObject };
|
||||
doc.Models.OverridePermanentTransform(modelItems, startTransform, false);
|
||||
}
|
||||
|
||||
public void ResetAnimation()
|
||||
{
|
||||
// 动画结束后,使用原始Transform恢复位置
|
||||
var modelItems = new ModelItemCollection { _animatedObject };
|
||||
doc.Models.OverridePermanentTransform(modelItems, _originalTransform, false);
|
||||
}
|
||||
```
|
||||
|
||||
**案例2:用户手动位置恢复**
|
||||
```csharp
|
||||
public void RestoreToOriginalPosition(ModelItem selectedObject)
|
||||
{
|
||||
// 不需要记录Transform,直接重置到设计文件原始位置
|
||||
var doc = Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { selectedObject };
|
||||
|
||||
// 清除所有增量变换,恢复到设计文件原始位置
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
}
|
||||
```
|
||||
|
||||
### 11.5 常见Transform问题和解决方案
|
||||
|
||||
**问题1:位置恢复有偏移**
|
||||
```csharp
|
||||
// ❌ 错误:使用增量变换恢复位置
|
||||
doc.Models.OverridePermanentTransform(modelItems, originalTransform, false);
|
||||
// 问题:如果物体已经被移动过,这会导致累积偏移
|
||||
|
||||
// ✅ 正确:重置到原始位置
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
// 结果:直接恢复到设计文件中的原始位置,无偏移
|
||||
```
|
||||
|
||||
**问题2:动画结束后位置不准确**
|
||||
```csharp
|
||||
// ✅ 动画系统应该记录原始Transform并使用增量恢复
|
||||
private Transform3D _originalTransform;
|
||||
|
||||
// 动画开始时
|
||||
_originalTransform = animatedObject.Transform;
|
||||
|
||||
// 动画结束时恢复
|
||||
doc.Models.OverridePermanentTransform(modelItems, _originalTransform, false);
|
||||
```
|
||||
|
||||
**问题3:记录Transform但不使用**
|
||||
```csharp
|
||||
// ❌ 不必要:记录Transform但使用Reset
|
||||
private Transform3D _originalTransform;
|
||||
_originalTransform = selectedItem.Transform; // 记录了但不使用
|
||||
doc.Models.ResetPermanentTransform(modelItems); // 直接重置
|
||||
|
||||
// ✅ 简化:直接重置,无需记录
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
```
|
||||
|
||||
### 11.6 Transform 最佳实践
|
||||
|
||||
1. **选择合适的恢复方式**:
|
||||
- 动画系统:使用 `OverridePermanentTransform` + 原始Transform
|
||||
- 用户操作:使用 `ResetPermanentTransform` 直接重置
|
||||
|
||||
2. **避免不必要的Transform记录**:
|
||||
- 如果只需要恢复到设计文件原始位置,使用 `ResetPermanentTransform`
|
||||
- 只有需要恢复到特定中间状态时才记录Transform
|
||||
|
||||
3. **理解增量vs绝对变换**:
|
||||
- `OverridePermanentTransform` 是增量的,会与现有变换叠加
|
||||
- `ResetPermanentTransform` 是绝对的,清除所有变换
|
||||
|
||||
4. **线程安全**:
|
||||
- 所有Transform操作都必须在主UI线程中执行
|
||||
- 使用 `Dispatcher.Invoke` 确保线程安全
|
||||
|
||||
## 12. 参考官方示例
|
||||
|
||||
强烈建议查看以下官方示例了解更多用法:
|
||||
- `SearchComparisonPlugIn.cs` - 搜索性能对比
|
||||
|
||||
@ -559,7 +559,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
_pathPointMarkers?.Clear();
|
||||
// 通知渲染插件更新显示
|
||||
_renderPlugin?.ClearPathMarkers();
|
||||
_renderPlugin?.ClearAllPaths();
|
||||
LogManager.Info("3D路径标记已清除");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -591,11 +591,11 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
// 同时尝试通过坐标移除3D标记
|
||||
if (_renderPlugin != null)
|
||||
// 重新渲染当前路径以反映更改
|
||||
if (_renderPlugin != null && CurrentRoute != null)
|
||||
{
|
||||
_renderPlugin.RemoveMarkerAt(point.Position, 2.0);
|
||||
LogManager.Info($"已从3D中移除路径点: {point.Name}");
|
||||
_renderPlugin.RenderPath(CurrentRoute);
|
||||
LogManager.Info($"已更新路径可视化: {point.Name}");
|
||||
}
|
||||
|
||||
// 触发路径点移除事件
|
||||
@ -636,9 +636,49 @@ namespace NavisworksTransport
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.WriteLog("[事件清理] ===== 开始执行StopClickTool - 完整事件订阅清理 =====");
|
||||
|
||||
// 1. 停用ToolPlugin并清理事件订阅
|
||||
DeactivateToolPlugin();
|
||||
|
||||
// 2. 额外的事件订阅清理 - 确保所有可能的重复订阅都被清除
|
||||
LogManager.WriteLog("[事件清理] 执行额外的事件订阅清理");
|
||||
try
|
||||
{
|
||||
// 移除所有可能的OnToolPluginMouseClicked订阅
|
||||
var mouseClickedEvent = typeof(PathClickToolPlugin).GetEvent("MouseClicked");
|
||||
if (mouseClickedEvent != null)
|
||||
{
|
||||
var eventField = typeof(PathClickToolPlugin).GetField("MouseClicked",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
if (eventField != null)
|
||||
{
|
||||
var currentDelegate = (MulticastDelegate)eventField.GetValue(null);
|
||||
if (currentDelegate != null)
|
||||
{
|
||||
var invocationList = currentDelegate.GetInvocationList();
|
||||
LogManager.WriteLog($"[事件清理] 发现 {invocationList.Length} 个事件订阅者");
|
||||
|
||||
foreach (var handler in invocationList)
|
||||
{
|
||||
if (handler.Target == this && handler.Method.Name == "OnToolPluginMouseClicked")
|
||||
{
|
||||
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
|
||||
LogManager.WriteLog($"[事件清理] 移除了PathPlanningManager.OnToolPluginMouseClicked订阅");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception cleanupEx)
|
||||
{
|
||||
LogManager.WriteLog($"[事件清理] 额外清理过程异常: {cleanupEx.Message}");
|
||||
}
|
||||
|
||||
// 3. 更新状态
|
||||
PathEditState = PathEditState.None;
|
||||
LogManager.Info("点击工具已停止");
|
||||
LogManager.WriteLog("[事件清理] ===== StopClickTool执行完成,所有事件订阅已清理 =====");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -1068,13 +1108,11 @@ namespace NavisworksTransport
|
||||
lastPoint.Type = PathPointType.EndPoint;
|
||||
lastPoint.Name = GeneratePointName(PathPointType.EndPoint);
|
||||
|
||||
// 更新3D标记类型
|
||||
// 更新3D路径可视化
|
||||
if (_renderPlugin != null)
|
||||
{
|
||||
// 移除旧标记
|
||||
_renderPlugin.RemoveMarkerAt(lastPoint.Position, 2.0);
|
||||
// 添加终点标记
|
||||
_renderPlugin.AddCircleMarker(lastPoint.Position, PathPointType.EndPoint, CurrentRoute.Points.Count);
|
||||
// 重新渲染整个路径以反映类型变更
|
||||
_renderPlugin.RenderPath(CurrentRoute);
|
||||
}
|
||||
|
||||
LogManager.Info($"已自动设置最后一个点为终点: {lastPoint.Name}");
|
||||
@ -1908,8 +1946,44 @@ namespace NavisworksTransport
|
||||
|
||||
private bool DeactivateToolPlugin()
|
||||
{
|
||||
// TODO: 实现ToolPlugin停用逻辑
|
||||
return true;
|
||||
if (!_isToolPluginActive)
|
||||
{
|
||||
LogManager.WriteLog("[ToolPlugin] ToolPlugin未激活,无需停用");
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.WriteLog("[ToolPlugin] ===== 开始停用ToolPlugin =====");
|
||||
|
||||
// 1. 取消事件订阅
|
||||
LogManager.WriteLog("[ToolPlugin] 步骤1: 取消事件订阅");
|
||||
PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
|
||||
LogManager.WriteLog("[ToolPlugin] ✓ 事件订阅已取消");
|
||||
|
||||
// 2. 重置为无活动工具状态
|
||||
LogManager.WriteLog("[ToolPlugin] 步骤2: 重置为默认工具");
|
||||
try
|
||||
{
|
||||
// 使用Tool.None重置到无活动工具状态,让Navisworks处理默认导航
|
||||
Application.MainDocument.Tool.Value = Tool.None;
|
||||
LogManager.WriteLog("[ToolPlugin] ✓ 已重置工具为None状态");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[ToolPlugin] 重置工具状态失败: {ex.Message}");
|
||||
}
|
||||
|
||||
_isToolPluginActive = false;
|
||||
LogManager.WriteLog("[ToolPlugin] ===== ToolPlugin停用完成 =====");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[ToolPlugin] 停用异常: {ex.Message}");
|
||||
LogManager.WriteLog($"[ToolPlugin] 堆栈: {ex.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -2137,71 +2211,10 @@ namespace NavisworksTransport
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAutoPath)
|
||||
{
|
||||
// 自动路径可视化
|
||||
var sortedPoints = route.GetSortedPoints();
|
||||
|
||||
// 安全显示自动路径,限制显示数量防止崩溃
|
||||
int maxDisplayPoints = Math.Min(10, sortedPoints.Count); // 最多显示10个点
|
||||
LogManager.Info($"安全显示自动路径: 原始{sortedPoints.Count}个点,限制显示{maxDisplayPoints}个点");
|
||||
|
||||
if (sortedPoints.Count > maxDisplayPoints)
|
||||
{
|
||||
// 如果点太多,只显示起点、终点和几个中间点
|
||||
var displayPoints = new List<PathPoint>
|
||||
{
|
||||
sortedPoints[0] // 起点
|
||||
};
|
||||
|
||||
// 添加几个等间距的中间点
|
||||
for (int i = 1; i < maxDisplayPoints - 1; i++)
|
||||
{
|
||||
int index = (int)((double)i / (maxDisplayPoints - 1) * (sortedPoints.Count - 1));
|
||||
displayPoints.Add(sortedPoints[index]);
|
||||
}
|
||||
|
||||
displayPoints.Add(sortedPoints[sortedPoints.Count - 1]); // 终点
|
||||
|
||||
int displayIndex = 0;
|
||||
foreach (var point in displayPoints)
|
||||
{
|
||||
LogManager.Info($"[路径点{displayIndex}] 坐标: ({point.Position.X:F2}, {point.Position.Y:F2}, {point.Position.Z:F2})");
|
||||
renderPlugin.AddCircleMarker(point.Position, point.Type, -1000 - displayIndex);
|
||||
displayIndex++;
|
||||
}
|
||||
|
||||
LogManager.Info($"已可视化自动路径: {route.Name},安全显示 {displayIndex} 个关键点和橙色连线");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 点数较少时完整显示
|
||||
int displayIndex = 0;
|
||||
for (int i = 0; i < sortedPoints.Count; i++)
|
||||
{
|
||||
var point = sortedPoints[i];
|
||||
LogManager.Info($"[路径点{displayIndex}] 坐标: ({point.Position.X:F2}, {point.Position.Y:F2}, {point.Position.Z:F2})");
|
||||
renderPlugin.AddCircleMarker(point.Position, point.Type, -1000 - displayIndex);
|
||||
displayIndex++;
|
||||
}
|
||||
|
||||
LogManager.Info($"已可视化自动路径: {route.Name},完整显示 {displayIndex} 个路径点和橙色连线");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 手工路径:完整显示,清除所有标记后重绘,使用黑色连线
|
||||
renderPlugin.ClearAllMarkers();
|
||||
|
||||
var sortedPoints = route.GetSortedPoints();
|
||||
for (int i = 0; i < sortedPoints.Count; i++)
|
||||
{
|
||||
var point = sortedPoints[i];
|
||||
renderPlugin.AddCircleMarker(point.Position, point.Type, i + 1);
|
||||
}
|
||||
|
||||
LogManager.Info($"已绘制路径: {route.Name},包含 {sortedPoints.Count} 个路径点和连线");
|
||||
}
|
||||
// 使用新的统一路径渲染API
|
||||
renderPlugin.RenderPath(route);
|
||||
|
||||
LogManager.Info($"已渲染路径: {route.Name},包含 {route.Points.Count} 个路径点");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -3,9 +3,96 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using Autodesk.Navisworks.Api.Plugins;
|
||||
using NavisworksTransport.Core;
|
||||
|
||||
namespace NavisworksTransport
|
||||
{
|
||||
/// <summary>
|
||||
/// 连线标记,用于渲染路径点之间的连接线
|
||||
/// </summary>
|
||||
public class LineMarker
|
||||
{
|
||||
/// <summary>
|
||||
/// 连线起点
|
||||
/// </summary>
|
||||
public Point3D StartPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连线终点
|
||||
/// </summary>
|
||||
public Point3D EndPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连线颜色
|
||||
/// </summary>
|
||||
public Color Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连线半径
|
||||
/// </summary>
|
||||
public double Radius { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 起点在路径中的索引
|
||||
/// </summary>
|
||||
public int FromIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终点在路径中的索引
|
||||
/// </summary>
|
||||
public int ToIndex { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"LineMarker[{FromIndex}->{ToIndex}, 起点=({StartPoint.X:F2},{StartPoint.Y:F2},{StartPoint.Z:F2}), 终点=({EndPoint.X:F2},{EndPoint.Y:F2},{EndPoint.Z:F2})]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路径可视化数据,包含一个完整路径的所有可视化元素
|
||||
/// </summary>
|
||||
public class PathVisualization
|
||||
{
|
||||
/// <summary>
|
||||
/// 路径唯一标识
|
||||
/// </summary>
|
||||
public string PathId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路径数据引用
|
||||
/// </summary>
|
||||
public PathRoute PathRoute { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 点标记集合
|
||||
/// </summary>
|
||||
public List<CircleMarker> PointMarkers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连线标记集合
|
||||
/// </summary>
|
||||
public List<LineMarker> LineMarkers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新时间
|
||||
/// </summary>
|
||||
public DateTime LastUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public PathVisualization()
|
||||
{
|
||||
PointMarkers = new List<CircleMarker>();
|
||||
LineMarkers = new List<LineMarker>();
|
||||
LastUpdated = DateTime.Now;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"PathVisualization[PathId={PathId}, 点数={PointMarkers.Count}, 连线数={LineMarkers.Count}]";
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 路径点圆形标记渲染插件
|
||||
/// 使用Graphics.Circle在3D空间绘制圆形标记
|
||||
@ -14,9 +101,11 @@ namespace NavisworksTransport
|
||||
public class PathPointRenderPlugin : RenderPlugin
|
||||
{
|
||||
private readonly object _lockObject = new object();
|
||||
private List<CircleMarker> _circleMarkers = new List<CircleMarker>();
|
||||
private Dictionary<string, PathVisualization> _pathVisualizations = new Dictionary<string, PathVisualization>();
|
||||
private bool _isEnabled = true;
|
||||
private int _lastAutoMarkersCount = -1; // 用于检测自动路径标记数量变化
|
||||
|
||||
// 为向后兼容保留的旧字段
|
||||
private List<CircleMarker> _circleMarkers = new List<CircleMarker>();
|
||||
|
||||
// 静态实例,用于外部访问
|
||||
private static PathPointRenderPlugin _instance;
|
||||
@ -52,7 +141,21 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前圆形标记数量
|
||||
/// 当前路径总数
|
||||
/// </summary>
|
||||
public int PathCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
return _pathVisualizations.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前点标记总数
|
||||
/// </summary>
|
||||
public int MarkerCount
|
||||
{
|
||||
@ -60,7 +163,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
return _circleMarkers.Count;
|
||||
return _pathVisualizations.Values.Sum(v => v.PointMarkers.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,85 +186,38 @@ namespace NavisworksTransport
|
||||
return; // 静默返回,避免日志泛滥
|
||||
}
|
||||
|
||||
// 检查是否有标记需要渲染
|
||||
int markerCount;
|
||||
// 检查是否有路径需要渲染
|
||||
int pathCount;
|
||||
lock (_lockObject)
|
||||
{
|
||||
markerCount = _circleMarkers.Count;
|
||||
pathCount = _pathVisualizations.Count;
|
||||
}
|
||||
|
||||
if (markerCount == 0) return;
|
||||
if (pathCount == 0) return;
|
||||
|
||||
// 使用BeginModelContext确保正确的渲染上下文
|
||||
graphics.BeginModelContext();
|
||||
|
||||
// 缓存转换系数,避免重复计算
|
||||
double lineRadiusInMeters = 0.2;
|
||||
double lineRadiusInModelUnits = lineRadiusInMeters * GetMetersToModelUnitsConversionFactor();
|
||||
|
||||
lock (_lockObject)
|
||||
{
|
||||
// 优化:预过滤和排序,减少重复计算
|
||||
var manualMarkers = _circleMarkers.Where(m => m.SequenceNumber >= 0)
|
||||
.OrderBy(m => m.SequenceNumber)
|
||||
.ToArray(); // 转为数组提高性能
|
||||
|
||||
var autoMarkers = _circleMarkers.Where(m => m.SequenceNumber < -999)
|
||||
.OrderByDescending(m => m.SequenceNumber)
|
||||
.ToArray();
|
||||
|
||||
// 绘制连接线段(仅在有多个标记时)
|
||||
if (markerCount > 1)
|
||||
foreach (var visualization in _pathVisualizations.Values)
|
||||
{
|
||||
// 1. 绘制手动路径连线(正序号,黑色)
|
||||
if (manualMarkers.Length > 1)
|
||||
// 渲染所有点标记
|
||||
foreach (var pointMarker in visualization.PointMarkers)
|
||||
{
|
||||
graphics.Color(Color.FromByteRGB(0, 0, 0), 1.0);
|
||||
for (int i = 0; i < manualMarkers.Length - 1; i++)
|
||||
{
|
||||
var current = manualMarkers[i];
|
||||
var next = manualMarkers[i + 1];
|
||||
|
||||
// 只为连续序号的点绘制连线
|
||||
if (next.SequenceNumber == current.SequenceNumber + 1)
|
||||
{
|
||||
graphics.Cylinder(current.Center, next.Center, lineRadiusInModelUnits);
|
||||
}
|
||||
}
|
||||
graphics.Color(pointMarker.Color, pointMarker.Alpha);
|
||||
graphics.Sphere(pointMarker.Center, pointMarker.Radius);
|
||||
}
|
||||
|
||||
// 2. 绘制自动路径连线(负序号-1000系列,橙色)
|
||||
if (autoMarkers.Length > 1)
|
||||
|
||||
// 渲染所有连线
|
||||
LogManager.WriteLog($"[渲染连线] 路径 {visualization.PathId} 有 {visualization.LineMarkers.Count} 条连线");
|
||||
foreach (var lineMarker in visualization.LineMarkers)
|
||||
{
|
||||
graphics.Color(Color.FromByteRGB(255, 165, 0), 1.0);
|
||||
|
||||
// 只在标记数量变化时输出日志
|
||||
if (autoMarkers.Length != _lastAutoMarkersCount)
|
||||
{
|
||||
LogManager.WriteLog($"[自动路径连线] 找到 {autoMarkers.Length} 个自动路径标记");
|
||||
_lastAutoMarkersCount = autoMarkers.Length;
|
||||
}
|
||||
|
||||
for (int i = 0; i < autoMarkers.Length - 1; i++)
|
||||
{
|
||||
var current = autoMarkers[i];
|
||||
var next = autoMarkers[i + 1];
|
||||
|
||||
// 为连续负序号的点绘制连线
|
||||
if (current.SequenceNumber - next.SequenceNumber == 1)
|
||||
{
|
||||
graphics.Cylinder(current.Center, next.Center, lineRadiusInModelUnits);
|
||||
}
|
||||
}
|
||||
graphics.Color(lineMarker.Color, 1.0);
|
||||
graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius);
|
||||
LogManager.WriteLog($"[渲染连线] 绘制连线 {lineMarker.FromIndex}->{lineMarker.ToIndex}, 半径={lineMarker.Radius:F3}");
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制所有球体标记(使用原始集合避免重复过滤)
|
||||
foreach (var marker in _circleMarkers)
|
||||
{
|
||||
graphics.Color(marker.Color, marker.Alpha);
|
||||
graphics.Sphere(marker.Center, marker.Radius);
|
||||
}
|
||||
}
|
||||
|
||||
graphics.EndModelContext();
|
||||
@ -174,42 +230,371 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
#region 新的统一路径可视化接口
|
||||
|
||||
/// <summary>
|
||||
/// 添加球体标记
|
||||
/// 渲染完整路径
|
||||
/// </summary>
|
||||
/// <param name="center">圆心位置</param>
|
||||
/// <param name="pointType">路径点类型</param>
|
||||
/// <param name="sequenceNumber">序号</param>
|
||||
public void AddCircleMarker(Point3D center, PathPointType pointType, int sequenceNumber)
|
||||
/// <param name="pathRoute">路径数据</param>
|
||||
public void RenderPath(PathRoute pathRoute)
|
||||
{
|
||||
if (pathRoute == null)
|
||||
{
|
||||
LogManager.WriteLog("[路径渲染] 路径数据为空");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var marker = new CircleMarker
|
||||
{
|
||||
Center = center,
|
||||
Normal = new Vector3D(0, 0, 1), // 垂直向上
|
||||
Radius = GetRadiusForPointType(pointType),
|
||||
Color = GetColorForPointType(pointType),
|
||||
Alpha = 1.0, // 完全不透明
|
||||
Filled = true, // 实心圆
|
||||
PointType = pointType,
|
||||
SequenceNumber = sequenceNumber,
|
||||
CreatedTime = DateTime.Now
|
||||
var visualization = new PathVisualization
|
||||
{
|
||||
PathId = pathRoute.Id,
|
||||
PathRoute = pathRoute
|
||||
};
|
||||
|
||||
BuildVisualization(visualization);
|
||||
|
||||
lock (_lockObject)
|
||||
{
|
||||
_circleMarkers.Add(marker);
|
||||
_pathVisualizations[pathRoute.Id] = visualization;
|
||||
}
|
||||
|
||||
//LogManager.WriteLog($"[圆形标记] 添加圆形标记: 类型={pointType}, 序号={sequenceNumber}, 中心=({center.X:F2}, {center.Y:F2}, {center.Z:F2})");
|
||||
|
||||
// 触发视图刷新
|
||||
LogManager.WriteLog($"[路径渲染] 渲染路径: {pathRoute.Name}, 点数: {pathRoute.Points.Count}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[圆形标记] 添加标记失败: {ex.Message}");
|
||||
LogManager.WriteLog($"[路径渲染] 渲染路径失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新路径可视化
|
||||
/// </summary>
|
||||
/// <param name="pathId">路径ID</param>
|
||||
public void RefreshPath(string pathId)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
if (_pathVisualizations.TryGetValue(pathId, out var visualization))
|
||||
{
|
||||
BuildVisualization(visualization);
|
||||
LogManager.WriteLog($"[路径刷新] 刷新路径: {pathId}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除路径
|
||||
/// </summary>
|
||||
/// <param name="pathId">路径ID</param>
|
||||
public void RemovePath(string pathId)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
if (_pathVisualizations.Remove(pathId))
|
||||
{
|
||||
LogManager.WriteLog($"[路径移除] 移除路径: {pathId}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有路径
|
||||
/// </summary>
|
||||
public void ClearAllPaths()
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
var count = _pathVisualizations.Count;
|
||||
_pathVisualizations.Clear();
|
||||
LogManager.WriteLog($"[路径清空] 清空所有路径,共{count}个");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建路径可视化
|
||||
/// </summary>
|
||||
/// <param name="visualization">路径可视化对象</param>
|
||||
private void BuildVisualization(PathVisualization visualization)
|
||||
{
|
||||
// 清空现有标记
|
||||
visualization.PointMarkers.Clear();
|
||||
visualization.LineMarkers.Clear();
|
||||
|
||||
var points = visualization.PathRoute.Points;
|
||||
if (points.Count == 0) return;
|
||||
|
||||
// 按索引排序点
|
||||
var sortedPoints = points.OrderBy(p => p.Index).ToList();
|
||||
|
||||
// 构建点标记
|
||||
foreach (var point in sortedPoints)
|
||||
{
|
||||
var pointMarker = CreatePointMarker(point);
|
||||
visualization.PointMarkers.Add(pointMarker);
|
||||
}
|
||||
|
||||
// 构建连线标记(按排序后的顺序连接)
|
||||
for (int i = 0; i < sortedPoints.Count - 1; i++)
|
||||
{
|
||||
var currentPoint = sortedPoints[i];
|
||||
var nextPoint = sortedPoints[i + 1];
|
||||
|
||||
var lineMarker = new LineMarker
|
||||
{
|
||||
StartPoint = currentPoint.Position,
|
||||
EndPoint = nextPoint.Position,
|
||||
Color = GetLineColor(),
|
||||
Radius = GetLineRadius(),
|
||||
FromIndex = currentPoint.Index,
|
||||
ToIndex = nextPoint.Index
|
||||
};
|
||||
visualization.LineMarkers.Add(lineMarker);
|
||||
|
||||
LogManager.WriteLog($"[连线构建] 创建连线: {currentPoint.Index} -> {nextPoint.Index}, " +
|
||||
$"起点({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2}) -> " +
|
||||
$"终点({nextPoint.Position.X:F2}, {nextPoint.Position.Y:F2}, {nextPoint.Position.Z:F2})");
|
||||
}
|
||||
|
||||
visualization.LastUpdated = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建点标记
|
||||
/// </summary>
|
||||
/// <param name="point">路径点</param>
|
||||
/// <returns>圆形标记</returns>
|
||||
private CircleMarker CreatePointMarker(PathPoint point)
|
||||
{
|
||||
return new CircleMarker
|
||||
{
|
||||
Center = point.Position,
|
||||
Normal = new Vector3D(0, 0, 1),
|
||||
Radius = GetRadiusForPointType(point.Type),
|
||||
Color = GetColorForPointType(point.Type),
|
||||
Alpha = 1.0,
|
||||
Filled = true,
|
||||
PointType = point.Type,
|
||||
SequenceNumber = point.Index, // 使用Index而不是任意序号
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取连线颜色(统一使用橙色)
|
||||
/// </summary>
|
||||
/// <returns>连线颜色</returns>
|
||||
private Color GetLineColor()
|
||||
{
|
||||
return Color.FromByteRGB(255, 165, 0); // 统一使用橙色连线
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取连线半径
|
||||
/// </summary>
|
||||
/// <returns>连线半径</returns>
|
||||
private double GetLineRadius()
|
||||
{
|
||||
double lineRadiusInMeters = 0.2;
|
||||
return lineRadiusInMeters * GetMetersToModelUnitsConversionFactor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加路径点到指定路径
|
||||
/// </summary>
|
||||
/// <param name="pathId">路径ID</param>
|
||||
/// <param name="newPoint">新的路径点</param>
|
||||
/// <param name="insertIndex">插入位置索引,-1表示添加到末尾</param>
|
||||
public void AddPointToPath(string pathId, PathPoint newPoint, int insertIndex = -1)
|
||||
{
|
||||
var visualization = GetPathVisualization(pathId);
|
||||
if (visualization == null)
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var pathRoute = visualization.PathRoute;
|
||||
|
||||
if (insertIndex == -1)
|
||||
{
|
||||
// 添加到末尾
|
||||
newPoint.Index = pathRoute.Points.Count;
|
||||
pathRoute.Points.Add(newPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 插入到指定位置
|
||||
pathRoute.Points.Insert(insertIndex, newPoint);
|
||||
// 重新分配所有点的索引
|
||||
ReindexPoints(pathRoute);
|
||||
}
|
||||
|
||||
// 重建可视化
|
||||
BuildVisualization(visualization);
|
||||
LogManager.WriteLog($"[路径编辑] 添加路径点: {newPoint.Name} 到路径 {pathId}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 添加路径点失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定路径移除路径点
|
||||
/// </summary>
|
||||
/// <param name="pathId">路径ID</param>
|
||||
/// <param name="pointIndex">要移除的点索引</param>
|
||||
public void RemovePointFromPath(string pathId, int pointIndex)
|
||||
{
|
||||
var visualization = GetPathVisualization(pathId);
|
||||
if (visualization == null)
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var pathRoute = visualization.PathRoute;
|
||||
var pointToRemove = pathRoute.Points.FirstOrDefault(p => p.Index == pointIndex);
|
||||
|
||||
if (pointToRemove != null)
|
||||
{
|
||||
pathRoute.Points.Remove(pointToRemove);
|
||||
// 重新分配索引
|
||||
ReindexPoints(pathRoute);
|
||||
|
||||
// 重建可视化
|
||||
BuildVisualization(visualization);
|
||||
LogManager.WriteLog($"[路径编辑] 移除路径点: 索引 {pointIndex} 从路径 {pathId}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 移除路径点失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新指定路径中的路径点
|
||||
/// </summary>
|
||||
/// <param name="pathId">路径ID</param>
|
||||
/// <param name="pointIndex">要更新的点索引</param>
|
||||
/// <param name="updatedPoint">更新后的路径点</param>
|
||||
public void UpdatePointInPath(string pathId, int pointIndex, PathPoint updatedPoint)
|
||||
{
|
||||
var visualization = GetPathVisualization(pathId);
|
||||
if (visualization == null)
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 未找到路径: {pathId}");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var pathRoute = visualization.PathRoute;
|
||||
var existingPoint = pathRoute.Points.FirstOrDefault(p => p.Index == pointIndex);
|
||||
|
||||
if (existingPoint != null)
|
||||
{
|
||||
// 保持索引不变
|
||||
updatedPoint.Index = pointIndex;
|
||||
|
||||
// 替换点
|
||||
var index = pathRoute.Points.IndexOf(existingPoint);
|
||||
pathRoute.Points[index] = updatedPoint;
|
||||
|
||||
// 重建可视化
|
||||
BuildVisualization(visualization);
|
||||
LogManager.WriteLog($"[路径编辑] 更新路径点: 索引 {pointIndex} 在路径 {pathId}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 未找到索引为 {pointIndex} 的路径点");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[路径编辑] 更新路径点失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新分配路径点索引
|
||||
/// </summary>
|
||||
/// <param name="pathRoute">路径对象</param>
|
||||
private void ReindexPoints(PathRoute pathRoute)
|
||||
{
|
||||
// 按照当前在List中的位置重新分配连续索引
|
||||
for (int i = 0; i < pathRoute.Points.Count; i++)
|
||||
{
|
||||
pathRoute.Points[i].Index = i;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取路径可视化对象
|
||||
/// </summary>
|
||||
/// <param name="pathId">路径ID</param>
|
||||
/// <returns>路径可视化对象,如果不存在返回null</returns>
|
||||
private PathVisualization GetPathVisualization(string pathId)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
_pathVisualizations.TryGetValue(pathId, out var visualization);
|
||||
return visualization;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 向后兼容的旧接口(保留以避免编译错误)
|
||||
|
||||
/// <summary>
|
||||
/// [已过时] 添加球体标记 - 请使用RenderPath方法代替
|
||||
/// </summary>
|
||||
/// <param name="center">圆心位置</param>
|
||||
/// <param name="pointType">路径点类型</param>
|
||||
/// <param name="sequenceNumber">序号</param>
|
||||
[Obsolete("此方法已过时,请使用RenderPath方法进行统一的路径可视化", false)]
|
||||
public void AddCircleMarker(Point3D center, PathPointType pointType, int sequenceNumber)
|
||||
{
|
||||
LogManager.WriteLog($"[兼容性警告] 使用了已过时的AddCircleMarker方法,建议使用RenderPath方法");
|
||||
|
||||
try
|
||||
{
|
||||
// 为了兼容性,创建一个临时路径
|
||||
var tempPath = new PathRoute($"TempPath_{Guid.NewGuid().ToString("N").Substring(0, 8)}")
|
||||
{
|
||||
Id = $"temp_{sequenceNumber}_{DateTime.Now.Ticks}"
|
||||
};
|
||||
|
||||
var pathPoint = new PathPoint(center, $"Point_{sequenceNumber}", pointType)
|
||||
{
|
||||
Index = 0
|
||||
};
|
||||
tempPath.Points.Add(pathPoint);
|
||||
|
||||
// 使用新的渲染方法
|
||||
RenderPath(tempPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[兼容性标记] 添加标记失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,145 +640,58 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有球体标记
|
||||
/// [已过时] 清除所有球体标记 - 请使用ClearAllPaths方法代替
|
||||
/// </summary>
|
||||
[Obsolete("此方法已过时,请使用ClearAllPaths方法", false)]
|
||||
public void ClearAllMarkers()
|
||||
{
|
||||
try
|
||||
{
|
||||
int removedCount = 0;
|
||||
|
||||
lock (_lockObject)
|
||||
{
|
||||
removedCount = _circleMarkers.Count;
|
||||
_circleMarkers.Clear();
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"[球体标记] 清除所有标记,共移除 {removedCount} 个球体标记");
|
||||
|
||||
if (removedCount > 0)
|
||||
{
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[球体标记] 清除标记失败: {ex.Message}");
|
||||
}
|
||||
LogManager.WriteLog($"[兼容性警告] 使用了已过时的ClearAllMarkers方法,建议使用ClearAllPaths方法");
|
||||
ClearAllPaths();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有自动路径标记(序列号-1000系列)
|
||||
/// [已过时] 清除所有自动路径标记 - 请使用ClearAllPaths方法代替
|
||||
/// </summary>
|
||||
[Obsolete("此方法已过时,请使用ClearAllPaths方法", false)]
|
||||
public void ClearAutoPathMarkers()
|
||||
{
|
||||
try
|
||||
{
|
||||
int removedCount = 0;
|
||||
|
||||
lock (_lockObject)
|
||||
{
|
||||
// 移除所有序列号小于-999的标记(自动路径标记)
|
||||
for (int i = _circleMarkers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var marker = _circleMarkers[i];
|
||||
if (marker.SequenceNumber < -999)
|
||||
{
|
||||
_circleMarkers.RemoveAt(i);
|
||||
removedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 重置自动路径标记计数
|
||||
_lastAutoMarkersCount = -1;
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"[球体标记] 清除自动路径标记,共移除 {removedCount} 个自动路径点");
|
||||
|
||||
if (removedCount > 0)
|
||||
{
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[球体标记] 清除自动路径标记失败: {ex.Message}");
|
||||
}
|
||||
LogManager.WriteLog($"[兼容性警告] 使用了已过时的ClearAutoPathMarkers方法,建议使用ClearAllPaths方法");
|
||||
ClearAllPaths();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除手动路径标记(序列号>=0)
|
||||
/// [已过时] 清除手动路径标记 - 请使用ClearAllPaths方法代替
|
||||
/// </summary>
|
||||
[Obsolete("此方法已过时,请使用ClearAllPaths方法", false)]
|
||||
public void ClearManualPathMarkers()
|
||||
{
|
||||
try
|
||||
{
|
||||
int removedCount = 0;
|
||||
|
||||
lock (_lockObject)
|
||||
{
|
||||
// 移除所有序列号>=0的标记(手动路径标记)
|
||||
for (int i = _circleMarkers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var marker = _circleMarkers[i];
|
||||
if (marker.SequenceNumber >= 0)
|
||||
{
|
||||
_circleMarkers.RemoveAt(i);
|
||||
removedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog($"[球体标记] 清除手动路径标记,共移除 {removedCount} 个手动路径点");
|
||||
|
||||
if (removedCount > 0)
|
||||
{
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[球体标记] 清除手动路径标记失败: {ex.Message}");
|
||||
}
|
||||
LogManager.WriteLog($"[兼容性警告] 使用了已过时的ClearManualPathMarkers方法,建议使用ClearAllPaths方法");
|
||||
ClearAllPaths();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有球体标记的副本
|
||||
/// [已过时] 获取所有球体标记的副本 - 此方法不再适用于新的路径系统
|
||||
/// </summary>
|
||||
/// <returns>标记列表</returns>
|
||||
/// <returns>空列表</returns>
|
||||
[Obsolete("此方法已过时,新的路径系统不使用独立的标记概念", false)]
|
||||
public List<CircleMarker> GetAllMarkers()
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
return new List<CircleMarker>(_circleMarkers);
|
||||
}
|
||||
LogManager.WriteLog($"[兼容性警告] 使用了已过时的GetAllMarkers方法,新系统不再支持独立标记");
|
||||
return new List<CircleMarker>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据序号更新一个已存在的球体标记
|
||||
/// [已过时] 根据序号更新一个已存在的球体标记 - 请使用UpdatePointInPath方法代替
|
||||
/// </summary>
|
||||
[Obsolete("此方法已过时,请使用UpdatePointInPath方法更新路径中的点", false)]
|
||||
public void UpdateMarker(int sequenceNumber, Color newColor, double newRadius)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
var markerToUpdate = _circleMarkers.FirstOrDefault(m => m.SequenceNumber == sequenceNumber);
|
||||
if (markerToUpdate != null)
|
||||
{
|
||||
markerToUpdate.Color = newColor;
|
||||
markerToUpdate.Radius = newRadius;
|
||||
LogManager.WriteLog($"[球体标记] 更新标记: 序号={sequenceNumber}, 新颜色={newColor}, 新半径={newRadius:F2}");
|
||||
RequestViewRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.WriteLog($"[球体标记] 更新标记失败: {ex.Message}");
|
||||
}
|
||||
LogManager.WriteLog($"[兼容性警告] 使用了已过时的UpdateMarker方法,请使用UpdatePointInPath方法");
|
||||
// 由于新系统没有直接的序号对应关系,这个方法不再有效
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有辅助方法
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -31,34 +31,7 @@
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="系统管理" Name="SystemManagementTab">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="10">
|
||||
|
||||
<GroupBox Header="日志管理" Margin="0,10" Height="100">
|
||||
<StackPanel Orientation="Horizontal" Margin="10">
|
||||
<Button Content="查看日志" Name="ViewLogButton" Margin="0,0,10,0"/>
|
||||
<Button Content="清空日志" Name="ClearLogButton" Margin="0,0,10,0"/>
|
||||
<Button Content="导出日志" Name="ExportLogButton"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="插件设置" Margin="0,10" Height="100">
|
||||
<StackPanel Orientation="Horizontal" Margin="10">
|
||||
<Button Content="设置选项" Name="SettingsButton" Margin="0,0,10,0"/>
|
||||
<Button Content="重置设置" Name="ResetSettingsButton"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="系统信息" Margin="0,10" Height="160">
|
||||
<StackPanel Margin="10">
|
||||
<Label Content="插件版本: v1.0" Name="VersionLabel"/>
|
||||
<Label Content="Navisworks版本: 2026" Name="NavisVersionLabel"/>
|
||||
<Label Content="系统状态: 正常" Name="SystemStatusLabel"/>
|
||||
<Button Content="检查更新" Name="CheckUpdateButton" Margin="0,10,0,0"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<views:SystemManagementView x:Name="SystemManagementView"/>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ namespace NavisworksTransport.UI.WPF
|
||||
{
|
||||
// ViewModel实例
|
||||
public LogisticsControlViewModel ViewModel { get; private set; }
|
||||
public SystemManagementViewModel SystemManagementViewModel { get; private set; }
|
||||
|
||||
// 分层管理视图
|
||||
private LayerManagementView _layerManagementView;
|
||||
@ -32,7 +33,11 @@ namespace NavisworksTransport.UI.WPF
|
||||
|
||||
// 创建并设置ViewModel
|
||||
ViewModel = new LogisticsControlViewModel();
|
||||
SystemManagementViewModel = new SystemManagementViewModel();
|
||||
DataContext = ViewModel;
|
||||
|
||||
// 为SystemManagementView设置独立的DataContext
|
||||
SystemManagementView.DataContext = SystemManagementViewModel;
|
||||
|
||||
InitializeSession();
|
||||
InitializeViews();
|
||||
@ -68,6 +73,9 @@ namespace NavisworksTransport.UI.WPF
|
||||
|
||||
// 初始化PathEditingView
|
||||
InitializePathEditingView();
|
||||
|
||||
// 初始化SystemManagementView
|
||||
InitializeSystemManagementView();
|
||||
|
||||
LogManager.Info("子视图初始化完成");
|
||||
}
|
||||
@ -180,6 +188,24 @@ namespace NavisworksTransport.UI.WPF
|
||||
LogManager.Error($"初始化PathEditingView失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化SystemManagementView
|
||||
/// </summary>
|
||||
private void InitializeSystemManagementView()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SystemManagementView?.DataContext != null)
|
||||
{
|
||||
LogManager.Info("SystemManagementView初始化完成");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"初始化SystemManagementView失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化事件处理器
|
||||
@ -282,6 +308,9 @@ namespace NavisworksTransport.UI.WPF
|
||||
|
||||
// 清理PathEditingView
|
||||
PathEditingView?.Cleanup();
|
||||
|
||||
// 清理SystemManagementViewModel
|
||||
SystemManagementViewModel?.Cleanup();
|
||||
|
||||
// TODO: 清理路径规划管理器事件订阅
|
||||
// 暂时注释掉,避免编译错误
|
||||
|
||||
@ -60,6 +60,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
private bool _hasSelectedAnimatedObject = false;
|
||||
private bool _canGenerateAnimation = false;
|
||||
private string _generationStatus = "就绪";
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
@ -856,6 +857,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行清除移动物体命令
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// 执行清除移动物体命令
|
||||
/// </summary>
|
||||
@ -863,13 +867,44 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("开始清除移动物体选择并恢复原始位置");
|
||||
|
||||
// 如果有选中的物体,则恢复到原始位置
|
||||
if (SelectedAnimatedObject != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"开始恢复物体 '{SelectedAnimatedObject.DisplayName}' 到原始位置");
|
||||
|
||||
// 使用ResetPermanentTransform清除所有增量变换,恢复到设计文件中的原始位置
|
||||
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { SelectedAnimatedObject };
|
||||
doc.Models.ResetPermanentTransform(modelItems);
|
||||
|
||||
LogManager.Info($"物体 '{SelectedAnimatedObject.DisplayName}' 已成功恢复到原始位置");
|
||||
GenerationStatus = "已清除移动物体选择并恢复到原始位置";
|
||||
}
|
||||
catch (Exception restoreEx)
|
||||
{
|
||||
LogManager.Error($"恢复物体到原始位置时发生错误: {restoreEx.Message}");
|
||||
GenerationStatus = $"已清除物体选择,但恢复位置失败: {restoreEx.Message}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info("没有选中的物体需要清除");
|
||||
GenerationStatus = "已清除移动物体选择";
|
||||
}
|
||||
|
||||
// 清理选择状态
|
||||
SelectedAnimatedObject = null;
|
||||
GenerationStatus = "已清除移动物体选择";
|
||||
LogManager.Info("移动物体选择已清除");
|
||||
|
||||
LogManager.Info("移动物体选择已完全清除");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"清除移动物体选择时发生错误: {ex.Message}");
|
||||
GenerationStatus = $"清除失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -61,21 +61,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
private string _collisionStatus = "就绪";
|
||||
private string _collisionSummary = "尚未运行碰撞检测";
|
||||
|
||||
// 系统管理相关字段
|
||||
private string _modelSplitterStatus = "就绪";
|
||||
private ObservableCollection<string> _logLevels;
|
||||
private string _selectedLogLevel = "Info";
|
||||
private string _logStatus = "日志系统正常";
|
||||
private bool _isAutoSaveEnabled = true;
|
||||
private bool _isDebugModeEnabled = false;
|
||||
private string _settingsStatus = "设置已加载";
|
||||
private string _pluginVersion = "v1.0";
|
||||
private string _navisworksVersion = "2026";
|
||||
private string _systemStatus = "正常";
|
||||
private string _systemStatusColor = "Green";
|
||||
private string _memoryUsage = "0 MB";
|
||||
private string _runningTime = "00:00:00";
|
||||
private string _performanceInfo = "性能监控就绪";
|
||||
|
||||
#endregion
|
||||
|
||||
@ -341,135 +326,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
#endregion
|
||||
|
||||
#region 系统管理属性
|
||||
|
||||
/// <summary>
|
||||
/// 模型分层拆分状态
|
||||
/// </summary>
|
||||
public string ModelSplitterStatus
|
||||
{
|
||||
get => _modelSplitterStatus;
|
||||
set => SetProperty(ref _modelSplitterStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志级别集合
|
||||
/// </summary>
|
||||
public ObservableCollection<string> LogLevels
|
||||
{
|
||||
get => _logLevels;
|
||||
set => SetProperty(ref _logLevels, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选中的日志级别
|
||||
/// </summary>
|
||||
public string SelectedLogLevel
|
||||
{
|
||||
get => _selectedLogLevel;
|
||||
set => SetProperty(ref _selectedLogLevel, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志状态
|
||||
/// </summary>
|
||||
public string LogStatus
|
||||
{
|
||||
get => _logStatus;
|
||||
set => SetProperty(ref _logStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用自动保存
|
||||
/// </summary>
|
||||
public bool IsAutoSaveEnabled
|
||||
{
|
||||
get => _isAutoSaveEnabled;
|
||||
set => SetProperty(ref _isAutoSaveEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用调试模式
|
||||
/// </summary>
|
||||
public bool IsDebugModeEnabled
|
||||
{
|
||||
get => _isDebugModeEnabled;
|
||||
set => SetProperty(ref _isDebugModeEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置状态
|
||||
/// </summary>
|
||||
public string SettingsStatus
|
||||
{
|
||||
get => _settingsStatus;
|
||||
set => SetProperty(ref _settingsStatus, 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 SystemStatus
|
||||
{
|
||||
get => _systemStatus;
|
||||
set => SetProperty(ref _systemStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态颜色
|
||||
/// </summary>
|
||||
public string SystemStatusColor
|
||||
{
|
||||
get => _systemStatusColor;
|
||||
set => SetProperty(ref _systemStatusColor, 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能信息
|
||||
/// </summary>
|
||||
public string PerformanceInfo
|
||||
{
|
||||
get => _performanceInfo;
|
||||
set => SetProperty(ref _performanceInfo, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
@ -480,16 +336,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
public ICommand StopAnimationCommand { get; private set; }
|
||||
public ICommand RunCollisionDetectionCommand { get; private set; }
|
||||
public ICommand ViewCollisionReportCommand { get; private set; }
|
||||
public ICommand ModelSplitterCommand { get; private set; }
|
||||
public ICommand SetLogisticsAttributeCommand { get; private set; }
|
||||
public ICommand ViewLogCommand { get; private set; }
|
||||
public ICommand ClearLogCommand { get; private set; }
|
||||
public ICommand ExportLogCommand { get; private set; }
|
||||
public ICommand OpenSettingsCommand { get; private set; }
|
||||
public ICommand ResetSettingsCommand { get; private set; }
|
||||
public ICommand ImportConfigCommand { get; private set; }
|
||||
public ICommand CheckUpdateCommand { get; private set; }
|
||||
public ICommand GeneratePerformanceReportCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@ -520,7 +367,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
LogisticsModels = new ThreadSafeObservableCollection<LogisticsModel>();
|
||||
AvailableCategories = new ThreadSafeObservableCollection<string>();
|
||||
AvailableFrameRates = new ThreadSafeObservableCollection<int>();
|
||||
LogLevels = new ThreadSafeObservableCollection<string>();
|
||||
|
||||
// 初始化命令(使用新的Command Pattern框架)
|
||||
InitializeCommandsAsync();
|
||||
@ -563,8 +409,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 初始化动画参数
|
||||
await InitializeAnimationSettingsAsync();
|
||||
|
||||
// 初始化系统管理设置
|
||||
await InitializeSystemManagementSettingsAsync();
|
||||
|
||||
LogManager.Info("LogisticsControlViewModel 初始化完成");
|
||||
}, "初始化ViewModel");
|
||||
@ -586,17 +430,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
RunCollisionDetectionCommand = new RelayCommand(async () => await ExecuteRunCollisionDetectionAsync(), () => CanRunCollisionDetection);
|
||||
ViewCollisionReportCommand = new RelayCommand(async () => await ExecuteViewCollisionReportAsync(), () => HasCollisionResults);
|
||||
|
||||
// 系统管理命令
|
||||
ModelSplitterCommand = new RelayCommand(async () => await ExecuteModelSplitterAsync());
|
||||
// 物流属性命令
|
||||
SetLogisticsAttributeCommand = new RelayCommand(async () => await ExecuteSetLogisticsAttributeAsync());
|
||||
ViewLogCommand = new RelayCommand(async () => await ExecuteViewLogAsync());
|
||||
ClearLogCommand = new RelayCommand(async () => await ExecuteClearLogAsync());
|
||||
ExportLogCommand = new RelayCommand(async () => await ExecuteExportLogAsync());
|
||||
OpenSettingsCommand = new RelayCommand(async () => await ExecuteOpenSettingsAsync());
|
||||
ResetSettingsCommand = new RelayCommand(async () => await ExecuteResetSettingsAsync());
|
||||
ImportConfigCommand = new RelayCommand(async () => await ExecuteImportConfigAsync());
|
||||
CheckUpdateCommand = new RelayCommand(async () => await ExecuteCheckUpdateAsync());
|
||||
GeneratePerformanceReportCommand = new RelayCommand(async () => await ExecuteGeneratePerformanceReportAsync());
|
||||
|
||||
LogManager.Info("命令初始化完成 - 使用新的异步Command Pattern框架");
|
||||
}, "初始化命令");
|
||||
@ -644,71 +479,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
/// <summary>
|
||||
/// 初始化系统管理设置
|
||||
/// </summary>
|
||||
private async Task InitializeSystemManagementSettingsAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
// 初始化日志级别
|
||||
LogLevels.Clear();
|
||||
var logLevels = new[] { "Debug", "Info", "Warning", "Error" };
|
||||
foreach (var level in logLevels)
|
||||
{
|
||||
LogLevels.Add(level);
|
||||
}
|
||||
SelectedLogLevel = "Info";
|
||||
|
||||
// 初始化系统信息
|
||||
ModelSplitterStatus = "就绪";
|
||||
LogStatus = "日志系统正常";
|
||||
SettingsStatus = "设置已加载";
|
||||
PluginVersion = "v1.0";
|
||||
NavisworksVersion = "2026";
|
||||
SystemStatus = "正常";
|
||||
SystemStatusColor = "Green";
|
||||
});
|
||||
|
||||
// 启动性能监控
|
||||
StartPerformanceMonitoring();
|
||||
|
||||
LogManager.Info("系统管理设置初始化完成");
|
||||
}, "初始化系统管理设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动性能监控
|
||||
/// </summary>
|
||||
private void StartPerformanceMonitoring()
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
// 使用定时器更新性能信息
|
||||
var timer = new System.Windows.Threading.DispatcherTimer();
|
||||
timer.Interval = TimeSpan.FromSeconds(5);
|
||||
timer.Tick += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 更新内存使用
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
var memoryMB = process.WorkingSet64 / (1024 * 1024);
|
||||
MemoryUsage = $"{memoryMB} MB";
|
||||
|
||||
// 更新运行时间
|
||||
var runTime = DateTime.Now - startTime;
|
||||
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
|
||||
|
||||
// 更新性能信息
|
||||
PerformanceInfo = $"CPU: 正常, 内存: {memoryMB}MB, 运行时间: {RunningTime}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"性能监控更新失败: {ex.Message}");
|
||||
}
|
||||
};
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -1057,126 +827,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteViewLog()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现日志查看功能
|
||||
StatusText = "打开日志查看器";
|
||||
LogManager.Info("查看日志");
|
||||
}, "查看日志");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteClearLog()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现日志清空功能
|
||||
LogStatus = "日志已清空";
|
||||
StatusText = "日志已清空";
|
||||
LogManager.Info("清空日志");
|
||||
}, "清空日志");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteExportLog()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现日志导出功能
|
||||
StatusText = "日志导出完成";
|
||||
LogManager.Info("导出日志");
|
||||
}, "导出日志");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteOpenSettings()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现设置对话框
|
||||
StatusText = "打开插件设置";
|
||||
LogManager.Info("打开设置");
|
||||
}, "打开设置");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteResetSettings()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现设置重置功能
|
||||
SettingsStatus = "设置已重置为默认值";
|
||||
IsAutoSaveEnabled = true;
|
||||
IsDebugModeEnabled = false;
|
||||
StatusText = "设置已重置";
|
||||
LogManager.Info("重置设置");
|
||||
}, "重置设置");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteImportConfig()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现配置导入功能
|
||||
StatusText = "配置导入完成";
|
||||
LogManager.Info("导入配置");
|
||||
}, "导入配置");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteCheckUpdate()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
StatusText = "正在检查更新...";
|
||||
|
||||
// 模拟检查更新
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
StatusText = "当前版本已是最新版本";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"更新检查UI更新失败: {ex.Message}");
|
||||
}
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
});
|
||||
|
||||
LogManager.Info("检查更新");
|
||||
}, "检查更新");
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteGeneratePerformanceReport()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
StatusText = "正在生成性能报告...";
|
||||
|
||||
// 模拟生成报告
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
System.Threading.Thread.Sleep(1500);
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
StatusText = "性能报告生成完成";
|
||||
PerformanceInfo = $"报告已生成 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"性能报告UI更新失败: {ex.Message}");
|
||||
}
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
});
|
||||
|
||||
LogManager.Info("生成性能报告");
|
||||
}, "生成性能报告");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步设置物流属性命令(使用UIStateManager和Command Pattern)
|
||||
@ -1267,18 +932,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
#region 其他异步命令实现
|
||||
private async Task ExecuteModelSplitterAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteViewLogAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteClearLogAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteExportLogAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteOpenSettingsAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteResetSettingsAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteImportConfigAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteCheckUpdateAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
private async Task ExecuteGeneratePerformanceReportAsync() { await Task.CompletedTask; /* TODO */ }
|
||||
|
||||
#endregion
|
||||
#region 自动路径规划命令实现
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -310,6 +310,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
AutoPathStatus = "正在创建新路径...";
|
||||
|
||||
// 清除所有现有路径的可视化显示
|
||||
if (PathPointRenderPlugin.Instance != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
PathPointRenderPlugin.Instance.ClearAllPaths();
|
||||
LogManager.Info("新建路径:已清除所有现有路径可视化显示");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"新建路径:清除现有路径可视化失败: {ex.Message}", ex);
|
||||
throw; // 重新抛出异常,让上层处理
|
||||
}
|
||||
}
|
||||
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
var newRoute = _pathPlanningManager.StartCreatingNewRoute();
|
||||
@ -372,32 +387,36 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
var pathName = SelectedPathRoute.Name;
|
||||
AutoPathStatus = $"正在删除路径: {pathName}...";
|
||||
|
||||
// 清理对应的3D可视化标记
|
||||
// 清理当前路径的3D可视化显示(使用新的统一API)
|
||||
if (PathPointRenderPlugin.Instance != null)
|
||||
{
|
||||
if (pathName.StartsWith("自动路径_"))
|
||||
try
|
||||
{
|
||||
// 清除所有自动路径标记
|
||||
var allMarkers = PathPointRenderPlugin.Instance.GetAllMarkers();
|
||||
var autoPathMarkers = allMarkers.Where(m => m.SequenceNumber < -999).ToList();
|
||||
|
||||
foreach (var marker in autoPathMarkers)
|
||||
// 使用路径名找到对应的Core路径,获取其ID进行精确清理
|
||||
string pathIdToRemove = null;
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
PathPointRenderPlugin.Instance.RemoveMarkerAt(marker.Center, 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 对于手动路径,清除对应序号的标记
|
||||
if (SelectedPathRoute.Points.Count > 0)
|
||||
{
|
||||
foreach (var point in SelectedPathRoute.Points)
|
||||
var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Name == pathName);
|
||||
if (coreRoute != null)
|
||||
{
|
||||
var pointLocation = new Point3D(point.X, point.Y, point.Z);
|
||||
PathPointRenderPlugin.Instance.RemoveMarkerAt(pointLocation, 2.0);
|
||||
pathIdToRemove = coreRoute.Id;
|
||||
LogManager.Info($"删除路径:找到Core路径ID: {pathIdToRemove}");
|
||||
|
||||
// 使用新的API精确删除该路径
|
||||
PathPointRenderPlugin.Instance.RemovePath(pathIdToRemove);
|
||||
LogManager.Info($"删除路径:已清除路径 {pathName} (ID: {pathIdToRemove}) 的可视化显示");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"删除路径:未找到路径 {pathName} 对应的Core路径,无法清理可视化");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"删除路径:清除路径可视化失败: {ex.Message}", ex);
|
||||
throw; // 重新抛出异常,让上层处理
|
||||
}
|
||||
}
|
||||
|
||||
// 通知PathPlanningManager删除对应的路径
|
||||
@ -506,6 +525,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
AutoPathStatus = "正在计算最优路径...";
|
||||
LogManager.Info("=== 开始执行自动路径规划 ===");
|
||||
|
||||
// 确保在开始自动路径规划前清理任何残留的事件订阅
|
||||
LogManager.WriteLog("[自动路径规划] 规划前清理事件订阅状态");
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
}
|
||||
|
||||
// 调用PathPlanningManager的自动路径规划功能
|
||||
var startPathPoint = new PathPoint
|
||||
{
|
||||
@ -533,6 +560,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
LogManager.Info($"路径规划成功,共 {pathRoute.Points.Count} 个点");
|
||||
|
||||
// 自动路径规划完成后,执行完整的事件订阅清理
|
||||
LogManager.WriteLog("[自动路径规划] 规划完成后清理事件订阅状态");
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
}
|
||||
|
||||
// 不在这里直接操作UI,让RouteGenerated事件处理UI更新
|
||||
// 这避免了重复的路径添加和UI更新冲突
|
||||
|
||||
@ -543,6 +578,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
AutoPathStatus = "❌ 路径规划失败,未找到可行路径";
|
||||
LogManager.Warning("自动路径规划失败:未找到可行路径");
|
||||
|
||||
// 失败情况下也要清理事件订阅
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
}
|
||||
}
|
||||
}, "自动路径规划");
|
||||
}
|
||||
@ -561,35 +603,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
}
|
||||
|
||||
// 清除3D标记
|
||||
// 清除所有路径可视化(使用新的统一API)
|
||||
if (PathPointRenderPlugin.Instance != null)
|
||||
{
|
||||
if (_hasStartPoint)
|
||||
{
|
||||
PathPointRenderPlugin.Instance.RemoveMarkerAt(_startPoint3D, 2.0);
|
||||
}
|
||||
if (_hasEndPoint)
|
||||
{
|
||||
PathPointRenderPlugin.Instance.RemoveMarkerAt(_endPoint3D, 2.0);
|
||||
}
|
||||
|
||||
// 清除自动路径规划生成的所有中间路径点标记(序号为-1000及以下)
|
||||
try
|
||||
{
|
||||
var allMarkers = PathPointRenderPlugin.Instance.GetAllMarkers();
|
||||
var autoPathMarkers = allMarkers.Where(m => m.SequenceNumber <= -1000).ToList();
|
||||
|
||||
LogManager.Info($"找到 {autoPathMarkers.Count} 个自动路径标记需要清除");
|
||||
|
||||
foreach (var marker in autoPathMarkers)
|
||||
{
|
||||
PathPointRenderPlugin.Instance.RemoveMarkerAt(marker.Center, 1.0);
|
||||
LogManager.Info($"已清除自动路径标记: 序号{marker.SequenceNumber}, 位置({marker.Center.X:F2}, {marker.Center.Y:F2}, {marker.Center.Z:F2})");
|
||||
}
|
||||
PathPointRenderPlugin.Instance.ClearAllPaths();
|
||||
LogManager.Info("重置参数:已清除所有路径可视化显示");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"清除自动路径标记时出现异常: {ex.Message}");
|
||||
LogManager.Error($"重置参数:清除路径可视化失败: {ex.Message}", ex);
|
||||
throw; // 重新抛出异常,让上层处理
|
||||
}
|
||||
}
|
||||
|
||||
@ -777,49 +802,61 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pickResult == null) return;
|
||||
LogManager.WriteLog("[自动路径事件] ===== OnAutoPathMouseClicked被调用 =====");
|
||||
|
||||
if (pickResult == null)
|
||||
{
|
||||
LogManager.WriteLog("[自动路径事件] pickResult为null,退出处理");
|
||||
return;
|
||||
}
|
||||
|
||||
var point3D = pickResult.Point;
|
||||
LogManager.Info($"接收到点击事件: ({point3D.X:F2}, {point3D.Y:F2}, {point3D.Z:F2})");
|
||||
LogManager.WriteLog($"[自动路径事件] 接收到点击事件: ({point3D.X:F2}, {point3D.Y:F2}, {point3D.Z:F2})");
|
||||
LogManager.WriteLog($"[自动路径事件] IsSelectingStartPoint: {IsSelectingStartPoint}, IsSelectingEndPoint: {IsSelectingEndPoint}");
|
||||
|
||||
if (IsSelectingStartPoint)
|
||||
{
|
||||
LogManager.WriteLog("[自动路径事件] 设置起点并停止点击工具");
|
||||
SetAutoPathStartPoint(point3D);
|
||||
await SafeExecuteAsync(() =>
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
_pathPlanningManager?.StopClickTool();
|
||||
}, "停止起点选择工具");
|
||||
}
|
||||
else if (IsSelectingEndPoint)
|
||||
{
|
||||
LogManager.WriteLog("[自动路径事件] 设置终点并停止点击工具");
|
||||
SetAutoPathEndPoint(point3D);
|
||||
await SafeExecuteAsync(() =>
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
_pathPlanningManager?.StopClickTool();
|
||||
}, "停止终点选择工具");
|
||||
}
|
||||
else
|
||||
{
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
LogManager.WriteLog("[自动路径事件] 非选择状态,直接清理事件订阅");
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"处理自动路径规划点击事件时发生错误: {ex.Message}");
|
||||
LogManager.Error($"[自动路径事件] 处理点击事件异常: {ex.Message}");
|
||||
AutoPathStatus = $"获取点击位置失败: {ex.Message}";
|
||||
|
||||
IsSelectingStartPoint = false;
|
||||
IsSelectingEndPoint = false;
|
||||
|
||||
if (_pathPlanningManager != null)
|
||||
// 异常情况下也要清理事件订阅
|
||||
try
|
||||
{
|
||||
await SafeExecuteAsync(() =>
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
}, "清理点击工具状态");
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
_pathPlanningManager?.StopClickTool();
|
||||
}
|
||||
catch (Exception cleanupEx)
|
||||
{
|
||||
LogManager.Error($"[自动路径事件] 清理异常: {cleanupEx.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -920,6 +957,52 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理自动路径相关的事件订阅
|
||||
/// </summary>
|
||||
private void CleanupAutoPathEventSubscriptions()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.WriteLog("[事件清理] 开始清理自动路径事件订阅");
|
||||
|
||||
// 移除所有可能的OnAutoPathMouseClicked订阅
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
|
||||
// 使用反射检查并清理重复订阅
|
||||
var mouseClickedEvent = typeof(PathClickToolPlugin).GetEvent("MouseClicked");
|
||||
if (mouseClickedEvent != null)
|
||||
{
|
||||
var eventField = typeof(PathClickToolPlugin).GetField("MouseClicked",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
if (eventField != null)
|
||||
{
|
||||
var currentDelegate = (MulticastDelegate)eventField.GetValue(null);
|
||||
if (currentDelegate != null)
|
||||
{
|
||||
var invocationList = currentDelegate.GetInvocationList();
|
||||
LogManager.WriteLog($"[事件清理] 发现 {invocationList.Length} 个事件订阅者");
|
||||
|
||||
foreach (var handler in invocationList)
|
||||
{
|
||||
if (handler.Target == this && handler.Method.Name == "OnAutoPathMouseClicked")
|
||||
{
|
||||
PathClickToolPlugin.MouseClicked -= (EventHandler<PickItemResult>)handler;
|
||||
LogManager.WriteLog($"[事件清理] 移除了PathEditingViewModel.OnAutoPathMouseClicked订阅");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.WriteLog("[事件清理] 自动路径事件订阅清理完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[事件清理] 清理自动路径事件订阅失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PathPlanningManager事件处理
|
||||
@ -1318,14 +1401,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 取消事件订阅
|
||||
UnsubscribeFromPathPlanningManager();
|
||||
|
||||
// 清理自动路径规划相关的事件订阅
|
||||
// 完整清理自动路径规划相关的事件订阅
|
||||
try
|
||||
{
|
||||
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
|
||||
CleanupAutoPathEventSubscriptions();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"取消PathClickToolPlugin.MouseClicked事件订阅时发生异常: {ex.Message}");
|
||||
LogManager.Warning($"清理自动路径事件订阅时发生异常: {ex.Message}");
|
||||
}
|
||||
|
||||
// 确保停止任何活动的点击工具
|
||||
try
|
||||
{
|
||||
if (_pathPlanningManager != null)
|
||||
{
|
||||
_pathPlanningManager.StopClickTool();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"停止点击工具时发生异常: {ex.Message}");
|
||||
}
|
||||
|
||||
LogManager.Info("PathEditingViewModel资源清理完成");
|
||||
|
||||
534
src/UI/WPF/ViewModels/SystemManagementViewModel.cs
Normal file
534
src/UI/WPF/ViewModels/SystemManagementViewModel.cs
Normal file
@ -0,0 +1,534 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using NavisworksTransport.UI.WPF.ViewModels;
|
||||
using NavisworksTransport.UI.WPF.Collections;
|
||||
using NavisworksTransport.Core;
|
||||
using NavisworksTransport.Utils;
|
||||
using NavisworksTransport.Commands;
|
||||
|
||||
namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统管理ViewModel - 处理插件系统管理功能
|
||||
/// </summary>
|
||||
public class SystemManagementViewModel : ViewModelBase
|
||||
{
|
||||
#region 私有字段
|
||||
|
||||
private readonly UIStateManager _uiStateManager;
|
||||
|
||||
// 系统管理相关字段
|
||||
private bool _isAutoSaveEnabled = true;
|
||||
private bool _isDebugModeEnabled = false;
|
||||
private ObservableCollection<string> _logLevels;
|
||||
private string _selectedLogLevel = "Info";
|
||||
private string _logStatus = "日志系统正常";
|
||||
private string _pluginVersion = "v1.0";
|
||||
private string _navisworksVersion = "2026";
|
||||
private string _settingsStatus = "设置已加载";
|
||||
private string _systemStatus = "正常";
|
||||
private string _systemStatusColor = "Green";
|
||||
private string _memoryUsage = "0 MB";
|
||||
private string _runningTime = "00:00:00";
|
||||
private string _performanceInfo = "性能监控就绪";
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共属性
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用自动保存
|
||||
/// </summary>
|
||||
public bool IsAutoSaveEnabled
|
||||
{
|
||||
get => _isAutoSaveEnabled;
|
||||
set => SetProperty(ref _isAutoSaveEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用调试模式
|
||||
/// </summary>
|
||||
public bool IsDebugModeEnabled
|
||||
{
|
||||
get => _isDebugModeEnabled;
|
||||
set => SetProperty(ref _isDebugModeEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志级别集合
|
||||
/// </summary>
|
||||
public ObservableCollection<string> LogLevels
|
||||
{
|
||||
get => _logLevels;
|
||||
set => SetProperty(ref _logLevels, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选中的日志级别
|
||||
/// </summary>
|
||||
public string SelectedLogLevel
|
||||
{
|
||||
get => _selectedLogLevel;
|
||||
set => SetProperty(ref _selectedLogLevel, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志状态
|
||||
/// </summary>
|
||||
public string LogStatus
|
||||
{
|
||||
get => _logStatus;
|
||||
set => SetProperty(ref _logStatus, 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 SettingsStatus
|
||||
{
|
||||
get => _settingsStatus;
|
||||
set => SetProperty(ref _settingsStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态
|
||||
/// </summary>
|
||||
public string SystemStatus
|
||||
{
|
||||
get => _systemStatus;
|
||||
set => SetProperty(ref _systemStatus, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态颜色
|
||||
/// </summary>
|
||||
public string SystemStatusColor
|
||||
{
|
||||
get => _systemStatusColor;
|
||||
set => SetProperty(ref _systemStatusColor, 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 性能信息
|
||||
/// </summary>
|
||||
public string PerformanceInfo
|
||||
{
|
||||
get => _performanceInfo;
|
||||
set => SetProperty(ref _performanceInfo, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand ClearLogCommand { get; private set; }
|
||||
public ICommand ExportLogCommand { get; private set; }
|
||||
public ICommand ViewLogCommand { get; private set; }
|
||||
public ICommand OpenSettingsCommand { get; private set; }
|
||||
public ICommand ResetSettingsCommand { get; private set; }
|
||||
public ICommand ImportConfigCommand { get; private set; }
|
||||
public ICommand CheckUpdateCommand { get; private set; }
|
||||
public ICommand GeneratePerformanceReportCommand { get; private set; }
|
||||
|
||||
#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();
|
||||
|
||||
LogManager.Info("SystemManagementViewModel构造函数执行完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
|
||||
|
||||
// 在构造函数中尽量保证对象处于可用状态
|
||||
SystemStatus = "初始化失败,请检查日志";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 初始化
|
||||
|
||||
/// <summary>
|
||||
/// 初始化命令
|
||||
/// </summary>
|
||||
private void InitializeCommands()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 系统管理命令
|
||||
ViewLogCommand = new RelayCommand(() => ExecuteViewLog());
|
||||
ClearLogCommand = new RelayCommand(() => ExecuteClearLog());
|
||||
ExportLogCommand = new RelayCommand(() => ExecuteExportLog());
|
||||
OpenSettingsCommand = new RelayCommand(() => ExecuteOpenSettings());
|
||||
ResetSettingsCommand = new RelayCommand(() => ExecuteResetSettings());
|
||||
ImportConfigCommand = new RelayCommand(() => ExecuteImportConfig());
|
||||
CheckUpdateCommand = new RelayCommand(() => ExecuteCheckUpdate());
|
||||
GeneratePerformanceReportCommand = new RelayCommand(() => ExecuteGeneratePerformanceReport());
|
||||
|
||||
LogManager.Info("系统管理命令初始化完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"初始化命令失败: {ex.Message}", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化系统管理设置
|
||||
/// </summary>
|
||||
private async Task InitializeSystemManagementSettingsAsync()
|
||||
{
|
||||
await SafeExecuteAsync(async () =>
|
||||
{
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
// 初始化日志级别
|
||||
LogLevels.Clear();
|
||||
var logLevels = new[] { "Debug", "Info", "Warning", "Error" };
|
||||
foreach (var level in logLevels)
|
||||
{
|
||||
LogLevels.Add(level);
|
||||
}
|
||||
SelectedLogLevel = "Info";
|
||||
|
||||
// 初始化系统信息
|
||||
LogStatus = "日志系统正常";
|
||||
SettingsStatus = "设置已加载";
|
||||
PluginVersion = "v1.0";
|
||||
NavisworksVersion = "2026";
|
||||
SystemStatus = "正常";
|
||||
SystemStatusColor = "Green";
|
||||
});
|
||||
|
||||
// 启动性能监控
|
||||
StartPerformanceMonitoring();
|
||||
|
||||
LogManager.Info("系统管理设置初始化完成");
|
||||
}, "初始化系统管理设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动性能监控
|
||||
/// </summary>
|
||||
private void StartPerformanceMonitoring()
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
// 使用定时器更新性能信息
|
||||
var timer = new System.Windows.Threading.DispatcherTimer();
|
||||
timer.Interval = TimeSpan.FromSeconds(5);
|
||||
timer.Tick += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 更新内存使用
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
var memoryMB = process.WorkingSet64 / (1024 * 1024);
|
||||
MemoryUsage = $"{memoryMB} MB";
|
||||
|
||||
// 更新运行时间
|
||||
var runTime = DateTime.Now - startTime;
|
||||
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
|
||||
|
||||
// 更新性能信息
|
||||
PerformanceInfo = $"CPU: 正常, 内存: {memoryMB}MB, 运行时间: {RunningTime}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"性能监控更新失败: {ex.Message}");
|
||||
}
|
||||
};
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令实现
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查看日志
|
||||
/// </summary>
|
||||
private void ExecuteViewLog()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现日志查看功能
|
||||
LogStatus = "打开日志查看器";
|
||||
LogManager.Info("查看日志");
|
||||
}, "查看日志");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空日志
|
||||
/// </summary>
|
||||
private void ExecuteClearLog()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现日志清空功能
|
||||
LogStatus = "日志已清空";
|
||||
LogManager.Info("清空日志");
|
||||
}, "清空日志");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出日志
|
||||
/// </summary>
|
||||
private void ExecuteExportLog()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现日志导出功能
|
||||
LogStatus = "日志导出完成";
|
||||
LogManager.Info("导出日志");
|
||||
}, "导出日志");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开设置
|
||||
/// </summary>
|
||||
private void ExecuteOpenSettings()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现设置对话框
|
||||
SettingsStatus = "打开插件设置";
|
||||
LogManager.Info("打开设置");
|
||||
}, "打开设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置设置
|
||||
/// </summary>
|
||||
private void ExecuteResetSettings()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现设置重置功能
|
||||
SettingsStatus = "设置已重置为默认值";
|
||||
IsAutoSaveEnabled = true;
|
||||
IsDebugModeEnabled = false;
|
||||
LogManager.Info("重置设置");
|
||||
}, "重置设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入配置
|
||||
/// </summary>
|
||||
private void ExecuteImportConfig()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
// TODO: 实现配置导入功能
|
||||
SettingsStatus = "配置导入完成";
|
||||
LogManager.Info("导入配置");
|
||||
}, "导入配置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查更新
|
||||
/// </summary>
|
||||
private void ExecuteCheckUpdate()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
SystemStatus = "正在检查更新...";
|
||||
|
||||
// 模拟检查更新
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
SystemStatus = "当前版本已是最新版本";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"更新检查UI更新失败: {ex.Message}");
|
||||
}
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
});
|
||||
|
||||
LogManager.Info("检查更新");
|
||||
}, "检查更新");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成性能报告
|
||||
/// </summary>
|
||||
private void ExecuteGeneratePerformanceReport()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
SystemStatus = "正在生成性能报告...";
|
||||
|
||||
// 模拟生成报告
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
System.Threading.Thread.Sleep(1500);
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
SystemStatus = "性能报告生成完成";
|
||||
PerformanceInfo = $"报告已生成 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"性能报告UI更新失败: {ex.Message}");
|
||||
}
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
});
|
||||
|
||||
LogManager.Info("生成性能报告");
|
||||
}, "生成性能报告");
|
||||
}
|
||||
|
||||
#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);
|
||||
SystemStatus = $"{operationName}失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全执行同步操作
|
||||
/// </summary>
|
||||
private void SafeExecute(Action action, string operationName = "未知操作")
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
|
||||
SystemStatus = $"{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}, " +
|
||||
$"系统状态: {SystemStatus}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 清理资源
|
||||
|
||||
public void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("开始清理SystemManagementViewModel资源");
|
||||
|
||||
// 目前没有需要特别清理的资源
|
||||
|
||||
LogManager.Info("SystemManagementViewModel资源清理完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"SystemManagementViewModel清理失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,56 +1,159 @@
|
||||
<!--
|
||||
NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Navisworks 2026风格
|
||||
|
||||
功能说明:
|
||||
1. 日志管理:查看、清空、导出日志,设置日志级别
|
||||
2. 插件设置:设置选项、重置设置、导入配置、启用选项
|
||||
3. 系统信息:插件版本、Navisworks版本、系统状态、内存使用、运行时间
|
||||
4. 性能监控:性能信息和性能报告生成
|
||||
|
||||
设计原则:与Navisworks 2026风格一致,480像素宽度,现代化UI布局,采用Border分组
|
||||
-->
|
||||
<UserControl x:Class="NavisworksTransport.UI.WPF.Views.SystemManagementView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="400">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="10">
|
||||
<GroupBox Header="模型分层拆分" Margin="0,10" Height="120">
|
||||
<StackPanel Margin="10">
|
||||
<Button Content="模型分层拆分" Command="{Binding ModelSplitterCommand}"
|
||||
Margin="0,0,0,10" HorizontalAlignment="Left"/>
|
||||
<Label Content="将大型模型按楼层或属性拆分为多个文件"
|
||||
Foreground="Gray" FontSize="10"/>
|
||||
<Label Content="{Binding ModelSplitterStatus}" FontSize="10" Foreground="DarkBlue"/>
|
||||
d:DesignHeight="800" d:DesignWidth="480">
|
||||
|
||||
<UserControl.Resources>
|
||||
<!-- Navisworks 2026 风格样式定义 -->
|
||||
<Style x:Key="SectionHeaderStyle" TargetType="Label">
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Foreground" Value="#FF2B579A"/>
|
||||
<Setter Property="Padding" Value="0,5,0,2"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ActionButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="#FF4472C4"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="#FF2B579A"/>
|
||||
<Setter Property="Padding" Value="10,5"/>
|
||||
<Setter Property="Margin" Value="0,0,10,0"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SecondaryButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="#FFE7F1FF"/>
|
||||
<Setter Property="Foreground" Value="#FF2B579A"/>
|
||||
<Setter Property="BorderBrush" Value="#FF4472C4"/>
|
||||
<Setter Property="Padding" Value="8,4"/>
|
||||
<Setter Property="Margin" Value="0,0,8,0"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StatusTextStyle" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
<Setter Property="Foreground" Value="#FF666666"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="InfoTextStyle" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
<Setter Property="Foreground" Value="#FF666666"/>
|
||||
<Setter Property="Padding" Value="0,2"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ParameterLabelStyle" TargetType="Label">
|
||||
<Setter Property="Width" Value="80"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Padding" Value="0,0,5,0"/>
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="StatusLabelStyle" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Foreground" Value="#FF2B579A"/>
|
||||
<Setter Property="Padding" Value="0,2"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="10">
|
||||
<StackPanel>
|
||||
<!-- 区域1: 日志管理 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="4" Margin="0,0,0,15" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="日志管理" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 日志操作按钮 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
|
||||
<Button Content="查看日志"
|
||||
Command="{Binding ViewLogCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"/>
|
||||
<Button Content="清空日志"
|
||||
Command="{Binding ClearLogCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="导出日志"
|
||||
Command="{Binding ExportLogCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 日志级别设置 -->
|
||||
<Grid Margin="0,5,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Grid.Column="0" Content="日志级别:" Style="{StaticResource ParameterLabelStyle}" Width="60"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding LogLevels}"
|
||||
SelectedItem="{Binding SelectedLogLevel}"
|
||||
Width="100"
|
||||
Margin="5,0,0,0"/>
|
||||
</Grid>
|
||||
|
||||
<!-- 状态显示 -->
|
||||
<Label Content="{Binding LogStatus}"
|
||||
Style="{StaticResource StatusLabelStyle}"
|
||||
Foreground="#FF2B8A2B"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</Border>
|
||||
|
||||
<GroupBox Header="日志管理" Margin="0,10" Height="140">
|
||||
<StackPanel Margin="10">
|
||||
<!-- 区域2: 插件设置 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="4" Margin="0,0,0,15" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="插件设置" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 设置操作按钮 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
|
||||
<Button Content="设置选项"
|
||||
Command="{Binding OpenSettingsCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"/>
|
||||
<Button Content="重置设置"
|
||||
Command="{Binding ResetSettingsCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
<Button Content="导入配置"
|
||||
Command="{Binding ImportConfigCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 选项设置 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
|
||||
<Button Content="查看日志" Command="{Binding ViewLogCommand}" Margin="0,0,10,0"/>
|
||||
<Button Content="清空日志" Command="{Binding ClearLogCommand}" Margin="0,0,10,0"/>
|
||||
<Button Content="导出日志" Command="{Binding ExportLogCommand}"/>
|
||||
<CheckBox Content="启用自动保存"
|
||||
IsChecked="{Binding IsAutoSaveEnabled}"
|
||||
Margin="0,0,20,0"
|
||||
VerticalAlignment="Center"/>
|
||||
<CheckBox Content="启用调试模式"
|
||||
IsChecked="{Binding IsDebugModeEnabled}"
|
||||
VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
|
||||
<Label Content="日志级别:" Width="60"/>
|
||||
<ComboBox ItemsSource="{Binding LogLevels}"
|
||||
SelectedItem="{Binding SelectedLogLevel}" Width="100"/>
|
||||
</StackPanel>
|
||||
<Label Content="{Binding LogStatus}" FontSize="10" Foreground="DarkGreen"/>
|
||||
|
||||
<!-- 状态显示 -->
|
||||
<Label Content="{Binding SettingsStatus}"
|
||||
Style="{StaticResource StatusLabelStyle}"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</Border>
|
||||
|
||||
<GroupBox Header="插件设置" Margin="0,10" Height="140">
|
||||
<StackPanel Margin="10">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
|
||||
<Button Content="设置选项" Command="{Binding OpenSettingsCommand}" Margin="0,0,10,0"/>
|
||||
<Button Content="重置设置" Command="{Binding ResetSettingsCommand}" Margin="0,0,10,0"/>
|
||||
<Button Content="导入配置" Command="{Binding ImportConfigCommand}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
|
||||
<CheckBox Content="启用自动保存" IsChecked="{Binding IsAutoSaveEnabled}" Margin="0,0,15,0"/>
|
||||
<CheckBox Content="启用调试模式" IsChecked="{Binding IsDebugModeEnabled}"/>
|
||||
</StackPanel>
|
||||
<Label Content="{Binding SettingsStatus}" FontSize="10" Foreground="DarkBlue"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="系统信息" Margin="0,10" Height="180">
|
||||
<StackPanel Margin="10">
|
||||
<Grid>
|
||||
<!-- 区域3: 系统信息 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="4" Margin="0,0,0,15" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="系统信息" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 系统信息表格 -->
|
||||
<Grid Margin="0,10,0,15">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
@ -63,34 +166,53 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="插件版本:" FontSize="10"/>
|
||||
<Label Grid.Row="0" Grid.Column="1" Content="{Binding PluginVersion}" FontSize="10"/>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="插件版本:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
|
||||
<Label Grid.Row="0" Grid.Column="1" Content="{Binding PluginVersion}" Style="{StaticResource InfoTextStyle}"/>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="Navisworks版本:" FontSize="10"/>
|
||||
<Label Grid.Row="1" Grid.Column="1" Content="{Binding NavisworksVersion}" FontSize="10"/>
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="Navisworks版本:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
|
||||
<Label Grid.Row="1" Grid.Column="1" Content="{Binding NavisworksVersion}" Style="{StaticResource InfoTextStyle}"/>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="系统状态:" FontSize="10"/>
|
||||
<Label Grid.Row="2" Grid.Column="1" Content="{Binding SystemStatus}" FontSize="10"
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="系统状态:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
|
||||
<Label Grid.Row="2" Grid.Column="1" Content="{Binding SystemStatus}"
|
||||
Style="{StaticResource InfoTextStyle}"
|
||||
Foreground="{Binding SystemStatusColor}"/>
|
||||
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="内存使用:" FontSize="10"/>
|
||||
<Label Grid.Row="3" Grid.Column="1" Content="{Binding MemoryUsage}" FontSize="10"/>
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="内存使用:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
|
||||
<Label Grid.Row="3" Grid.Column="1" Content="{Binding MemoryUsage}" Style="{StaticResource InfoTextStyle}"/>
|
||||
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="运行时间:" FontSize="10"/>
|
||||
<Label Grid.Row="4" Grid.Column="1" Content="{Binding RunningTime}" FontSize="10"/>
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="运行时间:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
|
||||
<Label Grid.Row="4" Grid.Column="1" Content="{Binding RunningTime}" Style="{StaticResource InfoTextStyle}"/>
|
||||
</Grid>
|
||||
<Button Content="检查更新" Command="{Binding CheckUpdateCommand}"
|
||||
Margin="0,10,0,0" HorizontalAlignment="Left"/>
|
||||
|
||||
<!-- 更新检查按钮 -->
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="检查更新"
|
||||
Command="{Binding CheckUpdateCommand}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</Border>
|
||||
|
||||
<GroupBox Header="性能监控" Margin="0,10">
|
||||
<StackPanel Margin="10">
|
||||
<Label Content="{Binding PerformanceInfo}" FontSize="10" Foreground="Gray"/>
|
||||
<Button Content="生成性能报告" Command="{Binding GeneratePerformanceReportCommand}"
|
||||
HorizontalAlignment="Left" Margin="0,5,0,0"/>
|
||||
<!-- 区域4: 性能监控 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="4" Margin="0,0,0,0" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="性能监控" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 性能信息显示 -->
|
||||
<TextBlock Text="{Binding PerformanceInfo}"
|
||||
FontSize="10"
|
||||
Foreground="#FF666666"
|
||||
Margin="0,10,0,15"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<!-- 报告生成按钮 -->
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="生成性能报告"
|
||||
Command="{Binding GeneratePerformanceReportCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
Loading…
Reference in New Issue
Block a user