把碰撞报告保存到数据库,修改碰撞报告格式

This commit is contained in:
tian 2025-10-05 19:07:23 +08:00
parent e46931311f
commit 8cd988279f
11 changed files with 393 additions and 151 deletions

View File

@ -144,7 +144,7 @@
<Compile Include="src\Commands\ImportPathCommand.cs" />
<Compile Include="src\Commands\SetLogisticsAttributeCommand.cs" />
<Compile Include="src\Commands\StartAnimationCommand.cs" />
<Compile Include="src\Commands\ViewCollisionReportCommand.cs" />
<Compile Include="src\Commands\GenerateCollisionReportCommand.cs" />
<!-- Core - Animation System -->
<Compile Include="src\Core\Animation\PathAnimationManager.cs" />

View File

@ -84,12 +84,18 @@ namespace NavisworksTransport.Commands
// 新增:被撞物体清单
public List<string> CollidedObjectsList { get; set; } = new List<string>();
public int UniqueCollidedObjectsCount { get; set; }
// 新增:动画参数
public string PathName { get; set; } = "未知路径";
public int FrameRate { get; set; } = 30;
public double Duration { get; set; } = 10.0;
public double DetectionGap { get; set; } = 0.05;
}
/// <summary>
/// 查看碰撞报告Command
/// 生成碰撞报告Command
/// </summary>
public class ViewCollisionReportCommand : CommandBase
public class GenerateCollisionReportCommand : CommandBase
{
#region
@ -107,8 +113,8 @@ namespace NavisworksTransport.Commands
private readonly CollisionReportParameters _parameters;
public ViewCollisionReportCommand(CollisionReportParameters parameters = null)
: base("ViewCollisionReport", "查看碰撞报告", "生成并显示详细的碰撞检测报告")
public GenerateCollisionReportCommand(CollisionReportParameters parameters = null)
: base("GenerateCollisionReport", "生成碰撞报告", "生成并显示详细的碰撞检测报告")
{
_parameters = parameters ?? new CollisionReportParameters();
}
@ -177,6 +183,17 @@ namespace NavisworksTransport.Commands
result.CollidedObjectsList = collisionData.UniqueCollidedObjects.OrderBy(x => x).ToList();
result.UniqueCollidedObjectsCount = collisionData.UniqueCollidedObjects.Count;
// 新增:从动画管理器获取动画参数
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
if (animationManager != null)
{
result.FrameRate = animationManager.AnimationFrameRate;
result.Duration = animationManager.AnimationDuration;
result.DetectionGap = animationManager.DetectionGap;
// PathName需要从动画管理器获取
result.PathName = animationManager.PathName ?? "未知路径";
}
LogManager.Info($"碰撞报告计数 - 检查点: {result.AnimationCollisions}, Clash Detective: {result.TotalCollisions}");
UpdateProgress(70, "生成报告内容...");
@ -578,21 +595,6 @@ namespace NavisworksTransport.Commands
report.AppendLine();
}
// 按状态分类
var newCollisions = collisions.Where(c => c.Status == ClashResultStatus.New).ToList();
var activeCollisions = collisions.Where(c => c.Status == ClashResultStatus.Active).ToList();
var reviewedCollisions = collisions.Where(c => c.Status == ClashResultStatus.Reviewed).ToList();
var approvedCollisions = collisions.Where(c => c.Status == ClashResultStatus.Approved).ToList();
var resolvedCollisions = collisions.Where(c => c.Status == ClashResultStatus.Resolved).ToList();
report.AppendLine("=== 按状态分类 ===");
report.AppendLine($"新发现: {newCollisions.Count}");
report.AppendLine($"活跃: {activeCollisions.Count}");
report.AppendLine($"已审阅: {reviewedCollisions.Count}");
report.AppendLine($"已批准: {approvedCollisions.Count}");
report.AppendLine($"已解决: {resolvedCollisions.Count}");
report.AppendLine();
// 详细信息
if (includeDetails && collisions.Count > 0)
{
@ -755,9 +757,9 @@ namespace NavisworksTransport.Commands
/// <summary>
/// 创建综合报告命令
/// </summary>
public static ViewCollisionReportCommand CreateComprehensive(bool autoHighlight = false)
public static GenerateCollisionReportCommand CreateComprehensive(bool autoHighlight = false)
{
return new ViewCollisionReportCommand(new CollisionReportParameters
return new GenerateCollisionReportCommand(new CollisionReportParameters
{
Type = CollisionReportParameters.ReportType.Comprehensive,
IncludeDetails = true,

View File

@ -116,6 +116,8 @@ namespace NavisworksTransport.Core.Animation
private double _movementSpeed = 1.0; // 运动速度默认1米/秒)
private double _detectionGap = 0.05; // 检测间隙默认0.05米)
private string _pathName = "未知路径"; // 路径名称
private string _currentRouteId = null; // 当前路由ID
private string _animatedObjectName = null; // 动画对象名称
// === 双向播放和步进控制 ===
private int _playbackDirection = 1; // 播放方向1=正向,-1=反向
@ -915,7 +917,15 @@ namespace NavisworksTransport.Core.Animation
if (!_completedCollisionTests.Contains(_currentAnimationHash) && _allCollisionResults.Count > 0)
{
LogManager.Info($"此动画配置首次完成,开始创建碰撞测试汇总(基于 {_allCollisionResults.Count} 个预计算碰撞记录)...");
ClashDetectiveIntegration.Instance.CreateAllAnimationCollisionTests(_allCollisionResults, _detectionGap, _pathName);
ClashDetectiveIntegration.Instance.CreateAllAnimationCollisionTests(
_allCollisionResults,
_detectionGap,
_pathName,
_currentRouteId,
_animatedObjectName,
_animationFrameRate,
_animationDuration
);
_completedCollisionTests.Add(_currentAnimationHash); // 记录此配置已完成碰撞检测
LogManager.Info($"碰撞测试汇总已创建并记录,此配置后续播放将跳过碰撞检测");
}
@ -1962,6 +1972,16 @@ namespace NavisworksTransport.Core.Animation
/// </summary>
public double DetectionGap => _detectionGap;
/// <summary>
/// 获取路径名称
/// </summary>
public string PathName => _pathName;
/// <summary>
/// 获取动画时长
/// </summary>
public double AnimationDuration => _animationDuration;
/// <summary>
/// 设置并触发状态变更事件
/// </summary>
@ -1982,9 +2002,16 @@ namespace NavisworksTransport.Core.Animation
/// <param name="pathPoints">路径点列表</param>
/// <param name="durationSeconds">动画持续时间(秒)</param>
/// <param name="pathName">路径名称</param>
public void CreateAnimation(ModelItem animatedObject, List<Point3D> pathPoints, double durationSeconds = 10.0, string pathName = "未知路径")
/// <param name="routeId">路由ID</param>
public void CreateAnimation(ModelItem animatedObject, List<Point3D> pathPoints, double durationSeconds = 10.0, string pathName = "未知路径", string routeId = null)
{
_pathName = pathName; // 存储路径名称
_currentRouteId = routeId; // 存储路由ID
_animatedObjectName = animatedObject?.DisplayName ?? "未知对象"; // 存储动画对象名称
// 添加调试日志
LogManager.Info($"[PathAnimationManager.CreateAnimation] 接收到参数: pathName='{pathName}', routeId='{routeId}', animatedObjectName='{_animatedObjectName}'");
LogManager.Info($"[PathAnimationManager.CreateAnimation] 存储的值: _pathName='{_pathName}', _currentRouteId='{_currentRouteId}'");
SetupAnimation(animatedObject, pathPoints, durationSeconds);
SetState(AnimationState.Ready);
}

View File

@ -244,7 +244,13 @@ namespace NavisworksTransport
/// <param name="precomputedCollisions">预计算碰撞结果</param>
/// <param name="detectionGap">检测间隙容差</param>
/// <param name="pathName">路径名称</param>
public void CreateAllAnimationCollisionTests(List<CollisionResult> precomputedCollisions, double detectionGap = 0.05, string pathName = "未知路径")
/// <param name="routeId">路由ID</param>
/// <param name="animatedObjectName">动画对象名称</param>
/// <param name="frameRate">帧率</param>
/// <param name="duration">动画时长</param>
public void CreateAllAnimationCollisionTests(List<CollisionResult> precomputedCollisions, double detectionGap = 0.05,
string pathName = "未知路径", string routeId = null, string animatedObjectName = null,
int frameRate = 30, double duration = 10.0)
{
try
{
@ -587,7 +593,7 @@ namespace NavisworksTransport
LogManager.Info($"Clash Detective权威结果: {_clashDetectiveCollisionCount}个碰撞 (最终权威数据)");
LogManager.Info($"统计说明: 动画过程使用简单包围盒检测Clash Detective使用精确几何体检测");
LogManager.Info($"=== 统计分离完成 ===");
LogManager.Info("=== 动画碰撞测试(分组方案)完成 ===");
// 触发碰撞检测完成事件,通知生成报告
@ -597,6 +603,10 @@ namespace NavisworksTransport
var eventArgs = new CollisionDetectedEventArgs(validCollisions);
OnCollisionDetected(eventArgs);
}
else
{
LogManager.Info("没有碰撞,不生成报告,不保存数据库");
}
}
}
catch (Exception ex)

View File

@ -78,19 +78,20 @@ namespace NavisworksTransport
)
");
// 2. 碰撞结果表
// 2. 碰撞报告表替换原有的CollisionResults表
ExecuteNonQuery(@"
CREATE TABLE IF NOT EXISTS CollisionResults (
CREATE TABLE IF NOT EXISTS CollisionReports (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
RouteId TEXT NOT NULL,
Item1Name TEXT,
Item2Name TEXT,
CenterX REAL,
CenterY REAL,
CenterZ REAL,
Distance REAL,
DetectedTime DATETIME,
FOREIGN KEY(RouteId) REFERENCES PathRoutes(Id) ON DELETE CASCADE
RouteId TEXT,
PathName TEXT,
AnimatedObjectName TEXT,
UniqueCollidedObjectsCount INTEGER,
FrameRate INTEGER,
Duration REAL,
DetectionGap REAL,
AnimationCollisionCount INTEGER,
ClashDetectiveCollisionCount INTEGER,
ReportTime DATETIME
)
");
@ -124,7 +125,7 @@ namespace NavisworksTransport
");
// 创建索引
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_collisions_route ON CollisionResults(RouteId)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_reports_route ON CollisionReports(RouteId)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_pathpoints_route ON PathPoints(RouteId)");
}
@ -205,7 +206,48 @@ namespace NavisworksTransport
}
/// <summary>
/// 保存路径的碰撞结果
/// 保存碰撞报告
/// </summary>
public void SaveCollisionReport(string routeId, string pathName, string animatedObjectName,
int uniqueCollidedObjectsCount, int frameRate, double duration, double detectionGap,
int animationCollisionCount, int clashDetectiveCollisionCount)
{
try
{
var sql = @"
INSERT INTO CollisionReports
(RouteId, PathName, AnimatedObjectName, UniqueCollidedObjectsCount, FrameRate, Duration,
DetectionGap, AnimationCollisionCount, ClashDetectiveCollisionCount, ReportTime)
VALUES (@routeId, @pathName, @animatedObjectName, @uniqueCollidedObjectsCount, @frameRate, @duration,
@detectionGap, @animationCount, @clashCount, @reportTime)
";
using (var cmd = new SQLiteCommand(sql, _connection))
{
cmd.Parameters.AddWithValue("@routeId", routeId ?? "");
cmd.Parameters.AddWithValue("@pathName", pathName ?? "未知路径");
cmd.Parameters.AddWithValue("@animatedObjectName", animatedObjectName ?? "未知对象");
cmd.Parameters.AddWithValue("@uniqueCollidedObjectsCount", uniqueCollidedObjectsCount);
cmd.Parameters.AddWithValue("@frameRate", frameRate);
cmd.Parameters.AddWithValue("@duration", duration);
cmd.Parameters.AddWithValue("@detectionGap", detectionGap);
cmd.Parameters.AddWithValue("@animationCount", animationCollisionCount);
cmd.Parameters.AddWithValue("@clashCount", clashDetectiveCollisionCount);
cmd.Parameters.AddWithValue("@reportTime", DateTime.Now);
cmd.ExecuteNonQuery();
}
LogManager.Info($"碰撞报告已保存: 路径={pathName}, 碰撞构件={uniqueCollidedObjectsCount}, 动画碰撞={animationCollisionCount}, ClashDetective碰撞={clashDetectiveCollisionCount}");
}
catch (Exception ex)
{
LogManager.Error($"保存碰撞报告失败: {ex.Message}", ex);
throw;
}
}
/// <summary>
/// 保存路径的碰撞结果(已废弃,保留以兼容旧代码)
/// </summary>
public void SaveCollisions(string routeId, List<CollisionResult> collisions)
{

View File

@ -2843,6 +2843,18 @@ namespace NavisworksTransport
#endregion
#region 访
/// <summary>
/// 获取PathDatabase实例
/// </summary>
public PathDatabase GetPathDatabase()
{
return _pathDatabase;
}
#endregion
#region
/// <summary>

View File

@ -156,6 +156,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
#region
private string _id;
private string _name;
private ObservableCollection<PathPointViewModel> _points;
private bool _isActive;
@ -176,6 +177,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#region
/// <summary>
/// 路径ID
/// </summary>
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
/// <summary>
/// 路径名称
/// </summary>
@ -380,6 +390,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// </summary>
private void InitializeDefaults()
{
_id = Guid.NewGuid().ToString();
_name = "新路径";
_description = "";
_isActive = false;

View File

@ -78,7 +78,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 碰撞检测相关字段
private bool _hasCollisionResults = false;
private CollisionReportResult _lastGeneratedReport; // 缓存最后生成的报告
// 碰撞检测参数字段
private double _detectionGap = 0.05; // 检测间隙(米)
private int _animationFrameRate = 30; // 动画帧率(FPS)
@ -456,8 +457,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置主ViewModel引用到基类
SetMainViewModel(mainViewModel);
// 初始化管理器
_pathAnimationManager = new NavisworksTransport.Core.Animation.PathAnimationManager();
// 初始化管理器 - 使用单例模式确保与GenerateCollisionReportCommand使用同一实例
_pathAnimationManager = NavisworksTransport.Core.Animation.PathAnimationManager.GetInstance();
_clashIntegration = ClashDetectiveIntegration.Instance;
_uiStateManager = UIStateManager.Instance;
@ -680,7 +681,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 查看碰撞报告命令
/// 查看碰撞报告命令(显示已缓存的报告)
/// </summary>
private async Task ExecuteViewCollisionReport()
{
@ -692,23 +693,42 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
UpdateMainStatus("正在生成碰撞报告...", -1, true);
LogManager.Info("开始生成碰撞检测详细报告");
// 直接调用完整的ViewCollisionReportCommand生成详细报告在主线程上执行COM操作
var viewReportCommand = NavisworksTransport.Commands.ViewCollisionReportCommand.CreateComprehensive();
var result = await viewReportCommand.ExecuteAsync();
if (result.IsSuccess)
// 检查是否有已缓存的报告
if (_lastGeneratedReport == null)
{
UpdateMainStatus("碰撞报告已生成");
LogManager.Info("碰撞报告生成完成并已显示");
UpdateMainStatus("报告尚未生成,请等待碰撞检测完成");
LogManager.Warning("尝试查看报告但缓存为空");
return;
}
else
UpdateMainStatus("正在显示碰撞报告...", -1, true);
LogManager.Info("开始显示已缓存的碰撞报告");
// 在UI线程上显示缓存的报告
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus($"报告生成失败: {result.ErrorMessage}");
LogManager.Error($"碰撞报告生成失败: {result.ErrorMessage}");
}
try
{
// 使用WPF碰撞报告对话框直接显示缓存的报告
var reportDialog = NavisworksTransport.UI.WPF.Views.CollisionReportDialog.ShowReport(_lastGeneratedReport);
if (reportDialog != null)
{
UpdateMainStatus("碰撞报告已显示");
LogManager.Info("成功显示缓存的碰撞报告");
}
else
{
UpdateMainStatus("显示报告对话框失败");
LogManager.Error("CollisionReportDialog.ShowReport返回null");
}
}
catch (Exception dialogEx)
{
UpdateMainStatus($"显示报告失败: {dialogEx.Message}");
LogManager.Error($"显示WPF报告对话框失败: {dialogEx.Message}");
}
});
}
catch (Exception ex)
{
@ -902,7 +922,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public void SetCurrentPath(PathRouteViewModel pathRoute)
{
CurrentPathRoute = pathRoute;
// 添加调试日志
if (pathRoute != null)
{
LogManager.Info($"[AnimationControlViewModel] 设置当前路径: 名称='{pathRoute.Name}', ID='{pathRoute.Id}', 点数={pathRoute.Points?.Count ?? 0}");
}
else
{
LogManager.Info("[AnimationControlViewModel] 清空当前路径");
}
// 路径改变时清除已生成的动画(如果有的话)
if (_pathAnimationManager != null &&
(_pathAnimationManager.CurrentState == NavisworksTransport.Core.Animation.AnimationState.Ready ||
@ -1009,15 +1039,98 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 处理碰撞检测事件
/// 处理碰撞检测事件 - 自动生成报告并保存数据库
/// </summary>
private void OnCollisionDetected(object sender, CollisionDetectedEventArgs e)
private async void OnCollisionDetected(object sender, CollisionDetectedEventArgs e)
{
HasCollisionResults = e.Results.Count > 0;
var summary = e.Results.Count > 0
? $"发现 {e.Results.Count} 个碰撞点"
: "未发现碰撞";
UpdateMainStatus(summary);
if (e.Results.Count > 0)
{
try
{
UpdateMainStatus($"发现 {e.Results.Count} 个碰撞点,正在生成报告...", -1, true);
LogManager.Info($"碰撞检测完成,发现 {e.Results.Count} 个碰撞,开始自动生成报告");
// 自动生成碰撞报告
var generateReportCommand = NavisworksTransport.Commands.GenerateCollisionReportCommand.CreateComprehensive();
var result = await generateReportCommand.ExecuteAsync();
if (result.IsSuccess && result is PathPlanningResult<CollisionReportResult> reportResult)
{
// 缓存报告结果,供后续查看使用
_lastGeneratedReport = reportResult.Data;
// 保存到数据库
await SaveCollisionReportToDatabase(reportResult.Data);
UpdateMainStatus($"✅ 碰撞报告已生成并保存:{e.Results.Count} 个碰撞");
LogManager.Info("碰撞报告已自动生成并保存到数据库");
}
else
{
UpdateMainStatus($"发现 {e.Results.Count} 个碰撞点(报告生成失败)");
LogManager.Error($"自动生成碰撞报告失败: {result.ErrorMessage}");
}
}
catch (Exception ex)
{
LogManager.Error($"处理碰撞检测事件失败: {ex.Message}", ex);
UpdateMainStatus($"发现 {e.Results.Count} 个碰撞点(报告生成异常)");
}
}
else
{
UpdateMainStatus("未发现碰撞");
_lastGeneratedReport = null;
}
}
/// <summary>
/// 保存碰撞报告到数据库
/// </summary>
private async Task SaveCollisionReportToDatabase(CollisionReportResult reportResult)
{
try
{
var pathPlanningManager = PathPlanningManager.Instance;
var pathDatabase = pathPlanningManager?.GetPathDatabase();
if (pathDatabase != null && reportResult != null)
{
// 获取路由ID
string routeId = CurrentPathRoute?.Id ?? "";
// 从报告中获取所有需要的数据
await Task.Run(() =>
{
pathDatabase.SaveCollisionReport(
routeId,
reportResult.PathName,
SelectedAnimatedObjectName ?? "未知对象",
reportResult.UniqueCollidedObjectsCount,
reportResult.FrameRate,
reportResult.Duration,
reportResult.DetectionGap,
reportResult.AnimationCollisions,
reportResult.TotalCollisions
);
});
LogManager.Info($"碰撞报告已保存到数据库 - 路径:{reportResult.PathName}, " +
$"碰撞构件:{reportResult.UniqueCollidedObjectsCount}, " +
$"动画碰撞:{reportResult.AnimationCollisions}, " +
$"ClashDetective:{reportResult.TotalCollisions}");
}
else
{
LogManager.Warning("无法获取PathDatabase实例或报告数据为空碰撞报告未保存到数据库");
}
}
catch (Exception ex)
{
LogManager.Error($"保存碰撞报告到数据库失败: {ex.Message}", ex);
}
}
/// <summary>
@ -1295,8 +1408,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 将PathRouteViewModel的点转换为Point3D列表
var pathPoints = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
// 添加调试日志
LogManager.Info($"[ExecuteGenerateAnimation] 准备创建动画: 路径名称='{CurrentPathRoute.Name}', ID='{CurrentPathRoute.Id}', 动画对象='{SelectedAnimatedObject.DisplayName}'");
// 使用PathAnimationManager创建物体动画真正的物体移动动画会设置状态为Ready
_pathAnimationManager.CreateAnimation(SelectedAnimatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name);
_pathAnimationManager.CreateAnimation(SelectedAnimatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id);
// 更新状态 - 使用新的按钮状态更新方法
UpdateAnimationButtonStates();
@ -1815,17 +1931,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
// 3. 清理动画管理器PathAnimationManager.Dispose内部已经优化了安全清理
// 3. 不再清理PathAnimationManager - 现在使用单例模式,由应用程序生命周期管理
// 注意PathAnimationManager.GetInstance()返回的是单例实例,
// 不应该在这里Dispose否则会影响其他使用该单例的地方
if (_pathAnimationManager != null)
{
try
{
_pathAnimationManager.Dispose();
LogManager.Debug("PathAnimationManager清理完成");
// 只清理事件订阅和重置状态不调用Dispose
_pathAnimationManager.ResetAnimation();
LogManager.Debug("PathAnimationManager状态重置完成");
}
catch (Exception disposeEx)
catch (Exception resetEx)
{
LogManager.Warning($"清理PathAnimationManager时出现警告: {disposeEx.Message}");
LogManager.Warning($"重置PathAnimationManager状态时出现警告: {resetEx.Message}");
}
}

View File

@ -80,6 +80,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private string _movingObjectInfo;
private ObservableCollection<string> _collidedObjectsList;
private int _uniqueCollidedObjectsCount;
private string _pathName;
private int _frameRate;
private double _duration;
private double _detectionGap;
#endregion
@ -203,6 +207,42 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _uniqueCollidedObjectsCount, value);
}
/// <summary>
/// 路径名称
/// </summary>
public string PathName
{
get => _pathName;
set => SetProperty(ref _pathName, value);
}
/// <summary>
/// 动画帧率
/// </summary>
public int FrameRate
{
get => _frameRate;
set => SetProperty(ref _frameRate, value);
}
/// <summary>
/// 动画时长
/// </summary>
public double Duration
{
get => _duration;
set => SetProperty(ref _duration, value);
}
/// <summary>
/// 检测间隙
/// </summary>
public double DetectionGap
{
get => _detectionGap;
set => SetProperty(ref _detectionGap, value);
}
#endregion
#region
@ -217,10 +257,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// </summary>
public ICommand CloseCommand { get; }
/// <summary>
/// 刷新报告命令
/// </summary>
public ICommand RefreshReportCommand { get; }
/// <summary>
/// 高亮碰撞对象命令
@ -242,7 +278,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化命令
ExportReportCommand = new RelayCommand(async () => await ExportReportAsync(), () => !IsGenerating && HasCollisions);
CloseCommand = new RelayCommand(CloseWindow);
RefreshReportCommand = new RelayCommand(async () => await RefreshReportAsync(), () => !IsGenerating);
HighlightCollisionCommand = new RelayCommand<CollisionReportItem>(HighlightCollision, item => item?.CollisionData != null);
// 初始化状态
@ -292,6 +327,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
// 设置动画参数
PathName = reportResult.PathName;
FrameRate = reportResult.FrameRate;
Duration = reportResult.Duration;
DetectionGap = reportResult.DetectionGap;
// 更新统计信息
UpdateStatistics(reportResult);
@ -579,7 +620,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
report.AppendLine("========================================");
report.AppendLine($"生成时间: {now:yyyy年MM月dd日 HH:mm:ss}");
report.AppendLine($"报告类型: {Statistics.ReportType}");
report.AppendLine($"路径名称: {PathName}");
// 总体统计
report.AppendLine("=== 总体统计 ===");
report.AppendLine($"总碰撞数: {Statistics.TotalCollisions}");
@ -587,13 +629,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
report.AppendLine($"检测点: {Statistics.AnimationCollisions}个");
report.AppendLine();
// 按状态分类
report.AppendLine("=== 按状态分类 ===");
report.AppendLine($"新发现: {Statistics.NewCollisions}");
report.AppendLine($"活跃: {Statistics.ActiveCollisions}");
report.AppendLine($"已审阅: {Statistics.ReviewedCollisions}");
report.AppendLine($"已批准: {Statistics.ApprovedCollisions}");
report.AppendLine($"已解决: {Statistics.ResolvedCollisions}");
// 动画参数
report.AppendLine("=== 动画参数 ===");
report.AppendLine($"帧率: {FrameRate} FPS");
report.AppendLine($"时长: {Duration:F1} 秒");
report.AppendLine($"检测间隙: {DetectionGap:F2} 米");
report.AppendLine();
// 运动构件信息
@ -686,8 +726,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
html.AppendLine(".stat-item { background: white; padding: 15px; border-radius: 6px; border: 1px solid #ddd; text-align: center; }");
html.AppendLine(".stat-label { font-size: 12px; color: #666; margin-bottom: 5px; }");
html.AppendLine(".stat-value { font-size: 18px; font-weight: bold; color: #2c5aa0; }");
html.AppendLine(".status-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin: 15px 0; }");
html.AppendLine(".status-item { background: #f9f9f9; padding: 10px; border-radius: 4px; text-align: center; font-size: 12px; }");
html.AppendLine(".moving-object { background: #f0f8ff; padding: 15px; border-radius: 8px; text-align: center; margin: 15px 0; border: 1px solid #b0d4f1; }");
html.AppendLine(".collided-list { background: #f8fbff; padding: 15px; border-radius: 8px; margin: 15px 0; max-height: 200px; overflow-y: auto; }");
html.AppendLine(".list-item { margin: 5px 0; padding: 5px; border-left: 3px solid #2c5aa0; padding-left: 10px; }");
@ -704,6 +742,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
html.AppendLine($"<h1>NavisworksTransport 碰撞检测报告</h1>");
html.AppendLine($"<p style='text-align: center; color: #666;'>生成时间: {now:yyyy年MM月dd日 HH:mm:ss}</p>");
html.AppendLine($"<p style='text-align: center; color: #666;'>报告类型: {Statistics.ReportType}</p>");
html.AppendLine($"<p style='text-align: center; color: #666;'>路径名称: {PathName}</p>");
// 总体统计
html.AppendLine("<div class='summary'>");
@ -724,14 +763,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
html.AppendLine("</div>");
html.AppendLine("</div>");
// 状态分布
html.AppendLine("<h2>状态分布</h2>");
html.AppendLine("<div class='status-grid'>");
html.AppendLine($"<div class='status-item'><strong>新发现</strong><br>{Statistics.NewCollisions}</div>");
html.AppendLine($"<div class='status-item'><strong>活跃</strong><br>{Statistics.ActiveCollisions}</div>");
html.AppendLine($"<div class='status-item'><strong>已审阅</strong><br>{Statistics.ReviewedCollisions}</div>");
html.AppendLine($"<div class='status-item'><strong>已批准</strong><br>{Statistics.ApprovedCollisions}</div>");
html.AppendLine($"<div class='status-item'><strong>已解决</strong><br>{Statistics.ResolvedCollisions}</div>");
// 动画参数
html.AppendLine("<h2>动画参数</h2>");
html.AppendLine("<div class='stats-grid'>");
html.AppendLine("<div class='stat-item'>");
html.AppendLine("<div class='stat-label'>帧率</div>");
html.AppendLine($"<div class='stat-value'>{FrameRate} FPS</div>");
html.AppendLine("</div>");
html.AppendLine("<div class='stat-item'>");
html.AppendLine("<div class='stat-label'>时长</div>");
html.AppendLine($"<div class='stat-value'>{Duration:F1} 秒</div>");
html.AppendLine("</div>");
html.AppendLine("<div class='stat-item'>");
html.AppendLine("<div class='stat-label'>检测间隙</div>");
html.AppendLine($"<div class='stat-value'>{DetectionGap:F2} 米</div>");
html.AppendLine("</div>");
html.AppendLine("</div>");
// 运动构件信息
@ -828,41 +874,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 刷新报告
/// </summary>
private async Task RefreshReportAsync()
{
try
{
IsGenerating = true;
ProgressMessage = "正在重新生成报告...";
ProgressPercentage = 0;
// 重新执行碰撞报告生成
var command = ViewCollisionReportCommand.CreateComprehensive(false);
var result = await command.ExecuteAsync();
if (result.IsSuccess && result is PathPlanningResult<CollisionReportResult> reportResult)
{
InitializeReport(reportResult.Data);
}
else
{
SetFailedReport(result.Message);
}
}
catch (Exception ex)
{
LogManager.Error($"刷新碰撞报告失败: {ex.Message}");
SetFailedReport(ex.Message);
}
finally
{
IsGenerating = false;
}
}
/// <summary>
/// 高亮碰撞对象
/// </summary>

View File

@ -667,6 +667,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 创建对应的 WPF ViewModel
var newPathViewModel = new PathRouteViewModel
{
Id = newRoute.Id, // 添加Id属性设置
Name = newRoute.Name,
Description = newRoute.Description,
IsActive = true
@ -1834,6 +1835,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var pathViewModel = new PathRouteViewModel
{
Id = coreRoute.Id, // 添加Id属性设置
Name = coreRoute.Name,
Description = coreRoute.Description,
IsActive = false
@ -2540,6 +2542,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 创建对应的 WPF ViewModel
var autoPathViewModel = new PathRouteViewModel
{
Id = e.Route.Id,
Name = e.Route.Name,
Description = e.Route.Description,
IsActive = true
@ -2616,6 +2619,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 创建对应的 WPF ViewModel
var dbPathViewModel = new PathRouteViewModel
{
Id = e.Route.Id,
Name = e.Route.Name,
Description = e.Route.Description,
IsActive = false // 历史路径默认不激活

View File

@ -224,37 +224,47 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
</Border>
</UniformGrid>
<!-- 按状态分类统计 -->
<Label Content="状态分布" Style="{StaticResource SectionHeaderStyle}"/>
<UniformGrid Columns="5" Margin="0,0,0,15">
<!-- 检测参数信息 -->
<Label Content="检测参数" Style="{StaticResource SectionHeaderStyle}"/>
<UniformGrid Columns="4" Margin="0,0,0,15">
<Border Style="{StaticResource StatisticItemStyle}">
<Grid>
<TextBlock Text="新发现" Style="{StaticResource StatisticLabelStyle}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Statistics.NewCollisions}" Style="{StaticResource StatisticValueStyle}"/>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="路径名称" Style="{StaticResource StatisticLabelStyle}"/>
<TextBlock Grid.Row="1" Text="{Binding PathName}" Style="{StaticResource StatisticValueStyle}" FontSize="11"/>
</Grid>
</Border>
<Border Style="{StaticResource StatisticItemStyle}">
<Grid>
<TextBlock Text="活跃" Style="{StaticResource StatisticLabelStyle}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Statistics.ActiveCollisions}" Style="{StaticResource StatisticValueStyle}"/>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="帧率(FPS)" Style="{StaticResource StatisticLabelStyle}"/>
<TextBlock Grid.Row="1" Text="{Binding FrameRate}" Style="{StaticResource StatisticValueStyle}"/>
</Grid>
</Border>
<Border Style="{StaticResource StatisticItemStyle}">
<Grid>
<TextBlock Text="已审阅" Style="{StaticResource StatisticLabelStyle}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Statistics.ReviewedCollisions}" Style="{StaticResource StatisticValueStyle}"/>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="时长(秒)" Style="{StaticResource StatisticLabelStyle}"/>
<TextBlock Grid.Row="1" Text="{Binding Duration}" Style="{StaticResource StatisticValueStyle}"/>
</Grid>
</Border>
<Border Style="{StaticResource StatisticItemStyle}">
<Grid>
<TextBlock Text="已批准" Style="{StaticResource StatisticLabelStyle}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Statistics.ApprovedCollisions}" Style="{StaticResource StatisticValueStyle}"/>
</Grid>
</Border>
<Border Style="{StaticResource StatisticItemStyle}">
<Grid>
<TextBlock Text="已解决" Style="{StaticResource StatisticLabelStyle}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Statistics.ResolvedCollisions}" Style="{StaticResource StatisticValueStyle}"/>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="检测间隙(米)" Style="{StaticResource StatisticLabelStyle}"/>
<TextBlock Grid.Row="1" Text="{Binding DetectionGap}" Style="{StaticResource StatisticValueStyle}"/>
</Grid>
</Border>
</UniformGrid>
@ -364,12 +374,6 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Content="刷新报告"
Command="{Binding RefreshReportCommand}"
Style="{StaticResource SecondaryButtonStyle}"
Margin="0,0,10,0"
Visibility="{Binding IsGenerating, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
<Button Content="导出报告"
Command="{Binding ExportReportCommand}"
Style="{StaticResource SecondaryButtonStyle}"