将路径、动画、系统的消息也迁移到状态栏

This commit is contained in:
tian 2025-09-07 22:46:20 +08:00
parent 3341ef82b7
commit 83aad61147
10 changed files with 652 additions and 398 deletions

View File

@ -33,7 +33,7 @@ namespace NavisworksTransport.UI.WPF
// 创建并设置ViewModel
ViewModel = new LogisticsControlViewModel();
SystemManagementViewModel = new SystemManagementViewModel();
SystemManagementViewModel = new SystemManagementViewModel(ViewModel); // 传递主ViewModel引用
DataContext = ViewModel;
// 为SystemManagementView设置独立的DataContext
@ -155,10 +155,22 @@ namespace NavisworksTransport.UI.WPF
{
try
{
// 重新创建AnimationControlView传入主ViewModel引用
var newAnimationControlView = new AnimationControlView(ViewModel);
// 替换XAML中的AnimationControlView
if (AnimationControlTab?.Content is Border animationControlBorder)
{
animationControlBorder.Child = newAnimationControlView;
// 更新引用
AnimationControlView = newAnimationControlView;
}
if (AnimationControlView?.ViewModel != null)
{
// 动画控制视图现在通过PathEditingView获取路径信息
LogManager.Info("AnimationControlView初始化完成");
LogManager.Info("AnimationControlView初始化完成 - 支持统一状态栏");
}
}
catch (Exception ex)
@ -174,12 +186,24 @@ namespace NavisworksTransport.UI.WPF
{
try
{
// 重新创建PathEditingView传入主ViewModel引用
var newPathEditingView = new PathEditingView(ViewModel);
// 替换XAML中的PathEditingView
if (PathEditingTab?.Content is Border pathEditingBorder)
{
pathEditingBorder.Child = newPathEditingView;
// 更新引用
PathEditingView = newPathEditingView;
}
if (PathEditingView?.ViewModel != null)
{
// 将PathPlanningManager传递给PathEditingView
PathEditingView.ViewModel.PathPlanningManager = _pathPlanningManager;
LogManager.Info("PathEditingView初始化完成");
LogManager.Info("PathEditingView初始化完成 - 支持统一状态栏");
}
}
catch (Exception ex)

View File

@ -72,6 +72,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private readonly NavisworksTransport.Core.Animation.LogisticsAnimationManager _logisticsAnimationManager;
private readonly ClashDetectiveIntegration _clashIntegration;
private readonly UIStateManager _uiStateManager;
private readonly LogisticsControlViewModel _mainViewModel;
// 动画参数相关字段
private ObservableCollection<int> _availableFrameRates;
@ -81,14 +82,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private bool _canStartAnimation = true;
private bool _canPauseAnimation = false;
private bool _canStopAnimation = false;
private string _animationStatus = "就绪";
private double _animationProgress = 0.0;
private string _startAnimationButtonText = "开始动画";
// 碰撞检测相关字段
private bool _hasCollisionResults = false;
private string _collisionStatus = "就绪";
private string _collisionSummary = "尚未运行碰撞检测";
// 碰撞检测参数字段
private double _collisionDetectionAccuracy = 0.1; // 检测精度(米)
@ -110,7 +108,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private string _selectedAnimatedObjectName = "未选择移动物体";
private bool _hasSelectedAnimatedObject = false;
private bool _canGenerateAnimation = false;
private string _generationStatus = "就绪";
#endregion
@ -182,14 +179,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _canStopAnimation, value);
}
/// <summary>
/// 动画状态
/// </summary>
public string AnimationStatus
{
get => _animationStatus;
set => SetProperty(ref _animationStatus, value);
}
/// <summary>
/// 动画进度
@ -219,23 +208,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _hasCollisionResults, value);
}
/// <summary>
/// 碰撞检测状态
/// </summary>
public string CollisionStatus
{
get => _collisionStatus;
set => SetProperty(ref _collisionStatus, value);
}
/// <summary>
/// 碰撞检测摘要
/// </summary>
public string CollisionSummary
{
get => _collisionSummary;
set => SetProperty(ref _collisionSummary, value);
}
/// <summary>
/// 碰撞检测精度(米)
@ -339,6 +312,22 @@ namespace NavisworksTransport.UI.WPF.ViewModels
UpdateAnimatedObjectInfo();
UpdateCanGenerateAnimation();
// 移动物体改变时清除已生成的动画(如果有的话)
if (_pathAnimationManager != null &&
(_pathAnimationManager.CurrentState == NavisworksTransport.Core.Animation.AnimationState.Ready ||
_pathAnimationManager.CurrentState == NavisworksTransport.Core.Animation.AnimationState.Finished))
{
try
{
_pathAnimationManager.StopAnimation(); // 这会将状态设置为Stopped需要重新生成动画
LogManager.Info("移动物体更改,已清除之前生成的动画");
}
catch (Exception ex)
{
LogManager.Warning($"清除之前动画时出现警告: {ex.Message}");
}
}
// ✨ 新功能:动画对象选择时预计算排除列表(线程安全版本)
_ = PrecomputeCollisionExclusionsAsync(value);
}
@ -371,14 +360,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _canGenerateAnimation, value);
}
/// <summary>
/// 生成状态
/// </summary>
public string GenerationStatus
{
get => _generationStatus;
set => SetProperty(ref _generationStatus, value);
}
#endregion
@ -434,6 +415,52 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 带主ViewModel参数的构造函数支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public AnimationControlViewModel(LogisticsControlViewModel mainViewModel) : base()
{
try
{
// 保存主ViewModel引用
_mainViewModel = mainViewModel;
// 初始化管理器
_pathAnimationManager = new NavisworksTransport.Core.Animation.PathAnimationManager();
_logisticsAnimationManager = new NavisworksTransport.Core.Animation.LogisticsAnimationManager();
_clashIntegration = ClashDetectiveIntegration.Instance;
_uiStateManager = UIStateManager.Instance;
// 订阅PathAnimationManager事件
_pathAnimationManager.ProgressChanged += OnAnimationProgressChanged;
_pathAnimationManager.StateChanged += OnAnimationStateChanged;
// 初始化集合
AvailableFrameRates = new ThreadSafeObservableCollection<int>();
// 初始化设置
InitializeAnimationSettings();
// 初始化命令
InitializeCommands();
// 初始化碰撞检测集成
InitializeClashIntegration();
// 初始化防抖定时器
InitializeParameterUpdateTimer();
LogManager.Info("AnimationControlViewModel初始化完成 - 支持统一状态栏");
}
catch (Exception ex)
{
LogManager.Error($"AnimationControlViewModel初始化失败: {ex.Message}", ex);
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
#endregion
#region
@ -464,8 +491,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化碰撞检测状态
HasCollisionResults = false;
CollisionStatus = "就绪";
CollisionSummary = "尚未运行碰撞检测";
UpdateMainStatus("碰撞检测就绪");
// 初始化碰撞检测参数
CollisionDetectionAccuracy = 0.1; // 0.1米
@ -529,7 +555,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "请先选择包含至少2个点的路径";
UpdateMainStatus("请先选择包含至少2个点的路径");
});
return;
}
@ -549,7 +575,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Warning("动画已在播放中");
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "动画已在播放中";
UpdateMainStatus("动画已在播放中");
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = false;
@ -577,7 +603,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = $"开始动画出错: {ex.Message}";
UpdateMainStatus($"开始动画出错: {ex.Message}");
LogManager.Error($"开始动画异常: {ex.Message}", ex);
// 恢复按钮状态
@ -608,7 +634,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 错误时手动恢复UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "暂停动画失败";
UpdateMainStatus("暂停动画失败");
});
}
}
@ -622,7 +648,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "动画状态: 已停止";
UpdateMainStatus("动画已停止");
AnimationProgress = 0;
CurrentAnimationTime = 0.0;
@ -652,7 +678,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "尚无碰撞检测结果可查看";
UpdateMainStatus("尚无碰撞检测结果可查看");
});
return;
}
@ -661,7 +687,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "正在生成碰撞报告...";
UpdateMainStatus("正在生成碰撞报告...", -1, true);
});
LogManager.Info("开始生成碰撞检测详细报告");
@ -687,7 +713,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "碰撞报告已生成";
UpdateMainStatus("碰撞报告已生成");
LogManager.Info("碰撞报告生成完成并已显示");
});
}
@ -695,7 +721,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "生成碰撞报告失败";
UpdateMainStatus("生成碰撞报告失败");
});
}
}
@ -703,7 +729,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "查看碰撞报告出错";
UpdateMainStatus("查看碰撞报告出错");
});
LogManager.Error($"查看碰撞报告异常: {ex.Message}", ex);
}
@ -720,21 +746,37 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
CurrentPathRoute = pathRoute;
// 路径改变时清除已生成的动画(如果有的话)
if (_pathAnimationManager != null &&
(_pathAnimationManager.CurrentState == NavisworksTransport.Core.Animation.AnimationState.Ready ||
_pathAnimationManager.CurrentState == NavisworksTransport.Core.Animation.AnimationState.Finished))
{
try
{
_pathAnimationManager.StopAnimation(); // 这会将状态设置为Stopped需要重新生成动画
LogManager.Info("路径更改,已清除之前生成的动画");
}
catch (Exception ex)
{
LogManager.Warning($"清除之前动画时出现警告: {ex.Message}");
}
}
// 使用新的统一按钮状态更新方法
UpdateAnimationButtonStates();
// 更新碰撞状态
if (pathRoute == null)
{
CollisionStatus = "请选择路径";
UpdateMainStatus("请选择路径");
}
else if (pathRoute.Points.Count < 2)
{
CollisionStatus = "路径点数不足";
UpdateMainStatus("路径点数不足");
}
else
{
CollisionStatus = "就绪";
UpdateMainStatus("碰撞检测就绪");
}
LogManager.Info($"AnimationControlViewModel当前路径更新: {pathRoute?.Name ?? ""}, 点数: {pathRoute?.Points.Count ?? 0}");
@ -771,21 +813,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
CanPauseAnimation = true;
CanStopAnimation = true;
StartAnimationButtonText = "开始动画"; // 播放中时按钮显示为灰色的"开始动画"
AnimationStatus = "动画状态: 播放中";
UpdateMainStatus("动画播放中");
break;
case NavisworksTransport.Core.Animation.AnimationState.Paused:
CanStartAnimation = true; // 暂停状态下可以继续
CanPauseAnimation = false;
CanStopAnimation = true;
StartAnimationButtonText = "继续播放"; // 暂停状态下显示"继续播放"
AnimationStatus = "动画状态: 已暂停";
UpdateMainStatus("动画已暂停");
break;
case NavisworksTransport.Core.Animation.AnimationState.Finished:
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = false;
StartAnimationButtonText = "开始动画"; // 完成后恢复"开始动画"
AnimationStatus = "动画状态: 已完成";
UpdateMainStatus("动画已完成");
// 动画完成后更新碰撞检测状态
UpdateCollisionStatusAfterAnimation();
break;
@ -794,11 +836,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
CanPauseAnimation = false;
CanStopAnimation = false;
StartAnimationButtonText = "开始动画"; // 停止后恢复"开始动画"
AnimationStatus = "动画状态: 已停止";
UpdateMainStatus("动画已停止");
break;
default:
StartAnimationButtonText = "开始动画";
AnimationStatus = $"动画状态: {state}";
UpdateMainStatus($"动画状态: {state}");
break;
}
}));
@ -813,9 +855,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
HasCollisionResults = e.Results.Count > 0;
CollisionSummary = e.Results.Count > 0
var summary = e.Results.Count > 0
? $"发现 {e.Results.Count} 个碰撞点"
: "未发现碰撞";
UpdateMainStatus(summary);
});
}
@ -834,14 +877,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (selectedItems.Count == 0)
{
GenerationStatus = "请先在Navisworks中选择一个物体";
UpdateMainStatus("请先在Navisworks中选择一个物体");
LogManager.Warning("用户未选择任何物体");
return;
}
if (selectedItems.Count > 1)
{
GenerationStatus = "请只选择一个物体作为移动对象";
UpdateMainStatus("请只选择一个物体作为移动对象");
LogManager.Warning($"用户选择了{selectedItems.Count}个物体,需要只选择一个");
return;
}
@ -853,7 +896,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (!hasAnyGeometry)
{
GenerationStatus = "选中的项目及其子项都不包含几何体,请选择其他物体";
UpdateMainStatus("选中的项目及其子项都不包含几何体,请选择其他物体");
LogManager.Warning("选中的项目及其子项都不包含几何体");
return;
}
@ -862,13 +905,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置选中的移动物体
SelectedAnimatedObject = selectedItem;
GenerationStatus = "移动物体选择成功";
UpdateMainStatus("移动物体选择成功");
LogManager.Info($"移动物体选择成功: {SelectedAnimatedObject.DisplayName}");
}
catch (Exception ex)
{
GenerationStatus = "选择移动物体失败";
UpdateMainStatus("选择移动物体失败");
LogManager.Error($"选择移动物体时发生错误: {ex.Message}");
}
}
@ -897,6 +940,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
// 清除PathAnimationManager中的动画数据将状态重置为Idle
if (_pathAnimationManager != null)
{
try
{
// 重置动画对象到原始位置并清除动画数据
_pathAnimationManager.ResetAnimation();
LogManager.Info("已清除PathAnimationManager中的动画数据");
}
catch (Exception resetEx)
{
LogManager.Warning($"重置PathAnimationManager时出现警告: {resetEx.Message}");
}
}
// 如果有选中的物体,则恢复到原始位置
if (SelectedAnimatedObject != null)
{
@ -910,18 +968,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
doc.Models.ResetPermanentTransform(modelItems);
LogManager.Info($"物体 '{SelectedAnimatedObject.DisplayName}' 已成功恢复到原始位置");
GenerationStatus = "已清除移动物体选择并恢复到原始位置";
UpdateMainStatus("已清除移动物体选择并恢复到原始位置");
}
catch (Exception restoreEx)
{
LogManager.Error($"恢复物体到原始位置时发生错误: {restoreEx.Message}");
GenerationStatus = $"已清除物体选择,但恢复位置失败: {restoreEx.Message}";
UpdateMainStatus($"已清除物体选择,但恢复位置失败: {restoreEx.Message}");
}
}
else
{
LogManager.Info("没有选中的物体需要清除");
GenerationStatus = "已清除移动物体选择";
UpdateMainStatus("已清除移动物体选择");
}
// 清理选择状态
@ -933,8 +991,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 清理碰撞检测结果
HasCollisionResults = false;
CollisionStatus = "就绪";
CollisionSummary = "尚未运行碰撞检测";
UpdateMainStatus("碰撞检测重置");
// 更新按钮状态 - 清除动画后应该重新评估按钮状态
UpdateAnimationButtonStates();
@ -947,7 +1004,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"清除移动物体选择时发生错误: {ex.Message}");
GenerationStatus = $"清除失败: {ex.Message}";
UpdateMainStatus($"清除失败: {ex.Message}");
}
}
@ -970,7 +1027,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 在UI线程中更新开始状态
await System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
GenerationStatus = "正在分析动画对象...";
UpdateMainStatus("正在分析动画对象...", -1, true);
}));
// 在UI线程中执行Navisworks API操作线程安全
@ -991,12 +1048,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (success)
{
var cacheStats = _logisticsAnimationManager.GetCacheStats();
GenerationStatus = $"动画对象分析完成";
UpdateMainStatus("动画对象分析完成");
LogManager.Info($"[缓存预计算] 预计算成功 - {cacheStats}");
}
else
{
GenerationStatus = "动画对象分析失败,将使用实时计算";
UpdateMainStatus("动画对象分析失败,将使用实时计算");
LogManager.Warning("[缓存预计算] 预计算失败,碰撞检测将使用实时计算模式");
}
}));
@ -1006,7 +1063,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Error($"[缓存预计算] 异步预计算过程异常: {ex.Message}", ex);
await System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
GenerationStatus = "动画对象分析异常";
UpdateMainStatus("动画对象分析异常");
}));
}
}
@ -1020,16 +1077,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (!CanGenerateAnimation)
{
GenerationStatus = "无法生成动画:缺少必要条件";
UpdateMainStatus("无法生成动画:缺少必要条件");
LogManager.Warning("尝试生成动画但条件不满足");
return;
}
GenerationStatus = "正在生成动画...";
UpdateMainStatus("正在生成动画...", -1, true);
LogManager.Info("开始生成动画");
// 🔥 新增:在生成动画阶段构建碰撞检测缓存
GenerationStatus = "正在构建碰撞检测缓存...";
UpdateMainStatus("正在构建碰撞检测缓存...", -1, true);
LogManager.Info("[动画生成] 开始构建碰撞检测缓存");
var cacheStartTime = DateTime.Now;
@ -1038,10 +1095,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 构建全局缓存(与具体移动物体无关)
ClashDetectiveIntegration.ClearAllCaches();
GenerationStatus = "正在缓存几何对象列表...";
UpdateMainStatus("正在缓存几何对象列表...", -1, true);
ClashDetectiveIntegration.BuildAllGeometryItemsCache();
GenerationStatus = "正在缓存通道对象...";
UpdateMainStatus("正在缓存通道对象...", -1, true);
var clashIntegration = ClashDetectiveIntegration.Instance;
clashIntegration.BuildChannelObjectsCache();
@ -1049,7 +1106,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"[动画生成] 碰撞检测缓存构建完成,耗时: {cacheElapsed:F1}ms");
// 构建特定于动画对象的缓存
GenerationStatus = "正在分析动画对象...";
UpdateMainStatus("正在分析动画对象...", -1, true);
var success = _logisticsAnimationManager.PrecomputeCollisionExclusions(SelectedAnimatedObject);
if (!success)
@ -1063,17 +1120,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
// 原有的动画生成逻辑
GenerationStatus = "正在生成路径动画...";
UpdateMainStatus("正在生成路径动画...", -1, true);
// 将PathRouteViewModel的点转换为Point3D列表
var pathPoints = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
// 使用PathAnimationManager设置物体动画(真正的物体移动动画
_pathAnimationManager.SetupAnimation(SelectedAnimatedObject, pathPoints, AnimationDuration);
// 使用PathAnimationManager创建物体动画真正的物体移动动画会设置状态为Ready
_pathAnimationManager.CreateAnimation(SelectedAnimatedObject, pathPoints, AnimationDuration);
// 更新状态 - 使用新的按钮状态更新方法
UpdateAnimationButtonStates();
GenerationStatus = "动画生成成功";
UpdateMainStatus("动画生成成功");
var totalElapsed = (DateTime.Now - cacheStartTime).TotalMilliseconds;
LogManager.Info($"[动画生成] 动画生成完成,总耗时: {totalElapsed:F1}ms");
@ -1081,8 +1138,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
catch (Exception ex)
{
GenerationStatus = "动画生成失败";
AnimationStatus = "动画生成失败";
UpdateMainStatus("动画生成失败");
LogManager.Error($"生成动画时发生错误: {ex.Message}");
LogManager.Error($"动画生成失败,详细错误信息:{ex}");
@ -1138,19 +1194,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (!hasObject && !hasPath)
{
GenerationStatus = "请选择移动物体和动画路径";
UpdateMainStatus("请选择移动物体和动画路径");
}
else if (!hasObject)
{
GenerationStatus = "请选择移动物体";
UpdateMainStatus("请选择移动物体");
}
else if (!hasPath)
{
GenerationStatus = "请选择有效的动画路径";
UpdateMainStatus("请选择有效的动画路径");
}
else
{
GenerationStatus = "可以生成动画";
UpdateMainStatus("可以生成动画");
}
// 同时更新动画按钮状态,因为对象或路径的变化会影响"开始动画"按钮的可用性
@ -1189,6 +1245,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 检查动画管理器当前状态
var animationState = _pathAnimationManager?.CurrentState ?? NavisworksTransport.Core.Animation.AnimationState.Stopped;
var isAnimating = _pathAnimationManager?.IsAnimating ?? false;
// 检查动画是否已经生成Ready状态表示动画已生成但未播放
var isAnimationReady = animationState == NavisworksTransport.Core.Animation.AnimationState.Ready ||
animationState == NavisworksTransport.Core.Animation.AnimationState.Finished;
// 根据动画状态和条件更新按钮状态
switch (animationState)
@ -1198,21 +1258,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
CanStartAnimation = false;
CanPauseAnimation = true;
CanStopAnimation = true;
AnimationStatus = "动画状态: 播放中";
UpdateMainStatus("动画播放中");
break;
case NavisworksTransport.Core.Animation.AnimationState.Paused:
// 暂停中:开始按钮可用(显示为继续),暂停按钮禁用,停止按钮可用
CanStartAnimation = hasValidAnimation;
CanStartAnimation = hasValidAnimation && isAnimationReady;
CanPauseAnimation = false;
CanStopAnimation = true;
StartAnimationButtonText = "继续播放";
AnimationStatus = "动画状态: 已暂停";
UpdateMainStatus("动画已暂停");
break;
default:
// 停止或其他状态:根据是否有有效动画来决定开始按钮状态
CanStartAnimation = hasValidAnimation;
// 停止或其他状态:需要同时满足有效动画条件和动画已生成条件
CanStartAnimation = hasValidAnimation && isAnimationReady;
CanPauseAnimation = false;
CanStopAnimation = false;
StartAnimationButtonText = "开始动画";
@ -1220,24 +1280,28 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 更新状态文本
if (!hasValidPath && !hasValidAnimatedObject)
{
AnimationStatus = "动画状态: 请选择路径和移动物体";
UpdateMainStatus("请选择路径和移动物体");
}
else if (!hasValidPath)
{
AnimationStatus = "动画状态: 请选择有效路径至少2个点";
UpdateMainStatus("请选择有效路径至少2个点");
}
else if (!hasValidAnimatedObject)
{
AnimationStatus = "动画状态: 请选择移动物体";
UpdateMainStatus("请选择移动物体");
}
else if (!isAnimationReady)
{
UpdateMainStatus("请点击'生成动画'");
}
else
{
AnimationStatus = "动画状态: 就绪";
UpdateMainStatus("动画就绪");
}
break;
}
LogManager.Debug($"按钮状态已更新: CanStart={CanStartAnimation}, CanPause={CanPauseAnimation}, CanStop={CanStopAnimation}, Status={AnimationStatus}");
LogManager.Debug($"按钮状态已更新: CanStart={CanStartAnimation}, CanPause={CanPauseAnimation}, CanStop={CanStopAnimation}");
}
catch (Exception ex)
{
@ -1325,14 +1389,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
// 通过检查是否有任何动画相关的碰撞测试来判断是否有结果
HasCollisionResults = true; // 假设动画完成后总是有结果可查看
CollisionStatus = "动画完成,碰撞检测已完成";
CollisionSummary = "请点击'查看碰撞报告'查看详细结果";
UpdateMainStatus("动画完成,碰撞检测已完成");
LogManager.Info("动画完成后碰撞状态已更新");
}
else
{
CollisionStatus = "碰撞检测未就绪";
CollisionSummary = "碰撞检测功能不可用";
UpdateMainStatus("碰撞检测未就绪");
LogManager.Warning("ClashDetectiveIntegration实例不可用");
}
}));
@ -1458,11 +1520,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
// 🔧 修复:显示动画过程缓存的碰撞数量,而非测试数量
var animationCollisionCount = _clashIntegration?.AnimationCollisionCount ?? 0;
CollisionSummary = $"动画碰撞: {animationCollisionCount}个 | Clash Detective权威结果: {reportData.TotalCollisions}个";
var summary = $"动画碰撞: {animationCollisionCount}个 | Clash Detective权威结果: {reportData.TotalCollisions}个";
UpdateMainStatus("碰撞报告已生成");
}
else
{
CollisionSummary = $"报告生成失败:{reportData.ErrorMessage}";
UpdateMainStatus($"报告生成失败:{reportData.ErrorMessage}");
}
});
@ -1566,6 +1629,67 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#endregion
#region
/// <summary>
/// 更新统一状态栏(简单版本,不显示进度条)
/// </summary>
private void UpdateMainStatus(string message)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 更新统一状态栏(支持百分比进度)
/// </summary>
private void UpdateMainStatus(string message, double percentage)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message, percentage);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 更新统一状态栏(完整版本,支持不确定进度)
/// </summary>
private void UpdateMainStatus(string message, double progress = -1, bool? isProcessing = null)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message, progress, isProcessing);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
#endregion
#region
private bool _disposed = false;

View File

@ -30,6 +30,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private PathPlanningManager _pathPlanningManager;
private readonly UIStateManager _uiStateManager;
private readonly PathDataManager _pathDataManager;
private readonly LogisticsControlViewModel _mainViewModel;
// 路径集合
private ObservableCollection<PathRouteViewModel> _pathRoutes;
@ -40,8 +41,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 自动路径规划参数
private string _autoPathStartPoint = "未选择";
private string _autoPathEndPoint = "未选择";
private string _autoPathStatus = "就绪";
private string _pathEditTipText = "提示:点击[添加路径点]后在3D视图中点击可通行的物流模型来添加路径点";
private Point3D _startPoint3D;
private Point3D _endPoint3D;
private bool _hasStartPoint = false;
@ -63,8 +62,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private PathRoute _autoPathStartPointRoute = null;
private PathRoute _autoPathEndPointRoute = null;
// 路径文件管理
private string _pathFileStatus = "未保存";
// 资源清理管理
private bool _disposed = false;
@ -204,19 +201,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _autoPathEndPoint, value);
}
public string AutoPathStatus
{
get => _autoPathStatus;
set => SetProperty(ref _autoPathStatus, value);
}
/// <summary>
/// 路径编辑提示文本
/// </summary>
public string PathEditTipText
{
get => _pathEditTipText;
set => SetProperty(ref _pathEditTipText, value);
}
public double VehicleLength
{
@ -308,11 +292,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#endregion
public string PathFileStatus
{
get => _pathFileStatus;
set => SetProperty(ref _pathFileStatus, value);
}
public PathPlanningManager PathPlanningManager
{
@ -419,7 +398,49 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"PathEditingViewModel构造函数异常: {ex.Message}", ex);
AutoPathStatus = "初始化失败,请检查日志";
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
/// <summary>
/// 带主ViewModel参数的构造函数支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public PathEditingViewModel(LogisticsControlViewModel mainViewModel) : base()
{
try
{
// 保存主ViewModel引用
_mainViewModel = mainViewModel;
_uiStateManager = UIStateManager.Instance;
_pathDataManager = new PathDataManager();
// 不在构造函数中创建PathPlanningManager由外部设置
_pathPlanningManager = null;
if (_uiStateManager == null)
{
throw new InvalidOperationException("UIStateManager初始化失败");
}
// PathPlanningManager将在外部设置这里不需要检查
// 初始化集合
PathRoutes = new ObservableCollection<PathRouteViewModel>();
// 初始化命令
InitializeCommands();
// 注意不在这里订阅PathPlanningManager事件
// 因为PathPlanningManager还没有设置事件订阅在PathPlanningManager属性setter中处理
LogManager.Info("PathEditingViewModel构造函数执行完成 - 支持统一状态栏");
}
catch (Exception ex)
{
LogManager.Error($"PathEditingViewModel构造函数异常: {ex.Message}", ex);
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
@ -458,7 +479,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
await SafeExecuteAsync(() =>
{
AutoPathStatus = "正在创建新路径...";
UpdateMainStatus("正在创建新路径...");
// 清除所有现有路径的可视化显示
if (PathPointRenderPlugin.Instance != null)
@ -511,19 +532,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 强制重新初始化ToolPlugin以确保获得鼠标焦点新建路径需要订阅事件
if (!ForceReinitializeToolPlugin(subscribeToEvents: true))
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
UpdateMainStatus("ToolPlugin初始化失败请重试");
LogManager.Error("新建路径ToolPlugin初始化失败");
return;
}
AutoPathStatus = $"已进入新建路径模式: {newRoute.Name} - 请在3D视图中点击设置路径点";
UpdateMainStatus($"已进入新建路径模式: {newRoute.Name} - 请在3D视图中点击设置路径点");
LogManager.Info($"开始新建路径: {newRoute.Name}已强制重新初始化ToolPlugin获取鼠标焦点");
// 不再显示对话框,状态文本已提供足够的反馈
}
else
{
AutoPathStatus = "创建新路径失败:没有可通行的物流模型";
UpdateMainStatus("创建新路径失败:没有可通行的物流模型");
LogManager.Error("创建新路径失败:没有可通行的物流模型");
MessageBox.Show("创建新路径失败:没有找到任何可通行的物流模型。\n请先为模型设置可通行的物流属性然后再尝试创建路径。", "错误",
MessageBoxButton.OK, MessageBoxImage.Warning);
@ -531,7 +552,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
AutoPathStatus = "路径规划管理器未初始化";
UpdateMainStatus("路径规划管理器未初始化");
LogManager.Error("路径规划管理器未初始化");
}
}, "新建路径");
@ -544,7 +565,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
await SafeExecuteAsync(() =>
{
var pathName = SelectedPathRoute.Name;
AutoPathStatus = $"正在删除路径: {pathName}...";
UpdateMainStatus($"正在删除路径: {pathName}...");
// 清理当前路径的3D可视化显示使用新的统一API
if (PathPointRenderPlugin.Instance != null)
@ -591,7 +612,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 更新UI
PathRoutes.Remove(SelectedPathRoute);
SelectedPathRoute = null;
AutoPathStatus = $"已完全删除路径: {pathName}";
UpdateMainStatus($"已完全删除路径: {pathName}");
}, "删除路径");
}
@ -608,7 +629,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_pathPlanningManager == null)
{
LogManager.Error("PathPlanningManager为null无法选择起点");
AutoPathStatus = "路径规划管理器未初始化";
UpdateMainStatus("路径规划管理器未初始化");
return;
}
@ -627,7 +648,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info("PathPlanningManager已初始化开始设置选择状态");
IsSelectingStartPoint = true;
IsSelectingEndPoint = false;
AutoPathStatus = "请在3D视图中点击选择起点...";
UpdateMainStatus("请在3D视图中点击选择起点...");
// 进入自动路径规划模式 - 动态事件订阅
LogManager.Info("进入自动路径规划模式,启用动态事件订阅");
@ -643,7 +664,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 强制重新初始化ToolPlugin以确保获得鼠标焦点自动路径不需要PathPlanningManager订阅事件
if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
UpdateMainStatus("ToolPlugin初始化失败请重试");
return;
}
@ -662,7 +683,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_pathPlanningManager == null)
{
LogManager.Error("PathPlanningManager为null无法选择终点");
AutoPathStatus = "路径规划管理器未初始化";
UpdateMainStatus("路径规划管理器未初始化");
return;
}
@ -681,7 +702,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info("PathPlanningManager已初始化开始设置选择状态");
IsSelectingStartPoint = false;
IsSelectingEndPoint = true;
AutoPathStatus = "请在3D视图中点击选择终点...";
UpdateMainStatus("请在3D视图中点击选择终点...");
// 进入自动路径规划模式 - 动态事件订阅
LogManager.Info("进入自动路径规划模式,启用动态事件订阅");
@ -697,7 +718,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 强制重新初始化ToolPlugin以确保获得鼠标焦点自动路径不需要PathPlanningManager订阅事件
if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
UpdateMainStatus("ToolPlugin初始化失败请重试");
return;
}
@ -713,11 +734,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (!_hasStartPoint || !_hasEndPoint)
{
AutoPathStatus = "请先选择起点和终点";
UpdateMainStatus("请先选择起点和终点");
return;
}
AutoPathStatus = "正在计算最优路径...";
UpdateMainStatus("正在计算最优路径...", -1, true);
LogManager.Info("=== 开始执行自动路径规划 ===");
// 确保在开始自动路径规划前清理任何残留的事件订阅
@ -786,23 +807,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 不在这里直接操作UI让RouteGenerated事件处理UI更新
// 这避免了重复的路径添加和UI更新冲突
// 不在这里设置AutoPathStatus让RouteGenerated事件处理UI更新
// 不在这里设置状态让RouteGenerated事件处理UI更新
LogManager.Info($"✅ 自动路径规划完成RouteGenerated事件将处理UI更新");
}
else
{
// 检查是否已经通过ErrorOccurred事件设置了详细错误信息
if (!AutoPathStatus.Contains("❌ 自动路径规划失败"))
{
// 如果没有详细错误信息,则设置通用错误提示
AutoPathStatus = "❌ 路径规划失败,未找到可行路径";
LogManager.Warning("自动路径规划失败:未找到可行路径");
}
else
{
// 如果已有详细错误信息,保留不覆盖
LogManager.Info("保留ErrorOccurred事件设置的详细错误信息不覆盖AutoPathStatus");
}
// 这里的逻辑已经在上方处理过了
// 失败情况下也要清理事件订阅和临时标记
LogManager.WriteLog("[自动路径规划] 规划失败后清理所有状态");
@ -868,7 +878,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_endPoint3D = new Point3D();
AutoPathStartPoint = "未选择";
AutoPathEndPoint = "未选择";
AutoPathStatus = "就绪";
UpdateMainStatus("就绪");
IsSelectingStartPoint = false;
IsSelectingEndPoint = false;
@ -899,8 +909,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var newName = $"路径 {PathRoutes.Count}";
var oldName = SelectedPathRoute.Name;
SelectedPathRoute.Name = newName;
AutoPathStatus = $"路径已重命名: {oldName} -> {newName}";
PathFileStatus = "未保存";
UpdateMainStatus($"路径已重命名: {oldName} -> {newName}");
});
}, "重命名路径");
}
@ -917,7 +926,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (SelectedPathRoute != null)
{
SelectedPathRoute.IsActive = true;
AutoPathStatus = $"正在激活3D路径编辑模式: {SelectedPathRoute.Name}...";
UpdateMainStatus($"正在激活3D路径编辑模式: {SelectedPathRoute.Name}...");
// 启动PathPlanningManager的点击工具这会设置正确的编辑状态
if (_pathPlanningManager != null)
@ -930,21 +939,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"启动点击工具失败: {ex.Message}");
AutoPathStatus = "启动3D编辑工具失败请重试";
UpdateMainStatus("启动3D编辑工具失败请重试");
IsPathEditMode = false;
return;
}
}
else
{
AutoPathStatus = "路径规划管理器未初始化";
UpdateMainStatus("路径规划管理器未初始化");
LogManager.Error("添加路径点PathPlanningManager未初始化");
IsPathEditMode = false;
return;
}
AutoPathStatus = $"已进入3D路径编辑模式: {SelectedPathRoute.Name}";
PathEditTipText = "✓ 预览模式已激活 - 在3D视图中点击设置灰色预览点满意后点击[确认]添加到路径,继续编辑或点击[结束]完成";
UpdateMainStatus($"已进入3D路径编辑模式: {SelectedPathRoute.Name} - 在3D视图中点击设置路径点");
LogManager.Info($"开始添加路径点: {SelectedPathRoute.Name},已启动点击工具");
// 手动触发按钮状态更新
@ -1023,18 +1031,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (_pathPlanningManager?.PathEditState == PathEditState.EditingPoint || operationMessage.Contains("路径点修改"))
{
AutoPathStatus = $"✅ 路径点修改完成: {SelectedPathRoute.Name}";
PathEditTipText = "路径点修改已完成";
UpdateMainStatus($"✅ 路径点修改完成: {SelectedPathRoute.Name}");
}
else if (wasInPreviewMode)
{
AutoPathStatus = $"✅ 预览点已确认,路径编辑完成: {SelectedPathRoute.Name}";
UpdateMainStatus($"✅ 预览点已确认,路径编辑完成: {SelectedPathRoute.Name}");
}
else
{
AutoPathStatus = $"✅ 路径编辑完成: {SelectedPathRoute.Name} - 最后一个点已自动设置为终点";
UpdateMainStatus($"✅ 路径编辑完成: {SelectedPathRoute.Name} - 最后一个点已自动设置为终点");
}
PathFileStatus = "已完成";
}
LogManager.Info("[UI状态] 路径编辑完成,等待状态变更事件更新按钮");
@ -1044,8 +1050,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 编辑完成失败
if (SelectedPathRoute != null)
{
AutoPathStatus = $"❌ 路径编辑失败: {SelectedPathRoute.Name}";
PathFileStatus = "编辑失败";
UpdateMainStatus($"❌ 路径编辑失败: {SelectedPathRoute.Name}");
}
LogManager.Error("[UI状态] 路径编辑失败");
@ -1070,8 +1075,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedPathRoute.Points.Clear();
AutoPathStatus = $"已清空路径 {SelectedPathRoute.Name} 的 {pointCount} 个点";
PathFileStatus = "未保存";
UpdateMainStatus($"已清空路径 {SelectedPathRoute.Name} 的 {pointCount} 个点");
});
}, "清空路径");
}
@ -1120,8 +1124,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
// 4. 更新UI状态
AutoPathStatus = $"已删除路径点: {point.Name}";
PathFileStatus = "未保存";
UpdateMainStatus($"已删除路径点: {point.Name}");
LogManager.Info($"路径点删除完成当前UI点数: {SelectedPathRoute.Points.Count}, Core点数: {coreRoute?.Points.Count ?? 0}");
});
@ -1174,14 +1177,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (success)
{
AutoPathStatus = $"正在修改路径点: {SelectedPathPoint.Name} - 请在3D视图中点击新位置";
PathEditTipText = "修改路径点模式在3D视图中点击选择新位置然后点击'确认'按钮完成修改";
UpdateMainStatus($"正在修改路径点: {SelectedPathPoint.Name} - 请在3D视图中点击新位置");
LogManager.Info($"已开始修改路径点: {SelectedPathPoint.Name}, 索引: {pointIndex}");
// 更新UI状态
OnPropertyChanged(nameof(AutoPathStatus));
OnPropertyChanged(nameof(PathEditTipText));
// 刷新命令状态
OnPropertyChanged(nameof(CanExecuteStartEdit));
OnPropertyChanged(nameof(CanExecuteEndEdit));
@ -1190,13 +1188,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
AutoPathStatus = "修改路径点失败,请检查路径状态";
UpdateMainStatus("修改路径点失败,请检查路径状态");
LogManager.Error($"开始修改路径点失败: {SelectedPathPoint.Name}, 索引: {pointIndex}");
}
}
else
{
AutoPathStatus = "找不到选中的路径点";
UpdateMainStatus("找不到选中的路径点");
LogManager.Error($"找不到路径点索引 - 选中点Id: {SelectedPathPoint.Id}, 选中点名称: {SelectedPathPoint.Name}");
LogManager.Error("可能原因1)选中的路径点与当前路径不匹配 2)路径点数据不同步 3)Id不匹配");
}
@ -1205,12 +1203,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (currentRoute == null)
{
AutoPathStatus = "当前没有活动路径";
UpdateMainStatus("当前没有活动路径");
LogManager.Error("尝试修改路径点时没有当前路径");
}
else
{
AutoPathStatus = "当前路径没有路径点数据";
UpdateMainStatus("当前路径没有路径点数据");
LogManager.Error("当前路径的Points集合为空");
}
}
@ -1219,12 +1217,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (SelectedPathPoint == null)
{
AutoPathStatus = "请先选中要修改的路径点";
UpdateMainStatus("请先选中要修改的路径点");
LogManager.Warning("修改路径点时没有选中路径点");
}
else
{
AutoPathStatus = "路径规划管理器未初始化";
UpdateMainStatus("路径规划管理器未初始化");
LogManager.Error("修改路径点时PathPlanningManager为空");
}
}
@ -1250,20 +1248,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (success)
{
AutoPathStatus = "已取消修改路径点";
PathEditTipText = "修改路径点操作已取消";
UpdateMainStatus("已取消修改路径点");
LogManager.Info("用户取消了修改路径点操作");
}
else
{
AutoPathStatus = "取消修改路径点失败";
UpdateMainStatus("取消修改路径点失败");
LogManager.Error("取消修改路径点失败");
}
// 更新UI状态
OnPropertyChanged(nameof(AutoPathStatus));
OnPropertyChanged(nameof(PathEditTipText));
// 刷新命令状态
OnPropertyChanged(nameof(CanExecuteStartEdit));
OnPropertyChanged(nameof(CanExecuteEndEdit));
@ -1350,11 +1343,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var importResult = (result as PathPlanningResult<ImportPathResult>)?.Data;
if (importResult != null)
{
AutoPathStatus = $"✅ 导入成功: {importResult.ImportedCount}/{importResult.TotalInFile} 个路径";
var statusMessage = $"✅ 导入成功: {importResult.ImportedCount}/{importResult.TotalInFile} 个路径";
if (importResult.FailedCount > 0)
{
AutoPathStatus += $" (失败 {importResult.FailedCount} 个)";
statusMessage += $" (失败 {importResult.FailedCount} 个)";
}
UpdateMainStatus(statusMessage);
if (!string.IsNullOrEmpty(importResult.BackupFilePath))
{
LogManager.Info($"导入前备份已创建: {importResult.BackupFilePath}");
@ -1362,15 +1356,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
AutoPathStatus = $"✅ 路径导入完成: {Path.GetFileName(filePath)}";
UpdateMainStatus($"✅ 路径导入完成: {Path.GetFileName(filePath)}");
}
PathFileStatus = "已导入";
}
else
{
AutoPathStatus = $"❌ 导入失败: {result.ErrorMessage}";
PathFileStatus = "导入失败";
UpdateMainStatus($"❌ 导入失败: {result.ErrorMessage}");
LogManager.Error($"路径导入失败: {result.ErrorMessage}");
}
}
@ -1378,8 +1369,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"导入路径异常: {ex.Message}", ex);
AutoPathStatus = $"❌ 导入异常: {ex.Message}";
PathFileStatus = "导入异常";
UpdateMainStatus($"❌ 导入异常: {ex.Message}");
}
}, "导入路径");
}
@ -1444,24 +1434,22 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var exportResult = (result as PathPlanningResult<ExportPathResult>)?.Data;
if (exportResult != null)
{
AutoPathStatus = $"✅ 导出全部成功: {exportResult.ExportedCount} 个路径到 {Path.GetFileName(filePath)}";
var statusMessage = $"✅ 导出全部成功: {exportResult.ExportedCount} 个路径到 {Path.GetFileName(filePath)}";
if (exportResult.FailedCount > 0)
{
AutoPathStatus += $" (失败 {exportResult.FailedCount} 个)";
statusMessage += $" (失败 {exportResult.FailedCount} 个)";
}
UpdateMainStatus(statusMessage);
LogManager.Info($"导出完成,文件大小: {exportResult.FileSizeMB:F2} MB");
}
else
{
AutoPathStatus = $"✅ 全部路径导出完成: {Path.GetFileName(filePath)}";
UpdateMainStatus($"✅ 全部路径导出完成: {Path.GetFileName(filePath)}");
}
PathFileStatus = "已导出";
}
else
{
AutoPathStatus = $"❌ 导出全部失败: {result.ErrorMessage}";
PathFileStatus = "导出全部失败";
UpdateMainStatus($"❌ 导出全部失败: {result.ErrorMessage}");
LogManager.Error($"全部路径导出失败: {result.ErrorMessage}");
}
}
@ -1469,8 +1457,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"导出全部路径异常: {ex.Message}", ex);
AutoPathStatus = $"❌ 导出全部异常: {ex.Message}";
PathFileStatus = "导出全部异常";
UpdateMainStatus($"❌ 导出全部异常: {ex.Message}");
}
}, "导出全部路径");
}
@ -1539,35 +1526,30 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var exportResult = (result as PathPlanningResult<ExportPathResult>)?.Data;
if (exportResult != null)
{
AutoPathStatus = $"✅ 导出选中路径成功: {SelectedPathRoute.Name} -> {Path.GetFileName(filePath)}";
UpdateMainStatus($"✅ 导出选中路径成功: {SelectedPathRoute.Name} -> {Path.GetFileName(filePath)}");
LogManager.Info($"导出选中路径完成,文件大小: {exportResult.FileSizeMB:F2} MB");
}
else
{
AutoPathStatus = $"✅ 导出选中路径完成: {Path.GetFileName(filePath)}";
UpdateMainStatus($"✅ 导出选中路径完成: {Path.GetFileName(filePath)}");
}
PathFileStatus = "已导出选中路径";
}
else
{
AutoPathStatus = $"❌ 导出选中路径失败: {result.ErrorMessage}";
PathFileStatus = "导出选中路径失败";
UpdateMainStatus($"❌ 导出选中路径失败: {result.ErrorMessage}");
LogManager.Error($"导出选中路径失败: {result.ErrorMessage}");
}
}
else
{
AutoPathStatus = $"❌ 导出选中路径失败找不到对应的Core路径: {SelectedPathRoute.Name}";
PathFileStatus = "导出选中路径失败";
UpdateMainStatus($"❌ 导出选中路径失败找不到对应的Core路径: {SelectedPathRoute.Name}");
}
}
}
catch (Exception ex)
{
LogManager.Error($"导出选中路径异常: {ex.Message}", ex);
AutoPathStatus = $"❌ 导出选中路径异常: {ex.Message}";
PathFileStatus = "导出选中路径异常";
UpdateMainStatus($"❌ 导出选中路径异常: {ex.Message}");
}
}, "导出选中路径");
}
@ -1690,7 +1672,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"[自动路径事件] 处理点击事件异常: {ex.Message}");
AutoPathStatus = $"获取点击位置失败: {ex.Message}";
UpdateMainStatus($"获取点击位置失败: {ex.Message}");
IsSelectingStartPoint = false;
IsSelectingEndPoint = false;
@ -1748,11 +1730,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_hasEndPoint)
{
AutoPathStatus = "起点和终点已设置,可以开始路径规划";
UpdateMainStatus("起点和终点已设置,可以开始路径规划");
}
else
{
AutoPathStatus = "起点已设置,请选择终点";
UpdateMainStatus("起点已设置,请选择终点");
}
LogManager.Info($"起点已设置: ({point.X:F2}, {point.Y:F2}, {point.Z:F2})");
@ -1798,11 +1780,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_hasStartPoint)
{
AutoPathStatus = "起点和终点已设置,可以开始路径规划";
UpdateMainStatus("起点和终点已设置,可以开始路径规划");
}
else
{
AutoPathStatus = "终点已设置,请选择起点";
UpdateMainStatus("终点已设置,请选择起点");
}
LogManager.Info($"终点已设置: ({point.X:F2}, {point.Y:F2}, {point.Z:F2})");
@ -1825,7 +1807,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
AutoPathStatus = $"{operationName}失败: {ex.Message}";
UpdateMainStatus($"{operationName}失败: {ex.Message}");
}
}
@ -2030,12 +2012,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SelectedPathRoute = pathViewModel;
}
AutoPathStatus = $"已添加路径点: {e.PathPoint.Name} 到 {e.Route.Name}";
UpdateMainStatus($"已添加路径点: {e.PathPoint.Name} 到 {e.Route.Name}");
LogManager.Info($"路径点操作完成: {e.PathPoint.Name} 已添加到路径 {e.Route.Name}");
}
else if (e.OperationType == PathPointOperationType.Removed)
{
AutoPathStatus = $"已移除路径点: {e.PathPoint.Name} 从 {e.Route.Name}";
UpdateMainStatus($"已移除路径点: {e.PathPoint.Name} 从 {e.Route.Name}");
LogManager.Info($"路径点操作完成: {e.PathPoint.Name} 已从路径 {e.Route.Name} 移除");
}
}, "处理路径点操作事件");
@ -2211,27 +2193,28 @@ namespace NavisworksTransport.UI.WPF.ViewModels
switch (e.NewState)
{
case PathEditState.Creating:
AutoPathStatus = $"正在新建路径: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点";
UpdateMainStatus($"正在新建路径: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点");
break;
case PathEditState.Editing:
AutoPathStatus = $"正在编辑路径: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点";
UpdateMainStatus($"正在编辑路径: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点");
break;
case PathEditState.AddingPoints:
AutoPathStatus = $"正在添加路径点到: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点";
UpdateMainStatus($"正在添加路径点到: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点");
break;
case PathEditState.EditingPoint:
AutoPathStatus = $"正在修改路径点: {e.EditingRoute?.Name} - 请在3D视图中点击新位置然后点击'结束'确认";
UpdateMainStatus($"正在修改路径点: {e.EditingRoute?.Name} - 请在3D视图中点击新位置然后点击'结束'确认");
break;
case PathEditState.Viewing:
// 如果当前状态包含路径规划完成信息(包括完成度百分比),则保留不覆盖
if (!AutoPathStatus.Contains("路径规划完成") && !AutoPathStatus.Contains("路径规划部分完成") &&
!AutoPathStatus.Contains("✅") && !AutoPathStatus.Contains("🔶"))
var currentStatus = _mainViewModel?.StatusText ?? "";
if (!currentStatus.Contains("路径规划完成") && !currentStatus.Contains("路径规划部分完成") &&
!currentStatus.Contains("✅") && !currentStatus.Contains("🔶"))
{
AutoPathStatus = "路径编辑已完成";
UpdateMainStatus("路径编辑已完成");
}
break;
default:
AutoPathStatus = "就绪";
UpdateMainStatus("就绪");
break;
}
@ -2338,8 +2321,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
statusMessage = $"🔶 自动路径规划部分完成: {e.Route.Name},共 {e.Route.Points.Count} 个路径点,长度 {e.Route.TotalLength:F2}米,(完成度: {e.Route.CompletionPercentage:F1}%)";
}
AutoPathStatus = statusMessage;
LogManager.Info($"*** AutoPathStatus已更新: {AutoPathStatus} ***");
UpdateMainStatus(statusMessage);
LogManager.Info($"*** 状态已更新: {statusMessage} ***");
}
else if (e.GenerationMethod == RouteGenerationMethod.Manual)
{
@ -2377,8 +2360,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 更新自动路径状态显示错误信息
AutoPathStatus = $"❌ 自动路径规划失败: {e.ErrorMessage}";
LogManager.Info($"*** AutoPathStatus已更新为: {AutoPathStatus} ***");
UpdateMainStatus($"❌ 自动路径规划失败: {e.ErrorMessage}");
LogManager.Info($"*** 状态已更新为: ❌ 自动路径规划失败: {e.ErrorMessage} ***");
});
}, "处理路径规划错误事件");
@ -2391,6 +2374,67 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#endregion
#region
/// <summary>
/// 更新统一状态栏(简单版本,不显示进度条)
/// </summary>
private void UpdateMainStatus(string message)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 更新统一状态栏(支持百分比进度)
/// </summary>
private void UpdateMainStatus(string message, double percentage)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message, percentage);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 更新统一状态栏(完整版本,支持不确定进度)
/// </summary>
private void UpdateMainStatus(string message, double progress = -1, bool? isProcessing = null)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message, progress, isProcessing);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
#endregion
#region
/// <summary>

View File

@ -18,6 +18,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#region
private readonly UIStateManager _uiStateManager;
private readonly LogisticsControlViewModel _mainViewModel;
// 系统管理相关字段
private bool _isAutoSaveEnabled = true;
@ -29,15 +30,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private bool _showUnknownGrid = 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 = "性能监控就绪";
// 🔧 修复:添加定时器字段以便在清理时停止
private System.Windows.Threading.DispatcherTimer _performanceTimer;
@ -130,14 +126,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _selectedLogLevel, value);
}
/// <summary>
/// 日志状态
/// </summary>
public string LogStatus
{
get => _logStatus;
set => SetProperty(ref _logStatus, value);
}
/// <summary>
@ -158,32 +146,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
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>
/// 内存使用情况
@ -203,14 +167,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _runningTime, value);
}
/// <summary>
/// 性能信息
/// </summary>
public string PerformanceInfo
{
get => _performanceInfo;
set => SetProperty(ref _performanceInfo, value);
}
#endregion
@ -260,7 +216,49 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
SystemStatus = "初始化失败,请检查日志";
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
/// <summary>
/// 带主ViewModel参数的构造函数支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public SystemManagementViewModel(LogisticsControlViewModel mainViewModel) : base()
{
try
{
// 保存主ViewModel引用
_mainViewModel = mainViewModel;
// 获取UI状态管理器实例
_uiStateManager = UIStateManager.Instance;
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化线程安全的集合
LogLevels = new ThreadSafeObservableCollection<string>();
// 初始化命令
InitializeCommands();
// 初始化系统管理设置
InitializeSystemManagementSettingsAsync();
LogManager.Info("SystemManagementViewModel构造函数执行完成 - 支持统一状态栏");
}
catch (Exception ex)
{
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
@ -315,18 +313,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
showObstacle: ShowObstacleGrid,
showUnknown: ShowUnknownGrid);
SettingsStatus = "网格可视化设置已更新";
UpdateMainStatus("网格可视化设置已更新");
}
else
{
LogManager.Warning("无法获取路径规划管理器,网格可视化设置可能不会立即生效");
SettingsStatus = "网格可视化设置已保存";
UpdateMainStatus("网格可视化设置已保存");
}
}
catch (Exception ex)
{
LogManager.Error($"应用网格可视化设置失败: {ex.Message}", ex);
SettingsStatus = "网格可视化设置应用失败";
UpdateMainStatus("网格可视化设置应用失败");
}
}
@ -377,12 +375,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SelectedLogLevel = "Info";
// 初始化系统信息
LogStatus = "日志系统正常";
SettingsStatus = "设置已加载";
PluginVersion = "v1.0";
NavisworksVersion = "2026";
SystemStatus = "正常";
SystemStatusColor = "Green";
UpdateMainStatus("系统管理初始化完成");
});
// 启动性能监控
@ -430,8 +425,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var runTime = DateTime.Now - startTime;
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
// 更新性能信息
PerformanceInfo = $"CPU: 正常, 内存: {memoryMB}MB, 运行时间: {RunningTime}";
// 性能信息更新已合并到统一状态栏
}
catch (Exception ex)
{
@ -497,12 +491,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 显示对话框使用Show而不是ShowDialog以避免阻塞
logViewerDialog.Show();
LogStatus = "日志查看器已打开";
UpdateMainStatus("日志查看器已打开");
LogManager.Info("通过系统管理打开日志查看器");
}
catch (Exception ex)
{
LogStatus = "打开日志查看器失败";
UpdateMainStatus("打开日志查看器失败");
LogManager.Error($"打开日志查看器失败: {ex.Message}", ex);
// 显示错误消息给用户
@ -534,7 +528,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 调用LogManager清空日志
LogManager.ClearLog();
LogStatus = "日志已清空";
UpdateMainStatus("日志已清空");
LogManager.Info("通过系统管理清空日志");
// 显示成功消息
@ -544,13 +538,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
LogStatus = "取消清空日志";
UpdateMainStatus("取消清空日志");
LogManager.Info("用户取消清空日志操作");
}
}
catch (Exception ex)
{
LogStatus = "清空日志失败";
UpdateMainStatus("清空日志失败");
LogManager.Error($"清空日志失败: {ex.Message}", ex);
// 显示错误消息给用户
@ -588,7 +582,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 从源日志文件复制到目标位置
System.IO.File.Copy(logFilePath, saveFileDialog.FileName, true);
LogStatus = $"日志已导出到: {System.IO.Path.GetFileName(saveFileDialog.FileName)}";
UpdateMainStatus($"日志已导出到: {System.IO.Path.GetFileName(saveFileDialog.FileName)}");
LogManager.Info($"日志已导出到: {saveFileDialog.FileName}");
// 显示成功消息并询问是否打开文件夹
@ -609,7 +603,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 如果日志文件不存在,创建一个空的日志文件
System.IO.File.WriteAllText(saveFileDialog.FileName, $"NavisworksTransport 日志文件\n导出时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n\n日志文件为空或不存在。\n");
LogStatus = "日志文件不存在,已创建空文件";
UpdateMainStatus("日志文件不存在,已创建空文件");
LogManager.Warning("日志文件不存在,已创建空的导出文件");
System.Windows.MessageBox.Show("原始日志文件不存在,已创建空的导出文件。", "注意",
@ -619,13 +613,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
LogStatus = "取消导出日志";
UpdateMainStatus("取消导出日志");
LogManager.Info("用户取消导出日志操作");
}
}
catch (Exception ex)
{
LogStatus = "导出日志失败";
UpdateMainStatus("导出日志失败");
LogManager.Error($"导出日志失败: {ex.Message}", ex);
// 显示错误消息给用户
@ -644,7 +638,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SafeExecute(() =>
{
// TODO: 实现设置对话框
SettingsStatus = "打开插件设置";
UpdateMainStatus("打开插件设置");
LogManager.Info("打开设置");
}, "打开设置");
}
@ -657,7 +651,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SafeExecute(() =>
{
// TODO: 实现设置重置功能
SettingsStatus = "设置已重置为默认值";
UpdateMainStatus("设置已重置为默认值");
IsAutoSaveEnabled = true;
IsDebugModeEnabled = false;
LogManager.Info("重置设置");
@ -672,7 +666,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SafeExecute(() =>
{
// TODO: 实现配置导入功能
SettingsStatus = "配置导入完成";
UpdateMainStatus("配置导入完成");
LogManager.Info("导入配置");
}, "导入配置");
}
@ -684,7 +678,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
SafeExecute(() =>
{
SystemStatus = "正在检查更新...";
UpdateMainStatus("正在检查更新...");
// 模拟检查更新
System.Threading.Tasks.Task.Run(() =>
@ -702,7 +696,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
return;
}
SystemStatus = "当前版本已是最新版本";
UpdateMainStatus("当前版本已是最新版本");
}
catch (Exception ex)
{
@ -722,7 +716,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
SafeExecute(() =>
{
SystemStatus = "正在生成性能报告...";
UpdateMainStatus("正在生成性能报告...");
// 模拟生成报告
System.Threading.Tasks.Task.Run(() =>
@ -740,8 +734,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
return;
}
SystemStatus = "性能报告生成完成";
PerformanceInfo = $"报告已生成 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
UpdateMainStatus("性能报告生成完成");
// 性能信息更新已合并到统一状态栏
}
catch (Exception ex)
{
@ -841,7 +835,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 5. 系统信息
report.AppendLine($"插件版本: {PluginVersion}");
report.AppendLine($"Navisworks版本: {NavisworksVersion}");
report.AppendLine($"系统状态: {SystemStatus}");
report.AppendLine("系统状态: 正常");
report.AppendLine("=== 诊断完成 ===");
@ -862,6 +856,63 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#region
/// <summary>
/// 更新统一状态栏(简单版本,不显示进度条)
/// </summary>
private void UpdateMainStatus(string message)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 更新统一状态栏(支持百分比进度)
/// </summary>
private void UpdateMainStatus(string message, double percentage)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message, percentage);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 更新统一状态栏(完整版本,支持不确定进度)
/// </summary>
private void UpdateMainStatus(string message, double progress = -1, bool? isProcessing = null)
{
try
{
// 如果有主ViewModel引用更新统一状态栏
if (_mainViewModel != null)
{
_mainViewModel.UpdateStatus(message, progress, isProcessing);
}
}
catch (Exception ex)
{
LogManager.Error($"更新统一状态栏失败: {ex.Message}", ex);
}
}
/// <summary>
/// 安全执行异步操作
/// </summary>
@ -874,7 +925,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
SystemStatus = $"{operationName}失败: {ex.Message}";
UpdateMainStatus($"{operationName}失败: {ex.Message}");
}
}
@ -890,7 +941,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
catch (Exception ex)
{
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
SystemStatus = $"{operationName}失败: {ex.Message}";
UpdateMainStatus($"{operationName}失败: {ex.Message}");
}
}
@ -909,8 +960,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public string GetStateInfo()
{
return $"UIStateManager: {(_uiStateManager != null ? "" : "")}, " +
$"日志级别数量: {LogLevels?.Count ?? 0}, " +
$"系统状态: {SystemStatus}";
$"日志级别数量: {LogLevels?.Count ?? 0}";
}
#endregion

View File

@ -243,11 +243,6 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
Style="{StaticResource SecondaryButtonStyle}"
Height="28"
Padding="12,4"/>
<TextBlock Text="{Binding GenerationStatus}"
VerticalAlignment="Center"
Margin="15,0,0,0"
FontWeight="SemiBold"
Foreground="#FF2B579A"/>
</StackPanel>
<!-- 生成状态提示 -->
@ -280,11 +275,6 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
Style="{StaticResource SecondaryButtonStyle}"/>
</StackPanel>
<!-- 动画状态显示 -->
<TextBlock Text="{Binding AnimationStatus}"
FontWeight="SemiBold"
Foreground="#FF2B579A"
Margin="0,0,0,10"/>
<!-- 进度条 -->
<Grid Margin="0,5,0,10">
@ -331,16 +321,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
Style="{StaticResource ActionButtonStyle}"/>
</StackPanel>
<!-- 检测状态显示 -->
<TextBlock Text="{Binding CollisionStatus}"
FontWeight="SemiBold"
Foreground="DarkRed"
Margin="0,0,0,5"/>
<!-- 检测结果摘要 -->
<TextBlock Text="{Binding CollisionSummary}"
Style="{StaticResource StatusTextStyle}"
Margin="0,5,0,0"/>
<!-- 提示信息 -->
<TextBlock Text="注:碰撞检测将在动画播放过程中自动进行,结果会在动画完成后显示"

View File

@ -22,6 +22,16 @@ namespace NavisworksTransport.UI.WPF.Views
InitializeViewModel();
}
/// <summary>
/// 带主ViewModel参数的构造函数支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public AnimationControlView(LogisticsControlViewModel mainViewModel)
{
InitializeComponent();
InitializeViewModel(mainViewModel);
}
/// <summary>
/// 初始化ViewModel
/// </summary>
@ -40,6 +50,25 @@ namespace NavisworksTransport.UI.WPF.Views
}
}
/// <summary>
/// 初始化ViewModel支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
private void InitializeViewModel(LogisticsControlViewModel mainViewModel)
{
try
{
ViewModel = new AnimationControlViewModel(mainViewModel);
DataContext = ViewModel;
LogManager.Info("AnimationControlView ViewModel初始化完成 - 支持统一状态栏");
}
catch (Exception ex)
{
LogManager.Error($"AnimationControlView ViewModel初始化失败: {ex.Message}", ex);
throw;
}
}
/// <summary>
/// 清理资源
/// </summary>

View File

@ -181,11 +181,6 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
Style="{StaticResource SecondaryButtonStyle}"/>
</StackPanel>
<!-- 状态显示 -->
<TextBlock Text="{Binding AutoPathStatus}"
FontWeight="SemiBold"
Foreground="#FF2B579A"
Margin="0,5,0,0"/>
</StackPanel>
</Border>
@ -195,25 +190,27 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
<Label Content="路径列表" Style="{StaticResource SectionHeaderStyle}"/>
<!-- 路径管理按钮 -->
<StackPanel Orientation="Horizontal" Margin="0,10,0,10">
<Button Content="手动创建"
Command="{Binding NewPathCommand}"
Style="{StaticResource ActionButtonStyle}"/>
<Button Content="删除"
Command="{Binding DeletePathCommand}"
Style="{StaticResource SecondaryButtonStyle}"
IsEnabled="{Binding SelectedPathRoute, Converter={x:Static converters:BoolToVisibilityConverter.IsNotNullToBoolConverter}}"/>
<Button Content="重命名"
Command="{Binding RenamePathCommand}"
Style="{StaticResource SecondaryButtonStyle}"
IsEnabled="{Binding SelectedPathRoute, Converter={x:Static converters:BoolToVisibilityConverter.IsNotNullToBoolConverter}}"/>
<Grid Margin="0,10,0,10">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button Content="手动创建"
Command="{Binding NewPathCommand}"
Style="{StaticResource ActionButtonStyle}"/>
<Button Content="删除"
Command="{Binding DeletePathCommand}"
Style="{StaticResource SecondaryButtonStyle}"
IsEnabled="{Binding SelectedPathRoute, Converter={x:Static converters:BoolToVisibilityConverter.IsNotNullToBoolConverter}}"/>
<Button Content="重命名"
Command="{Binding RenamePathCommand}"
Style="{StaticResource SecondaryButtonStyle}"
IsEnabled="{Binding SelectedPathRoute, Converter={x:Static converters:BoolToVisibilityConverter.IsNotNullToBoolConverter}}"/>
</StackPanel>
<Button Content="路径分析"
ToolTip="多路径对比分析..."
Style="{StaticResource ActionButtonStyle}"
Style="{StaticResource SecondaryButtonStyle}"
Click="OnPathAnalysisButtonClick"
Background="#FF4CAF50"
BorderBrush="#FF4CAF50"/>
</StackPanel>
HorizontalAlignment="Right"
Margin="0,0,0,0"/>
</Grid>
<!-- 路径列表 -->
<ListView ItemsSource="{Binding PathRoutes}"
@ -327,11 +324,6 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
</ListView.View>
</ListView>
<!-- 编辑提示 -->
<TextBlock Text="{Binding PathEditTipText}"
Style="{StaticResource StatusTextStyle}"
Foreground="#FF666666"
Margin="0,5,0,0"/>
</StackPanel>
</Border>
@ -355,21 +347,6 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
IsEnabled="{Binding CanExecuteSaveAsPath}"/>
</StackPanel>
<!-- 文件状态显示 -->
<Grid Margin="0,5,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="文件状态:" Style="{StaticResource ParameterLabelStyle}"/>
<TextBlock Grid.Column="1"
Text="{Binding PathFileStatus}"
VerticalAlignment="Center"
FontWeight="SemiBold"
Foreground="#FF2B579A"
Margin="5,0"/>
</Grid>
</StackPanel>
</Border>

View File

@ -28,6 +28,21 @@ namespace NavisworksTransport.UI.WPF.Views
LogManager.Info("PathEditingView初始化完成");
}
/// <summary>
/// 带主ViewModel参数的构造函数支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public PathEditingView(LogisticsControlViewModel mainViewModel)
{
InitializeComponent();
// 创建ViewModel传入主ViewModel引用
ViewModel = new PathEditingViewModel(mainViewModel);
DataContext = ViewModel;
LogManager.Info("PathEditingView初始化完成 - 支持统一状态栏");
}
/// <summary>
/// 清理资源
/// </summary>

View File

@ -76,10 +76,6 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
Margin="5,0,0,0"/>
</Grid>
<!-- 状态显示 -->
<Label Content="{Binding LogStatus}"
Style="{StaticResource StatusLabelStyle}"
Foreground="#FF2B8A2B"/>
</StackPanel>
</Border>
@ -146,9 +142,6 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
</StackPanel>
</Grid>
<!-- 状态显示 -->
<Label Content="{Binding SettingsStatus}"
Style="{StaticResource StatusLabelStyle}"/>
</StackPanel>
</Border>
@ -177,10 +170,6 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
<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="系统状态:" 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="内存使用:" Style="{StaticResource ParameterLabelStyle}" Width="100"/>
<Label Grid.Row="3" Grid.Column="1" Content="{Binding MemoryUsage}" Style="{StaticResource InfoTextStyle}"/>
@ -203,12 +192,6 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
<StackPanel>
<Label Content="性能监控" Style="{StaticResource SectionHeaderStyle}"/>
<!-- 性能信息显示 -->
<TextBlock Text="{Binding PerformanceInfo}"
FontSize="10"
Foreground="#FF666666"
Margin="0,10,0,15"
TextWrapping="Wrap"/>
<!-- 报告生成按钮 -->
<StackPanel Orientation="Horizontal">

View File

@ -1,15 +1,42 @@
using System.Windows.Controls;
using NavisworksTransport.UI.WPF.ViewModels;
namespace NavisworksTransport.UI.WPF.Views
{
/// <summary>
/// SystemManagementView.xaml 的交互逻辑
/// 系统管理页签视图,提供日志管理、插件设置、系统信息和性能监控功能
/// </summary>
public partial class SystemManagementView : UserControl
{
/// <summary>
/// 系统管理视图模型
/// </summary>
public SystemManagementViewModel ViewModel { get; private set; }
public SystemManagementView()
{
InitializeComponent();
}
/// <summary>
/// 带主ViewModel参数的构造函数支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public SystemManagementView(LogisticsControlViewModel mainViewModel)
{
InitializeComponent();
InitializeViewModel(mainViewModel);
}
/// <summary>
/// 初始化ViewModel支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
private void InitializeViewModel(LogisticsControlViewModel mainViewModel)
{
ViewModel = new SystemManagementViewModel(mainViewModel);
DataContext = ViewModel;
}
}
}