using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using DOAN.Model.MES.dev; using DOAN.Model.MES.dev.Dto; using DOAN.Model.System; using DOAN.Service.MES.dev.IService; using Infrastructure.Attribute; using Infrastructure.Extensions; using Microsoft.AspNetCore.Components.Forms; namespace DOAN.Service.MES.dev { /// /// 设备数据分析 /// [AppService( ServiceType = typeof(IDeviceDataAnalysisServcie), ServiceLifetime = LifeTime.Transient )] public class DeviceDataAnalysisService : BaseService, IDeviceDataAnalysisServcie { public static List FindAllLeafNodes(List nodeList, int targetId) { List childIds = new List { targetId }; List result = new List(); while (childIds.Any()) { int parentId = childIds.First(); childIds.RemoveAt(0); List children = nodeList .Where(n => n.ParentId == parentId) .Select(n => n.Id) .ToList(); if (children.Any()) { childIds.AddRange(children); } else { result.Add(nodeList.First(n => n.Id == parentId)); } } return result; } /// /// 故障类型 pie /// /// /// public List DefaultTypePie(DeviceDefaultDto devicedefault) { List resultList = new List(); int[] all_device_type_array = null; if (devicedefault.DevicetTypeId > 0) { List all_device_type_list = FindAllLeafNodes( Context.Queryable().ToList(), devicedefault.DevicetTypeId ?? 0 ); all_device_type_array = all_device_type_list.Select(it => it.Id).ToArray(); } var predicate = Expressionable .Create() .AndIF( all_device_type_array != null && all_device_type_array.Length > 0, (r, a, d) => all_device_type_array.Contains(a.FkDeviceType) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceName), (r, a, d) => a.DeviceName.Contains(devicedefault.DeviceName) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceCode), (r, a, d) => a.DeviceCode.Contains(devicedefault.DeviceCode) ) .AndIF( devicedefault.searchTime[0] > new DateTime(1991, 1, 1), (r, a, d) => r.CreatedTime >= devicedefault.searchTime[0] ) .AndIF( devicedefault.searchTime[1] > new DateTime(1991, 1, 1), (r, a, d) => r.CreatedTime <= devicedefault.searchTime[1] ) .And((r, a, d) => d.DictType == "mes_device_fault_type"); List deviceRepair_list = Context .Queryable() .LeftJoin((r, a) => r.FkDeviceId == a.Id) .LeftJoin((r, a, d) => r.Type == d.DictValue) .Where(predicate.ToExpression()) .Select( (r, a, d) => new DeviceRepair_chart { Type = r.Type, TypeName = d.DictLabel, } ) .ToList(); if (deviceRepair_list.Count > 0) { var TypeGroups = deviceRepair_list.GroupBy(it => it.TypeName); foreach (var group in TypeGroups) { DeviceStatusAnalysisResultDto result = new DeviceStatusAnalysisResultDto(); result.name = group.Key; result.value = group.Count(); resultList.Add(result); } } return resultList; } /// /// 每日故障数量统计 /// /// /// public DeviceFaultBarResultDto FaultTypeBar(DeviceDefaultDto devicedefault) { DeviceFaultBarResultDto result = new DeviceFaultBarResultDto(); int[] all_device_type_array = null; if (devicedefault.DevicetTypeId > 0) { List all_device_type_list = FindAllLeafNodes( Context.Queryable().ToList(), devicedefault.DevicetTypeId ?? 0 ); all_device_type_array = all_device_type_list.Select(it => it.Id).ToArray(); } var predicate = Expressionable .Create() .AndIF( all_device_type_array != null && all_device_type_array.Length > 0, (r, a, d) => all_device_type_array.Contains(a.FkDeviceType) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceName), (r, a, d) => a.DeviceName.Contains(devicedefault.DeviceName) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceCode), (r, a, d) => a.DeviceCode.Contains(devicedefault.DeviceCode) ) .AndIF( devicedefault.searchTime[0] > new DateTime(1991, 1, 1), (r, a, d) => r.CreatedTime >= devicedefault.searchTime[0] ) .AndIF( devicedefault.searchTime[1] > new DateTime(1991, 1, 1), (r, a, d) => r.CreatedTime <= devicedefault.searchTime[1] ) .And((r, a, d) => d.DictType == "mes_device_fault_type"); List deviceRepair_list = Context .Queryable() .LeftJoin((r, a) => r.FkDeviceId == a.Id) .LeftJoin((r, a, d) => r.Type == d.DictValue) .Where(predicate.ToExpression()) .Select( (r, a, d) => new DeviceRepair_chart { Type = r.Type, TypeName = d.DictLabel, CreatedTime = (DateTime)r.CreatedTime } ) .ToList(); //获取所有故障类型 List all_fault_type = Context .Queryable() .Where(it => it.DictType == "mes_device_fault_type") .ToList(); // 先按照天进行上卷聚合,然后按照故障种类进行上卷聚合 var first_groups = deviceRepair_list.GroupBy(it => it.CreatedTime.Date); string[] Xdata = new string[first_groups.Count()]; int index = 0; foreach (var group in first_groups) { Xdata[index] = group.Key.ToString("yyyy-MM-dd"); index++; } List SeriesData = new List(); foreach (SysDictData dict in all_fault_type) { SeriesData_Item seriesData_Item = new SeriesData_Item(); seriesData_Item.Name = dict.DictLabel; //这种故障在每天的值 int[] values = new int[first_groups.Count()]; int index2 = 0; foreach (var group in first_groups) { //凌晨 DateTime startOfDay = group.Key; //午夜(23:59:59) DateTime endOfDay = group.Key.AddDays(1).AddSeconds(-1); values[index2] = deviceRepair_list .Where(it => it.CreatedTime >= startOfDay && it.CreatedTime <= endOfDay) .Where(it => it.Type == dict.DictValue) .Count(); index2++; } seriesData_Item.Data = values; SeriesData.Add(seriesData_Item); } result.XData = Xdata; result.SeriesData = SeriesData; return result; } /// /// 获取设备故障类别累计次数折线图 /// /// /// public DeviceFaultLineResultDto FaultTypeLine(DeviceDefaultDto devicedefault) { DeviceFaultLineResultDto result = new DeviceFaultLineResultDto(); int[] all_device_type_array = null; if (devicedefault.DevicetTypeId > 0) { List all_device_type_list = FindAllLeafNodes( Context.Queryable().ToList(), devicedefault.DevicetTypeId ?? 0 ); all_device_type_array = all_device_type_list.Select(it => it.Id).ToArray(); } var predicate = Expressionable .Create() .AndIF( all_device_type_array != null && all_device_type_array.Length > 0, (r, a, d) => all_device_type_array.Contains(a.FkDeviceType) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceName), (r, a, d) => a.DeviceName.Contains(devicedefault.DeviceName) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceCode), (r, a, d) => a.DeviceCode.Contains(devicedefault.DeviceCode) ) .AndIF( devicedefault.searchTime[0] > new DateTime(1991, 1, 1), (r, a, d) => r.CreatedTime >= devicedefault.searchTime[0] ) .AndIF( devicedefault.searchTime[1] > new DateTime(1991, 1, 1), (r, a, d) => r.CreatedTime <= devicedefault.searchTime[1] ) .And((r, a, d) => d.DictType == "mes_device_fault_type"); List deviceRepair_list = Context .Queryable() .LeftJoin((r, a) => r.FkDeviceId == a.Id) .LeftJoin((r, a, d) => r.Type == d.DictValue) .Where(predicate.ToExpression()) .Select( (r, a, d) => new DeviceRepair_chart { Id = r.Id, Type = r.Type, TypeName = d.DictLabel, CreatedTime = (DateTime)r.CreatedTime } ) .ToList(); foreach (var repair in deviceRepair_list) { repair.AccValue_SameType = Context .Queryable() .Where(it => it.Type == repair.Type) .Where(it => it.CreatedTime <= repair.CreatedTime) .Count(); } //获取所有故障类型 List all_fault_type = Context .Queryable() .Where(it => it.DictType == "mes_device_fault_type") .ToList(); // 先按照天进行上卷聚合,然后按照故障种类进行上卷聚合 var first_groups = deviceRepair_list.GroupBy(it => it.CreatedTime.Date); string[] Xdata = new string[first_groups.Count()]; int index = 0; foreach (var group in first_groups) { Xdata[index] = group.Key.ToString("yyyy-MM-dd"); index++; } //处理纵坐标 List SeriesData = new List(); foreach (SysDictData dict in all_fault_type) { SeriesData_Item_line seriesData_Item = new SeriesData_Item_line(); seriesData_Item.Name = dict.DictLabel; seriesData_Item.Type = "line"; int[] values = new int[first_groups.Count()]; int index2 = 0; foreach (var group in first_groups) { //凌晨 DateTime startOfDay = group.Key; //午夜(23:59:59) DateTime endOfDay = group.Key.AddDays(1).AddSeconds(-1); values[index2] = deviceRepair_list .Where(it => it.CreatedTime <= endOfDay) .Where(it => it.Type == dict.DictValue) .Sum(it => it.AccValue_SameType); index2++; } seriesData_Item.Data = values; SeriesData.Add(seriesData_Item); } result.XData = Xdata; result.SeriesData = SeriesData; return result; } /// /// 获取每日设备故障总数与维修完成数柱状图 /// /// /// public DeviceRepairBarResultDto FaultTypeBarByDay(DeviceDefaultDto devicedefault) { DeviceRepairBarResultDto result = new DeviceRepairBarResultDto(); int[] all_device_type_array = null; if (devicedefault.DevicetTypeId > 0) { List all_device_type_list = FindAllLeafNodes( Context.Queryable().ToList(), devicedefault.DevicetTypeId ?? 0 ); all_device_type_array = all_device_type_list.Select(it => it.Id).ToArray(); } var predicate = Expressionable .Create() .AndIF( all_device_type_array != null && all_device_type_array.Length > 0, (r, a) => all_device_type_array.Contains(a.FkDeviceType) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceName), (r, a) => a.DeviceName.Contains(devicedefault.DeviceName) ) .AndIF( !string.IsNullOrEmpty(devicedefault.DeviceCode), (r, a) => a.DeviceCode.Contains(devicedefault.DeviceCode) ) .AndIF( devicedefault.searchTime[0] > new DateTime(1991, 1, 1), (r, a) => r.CreatedTime >= devicedefault.searchTime[0] ) .AndIF( devicedefault.searchTime[1] > new DateTime(1991, 1, 1), (r, a) => r.CreatedTime <= devicedefault.searchTime[1] ); List deviceRepair_list = Context .Queryable() .LeftJoin((r, a) => r.FkDeviceId == a.Id) .Where(predicate.ToExpression()) .Select( (r, a) => new DeviceRepair_chart { Id = r.Id, Type = r.Type, Status = r.Status ?? 0, CreatedTime = (DateTime)r.CreatedTime } ) .ToList(); // 先按照天进行上卷聚合 var first_groups = deviceRepair_list.GroupBy(it => it.CreatedTime.Date); string[] Xdata = new string[first_groups.Count()]; int index = 0; foreach (var group in first_groups) { Xdata[index] = group.Key.ToString("yyyy-MM-dd"); index++; } result.XData = Xdata; List SeriesData = new List(); SeriesData_Item_line2 faultAll = new SeriesData_Item_line2(); faultAll.Name = "报修数"; int[] Data1 = new int[first_groups.Count()]; int index1 = 0; foreach (var group in first_groups) { Data1[index1] = group.Count(); index1++; } faultAll.Data = Data1; SeriesData.Add(faultAll); SeriesData_Item_line2 repair_success_all = new SeriesData_Item_line2(); repair_success_all.Name = "维修数"; List deviceRepair_list_success = Context .Queryable() .LeftJoin((r, a) => r.FkDeviceId == a.Id) .Where(predicate.ToExpression()) .Where((r, a) => r.Status == 2) .Select( (r, a) => new DeviceRepair_chart { Id = r.Id, Type = r.Type, Status = r.Status ?? 0, CreatedTime = (DateTime)r.CreatedTime } ) .ToList(); // 先按照天进行上卷聚合 var first_groups_success = deviceRepair_list.GroupBy(it => it.CreatedTime.Date); int[] Data2 = new int[first_groups_success.Count()]; int index2 = 0; foreach (var group in first_groups_success) { Data2[index2] = group.Count(); index2++; } repair_success_all.Data = Data2; SeriesData.Add(repair_success_all); result.SeriesData = SeriesData; return result; } /// /// 获取每日点检巡检总数折线图 /// /// /// public TaskLineResultDto TaskLinebyDay(DeviceDefaultDto devicedefault) { TaskLineResultDto taskLine = new TaskLineResultDto(); var predicate = Expressionable .Create() .AndIF( devicedefault.searchTime[0] > new DateTime(1991, 1, 1), (r) => r.CreatedTime >= devicedefault.searchTime[0] ) .AndIF( devicedefault.searchTime[1] > new DateTime(1991, 1, 1), (r) => r.CreatedTime <= devicedefault.searchTime[1] ) .ToExpression(); List InitDataCollection = Context .Queryable() .Where(predicate) .ToList(); List SeriesData = new List(); var SecondDataCollection = InitDataCollection.GroupBy(it => ((DateTime)it.CreatedTime).Date ); string[] Xdata = new string[SecondDataCollection.Count()]; int index = 0; foreach (var group in SecondDataCollection) { Xdata[index] = group.Key.ToString("yyyy-MM-dd"); index++; } taskLine.XData = Xdata; SeriesData_Item_line3 line3 = new SeriesData_Item_line3(); int[] Data = new int[SecondDataCollection.Count()]; int index2 = 0; foreach (var group in SecondDataCollection) { Data[index2] = group.Count(); index2++; } line3.Data = Data; SeriesData.Add(line3); taskLine.SeriesData = SeriesData; return taskLine; } private PersonnelResponseResultDto dataAnalysis(DeviceDefaultDto devicedefault) { PersonnelResponseResultDto personnelResponseResultDto = new PersonnelResponseResultDto(); personnelResponseResultDto.XData = []; personnelResponseResultDto.SeriesData = null; // 任务接受响应系列 PersonnelResponse_Series task_accept_series = new PersonnelResponse_Series(); var predicate = Expressionable .Create() .AndIF( devicedefault.searchTime[0] > new DateTime(1991, 1, 1), (r) => r.CreatedTime >= devicedefault.searchTime[0] ) .AndIF( devicedefault.searchTime[1] > new DateTime(1991, 1, 1), (r) => r.CreatedTime <= devicedefault.searchTime[1] ) .And(it => it.DistributedTime != DateTime.MinValue) .And(it => it.StartTime != DateTime.MinValue) .And(it => it.EndTime != DateTime.MinValue) .ToExpression(); List InitDataCollection = Context .Queryable() .Where(predicate) .ToList(); if (InitDataCollection.Count == 0) { personnelResponseResultDto.TaskTotal = 0; personnelResponseResultDto.TaskMax = new TimeSpan(0); personnelResponseResultDto.TaskMin = new TimeSpan(0); personnelResponseResultDto.TaskAvg = new TimeSpan(0); return personnelResponseResultDto; } personnelResponseResultDto.TaskTotal = InitDataCollection.Count; PersonnelResponseDto[] SecondDataCollection = new PersonnelResponseDto[ InitDataCollection.Count ]; string[] XData = new string[InitDataCollection.Count]; int[] resultDate = new int[InitDataCollection.Count]; if (InitDataCollection.Count > 0) { int index = 0; foreach (var item in InitDataCollection) { XData[index] = item.TaskName; PersonnelResponseDto temp = new PersonnelResponseDto(); temp.Id = item.Id; temp.TaskName = item.TaskName; temp.Accept_response = (item.StartTime ?? DateTime.Now) - (item.DistributedTime ?? DateTime.Now); temp.Action_response = (item.EndTime ?? DateTime.Now) - (item.StartTime ?? DateTime.Now); SecondDataCollection[index] = temp; index++; } } #region 固定配置 MarkPoint_ markPoint_ = new MarkPoint_(); TypeName[] data = new TypeName[2]; TypeName item1 = new TypeName(); item1.Type = "max"; item1.Name = "最大值"; data[0] = item1; TypeName item2 = new TypeName(); item2.Type = "min"; item2.Name = "最小值"; data[1] = item2; markPoint_.data = data; task_accept_series.markPoint = markPoint_; MarkPoint_ markLine = new MarkPoint_(); TypeName[] data2 = new TypeName[1]; TypeName item3 = new TypeName(); item3.Type = "average"; item3.Name = "平均值"; data2[0] = item3; markLine.data = data2; task_accept_series.markLine = markLine; #endregion if (devicedefault.searchType == 1) { task_accept_series.Name = "人员接受任务响应时间"; personnelResponseResultDto.TaskMax = SecondDataCollection.Max(it => it.Accept_response ); personnelResponseResultDto.TaskMin = SecondDataCollection.Min(it => it.Accept_response ); personnelResponseResultDto.TaskAvg = CalculateAverageTimeSpan( SecondDataCollection.Select(it => it.Action_response).ToArray() ); personnelResponseResultDto.SeriesData = task_accept_series; resultDate = SecondDataCollection .Select(it => (int)Math.Ceiling(it.Accept_response.TotalMinutes)) .ToArray(); } else if (devicedefault.searchType == 2) { task_accept_series.Name = "人员处理任务响应时间"; personnelResponseResultDto.TaskMax = SecondDataCollection.Max(it => it.Action_response ); personnelResponseResultDto.TaskMin = SecondDataCollection.Min(it => it.Action_response ); personnelResponseResultDto.TaskAvg = CalculateAverageTimeSpan( SecondDataCollection.Select(it => it.Action_response).ToArray() ); personnelResponseResultDto.SeriesData = task_accept_series; resultDate = SecondDataCollection .Select(it => (int)Math.Ceiling(it.Action_response.TotalMinutes)) .ToArray(); } personnelResponseResultDto.XData = XData; personnelResponseResultDto.SeriesData.Data = resultDate; return personnelResponseResultDto; } /// /// 获取人员响应折线图 /// /// /// public PersonnelResponseResultDto PersonResponse(DeviceDefaultDto devicedefault) { PersonnelResponseResultDto crount = dataAnalysis(devicedefault); DeviceDefaultDto devicedefault_last = new DeviceDefaultDto(); devicedefault_last.searchType = devicedefault.searchType; DateTime lastMondayMidnight, lastSundayMidnight; GetLastWeekBoundaries( devicedefault.searchTime[0], out lastMondayMidnight, out lastSundayMidnight ); devicedefault_last.searchTime = new DateTime[2] { lastMondayMidnight, lastSundayMidnight }; PersonnelResponseResultDto last = dataAnalysis(devicedefault_last); crount.lastTotalPer = CalculatePercentageIncrease(crount.TaskTotal, last.TaskTotal); crount.lastMaxPer = CalculatePercentageIncrease(crount.TaskMax, last.TaskMax); crount.lastMinPer = CalculatePercentageIncrease(crount.TaskMin, last.TaskMin); crount.lastAvgPer = CalculatePercentageIncrease(crount.TaskAvg, last.TaskAvg); return crount; } private static int CalculatePercentageIncrease(int number1, int number2) { if (number2 == 0) { return 100; } return ((int)(number1 - number2) / number2) * 100; } private static int CalculatePercentageIncrease(TimeSpan timeSpan1, TimeSpan timeSpan2) { double totalSeconds1 = timeSpan1.TotalSeconds; double totalSeconds2 = timeSpan2.TotalSeconds; if (totalSeconds2 == 0) { return 100; } return (int)((totalSeconds1 - totalSeconds2) / totalSeconds2) * 100; } public static TimeSpan CalculateAverageTimeSpan(TimeSpan[] timeSpans) { // 将 TimeSpan 数组中的每个 TimeSpan 值转换为总秒数 double totalSeconds = timeSpans.Sum(ts => ts.TotalSeconds); // 计算平均总秒数 double averageSeconds = totalSeconds / timeSpans.Length; // 将平均总秒数转换为 TimeSpan 格式 TimeSpan averageTimeSpan = TimeSpan.FromSeconds(averageSeconds); return averageTimeSpan; } public static void GetLastWeekBoundaries( DateTime inputDateTime, out DateTime lastMondayMidnight, out DateTime lastSundayMidnight ) { DayOfWeek currentDayOfWeek = inputDateTime.DayOfWeek; int daysToSubtract = (int)currentDayOfWeek + 6; // 6 days to subtract to get to last Monday lastMondayMidnight = inputDateTime.Date.AddDays(-daysToSubtract).AddDays(-7).Date; // Last Monday midnight lastSundayMidnight = lastMondayMidnight .AddDays(6) .AddHours(23) .AddMinutes(59) .AddSeconds(59); // Last Sunday midnight } /// /// 获取大屏总数 - 报修部分分开查询 /// /// public FullScreenTotal GetAllTotal() { var screenTotal = new FullScreenTotal(); // 设备可用数/停机数(保持原样) screenTotal.UseDeviceTotal = Context .Queryable() .Where(it => it.Status == 1) .Count(); screenTotal.UnUseDeviceTotal = Context .Queryable() .Where(it => it.Status == 0) .Count(); // 累计任务数/已完成任务数(保持原样) screenTotal.TaskTotal = Context.Queryable().Count(); screenTotal.FinishTaskTotal = Context .Queryable() .Where(it => it.Status == 2) .Count(); // 报修分类:分开查询 var startOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1); var endOfMonth = startOfMonth.AddMonths(1).AddSeconds(-1); // 1. 本月总报修数 screenTotal.RepairTotal = Context .Queryable() .Where(it => it.CreatedTime >= startOfMonth && it.CreatedTime <= endOfMonth) .Count(); // 2. 本月已完成的报修数(Status == 2) const int RepairFinishedStatus = 2; screenTotal.FinishRepairTotal = Context .Queryable() .Where(it => it.CreatedTime >= startOfMonth && it.CreatedTime <= endOfMonth && it.Status == RepairFinishedStatus ) .Count(); return screenTotal; } public List GetTaskExecuteList(DeviceDataListDto parm) { var predicate = Expressionable .Create() .AndIF(parm.StartTime > DateTime.MinValue, it => it.CreatedTime >= parm.StartTime) .AndIF(parm.EndTime > DateTime.MinValue, it => it.CreatedTime <= parm.EndTime); var response = Context .Queryable() .Where(predicate.ToExpression()) .OrderByDescending(x => x.Id) .ToList(); return response; } public List GetDeviceRepairList(DeviceDataListDto parm) { var predicate = Expressionable .Create() .AndIF(parm.StartTime > DateTime.MinValue, (dr,da) => dr.CreatedTime >= parm.StartTime) .AndIF(parm.EndTime > DateTime.MinValue, (dr, da) => dr.CreatedTime <= parm.EndTime); var response = Context .Queryable((dr, da) => new JoinQueryInfos(JoinType.Left,dr.FkDeviceId == da.Id)) .Where(predicate.ToExpression()) .OrderByDescending((dr, da) => dr.Id) .Select() .ToList(); return response; } } }