using MoviconWebApi.Entities; namespace MoviconWebApi.API.DeviceStateApi { public static class Data { /// /// 获取设备状态列表 /// public static async Task> GetDeviceStateListAsync( IFreeSql db, DeviceStateRequest request) { try { // 1) 校验时间范围 var hasStart = DateTime.TryParse(request.StartTime, out var startTime); var hasEnd = DateTime.TryParse(request.EndTime, out var endTime); if (!hasStart || !hasEnd) { // 未提供有效时间范围,返回空列表(遵循列表查询返回空集合不返回404的约定) return new List(); } if (endTime < startTime) { // 纠正时间顺序或直接返回空 return new List(); } var totalMinutes = (endTime - startTime).TotalMinutes; if (totalMinutes <= 0) { return new List(); } // 2) 基础查询(按设备、时间过滤) var baseQuery = db.Select() .WhereIf(!string.IsNullOrWhiteSpace(request.DeviceCode), x => x.DeviceCode == request.DeviceCode) .Where(x => x.CreateTime >= startTime && x.CreateTime <= endTime); // 3) 聚合统计:仅选择必要字段到内存做聚合,避免类型不兼容问题 var lightList = await baseQuery.ToListAsync(a => new { a.PowerOnTime, a.RunTime, a.StandbyTime, a.FaultTime, a.ShutdownTime, a.FaultNum }); long totalPowerOn = lightList.Sum(x => (long)(x.PowerOnTime ?? 0)); long totalRun = lightList.Sum(x => (long)(x.RunTime ?? 0)); long totalStandby = lightList.Sum(x => (long)(x.StandbyTime ?? 0)); long totalFault = lightList.Sum(x => (long)(x.FaultTime ?? 0)); long totalShutdown = lightList.Sum(x => (long)(x.ShutdownTime ?? 0)); long totalFaultCount = lightList.Sum(x => (long)(x.FaultNum ?? 0)); // 作业次数:来自当前搜索时间内 ClearData 的记录数 long totalJobCount = await db.Select() .WhereIf(!string.IsNullOrWhiteSpace(request.DeviceCode), x => x.DeviceCode == request.DeviceCode) .Where(x => x.CreateTime >= startTime && x.CreateTime <= endTime) .CountAsync(); // 若该时间段内没有任何记录,返回空集合 var hasAnyData = (totalPowerOn + totalRun + totalStandby + totalFault + totalShutdown + totalFaultCount + totalJobCount) > 0; if (!hasAnyData) { return new List(); } // 4) 计算使用率:默认按(开机+运行+待机+故障)/ 时间段总分钟 var usedMinutes = totalPowerOn + totalRun + totalStandby + totalFault; // 排除关机 double ratio = usedMinutes <= 0 ? 0 : Math.Min(100.0, Math.Max(0.0, usedMinutes * 100.0 / totalMinutes)); var useRatioText = $"{Math.Round(ratio, 2)}%"; // 5) 获取设备名称(取时间段内最新一条的名称,避免跨设备统计导致名称混淆) string? deviceName = null; try { deviceName = await db.Select() .WhereIf(!string.IsNullOrWhiteSpace(request.DeviceCode), x => x.DeviceCode == request.DeviceCode) .Where(x => x.CreateTime >= startTime && x.CreateTime <= endTime) .OrderByDescending(x => x.CreateTime) .FirstAsync(x => x.DeviceName); } catch { // 忽略设备名获取失败,不影响主逻辑 } // 6) 组装单条汇总结果 var summary = new DeviceStateResponse { DeviceCode = string.IsNullOrWhiteSpace(request.DeviceCode) ? null : request.DeviceCode, DeviceName = deviceName, PowerOnTime = (int)totalPowerOn, RunTime = (int)totalRun, StandbyTime = (int)totalStandby, FaultTime = (int)totalFault, ShutdownTime = (int)totalShutdown, UseRatio = useRatioText, FaultNum = (int)totalFaultCount, JobNum = totalJobCount > int.MaxValue ? int.MaxValue : (int)totalJobCount, CreateTime = endTime.ToString("yyyy-MM-dd HH:mm:ss") }; return new List { summary }; } catch (Exception ex) { throw new Exception($"查询设备状态数据失败: {ex.Message}", ex); } } /// /// 分页获取设备状态 /// public static async Task<(List, long)> GetDeviceStatePagedAsync( IFreeSql db, DeviceStatePagedRequest request) { try { var query = db.Select() .WhereIf(!string.IsNullOrWhiteSpace(request.DeviceCode), a => a.DeviceCode == request.DeviceCode); if (!string.IsNullOrWhiteSpace(request.StartTime) && DateTime.TryParse(request.StartTime, out var startTime)) { query = query.Where(a => a.CreateTime >= startTime); } if (!string.IsNullOrWhiteSpace(request.EndTime) && DateTime.TryParse(request.EndTime, out var endTime)) { query = query.Where(a => a.CreateTime <= endTime); } var total = await query.CountAsync(); var data = await query .OrderByDescending(a => a.CreateTime) .Page(request.PageIndex, request.PageSize) .ToListAsync(a => new DeviceStateResponse { DeviceCode = a.DeviceCode, DeviceName = a.DeviceName, PowerOnTime = a.PowerOnTime, RunTime = a.RunTime, StandbyTime = a.StandbyTime, FaultTime = a.FaultTime, ShutdownTime = a.ShutdownTime, UseRatio = a.UseRatio, FaultNum = a.FaultNum, JobNum = a.JobNum, CreateTime = a.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") }); return (data ?? new List(), total); } catch (Exception ex) { throw new Exception($"分页查询设备状态数据失败: {ex.Message}", ex); } } /// /// 获取最新的设备状态记录 /// public static async Task GetLatestDeviceStateAsync( IFreeSql db, DeviceStateRequest request) { try { var query = db.Select() .WhereIf(!string.IsNullOrWhiteSpace(request.DeviceCode), a => a.DeviceCode == request.DeviceCode); if (!string.IsNullOrWhiteSpace(request.StartTime) && DateTime.TryParse(request.StartTime, out var startTime)) { query = query.Where(a => a.CreateTime >= startTime); } if (!string.IsNullOrWhiteSpace(request.EndTime) && DateTime.TryParse(request.EndTime, out var endTime)) { query = query.Where(a => a.CreateTime <= endTime); } var data = await query .OrderByDescending(a => a.CreateTime) .FirstAsync(a => new DeviceStateResponse { DeviceCode = a.DeviceCode, DeviceName = a.DeviceName, PowerOnTime = a.PowerOnTime, RunTime = a.RunTime, StandbyTime = a.StandbyTime, FaultTime = a.FaultTime, ShutdownTime = a.ShutdownTime, UseRatio = a.UseRatio, FaultNum = a.FaultNum, JobNum = a.JobNum, CreateTime = a.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") }); return data; } catch (Exception ex) { throw new Exception($"查询最新设备状态数据失败: {ex.Message}", ex); } } } }