diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md index 71777e0..4d1e9f9 100644 --- a/doc/requirement/todo_features.md +++ b/doc/requirement/todo_features.md @@ -6,7 +6,8 @@ 1. [ ] (优化)将ViewPonit的RenderStyle改成Shaded,以免影响高亮(考虑在显示碰撞时,改成Wireframe) 2、[ ] (优化)修改架构适应模型坐标系的变化(Yup-Xright-Zfront) -3、[ ] (优化)修改吊装路径适应桁车空中路线(纵向+平移,有吊绳) +3、[x] (优化)修改吊装路径适应桁车空中路线(纵向+平移,有吊绳) +4、[x] (优化)对系统配置文件的修改即时起效 ### [2026/1/26] diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index 02e0636..8a5526c 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -212,8 +212,104 @@ namespace NavisworksTransport.Core.Animation // 订阅文档状态事件 DocumentStateManager.Instance.DocumentInvalidated += OnDocumentInvalidated; + + // 订阅配置变更事件 + SubscribeToConfigChanges(); } + #region 配置变更处理 + + /// + /// 订阅配置变更事件 + /// + private void SubscribeToConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged; + LogManager.Info("PathAnimationManager 已订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex); + } + } + + /// + /// 取消订阅配置变更事件 + /// + private void UnsubscribeFromConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged; + LogManager.Info("PathAnimationManager 已取消订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}"); + } + } + + /// + /// 配置变更事件处理 + /// + private void OnCategoryConfigurationChanged(object sender, Tuple args) + { + try + { + var category = args.Item1; + var eventArgs = args.Item2; + + // 处理 Animation 类别变更 + if (category == ConfigCategory.Animation || category == ConfigCategory.All) + { + LogManager.Info("收到 Animation 配置变更通知,正在更新动画参数..."); + + var config = ConfigManager.Instance.Current; + bool needReset = false; + + // 检查帧率是否变更 + if (_animationFrameRate != config.Animation.FrameRate) + { + _animationFrameRate = config.Animation.FrameRate; + _frameInterval = 1000.0 / _animationFrameRate; + + // 更新定时器间隔 + if (_animationTimer != null) + { + _animationTimer.Interval = TimeSpan.FromMilliseconds(_frameInterval); + } + + needReset = true; + LogManager.Info($"动画帧率已更新: {_animationFrameRate} fps, 帧间隔: {_frameInterval:F1} ms"); + } + + // 检查持续时间是否变更 + if (_animationDuration != config.Animation.DurationSeconds) + { + _animationDuration = config.Animation.DurationSeconds; + needReset = true; + LogManager.Info($"动画持续时间已更新: {_animationDuration} 秒"); + } + + // 如果动画正在运行,需要重置 + if (needReset && (_currentState == AnimationState.Playing || _currentState == AnimationState.Paused)) + { + // 停止当前动画,让用户重新生成 + ShutdownAnimation(); + LogManager.Info("动画参数已变更,当前动画已停止,请重新生成动画"); + } + } + } + catch (Exception ex) + { + LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex); + } + } + + #endregion + /// /// 获取单例实例 /// @@ -2370,6 +2466,9 @@ namespace NavisworksTransport.Core.Animation { LogManager.Info("开始清理PathAnimationManager资源"); + // 0. 取消配置变更事件订阅 + UnsubscribeFromConfigChanges(); + // 1. 优先停止动画(最小化的操作,不触发复杂的重置逻辑) // 只有在动画运行时才停止,避免重复调用 try diff --git a/src/Core/Config/ConfigManager.cs b/src/Core/Config/ConfigManager.cs index 88e63ac..48542c7 100644 --- a/src/Core/Config/ConfigManager.cs +++ b/src/Core/Config/ConfigManager.cs @@ -7,11 +7,56 @@ using Tomlyn.Syntax; namespace NavisworksTransport.Core.Config { + /// + /// 配置变更类别 + /// + public enum ConfigCategory + { + None = 0, + PathEditing = 1, + Visualization = 2, + Animation = 3, + Logistics = 4, + CoordinateSystem = 5, + GridGeneration = 6, + PathPlanning = 7, + All = 99 + } + + /// + /// 配置变更事件参数 + /// + public class ConfigurationChangedEventArgs : EventArgs + { + /// + /// 变更的配置类别 + /// + public ConfigCategory ChangedCategory { get; set; } + + /// + /// 是否是外部文件修改触发的变更 + /// + public bool IsExternalChange { get; set; } + + /// + /// 变更时间戳 + /// + public DateTime ChangeTime { get; set; } + + public ConfigurationChangedEventArgs(ConfigCategory category, bool isExternal = false) + { + ChangedCategory = category; + IsExternalChange = isExternal; + ChangeTime = DateTime.Now; + } + } + /// /// 系统配置管理器 /// 负责 TOML 配置文件的读取、保存和管理 + /// 支持配置变更通知机制 /// - public class ConfigManager + public class ConfigManager : IDisposable { private static ConfigManager _instance; private static readonly object _lock = new object(); @@ -37,6 +82,18 @@ namespace NavisworksTransport.Core.Config } } + /// + /// 配置变更事件 + /// 订阅此事件以在配置发生变化时接收通知 + /// + public event EventHandler ConfigurationChanged; + + /// + /// 特定类别配置变更事件 + /// 参数:发送者,(类别,事件参数) + /// + public event EventHandler> CategoryConfigurationChanged; + /// /// 配置文件路径 /// @@ -78,10 +135,124 @@ namespace NavisworksTransport.Core.Config private SystemConfig _currentConfig; private string _cachedTemplateContent; + private FileSystemWatcher _fileWatcher; + private bool _isDisposed; + private bool _isReloading; + private DateTime _lastWriteTime; + private readonly object _reloadLock = new object(); + + /// + /// 是否启用文件监控(自动检测外部配置修改) + /// 默认启用 + /// + public bool EnableFileWatcher { get; set; } = true; + + /// + /// 文件监控防抖时间(毫秒) + /// 防止文件保存时多次触发事件 + /// + public int FileWatcherDebounceMs { get; set; } = 500; private ConfigManager() { _currentConfig = LoadConfigFile(); + InitializeFileWatcher(); + } + + /// + /// 初始化文件监控 + /// + private void InitializeFileWatcher() + { + try + { + if (!EnableFileWatcher) + { + LogManager.Debug("配置文件监控已禁用"); + return; + } + + string configDir = ConfigDirectory; + if (!Directory.Exists(configDir)) + { + Directory.CreateDirectory(configDir); + } + + _fileWatcher = new FileSystemWatcher(configDir, "config.toml") + { + NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size, + EnableRaisingEvents = true + }; + + _fileWatcher.Changed += OnConfigFileChanged; + _fileWatcher.Renamed += OnConfigFileRenamed; + + LogManager.Info($"配置文件监控已启动: {ConfigFilePath}"); + } + catch (Exception ex) + { + LogManager.Error($"初始化配置文件监控失败: {ex.Message}"); + // 不影响主功能,继续运行 + } + } + + /// + /// 配置文件变化处理 + /// + private void OnConfigFileChanged(object sender, FileSystemEventArgs e) + { + if (_isReloading || e.ChangeType != WatcherChangeTypes.Changed) + return; + + lock (_reloadLock) + { + try + { + // 防抖处理:检查文件最后写入时间 + var fileInfo = new FileInfo(e.FullPath); + if ((DateTime.Now - fileInfo.LastWriteTime).TotalMilliseconds > FileWatcherDebounceMs) + { + return; + } + + // 避免重复加载 + if ((DateTime.Now - _lastWriteTime).TotalMilliseconds < FileWatcherDebounceMs) + { + return; + } + + _isReloading = true; + _lastWriteTime = DateTime.Now; + + LogManager.Info("检测到配置文件外部修改,正在重新加载..."); + + // 延迟一点执行,确保文件写入完成 + System.Threading.Thread.Sleep(100); + + // 重新加载配置 + ReloadInternal(isExternal: true); + } + catch (Exception ex) + { + LogManager.Error($"处理配置文件变更失败: {ex.Message}"); + } + finally + { + _isReloading = false; + } + } + } + + /// + /// 配置文件重命名处理 + /// + private void OnConfigFileRenamed(object sender, RenamedEventArgs e) + { + if (e.Name == "config.toml") + { + LogManager.Info("配置文件被重命名/恢复,正在重新加载..."); + ReloadInternal(isExternal: true); + } } /// @@ -259,6 +430,16 @@ namespace NavisworksTransport.Core.Config /// 保存配置到文件 /// public void SaveConfig(SystemConfig config) + { + SaveConfig(config, notifyChange: true); + } + + /// + /// 保存配置到文件 + /// + /// 配置对象 + /// 是否触发配置变更事件 + public void SaveConfig(SystemConfig config, bool notifyChange) { try { @@ -270,6 +451,12 @@ namespace NavisworksTransport.Core.Config _currentConfig = config; LogManager.Info($"配置文件已保存: {ConfigFilePath}"); + + // 触发配置变更事件 + if (notifyChange) + { + NotifyConfigurationChanged(ConfigCategory.All, isExternal: false); + } } catch (Exception ex) { @@ -397,7 +584,28 @@ namespace NavisworksTransport.Core.Config /// public void Reload() { - _currentConfig = LoadConfigFile(); + ReloadInternal(isExternal: false); + } + + /// + /// 内部重新加载方法 + /// + /// 是否是外部修改触发的重载 + private void ReloadInternal(bool isExternal) + { + try + { + _currentConfig = LoadConfigFile(); + LogManager.Info($"配置文件已重新加载{(isExternal ? "(外部修改)" : "")}"); + + // 触发配置变更事件 + NotifyConfigurationChanged(ConfigCategory.All, isExternal); + } + catch (Exception ex) + { + LogManager.Error($"重新加载配置文件失败: {ex.Message}"); + throw; + } } /// @@ -418,6 +626,73 @@ namespace NavisworksTransport.Core.Config _currentConfig = newConfig; LogManager.Info("默认配置恢复完成"); + + // 触发配置变更事件 + NotifyConfigurationChanged(ConfigCategory.All, isExternal: false); + } + + /// + /// 触发配置变更事件 + /// + /// 变更的配置类别 + /// 是否是外部修改 + public void NotifyConfigurationChanged(ConfigCategory category, bool isExternal = false) + { + var args = new ConfigurationChangedEventArgs(category, isExternal); + + try + { + // 触发总事件 + ConfigurationChanged?.Invoke(this, args); + + // 触发分类事件 + CategoryConfigurationChanged?.Invoke(this, + new Tuple(category, args)); + + // 如果是 All,触发各个分类事件 + if (category == ConfigCategory.All) + { + for (int i = 1; i <= 7; i++) + { + CategoryConfigurationChanged?.Invoke(this, + new Tuple((ConfigCategory)i, args)); + } + } + + LogManager.Debug($"配置变更事件已触发: {category}"); + } + catch (Exception ex) + { + LogManager.Error($"触发配置变更事件失败: {ex.Message}"); + } + } + + /// + /// 更新特定类别的配置并触发事件 + /// + /// 配置类别 + /// 更新操作 + public void UpdateCategoryConfig(ConfigCategory category, Action updateAction) + { + if (updateAction == null) + throw new ArgumentNullException(nameof(updateAction)); + + updateAction(_currentConfig); + SaveConfig(_currentConfig, notifyChange: false); + NotifyConfigurationChanged(category, isExternal: false); + } + + /// + /// 资源释放 + /// + public void Dispose() + { + if (!_isDisposed) + { + _fileWatcher?.Dispose(); + _isDisposed = true; + LogManager.Info("ConfigManager 已释放"); + } } // 辅助方法:从 TomlTable 获取必需值 diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs index 24331ea..ee3129c 100644 --- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs +++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs @@ -9,6 +9,7 @@ using Autodesk.Navisworks.Api; using Autodesk.Navisworks.Api.Clash; using NavisworksTransport.Core; using NavisworksTransport.Core.Models; +using NavisworksTransport.Core.Config; using NavisworksTransport.Commands; using NavisworksTransport.UI.WPF.Collections; using NavisworksTransport.Utils; @@ -939,7 +940,95 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 设置动画按钮的初始状态 UpdateAnimationButtonStates(); - LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 安全间隙:{_safetyMargin}米"); } + LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 安全间隙:{_safetyMargin}米"); + + // 订阅配置变更事件 + SubscribeToConfigChanges(); + } + + #region 配置变更处理 + + /// + /// 订阅配置变更事件 + /// + private void SubscribeToConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged; + LogManager.Info("AnimationControlViewModel 已订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex); + } + } + + /// + /// 取消订阅配置变更事件 + /// + private void UnsubscribeFromConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged; + LogManager.Info("AnimationControlViewModel 已取消订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}"); + } + } + + /// + /// 配置变更事件处理 + /// + private void OnCategoryConfigurationChanged(object sender, Tuple args) + { + try + { + var category = args.Item1; + var eventArgs = args.Item2; + + // 处理 Animation 类别变更 + if (category == ConfigCategory.Animation || category == ConfigCategory.All) + { + LogManager.Info("收到 Animation 配置变更通知,正在更新参数..."); + + var config = ConfigManager.Instance.Current; + + // 更新动画参数 + SelectedFrameRate = config.Animation.FrameRate; + AnimationDuration = config.Animation.DurationSeconds; + AnimationFrameRate = config.Animation.FrameRate; + _detectionTolerance = config.Animation.DetectionToleranceMeters; + + LogManager.Info($"Animation 配置已更新 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒"); + } + + // 处理 PathEditing 类别变更(车辆参数和安全间隙) + if (category == ConfigCategory.PathEditing || category == ConfigCategory.All) + { + LogManager.Info("收到 PathEditing 配置变更通知,正在更新车辆参数..."); + + var config = ConfigManager.Instance.Current; + + // 更新车辆参数 + VirtualVehicleLength = config.PathEditing.VehicleLengthMeters; + VirtualVehicleWidth = config.PathEditing.VehicleWidthMeters; + VirtualVehicleHeight = config.PathEditing.VehicleHeightMeters; + _safetyMargin = config.PathEditing.SafetyMarginMeters; + + LogManager.Info($"车辆参数已更新 - 尺寸:{VirtualVehicleLength:F1}x{VirtualVehicleWidth:F1}x{VirtualVehicleHeight:F1}米, 安全间隙:{_safetyMargin:F2}米"); + } + } + catch (Exception ex) + { + LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex); + } + } + + #endregion /// /// 初始化命令 @@ -3351,6 +3440,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 1. 取消事件订阅(在停止动画之前,避免事件处理中访问已释放的对象) + // 取消配置变更事件订阅 + UnsubscribeFromConfigChanges(); + // 取消DocumentStateManager事件订阅 try { diff --git a/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs b/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs index 761133f..7e66079 100644 --- a/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs +++ b/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs @@ -392,6 +392,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 初始化命令 InitializeCommands(); + // 订阅配置变更事件 + SubscribeToConfigChanges(); + // 订阅Navisworks选择变化事件 - 使用新的选择管理服务 SubscribeToSelectionEvents(); @@ -414,6 +417,84 @@ namespace NavisworksTransport.UI.WPF.ViewModels #endregion + #region 配置变更处理 + + /// + /// 订阅配置变更事件 + /// + private void SubscribeToConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged; + LogManager.Info("ModelSettingsViewModel 已订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex); + } + } + + /// + /// 取消订阅配置变更事件 + /// + private void UnsubscribeFromConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged; + LogManager.Info("ModelSettingsViewModel 已取消订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}"); + } + } + + /// + /// 配置变更事件处理 + /// + private void OnCategoryConfigurationChanged(object sender, Tuple args) + { + try + { + var category = args.Item1; + var eventArgs = args.Item2; + + // 处理 Logistics 类别变更 + if (category == ConfigCategory.Logistics || category == ConfigCategory.All) + { + LogManager.Info("收到 Logistics 配置变更通知,正在更新默认属性值..."); + + var config = ConfigManager.Instance.Current; + + // 更新默认属性值(仅当用户未选择模型时) + SafeExecute(() => + { + // 如果当前没有选择模型,更新默认值 + if (!HasSelectedModels) + { + IsTraversable = config.Logistics.Traversable; + Priority = config.Logistics.Priority; + WidthLimit = config.Logistics.WidthLimitMeters; + HeightLimit = config.Logistics.HeightLimitMeters; + SpeedLimit = config.Logistics.SpeedLimitMetersPerSecond; + + string source = eventArgs.IsExternalChange ? "外部修改" : "内部更新"; + UpdateMainStatus($"默认属性已更新 ({source})"); + LogManager.Info($"默认物流属性已更新 - 来源: {source}"); + } + }); + } + } + catch (Exception ex) + { + LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex); + } + } + + #endregion + #region 命令初始化 - 统一的Command Pattern /// @@ -1368,6 +1449,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 取消文档模型集合事件订阅 UnsubscribeFromDocumentModelsEvents(); + // 取消配置变更事件订阅 + UnsubscribeFromConfigChanges(); + LogManager.Info("[ModelSettingsViewModel] 资源清理完成"); } catch (Exception ex) diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index 46608e1..6eb4a6f 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -735,6 +735,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 从配置加载参数 LoadParametersFromConfig(); + // 订阅配置变更事件 + SubscribeToConfigChanges(); + // 初始化命令 InitializeCommands(); @@ -815,6 +818,86 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } + #region 配置变更处理 + + /// + /// 订阅配置变更事件 + /// + private void SubscribeToConfigChanges() + { + try + { + // 订阅特定类别的配置变更事件 + ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged; + LogManager.Info("PathEditingViewModel 已订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex); + } + } + + /// + /// 取消订阅配置变更事件 + /// + private void UnsubscribeFromConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged; + LogManager.Info("PathEditingViewModel 已取消订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}"); + } + } + + /// + /// 配置变更事件处理 + /// + private void OnCategoryConfigurationChanged(object sender, Tuple args) + { + try + { + var category = args.Item1; + var eventArgs = args.Item2; + + // 只处理 PathEditing 相关的配置变更 + if (category == ConfigCategory.PathEditing || category == ConfigCategory.All) + { + LogManager.Info($"收到 PathEditing 配置变更通知,正在更新参数..."); + + // 从配置重新加载参数 + LoadParametersFromConfig(); + + // 触发属性变更通知,更新UI + OnPropertiesChanged( + nameof(VehicleLength), + nameof(VehicleWidth), + nameof(VehicleHeight), + nameof(SafetyMargin), + nameof(GridSize) + ); + + // 同步车辆参数到渲染插件 + SyncVehicleParametersToRenderPlugin(); + + // 更新状态栏 + string source = eventArgs.IsExternalChange ? "外部修改" : "内部更新"; + UpdateMainStatus($"配置已更新 ({source}) - 车辆参数: {VehicleLength:F1}x{VehicleWidth:F1}x{VehicleHeight:F1}米"); + + LogManager.Info($"PathEditing 配置参数已更新完成 - 来源: {source}"); + } + } + catch (Exception ex) + { + LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex); + } + } + + #endregion + private void InitializeCommands() { NewPathCommand = new RelayCommand(async () => await ExecuteNewPathAsync(), () => CanExecuteNewPath); @@ -3564,6 +3647,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels { LogManager.Info("开始清理PathEditingViewModel资源"); + // 取消配置变更事件订阅 + UnsubscribeFromConfigChanges(); + // 取消事件订阅 UnsubscribeFromPathPlanningManager(); diff --git a/src/UI/WPF/ViewModels/TimeTagViewModel.cs b/src/UI/WPF/ViewModels/TimeTagViewModel.cs index cc2f805..99a6057 100644 --- a/src/UI/WPF/ViewModels/TimeTagViewModel.cs +++ b/src/UI/WPF/ViewModels/TimeTagViewModel.cs @@ -134,6 +134,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels InitializeCollections(); LoadRouteData(_pathPlanningManager.CurrentRoute); + // 订阅配置变更事件 + SubscribeToConfigChanges(); + LogManager.Info($"TimeTagViewModel初始化完成 - 默认速度: {_defaultSpeed:F1}m/s(来自配置)"); } catch (Exception ex) @@ -142,6 +145,75 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } + #region 配置变更处理 + + /// + /// 订阅配置变更事件 + /// + private void SubscribeToConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged; + LogManager.Info("TimeTagViewModel 已订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex); + } + } + + /// + /// 取消订阅配置变更事件 + /// + private void UnsubscribeFromConfigChanges() + { + try + { + ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged; + LogManager.Info("TimeTagViewModel 已取消订阅配置变更事件"); + } + catch (Exception ex) + { + LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}"); + } + } + + /// + /// 配置变更事件处理 + /// + private void OnCategoryConfigurationChanged(object sender, Tuple args) + { + try + { + var category = args.Item1; + var eventArgs = args.Item2; + + // 处理 Logistics 类别变更(默认速度) + if (category == ConfigCategory.Logistics || category == ConfigCategory.All) + { + LogManager.Info("收到 Logistics 配置变更通知,正在更新默认速度..."); + + var config = ConfigManager.Instance.Current; + double newSpeed = config.Logistics.SpeedLimitMetersPerSecond; + + // 更新默认速度 + if (_defaultSpeed != newSpeed) + { + _defaultSpeed = newSpeed; + DefaultSpeed = newSpeed; // 触发属性变更通知 + LogManager.Info($"默认速度已更新: {newSpeed:F1} m/s"); + } + } + } + catch (Exception ex) + { + LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex); + } + } + + #endregion + #endregion #region 初始化方法 @@ -438,6 +510,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels } #endregion + + #region 资源清理 + + /// + /// 释放资源 + /// + public void Dispose() + { + UnsubscribeFromConfigChanges(); + } + + #endregion } #region 数据模型