Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
571 lines
20 KiB
C#
571 lines
20 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using TellmePdmsPluging.Models;
|
|
using Aveva.ApplicationFramework;
|
|
using Aveva.Pdms.Database;
|
|
using System.Linq;
|
|
|
|
namespace TellmePdmsPluging.Core
|
|
{
|
|
public class PdmsManager
|
|
{
|
|
private static PdmsManager _instance;
|
|
private static readonly object _lock = new object();
|
|
|
|
public static PdmsManager Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance == null)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
if (_instance == null)
|
|
_instance = new PdmsManager();
|
|
}
|
|
}
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
private PdmsManager()
|
|
{
|
|
}
|
|
|
|
public SimplifyModelResult SimplifyModel(SimplifyModelRequest request)
|
|
{
|
|
var effectiveRequest = request ?? new SimplifyModelRequest();
|
|
effectiveRequest.ApplyDefaults();
|
|
|
|
var result = new SimplifyModelResult
|
|
{
|
|
DryRun = effectiveRequest.DryRun,
|
|
StartedAt = DateTime.Now
|
|
};
|
|
|
|
try
|
|
{
|
|
if (!IsPdmsConnected())
|
|
{
|
|
result.Success = false;
|
|
result.CompletedAt = DateTime.Now;
|
|
result.Message = "PDMS 未连接";
|
|
result.Errors.Add("PDMS 未连接");
|
|
return result;
|
|
}
|
|
|
|
var currentMdb = MDB.CurrentMDB;
|
|
var designDb = currentMdb?.GetFirstDB(DbType.Design);
|
|
if (designDb == null || designDb.World == null)
|
|
{
|
|
result.Success = false;
|
|
result.CompletedAt = DateTime.Now;
|
|
result.Message = "未找到有效的设计数据库";
|
|
result.Errors.Add("未找到有效的设计数据库");
|
|
return result;
|
|
}
|
|
|
|
var context = new SimplifyContext(effectiveRequest, result);
|
|
var sites = designDb.World.Members();
|
|
bool processed = false;
|
|
|
|
if (sites != null)
|
|
{
|
|
foreach (var site in sites)
|
|
{
|
|
if (!IsElementValid(site) || !string.Equals(GetElementTypeName(site), "SITE", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var zones = site.Members();
|
|
if (zones == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foreach (var zone in zones)
|
|
{
|
|
if (!IsElementValid(zone) || !string.Equals(GetElementTypeName(zone), "ZONE", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!context.ShouldProcessZone(zone))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
processed = true;
|
|
context.EnterZone(zone);
|
|
context.ProcessChildren(zone);
|
|
}
|
|
}
|
|
}
|
|
|
|
result.Success = processed && result.Errors.Count == 0;
|
|
result.Message = processed
|
|
? (result.DryRun ? "模型轻量化干跑完成" : "模型轻量化完成")
|
|
: "未找到符合过滤条件的Zone";
|
|
result.CompletedAt = DateTime.Now;
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result.Success = false;
|
|
result.Errors.Add(ex.Message);
|
|
result.Message = "模型轻量化失败";
|
|
result.CompletedAt = DateTime.Now;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public ModelStatusResponse GetModelStatus()
|
|
{
|
|
try
|
|
{
|
|
// 检查PDMS是否连接
|
|
if (!IsPdmsConnected())
|
|
{
|
|
return new ModelStatusResponse
|
|
{
|
|
ModelLoaded = false
|
|
};
|
|
}
|
|
|
|
return new ModelStatusResponse
|
|
{
|
|
ModelLoaded = true,
|
|
ProjectInfo = GetProjectInfo(),
|
|
ModelStatistics = GetModelStatistics(),
|
|
SessionInfo = GetSessionInfo()
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 记录错误日志
|
|
System.Diagnostics.Debug.WriteLine($"获取PDMS模型状态失败: {ex.Message}");
|
|
return new ModelStatusResponse
|
|
{
|
|
ModelLoaded = false
|
|
};
|
|
}
|
|
}
|
|
|
|
private bool IsPdmsConnected()
|
|
{
|
|
try
|
|
{
|
|
// 使用MDB.CurrentMDB检查PDMS连接状态
|
|
var currentMdb = MDB.CurrentMDB;
|
|
return currentMdb != null;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private ProjectInfo GetProjectInfo()
|
|
{
|
|
try
|
|
{
|
|
// 使用MDB.CurrentMDB和Project.CurrentProject获取真实项目信息
|
|
var currentMdb = MDB.CurrentMDB;
|
|
var currentProject = Project.CurrentProject;
|
|
|
|
if (currentMdb != null)
|
|
{
|
|
var designDb = currentMdb.GetFirstDB(DbType.Design);
|
|
if (designDb != null)
|
|
{
|
|
return new ProjectInfo
|
|
{
|
|
ProjectName = designDb.Name ?? "Unknown",
|
|
MdsName = currentMdb.Name ?? "Unknown",
|
|
PdmsVersion = "12.1.SP4"
|
|
};
|
|
}
|
|
}
|
|
|
|
return new ProjectInfo
|
|
{
|
|
ProjectName = "Unknown",
|
|
MdsName = "Unknown",
|
|
PdmsVersion = "12.1.SP4"
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"获取项目信息失败: {ex.Message}");
|
|
return new ProjectInfo
|
|
{
|
|
ProjectName = "Unknown",
|
|
MdsName = "Unknown",
|
|
PdmsVersion = "12.1.SP4"
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private ModelStatistics GetModelStatistics()
|
|
{
|
|
try
|
|
{
|
|
// 使用MDB.CurrentMDB获取真实模型统计信息
|
|
var currentMdb = MDB.CurrentMDB;
|
|
if (currentMdb != null)
|
|
{
|
|
var designDb = currentMdb.GetFirstDB(DbType.Design);
|
|
if (designDb?.World != null)
|
|
{
|
|
// 初始化统计计数器
|
|
var elementCounts = new Dictionary<string, int>
|
|
{
|
|
{"SITE", 0}, {"ZONE", 0}, {"PIPE", 0}, {"EQUI", 0},
|
|
{"STRU", 0}, {"VALVE", 0}, {"FITT", 0}, {"NOZZ", 0}
|
|
};
|
|
|
|
int totalElements = 0;
|
|
var activeZones = new List<string>();
|
|
int zoneCount = 0;
|
|
|
|
// 递归统计所有元素
|
|
CountElementsByType(designDb.World, elementCounts, ref totalElements);
|
|
|
|
// 专门统计Zone信息
|
|
CountZones(designDb.World, ref zoneCount, activeZones);
|
|
|
|
return new ModelStatistics
|
|
{
|
|
TotalElements = totalElements,
|
|
ElementCounts = elementCounts,
|
|
ZoneCount = zoneCount,
|
|
ActiveZones = activeZones
|
|
};
|
|
}
|
|
}
|
|
|
|
return new ModelStatistics
|
|
{
|
|
TotalElements = 0,
|
|
ElementCounts = new Dictionary<string, int>(),
|
|
ZoneCount = 0,
|
|
ActiveZones = new List<string>()
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"获取模型统计信息失败: {ex.Message}");
|
|
return new ModelStatistics
|
|
{
|
|
TotalElements = 0,
|
|
ElementCounts = new Dictionary<string, int>(),
|
|
ZoneCount = 0,
|
|
ActiveZones = new List<string>()
|
|
};
|
|
}
|
|
}
|
|
|
|
private void CountElementsByType(DbElement parentElement, Dictionary<string, int> elementCounts, ref int totalElements)
|
|
{
|
|
try
|
|
{
|
|
if (parentElement == null || parentElement.IsNull || !parentElement.IsValid)
|
|
return;
|
|
|
|
// 获取所有子元素
|
|
var members = parentElement.Members();
|
|
if (members != null)
|
|
{
|
|
foreach (var element in members)
|
|
{
|
|
if (element != null && !element.IsNull && element.IsValid)
|
|
{
|
|
totalElements++;
|
|
|
|
// 获取元素的实际类型
|
|
var elementType = element.GetActualType();
|
|
if (elementType != null)
|
|
{
|
|
string typeName = elementType.Name;
|
|
if (elementCounts.ContainsKey(typeName))
|
|
{
|
|
elementCounts[typeName]++;
|
|
}
|
|
}
|
|
|
|
// 递归统计子元素
|
|
CountElementsByType(element, elementCounts, ref totalElements);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"统计元素类型时出错: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void CountZones(DbElement worldElement, ref int zoneCount, List<string> activeZones)
|
|
{
|
|
try
|
|
{
|
|
if (worldElement == null || worldElement.IsNull || !worldElement.IsValid)
|
|
return;
|
|
|
|
// 查找SITE元素
|
|
var sites = worldElement.Members();
|
|
if (sites != null)
|
|
{
|
|
foreach (var site in sites)
|
|
{
|
|
if (site != null && !site.IsNull && site.IsValid)
|
|
{
|
|
var siteType = site.GetActualType();
|
|
if (siteType != null && siteType.Name == "SITE")
|
|
{
|
|
// 在SITE下查找ZONE元素
|
|
var zones = site.Members();
|
|
if (zones != null)
|
|
{
|
|
foreach (var zone in zones)
|
|
{
|
|
if (zone != null && !zone.IsNull && zone.IsValid)
|
|
{
|
|
var zoneType = zone.GetActualType();
|
|
if (zoneType != null && zoneType.Name == "ZONE")
|
|
{
|
|
zoneCount++;
|
|
|
|
// 获取Zone名称
|
|
try
|
|
{
|
|
string zoneName = "";
|
|
if (zone.GetValidString(DbAttributeInstance.NAME, ref zoneName))
|
|
{
|
|
if (!string.IsNullOrEmpty(zoneName))
|
|
{
|
|
activeZones.Add(zoneName);
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 如果无法获取名称,跳过
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"统计Zone信息时出错: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private SessionInfo GetSessionInfo()
|
|
{
|
|
try
|
|
{
|
|
// 使用MDB.CurrentMDB获取真实会话信息
|
|
var currentMdb = MDB.CurrentMDB;
|
|
if (currentMdb != null)
|
|
{
|
|
var designDb = currentMdb.GetFirstDB(DbType.Design);
|
|
if (designDb?.CurrentSession != null)
|
|
{
|
|
// 从真实的数据库会话获取信息
|
|
var session = designDb.CurrentSession;
|
|
return new SessionInfo
|
|
{
|
|
UserName = session.User ?? Environment.UserName, // 从DbSession获取用户名
|
|
StartTime = session.Date, // 从DbSession获取会话创建时间
|
|
DurationMinutes = (int)(DateTime.Now - session.Date).TotalMinutes // 计算会话持续时间
|
|
};
|
|
}
|
|
}
|
|
|
|
return new SessionInfo
|
|
{
|
|
UserName = Environment.UserName,
|
|
StartTime = DateTime.Now,
|
|
DurationMinutes = 0
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"获取会话信息失败: {ex.Message}");
|
|
return new SessionInfo
|
|
{
|
|
UserName = Environment.UserName,
|
|
StartTime = DateTime.Now,
|
|
DurationMinutes = 0
|
|
};
|
|
}
|
|
}
|
|
private static bool IsElementValid(DbElement element)
|
|
{
|
|
return element != null && !element.IsNull && element.IsValid;
|
|
}
|
|
|
|
private static string GetElementTypeName(DbElement element)
|
|
{
|
|
try
|
|
{
|
|
var type = element?.GetActualType();
|
|
return type?.Name ?? string.Empty;
|
|
}
|
|
catch
|
|
{
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
private static string BuildElementPath(DbElement element)
|
|
{
|
|
var segments = new List<string>();
|
|
var current = element;
|
|
int guard = 0;
|
|
|
|
while (IsElementValid(current) && guard < 128)
|
|
{
|
|
string name = string.Empty;
|
|
try
|
|
{
|
|
if (!current.GetValidString(DbAttributeInstance.NAME, ref name) || string.IsNullOrEmpty(name))
|
|
{
|
|
name = current.ToString();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
name = current.ToString();
|
|
}
|
|
|
|
segments.Add(name.Trim());
|
|
current = current.Owner;
|
|
guard++;
|
|
}
|
|
|
|
segments.Reverse();
|
|
return "/" + string.Join("/", segments.ToArray());
|
|
}
|
|
|
|
private class SimplifyContext
|
|
{
|
|
private const int MaxRemovedSnapshots = 200;
|
|
|
|
public SimplifyContext(SimplifyModelRequest request, SimplifyModelResult result)
|
|
{
|
|
Request = request;
|
|
Result = result;
|
|
_keepTypes = new HashSet<string>(request.KeepTypes ?? new List<string>());
|
|
_removeTypes = new HashSet<string>(request.RemoveTypes ?? new List<string>());
|
|
}
|
|
|
|
public SimplifyModelRequest Request { get; }
|
|
public SimplifyModelResult Result { get; }
|
|
public string CurrentZoneName { get; private set; }
|
|
|
|
private readonly HashSet<string> _keepTypes;
|
|
private readonly HashSet<string> _removeTypes;
|
|
|
|
public bool ShouldProcessZone(DbElement zone)
|
|
{
|
|
if (Request.ZoneFilters == null || Request.ZoneFilters.Count == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var zonePath = BuildElementPath(zone).ToUpperInvariant();
|
|
return Request.ZoneFilters.Any(filter => zonePath.Contains(filter));
|
|
}
|
|
|
|
public void EnterZone(DbElement zone)
|
|
{
|
|
CurrentZoneName = BuildElementPath(zone);
|
|
if (!Result.ZoneSummaries.Contains(CurrentZoneName))
|
|
{
|
|
Result.ZoneSummaries.Add(CurrentZoneName);
|
|
}
|
|
}
|
|
|
|
public void ProcessChildren(DbElement parent)
|
|
{
|
|
var members = parent.Members();
|
|
if (members == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (var child in members)
|
|
{
|
|
ProcessElement(child);
|
|
}
|
|
}
|
|
|
|
private void ProcessElement(DbElement element)
|
|
{
|
|
if (!IsElementValid(element))
|
|
{
|
|
return;
|
|
}
|
|
|
|
Result.TotalVisited++;
|
|
var typeName = GetElementTypeName(element);
|
|
var normalizedType = string.IsNullOrEmpty(typeName) ? string.Empty : typeName.ToUpperInvariant();
|
|
|
|
bool keep = _keepTypes.Contains(normalizedType);
|
|
bool remove = _removeTypes.Contains(normalizedType) && !keep;
|
|
|
|
if (remove)
|
|
{
|
|
RemoveElement(element, normalizedType);
|
|
return;
|
|
}
|
|
|
|
Result.KeptCount++;
|
|
ProcessChildren(element);
|
|
}
|
|
|
|
private void RemoveElement(DbElement element, string typeName)
|
|
{
|
|
var elementPath = BuildElementPath(element);
|
|
|
|
if (Request.DryRun)
|
|
{
|
|
SnapshotRemoval(elementPath, typeName, true);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
element.Delete();
|
|
SnapshotRemoval(elementPath, typeName, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Result.Errors.Add($"删除元素 {elementPath} 失败: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void SnapshotRemoval(string elementPath, string typeName, bool dryRun)
|
|
{
|
|
Result.RemovedCount++;
|
|
|
|
if (Result.RemovedElements.Count < MaxRemovedSnapshots)
|
|
{
|
|
var marker = dryRun ? "DRY" : "DEL";
|
|
Result.RemovedElements.Add($"[{marker}] {elementPath} ({typeName})");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |