009_DI-Elec/Learun.Application.Web/AppApi/PlotLayoutApiController.cs

543 lines
26 KiB
C#
Raw Normal View History

2025-08-13 11:14:39 +08:00
using Learun.Application.TwoDevelopment.ZZDT_EC;
2025-09-16 09:51:40 +08:00
using Learun.Application.TwoDevelopment.ZZDT_EC.Frame;
2025-08-13 11:14:39 +08:00
using Learun.Util;
using Learun.Util.SqlSugar;
2025-08-29 15:16:09 +08:00
using NPOI.SS.Formula.Functions;
2025-08-13 11:14:39 +08:00
using NPOI.SS.Formula.PTG;
using NPOI.Util.Collections;
using Pipelines.Sockets.Unofficial.Arenas;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime;
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 PlotLayoutApiController : WebApiControllerBase
{
/// <summary>
/// 查找一个图上的所有基点
/// </summary>
/// <param name="keyProp">所属系统 甲板号 区域 的其中一个</param>
/// <param name="keyOperator"></param>
/// <param name="keyValue"></param>
/// <param name="ProjectId"></param>
/// <param name="drawingId"></param>
/// <returns></returns>
[HttpGet]
public IHttpActionResult GetBasePointByDwg(string keyProp, string keyOperator, string keyValue, string ProjectId = "c151f5d4-cbe1-4522-945c-501b1ad990d5", string drawingId = "277d883d-e271-45e4-990b-926585321fa8")
{
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 listTbName = ProjectSugar.TableName<ec_dataitemEntity>(ProjectId);
var detailTbName = ProjectSugar.TableName<ec_dataitemdetailEntity>(ProjectId);
var typeFilterTbName = ProjectSugar.TableName<ec_objTypeLayoutFilter>(ProjectId);
var typeFilterPTbName = ProjectSugar.TableName<ec_objTypeLayoutFilterP>(ProjectId);
var allFilter = SqlSugarHelper.Db.Queryable<ec_objTypeLayoutFilter>().AS(typeFilterTbName).ToList();
var allFilterP = SqlSugarHelper.Db.Queryable<ec_objTypeLayoutFilterP>().AS(typeFilterPTbName).ToList();
var allType = SqlSugarHelper.Db.Queryable<ec_objecttypeEntity>().AS(typeTbName).ToList();
var pointType = allType.First(x => x.ObjectTypeName == GlobalObject.objectType_Base);
if (pointType == null)
{
return Fail("找不到基点这个对象类型。");
}
#region frame
2025-09-16 09:51:40 +08:00
var frameBll = new FrameBll();
var frameLists = frameBll.GetFrameList(ProjectId);
if (frameLists == null)
2025-08-13 11:14:39 +08:00
{
2025-09-16 09:51:40 +08:00
return Fail("项目数据字典中,没有找到【肋位号】的下拉项中。");// 或者 无法从数据字典中找到对应的那个下拉
2025-08-13 11:14:39 +08:00
}
2025-09-25 16:56:23 +08:00
ec_dataitemBLL ec_DataitemBLL = new ec_dataitemBLL();
var roomLists = ec_DataitemBLL.GetDetailList("RoomNo", "", ProjectId, false);
if (roomLists == null)
{
return Fail("项目数据字典中,没有找到【房间号】的下拉项中。");// 或者 无法从数据字典中找到对应的那个下拉
}
2025-08-13 11:14:39 +08:00
#endregion
var pointsOnDwg = SqlSugarHelper.Db.Queryable<ec_enginedata_pixelEntity>().AS(pixelTbName).
Where(x => x.DrawingFileID == drawingId && x.DeleteFlg==0).ToList();
2025-08-13 11:14:39 +08:00
var pointTags = SqlSugarHelper.Db.Queryable<ec_enginedataEntity>().AS(tagTbName).
Where(x => pointsOnDwg.Select(y => y.EngineDataID).Distinct().Contains(x.EngineDataID)
&& x.ObjectTypeID == pointType.ObjectTypeID).ToList();
var propAll = SqlSugarHelper.Db.Queryable<ec_enginedata_propertyEntity>().AS(propTbName).ToList();
//Where(x => x.PropertyName == GlobalObject.propName_Frame
//|| x.PropertyName == GlobalObject.propName_FrameOff
//|| x.PropertyName == GlobalObject.propName_YOff
//|| x.PropertyName == GlobalObject.propName_System
//|| x.PropertyName == "甲板号"
//|| x.PropertyName == "区域").ToList();
List<layoutTagInfoBrief> res = new List<layoutTagInfoBrief>();
foreach (var pointTag in pointTags)
{
var tagProps = propAll.FindAll(x => x.EngineDataID == pointTag.EngineDataID);
var Prop_Frame = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_Frame)?.PropertyValue;
if (Prop_Frame != null)
{
Prop_Frame = Prop_Frame.Split(new string[] { GlobalObject.enum_separator }, StringSplitOptions.None)[0];//插件端对于下拉列表 都是 name || nameEN
2025-09-25 16:56:23 +08:00
}
var Prop_Room = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_Room)?.PropertyValue;
if (Prop_Room != null)
{
Prop_Room = Prop_Room.Split(new string[] { GlobalObject.enum_separator }, StringSplitOptions.None)[0];//插件端对于下拉列表 都是 name || nameEN
}
var matchedFrame = frameLists.FirstOrDefault(X => X.Num == Prop_Frame);
2025-09-25 16:56:23 +08:00
var matchedRoom = roomLists.FirstOrDefault(X => X.DataItemName == Prop_Room);
if (matchedFrame == null && matchedRoom == null)
{
//没有
//无效的基点
var layoutTagInvalid = new layoutTagInfoBrief()
{
EngineDataID = pointTag.EngineDataID,
FileId = "",
PixelOnDwg = pointsOnDwg.FirstOrDefault(x => x.EngineDataID == pointTag.EngineDataID)?.PixelCode,
TagNumber = pointTag.TagNumber,
area = "ERR"
};
res.Add(layoutTagInvalid);
continue;
}
2025-09-25 16:56:23 +08:00
double xValue = 0 ;
if (matchedFrame != null)
{
xValue = frameLists.FirstOrDefault(X => X.Num == Prop_Frame).Value;
if (xValue < 400)
{
// 小于400我几乎可以认为此时肋位号用的是m这个单位。因为如果用的是mm400mm的肋位号似乎也太小了。
xValue = 1000 * xValue; // 转成mm
}
}
string strRoom = string.Empty;
if (matchedRoom != null)
2025-08-29 15:16:09 +08:00
{
2025-09-25 16:56:23 +08:00
strRoom = matchedRoom.DataItemName;
2025-08-29 15:16:09 +08:00
}
2025-09-25 16:56:23 +08:00
2025-08-13 11:14:39 +08:00
var Prop_FrameOff = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_FrameOff)?.PropertyValue;
var Prop_YOff = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_YOff)?.PropertyValue;
var DECK = tagProps.FirstOrDefault(x => x.PropertyName == "甲板号")?.PropertyValue;
var AREA = tagProps.FirstOrDefault(x => x.PropertyName == "区域")?.PropertyValue;
2025-09-01 13:24:47 +08:00
var BasePointProp_scale = tagProps.FirstOrDefault(x => x.PropertyName == "比例");
2025-08-13 11:14:39 +08:00
var layoutTag = new layoutTagInfoBrief()
{
2025-09-01 13:24:47 +08:00
2025-08-13 11:14:39 +08:00
EngineDataID = pointTag.EngineDataID,
FileId = "",
PixelOnDwg = pointsOnDwg.FirstOrDefault(x => x.EngineDataID == pointTag.EngineDataID)?.PixelCode,
TagNumber = pointTag.TagNumber,
2025-08-29 15:16:09 +08:00
X = xValue,
2025-08-13 11:14:39 +08:00
XOff = Prop_FrameOff,
YOff = Prop_YOff,
deck = DECK,
2025-09-01 13:24:47 +08:00
area = AREA,
2025-09-25 16:56:23 +08:00
Scale = BasePointProp_scale == null ? 1 : (double.TryParse(BasePointProp_scale.PropertyValue, out double scale) ? scale : 1),
RoomNo = strRoom
2025-08-13 11:14:39 +08:00
};
2025-09-24 18:39:10 +08:00
layoutTag.Scale = 1.0 / layoutTag.Scale; // 这里的比例是放大多少倍,所以取倒数。
2025-08-13 11:14:39 +08:00
res.Add(layoutTag);
}
res = res.OrderByDescending(x => x.RoomNo).ToList();
2025-08-13 11:14:39 +08:00
// 找出area和deck列组合重复的行
var duplicateGroups = res
.GroupBy(r => new { r.area, r.deck, r.RoomNo })
2025-08-13 11:14:39 +08:00
.Where(g => g.Count() > 1)
.ToList();
if (duplicateGroups.Any())
{
return Fail("该图纸上有甲板、房间号信息重复的基点存在。");
2025-08-13 11:14:39 +08:00
}
//这里要考虑下拉列表 带 ||的问题
List<string> matchedTagIds = new List<string>();
//if (keyProp == GlobalObject.propName_System)
//{
//#task 9536
// 筛选出所有以 "a||" 或 "b||" 开头的元素
var validSystems = keyValue.Split(';').ToList();
matchedTagIds = propAll.Where(item =>
item.PropertyName == keyProp &&
(validSystems.Any(prefix => item.PropertyValue == prefix) || validSystems.Any(prefix => item.PropertyValue.StartsWith(prefix + GlobalObject.enum_separator)))
).Select(X => X.EngineDataID).Distinct().ToList();
//}
//else
//{
// matchedTagIds = propAll.Where(x => x.PropertyName == keyProp
// && (x.PropertyValue == keyValue || x.PropertyValue.StartsWith(keyValue + GlobalObject.enum_separator))).
// Select(X => X.EngineDataID).Distinct().ToList();
//}
2025-08-13 11:14:39 +08:00
//有效范围的设备
var matchedTags = SqlSugarHelper.Db.Queryable<ec_enginedataEntity>().AS(tagTbName).
InnerJoin<ec_objecttypeEntity>((a, b) => a.ObjectTypeID == b.ObjectTypeID).AS<ec_objecttypeEntity>(typeTbName).
2025-08-13 11:14:39 +08:00
Where(a => matchedTagIds.Contains(a.EngineDataID)
&& a.ObjectTypeID != pointType.ObjectTypeID)
.Select((a, b) => new { a.EngineDataID, a.TagNumber, a.ObjectTypeID, b.DefaultLayoutLibFileID })
.ToList();
//有效范围的设备的所有属性
var EquipPropAll = propAll.Where(x => matchedTags.Select(y => y.EngineDataID).Contains(x.EngineDataID))
.Select(x=>new ec_enginedata_propertyEntity {
PropertyName=x.PropertyName,
PropertyValue=x.PropertyValue,
EngineDataID=x.EngineDataID,
Marker = false
}).ToList();
2025-08-13 11:14:39 +08:00
foreach (var basePoint in res)
{
#region
//甲板 区域都和基点一致的设备
var DeckMatchedTagIds = EquipPropAll.Where(x => x.PropertyName == "甲板号" && (x.PropertyValue?.Split(new[] { "||" }, StringSplitOptions.None)[0] == basePoint.deck) && x.Marker==false).Select(X => X.EngineDataID).ToList();
//var AreaMatchedTagIds = EquipPropAll.Where(x => x.PropertyName == "区域" && x.PropertyValue == basePoint.area).Select(X => X.EngineDataID).ToList();
//#task 9542
var matchPointTagIds = DeckMatchedTagIds;//.Intersect(AreaMatchedTagIds).ToList();
var matchPointTagIdSet = new System.Collections.Generic.HashSet<string>(matchPointTagIds);
2025-08-13 11:14:39 +08:00
foreach (var matchPointTagId in matchPointTagIds)
{
var tagInfo = matchedTags.FirstOrDefault(X => X.EngineDataID == matchPointTagId);
2025-08-13 11:14:39 +08:00
var tagProps = EquipPropAll.Where(x => x.EngineDataID == matchPointTagId).ToList();
var Prop_Frame = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_Frame)?.PropertyValue;
if (Prop_Frame != null)
{
Prop_Frame = Prop_Frame.Split(new string[] { GlobalObject.enum_separator }, StringSplitOptions.None)[0];//插件端对于下拉列表 都是 name || nameEN
}
2025-09-25 16:56:23 +08:00
var Prop_RoomNo = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_Room)?.PropertyValue;
if (Prop_RoomNo != null)
{
Prop_RoomNo = Prop_RoomNo.Split(new string[] { GlobalObject.enum_separator }, StringSplitOptions.None)[0];//插件端对于下拉列表 都是 name || nameEN
}
var matchedFrame = frameLists.FirstOrDefault(X => X.Num == Prop_Frame);
var matchedRoom = roomLists.FirstOrDefault(x => x.DataItemName == Prop_RoomNo || x.DataItemName+" "+ x.DataItemNameEN==Prop_RoomNo);
2025-09-25 16:56:23 +08:00
if (matchedFrame == null && matchedRoom == null)
{
var layoutTagInfoInvalid = new layoutTagInfoBrief()
{
EngineDataID = matchPointTagId,
PixelOnDwg = "",
TagNumber = tagInfo.TagNumber,
area = "ERR",
};
basePoint.Tags.Add(layoutTagInfoInvalid);
foreach (var item in EquipPropAll)
{
if (matchPointTagIdSet.Contains(item.EngineDataID))
item.Marker = true;
}
continue;
}
2025-09-25 16:56:23 +08:00
double xValue = 0;
if (matchedFrame != null)
2025-08-29 15:16:09 +08:00
{
2025-09-25 16:56:23 +08:00
xValue = frameLists.FirstOrDefault(X => X.Num == Prop_Frame).Value;
if (xValue < 400)
{
// 小于400我几乎可以认为此时肋位号用的是m这个单位。因为如果用的是mm400mm的肋位号似乎也太小了。
xValue = 1000 * xValue; // 转成mm
}
}
string strRoom = string.Empty;
if (matchedRoom != null)
{
strRoom = matchedRoom.DataItemName;
2025-08-29 15:16:09 +08:00
}
2025-08-13 11:14:39 +08:00
var Prop_FrameOff = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_FrameOff)?.PropertyValue;
var Prop_YOff = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_YOff)?.PropertyValue;
2025-08-29 15:16:09 +08:00
var systemProp = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_System)?.PropertyValue;
var tagProp = tagProps.FirstOrDefault(x => x.PropertyName == GlobalObject.propName_Tag)?.PropertyValue;
2025-08-13 11:14:39 +08:00
#region
var fileId = tagInfo.DefaultLayoutLibFileID;
var matched = false;
var isNotDefaultSymbol = true;
2025-08-13 11:14:39 +08:00
foreach (var filter in allFilter.Where(x => x.ObjectTypeId == tagInfo.ObjectTypeID))
{
if (matched)
{
//有一个满足就可以了
break;
}
var filterOp = filter.Operator;//and or
var filterPs = allFilterP.Where(x => x.FilterID == filter.SP_ID).ToList();
foreach (var filterP in filterPs)
{
var prop = tagProps.FirstOrDefault(x => x.PropertyName == filterP.PropertyName);
if (prop != null)
{
if (prop.PropertyValue.ToUpper() == filterP.Value.ToUpper())
{
if (filterOp.ToUpper() == "OR")
{
//一个满足即可
matched = true;
fileId = filter.LayoutLibFileID;
isNotDefaultSymbol = false;
2025-08-13 11:14:39 +08:00
break;
}
//如果是and继续看下面的属性先给图例如果有一个不满足会break的,主要是避免只有一个条件的时候
fileId = filter.LayoutLibFileID;
matched = true;
isNotDefaultSymbol = false;
2025-08-13 11:14:39 +08:00
}
else
{
if (filterOp.ToUpper() == "AND")
{
matched = false;
isNotDefaultSymbol = true;
2025-08-13 11:14:39 +08:00
//一个不满足都不满足
break;
}
}
}
else
{
//压根没这个属性,认为不符合
if (filterOp.ToUpper() == "AND")
{
matched = false;
isNotDefaultSymbol = true;
2025-08-13 11:14:39 +08:00
break;
}
}
}
}
#endregion
2025-08-29 15:16:09 +08:00
#region tag number
var TagNumber_Upper = ""; var TagNumber_Lower = "";
var lastDashPos = tagInfo.TagNumber.LastIndexOf('-');//最后一个'-'的位置
if (lastDashPos > 0 && lastDashPos < tagInfo.TagNumber.Length - 1)
{
TagNumber_Upper = tagInfo.TagNumber.Substring(lastDashPos + 1);//tag
TagNumber_Lower = tagInfo.TagNumber.Substring(0, lastDashPos);//system
}
2025-08-29 15:16:09 +08:00
else
{
TagNumber_Upper = tagInfo.TagNumber;//tag
TagNumber_Lower = ""; //system
2025-08-29 15:16:09 +08:00
}
#endregion
2025-08-13 11:14:39 +08:00
var layoutTagInfo = new layoutTagInfoBrief()
{
EngineDataID = matchPointTagId,
FileId = fileId, //2个优先级
2025-08-29 15:16:09 +08:00
IsNotDefaultSymbol = isNotDefaultSymbol,
2025-08-13 11:14:39 +08:00
PixelOnDwg = "",
TagNumber = tagInfo.TagNumber,
2025-08-29 15:16:09 +08:00
TagNumber_Upper = TagNumber_Upper,
TagNumber_Lower = TagNumber_Lower,
System = systemProp,
Tag = tagProp,
X = xValue,
2025-08-13 11:14:39 +08:00
XOff = Prop_FrameOff,
YOff = Prop_YOff,
deck = basePoint.deck,
2025-09-01 13:24:47 +08:00
area = basePoint.area,
2025-09-25 16:56:23 +08:00
Scale = basePoint.Scale,
RoomNo = strRoom
2025-08-13 11:14:39 +08:00
};
basePoint.Tags.Add(layoutTagInfo);
foreach (var item in EquipPropAll)
{
if (matchPointTagIdSet.Contains(item.EngineDataID))
item.Marker = true;
}
2025-08-13 11:14:39 +08:00
}
#endregion
}
return Success(res);
}
///// <summary>
///// 拿项目的所属系统。所属系统是一个特定的数据字典。至于哪个作为所属系统则从settingAPI里查询
///// </summary>
///// <param name="ProjectId"></param>
///// <returns>返回TreeModel</returns>
//[HttpGet]
//public IHttpActionResult GetSystemList(string ProjectId)
//{
// var ec_propertyBLL = new ec_propertyBLL();
// var ec_dataitemBLL = new ec_dataitemBLL();
// var settings = new ec_projectSettingsBLL();
// List<TreeModel> treeList = new List<TreeModel>();
// var FrameListFlg = settings.GetEntity("所属系统", ProjectId);//???感觉不需要啊
// if (FrameListFlg != null)
// {
// //从setting找属性
// var property = ec_propertyBLL.GetList("{PropertyName:\"" + FrameListFlg.SettingValue + "\",ProjectId:\"" + ProjectId + "\"}").FirstOrDefault();
// if (property != null)
// {
// //从属性去找数据字典
// var res = ec_dataitemBLL.GetDetailList(property.EnumData, "", ProjectId, false);
// foreach (var item in res)
// {
// TreeModel node = new TreeModel();
// node.id = item.DataItemDetailID;
// node.text = item.DataItemName + "," + item.DataItemCode; //名字 + 编码 20230512;
// node.value = item.DataItemCode;
// node.showcheck = false;
// node.checkstate = 0;
// node.isexpand = true;
// node.parentId = item.UpDataItemDetailID == null ? "0" : item.UpDataItemDetailID;
// treeList.Add(node);
// }
// treeList = treeList.ToTree();
// return Success(treeList);
// }
// else
// {
// return Fail($"属性中property表没有找到【{FrameListFlg.SettingValue}】的属性。");
// }
// }
// else
// {
// return Fail("项目设置中projectSettings表没有找到【所属系统】的设置项。");
// }
//}
/// <summary>
/// 根据选中的所属系统返回位号idfileid和md5
/// </summary>
/// <param name="ProjectId"></param>
/// <param name="DataItemNames">数据字典里的枚举值,以逗号分开,不需要带引号</param>
/// <returns>返回List<treeModel>,id是对象idtext是fileIdvalue是MD5</treeModel></returns>
[HttpGet]
[Obsolete]
public IHttpActionResult GetLibraryFileBySelectedSystem(string ProjectId, string DataItemNames)
{
var res = new ec_library_fileService().GetFileOnSystemDwgByTagId(ProjectId, DataItemNames);
return Success(res);
}
/// <summary>
/// 拿项目的肋位号。肋位号是一个特定的数据字典。至于哪个作为肋位号则从settingAPI里查询
/// </summary>
/// <param name="ProjectId"></param>
/// <returns></returns>
[HttpGet]
public IHttpActionResult GetFrameList(string ProjectId)
{
2025-09-16 09:51:40 +08:00
var bll = new FrameBll();
var res = bll.GetFrameList(ProjectId);
if (res == null)
2025-08-13 11:14:39 +08:00
{
2025-09-16 09:51:40 +08:00
return Fail("项目设置中projectSettings表没有找到【肋位号】的设置项中对应的那个下拉。");// 或者 无法从数据字典中找到对应的那个下拉
2025-08-13 11:14:39 +08:00
}
else
{
2025-09-16 09:51:40 +08:00
return Success(res);
2025-08-13 11:14:39 +08:00
}
}
2025-09-16 09:51:40 +08:00
2025-08-13 11:14:39 +08:00
/// <summary>
/// 根据ObjectTypeID查绘制布置图时的图例
/// </summary>
/// <param name="ProjectId"></param>
/// <param name="objectTypeID"></param>
/// <returns>返回一个LibraryFileID属性的json对象</returns>
[HttpGet]
public IHttpActionResult GetLibraryFileByType(string ProjectId, string objectTypeID)
{
//DefaultLayoutLibFileID
var res = new ec_objecttypeBLL().GetEntity(objectTypeID, ProjectId);
if (res == null)
{
return Fail("无效的ObjectTypeID");
}
if (string.IsNullOrEmpty(res.DefaultLayoutLibFileID))
{
return Success("0");
}
else
{
var fileObj = new ec_library_fileBLL().GetEntity(res.DefaultLayoutLibFileID, ProjectId);
if (fileObj != null)
{
return Success(("{LibraryFileID:\"" + res.DefaultLayoutLibFileID + "\"}").ToJObject());
}
else
{
return Success("0");
}
}
}
/// <summary>
/// 查绘制布置图时的图例。
/// </summary>
/// <param name="ProjectId"></param>
/// <returns>返回所有有DefaultLayoutLibFileID的对象类型集合</returns>
[HttpGet]
public IHttpActionResult GetLibraryFileAll(string ProjectId)
{
//获取当前项目的所有对象类型数据
var allObjectData = new ec_objecttypeBLL().GetList("{ProjectId:\"" + ProjectId + "\"}").ToList();
List<ec_objecttypeEntity> resAll = new List<ec_objecttypeEntity>();
var fileBlll = new ec_library_fileBLL();
foreach (var res in allObjectData)
{
if (string.IsNullOrEmpty(res.DefaultLayoutLibFileID))
{
continue;
}
else
{
var fileObj = fileBlll.GetEntity(res.DefaultLayoutLibFileID, ProjectId);
if (fileObj != null)
{
resAll.Add(res);
}
else
{
continue;
}
}
}
return Success(resAll);
}
}
}