/* ==============================================================================
* 功能描述:上传或下载楼层文件
* 创 建 者:Garrett
* 创建日期:2018/3/30 18:16:55
* ==============================================================================*/
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using SAGA.DotNetUtils;
using SAGA.DotNetUtils.Extend;
using SAGA.DotNetUtils.Logger;
using SAGA.MBI.Calc;
using SAGA.MBI.Common;
using SAGA.MBI.Extend;
using SAGA.MBI.Model;
using SAGA.MBI.RequestData;
using SAGA.MBI.Tools;
using SAGA.MBI.WinView.Upload;
using SAGA.RevitUtils;
using SAGA.RevitUtils.Extends;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using SAGA.MBI.FileStream;
using SAGA.MBI.WinView.TraceView;
using SAGA.RevitUtils.MEP;
namespace SAGA.MBI.DataArrange
{
///
/// DalUploadFloor
///
public class DalUploadFloor
{
///
/// 检测是否需要下载模型,如果需要下载
/// 下载前关闭打开的模型;
/// 开始下载
///
public static void CheckAndBeginDownLoadFile()
{
Log4Net.Debug("开始:检测是否需要下载模型,如果需要下载");
if (!IsAllFloorClosed()) return;
Log4Net.Debug("中间:检测下载模型,如果需要下载");
BeginDownLoadFile();
Log4Net.Debug("结束:检测是否需要下载模型,如果需要下载");
}
///
/// 对比文件,开始下载
///
public static bool BeginDownLoadFile()
{
List> tuples = DalVisionOperate.GetNeedDownLoadFiles();
int i = 0, j = 0;
int count = tuples.Count;
foreach (var tuple in tuples)
{
i++;
if (UpLoadFileRequest.DownLoadFileAsync(tuple, count, i))
{
//下载成功-更新LocalFileVision文件
string floorid = tuple.Item1.GetFileName();
DalVisionOperate.SaveLocalVision(floorid, DalVisionOperate.GetCloudFileVision(floorid));
//下载成功清除本机本层的日志数据,其它用户的日志上传成功的时候才清除日志
ProjectLogManager.ClearFile(tuple.Item1);
//更新拓扑计算结果版本
GplotWatch.RefreshAll(DateTime.Now);
j++;
}
else
{
break;
}
}
if (count >= 1)
//下载完成提示窗体;文件服务器缺少文件,会出现进度条无法关闭的情况;
UpLoadFileRequest.CloseDownloadWin(count == j, hasTip: true);
return i == j;
}
///
/// 重新下载模型文件
///
///
///
public static bool? ReDownLoadFile(MFloor floor, ref string msg)
{
string fullPath = floor.FullPath;
bool? downloadstate;
if (DalVisionOperate.IsFileChanged(fullPath, floor.ToString()))
{
Tuple tuple = new Tuple(fullPath, 2, floor.ToString());
//模型文件有改动,备份并下载
downloadstate = UpLoadFileRequest.DownLoadFileAsync(tuple, 1, 1);
msg = downloadstate == true ? "模型文件更新成功" : "模型文件更新失败";
string floorid = floor.Id;
DalVisionOperate.SaveLocalVision(floorid, DalVisionOperate.GetCloudFileVision(floorid));
//下载成功清除本机本层的日志数据,其它用户的日志上传成功的时候才清除日志
ProjectLogManager.ClearFile(tuple.Item1);
GplotWatch.RefreshAll(DateTime.Now);
}
else
{
//模型文件没有改动
msg = "本地已是最新模型文件,无需更新;";
downloadstate = null;
}
return downloadstate;
}
///
/// 获取有模型文件的楼层
///
///
///
public static ObservableCollection GetHasFileFloors()
{
ObservableCollection ufloors = new ObservableCollection();
List mfloors = DalProjectTree.GetAllFloors();
foreach (var mFloor in mfloors)
{
UploadFloor ufloor = new UploadFloor();
ufloor.BuildingName = mFloor.BuildingId;
ufloor.FloorName = mFloor.ToString();
ufloor.FloorPath = Path.Combine(mFloor.RelativePath, mFloor.RevitName + ".rvt");
if (!mFloor.IsMissFile)
{
ufloor.MFloor = mFloor;
ufloors.Add(ufloor);
}
}
return ufloors;
}
///
/// 检查是否可以上传楼层
/// 上传模型之前需要关闭所有模型文件
///
public static bool IsAllFloorClosed()
{
//打开空文件并激活
var placeholderFile = MBIConst.EmptyFilePath;
var uiApp = ExternalDataWrapper.Current.UiApp;
var docs = uiApp.Application.Documents;
if (docs.IsEmpty) return true;
var allFloors = GetHasFileFloors();
//首先判断ActiveUIDocument是否为当前项目下的楼层
if (uiApp.ActiveUIDocument == null) return true;
Action replaceActiveDoc = () =>
{
string activeName = uiApp.ActiveUIDocument.Document.PathName;
var floor = allFloors.FirstOrDefault(t => t.MFloor.FullPath == activeName);
if (floor == null)
{
//不用打开空模型
}
else
{
//打开空模型
uiApp.OpenAndActivateDocument(placeholderFile);
}
};
List modifyFloors = new List();
List nomodifyFloors = new List();
//获取没有更改的楼层,同时获取更改的楼层
foreach (Document doc in docs)
{
string activeName = doc.PathName;
var floor = allFloors.FirstOrDefault(t => t.MFloor.FullPath == activeName);
if (floor != null)
{
if (doc.IsModified)
modifyFloors.Add(doc);
else
{
nomodifyFloors.Add(doc);
}
}
}
//如果有更改的楼层,弹出确认框,待用户确认后,保存
if (modifyFloors.Count > 0)
{
//弹出保存提示框
WinUploadSaveFileConfirm win = new WinUploadSaveFileConfirm();
if (win.ShowDialog() != true) return false;
replaceActiveDoc();
foreach (Document doc in modifyFloors)
{
doc.Close(true);
}
}
{
replaceActiveDoc();
//关闭没有更改的楼层,
foreach (Document doc in nomodifyFloors)
{
doc.Close(false);
}
}
return true;
}
///
/// 是否需要更新模型文件
///
///
public static bool IsNeedUpdataFile()
{
bool result = true;
var allFloors = GetHasFileFloors();
//获取MD5改变的文件
var modifyFloors = new ObservableCollection(allFloors
.Where(t => DalVisionOperate.IsModifyFileOverdue(t.MFloor.FullPath, t.MFloor.ToString())).ToList());
if (modifyFloors.Count > 0)
{
WinUploadTipFileOverdue win = new WinUploadTipFileOverdue();
win.UploadFloors = modifyFloors;
win.ShowDialog();
}
return modifyFloors.Count > 0;
}
///
/// 准备需要上传的楼层及拓扑关系
///
public static VMUploadModeManage PrepareUploadFloors()
{
Log4Net.Info("PrepareUpload Start");
string currentFloor = string.Empty;
VMUploadModeManage vm = new VMUploadModeManage();
try
{
//获取有模型文件的楼层
var allFloors = GetHasFileFloors();
//获取MD5改变的文件
var modifyFloors = new ObservableCollection(allFloors
.Where(t => DalVisionOperate.IsFileChanged(t.MFloor.FullPath, t.MFloor.ToString())).ToList());
//获取所有的拓扑图类型
var topologyGriphs = GetAllTopologyGriphs();
foreach (UploadFloor uploadFloor in modifyFloors)
{
if (uploadFloor == null) continue;
currentFloor = uploadFloor.MFloor.ToString();
try
{
#region 日志影响拓扑图
foreach (var topologyGriph in topologyGriphs)
{
uploadFloor.ReferGriphs.Add(topologyGriph);
}
#endregion
uploadFloor.IsUpload = true;
}
catch (Exception e)
{
throw;
}
finally
{
}
}
vm.UploadFloors = modifyFloors;
vm.MTopologyGriphs = PrepareMTopologyGriphs(modifyFloors);
}
catch (Exception e)
{
MessageShow.Show(e, strMessage: $"楼层 { currentFloor ?? string.Empty} 打开异常或网络异常,请检查后再进行操作!\r\n");
vm = null;
}
Log4Net.Info("PrepareUpload Start");
return vm;
}
///
/// 对 删除并保留岗位日志 进行的操作
///
///
private static void OperateDelSaveDutyLog(MRevitEquipBase mode)
{
if (mode != null)
{
mode.Operator = DocumentChangedOperator.DeleteSaveDuty;
}
}
///
/// 处理增加日志
///
private static void OperateModifyLog(MRevitEquipBase mode, Element elem, CalcContext context)
{
//如果为空间并且周长为零,删除云平台的空间数据
if (JudgeDeleteOperate(mode, elem)) return;
var revitmode = DalCommon.GetEquipmentBase(elem);
//不知什么原因,日志就显示add,但物理世界存在这条信息
if (mode != null)
{
IsEquipClassCodeChanged(mode, elem, revitmode, context);
}
else
{
if (revitmode.IsNullOrDefaultEquip())
{//不能识别的设备,部件,信标,空间
}
else
{
//请求Duty,Bim数据库中的id
var dutyId = revitmode.GetDutyBIMRelationByBIM()?.DutyId;
if (dutyId.IsNullOrEmpty())
{//本地数据库不存在此岗位
revitmode.Operator = DocumentChangedOperator.Add;
context.Add(revitmode);
}
else
{
var cloudmode = CommonConvert.QueryObjectById(dutyId);
if (cloudmode == null)
{
revitmode.Operator = DocumentChangedOperator.Add;
context.Add(revitmode);
}
else
{
//待建模型清单新建的设备
cloudmode.BimID = revitmode.BimID;
IsEquipClassCodeChanged(cloudmode, elem, revitmode, context);
context.Add(cloudmode);
}
}
}
}
}
///
/// 判断设备类编码是否更改
/// 如果发生更改,把之前的删除。
/// 重建岗位。
///
///
///
///
///
private static bool IsEquipClassCodeChanged(MRevitEquipBase mode, Element elem, MRevitEquipBase tempmode, CalcContext context)
{
bool result = false;
if (tempmode.IsNullOrDefaultEquip())
{
//本地编码不可识别,删除服务器数据
//xls 新编码和旧编码一致,则不处理数据
if (EquipmentCodeMap.GetOriginCode(mode.EquipClassCode) == EquipmentCodeMap.GetOriginCode(tempmode.EquipClassCode))
{
mode.Operator = DocumentChangedOperator.Modified;
mode.ReadRevitParamter(elem);
}
else
{
mode.Operator = DocumentChangedOperator.Delete;
}
}
else
{
//如果设备族四位或六位改了,需要将岗位删除,重建岗位
//string code1 = EquipmentCodeMap.GetOriginCode(mode.EquipClassCode);
//(tempmode.EquipClassCode 这个的取法上上一个不一样
// string code2 = EquipmentCodeMap.GetOriginCode(tempmode.EquipClassCode);
if (EquipmentCodeMap.GetOriginCode(mode.EquipClassCode) != EquipmentCodeMap.GetOriginCode(tempmode.EquipClassCode))
{
SetSavePropertyValue(tempmode, mode);
mode.Operator = DocumentChangedOperator.Delete;
tempmode.Operator = DocumentChangedOperator.Add;
context.Add(tempmode);
result = true;
}
else
{
mode.Operator = DocumentChangedOperator.Modified;
mode.ReadRevitParamter(elem);
}
}
return result;
}
///
/// 编码更改时保留的信息点
///
///
///
public static void SetSavePropertyValue(MRevitEquipBase mode, MRevitEquipBase oldmode)
{
string[] saveProperties = new[] { "LocalId", "LocalName" };
var oldProperties = oldmode.GetType().GetProperties();
foreach (PropertyInfo property in oldProperties)
{
string name = property.Name;
if (saveProperties.Contains(name))
{
object value = property.GetValue(oldmode);
if (value != null)
{
property.SetValue(mode, value);
}
}
}
}
///
/// 1,处理是无用的空间,周长为零
/// 2,对象被删除
///
///
///
private static bool JudgeDeleteOperate(MRevitEquipBase mode, Element elem)
{
bool result = false;
if (mode != null)
{
if (elem == null)
{
mode.Operator = DocumentChangedOperator.Delete;
result = true;
}
else if (elem is Space space)
{
if (space.IsDeleteSpace())
{
//如果是无用空间,直接删除云平台对应数据
mode.Operator = DocumentChangedOperator.Delete;
result = true;
}
}
}
return result;
}
///
/// 准备需要显示的拓扑图(全集)
///
///
///
public static ObservableCollection PrepareMTopologyGriphs(ObservableCollection uploadFloors)
{
ObservableCollection list = new ObservableCollection();
foreach (var uploadFloor in uploadFloors)
{
foreach (MTopologyGriph griph in uploadFloor.ReferGriphs)
{
var tempgriph = list.FirstOrDefault(t => t.Name == griph.Name);
if (tempgriph == null)
list.Add(griph);
}
}
return list;
}
///
/// 获取所有的拓扑图类型
///
///
public static List GetAllTopologyGriphs()
{
List list = new List();
list.Add(new MTopologyGriph() { Name = "空调冷冻水环路" });
list.Add(new MTopologyGriph() { Name = "空调冷却水环路" });
list.Add(new MTopologyGriph() { Name = "新风管网" });
list.Add(new MTopologyGriph() { Name = "空调风管网" });
list.Add(new MTopologyGriph() { Name = "光照辐射关系" });
list.Add(new MTopologyGriph() { Name = "空间邻接关系" });
list.Add(new MTopologyGriph() { Name = "建筑交通关系" });
list.Add(new MTopologyGriph() { Name = "空间流通网络" });
return list;
}
///
/// 判断物理世界岗位与本地岗位是否一致
/// 依据1:BimID
/// --暂时不使用,依据2:CADID
///
///
///
///
public static bool IsEqualCloudDuty2LocalDuty(MRevitEquipBase cduty,MRevitEquipBase lduty)
{
string lbimId = lduty.BimID;
string cbimId = cduty.BimID;
bool result = false;
do
{
result = lbimId == cbimId;
result = !cbimId.IsOnlyDutyNoModelBIMID() && result;
break;
//本地的bimid一定是完整的。
//有对应的bimId,或者bimId的格式正确。
if (result||!cbimId.IsOnlyDutyNoModelBIMID())
{
break;
}
string lcadId, ccadId;
//bimId格式不正确,判断CADID
//设备
if (lduty is MEquipment lequip && cduty is MEquipment cequip)
{
lcadId = lequip.CADID;
ccadId = cequip.CADID;
result = lcadId.IsNotNullEmpty() && lcadId == ccadId;
break;
}
//部件
if (lduty is MEquipmentPart lpart && cduty is MEquipmentPart cpart)
{
lcadId = lpart.CADID;
ccadId = cpart.CADID;
result = lcadId.IsNotNullEmpty() && lcadId == ccadId;
break;
}
} while (false);
return result;
}
///
/// 判断物理世界岗位与本地岗位是否一致
/// 依据1:BimID
/// 依据2:CADID
///
///
///
///
public static bool IsEqualDutyByCADID(MRevitEquipBase cduty, MRevitEquipBase lduty)
{
bool result = false;
do
{
if (!cduty.BimID.IsOnlyDutyNoModelBIMID())
{
result = false;
break;
}
string lcadId, ccadId;
//bimId格式不正确,判断CADID
//设备
if (lduty is MEquipment lequip && cduty is MEquipment cequip)
{
lcadId = lequip.CADID;
ccadId = cequip.CADID;
result = lcadId.IsNotNullEmpty() && lcadId == ccadId;
break;
}
//部件
if (lduty is MEquipmentPart lpart && cduty is MEquipmentPart cpart)
{
lcadId = lpart.CADID;
ccadId = cpart.CADID;
result = lcadId.IsNotNullEmpty() && lcadId == ccadId;
break;
}
} while (false);
return result;
}
///
/// 新旧文件对比过后,需要添加的数据
///
public static void WrapperContext(CalcContext cloudContext, CalcContext localContext)
{
var cloudDutys = cloudContext.GetAllDutys();
var localDutys = localContext.GetAllDutys();
//设置初始状态
cloudContext.SetState(DocumentChangedOperator.None);
localContext.SetState(DocumentChangedOperator.None);
#region Modify Add
foreach (var lduty in localDutys)
{
var cdutys = cloudDutys.Where(t=> IsEqualCloudDuty2LocalDuty(t,lduty)).ToList();
var cdutysByCADID= cloudDutys.Where(t => IsEqualDutyByCADID(t, lduty)).ToList();
MRevitEquipBase cduty = null;
//如果对应多个岗位,仅保留信息点多的岗位,删除其它岗位
if (cdutys.Any()||cdutysByCADID.Count==1)
{
//如果通过CADID只找到一个,当做对应岗位处理。
cdutys.AddRange(cdutysByCADID);
if (cdutys.Count() > 1)
{//信息点的个数从大到小排序
cdutys.Sort((x, y) => { return -x.CloundJObject.Count.CompareTo(y.CloundJObject.Count); });
//删除多余的岗位
for (int i = 1; i < cdutys.Count; i++)
{
cdutys[i].Operator = DocumentChangedOperator.Delete;
}
}
}
else
{
//通过CADID找到多个,也当做新增处理 190823 tjc
//请求Duty,Bim数据库中的id,待建模型清单产生的
var dutyId = lduty.GetDutyBIMRelationByBIM()?.DutyId;
if (dutyId.IsNotNullEmpty())
{
cdutys = cloudDutys.Where(t => t.Id == dutyId).ToList();
if (!cdutys.Any())
{
//去跟据id物理世界查找
var tempcduty = DalCommon.QueryObjectById(dutyId);
if (tempcduty != null)
{
cdutys.Add(tempcduty);
//添加设备所在楼层
localContext.UnGroupDatas.Add(new RltEquipinFloor(dutyId,cloudContext.FloorId){Operator = DocumentChangedOperator.Add});
}
}
}
else
{
lduty.Id = dutyId;
}
}
cduty = cdutys.FirstOrDefault();
if (cduty == null)
{
//找不到物理世界对应的岗位,即为添加
lduty.Operator = DocumentChangedOperator.Add;
}
else
{
//判断族编码是否更改
if (EquipmentCodeMap.GetOriginCode(lduty.EquipClassCode) !=
EquipmentCodeMap.GetOriginCode(cduty.EquipClassCode))
{
//族编码更改。删除旧岗位,创建新岗位
cduty.Operator = DocumentChangedOperator.Delete;
lduty.Operator = DocumentChangedOperator.Add;
}
else
{
lduty.Id = cduty.Id;
lduty.Operator = DocumentChangedOperator.Modified;
//后续物理世界Modified转化为None
cduty.Operator = DocumentChangedOperator.Modified;
}
}
//处理设备所在空间的关系
OperateBaseRelation(localContext, lduty);
}
#endregion
#region Delete
//CloudDuty,有两种操作,更新和删除。更新等价于None
foreach (var duty in cloudDutys)
{
//物理世界修改,不做处理或台账转过来的岗位
if (duty.BimID.IsOnlyDutyNoModelBIMID() || duty.Operator == DocumentChangedOperator.Modified)
{
duty.Operator = DocumentChangedOperator.None;
continue;
}
duty.Operator = DocumentChangedOperator.Delete;
DelServiceRelation(cloudContext, duty);
//删除时,会删除所在空间和所在楼层的关系
}
#endregion
}
///
/// 删除服务器基本关系
///
private static void DelServiceRelation(CalcContext localContext, MRevitEquipBase mode)
{
if (mode.Operator != DocumentChangedOperator.Delete) return;
#region EquipInSpace,Beacon
var equiprelations = localContext.RltEquipInSpaces;
var beaconrelations = localContext.RltBeaconinElementSps;
if (mode is MBSpace)
{
var equipRelation = new RltEquipInSpace(null, mode.Id) { Operator = DocumentChangedOperator.Delete };
equiprelations.Add(equipRelation);
var beaconRelation = new RltBeaconinElementSp(null, mode.Id) { Operator = DocumentChangedOperator.Delete };
beaconrelations.Add(beaconRelation);
}
else if (mode is MBeacon)
{
var beaconRelation = new RltBeaconinElementSp(mode.Id, null) { Operator = DocumentChangedOperator.Delete };
beaconrelations.Add(beaconRelation);
}
else
{
var equipRelation = new RltEquipInSpace(mode.Id, null) { Operator = DocumentChangedOperator.Delete };
equiprelations.Add(equipRelation);
}
#endregion
}
///
/// 处理基本关系
///
private static void OperateBaseRelation(CalcContext localContext, MRevitEquipBase mode)
{
string bimid = mode.BimID;
#region EquipInSpace,Beacon
var equiprelations = localContext.RltEquipInSpaces;
var beaconrelations = localContext.RltBeaconinElementSps;
List tempEquipRelations = new List();
List tempBeaconRelations = new List();
if (mode is MBSpace)
{
tempEquipRelations = equiprelations.Where(t => t.MSpace.BimID == bimid).ToList();
tempBeaconRelations = beaconrelations.Where(t => t.MSpace.BimID == bimid).ToList();
}
else if (mode is MBeacon)
{
tempBeaconRelations = beaconrelations.Where(t => t.MBeacon.BimID == bimid).ToList();
}
else
{
tempEquipRelations = equiprelations.Where(t => t.MEquipment.BimID == bimid).ToList();
}
switch (mode.Operator)
{
case DocumentChangedOperator.Add:
tempEquipRelations.ForEach(t => t.Operator = DocumentChangedOperator.Add);
tempBeaconRelations.ForEach(t => t.Operator = DocumentChangedOperator.Add);
break;
case DocumentChangedOperator.Delete:
tempEquipRelations.ForEach(t => t.Operator = DocumentChangedOperator.Delete);
tempBeaconRelations.ForEach(t => t.Operator = DocumentChangedOperator.Delete);
break;
case DocumentChangedOperator.Modified:
tempEquipRelations.ForEach(t => t.Operator = DocumentChangedOperator.Delete);
tempEquipRelations.ForEach(t => equiprelations.Add(new RltEquipInSpace(t.MSpace, t.MEquipment) { Operator = DocumentChangedOperator.Add }));
tempBeaconRelations.ForEach(t => t.Operator = DocumentChangedOperator.Delete);
tempBeaconRelations.ForEach(t => beaconrelations.Add(new RltBeaconinElementSp(t.MSpace, t.MBeacon) { Operator = DocumentChangedOperator.Add }));
break;
default:
break;
}
#endregion
}
///
/// 上传岗位和基本关系数据操作
///
///
public static void UploadDataOperate(MFloor floor)
{
LoadingOperation.Update();
CalcContext serviceContext = DalCommon.DownLoadFloorDataByBIMFloorInfo(floor);
LoadingOperation.Update();
CalcContext localContext = ObjectCalc.Calc(floor);
LoadingOperation.Update();
WrapperContext(serviceContext, localContext);
LoadingOperation.Update();
serviceContext.Upload();
UploadReportUtil.SendReport(serviceContext,localContext);
LoadingOperation.Update();
localContext.Upload();
}
///
/// 上传或下载完成之后的操作
///
public static void AfterUploadOperate(MFloor floor, bool isunlock = true)
{
//请除Duty和BIMID的关系
MBIAssistHelper.DeleteFloorRelation(floor.Id);
if (isunlock)
//解锁
DalLock.UnLockFloor(floor.Id, false);
//上传成功后清除日志数据
ProjectLogManager.ClearFiles(floor.Id);
//删除备份文件
FloorFileOperate.Del000BakFile(floor.FullPath);
}
}
}