NavisworksTransport/CategoryAttributeManager.cs

960 lines
42 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
namespace NavisworksTransport
{
/// <summary>
/// 类别属性管理器 - 负责为模型元素添加和管理物流相关的自定义属性
/// </summary>
public class CategoryAttributeManager
{
/// <summary>
/// 物流类别定义
/// </summary>
public static class LogisticsCategories
{
public const string LOGISTICS = "物流属性";
public const string CATEGORY_INTERNAL_NAME = "物流属性_Internal";
}
/// <summary>
/// 物流属性定义
/// </summary>
public static class LogisticsProperties
{
public const string TYPE = "类型";
public const string TRAVERSABLE = "可通行";
public const string PRIORITY = "优先级";
public const string VEHICLE_SIZE = "适用车辆尺寸";
public const string SPEED_LIMIT = "速度限制";
}
/// <summary>
/// 物流元素类型
/// </summary>
public enum LogisticsElementType
{
,
,
,
,
,
,
,
}
/// <summary>
/// 为选定的模型项添加物流属性
/// </summary>
/// <param name="items">要处理的模型项集合</param>
/// <param name="elementType">物流元素类型</param>
/// <param name="isTraversable">是否可通行</param>
/// <param name="priority">优先级1-10</param>
/// <param name="vehicleSize">适用车辆尺寸</param>
/// <param name="speedLimit">速度限制km/h</param>
/// <returns>成功处理的项目数量</returns>
public static int AddLogisticsAttributes(
ModelItemCollection items,
LogisticsElementType elementType,
bool isTraversable = true,
int priority = 5,
string vehicleSize = "标准",
double speedLimit = 10.0)
{
if (items == null || items.Count == 0)
{
return 0;
}
int successCount = 0;
try
{
// 获取COM API状态对象
ComApi.InwOpState10 state = ComApiBridge.State;
// 转换选择集合为COM对象
ComApi.InwOpSelection comSelection = ComApiBridge.ToInwOpSelection(items);
// 遍历每个路径对象
foreach (ComApi.InwOaPath3 path in comSelection.Paths())
{
try
{
// 获取属性节点
ComApi.InwGUIPropertyNode2 propertyNode =
(ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, false);
// 查找现有属性类别的索引
int existingIndex = GetLogisticsAttributeIndex(propertyNode);
// 创建新的属性类别
ComApi.InwOaPropertyVec propertyCategory =
(ComApi.InwOaPropertyVec)state.ObjectFactory(
ComApi.nwEObjectType.eObjectType_nwOaPropertyVec, null, null);
// 创建并添加类型属性
AddProperty(state, propertyCategory, LogisticsProperties.TYPE,
elementType.ToString(), elementType.ToString() + "_Internal");
// 创建并添加可通行属性
AddProperty(state, propertyCategory, LogisticsProperties.TRAVERSABLE,
isTraversable ? "是" : "否", "Traversable_Internal");
// 创建并添加优先级属性
AddProperty(state, propertyCategory, LogisticsProperties.PRIORITY,
priority.ToString(), "Priority_Internal");
// 创建并添加车辆尺寸属性
AddProperty(state, propertyCategory, LogisticsProperties.VEHICLE_SIZE,
vehicleSize, "VehicleSize_Internal");
// 创建并添加速度限制属性
AddProperty(state, propertyCategory, LogisticsProperties.SPEED_LIMIT,
speedLimit.ToString("F1") + " km/h", "SpeedLimit_Internal");
if (existingIndex >= 0)
{
// 如果存在现有属性,使用覆盖模式 (参数1)
LogManager.WriteLog($"[属性添加] 发现现有物流属性,使用覆盖模式更新");
LogPropertyNodeState(propertyNode, "属性添加-覆盖前");
try
{
// 使用参数1表示覆盖现有PropertyCategory
propertyNode.SetUserDefined(1, LogisticsCategories.LOGISTICS,
LogisticsCategories.CATEGORY_INTERNAL_NAME, propertyCategory);
LogManager.WriteLog($"[属性添加] ✅ 成功覆盖现有属性类别");
// 立即刷新并验证结果
propertyNode = RefreshPropertyNode(state, path, "属性添加-覆盖验证");
LogPropertyNodeState(propertyNode, "属性添加-覆盖后");
}
catch (Exception setEx)
{
LogManager.WriteLog($"[属性添加] ❌ 覆盖属性失败,错误: {setEx.Message}");
throw;
}
}
else
{
// 如果不存在,创建新的属性类别,使用创建模式 (参数0)
LogManager.WriteLog("[属性添加] 未发现现有物流属性,使用创建模式");
LogPropertyNodeState(propertyNode, "属性添加-创建前");
try
{
// 使用参数0表示创建新的PropertyCategory
propertyNode.SetUserDefined(0, LogisticsCategories.LOGISTICS,
LogisticsCategories.CATEGORY_INTERNAL_NAME, propertyCategory);
LogManager.WriteLog("[属性添加] ✅ 成功创建新的属性类别");
// 立即刷新并验证结果
propertyNode = RefreshPropertyNode(state, path, "属性添加-创建验证");
LogPropertyNodeState(propertyNode, "属性添加-创建后");
}
catch (Exception setEx)
{
LogManager.WriteLog($"[属性添加] ❌ 创建属性失败,错误: {setEx.Message}");
throw;
}
}
successCount++;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"处理单个模型项时发生错误: {ex.Message}");
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"添加物流属性时发生错误: {ex.Message}");
}
return successCount;
}
/// <summary>
/// 创建并添加单个属性到属性类别
/// </summary>
/// <param name="state">COM API状态对象</param>
/// <param name="propertyCategory">属性类别对象</param>
/// <param name="displayName">显示名称</param>
/// <param name="value">属性值</param>
/// <param name="internalName">内部名称</param>
private static void AddProperty(ComApi.InwOpState10 state,
ComApi.InwOaPropertyVec propertyCategory,
string displayName,
string value,
string internalName)
{
// 创建新属性
ComApi.InwOaProperty property = (ComApi.InwOaProperty)state.ObjectFactory(
ComApi.nwEObjectType.eObjectType_nwOaProperty, null, null);
// 设置属性信息
property.name = internalName; // 内部名称
property.UserName = displayName; // 显示名称
property.value = value; // 属性值
// 添加到属性类别
propertyCategory.Properties().Add(property);
}
/// <summary>
/// 检查模型项是否已有物流属性
/// </summary>
/// <param name="item">要检查的模型项</param>
/// <returns>如果已有物流属性返回true</returns>
public static bool HasLogisticsAttributes(ModelItem item)
{
try
{
// 检查自定义属性
foreach (PropertyCategory category in item.PropertyCategories)
{
if (category.DisplayName == LogisticsCategories.LOGISTICS)
{
return true;
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"检查物流属性时发生错误: {ex.Message}");
}
return false;
}
/// <summary>
/// 获取模型项的物流属性值
/// </summary>
/// <param name="item">模型项</param>
/// <param name="propertyName">属性名称</param>
/// <returns>属性值,如果不存在返回空字符串</returns>
public static string GetLogisticsPropertyValue(ModelItem item, string propertyName)
{
try
{
foreach (PropertyCategory category in item.PropertyCategories)
{
if (category.DisplayName == LogisticsCategories.LOGISTICS)
{
foreach (DataProperty property in category.Properties)
{
if (property.DisplayName == propertyName)
{
return property.Value.ToDisplayString();
}
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"获取物流属性值时发生错误: {ex.Message}");
}
return string.Empty;
}
/// <summary>
/// 根据物流属性筛选模型项
/// </summary>
/// <param name="items">要筛选的模型项集合</param>
/// <param name="elementType">要筛选的元素类型</param>
/// <returns>匹配条件的模型项集合</returns>
public static ModelItemCollection FilterByLogisticsType(ModelItemCollection items, LogisticsElementType elementType)
{
ModelItemCollection filteredItems = new ModelItemCollection();
foreach (ModelItem item in items)
{
string typeValue = GetLogisticsPropertyValue(item, LogisticsProperties.TYPE);
if (typeValue == elementType.ToString())
{
filteredItems.Add(item);
}
}
return filteredItems;
}
/// <summary>
/// 筛选可通行的模型项
/// </summary>
/// <param name="items">要筛选的模型项集合</param>
/// <returns>可通行的模型项集合</returns>
public static ModelItemCollection FilterTraversableItems(ModelItemCollection items)
{
ModelItemCollection filteredItems = new ModelItemCollection();
foreach (ModelItem item in items)
{
string traversableValue = GetLogisticsPropertyValue(item, LogisticsProperties.TRAVERSABLE);
if (traversableValue == "是")
{
filteredItems.Add(item);
}
}
return filteredItems;
}
/// <summary>
/// 根据车辆尺寸筛选适用的通道
/// </summary>
/// <param name="items">要筛选的模型项集合</param>
/// <param name="vehicleSize">车辆尺寸</param>
/// <returns>适用的通道集合</returns>
public static ModelItemCollection FilterByVehicleSize(ModelItemCollection items, string vehicleSize)
{
ModelItemCollection filteredItems = new ModelItemCollection();
foreach (ModelItem item in items)
{
string sizeValue = GetLogisticsPropertyValue(item, LogisticsProperties.VEHICLE_SIZE);
if (sizeValue == vehicleSize || sizeValue == "标准" || string.IsNullOrEmpty(sizeValue))
{
filteredItems.Add(item);
}
}
return filteredItems;
}
/// <summary>
/// 删除选定模型项的物流属性
/// </summary>
/// <param name="items">要删除属性的模型项集合</param>
/// <returns>成功删除属性的项目数量</returns>
public static int RemoveLogisticsAttributes(ModelItemCollection items)
{
if (items == null || items.Count == 0)
{
LogManager.WriteLog("[属性删除] 输入参数为空或无模型项");
return 0;
}
int successCount = 0;
LogManager.WriteLog($"[属性删除] 开始删除 {items.Count} 个模型的物流属性");
try
{
// 获取COM API状态对象
ComApi.InwOpState10 state = ComApiBridge.State;
LogManager.WriteLog("[属性删除] 已获取COM API状态对象");
// 转换选择集合为COM对象
ComApi.InwOpSelection comSelection = ComApiBridge.ToInwOpSelection(items);
LogManager.WriteLog($"[属性删除] 已转换为COM选择集合路径数: {comSelection.Paths().Count}");
// 遍历每个路径对象
foreach (ComApi.InwOaPath3 path in comSelection.Paths())
{
try
{
LogManager.WriteLog("[属性删除] 开始处理路径对象");
// 获取属性节点
ComApi.InwGUIPropertyNode2 propertyNode =
(ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, false);
LogManager.WriteLog("[属性删除] 已获取属性节点");
// 记录操作前的属性状态
LogPropertyNodeState(propertyNode, "属性删除-操作前");
// 查找现有属性类别的索引
int existingIndex = GetLogisticsAttributeIndex(propertyNode);
if (existingIndex < 0)
{
LogManager.WriteLog("[属性删除] 该模型没有物流属性类别,跳过");
continue;
}
// 使用RemoveUserDefined方法完全删除属性类别
LogManager.WriteLog($"[属性删除] 发现现有物流属性使用RemoveUserDefined方法删除");
LogPropertyNodeState(propertyNode, "属性删除-删除前");
try
{
// 计算用户定义属性的相对索引从1开始
int relativeIndex = GetLogisticsAttributeRelativeIndex(propertyNode);
if (relativeIndex >= 0)
{
// 用户定义属性索引从1开始所以需要+1
int userDefinedIndex = relativeIndex + 1;
LogManager.WriteLog($"[属性删除] 使用用户定义属性索引: {userDefinedIndex}(相对索引: {relativeIndex}");
// 使用RemoveUserDefined方法完全删除属性类别
propertyNode.RemoveUserDefined(userDefinedIndex);
LogManager.WriteLog($"[属性删除] ✅ 成功使用RemoveUserDefined删除属性类别");
}
else
{
LogManager.WriteLog($"[属性删除] ❌ 无法找到物流属性的相对索引");
throw new InvalidOperationException("无法找到物流属性的相对索引");
}
LogPropertyNodeState(propertyNode, "属性删除-删除后");
}
catch (Exception setEx)
{
LogManager.WriteLog($"[属性删除] ❌ 删除属性失败,错误: {setEx.Message}");
throw;
}
successCount++;
LogManager.WriteLog($"[属性删除] 成功删除一个模型的属性,当前成功数: {successCount}");
}
catch (Exception ex)
{
LogManager.WriteLog($"[属性删除] 删除单个模型项属性时发生错误: {ex.Message}");
LogManager.WriteLog($"[属性删除] 异常详细信息: {ex}");
System.Diagnostics.Debug.WriteLine($"删除单个模型项属性时发生错误: {ex.Message}");
}
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[属性删除] 删除物流属性时发生错误: {ex.Message}");
LogManager.WriteLog($"[属性删除] 异常详细信息: {ex}");
System.Diagnostics.Debug.WriteLine($"删除物流属性时发生错误: {ex.Message}");
}
LogManager.WriteLog($"[属性删除] 删除操作完成,成功删除 {successCount} 个模型的属性");
return successCount;
}
/// <summary>
/// 验证索引是否有效
/// </summary>
/// <param name="propertyNode">属性节点</param>
/// <param name="index">要验证的索引</param>
/// <param name="operation">操作名称</param>
/// <returns>索引是否有效</returns>
private static bool ValidateIndex(ComApi.InwGUIPropertyNode2 propertyNode, int index, string operation)
{
try
{
int totalCount = 0;
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
totalCount++;
}
bool isValid = index >= 0 && index < totalCount;
LogManager.WriteLog($"[{operation}] 索引验证: index={index}, totalCount={totalCount}, valid={isValid}");
return isValid;
}
catch (Exception ex)
{
LogManager.WriteLog($"[{operation}] 索引验证失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 强制刷新属性节点(尝试清理缓存)
/// </summary>
/// <param name="state">COM API状态对象</param>
/// <param name="path">路径对象</param>
/// <param name="operation">操作名称</param>
/// <returns>刷新后的属性节点</returns>
private static ComApi.InwGUIPropertyNode2 RefreshPropertyNode(ComApi.InwOpState10 state, ComApi.InwOaPath3 path, string operation)
{
try
{
LogManager.WriteLog($"[{operation}] 强制刷新属性节点");
// 尝试多种方式获取属性节点以清理缓存
ComApi.InwGUIPropertyNode2 propertyNode1 = (ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, false);
ComApi.InwGUIPropertyNode2 propertyNode2 = (ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, true);
ComApi.InwGUIPropertyNode2 propertyNode3 = (ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, false);
LogManager.WriteLog($"[{operation}] 属性节点刷新完成");
return propertyNode3;
}
catch (Exception ex)
{
LogManager.WriteLog($"[{operation}] 属性节点刷新失败: {ex.Message}");
return (ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, false);
}
}
/// <summary>
/// 记录属性节点的完整状态(用于调试)
/// </summary>
/// <param name="propertyNode">属性节点</param>
/// <param name="operation">操作名称</param>
private static void LogPropertyNodeState(ComApi.InwGUIPropertyNode2 propertyNode, string operation)
{
try
{
LogManager.WriteLog($"[{operation}] 开始记录属性节点状态");
// 强制重新枚举属性
var attributesList = new List<ComApi.InwGUIAttribute2>();
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
attributesList.Add(attribute);
}
LogManager.WriteLog($"[{operation}] 重新枚举完成,共发现 {attributesList.Count} 个属性");
int index = 0;
int userDefinedCount = 0;
int totalCount = attributesList.Count;
foreach (var attribute in attributesList)
{
try
{
string userDefined = attribute.UserDefined ? "用户定义" : "系统属性";
string className = attribute.ClassUserName ?? "无名称";
LogManager.WriteLog($"[{operation}] 属性 {index}: {userDefined}, 类别名称='{className}'");
if (attribute.UserDefined)
{
userDefinedCount++;
if (className == LogisticsCategories.LOGISTICS)
{
LogManager.WriteLog($"[{operation}] ⭐ 这是物流属性类别,索引: {index}");
// 尝试读取属性内容以验证
try
{
var properties = attribute.Properties();
int propCount = 0;
foreach (ComApi.InwOaProperty prop in properties)
{
propCount++;
}
LogManager.WriteLog($"[{operation}] 物流属性类别包含 {propCount} 个子属性");
}
catch (Exception propEx)
{
LogManager.WriteLog($"[{operation}] 读取物流属性子属性失败: {propEx.Message}");
}
}
}
}
catch (Exception attrEx)
{
LogManager.WriteLog($"[{operation}] 读取属性 {index} 信息失败: {attrEx.Message}");
}
index++;
}
LogManager.WriteLog($"[{operation}] 属性节点状态总结: 总属性数={totalCount}, 用户定义属性数={userDefinedCount}");
}
catch (Exception ex)
{
LogManager.WriteLog($"[{operation}] 记录属性节点状态时发生错误: {ex.Message}");
}
}
/// <summary>
/// 查找现有物流属性类别的绝对索引(用于日志记录)
/// </summary>
/// <param name="propertyNode">属性节点</param>
/// <returns>找到的绝对索引,如果不存在返回-1</returns>
private static int GetLogisticsAttributeAbsoluteIndex(ComApi.InwGUIPropertyNode2 propertyNode)
{
try
{
int index = 0;
int userDefinedCount = 0;
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
string className = attribute.ClassUserName ?? "无名称";
if (attribute.UserDefined)
{
userDefinedCount++;
if (className == LogisticsCategories.LOGISTICS)
{
return index;
}
}
index++;
}
return -1;
}
catch (Exception ex)
{
LogManager.WriteLog($"[绝对索引查找] 查找属性绝对索引时发生错误: {ex.Message}");
return -1;
}
}
/// <summary>
/// 查找现有物流属性类别的相对索引(在用户定义属性中的位置)
/// </summary>
/// <param name="propertyNode">属性节点</param>
/// <returns>找到的相对索引,如果不存在返回-1</returns>
private static int GetLogisticsAttributeRelativeIndex(ComApi.InwGUIPropertyNode2 propertyNode)
{
try
{
int userDefinedIndex = 0;
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
string className = attribute.ClassUserName ?? "无名称";
if (attribute.UserDefined)
{
if (className == LogisticsCategories.LOGISTICS)
{
LogManager.WriteLog($"[相对索引查找] ✅ 找到物流属性类别,相对索引: {userDefinedIndex}");
return userDefinedIndex;
}
userDefinedIndex++;
}
}
LogManager.WriteLog($"[相对索引查找] ❌ 未找到物流属性类别");
return -1;
}
catch (Exception ex)
{
LogManager.WriteLog($"[相对索引查找] 查找属性相对索引时发生错误: {ex.Message}");
return -1;
}
}
/// <summary>
/// 查找现有物流属性类别的索引
/// </summary>
/// <param name="propertyNode">属性节点</param>
/// <returns>找到的索引,如果不存在返回-1</returns>
private static int GetLogisticsAttributeIndex(ComApi.InwGUIPropertyNode2 propertyNode)
{
try
{
LogManager.WriteLog("[索引查找] 开始查找物流属性类别索引");
int index = 0;
int totalAttributes = 0;
int userDefinedCount = 0;
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
totalAttributes++;
string className = attribute.ClassUserName ?? "无名称";
LogManager.WriteLog($"[索引查找] 检查属性 {index}: UserDefined={attribute.UserDefined}, ClassUserName='{className}'");
if (attribute.UserDefined)
{
userDefinedCount++;
if (className == LogisticsCategories.LOGISTICS)
{
LogManager.WriteLog($"[索引查找] ✅ 找到物流属性类别,绝对索引: {index}, 在第{userDefinedCount}个用户定义属性中");
// 获取相对索引
int relativeIndex = GetLogisticsAttributeRelativeIndex(propertyNode);
LogManager.WriteLog($"[索引查找] 物流属性相对索引: {relativeIndex}");
return index; // 仍然返回绝对索引用于兼容性
}
}
index++;
}
LogManager.WriteLog($"[索引查找] ❌ 未找到物流属性类别,总共检查了 {totalAttributes} 个属性(其中 {userDefinedCount} 个用户定义属性)");
return -1;
}
catch (Exception ex)
{
LogManager.WriteLog($"[索引查找] 查找属性索引时发生错误: {ex.Message}");
return -1;
}
}
/// <summary>
/// 更新选定模型项的物流属性
/// </summary>
/// <param name="items">要更新属性的模型项集合</param>
/// <param name="elementType">新的物流元素类型</param>
/// <param name="isTraversable">是否可通行</param>
/// <param name="priority">优先级1-10</param>
/// <param name="vehicleSize">适用车辆尺寸</param>
/// <param name="speedLimit">速度限制km/h</param>
/// <returns>成功更新的项目数量</returns>
public static int UpdateLogisticsAttributes(
ModelItemCollection items,
LogisticsElementType elementType,
bool isTraversable = true,
int priority = 5,
string vehicleSize = "标准",
double speedLimit = 10.0)
{
if (items == null || items.Count == 0)
{
return 0;
}
int successCount = 0;
try
{
// 获取COM API状态对象
ComApi.InwOpState10 state = ComApiBridge.State;
// 转换选择集合为COM对象
ComApi.InwOpSelection comSelection = ComApiBridge.ToInwOpSelection(items);
// 遍历每个路径对象
foreach (ComApi.InwOaPath3 path in comSelection.Paths())
{
try
{
// 获取属性节点
ComApi.InwGUIPropertyNode2 propertyNode =
(ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(path, false);
// 查找现有属性类别的索引
int existingIndex = GetLogisticsAttributeIndex(propertyNode);
// 创建新的属性类别
ComApi.InwOaPropertyVec propertyCategory =
(ComApi.InwOaPropertyVec)state.ObjectFactory(
ComApi.nwEObjectType.eObjectType_nwOaPropertyVec, null, null);
// 创建并添加各个属性
AddProperty(state, propertyCategory, LogisticsProperties.TYPE,
elementType.ToString(), elementType.ToString() + "_Internal");
AddProperty(state, propertyCategory, LogisticsProperties.TRAVERSABLE,
isTraversable ? "是" : "否", "Traversable_Internal");
AddProperty(state, propertyCategory, LogisticsProperties.PRIORITY,
priority.ToString(), "Priority_Internal");
AddProperty(state, propertyCategory, LogisticsProperties.VEHICLE_SIZE,
vehicleSize, "VehicleSize_Internal");
AddProperty(state, propertyCategory, LogisticsProperties.SPEED_LIMIT,
speedLimit.ToString("F1") + " km/h", "SpeedLimit_Internal");
// 记录操作前的属性状态
LogPropertyNodeState(propertyNode, "属性更新-操作前");
if (existingIndex >= 0)
{
// 如果存在现有属性,使用覆盖模式 (参数1)
LogManager.WriteLog($"[属性更新] 发现现有物流属性,使用覆盖模式更新");
LogPropertyNodeState(propertyNode, "属性更新-覆盖前");
try
{
// 使用参数1表示覆盖现有PropertyCategory
propertyNode.SetUserDefined(1, LogisticsCategories.LOGISTICS,
LogisticsCategories.CATEGORY_INTERNAL_NAME, propertyCategory);
LogManager.WriteLog($"[属性更新] ✅ 成功覆盖现有属性类别");
// 立即刷新并验证结果
propertyNode = RefreshPropertyNode(state, path, "属性更新-覆盖验证");
LogPropertyNodeState(propertyNode, "属性更新-覆盖后");
}
catch (Exception setEx)
{
LogManager.WriteLog($"[属性更新] ❌ 覆盖属性失败,错误: {setEx.Message}");
throw;
}
}
else
{
// 如果不存在,创建新的属性类别,使用创建模式 (参数0)
LogManager.WriteLog("[属性更新] 未发现现有物流属性,使用创建模式");
LogPropertyNodeState(propertyNode, "属性更新-创建前");
try
{
// 使用参数0表示创建新的PropertyCategory
propertyNode.SetUserDefined(0, LogisticsCategories.LOGISTICS,
LogisticsCategories.CATEGORY_INTERNAL_NAME, propertyCategory);
LogManager.WriteLog("[属性更新] ✅ 成功创建新的属性类别");
// 立即刷新并验证结果
propertyNode = RefreshPropertyNode(state, path, "属性更新-创建验证");
LogPropertyNodeState(propertyNode, "属性更新-创建后");
}
catch (Exception setEx)
{
LogManager.WriteLog($"[属性更新] ❌ 创建属性失败,错误: {setEx.Message}");
throw;
}
}
successCount++;
}
catch (Exception ex)
{
LogManager.WriteLog($"[属性更新] 更新单个模型项时发生错误: {ex.Message}");
}
}
}
catch (Exception ex)
{
LogManager.WriteLog($"[属性更新] 更新物流属性时发生错误: {ex.Message}");
}
LogManager.WriteLog($"[属性更新] 更新操作完成,成功更新 {successCount} 个模型的属性");
return successCount;
}
/// <summary>
/// 通过COM API获取物流属性值解决缓存同步问题
/// </summary>
/// <param name="item">模型项</param>
/// <param name="propertyName">属性名称</param>
/// <returns>属性值,如果不存在返回空字符串</returns>
public static string GetLogisticsPropertyValueViaCom(ModelItem item, string propertyName)
{
try
{
// 获取COM API状态对象
ComApi.InwOpState10 state = ComApiBridge.State;
// 转换ModelItem为COM路径
ComApi.InwOaPath comPath = ComApiBridge.ToInwOaPath(item);
// 获取属性节点
ComApi.InwGUIPropertyNode2 propertyNode =
(ComApi.InwGUIPropertyNode2)state.GetGUIPropertyNode(comPath, false);
// 遍历所有属性类别
foreach (ComApi.InwGUIAttribute2 attribute in propertyNode.GUIAttributes())
{
if (attribute.UserDefined && attribute.ClassUserName == LogisticsCategories.LOGISTICS)
{
// 获取属性集合
ComApi.InwOaPropertyColl propertyColl = attribute.Properties();
// 遍历属性
foreach (ComApi.InwOaProperty property in propertyColl)
{
if (property.UserName == propertyName)
{
string value = property.value.ToString();
LogManager.WriteLog($"[COM API读取] 模型: {item.DisplayName}, 属性: {propertyName}, 值: {value}");
return value;
}
}
}
}
LogManager.WriteLog($"[COM API读取] 模型: {item.DisplayName}, 属性: {propertyName} - 未找到");
}
catch (Exception ex)
{
LogManager.WriteLog($"通过COM API获取物流属性值时发生错误: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"通过COM API获取物流属性值时发生错误: {ex.Message}");
}
return string.Empty;
}
/// <summary>
/// 获取模型项的完整物流属性信息
/// </summary>
/// <param name="item">模型项</param>
/// <returns>物流属性信息如果不存在返回null</returns>
public static LogisticsAttributeInfo GetLogisticsAttributeInfo(ModelItem item)
{
if (!HasLogisticsAttributes(item))
{
return null;
}
try
{
var info = new LogisticsAttributeInfo();
// 使用COM API获取各个属性值以确保数据一致性
info.ElementType = GetLogisticsPropertyValueViaCom(item, LogisticsProperties.TYPE);
info.IsTraversable = GetLogisticsPropertyValueViaCom(item, LogisticsProperties.TRAVERSABLE) == "是";
string priorityStr = GetLogisticsPropertyValueViaCom(item, LogisticsProperties.PRIORITY);
if (int.TryParse(priorityStr, out int priority))
{
info.Priority = priority;
}
info.VehicleSize = GetLogisticsPropertyValueViaCom(item, LogisticsProperties.VEHICLE_SIZE);
string speedStr = GetLogisticsPropertyValueViaCom(item, LogisticsProperties.SPEED_LIMIT);
if (speedStr.Contains("km/h"))
{
speedStr = speedStr.Replace("km/h", "").Trim();
if (double.TryParse(speedStr, out double speed))
{
info.SpeedLimit = speed;
}
}
return info;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"获取物流属性信息时发生错误: {ex.Message}");
return null;
}
}
}
/// <summary>
/// 物流属性信息类
/// </summary>
public class LogisticsAttributeInfo
{
/// <summary>
/// 元素类型
/// </summary>
public string ElementType { get; set; } = "";
/// <summary>
/// 是否可通行
/// </summary>
public bool IsTraversable { get; set; } = true;
/// <summary>
/// 优先级
/// </summary>
public int Priority { get; set; } = 5;
/// <summary>
/// 适用车辆尺寸
/// </summary>
public string VehicleSize { get; set; } = "标准";
/// <summary>
/// 速度限制
/// </summary>
public double SpeedLimit { get; set; } = 10.0;
/// <summary>
/// 尝试解析元素类型为枚举
/// </summary>
/// <returns>解析成功的枚举值,失败返回通道</returns>
public CategoryAttributeManager.LogisticsElementType GetElementTypeEnum()
{
if (Enum.TryParse<CategoryAttributeManager.LogisticsElementType>(ElementType, out var result))
{
return result;
}
return CategoryAttributeManager.LogisticsElementType.;
}
}
}