009_DI-Elec/Learun.Application.Web/AppApi/PlotBOMApiController.cs
2025-10-17 16:45:00 +08:00

302 lines
12 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 Learun.Application.TwoDevelopment.ZZDT_EC;
using Learun.Util;
using Learun.Util.SqlSugar;
using NPOI.SS.Formula.Functions;
using NPOI.SS.Formula.PTG;
using NPOI.Util.Collections;
using OfficeOpenXml.Drawing.Vml;
using Pipelines.Sockets.Unofficial.Arenas;
using SWS.Share;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Http;
using System.Windows.Controls;
namespace Learun.Application.Web.AppApi
{
/// <summary>
/// 绘制材料表相关的By YuXH
/// </summary>
[HandlerApiLogin(FilterMode.Ignore)]
public class PlotBOMApiController : WebApiControllerBase
{
/// <summary>
/// 获取材料表绘制所需的分组信息、symbol信息
/// </summary>
/// <param name="ProjectId"></param>
/// <param name="drawingId"></param>
/// <returns></returns>
[HttpGet]
public IHttpActionResult GetBOMGroupInfo(string ProjectId = "403ee1e6-ca2e-4acc-9667-273afd4ea93c", string drawingId = "db834963-f62b-4c44-8180-1b9073819546")
{
var res = new List<BOMGroupInfo>();//声明结果
#region
var typeTbName = ProjectSugar.TableName<ec_objecttypeEntity>(ProjectId);
var pixelTbName = ProjectSugar.TableName<ec_enginedata_pixelEntity>(ProjectId);
var tagTbName = ProjectSugar.TableName<ec_enginedataEntity>(ProjectId);
var propTbName = ProjectSugar.TableName<ec_enginedata_propertyEntity>(ProjectId);
var fileTbName = ProjectSugar.TableName<ec_library_fileEntity>(ProjectId);
#endregion
#region
var allTag = SqlSugarHelper.Db.Queryable<ec_enginedataEntity>().AS(tagTbName)
.InnerJoin<ec_enginedata_pixelEntity>((t, p) => t.EngineDataID == p.EngineDataID && p.DrawingFileID == drawingId)
.AS<ec_enginedata_pixelEntity>(pixelTbName)
.GroupBy(t => t.ObjectTypeID)
.ToList();
var allProp = SqlSugarHelper.Db.Queryable<ec_enginedata_propertyEntity>().AS(propTbName)
.Where(x => allTag.Select(t => t.EngineDataID).Contains(x.EngineDataID))
.ToList();
var allType = SqlSugarHelper.Db.Queryable<ec_objecttypeEntity>().AS(typeTbName)
.Where(x => allTag.Select(t => t.ObjectTypeID).Contains(x.ObjectTypeID))
.ToList();
var allLib = SqlSugarHelper.Db.Queryable<ec_library_fileEntity>().AS(fileTbName)
.ToList();
#endregion
//1.先按类型分组
//2.去除tagnumber下的右侧数字
//3.再按几个属性分组
//设备型号 和 厂商
var TagsInBOM = new List<BOMTagInfo>();
#region
foreach (ec_enginedataEntity tag in allTag)
{
if(tag.TagNumber.Length==38&&tag.TagNumber.Contains("{"))
{ continue; }
var matchedTypes = new List<string>();
var idx = 0;
var GroupName = TrimTagNubmer(tag.TagNumber, out idx);// 如 A-B1,A-B2,取出来的group就是A-Bidx为0
var seq = tag.TagNumber.Substring(idx).Replace(GroupName, "");// 1,2
var BOMTagInfo = new BOMTagInfo()
{
objectTypeId = tag.ObjectTypeID,
TagNumber = tag.TagNumber,
Group = GroupName,// 如 A-B1,A-B2,
vendor = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == "厂商")?.PropertyValue ?? "",
Model = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == "设备型号")?.PropertyValue ?? "",
Volt = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == "电制")?.PropertyValue ?? "",
RatingPower = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == "额定功率")?.PropertyValue ?? "",
IPLevel = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == "IP等级")?.PropertyValue ?? "",
ExplosionProofLevel = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == "防爆等级")?.PropertyValue ?? "",
Name = "",
Seq = seq
};
//???特定类型的,还需要额外根据”中文名称“来分组,比如照明设备类型下的所有设备
if (matchedTypes.Contains(tag.ObjectTypeID))
{
//如照明下的。比如10个照明的灯4个中文名称是“顶灯”6个中文名称是“壁灯”
BOMTagInfo.Name = allProp.FirstOrDefault(x => x.EngineDataID == tag.EngineDataID && x.PropertyName == GlobalObject.propName_NameCN)?.PropertyValue ?? "";
}
TagsInBOM.Add(BOMTagInfo);
}
var groups = TagsInBOM.GroupBy(x => new
{
x.objectTypeId,
x.Group,
x.vendor,
x.Model,
x.Volt,
x.IPLevel,
x.RatingPower,
x.ExplosionProofLevel,
x.Name
}).ToList();
#endregion
foreach (var group in groups)
{
List<BOMTagInfo> allTagsInThisGroup = group.ToList();
var GroupName = group.Key.Group; //A-ABC, 正常情况下A是system放下面B是tag放上面
string part1 = string.Empty;
string part0 = string.Empty;
if (!GroupName.Contains("-"))
{
part1 = GroupName;
}
else
{
part0 = GroupName.Split('-')[0];
part1 = GroupName.Split('-')[1];//ABC
}
var upper_text_Part1 = part1;//ABC
var upper_text_Part2 = "";//seq
#region seq的不同情况
//得到每个位号下的seq
var allSeqText = allTagsInThisGroup.OrderBy(x => x.Seq).Select(x => x.Seq).ToList();
var allSeq = ExtractNumbers(allSeqText);//把1A 1B 这种情况也处理了变成1,1
if (allSeq.Distinct().Count() <= 1)
{
//TAG如果一样的就取这个TAG就行???
upper_text_Part2 = allSeqText.First();
}
//数里小于等于2个
else if (allTagsInThisGroup.Count <= 2)
{
//遍历每一个group下的原始 ec_enginedataEntity.TagNumber里的数字。比如2个分别是 1 2 那么就显示1,2
//就是这里就是2个因为1个的话第一个if已经处理了
upper_text_Part2 = allSeqText[0] + "," + allSeqText[1];
}
else
{
//遍历每一个group下的原始 ec_enginedataEntity.TagNumber里的数字
//有一种情况还需要明确 1A 1B 1C这种
upper_text_Part2 = ec_enginedataEntity.FindConsecutiveSequences(allSeq).ToString();
}
#endregion
var typeInfo = allType.FirstOrDefault(x => x.ObjectTypeID == group.Key.objectTypeId);
var specCombine = $"{group.Key.Volt} {group.Key.RatingPower} {group.Key.IPLevel} {group.Key.ExplosionProofLevel}";
var BOMGroupInfo = new BOMGroupInfo
{
upper_text = upper_text_Part1 + upper_text_Part2,
lower_text = part0,//A
Count = group.Count(),
Remark = group.Key.vendor,
Model = group.Key.Model,
Spec = specCombine,
FileId = GetSymbolForBOM(typeInfo, allLib)
};
if (BOMGroupInfo.upper_text == BOMGroupInfo.lower_text)
{
//如果SYSTEM等于TAG那么隐藏SYSTEM
BOMGroupInfo.lower_text = "";//
}
res.Add(BOMGroupInfo);
}
return Success(res);
}
/// <summary>
/// 从字符串中提取数字可能出现1A 1B这样的情况
/// </summary>
private static List<int> ExtractNumbers(List<string> stringNumbers)
{
var numbers = new List<int>();
if (stringNumbers == null || !stringNumbers.Any())
return numbers;
// 正则表达式:匹配字符串中的所有数字
var regex = new Regex(@"\d+");
foreach (var str in stringNumbers)
{
if (string.IsNullOrWhiteSpace(str))
continue;
// 提取字符串中的第一个数字(如"1a"提取1"a2b3"提取2
var match = regex.Match(str);
if (match.Success && int.TryParse(match.Value, out int num))
{
numbers.Add(num);
}
}
return numbers;
}
/// <summary>
/// 决定应该用哪个symbol
/// </summary>
/// <param name="objectTypeId"></param>
/// <returns></returns>
string GetSymbolForBOM(ec_objecttypeEntity T, List<ec_library_fileEntity> allLib)
{
var fileId = "default";
//3个level
//1.插件端文件夹下的某个默认symbol
var fileIdOnType = allLib.FirstOrDefault(x => x.LibraryFileID == T.DefaultBOMFileID);
if (fileIdOnType != null)
{
return fileIdOnType.LibraryFileID;
}
//2.对象类型下的默认symbol
//3.满足某个细分类型的symbol比如按中文名称来分组的一些特别东西
//马达,圆形
//通讯设备-外通设备-天线,三角形
return fileId;
}
/// <summary>
/// 去除tagnumber下的右侧数字
/// </summary>
/// <param name="tagNumber"></param>
/// <param name="replaceStartIdx">去除数字后的段落是整个tagNumber的第几位</param>
/// <returns></returns>
string TrimTagNubmer(string tagNumber, out int replaceStartIdx)
{
//1MAC-PT1 和 1MAC-PT2 归为一组剩下的是1MAC-PT 而不是MAC-PT
// 还要考虑1A 1B这种后缀情况
//1MAC-PT1A 1MAC-PT1B 归为一组剩下的是1MAC-PT而不是变成1MAC-PT1A 和 1MAC-PT1B
replaceStartIdx = 0;
return tagNumber;
}
}
public class BOMTagInfo
{
public string objectTypeId { set; get; }
public string TagNumber { set; get; }
/// <summary>
/// 去除数字后的内容大概率是A-B。A为systemB为tag
/// </summary>
public string Group { set; get; }
/// <summary>
/// 正常情况下 Group + Seq = TagNumber
/// </summary>
public string Seq { set; get; }
/// <summary>
/// 厂商,对应<see cref="BOMGroupInfo.Remark"/>
/// </summary>
public string vendor { set; get; }
/// <summary>
/// 设备型号,对应<see cref="BOMGroupInfo.Model"/>
/// </summary>
public string Model { set; get; }
/// <summary>
/// 电制
/// </summary>
public string Volt { set; get; }
/// <summary>
/// 额定功率
/// </summary>
public string RatingPower { set; get; }
/// <summary>
/// ip等级
/// </summary>
public string IPLevel { set; get; }
/// <summary>
/// 防爆等级
/// </summary>
public string ExplosionProofLevel { set; get; }
/// <summary>
/// 中文名称(针对某些特殊类型的分组需要用到)
/// </summary>
public string Name { set; get; }
}
}