using OfficeOpenXml.VBA; using ProductionLineMonitor.Application.Services.FaultService.Dtos; using ProductionLineMonitor.Application.Services.LineService.Dtos; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; using System.Timers; namespace ProductionLineMonitor.Web.Services.LineService { /// /// 产线详情 /// public class ProductionLineViewModel { public ProductionLineViewModel() { } public ProductionLineViewModel(int floor, int line, string date, string topic, string lineName) { Floor = floor; Line = line; Date = date; LineName = lineName; ProductionPlans = MesApiService.GetProductionPlansV1(Floor, Line, Date); KeyInInfos = MesApiService.GetKeyInInfos(Floor, Line, Date); HourKeyInInfos = GetHourKeyInInfos(KeyInInfos); try { DateTime dateTime = Convert.ToDateTime($"{date} 08:00:00"); DateTime[] m = new DateTime[] { dateTime, dateTime.AddHours(12), dateTime.AddHours(24) }; MorningReplaceConsumables = AccumulativeReplaceConsumableTime(KeyInInfos.Where(x => x.StartTime >= m[0] && x.StartTime < m[1])); NightReplaceConsumables = AccumulativeReplaceConsumableTime(KeyInInfos.Where(x => x.StartTime >= m[1] && x.StartTime < m[2])); } catch (Exception) { return; } MachineViewModel machineViewModel = new MachineViewModel( topic, date, KeyInInfos, ProductionPlans, true); if (machineViewModel.Statistics.Count() == 0) { return; } ModuleType = machineViewModel.Statistics.Last().ModuleType; Capa = machineViewModel.Statistics.Last().Capa; Capacity = machineViewModel.Statistics.Last().Capacity; PlanCapacity = machineViewModel.Statistics.Last().PlanCapacity; OEE = machineViewModel.Statistics.Last().OEE; Statistics = machineViewModel.Statistics; LoadOutPutPerHours = machineViewModel.LoadOutPutPerHours; NewOutPutPerHours = machineViewModel.NewOutPutPerHours; UpdateDown(); } private List AccumulativeReplaceConsumableTime(IEnumerable keyInInfos) { List rev = new List(); foreach (var keyInInfo in keyInInfos) { if (keyInInfo.KeyInType != 8) { continue; } var temp = rev.Find(x => x.Name == keyInInfo.Description); if (temp != null) { temp.Count += 1; temp.AccumulativeTime += keyInInfo.AffectTime; } else { var replaceConsumable = new ReplaceConsumable() { Name = keyInInfo.Description, Count = 1, AccumulativeTime = keyInInfo.AffectTime }; rev.Add(replaceConsumable); } } return rev; } private IEnumerable GetHourKeyInInfos(List keyInInfos) { IList dtos = new List(); foreach (var key in keyInInfos) { if (key.StartTime == null || key.EndTime == null) continue; IList dateTimes = new List { key.StartTime.Value }; DateTime d1 = key.StartTime.Value; int j = 1; while (d1 < key.EndTime.Value) { d1 = key.StartTime.Value.AddHours(j); DateTime d2 = Convert.ToDateTime($"{d1:yyyy-MM-dd HH}:00:00"); j++; if (d2 < key.EndTime.Value) { dateTimes.Add(d2); } } dateTimes.Add(key.EndTime.Value); for (int i = 0; i < dateTimes.Count - 1; i++) { KeyInInfo dto = new KeyInInfo { KeyInType = key.KeyInType, Description = key.Description, Id = key.Id, StartTime = dateTimes[i], EndTime = dateTimes[i + 1] }; dto.AffectTime = (int)(dto.EndTime - dto.StartTime).Value.TotalMinutes; if (dto.AffectTime > 1) { dtos.Add(dto); } } } return dtos; } private void UpdateDown() { if (Statistics != null) { if (Statistics.Count == 1) { Statistics[0].Reload = KeyInInfos.Where(x => x.KeyInType == 8).Sum(x => x.AffectTime); double d = Statistics[0].IdelTime - Statistics[0].Reload; if (d < 0) d = 0; Statistics[0].DownTime += d; } else { foreach (var item in Statistics) { var outs = NewOutPutPerHours.Where(x => x.ModuleType != "" && x.ModuleType[..8] == item.ModuleType).ToList(); if (outs.Count() > 0) { DateTime start = outs[0].DataTime; DateTime end = outs.Last().DataTime.AddHours(1); item.Reload = KeyInInfos.Where( x => x.KeyInType == 8 && x.StartTime >= start && x.StartTime.Value < end).Sum(x => x.AffectTime); double d = item.IdelTime - item.Reload; if (d < 0) d = 0; item.DownTime += d; } } } } } private void CheckFault() { DateTime startTime = Convert.ToDateTime($"{Date} 08:00:00"); DateTime endTime = startTime.AddDays(1); foreach (var item in Machines) { FaultStatistic faultStatistic = new FaultStatistic(); faultStatistic.Name = item.Type; switch (item.Type) { case "AG": faultStatistic.Name = "AG + FPL"; List tempFaults = new List(); tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL", endTime)); tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL01", endTime)); tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL02", endTime)); tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL03", endTime)); tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL04", endTime)); double time1 = tempFaults.Sum(x => x.Duration); double time2 = item.Statistics.Sum(x => x.DownTime); faultStatistic.DownTime = Math.Round(time1 + time2); break; case "FOG": // 在 FOG 前增加COG List tempCogFaults = new List(); tempCogFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "COG", endTime)); FaultStatistic cog = new FaultStatistic { Name = "COG", DownTime = Math.Round(tempCogFaults.Sum(x => x.Duration)) }; FaultStatistics.Add(cog); // FOG 故障时间 faultStatistic.DownTime = Math.Round(item.Statistics.Sum(x => x.DownTime)); break; default: faultStatistic.DownTime = Math.Round(item.Statistics.Sum(x => x.DownTime)); break; } FaultStatistics.Add(faultStatistic); } } private List getKeyInLineDayFaultRecord(int floor, int line, string date, string type, DateTime endTime) { List lineDayFaultRecords = new List(); var fs = MesApiService.GetKeyInFaults(floor, line, date, type); foreach (var f in fs) { LineDayFaultRecord fLineDayFaultRecord = new LineDayFaultRecord { MechineName = type, FaultCode = f.FaultCode, FaultInfo = f.FaultInfo, StartTime = f.StartTime, DataSource = 1 }; if (f.EndTime == null) fLineDayFaultRecord.EndTime = endTime; else fLineDayFaultRecord.EndTime = f.EndTime.Value; fLineDayFaultRecord.Duration = (fLineDayFaultRecord.EndTime.Value - fLineDayFaultRecord.StartTime).TotalMinutes; lineDayFaultRecords.Add(fLineDayFaultRecord); } return lineDayFaultRecords; } private void CheckModuleType() { if (ModuleType != null && ModuleType != "") { if (ProductionPlans .Where(x => x.ModuleType.Length >= 8) .Where(x => x.ModuleType.Substring(0, 8) == ModuleType).Count() == 0) { State = 99; StateMessage = "生产机种与排程不符"; } } } public virtual void CheckState() { DateTime now = DateTime.Now; DateTime time = Convert.ToDateTime($"{Date} {now:HH:mm:ss}"); if (time.Day != now.Day || time.Year != now.Year || time.Month != now.Month) { time = Convert.ToDateTime($"{Date} 07:59:00").AddDays(1); } foreach (var item in KeyInInfos) { if (item.KeyInType == 2 || item.KeyInType == 3 || item.KeyInType == 4 || item.KeyInType == 6 || item.KeyInType == 7 || item.KeyInType == 9) { if (time >= item.StartTime && time <= item.EndTime) { State = item.KeyInType; StateMessage = item.Description; return; } } } if (ProductionPlans.Count == 0) { State = 11; StateMessage = ""; return; } if (ProductionPlans.Count == 1) { if (ProductionPlans[0].ModuleType == "未指定") { State = 11; StateMessage = ""; return; } } State = 99; StateMessage = ""; } public int Floor { get; set; } public int Line { get; set; } public string LineName { get; set; } = string.Empty; public string Date { get; set; } = string.Empty; private int _state = -1; public int State { get { return _state; } set { /// 0:品质异常停线 /// ---------------1:宕机 /// 2:换线 /// 3:实验 /// 4:W/F送样 /// ---------------5:物料缺料或生管调整影响 /// 6:放假 /// 7:停电气等停线 /// ---------------8:换耗材类 /// 9:停机未生产 /// ----------------10:效率爬升 _state = value; switch (_state) { case 0: StateName = "品质异常停线"; break; case 1: break; case 2: StateName = "换线"; break; case 3: StateName = "实验"; break; case 4: StateName = "W/F送样"; break; case 5: break; case 6: StateName = "放假"; break; case 7: StateName = "停电气等停线"; break; case 8: break; case 9: StateName = "停机未生产"; break; case 10: break; case 11: StateName = "未排产"; break; default: StateName = "正常生产"; break; } } } public string StateName { get; set; } = string.Empty; /// /// 状态描述 /// public string StateMessage { get; set; } = string.Empty; /// /// 机种 /// public string ModuleType { get; set; } = string.Empty; /// /// Capa /// public int Capa { get; set; } /// /// 计划产能 /// public int PlanCapacity { get; set; } /// /// 产能 /// public int Capacity { get; set; } /// /// OEE /// public double OEE { get; set; } public double TheoryRefueledTime { get; set; } /// /// 生产计划 /// public List ProductionPlans { get; set; } = new List(); /// /// key in 的异常 /// public List KeyInInfos { get; set; } = new List(); public IEnumerable HourKeyInInfos { get; set; } = new List(); /// /// 小时产能 /// public List LoadOutPutPerHours { get; set; } = new List(); /// /// 清理后小时产能 /// public List NewOutPutPerHours { get; set; } = new List(); /// /// 统计 /// public List Statistics { get; set; } = new List(); /// /// 机台 /// public List Machines { get; set; } = new List(); /// /// key in 故障 /// public List KeyInFaults { get; set; } = new List(); public List FaultStatistics { get; set; } = new List(); public class FaultStatistic { public string Name { get; set; } = string.Empty; public double DownTime { get; set; } } public List ReplaceConsumables { get; set; } = new List(); public List MorningReplaceConsumables { get; set; } = new List(); public List NightReplaceConsumables { get; set; } = new List(); } }