655 lines
25 KiB
C#
655 lines
25 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using NavisworksTransport.Core;
|
||
using NavisworksTransport.PathPlanning;
|
||
using NavisworksTransport.Utils;
|
||
|
||
namespace NavisworksTransport.Commands
|
||
{
|
||
/// <summary>
|
||
/// 删除路径参数类
|
||
/// </summary>
|
||
public class DeletePathParameters
|
||
{
|
||
/// <summary>
|
||
/// 要删除的路径集合
|
||
/// </summary>
|
||
public List<PathRoute> PathsToDelete { get; set; }
|
||
|
||
/// <summary>
|
||
/// 路径ID集合(作为PathsToDelete的替代)
|
||
/// </summary>
|
||
public List<string> PathIds { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否删除所有路径
|
||
/// </summary>
|
||
public bool DeleteAll { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 是否创建删除前的备份
|
||
/// </summary>
|
||
public bool CreateBackup { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 删除确认回调函数
|
||
/// </summary>
|
||
public Func<PathRoute, bool> ConfirmDeleteCallback { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否强制删除(跳过确认)
|
||
/// </summary>
|
||
public bool ForceDelete { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 操作描述
|
||
/// </summary>
|
||
public string Description { get; set; }
|
||
|
||
public DeletePathParameters()
|
||
{
|
||
PathsToDelete = new List<PathRoute>();
|
||
PathIds = new List<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证参数有效性
|
||
/// </summary>
|
||
public PathPlanningResult ValidateParameters()
|
||
{
|
||
var errors = new List<string>();
|
||
|
||
if (!DeleteAll)
|
||
{
|
||
if ((PathsToDelete == null || PathsToDelete.Count == 0) &&
|
||
(PathIds == null || PathIds.Count == 0))
|
||
{
|
||
errors.Add("必须指定要删除的路径或路径ID,或设置DeleteAll为true");
|
||
}
|
||
|
||
// 检查路径有效性
|
||
if (PathsToDelete != null)
|
||
{
|
||
foreach (var path in PathsToDelete)
|
||
{
|
||
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 (errors.Count > 0)
|
||
{
|
||
return PathPlanningResult.ValidationFailure($"参数验证失败: {string.Join("; ", errors)}");
|
||
}
|
||
|
||
return PathPlanningResult.Success("参数验证通过");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除路径结果类
|
||
/// </summary>
|
||
public class DeletePathResult
|
||
{
|
||
/// <summary>
|
||
/// 成功删除的路径数量
|
||
/// </summary>
|
||
public int DeletedCount { 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> DeletedPaths { get; set; }
|
||
|
||
/// <summary>
|
||
/// 删除失败的路径信息
|
||
/// </summary>
|
||
public List<string> FailedPaths { get; set; }
|
||
|
||
/// <summary>
|
||
/// 备份文件路径(如果创建了备份)
|
||
/// </summary>
|
||
public string BackupFilePath { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作执行时间(毫秒)
|
||
/// </summary>
|
||
public long ExecutionTimeMs { get; set; }
|
||
|
||
public DeletePathResult()
|
||
{
|
||
DeletedPaths = new List<string>();
|
||
FailedPaths = new List<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除成功率
|
||
/// </summary>
|
||
public double DeleteSuccessRate => TotalCount > 0 ? (double)DeletedCount / TotalCount : 0.0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除路径Command
|
||
/// </summary>
|
||
public class DeletePathCommand : CommandBase
|
||
{
|
||
#region 字段和属性
|
||
|
||
private readonly DeletePathParameters _parameters;
|
||
private readonly PathPlanningManager _pathPlanningManager;
|
||
private readonly UIStateManager _uiStateManager;
|
||
|
||
/// <summary>
|
||
/// 命令参数
|
||
/// </summary>
|
||
public DeletePathParameters Parameters => _parameters;
|
||
|
||
#endregion
|
||
|
||
#region 构造函数
|
||
|
||
/// <summary>
|
||
/// 初始化删除路径命令
|
||
/// </summary>
|
||
/// <param name="parameters">删除参数</param>
|
||
/// <param name="pathPlanningManager">路径规划管理器</param>
|
||
public DeletePathCommand(DeletePathParameters parameters, PathPlanningManager pathPlanningManager = null)
|
||
: base("DeletePath", "删除路径", "删除指定的路径规划数据")
|
||
{
|
||
_parameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
|
||
_pathPlanningManager = pathPlanningManager ?? throw new ArgumentNullException(nameof(pathPlanningManager));
|
||
_uiStateManager = UIStateManager.Instance;
|
||
|
||
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.DeleteAll && _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状态更新:路径删除进行中");
|
||
});
|
||
|
||
// 第二阶段:收集要删除的路径(20%)
|
||
UpdateProgress(20, "正在收集要删除的路径...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
var pathsToDelete = await Task.Run(() => CollectPathsToDelete(), cancellationToken);
|
||
|
||
if (pathsToDelete.Count == 0)
|
||
{
|
||
LogWarning("没有找到需要删除的路径");
|
||
return PathPlanningResult.Success("没有找到需要删除的路径");
|
||
}
|
||
|
||
LogInfo($"收集到 {pathsToDelete.Count} 个路径待删除");
|
||
|
||
var result = new DeletePathResult
|
||
{
|
||
TotalCount = pathsToDelete.Count
|
||
};
|
||
|
||
// 第三阶段:创建备份(30%)
|
||
if (_parameters.CreateBackup && pathsToDelete.Count > 0)
|
||
{
|
||
UpdateProgress(30, "正在创建删除前备份...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
try
|
||
{
|
||
result.BackupFilePath = await CreateBackupAsync(pathsToDelete, cancellationToken);
|
||
LogInfo($"备份已创建: {result.BackupFilePath}");
|
||
}
|
||
catch (Exception backupEx)
|
||
{
|
||
LogWarning($"创建备份失败: {backupEx.Message}");
|
||
// 备份失败不阻止删除操作,但记录警告
|
||
}
|
||
}
|
||
|
||
// 第四阶段:执行删除操作(40% - 80%)
|
||
UpdateProgress(40, "正在删除路径...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
LogInfo("开始批量删除路径");
|
||
|
||
int processedCount = 0;
|
||
foreach (var path in pathsToDelete)
|
||
{
|
||
try
|
||
{
|
||
// 检查取消请求
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 检查是否需要确认删除
|
||
bool shouldDelete = _parameters.ForceDelete;
|
||
if (!shouldDelete && _parameters.ConfirmDeleteCallback != null)
|
||
{
|
||
shouldDelete = _parameters.ConfirmDeleteCallback(path);
|
||
if (!shouldDelete)
|
||
{
|
||
result.SkippedCount++;
|
||
LogInfo($"用户取消删除路径: {path.Name}");
|
||
processedCount++;
|
||
continue;
|
||
}
|
||
}
|
||
else if (!_parameters.ForceDelete)
|
||
{
|
||
// 默认删除
|
||
shouldDelete = true;
|
||
}
|
||
|
||
if (shouldDelete)
|
||
{
|
||
// 执行删除
|
||
bool deleteSuccess = _pathPlanningManager.DeleteRoute(path);
|
||
|
||
if (deleteSuccess)
|
||
{
|
||
result.DeletedCount++;
|
||
result.DeletedPaths.Add($"{path.Name} (ID: {path.Id})");
|
||
LogInfo($"成功删除路径: {path.Name}");
|
||
}
|
||
else
|
||
{
|
||
result.FailedCount++;
|
||
result.FailedPaths.Add($"{path.Name} (ID: {path.Id}) - 删除操作失败");
|
||
LogWarning($"删除路径失败: {path.Name}");
|
||
}
|
||
}
|
||
|
||
processedCount++;
|
||
|
||
// 更新进度(40% - 80%)
|
||
var progressPercent = 40 + (int)((double)processedCount / pathsToDelete.Count * 40);
|
||
UpdateProgress(progressPercent, $"正在删除路径... ({processedCount}/{pathsToDelete.Count})");
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
throw; // 重新抛出取消异常
|
||
}
|
||
catch (Exception pathEx)
|
||
{
|
||
result.FailedCount++;
|
||
result.FailedPaths.Add($"{path.Name} (ID: {path.Id}) - 异常: {pathEx.Message}");
|
||
LogError($"删除路径时发生异常: {path.Name}", pathEx);
|
||
}
|
||
}
|
||
|
||
LogInfo($"路径删除完成 - 删除: {result.DeletedCount}, 失败: {result.FailedCount}, 跳过: {result.SkippedCount}");
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
LogInfo("路径删除被用户取消");
|
||
throw; // 重新抛出取消异常
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogError("批量删除路径时发生异常", ex);
|
||
throw;
|
||
}
|
||
}, cancellationToken);
|
||
|
||
UpdateProgress(85, "正在完成删除操作...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 第五阶段:刷新UI状态(90%)
|
||
UpdateProgress(90, "正在刷新界面状态...");
|
||
|
||
try
|
||
{
|
||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||
{
|
||
// 如果删除了当前路径,需要选择新的当前路径
|
||
if (_pathPlanningManager.Routes.Count > 0 && _pathPlanningManager.CurrentRoute == null)
|
||
{
|
||
_pathPlanningManager.SetCurrentRoute(_pathPlanningManager.Routes.First());
|
||
}
|
||
LogInfo("UI状态已刷新");
|
||
});
|
||
}
|
||
catch (Exception refreshEx)
|
||
{
|
||
LogWarning($"刷新UI状态失败: {refreshEx.Message}");
|
||
}
|
||
|
||
// 完成(100%)
|
||
UpdateProgress(100, "路径删除完成");
|
||
|
||
var elapsedMs = (DateTime.UtcNow - startTime).TotalMilliseconds;
|
||
result.ExecutionTimeMs = (long)elapsedMs;
|
||
|
||
LogInfo($"删除路径执行完成,总耗时: {elapsedMs:F0}ms");
|
||
LogInfo($"删除结果 - 总数: {result.TotalCount}, 删除: {result.DeletedCount}, 失败: {result.FailedCount}, 跳过: {result.SkippedCount}");
|
||
|
||
// 创建结果对象
|
||
string resultMessage;
|
||
if (result.TotalCount == 0)
|
||
{
|
||
resultMessage = "没有找到需要删除的路径";
|
||
}
|
||
else
|
||
{
|
||
resultMessage = $"路径删除完成:删除 {result.DeletedCount}/{result.TotalCount} 项";
|
||
if (result.FailedCount > 0)
|
||
{
|
||
resultMessage += $",失败 {result.FailedCount} 项";
|
||
}
|
||
if (result.SkippedCount > 0)
|
||
{
|
||
resultMessage += $",跳过 {result.SkippedCount} 项";
|
||
}
|
||
}
|
||
|
||
var commandResult = PathPlanningResult<DeletePathResult>.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> CollectPathsToDelete()
|
||
{
|
||
var pathsToDelete = new List<PathRoute>();
|
||
|
||
if (_parameters.DeleteAll)
|
||
{
|
||
// 删除所有路径
|
||
pathsToDelete.AddRange(_pathPlanningManager.Routes);
|
||
LogInfo($"收集所有路径进行删除:{pathsToDelete.Count} 个");
|
||
}
|
||
else
|
||
{
|
||
// 从直接指定的路径收集
|
||
if (_parameters.PathsToDelete != null)
|
||
{
|
||
pathsToDelete.AddRange(_parameters.PathsToDelete.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];
|
||
pathsToDelete.AddRange(routes);
|
||
}
|
||
}
|
||
|
||
// 去重
|
||
pathsToDelete = pathsToDelete.Distinct().ToList();
|
||
LogInfo($"收集指定路径进行删除:{pathsToDelete.Count} 个");
|
||
}
|
||
|
||
return pathsToDelete;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建删除前备份
|
||
/// </summary>
|
||
private async Task<string> CreateBackupAsync(List<PathRoute> pathsToDelete, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
var backupFileName = $"路径删除备份_{DateTime.Now:yyyyMMdd_HHmmss}.xml";
|
||
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||
var backupPath = System.IO.Path.Combine(documentsPath, "NavisworksTransport", "Backups");
|
||
|
||
if (!System.IO.Directory.Exists(backupPath))
|
||
{
|
||
System.IO.Directory.CreateDirectory(backupPath);
|
||
}
|
||
|
||
var backupFilePath = System.IO.Path.Combine(backupPath, backupFileName);
|
||
|
||
// 使用PathDataManager创建备份
|
||
var pathDataManager = new PathDataManager();
|
||
var exportSettings = new ExportSettings
|
||
{
|
||
ProjectName = "删除前备份",
|
||
Description = $"删除 {pathsToDelete.Count} 个路径前的备份",
|
||
Units = "meters"
|
||
};
|
||
|
||
await Task.Run(() =>
|
||
{
|
||
bool success = pathDataManager.ExportToXml(pathsToDelete, backupFilePath, exportSettings);
|
||
if (!success)
|
||
{
|
||
throw new InvalidOperationException("备份文件创建失败");
|
||
}
|
||
}, cancellationToken);
|
||
|
||
return backupFilePath;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogError("创建备份文件失败", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 公共方法
|
||
|
||
/// <summary>
|
||
/// 创建删除单个路径的快捷命令
|
||
/// </summary>
|
||
/// <param name="pathToDelete">要删除的路径</param>
|
||
/// <param name="createBackup">是否创建备份</param>
|
||
/// <param name="forceDelete">是否强制删除</param>
|
||
/// <returns>删除路径命令实例</returns>
|
||
public static DeletePathCommand CreateSingle(PathRoute pathToDelete, bool createBackup = true, bool forceDelete = false)
|
||
{
|
||
var parameters = new DeletePathParameters
|
||
{
|
||
PathsToDelete = new List<PathRoute> { pathToDelete },
|
||
CreateBackup = createBackup,
|
||
ForceDelete = forceDelete,
|
||
Description = $"删除路径: {pathToDelete?.Name}"
|
||
};
|
||
|
||
return new DeletePathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建删除多个路径的快捷命令
|
||
/// </summary>
|
||
/// <param name="pathsToDelete">要删除的路径集合</param>
|
||
/// <param name="createBackup">是否创建备份</param>
|
||
/// <param name="confirmCallback">删除确认回调</param>
|
||
/// <returns>删除路径命令实例</returns>
|
||
public static DeletePathCommand CreateMultiple(List<PathRoute> pathsToDelete, bool createBackup = true, Func<PathRoute, bool> confirmCallback = null)
|
||
{
|
||
var parameters = new DeletePathParameters
|
||
{
|
||
PathsToDelete = pathsToDelete ?? new List<PathRoute>(),
|
||
CreateBackup = createBackup,
|
||
ConfirmDeleteCallback = confirmCallback,
|
||
ForceDelete = confirmCallback == null, // 如果没有确认回调,则强制删除
|
||
Description = $"删除 {pathsToDelete?.Count ?? 0} 个路径"
|
||
};
|
||
|
||
return new DeletePathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建删除所有路径的快捷命令
|
||
/// </summary>
|
||
/// <param name="createBackup">是否创建备份</param>
|
||
/// <param name="confirmCallback">删除确认回调</param>
|
||
/// <returns>删除路径命令实例</returns>
|
||
public static DeletePathCommand CreateDeleteAll(bool createBackup = true, Func<PathRoute, bool> confirmCallback = null)
|
||
{
|
||
var parameters = new DeletePathParameters
|
||
{
|
||
DeleteAll = true,
|
||
CreateBackup = createBackup,
|
||
ConfirmDeleteCallback = confirmCallback,
|
||
ForceDelete = confirmCallback == null, // 如果没有确认回调,则强制删除
|
||
Description = "删除所有路径"
|
||
};
|
||
|
||
return new DeletePathCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取命令执行摘要信息
|
||
/// </summary>
|
||
/// <returns>命令信息摘要</returns>
|
||
public string GetExecutionSummary()
|
||
{
|
||
var targetDescription = _parameters.DeleteAll ? "所有路径" :
|
||
$"{_parameters.PathsToDelete?.Count ?? 0} + {_parameters.PathIds?.Count ?? 0} 个路径";
|
||
|
||
return $"删除路径命令 - 目标:{targetDescription}, " +
|
||
$"备份:{_parameters.CreateBackup}, " +
|
||
$"强制:{_parameters.ForceDelete}, " +
|
||
$"状态:{Status}";
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |