490 lines
19 KiB
C#
490 lines
19 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Autodesk.Navisworks.Api;
|
||
using NavisworksTransport.Core;
|
||
|
||
namespace NavisworksTransport.Commands
|
||
{
|
||
/// <summary>
|
||
/// 设置物流属性参数类
|
||
/// </summary>
|
||
public class SetLogisticsAttributeParameters
|
||
{
|
||
/// <summary>
|
||
/// 目标模型项集合
|
||
/// </summary>
|
||
public ModelItemCollection TargetItems { get; set; }
|
||
|
||
/// <summary>
|
||
/// 物流元素类型
|
||
/// </summary>
|
||
public CategoryAttributeManager.LogisticsElementType ElementType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否可通行(仅对通道类型有效)
|
||
/// </summary>
|
||
public bool? IsTraversable { get; set; }
|
||
|
||
/// <summary>
|
||
/// 自定义属性字典
|
||
/// </summary>
|
||
public Dictionary<string, object> CustomAttributes { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否覆盖现有属性
|
||
/// </summary>
|
||
public bool OverwriteExisting { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 操作描述(用于日志记录)
|
||
/// </summary>
|
||
public string Description { get; set; }
|
||
|
||
public SetLogisticsAttributeParameters()
|
||
{
|
||
TargetItems = new ModelItemCollection();
|
||
CustomAttributes = new Dictionary<string, object>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证参数有效性
|
||
/// </summary>
|
||
public PathPlanningResult ValidateParameters()
|
||
{
|
||
var errors = new List<string>();
|
||
|
||
if (TargetItems == null || TargetItems.Count == 0)
|
||
errors.Add("目标模型项集合不能为空");
|
||
|
||
if (!Enum.IsDefined(typeof(CategoryAttributeManager.LogisticsElementType), ElementType))
|
||
errors.Add("无效的物流元素类型");
|
||
|
||
// 检查通道类型的特殊要求
|
||
if (ElementType == CategoryAttributeManager.LogisticsElementType.通道 && !IsTraversable.HasValue)
|
||
{
|
||
errors.Add("通道类型必须指定是否可通行");
|
||
}
|
||
|
||
if (errors.Count > 0)
|
||
{
|
||
return PathPlanningResult.ValidationFailure($"参数验证失败: {string.Join("; ", errors)}");
|
||
}
|
||
|
||
return PathPlanningResult.Success("参数验证通过");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置物流属性结果类
|
||
/// </summary>
|
||
public class SetLogisticsAttributeResult
|
||
{
|
||
/// <summary>
|
||
/// 成功设置属性的模型项数量
|
||
/// </summary>
|
||
public int SuccessCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 失败的模型项数量
|
||
/// </summary>
|
||
public int FailureCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 总模型项数量
|
||
/// </summary>
|
||
public int TotalCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 详细结果信息
|
||
/// </summary>
|
||
public List<string> DetailedResults { get; set; }
|
||
|
||
/// <summary>
|
||
/// 已设置的物流元素类型
|
||
/// </summary>
|
||
public CategoryAttributeManager.LogisticsElementType ElementType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 操作执行时间(毫秒)
|
||
/// </summary>
|
||
public long ExecutionTimeMs { get; set; }
|
||
|
||
public SetLogisticsAttributeResult()
|
||
{
|
||
DetailedResults = new List<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 成功率
|
||
/// </summary>
|
||
public double SuccessRate => TotalCount > 0 ? (double)SuccessCount / TotalCount : 0.0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置物流属性Command
|
||
/// </summary>
|
||
public class SetLogisticsAttributeCommand : CommandBase
|
||
{
|
||
#region 字段和属性
|
||
|
||
private readonly SetLogisticsAttributeParameters _parameters;
|
||
private readonly CategoryAttributeManager _categoryAttributeManager;
|
||
private readonly UIStateManager _uiStateManager;
|
||
|
||
/// <summary>
|
||
/// 命令参数
|
||
/// </summary>
|
||
public SetLogisticsAttributeParameters Parameters => _parameters;
|
||
|
||
#endregion
|
||
|
||
#region 构造函数
|
||
|
||
/// <summary>
|
||
/// 初始化设置物流属性命令
|
||
/// </summary>
|
||
/// <param name="parameters">设置参数</param>
|
||
/// <param name="categoryAttributeManager">类别属性管理器</param>
|
||
public SetLogisticsAttributeCommand(SetLogisticsAttributeParameters parameters, CategoryAttributeManager categoryAttributeManager = null)
|
||
: base("SetLogisticsAttribute", "设置物流属性", "为指定模型项设置物流相关的属性信息")
|
||
{
|
||
_parameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
|
||
_categoryAttributeManager = categoryAttributeManager ?? new CategoryAttributeManager();
|
||
_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;
|
||
}
|
||
|
||
// 验证CategoryAttributeManager状态
|
||
if (_categoryAttributeManager == null)
|
||
{
|
||
return PathPlanningResult.ValidationFailure("类别属性管理器未初始化");
|
||
}
|
||
|
||
// 验证Navisworks文档状态
|
||
var document = Application.ActiveDocument;
|
||
if (document?.Models == null || !document.Models.Any())
|
||
{
|
||
return PathPlanningResult.ValidationFailure("当前没有加载的Navisworks模型");
|
||
}
|
||
|
||
// 验证目标模型项是否在当前文档中
|
||
foreach (ModelItem item in _parameters.TargetItems)
|
||
{
|
||
if (item == null)
|
||
{
|
||
return PathPlanningResult.ValidationFailure("目标模型项集合包含空引用");
|
||
}
|
||
}
|
||
|
||
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 totalItems = _parameters.TargetItems.Count;
|
||
LogInfo($"目标模型项数量: {totalItems}");
|
||
LogInfo($"物流元素类型: {_parameters.ElementType}");
|
||
LogInfo($"是否覆盖现有属性: {_parameters.OverwriteExisting}");
|
||
if (_parameters.IsTraversable.HasValue)
|
||
{
|
||
LogInfo($"可通行性设置: {_parameters.IsTraversable.Value}");
|
||
}
|
||
|
||
// 第三阶段:执行属性设置(30% - 80%)
|
||
UpdateProgress(30, "正在设置物流属性...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
var result = new SetLogisticsAttributeResult
|
||
{
|
||
TotalCount = totalItems,
|
||
ElementType = _parameters.ElementType
|
||
};
|
||
|
||
// 在后台线程中执行属性设置操作
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
LogInfo("开始批量设置物流属性");
|
||
|
||
int processedCount = 0;
|
||
foreach (ModelItem item in _parameters.TargetItems)
|
||
{
|
||
try
|
||
{
|
||
// 检查取消请求
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 设置基本物流属性
|
||
// 创建单个项目的ModelItemCollection
|
||
var itemCollection = new ModelItemCollection
|
||
{
|
||
item
|
||
};
|
||
|
||
// 使用配置的默认值添加物流属性
|
||
int affectedCount = CategoryAttributeManager.AddLogisticsAttributes(
|
||
itemCollection,
|
||
_parameters.ElementType);
|
||
|
||
bool success = affectedCount > 0;
|
||
|
||
if (success)
|
||
{
|
||
// 如果是通道类型,设置可通行性
|
||
if (_parameters.ElementType == CategoryAttributeManager.LogisticsElementType.通道 &&
|
||
_parameters.IsTraversable.HasValue)
|
||
{
|
||
success = _categoryAttributeManager.SetTraversable(item, _parameters.IsTraversable.Value);
|
||
}
|
||
|
||
// 设置自定义属性
|
||
if (success && _parameters.CustomAttributes.Count > 0)
|
||
{
|
||
foreach (var kvp in _parameters.CustomAttributes)
|
||
{
|
||
try
|
||
{
|
||
_categoryAttributeManager.SetCustomAttribute(item, kvp.Key, kvp.Value?.ToString() ?? string.Empty, _parameters.OverwriteExisting);
|
||
}
|
||
catch (Exception attrEx)
|
||
{
|
||
LogWarning($"设置自定义属性失败 - 项: {item.DisplayName}, 属性: {kvp.Key}, 错误: {attrEx.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (success)
|
||
{
|
||
result.SuccessCount++;
|
||
result.DetailedResults.Add($"成功: {item.DisplayName}");
|
||
LogInfo($"成功设置物流属性: {item.DisplayName} -> {_parameters.ElementType}");
|
||
}
|
||
else
|
||
{
|
||
result.FailureCount++;
|
||
result.DetailedResults.Add($"失败: {item.DisplayName}");
|
||
LogWarning($"设置物流属性失败: {item.DisplayName}");
|
||
}
|
||
|
||
processedCount++;
|
||
|
||
// 更新进度(30% - 80%)
|
||
var progressPercent = 30 + (int)((double)processedCount / totalItems * 50);
|
||
UpdateProgress(progressPercent, $"正在设置物流属性... ({processedCount}/{totalItems})");
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
throw; // 重新抛出取消异常
|
||
}
|
||
catch (Exception itemEx)
|
||
{
|
||
result.FailureCount++;
|
||
result.DetailedResults.Add($"异常: {item.DisplayName} - {itemEx.Message}");
|
||
LogError($"设置模型项属性时发生异常: {item.DisplayName}", itemEx);
|
||
}
|
||
}
|
||
|
||
LogInfo($"物流属性设置完成 - 成功: {result.SuccessCount}, 失败: {result.FailureCount}");
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
LogInfo("物流属性设置被用户取消");
|
||
throw; // 重新抛出取消异常
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogError("批量设置物流属性时发生异常", ex);
|
||
throw;
|
||
}
|
||
}, cancellationToken);
|
||
|
||
UpdateProgress(85, "正在完成属性设置...");
|
||
ThrowIfCancellationRequested(cancellationToken);
|
||
|
||
// 第四阶段:保存更改和后处理(90%)
|
||
UpdateProgress(90, "正在保存更改...");
|
||
|
||
// 刷新文档以确保属性更改生效
|
||
try
|
||
{
|
||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||
{
|
||
// 触发文档刷新
|
||
Application.ActiveDocument.CurrentSelection.Clear();
|
||
LogInfo("文档状态已刷新");
|
||
});
|
||
}
|
||
catch (Exception refreshEx)
|
||
{
|
||
LogWarning($"刷新文档状态失败: {refreshEx.Message}");
|
||
}
|
||
|
||
// 完成(100%)
|
||
UpdateProgress(100, "物流属性设置完成");
|
||
|
||
var elapsedMs = (DateTime.UtcNow - startTime).TotalMilliseconds;
|
||
result.ExecutionTimeMs = (long)elapsedMs;
|
||
|
||
LogInfo($"设置物流属性执行完成,总耗时: {elapsedMs:F0}ms");
|
||
LogInfo($"设置结果 - 总数: {result.TotalCount}, 成功: {result.SuccessCount}, 失败: {result.FailureCount}, 成功率: {result.SuccessRate:P2}");
|
||
|
||
// 创建结果对象
|
||
var commandResult = PathPlanningResult<SetLogisticsAttributeResult>.Success(
|
||
result,
|
||
$"物流属性设置完成:成功 {result.SuccessCount}/{result.TotalCount} 项,成功率 {result.SuccessRate:P2}"
|
||
);
|
||
|
||
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>
|
||
/// <param name="targetItems">目标模型项</param>
|
||
/// <param name="elementType">物流元素类型</param>
|
||
/// <param name="isTraversable">是否可通行(通道类型)</param>
|
||
/// <param name="description">操作描述</param>
|
||
/// <returns>设置物流属性命令实例</returns>
|
||
public static SetLogisticsAttributeCommand CreateQuick(ModelItemCollection targetItems,
|
||
CategoryAttributeManager.LogisticsElementType elementType,
|
||
bool? isTraversable = null,
|
||
string description = null)
|
||
{
|
||
var parameters = new SetLogisticsAttributeParameters
|
||
{
|
||
TargetItems = targetItems ?? new ModelItemCollection(),
|
||
ElementType = elementType,
|
||
IsTraversable = isTraversable,
|
||
Description = description,
|
||
OverwriteExisting = true
|
||
};
|
||
|
||
return new SetLogisticsAttributeCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建带自定义属性的设置命令
|
||
/// </summary>
|
||
/// <param name="targetItems">目标模型项</param>
|
||
/// <param name="elementType">物流元素类型</param>
|
||
/// <param name="customAttributes">自定义属性</param>
|
||
/// <param name="overwriteExisting">是否覆盖现有属性</param>
|
||
/// <returns>设置物流属性命令实例</returns>
|
||
public static SetLogisticsAttributeCommand CreateWithCustomAttributes(ModelItemCollection targetItems,
|
||
CategoryAttributeManager.LogisticsElementType elementType,
|
||
Dictionary<string, object> customAttributes,
|
||
bool overwriteExisting = true)
|
||
{
|
||
var parameters = new SetLogisticsAttributeParameters
|
||
{
|
||
TargetItems = targetItems ?? new ModelItemCollection(),
|
||
ElementType = elementType,
|
||
CustomAttributes = customAttributes ?? new Dictionary<string, object>(),
|
||
OverwriteExisting = overwriteExisting
|
||
};
|
||
|
||
return new SetLogisticsAttributeCommand(parameters);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取命令执行摘要信息
|
||
/// </summary>
|
||
/// <returns>命令信息摘要</returns>
|
||
public string GetExecutionSummary()
|
||
{
|
||
return $"设置物流属性命令 - 目标数量:{_parameters.TargetItems?.Count ?? 0}, " +
|
||
$"元素类型:{_parameters.ElementType}, " +
|
||
$"可通行:{_parameters.IsTraversable?.ToString() ?? "未设置"}, " +
|
||
$"状态:{Status}";
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |