481 lines
26 KiB
C#
481 lines
26 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using Autodesk.Navisworks.Api;
|
||
using NavisworksTransport.Commands;
|
||
|
||
namespace NavisworksTransport.Utils
|
||
{
|
||
/// <summary>
|
||
/// 碰撞报告HTML生成器
|
||
/// </summary>
|
||
public static class CollisionReportHtmlGenerator
|
||
{
|
||
/// <summary>
|
||
/// 生成HTML报告内容
|
||
/// </summary>
|
||
/// <param name="report">碰撞报告结果</param>
|
||
/// <param name="htmlFilePath">HTML文件路径(用于计算截图相对路径)</param>
|
||
/// <returns>HTML内容</returns>
|
||
public static string GenerateHtmlReport(CollisionReportResult report, string htmlFilePath)
|
||
{
|
||
if (report == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(report));
|
||
}
|
||
|
||
var html = new StringBuilder();
|
||
var now = DateTime.Now;
|
||
|
||
// HTML头部和样式
|
||
html.AppendLine("<!DOCTYPE html>");
|
||
html.AppendLine("<html><head>");
|
||
html.AppendLine("<meta charset='UTF-8'>");
|
||
html.AppendLine("<title>NavisworksTransport 碰撞检测报告</title>");
|
||
html.AppendLine("<style>");
|
||
html.AppendLine("body { font-family: 'Microsoft YaHei', Arial, sans-serif; margin: 20px; line-height: 1.6; }");
|
||
html.AppendLine("h1 { color: #2c5aa0; text-align: center; border-bottom: 2px solid #2c5aa0; padding-bottom: 10px; }");
|
||
html.AppendLine("h2 { color: #2c5aa0; margin-top: 25px; }");
|
||
html.AppendLine(".summary { background: #f8fbff; padding: 15px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #2c5aa0; }");
|
||
html.AppendLine(".stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin: 15px 0; }");
|
||
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(".moving-object { background: #f0f8ff; padding: 15px; border-radius: 8px; text-align: center; margin: 15px 0; border: 1px solid #b0d4f1; }");
|
||
html.AppendLine(".collided-list { background: #fdf2f2; padding: 15px; border-radius: 8px; margin: 15px 0; max-height: 200px; overflow-y: auto; border: 1px solid #f5c6c6; }");
|
||
html.AppendLine(".collided-list .list-item { margin: 5px 0; padding: 5px; border-left: 3px solid #dc3545; padding-left: 10px; color: #721c24; font-weight: 500; }");
|
||
html.AppendLine(".excluded-list { background: #fef9e7; padding: 15px; border-radius: 8px; margin: 15px 0; max-height: 250px; overflow-y: auto; border: 1px solid #f9e79f; }");
|
||
html.AppendLine(".excluded-list .list-item { margin: 5px 0; padding: 5px; border-left: 3px solid #f9e79f; padding-left: 10px; color: #856404; }");
|
||
html.AppendLine(".recommendation { background: #fff3cd; padding: 15px; border-radius: 8px; border-left: 4px solid #ffc107; margin: 15px 0; }");
|
||
html.AppendLine(".collision-item { background: white; margin: 10px 0; padding: 15px; border-radius: 6px; border: 1px solid #eee; }");
|
||
html.AppendLine(".collision-title { font-weight: bold; color: #333; margin-bottom: 8px; }");
|
||
html.AppendLine(".collision-status { display: inline-block; padding: 3px 8px; border-radius: 12px; font-size: 11px; color: white; margin-bottom: 8px; }");
|
||
html.AppendLine(".status-new { background-color: #ff6b6b; } .status-active { background-color: #ffa500; }");
|
||
html.AppendLine(".status-reviewed { background-color: #87ceeb; } .status-approved { background-color: #98fb98; } .status-resolved { background-color: #90ee90; }");
|
||
html.AppendLine(".screenshot-section { margin: 20px 0; padding: 15px; background-color: #f5f5f5; border-radius: 5px; }");
|
||
html.AppendLine(".screenshot-container { text-align: center; }");
|
||
html.AppendLine(".screenshot-image { max-width: 100%; height: auto; border: 1px solid #ddd; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }");
|
||
html.AppendLine(".screenshot-info { margin-top: 10px; font-size: 12px; color: #666; }");
|
||
html.AppendLine("</style>");
|
||
html.AppendLine("</head><body>");
|
||
|
||
// 从数据库获取检测记录信息
|
||
var (testName, testTime) = GetDetectionRecordInfo(report.ResultId);
|
||
|
||
// 报告标题
|
||
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;'>报告类型: 综合报告</p>");
|
||
|
||
// 检测记录信息
|
||
html.AppendLine("<div class='summary'>");
|
||
html.AppendLine("<h2>检测记录</h2>");
|
||
html.AppendLine("<div class='stats-grid' style='grid-template-columns: repeat(2, 1fr);'>");
|
||
html.AppendLine("<div class='stat-item'>");
|
||
html.AppendLine("<div class='stat-label'>测试名称</div>");
|
||
html.AppendLine($"<div class='stat-value'>{testName ?? "未命名"}</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("<div class='stat-item'>");
|
||
html.AppendLine("<div class='stat-label'>检测时间</div>");
|
||
html.AppendLine($"<div class='stat-value'>{testTime}</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</div>");
|
||
|
||
// 总体统计
|
||
html.AppendLine("<div class='summary'>");
|
||
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'>{report.TotalCollisions}</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("<div class='stat-item'>");
|
||
html.AppendLine("<div class='stat-label'>碰撞构件</div>");
|
||
html.AppendLine($"<div class='stat-value'>{report.UniqueCollidedObjectsCount}个</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("<div class='stat-item'>");
|
||
html.AppendLine("<div class='stat-label'>检测点</div>");
|
||
html.AppendLine($"<div class='stat-value'>{report.AnimationCollisions}个</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</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'>{report.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'>{report.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'>{report.DetectionTolerance:F2} 米</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</div>");
|
||
|
||
// 碰撞场景截图(支持多张)
|
||
var validScreenshots = report.Screenshots?.Where(s => !string.IsNullOrEmpty(s.FilePath) && File.Exists(s.FilePath)).ToList();
|
||
if (validScreenshots?.Count > 0)
|
||
{
|
||
html.AppendLine("<h2>碰撞场景截图</h2>");
|
||
|
||
// 多张截图样式 - 大图+缩略图横排交互式布局
|
||
if (validScreenshots?.Count > 1)
|
||
{
|
||
html.AppendLine("<style>");
|
||
// 主图区域样式
|
||
html.AppendLine(".main-image-container { background: white; padding: 15px; border-radius: 6px; border: 1px solid #ddd; margin-bottom: 15px; }");
|
||
html.AppendLine(".main-image { width: 100%; height: auto; border-radius: 4px; cursor: pointer; transition: transform 0.2s; }");
|
||
html.AppendLine(".main-image:hover { transform: scale(1.01); }");
|
||
html.AppendLine(".main-image-info { margin-top: 10px; font-size: 13px; color: #666; text-align: center; }");
|
||
// 缩略图横排样式
|
||
html.AppendLine(".thumbnail-row { display: flex; gap: 10px; overflow-x: auto; padding: 10px; background: #f9f9f9; border-radius: 6px; border: 1px solid #e0e0e0; }");
|
||
html.AppendLine(".thumbnail-item { flex: 0 0 auto; width: 120px; cursor: pointer; transition: all 0.2s; }");
|
||
html.AppendLine(".thumbnail-item img { width: 100%; height: 80px; object-fit: cover; border-radius: 4px; border: 2px solid transparent; transition: all 0.2s; }");
|
||
html.AppendLine(".thumbnail-item:hover img { border-color: #87ceeb; transform: scale(1.05); }");
|
||
html.AppendLine(".thumbnail-item.active img { border-color: #2B579A; box-shadow: 0 0 6px rgba(43,87,154,0.4); }");
|
||
html.AppendLine(".thumbnail-label { font-size: 11px; color: #666; text-align: center; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }");
|
||
html.AppendLine(".thumbnail-item.active .thumbnail-label { color: #2B579A; font-weight: bold; }");
|
||
html.AppendLine("</style>");
|
||
|
||
// 主图区域
|
||
html.AppendLine("<div class='main-image-container'>");
|
||
html.AppendLine("<img id='mainImage' src=\"\" alt=\"主图\" class=\"main-image\" onclick=\"window.open(this.src)\">");
|
||
html.AppendLine("<div id='mainImageInfo' class='main-image-info'></div>");
|
||
html.AppendLine("</div>");
|
||
|
||
// 缩略图横排
|
||
html.AppendLine("<div class='thumbnail-row' id='thumbnailRow'>");
|
||
int index = 1;
|
||
foreach (var screenshot in validScreenshots.OrderBy(s => s.SortOrder))
|
||
{
|
||
string relativePath = PathHelper.GetRelativePath(htmlFilePath, screenshot.FilePath);
|
||
string label = string.IsNullOrEmpty(screenshot.Description) ? $"截图 {index}" : screenshot.Description;
|
||
string desc = screenshot.Description ?? $"截图 {index}";
|
||
html.AppendLine($"<div class='thumbnail-item' data-src=\"{relativePath}\" data-index=\"{index}\" data-width=\"{screenshot.Width}\" data-height=\"{screenshot.Height}\" data-time=\"{screenshot.CaptureTime:yyyy-MM-dd HH:mm}\" data-desc=\"{desc}\" onclick=\"selectImage(this)\">");
|
||
html.AppendLine($"<img src=\"{relativePath}\" alt=\"{label}\">");
|
||
html.AppendLine($"<div class='thumbnail-label'>{label}</div>");
|
||
html.AppendLine("</div>");
|
||
index++;
|
||
}
|
||
html.AppendLine("</div>");
|
||
|
||
// JavaScript交互
|
||
html.AppendLine("<script>");
|
||
html.AppendLine("function selectImage(element) {");
|
||
html.AppendLine(" // 更新选中状态");
|
||
html.AppendLine(" document.querySelectorAll('.thumbnail-item').forEach(function(el) { el.classList.remove('active'); });");
|
||
html.AppendLine(" element.classList.add('active');");
|
||
html.AppendLine(" // 更新主图");
|
||
html.AppendLine(" var mainImage = document.getElementById('mainImage');");
|
||
html.AppendLine(" mainImage.src = element.getAttribute('data-src');");
|
||
html.AppendLine(" // 更新主图信息");
|
||
html.AppendLine(" var desc = element.getAttribute('data-desc');");
|
||
html.AppendLine(" var width = element.getAttribute('data-width');");
|
||
html.AppendLine(" var height = element.getAttribute('data-height');");
|
||
html.AppendLine(" var time = element.getAttribute('data-time');");
|
||
html.AppendLine(" document.getElementById('mainImageInfo').innerHTML = desc + ' • ' + width + 'x' + height + ' • ' + time;");
|
||
html.AppendLine("}");
|
||
html.AppendLine("// 初始化显示第一张图");
|
||
html.AppendLine("document.addEventListener('DOMContentLoaded', function() {");
|
||
html.AppendLine(" var firstThumb = document.querySelector('.thumbnail-item');");
|
||
html.AppendLine(" if (firstThumb) selectImage(firstThumb);");
|
||
html.AppendLine("});");
|
||
html.AppendLine("</script>");
|
||
}
|
||
else if (validScreenshots?.Count == 1)
|
||
{
|
||
// 单张截图样式
|
||
var screenshot = validScreenshots.First();
|
||
|
||
html.AppendLine("<div class='screenshot-section'>");
|
||
string relativePath = PathHelper.GetRelativePath(htmlFilePath, screenshot.FilePath);
|
||
html.AppendLine("<div class='screenshot-container'>");
|
||
html.AppendLine($"<img src=\"{relativePath}\" alt=\"碰撞场景截图\" class=\"screenshot-image\"/>");
|
||
html.AppendLine("<div class='screenshot-info'>");
|
||
html.AppendLine($"<p>分辨率: {screenshot.Width} x {screenshot.Height}</p>");
|
||
html.AppendLine($"<p>格式: {screenshot.Format}</p>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</div>");
|
||
html.AppendLine("</div>");
|
||
}
|
||
}
|
||
|
||
// 运动构件信息
|
||
if (!string.IsNullOrEmpty(report.MovingObjectInfo))
|
||
{
|
||
html.AppendLine("<h2>运动构件信息</h2>");
|
||
html.AppendLine("<div class='moving-object'>");
|
||
html.AppendLine($"<strong>🚛 {report.MovingObjectInfo}</strong>");
|
||
html.AppendLine("</div>");
|
||
}
|
||
|
||
// 碰撞构件清单
|
||
if (report.CollidedObjectsList?.Count > 0)
|
||
{
|
||
html.AppendLine("<h2>碰撞构件清单</h2>");
|
||
html.AppendLine("<div class='collided-list'>");
|
||
html.AppendLine($"<p style='margin: 0 0 10px 0; color: #721c24;'><strong>⚠️ 发现 {report.UniqueCollidedObjectsCount} 个碰撞构件</strong></p>");
|
||
int index = 1;
|
||
foreach (var objName in report.CollidedObjectsList.Take(50)) // 限制显示前50个
|
||
{
|
||
html.AppendLine($"<div class='list-item'>{index}. {objName}</div>");
|
||
index++;
|
||
}
|
||
if (report.CollidedObjectsList.Count > 50)
|
||
{
|
||
html.AppendLine($"<div class='list-item'><em>... 还有 {report.CollidedObjectsList.Count - 50} 个构件</em></div>");
|
||
}
|
||
html.AppendLine("</div>");
|
||
}
|
||
|
||
// 排除对象清单
|
||
if (report.ExcludedObjects?.Count > 0)
|
||
{
|
||
html.AppendLine("<h2>排除对象清单</h2>");
|
||
html.AppendLine("<div class='excluded-list'>");
|
||
html.AppendLine($"<p style='margin: 0 0 10px 0; color: #856404;'><strong>🚫 以下 {report.ExcludedObjects.Count} 个对象被排除在碰撞检测之外</strong></p>");
|
||
int index = 1;
|
||
foreach (var excludedObj in report.ExcludedObjects.Take(30)) // 限制显示前30个
|
||
{
|
||
string displayName = !string.IsNullOrEmpty(excludedObj.DisplayName) ? excludedObj.DisplayName : excludedObj.ObjectName ?? "未知对象";
|
||
string reason = !string.IsNullOrEmpty(excludedObj.Reason) ? $"原因: {excludedObj.Reason}" : "无";
|
||
string time = excludedObj.ExcludedTime > DateTime.MinValue ? $"时间: {excludedObj.ExcludedTime:yyyy-MM-dd HH:mm}" : "";
|
||
html.AppendLine($"<div class='list-item'>");
|
||
html.AppendLine($"<strong>{index}. {displayName}</strong>");
|
||
html.AppendLine($"<span style='color: #856404; font-size: 11px; margin-left: 10px;'>({reason}{(!string.IsNullOrEmpty(time) ? " | " + time : "")})</span>");
|
||
html.AppendLine("</div>");
|
||
index++;
|
||
}
|
||
if (report.ExcludedObjects.Count > 30)
|
||
{
|
||
html.AppendLine($"<div class='list-item'><em>... 还有 {report.ExcludedObjects.Count - 30} 个排除对象</em></div>");
|
||
}
|
||
html.AppendLine("</div>");
|
||
}
|
||
|
||
// 总结与建议
|
||
html.AppendLine("<h2>总结与建议</h2>");
|
||
html.AppendLine("<div class='recommendation'>");
|
||
|
||
// 根据碰撞数量生成总结信息
|
||
string summaryMessage;
|
||
if (report.TotalCollisions == 0)
|
||
{
|
||
summaryMessage = "✅ 未检测到碰撞,路径规划合理,可以安全通行。";
|
||
}
|
||
else if (report.TotalCollisions <= 5)
|
||
{
|
||
summaryMessage = $"⚠️ 检测到 {report.TotalCollisions} 个碰撞,建议优化路径或调整构件位置。";
|
||
}
|
||
else
|
||
{
|
||
summaryMessage = $"🔴 检测到 {report.TotalCollisions} 个碰撞,存在严重安全隐患,必须立即处理。";
|
||
}
|
||
|
||
html.AppendLine($"<p><strong>{summaryMessage}</strong></p>");
|
||
|
||
// 生成建议措施
|
||
html.AppendLine("<p><strong>建议措施:</strong></p>");
|
||
html.AppendLine("<ul>");
|
||
|
||
if (report.TotalCollisions == 0)
|
||
{
|
||
html.AppendLine("<li>保持当前路径规划方案</li>");
|
||
html.AppendLine("<li>定期检查构件位置变化</li>");
|
||
html.AppendLine("<li>建议进行现场复核确认</li>");
|
||
}
|
||
else
|
||
{
|
||
html.AppendLine("<li>检查碰撞构件的实际位置和尺寸</li>");
|
||
html.AppendLine("<li>优化路径规划,避开碰撞区域</li>");
|
||
html.AppendLine("<li>调整构件位置或尺寸</li>");
|
||
html.AppendLine("<li>考虑增加安全间隙</li>");
|
||
html.AppendLine("<li>进行现场勘察确认</li>");
|
||
}
|
||
|
||
html.AppendLine("</ul>");
|
||
html.AppendLine("</div>");
|
||
|
||
// 详细碰撞信息(前10个)
|
||
if (report.AllCollisions?.Count > 0)
|
||
{
|
||
html.AppendLine("<h2>碰撞详情</h2>");
|
||
int collisionIndex = 1;
|
||
foreach (var collision in report.AllCollisions.Take(10))
|
||
{
|
||
html.AppendLine("<div class='collision-item'>");
|
||
|
||
// 生成碰撞标题
|
||
string item1Name = collision.Item1 != null ? ModelItemAnalysisHelper.GetSafeDisplayName(collision.Item1) : "未知对象";
|
||
string item2Name = collision.Item2 != null ? ModelItemAnalysisHelper.GetSafeDisplayName(collision.Item2) : "未知对象";
|
||
html.AppendLine($"<div class='collision-title'>{collisionIndex}. {item1Name} ↔ {item2Name}</div>");
|
||
|
||
// 全路径
|
||
string item1Path = GetModelItemFullPath(collision.Item1);
|
||
string item2Path = GetModelItemFullPath(collision.Item2);
|
||
html.AppendLine($"<p style='font-size: 11px; color: #666; margin: 3px 0;'>🚛 <strong>运动物体:</strong> {item1Path}</p>");
|
||
html.AppendLine($"<p style='font-size: 11px; color: #666; margin: 3px 0;'>💥 <strong>被撞对象:</strong> {item2Path}</p>");
|
||
|
||
// 碰撞位置
|
||
if (collision.Center != null)
|
||
{
|
||
html.AppendLine($"<p style='font-size: 11px; color: #999; margin: 3px 0;'><strong>位置:</strong> ({collision.Center.X:F2}, {collision.Center.Y:F2}, {collision.Center.Z:F2})</p>");
|
||
}
|
||
|
||
html.AppendLine("</div>");
|
||
collisionIndex++;
|
||
}
|
||
if (report.AllCollisions.Count > 10)
|
||
{
|
||
html.AppendLine($"<p><em>... 还有 {report.AllCollisions.Count - 10} 个碰撞未显示</em></p>");
|
||
}
|
||
}
|
||
|
||
// HTML结尾
|
||
html.AppendLine($"<hr style='margin: 30px 0;'>");
|
||
html.AppendLine($"<p style='text-align: center; color: #999; font-size: 12px;'>报告生成完成 - {now:HH:mm:ss}</p>");
|
||
html.AppendLine("</body></html>");
|
||
|
||
return html.ToString();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存HTML报告到文件
|
||
/// </summary>
|
||
/// <param name="report">碰撞报告结果</param>
|
||
/// <param name="htmlFilePath">HTML文件保存路径</param>
|
||
/// <returns>是否保存成功</returns>
|
||
public static bool SaveHtmlReport(CollisionReportResult report, string htmlFilePath)
|
||
{
|
||
try
|
||
{
|
||
// 确保目录存在
|
||
string directory = Path.GetDirectoryName(htmlFilePath);
|
||
if (!string.IsNullOrEmpty(directory))
|
||
{
|
||
PathHelper.EnsureDirectoryExists(directory);
|
||
}
|
||
|
||
// 生成HTML内容
|
||
string htmlContent = GenerateHtmlReport(report, htmlFilePath);
|
||
|
||
// 保存到文件
|
||
File.WriteAllText(htmlFilePath, htmlContent, System.Text.Encoding.UTF8);
|
||
|
||
LogManager.Info($"HTML报告已保存: {htmlFilePath}");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"保存HTML报告失败: {ex.Message}", ex);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取ModelItem的完整层级路径
|
||
/// </summary>
|
||
private static string GetModelItemFullPath(ModelItem item)
|
||
{
|
||
if (item == null) return "未知对象";
|
||
|
||
try
|
||
{
|
||
var pathParts = new List<string>();
|
||
var current = item;
|
||
int levels = 0;
|
||
|
||
while (current != null && levels < 20)
|
||
{
|
||
var name = ModelItemAnalysisHelper.GetSafeDisplayName(current);
|
||
if (!string.IsNullOrEmpty(name) && name != "未命名对象")
|
||
{
|
||
pathParts.Insert(0, name);
|
||
}
|
||
current = current.Parent;
|
||
levels++;
|
||
}
|
||
|
||
return pathParts.Count > 0 ? string.Join(" > ", pathParts) : "未知对象";
|
||
}
|
||
catch
|
||
{
|
||
return ModelItemAnalysisHelper.GetSafeDisplayName(item);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自动生成并保存HTML报告到默认目录
|
||
/// </summary>
|
||
/// <param name="report">碰撞报告结果</param>
|
||
/// <returns>HTML文件路径,失败返回null</returns>
|
||
public static string AutoSaveHtmlReport(CollisionReportResult report)
|
||
{
|
||
try
|
||
{
|
||
// 生成文件名
|
||
string sanitizedName = PathHelper.SanitizeFileName(report.PathName ?? "未知路径");
|
||
string fileName = PathHelper.GenerateTimestampedFileName($"collision_{sanitizedName}", "html");
|
||
|
||
// 获取报告目录
|
||
string reportDir = PathHelper.GetReportDirectory();
|
||
string htmlFilePath = Path.Combine(reportDir, fileName);
|
||
|
||
// 保存报告
|
||
if (SaveHtmlReport(report, htmlFilePath))
|
||
{
|
||
return htmlFilePath;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"自动保存HTML报告失败: {ex.Message}", ex);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从数据库获取检测记录信息
|
||
/// </summary>
|
||
private static (string testName, string testTime) GetDetectionRecordInfo(int resultId)
|
||
{
|
||
try
|
||
{
|
||
if (resultId <= 0)
|
||
{
|
||
return (null, "未知时间");
|
||
}
|
||
|
||
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
|
||
if (pathDatabase == null)
|
||
{
|
||
return (null, "未知时间");
|
||
}
|
||
|
||
var record = pathDatabase.GetDetectionResultById(resultId);
|
||
if (record != null)
|
||
{
|
||
string timeStr = record.TestTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? "未知时间";
|
||
return (record.TestName, timeStr);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[CollisionReportHtmlGenerator] 获取检测记录信息失败: {ex.Message}");
|
||
}
|
||
|
||
return (null, "未知时间");
|
||
}
|
||
}
|
||
}
|