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 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 { /// /// 绘制材料表相关的(By YuXH) /// [HandlerApiLogin(FilterMode.Ignore)] public class PlotBOMApiController : WebApiControllerBase { /// /// 获取材料表绘制所需的分组信息、symbol信息 /// /// /// /// [HttpGet] public IHttpActionResult GetBOMGroupInfo(string ProjectId = "c151f5d4-cbe1-4522-945c-501b1ad990d5", string drawingId = "277d883d-e271-45e4-990b-926585321fa8") { var res = new List();//声明结果 #region 表名 var typeTbName = ProjectSugar.TableName(ProjectId); var pixelTbName = ProjectSugar.TableName(ProjectId); var tagTbName = ProjectSugar.TableName(ProjectId); var propTbName = ProjectSugar.TableName(ProjectId); var fileTbName = ProjectSugar.TableName(ProjectId); #endregion #region 全局数据 var allTag = SqlSugarHelper.Db.Queryable().AS(tagTbName) .InnerJoin((t, p) => t.EngineDataID == p.EngineDataID && p.DrawingFileID == drawingId) .AS(pixelTbName) .GroupBy(t => t.ObjectTypeID) .ToList(); var allProp = SqlSugarHelper.Db.Queryable().AS(propTbName) .Where(x => allTag.Select(t => t.EngineDataID).Contains(x.EngineDataID)) .ToList(); var allType = SqlSugarHelper.Db.Queryable().AS(typeTbName) .Where(x => allTag.Select(t => t.ObjectTypeID).Contains(x.ObjectTypeID)) .ToList(); var allLib = SqlSugarHelper.Db.Queryable().AS(fileTbName) .ToList(); #endregion //1.先按类型分组 //2.去除tagnumber下的右侧数字 //3.再按几个属性分组 //设备型号 和 厂商 var TagsInBOM = new List(); #region 预处理每个位号,然后进行分组 foreach (ec_enginedataEntity tag in allTag) { var matchedTypes = new List(); var idx = 0; var GroupName = TrimTagNubmer(tag.TagNumber, out idx);// 如 A-B1,A-B2,取出来的group就是A-B,idx为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 allTagsInThisGroup = group.ToList(); var GroupName = group.Key.Group; //A-ABC, 正常情况下A是system,放下面;B是tag,放上面 var upper_text_Part1 = GroupName.Split('-')[1];//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 = GroupName.Split('-')[0],//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); } /// /// 从字符串中提取数字(可能出现1A 1B这样的情况) /// private static List ExtractNumbers(List stringNumbers) { var numbers = new List(); 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; } /// /// 决定应该用哪个symbol /// /// /// string GetSymbolForBOM(ec_objecttypeEntity T, List 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; } /// /// 去除tagnumber下的右侧数字 /// /// /// 去除数字后的段落,是整个tagNumber的第几位 /// 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; } /// /// 去除数字后的内容,大概率是A-B。A为system,B为tag /// public string Group { set; get; } /// /// 正常情况下 Group + Seq = TagNumber /// public string Seq { set; get; } /// /// 厂商,对应 /// public string vendor { set; get; } /// /// 设备型号,对应 /// public string Model { set; get; } /// /// 电制 /// public string Volt { set; get; } /// /// 额定功率 /// public string RatingPower { set; get; } /// /// ip等级 /// public string IPLevel { set; get; } /// /// 防爆等级 /// public string ExplosionProofLevel { set; get; } /// /// 中文名称(针对某些特殊类型的分组需要用到) /// public string Name { set; get; } } public class BOMGroupInfo { public string upper_text { set; get; } public string lower_text { set; get; } /// /// 每一行用的symbol是什么 /// public string FileId { set; get; } /// /// 个数 /// public int Count { set; get; } /// /// 备注(由 厂商) /// public string Remark { set; get; } /// /// 规格(由 电制 额定功率 ip等级 防爆等级等属性拼接而成) /// public string Spec { set; get; } /// /// 型号 /// public string Model { set; get; } } }