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 数据模型