923 lines
35 KiB
C#
923 lines
35 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using NavisworksTransport.Core;
|
||
|
||
namespace NavisworksTransport.Commands
|
||
{
|
||
/// <summary>
|
||
/// 导出路径参数类
|
||
/// </summary>
|
||
public class ExportPathParameters
|
||
{
|
||
/// <summary>
|
||
/// 要导出的路径集合
|
||
/// </summary>
|
||
public List<PathRoute> PathsToExport { get; set; }
|
||
|
||
/// <summary>
|
||
/// 路径ID集合(作为PathsToExport的替代)
|
||
/// </summary>
|
||
public List<string> PathIds { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否导出所有路径
|
||
/// </summary>
|
||
public bool ExportAll { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 导出文件路径
|
||
/// </summary>
|
||
public string OutputFilePath { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导出格式
|
||
/// </summary>
|
||
public ExportFormat ExportFormat { get; set; } = ExportFormat.Xml;
|
||
|
||
/// <summary>
|
||
/// 导出设置
|
||
/// </summary>
|
||
public ExportSettings ExportSettings { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否覆盖现有文件
|
||
/// </summary>
|
||
public bool OverwriteExisting { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 是否验证导出数据
|
||
/// </summary>
|
||
public bool ValidateExportData { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 是否生成导出报告
|
||
/// </summary>
|
||
public bool GenerateReport { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 路径过滤条件(可选)
|
||
/// </summary>
|
||
public Func<PathRoute, bool> RouteFilter { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作描述
|
||
/// </summary>
|
||
public string Description { get; set; }
|
||
|
||
public ExportPathParameters()
|
||
{
|
||
PathsToExport = new List<PathRoute>();
|
||
PathIds = new List<string>();
|
||
ExportSettings = new ExportSettings();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证参数有效性
|
||
/// </summary>
|
||
public PathPlanningResult ValidateParameters()
|
||
{
|
||
var errors = new List<string>();
|
||
|
||
if (!ExportAll)
|
||
{
|
||
if ((PathsToExport == null || PathsToExport.Count == 0) &&
|
||
(PathIds == null || PathIds.Count == 0))
|
||
{
|
||
errors.Add("必须指定要导出的路径或路径ID,或设置ExportAll为true");
|
||
}
|
||
|
||
// 检查路径有效性
|
||
if (PathsToExport != null)
|
||
{
|
||
foreach (var path in PathsToExport)
|
||
{
|
||
if (path == null)
|
||
{
|
||
errors.Add("路径集合包含空引用");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 检查路径ID有效性
|
||
if (PathIds != null)
|
||
{
|
||
foreach (var id in PathIds)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(id))
|
||
{
|
||
errors.Add("路径ID集合包含空或无效的ID");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(OutputFilePath))
|
||
{
|
||
errors.Add("导出文件路径不能为空");
|
||
}
|
||
else
|
||
{
|
||
// 检查目录是否存在
|
||
var directory = Path.GetDirectoryName(OutputFilePath);
|
||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||
{
|
||
try
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
errors.Add($"无法创建导出目录: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// 检查文件是否存在且不允许覆盖
|
||
if (!OverwriteExisting && File.Exists(OutputFilePath))
|
||
{
|
||
errors.Add($"导出文件已存在且不允许覆盖: {OutputFilePath}");
|
||
}
|
||
|
||
// 检查文件扩展名与格式是否匹配
|
||
var extension = Path.GetExtension(OutputFilePath).ToLower();
|
||
string[] expectedExtensions;
|
||
switch (ExportFormat)
|
||
{
|
||
case ExportFormat.Json:
|
||
expectedExtensions = new[] { ".json" };
|
||
break;
|
||
case ExportFormat.Csv:
|
||
expectedExtensions = new[] { ".csv" };
|
||
break;
|
||
default:
|
||
expectedExtensions = new[] { ".xml" };
|
||
break;
|
||
}
|
||
|
||
if (!expectedExtensions.Contains(extension))
|
||
{
|
||
errors.Add($"文件扩展名 '{extension}' 与导出格式 '{ExportFormat}' 不匹配");
|
||
}
|
||
}
|
||
|
||
if (!Enum.IsDefined(typeof(ExportFormat), ExportFormat))
|
||
{
|
||
errors.Add("无效的导出格式");
|
||
}
|
||
|
||
if (errors.Count > 0)
|
||
{
|
||
return PathPlanningResult.ValidationFailure($"参数验证失败: {string.Join("; ", errors)}");
|
||
}
|
||
|
||
return PathPlanningResult.Success("参数验证通过");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出路径结果类
|
||
/// </summary>
|
||
public class ExportPathResult
|
||
{
|
||
/// <summary>
|
||
/// 成功导出的路径数量
|
||
/// </summary>
|
||
public int ExportedCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 失败的路径数量
|
||
/// </summary>
|
||
public int FailedCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 跳过的路径数量
|
||
/// </summary>
|
||
public int SkippedCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 总路径数量
|
||
/// </summary>
|
||
public int TotalCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 已导出的路径信息
|
||
/// </summary>
|
||
public List<string> ExportedPaths { get; set; }
|
||
|
||
/// <summary>
|
||
/// 失败的路径信息
|
||
/// </summary>
|
||
public List<string> FailedPaths { get; set; }
|
||
|
||
/// <summary>
|
||
/// 跳过的路径信息
|
||
/// </summary>
|
||
public List<string> SkippedPaths { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导出文件路径
|
||
/// </summary>
|
||
public string OutputFilePath { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导出格式
|
||
/// </summary>
|
||
public ExportFormat ExportFormat { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导出文件大小(字节)
|
||
/// </summary>
|
||
public long FileSizeBytes { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导出报告文件路径(如果生成了报告)
|
||
/// </summary>
|
||
public string ReportFilePath { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作执行时间(毫秒)
|
||
/// </summary>
|
||
public long ExecutionTimeMs { get; set; }
|
||
|
||
public ExportPathResult()
|
||
{
|
||
ExportedPaths = new List<string>();
|
||
FailedPaths = new List<string>();
|
||
SkippedPaths = new List<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出成功率
|
||
/// </summary>
|
||
public double ExportSuccessRate => TotalCount > 0 ? (double)ExportedCount / TotalCount : 0.0;
|
||
|
||
/// <summary>
|
||
/// 文件大小(MB)
|
||
/// </summary>
|
||
public double FileSizeMB => FileSizeBytes / 1024.0 / 1024.0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出路径Command
|
||
/// </summary>
|
||
public class ExportPathCommand : CommandBase
|
||
{
|
||
#region 字段和属性
|
||
|
||
private readonly ExportPathParameters _parameters;
|
||
private readonly PathPlanningManager _pathPlanningManager;
|
||
private readonly UIStateManager _uiStateManager;
|
||
private readonly PathDataManager _pathDataManager;
|
||
|
||
/// <summary>
|
||
/// 命令参数
|
||
/// </summary>
|
||
public ExportPathParameters Parameters => _parameters;
|
||
|
||
#endregion
|
||
|
||
#region 构造函数
|
||
|
||
/// <summary>
|
||
/// 初始化导出路径命令
|
||
/// </summary>
|
||
/// <param name="parameters">导出参数</param>
|
||
/// <param name="pathPlanningManager">路径规划管理器</param>
|
||
public ExportPathCommand(ExportPathParameters parameters, PathPlanningManager pathPlanningManager = null)
|
||
: base("ExportPath", "导出路径", "将路径规划数据导出到文件")
|
||
{
|
||
_parameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
|
||
_pathPlanningManager = pathPlanningManager ?? throw new ArgumentNullException(nameof(pathPlanningManager));
|
||
_uiStateManager = UIStateManager.Instance;
|
||
_pathDataManager = new PathDataManager();
|
||
|
||
LogInfo("导出路径命令初始化完成");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region CommandBase实现
|
||
|
||
/// <summary>
|
||
/// 验证命令参数
|
||
/// </summary>
|
||
protected override PathPlanningResult ValidateParameters()
|
||
{
|
||
LogInfo("开始验证导出路径参数");
|
||
|
||
try
|
||
{
|
||
// 验证基础参数
|
||
var basicValidation = _parameters.ValidateParameters();
|
||
if (!basicValidation.IsSuccess)
|
||
{
|
||
LogWarning($"基础参数验证失败: {basicValidation.ErrorMessage}");
|
||
return basicValidation;
|
||
}
|
||
|
||
// 验证PathPlanningManager状态
|
||
if (_pathPlanningManager == null)
|
||
{
|
||
return PathPlanningResult.ValidationFailure("路径规划管理器未初始化");
|
||
}
|
||
|
||
// 检查是否有路径可导出
|
||
if (!_parameters.ExportAll && _pathPlanningManager.Routes.Count == 0)
|
||
{
|
||
return PathPlanningResult.ValidationFailure("当前没有可导出的路径");
|
||
}
|
||
|
||
// 如果指定了路径ID,验证ID是否存在
|
||
if (_parameters.PathIds.Count > 0)
|
||
{
|
||
var availableIds = _pathPlanningManager.Routes.Select(r => r.Id).ToHashSet();
|
||
var invalidIds = _parameters.PathIds.Where(id => !availableIds.Contains(id)).ToList();
|
||
|
||
if (invalidIds.Count > 0)
|
||
{
|
||
LogWarning($"发现无效的路径ID: {string.Join(", ", invalidIds)}");
|
||
// 不阻止执行,只是警告
|
||
}
|
||
}
|
||
|
||
LogInfo("参数验证通过");
|
||
return PathPlanningResult.Success("所有参数验证通过");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogError("参数验证过程中发生异常", ex);
|
||
return PathPlanningResult.ValidationFailure($"验证过程异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行导出路径的核心逻辑
|
||
/// </summary>
|
||
protected override async Task<PathPlanningResult> ExecuteInternalAsync(CancellationToken cancellationToken)
|
||
{
|
||
LogInfo("开始执行导出路径");
|
||
var startTime = DateTime.UtcNow;
|
||
|
||
try
|
||
{
|
||
// 第一阶段:初始化(10%)
|
||
UpdateProgress(10, "正在初始化导出操作...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 更新UI状态
|
||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||
{
|
||
LogInfo("UI状态更新:路径导出进行中");
|
||
});
|
||
|
||
var result = new ExportPathResult
|
||
{
|
||
OutputFilePath = _parameters.OutputFilePath,
|
||
ExportFormat = _parameters.ExportFormat
|
||
};
|
||
|
||
// 第二阶段:收集要导出的路径(20%)
|
||
UpdateProgress(20, "正在收集要导出的路径...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
var pathsToExport = await Task.Run(() => CollectPathsToExport(), cancellationToken);
|
||
|
||
if (pathsToExport.Count == 0)
|
||
{
|
||
LogWarning("没有找到需要导出的路径");
|
||
return PathPlanningResult.Success("没有找到需要导出的路径");
|
||
}
|
||
|
||
LogInfo($"收集到 {pathsToExport.Count} 个路径待导出");
|
||
result.TotalCount = pathsToExport.Count;
|
||
|
||
// 第三阶段:验证导出数据(30%)
|
||
if (_parameters.ValidateExportData)
|
||
{
|
||
UpdateProgress(30, "正在验证导出数据...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
await Task.Run(() => ValidateExportData(pathsToExport, result), cancellationToken);
|
||
}
|
||
|
||
// 第四阶段:执行导出操作(40% - 80%)
|
||
UpdateProgress(40, "正在导出路径数据...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
bool exportSuccess = await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
LogInfo("开始执行路径数据导出");
|
||
|
||
// 确保导出目录存在
|
||
var directory = Path.GetDirectoryName(_parameters.OutputFilePath);
|
||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
LogInfo($"已创建导出目录: {directory}");
|
||
}
|
||
|
||
UpdateProgress(50, "正在写入导出文件...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 执行实际的导出操作
|
||
bool success;
|
||
if (_parameters.ExportFormat == ExportFormat.Json)
|
||
{
|
||
success = _pathDataManager.ExportToJson(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
|
||
}
|
||
else if (_parameters.ExportFormat == ExportFormat.Xml)
|
||
{
|
||
success = _pathDataManager.ExportToXml(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
|
||
}
|
||
else if (_parameters.ExportFormat == ExportFormat.Csv)
|
||
{
|
||
success = _pathDataManager.ExportToCsv(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
|
||
}
|
||
else
|
||
{
|
||
// DELMIA格式
|
||
success = _pathDataManager.ExportDelmiaFormat(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
|
||
}
|
||
|
||
UpdateProgress(70, "正在验证导出文件...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
if (success && File.Exists(_parameters.OutputFilePath))
|
||
{
|
||
// 获取文件大小
|
||
var fileInfo = new FileInfo(_parameters.OutputFilePath);
|
||
result.FileSizeBytes = fileInfo.Length;
|
||
|
||
// 更新成功统计
|
||
result.ExportedCount = pathsToExport.Count;
|
||
foreach (var path in pathsToExport)
|
||
{
|
||
result.ExportedPaths.Add($"{path.Name} ({path.Points.Count} 个点)");
|
||
}
|
||
|
||
LogInfo($"导出成功: {result.ExportedCount} 个路径,文件大小: {result.FileSizeMB:F2} MB");
|
||
}
|
||
else
|
||
{
|
||
result.FailedCount = pathsToExport.Count;
|
||
foreach (var path in pathsToExport)
|
||
{
|
||
result.FailedPaths.Add($"{path.Name} - 导出失败");
|
||
}
|
||
LogError("路径导出失败:文件未生成或导出方法返回失败");
|
||
}
|
||
|
||
return success;
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
LogInfo("路径导出被用户取消");
|
||
throw; // 重新抛出取消异常
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogError("导出路径数据时发生异常", ex);
|
||
|
||
// 记录失败信息
|
||
result.FailedCount = pathsToExport.Count;
|
||
foreach (var path in pathsToExport)
|
||
{
|
||
result.FailedPaths.Add($"{path.Name} - 异常: {ex.Message}");
|
||
}
|
||
|
||
throw;
|
||
}
|
||
}, cancellationToken);
|
||
|
||
UpdateProgress(85, "正在完成导出操作...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 第五阶段:生成导出报告(90%)
|
||
if (_parameters.GenerateReport && result.ExportedCount > 0)
|
||
{
|
||
UpdateProgress(90, "正在生成导出报告...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
try
|
||
{
|
||
result.ReportFilePath = await GenerateExportReportAsync(result, pathsToExport, cancellationToken);
|
||
LogInfo($"导出报告已生成: {result.ReportFilePath}");
|
||
}
|
||
catch (Exception reportEx)
|
||
{
|
||
LogWarning($"生成导出报告失败: {reportEx.Message}");
|
||
// 报告生成失败不影响主要导出功能
|
||
}
|
||
}
|
||
|
||
// 第六阶段:验证导出文件(95%)
|
||
if (exportSuccess && _parameters.ValidateExportData)
|
||
{
|
||
UpdateProgress(95, "正在验证导出文件...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
try
|
||
{
|
||
var validationResult = _pathDataManager.ValidateExportFile(_parameters.OutputFilePath, _parameters.ExportFormat);
|
||
if (!validationResult.IsValid)
|
||
{
|
||
LogWarning($"导出文件验证失败: {string.Join("; ", validationResult.Errors)}");
|
||
}
|
||
else if (validationResult.Warnings.Count > 0)
|
||
{
|
||
LogWarning($"导出文件验证警告: {string.Join("; ", validationResult.Warnings)}");
|
||
}
|
||
else
|
||
{
|
||
LogInfo("导出文件验证成功");
|
||
}
|
||
}
|
||
catch (Exception validateEx)
|
||
{
|
||
LogWarning($"导出文件验证失败: {validateEx.Message}");
|
||
}
|
||
}
|
||
|
||
// 完成(100%)
|
||
UpdateProgress(100, "路径导出完成");
|
||
|
||
var elapsedMs = (DateTime.UtcNow - startTime).TotalMilliseconds;
|
||
result.ExecutionTimeMs = (long)elapsedMs;
|
||
|
||
LogInfo($"导出路径执行完成,总耗时: {elapsedMs:F0}ms");
|
||
LogInfo($"导出结果 - 总数: {result.TotalCount}, 导出: {result.ExportedCount}, 失败: {result.FailedCount}, 跳过: {result.SkippedCount}");
|
||
|
||
// 创建结果对象
|
||
string resultMessage;
|
||
if (result.TotalCount == 0)
|
||
{
|
||
resultMessage = "没有找到需要导出的路径";
|
||
}
|
||
else if (result.ExportedCount == result.TotalCount)
|
||
{
|
||
resultMessage = $"路径导出完成:成功导出 {result.ExportedCount} 个路径到 {Path.GetFileName(result.OutputFilePath)}";
|
||
}
|
||
else
|
||
{
|
||
resultMessage = $"路径导出部分完成:导出 {result.ExportedCount}/{result.TotalCount} 项";
|
||
if (result.FailedCount > 0)
|
||
{
|
||
resultMessage += $",失败 {result.FailedCount} 项";
|
||
}
|
||
if (result.SkippedCount > 0)
|
||
{
|
||
resultMessage += $",跳过 {result.SkippedCount} 项";
|
||
}
|
||
}
|
||
|
||
var commandResult = PathPlanningResult<ExportPathResult>.Success(result, resultMessage);
|
||
commandResult.ElapsedMilliseconds = (long)elapsedMs;
|
||
return commandResult;
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
LogInfo("导出路径被用户取消");
|
||
throw; // 让基类处理取消异常
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var elapsedMs = (DateTime.UtcNow - startTime).TotalMilliseconds;
|
||
LogError($"导出路径执行失败,已耗时: {elapsedMs:F0}ms", ex);
|
||
|
||
// 尝试恢复UI状态
|
||
try
|
||
{
|
||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||
{
|
||
LogInfo("尝试恢复UI状态");
|
||
});
|
||
}
|
||
catch (Exception uiEx)
|
||
{
|
||
LogError("UI状态恢复失败", uiEx);
|
||
}
|
||
|
||
return PathPlanningResult.Failure($"导出路径失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 私有辅助方法
|
||
|
||
/// <summary>
|
||
/// 收集要导出的路径
|
||
/// </summary>
|
||
private List<PathRoute> CollectPathsToExport()
|
||
{
|
||
var pathsToExport = new List<PathRoute>();
|
||
|
||
if (_parameters.ExportAll)
|
||
{
|
||
// 导出所有路径
|
||
pathsToExport.AddRange(_pathPlanningManager.Routes);
|
||
LogInfo($"收集所有路径进行导出:{pathsToExport.Count} 个");
|
||
}
|
||
else
|
||
{
|
||
// 从直接指定的路径收集
|
||
if (_parameters.PathsToExport != null)
|
||
{
|
||
pathsToExport.AddRange(_parameters.PathsToExport.Where(p => p != null));
|
||
}
|
||
|
||
// 从路径ID收集
|
||
if (_parameters.PathIds != null && _parameters.PathIds.Count > 0)
|
||
{
|
||
var availableRoutes = _pathPlanningManager.Routes.ToLookup(r => r.Id);
|
||
foreach (var pathId in _parameters.PathIds.Where(id => !string.IsNullOrWhiteSpace(id)))
|
||
{
|
||
var routes = availableRoutes[pathId];
|
||
pathsToExport.AddRange(routes);
|
||
}
|
||
}
|
||
|
||
// 去重
|
||
pathsToExport = pathsToExport.Distinct().ToList();
|
||
LogInfo($"收集指定路径进行导出:{pathsToExport.Count} 个");
|
||
}
|
||
|
||
// 应用过滤器
|
||
if (_parameters.RouteFilter != null)
|
||
{
|
||
var originalCount = pathsToExport.Count;
|
||
pathsToExport = pathsToExport.Where(_parameters.RouteFilter).ToList();
|
||
LogInfo($"过滤后剩余 {pathsToExport.Count} 个路径(原始 {originalCount} 个)");
|
||
}
|
||
|
||
return pathsToExport;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证导出数据
|
||
/// </summary>
|
||
private void ValidateExportData(List<PathRoute> routes, ExportPathResult result)
|
||
{
|
||
LogInfo("开始验证导出数据");
|
||
|
||
var invalidRoutes = new List<PathRoute>();
|
||
foreach (var route in routes)
|
||
{
|
||
try
|
||
{
|
||
// 使用PathPlanningManager的验证方法
|
||
var validationResult = _pathPlanningManager.ValidateRoute(route);
|
||
if (!validationResult.IsSuccess)
|
||
{
|
||
invalidRoutes.Add(route);
|
||
result.FailedPaths.Add($"{route.Name} - 验证失败: {validationResult.ErrorMessage}");
|
||
LogWarning($"路径验证失败: {route.Name} - {validationResult.ErrorMessage}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
invalidRoutes.Add(route);
|
||
result.FailedPaths.Add($"{route.Name} - 验证异常: {ex.Message}");
|
||
LogError($"验证路径时发生异常: {route.Name}", ex);
|
||
}
|
||
}
|
||
|
||
// 从导出列表中移除无效路径
|
||
foreach (var invalidRoute in invalidRoutes)
|
||
{
|
||
routes.Remove(invalidRoute);
|
||
result.FailedCount++;
|
||
}
|
||
|
||
LogInfo($"导出数据验证完成,有效路径: {routes.Count}, 无效路径: {invalidRoutes.Count}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成导出报告
|
||
/// </summary>
|
||
private async Task<string> GenerateExportReportAsync(ExportPathResult result, List<PathRoute> exportedRoutes, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
var reportFileName = Path.GetFileNameWithoutExtension(_parameters.OutputFilePath) + "_导出报告.html";
|
||
var reportFilePath = Path.Combine(Path.GetDirectoryName(_parameters.OutputFilePath), reportFileName);
|
||
|
||
var reportContent = await Task.Run(() => GenerateHtmlReport(result, exportedRoutes), cancellationToken);
|
||
|
||
await Task.Run(() => File.WriteAllText(reportFilePath, reportContent, System.Text.Encoding.UTF8), cancellationToken);
|
||
|
||
return reportFilePath;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogError("生成导出报告失败", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成HTML报告内容
|
||
/// </summary>
|
||
private string GenerateHtmlReport(ExportPathResult result, List<PathRoute> exportedRoutes)
|
||
{
|
||
var html = $@"
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>路径导出报告</title>
|
||
<meta charset='utf-8'>
|
||
<style>
|
||
body {{ font-family: 'Microsoft YaHei', Arial, sans-serif; margin: 20px; }}
|
||
.header {{ background-color: #f0f0f0; padding: 15px; border-radius: 5px; }}
|
||
.summary {{ margin: 20px 0; }}
|
||
.results {{ margin-top: 20px; }}
|
||
table {{ border-collapse: collapse; width: 100%; }}
|
||
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
|
||
th {{ background-color: #f2f2f2; }}
|
||
.success {{ color: green; }}
|
||
.error {{ color: red; }}
|
||
.warning {{ color: orange; }}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class='header'>
|
||
<h1>路径导出报告</h1>
|
||
<p>生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}</p>
|
||
<p>导出文件: {Path.GetFileName(result.OutputFilePath)}</p>
|
||
<p>导出格式: {result.ExportFormat}</p>
|
||
<p>文件大小: {result.FileSizeMB:F2} MB</p>
|
||
</div>
|
||
|
||
<div class='summary'>
|
||
<h2>汇总信息</h2>
|
||
<p>总路径数: {result.TotalCount}</p>
|
||
<p>成功导出: <span class='success'>{result.ExportedCount}</span></p>
|
||
<p>导出失败: <span class='error'>{result.FailedCount}</span></p>
|
||
<p>跳过路径: <span class='warning'>{result.SkippedCount}</span></p>
|
||
<p>成功率: <span class='{(result.ExportSuccessRate >= 0.9 ? "success" : result.ExportSuccessRate >= 0.7 ? "warning" : "error")}'>{result.ExportSuccessRate:P2}</span></p>
|
||
<p>导出耗时: {result.ExecutionTimeMs} ms</p>
|
||
</div>
|
||
|
||
<div class='results'>
|
||
<h2>详细路径信息</h2>
|
||
<table>
|
||
<tr>
|
||
<th>路径名称</th>
|
||
<th>路径点数</th>
|
||
<th>路径长度(m)</th>
|
||
<th>创建时间</th>
|
||
<th>状态</th>
|
||
</tr>";
|
||
|
||
foreach (var route in exportedRoutes)
|
||
{
|
||
var status = result.ExportedPaths.Any(ep => ep.StartsWith(route.Name)) ?
|
||
"<span class='success'>成功导出</span>" :
|
||
"<span class='error'>导出失败</span>";
|
||
|
||
html += $@"
|
||
<tr>
|
||
<td>{route.Name}</td>
|
||
<td>{route.Points.Count}</td>
|
||
<td>{route.TotalLength:F2}</td>
|
||
<td>{route.CreatedTime:yyyy-MM-dd HH:mm:ss}</td>
|
||
<td>{status}</td>
|
||
</tr>";
|
||
}
|
||
|
||
html += @"
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>";
|
||
|
||
return html;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 公共方法
|
||
|
||
/// <summary>
|
||
/// 创建导出所有路径到XML的快捷命令
|
||
/// </summary>
|
||
/// <param name="outputFilePath">输出文件路径</param>
|
||
/// <param name="overwriteExisting">是否覆盖现有文件</param>
|
||
/// <returns>导出路径命令实例</returns>
|
||
public static ExportPathCommand CreateXmlExportAll(string outputFilePath, bool overwriteExisting = false)
|
||
{
|
||
var parameters = new ExportPathParameters
|
||
{
|
||
ExportAll = true,
|
||
OutputFilePath = outputFilePath,
|
||
ExportFormat = ExportFormat.Xml,
|
||
OverwriteExisting = overwriteExisting,
|
||
ValidateExportData = true,
|
||
GenerateReport = false,
|
||
Description = $"导出所有路径到XML: {Path.GetFileName(outputFilePath)}"
|
||
};
|
||
|
||
return new ExportPathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建导出指定路径的快捷命令
|
||
/// </summary>
|
||
/// <param name="pathsToExport">要导出的路径</param>
|
||
/// <param name="outputFilePath">输出文件路径</param>
|
||
/// <param name="exportFormat">导出格式</param>
|
||
/// <returns>导出路径命令实例</returns>
|
||
public static ExportPathCommand CreateSpecificExport(List<PathRoute> pathsToExport, string outputFilePath, ExportFormat exportFormat = ExportFormat.Xml)
|
||
{
|
||
var parameters = new ExportPathParameters
|
||
{
|
||
PathsToExport = pathsToExport ?? new List<PathRoute>(),
|
||
OutputFilePath = outputFilePath,
|
||
ExportFormat = exportFormat,
|
||
OverwriteExisting = true,
|
||
ValidateExportData = true,
|
||
GenerateReport = false,
|
||
Description = $"导出 {pathsToExport?.Count ?? 0} 个路径到 {exportFormat}: {Path.GetFileName(outputFilePath)}"
|
||
};
|
||
|
||
return new ExportPathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建DELMIA格式导出命令
|
||
/// </summary>
|
||
/// <param name="outputFilePath">输出文件路径</param>
|
||
/// <param name="exportSettings">导出设置</param>
|
||
/// <returns>导出路径命令实例</returns>
|
||
public static ExportPathCommand CreateDelmiaExport(string outputFilePath, ExportSettings exportSettings = null)
|
||
{
|
||
var parameters = new ExportPathParameters
|
||
{
|
||
ExportAll = true,
|
||
OutputFilePath = outputFilePath,
|
||
ExportFormat = ExportFormat.Xml, // DELMIA使用XML格式
|
||
ExportSettings = exportSettings ?? new ExportSettings
|
||
{
|
||
ProjectName = "DELMIA路径规划",
|
||
Description = "导出到DELMIA兼容格式",
|
||
Units = "meters"
|
||
},
|
||
OverwriteExisting = true,
|
||
ValidateExportData = true,
|
||
GenerateReport = true,
|
||
Description = $"导出到DELMIA格式: {Path.GetFileName(outputFilePath)}"
|
||
};
|
||
|
||
return new ExportPathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建带过滤器的导出命令
|
||
/// </summary>
|
||
/// <param name="outputFilePath">输出文件路径</param>
|
||
/// <param name="routeFilter">路径过滤器</param>
|
||
/// <param name="exportFormat">导出格式</param>
|
||
/// <returns>导出路径命令实例</returns>
|
||
public static ExportPathCommand CreateWithFilter(string outputFilePath, Func<PathRoute, bool> routeFilter, ExportFormat exportFormat = ExportFormat.Xml)
|
||
{
|
||
var parameters = new ExportPathParameters
|
||
{
|
||
ExportAll = true,
|
||
OutputFilePath = outputFilePath,
|
||
ExportFormat = exportFormat,
|
||
RouteFilter = routeFilter,
|
||
OverwriteExisting = true,
|
||
ValidateExportData = true,
|
||
GenerateReport = false,
|
||
Description = $"带过滤器导出到 {exportFormat}: {Path.GetFileName(outputFilePath)}"
|
||
};
|
||
|
||
return new ExportPathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取命令执行摘要信息
|
||
/// </summary>
|
||
/// <returns>命令信息摘要</returns>
|
||
public string GetExecutionSummary()
|
||
{
|
||
var targetDescription = _parameters.ExportAll ? "所有路径" :
|
||
$"{_parameters.PathsToExport?.Count ?? 0} + {_parameters.PathIds?.Count ?? 0} 个路径";
|
||
|
||
return $"导出路径命令 - 目标:{targetDescription}, " +
|
||
$"文件:{Path.GetFileName(_parameters.OutputFilePath ?? "未指定")}, " +
|
||
$"格式:{_parameters.ExportFormat}, " +
|
||
$"覆盖:{_parameters.OverwriteExisting}, " +
|
||
$"状态:{Status}";
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |