ProductionLineViewModel.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. using OfficeOpenXml.VBA;
  2. using ProductionLineMonitor.Application.Services.FaultService.Dtos;
  3. using ProductionLineMonitor.Application.Services.LineService.Dtos;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Collections.ObjectModel;
  7. using System.Linq;
  8. using System.Threading;
  9. using System.Timers;
  10. namespace ProductionLineMonitor.Web.Services.LineService
  11. {
  12. /// <summary>
  13. /// 产线详情
  14. /// </summary>
  15. public class ProductionLineViewModel
  16. {
  17. public ProductionLineViewModel() { }
  18. public ProductionLineViewModel(int floor, int line, string date, string topic, string lineName)
  19. {
  20. Floor = floor;
  21. Line = line;
  22. Date = date;
  23. LineName = lineName;
  24. ProductionPlans = MesApiService.GetProductionPlansV1(Floor, Line, Date);
  25. KeyInInfos = MesApiService.GetKeyInInfos(Floor, Line, Date);
  26. HourKeyInInfos = GetHourKeyInInfos(KeyInInfos);
  27. try
  28. {
  29. DateTime dateTime = Convert.ToDateTime($"{date} 08:00:00");
  30. DateTime[] m = new DateTime[] { dateTime, dateTime.AddHours(12), dateTime.AddHours(24) };
  31. MorningReplaceConsumables = AccumulativeReplaceConsumableTime(KeyInInfos.Where(x => x.StartTime >= m[0] && x.StartTime < m[1]));
  32. NightReplaceConsumables = AccumulativeReplaceConsumableTime(KeyInInfos.Where(x => x.StartTime >= m[1] && x.StartTime < m[2]));
  33. }
  34. catch (Exception)
  35. {
  36. return;
  37. }
  38. MachineViewModel machineViewModel = new MachineViewModel(
  39. topic, date,
  40. KeyInInfos,
  41. ProductionPlans, true);
  42. if (machineViewModel.Statistics.Count() == 0)
  43. {
  44. return;
  45. }
  46. ModuleType = machineViewModel.Statistics.Last().ModuleType;
  47. Capa = machineViewModel.Statistics.Last().Capa;
  48. Capacity = machineViewModel.Statistics.Last().Capacity;
  49. PlanCapacity = machineViewModel.Statistics.Last().PlanCapacity;
  50. OEE = machineViewModel.Statistics.Last().OEE;
  51. Statistics = machineViewModel.Statistics;
  52. LoadOutPutPerHours = machineViewModel.LoadOutPutPerHours;
  53. NewOutPutPerHours = machineViewModel.NewOutPutPerHours;
  54. UpdateDown();
  55. }
  56. private List<ReplaceConsumable> AccumulativeReplaceConsumableTime(IEnumerable<KeyInInfo> keyInInfos)
  57. {
  58. List<ReplaceConsumable> rev = new List<ReplaceConsumable>();
  59. foreach (var keyInInfo in keyInInfos)
  60. {
  61. if (keyInInfo.KeyInType != 8)
  62. {
  63. continue;
  64. }
  65. var temp = rev.Find(x => x.Name == keyInInfo.Description);
  66. if (temp != null)
  67. {
  68. temp.Count += 1;
  69. temp.AccumulativeTime += keyInInfo.AffectTime;
  70. }
  71. else
  72. {
  73. var replaceConsumable = new ReplaceConsumable()
  74. {
  75. Name = keyInInfo.Description,
  76. Count = 1,
  77. AccumulativeTime = keyInInfo.AffectTime
  78. };
  79. rev.Add(replaceConsumable);
  80. }
  81. }
  82. return rev;
  83. }
  84. private IEnumerable<KeyInInfo> GetHourKeyInInfos(List<KeyInInfo> keyInInfos)
  85. {
  86. IList<KeyInInfo> dtos = new List<KeyInInfo>();
  87. foreach (var key in keyInInfos)
  88. {
  89. if (key.StartTime == null || key.EndTime == null)
  90. continue;
  91. IList<DateTime> dateTimes = new List<DateTime>
  92. {
  93. key.StartTime.Value
  94. };
  95. DateTime d1 = key.StartTime.Value;
  96. int j = 1;
  97. while (d1 < key.EndTime.Value)
  98. {
  99. d1 = key.StartTime.Value.AddHours(j);
  100. DateTime d2 = Convert.ToDateTime($"{d1:yyyy-MM-dd HH}:00:00");
  101. j++;
  102. if (d2 < key.EndTime.Value)
  103. {
  104. dateTimes.Add(d2);
  105. }
  106. }
  107. dateTimes.Add(key.EndTime.Value);
  108. for (int i = 0; i < dateTimes.Count - 1; i++)
  109. {
  110. KeyInInfo dto = new KeyInInfo
  111. {
  112. KeyInType = key.KeyInType,
  113. Description = key.Description,
  114. Id = key.Id,
  115. StartTime = dateTimes[i],
  116. EndTime = dateTimes[i + 1]
  117. };
  118. dto.AffectTime = (int)(dto.EndTime - dto.StartTime).Value.TotalMinutes;
  119. if (dto.AffectTime > 1)
  120. {
  121. dtos.Add(dto);
  122. }
  123. }
  124. }
  125. return dtos;
  126. }
  127. private void UpdateDown()
  128. {
  129. if (Statistics != null)
  130. {
  131. if (Statistics.Count == 1)
  132. {
  133. Statistics[0].Reload = KeyInInfos.Where(x => x.KeyInType == 8).Sum(x => x.AffectTime);
  134. double d = Statistics[0].IdelTime - Statistics[0].Reload;
  135. if (d < 0)
  136. d = 0;
  137. Statistics[0].DownTime += d;
  138. }
  139. else
  140. {
  141. foreach (var item in Statistics)
  142. {
  143. var outs = NewOutPutPerHours.Where(x => x.ModuleType != "" && x.ModuleType[..8] == item.ModuleType).ToList();
  144. if (outs.Count() > 0)
  145. {
  146. DateTime start = outs[0].DataTime;
  147. DateTime end = outs.Last().DataTime.AddHours(1);
  148. item.Reload = KeyInInfos.Where(
  149. x => x.KeyInType == 8 && x.StartTime >= start && x.StartTime.Value < end).Sum(x => x.AffectTime);
  150. double d = item.IdelTime - item.Reload;
  151. if (d < 0)
  152. d = 0;
  153. item.DownTime += d;
  154. }
  155. }
  156. }
  157. }
  158. }
  159. private void CheckFault()
  160. {
  161. DateTime startTime = Convert.ToDateTime($"{Date} 08:00:00");
  162. DateTime endTime = startTime.AddDays(1);
  163. foreach (var item in Machines)
  164. {
  165. FaultStatistic faultStatistic = new FaultStatistic();
  166. faultStatistic.Name = item.Type;
  167. switch (item.Type)
  168. {
  169. case "AG":
  170. faultStatistic.Name = "AG + FPL";
  171. List<LineDayFaultRecord> tempFaults = new List<LineDayFaultRecord>();
  172. tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL", endTime));
  173. tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL01", endTime));
  174. tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL02", endTime));
  175. tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL03", endTime));
  176. tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL04", endTime));
  177. double time1 = tempFaults.Sum(x => x.Duration);
  178. double time2 = item.Statistics.Sum(x => x.DownTime);
  179. faultStatistic.DownTime = Math.Round(time1 + time2);
  180. break;
  181. case "FOG":
  182. // 在 FOG 前增加COG
  183. List<LineDayFaultRecord> tempCogFaults = new List<LineDayFaultRecord>();
  184. tempCogFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "COG", endTime));
  185. FaultStatistic cog = new FaultStatistic
  186. {
  187. Name = "COG",
  188. DownTime = Math.Round(tempCogFaults.Sum(x => x.Duration))
  189. };
  190. FaultStatistics.Add(cog);
  191. // FOG 故障时间
  192. faultStatistic.DownTime = Math.Round(item.Statistics.Sum(x => x.DownTime));
  193. break;
  194. default:
  195. faultStatistic.DownTime = Math.Round(item.Statistics.Sum(x => x.DownTime));
  196. break;
  197. }
  198. FaultStatistics.Add(faultStatistic);
  199. }
  200. }
  201. private List<LineDayFaultRecord> getKeyInLineDayFaultRecord(int floor, int line, string date, string type, DateTime endTime)
  202. {
  203. List<LineDayFaultRecord> lineDayFaultRecords = new List<LineDayFaultRecord>();
  204. var fs = MesApiService.GetKeyInFaults(floor, line, date, type);
  205. foreach (var f in fs)
  206. {
  207. LineDayFaultRecord fLineDayFaultRecord = new LineDayFaultRecord
  208. {
  209. MechineName = type,
  210. FaultCode = f.FaultCode,
  211. FaultInfo = f.FaultInfo,
  212. StartTime = f.StartTime,
  213. DataSource = 1
  214. };
  215. if (f.EndTime == null)
  216. fLineDayFaultRecord.EndTime = endTime;
  217. else
  218. fLineDayFaultRecord.EndTime = f.EndTime.Value;
  219. fLineDayFaultRecord.Duration = (fLineDayFaultRecord.EndTime.Value - fLineDayFaultRecord.StartTime).TotalMinutes;
  220. lineDayFaultRecords.Add(fLineDayFaultRecord);
  221. }
  222. return lineDayFaultRecords;
  223. }
  224. private void CheckModuleType()
  225. {
  226. if (ModuleType != null && ModuleType != "")
  227. {
  228. if (ProductionPlans
  229. .Where(x => x.ModuleType.Length >= 8)
  230. .Where(x => x.ModuleType.Substring(0, 8) == ModuleType).Count() == 0)
  231. {
  232. State = 99;
  233. StateMessage = "生产机种与排程不符";
  234. }
  235. }
  236. }
  237. public virtual void CheckState()
  238. {
  239. DateTime now = DateTime.Now;
  240. DateTime time = Convert.ToDateTime($"{Date} {now:HH:mm:ss}");
  241. if (time.Day != now.Day || time.Year != now.Year || time.Month != now.Month)
  242. {
  243. time = Convert.ToDateTime($"{Date} 07:59:00").AddDays(1);
  244. }
  245. foreach (var item in KeyInInfos)
  246. {
  247. if (item.KeyInType == 2 || item.KeyInType == 3 || item.KeyInType == 4 ||
  248. item.KeyInType == 6 || item.KeyInType == 7 || item.KeyInType == 9)
  249. {
  250. if (time >= item.StartTime && time <= item.EndTime)
  251. {
  252. State = item.KeyInType;
  253. StateMessage = item.Description;
  254. return;
  255. }
  256. }
  257. }
  258. if (ProductionPlans.Count == 0)
  259. {
  260. State = 11;
  261. StateMessage = "";
  262. return;
  263. }
  264. if (ProductionPlans.Count == 1)
  265. {
  266. if (ProductionPlans[0].ModuleType == "未指定")
  267. {
  268. State = 11;
  269. StateMessage = "";
  270. return;
  271. }
  272. }
  273. State = 99;
  274. StateMessage = "";
  275. }
  276. public int Floor { get; set; }
  277. public int Line { get; set; }
  278. public string LineName { get; set; } = string.Empty;
  279. public string Date { get; set; } = string.Empty;
  280. private int _state = -1;
  281. public int State
  282. {
  283. get { return _state; }
  284. set
  285. {
  286. /// 0:品质异常停线
  287. /// ---------------1:宕机
  288. /// 2:换线
  289. /// 3:实验
  290. /// 4:W/F送样
  291. /// ---------------5:物料缺料或生管调整影响
  292. /// 6:放假
  293. /// 7:停电气等停线
  294. /// ---------------8:换耗材类
  295. /// 9:停机未生产
  296. /// ----------------10:效率爬升
  297. _state = value;
  298. switch (_state)
  299. {
  300. case 0: StateName = "品质异常停线"; break;
  301. case 1: break;
  302. case 2: StateName = "换线"; break;
  303. case 3: StateName = "实验"; break;
  304. case 4: StateName = "W/F送样"; break;
  305. case 5: break;
  306. case 6: StateName = "放假"; break;
  307. case 7: StateName = "停电气等停线"; break;
  308. case 8: break;
  309. case 9: StateName = "停机未生产"; break;
  310. case 10: break;
  311. case 11: StateName = "未排产"; break;
  312. default: StateName = "正常生产"; break;
  313. }
  314. }
  315. }
  316. public string StateName { get; set; } = string.Empty;
  317. /// <summary>
  318. /// 状态描述
  319. /// </summary>
  320. public string StateMessage { get; set; } = string.Empty;
  321. /// <summary>
  322. /// 机种
  323. /// </summary>
  324. public string ModuleType { get; set; } = string.Empty;
  325. /// <summary>
  326. /// Capa
  327. /// </summary>
  328. public int Capa { get; set; }
  329. /// <summary>
  330. /// 计划产能
  331. /// </summary>
  332. public int PlanCapacity { get; set; }
  333. /// <summary>
  334. /// 产能
  335. /// </summary>
  336. public int Capacity { get; set; }
  337. /// <summary>
  338. /// OEE
  339. /// </summary>
  340. public double OEE { get; set; }
  341. public double TheoryRefueledTime { get; set; }
  342. /// <summary>
  343. /// 生产计划
  344. /// </summary>
  345. public List<ProductionPlanDtoV1> ProductionPlans { get; set; }
  346. = new List<ProductionPlanDtoV1>();
  347. /// <summary>
  348. /// key in 的异常
  349. /// </summary>
  350. public List<KeyInInfo> KeyInInfos { get; set; }
  351. = new List<KeyInInfo>();
  352. public IEnumerable<KeyInInfo> HourKeyInInfos { get; set; }
  353. = new List<KeyInInfo>();
  354. /// <summary>
  355. /// 小时产能
  356. /// </summary>
  357. public List<MachineDayOutPutPerHour> LoadOutPutPerHours { get; set; }
  358. = new List<MachineDayOutPutPerHour>();
  359. /// <summary>
  360. /// 清理后小时产能
  361. /// </summary>
  362. public List<NewMachineDayOutPutPerHour> NewOutPutPerHours { get; set; }
  363. = new List<NewMachineDayOutPutPerHour>();
  364. /// <summary>
  365. /// 统计
  366. /// </summary>
  367. public List<Statistic> Statistics { get; set; }
  368. = new List<Statistic>();
  369. /// <summary>
  370. /// 机台
  371. /// </summary>
  372. public List<MachineViewModel> Machines { get; set; }
  373. = new List<MachineViewModel>();
  374. /// <summary>
  375. /// key in 故障
  376. /// </summary>
  377. public List<LineDayFaultRecord> KeyInFaults { get; set; }
  378. = new List<LineDayFaultRecord>();
  379. public List<FaultStatistic> FaultStatistics { get; set; }
  380. = new List<FaultStatistic>();
  381. public class FaultStatistic
  382. {
  383. public string Name { get; set; } = string.Empty;
  384. public double DownTime { get; set; }
  385. }
  386. public List<ReplaceConsumable> ReplaceConsumables { get; set; }
  387. = new List<ReplaceConsumable>();
  388. public List<ReplaceConsumable> MorningReplaceConsumables { get; set; }
  389. = new List<ReplaceConsumable>();
  390. public List<ReplaceConsumable> NightReplaceConsumables { get; set; }
  391. = new List<ReplaceConsumable>();
  392. }
  393. }