From a954427d41efcfe362a5af32686041812c668d27 Mon Sep 17 00:00:00 2001 From: Tyrone CT Date: Wed, 17 Sep 2025 17:22:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=96=B0=E9=9C=80=E6=B1=82?= =?UTF-8?q?=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MoviconHub.App/Models/ClearAction.cs | 84 ++++++++++++++- MoviconHub.App/Models/ClearData.cs | 106 +++++++++++++++++++ MoviconHub.App/Models/DeviceStatusChange.cs | 60 +++++++++++ MoviconHub.App/Models/TestData.cs | 83 +++++++++++++++ MoviconHub.App/MoviconHub.App.csproj | 1 + MoviconHub.App/Services/DBServices.cs | 2 +- MoviconHub.App/frmMain.cs | 52 ++++++++- MoviconWebApi/API/ClearDataApi/Data.cs | 24 +++-- MoviconWebApi/API/ClearDataApi/Endpoint.cs | 53 +++++----- MoviconWebApi/API/ClearDataApi/Models.cs | 12 ++- MoviconWebApi/API/ClearDataQrApi/Data.cs | 22 ++-- MoviconWebApi/API/ClearDataQrApi/Endpoint.cs | 36 ++++--- MoviconWebApi/API/ClearDataQrApi/Models.cs | 12 ++- MoviconWebApi/API/ClearStaticApi/Data.cs | 74 +++++++------ MoviconWebApi/API/ClearStaticApi/Models.cs | 32 +++--- MoviconWebApi/API/DeviceAlarmApi/Data.cs | 15 ++- MoviconWebApi/API/DeviceAlarmApi/Endpoint.cs | 33 +++++- MoviconWebApi/API/DeviceAlarmApi/Models.cs | 12 ++- MoviconWebApi/API/DeviceStateApi/Endpoint.cs | 6 +- MoviconWebApi/Common/ApiResponse.cs | 7 +- MoviconWebApi/Common/Pagination.cs | 33 ++++++ 21 files changed, 633 insertions(+), 126 deletions(-) create mode 100644 MoviconHub.App/Models/DeviceStatusChange.cs create mode 100644 MoviconWebApi/Common/Pagination.cs diff --git a/MoviconHub.App/Models/ClearAction.cs b/MoviconHub.App/Models/ClearAction.cs index f929a9d..f5da4cf 100644 --- a/MoviconHub.App/Models/ClearAction.cs +++ b/MoviconHub.App/Models/ClearAction.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; namespace MoviconHub.App.Models { @@ -11,11 +7,22 @@ namespace MoviconHub.App.Models /// public class ClearAction { + /// /// 清洗事件 /// public event EventHandler ClearActionEvent; + /// + /// 设备状态改变事件 + /// + public event EventHandler DeviceStateChangeEvent; + + + // 状态变更并发锁:确保在多线程环境下,状态切换与事件发布的原子性,避免竞态条件 + private readonly object _stateLock = new object(); + // 是否已存在当前状态:用于首次赋值时不发布“上一状态”事件的标记 + private bool _hasCurrentState = false; private bool _ClearEnd; /// @@ -61,7 +68,74 @@ namespace MoviconHub.App.Models } } + /// + /// 当前状态信息 + /// + public StateInfo CurStateInfo { get; set; } = new StateInfo(); + private int _DeviceState; + /// + /// 设备状态 + /// + public int DeviceState + { + get { return _DeviceState; } + set + { + if (_DeviceState != value) + { + lock (_stateLock) + { + var now = DateTime.Now; + // 若已有当前状态,先发布上一个状态的维持区间 + if (_hasCurrentState) + { + var prevStateInfo = new StateInfo + { + StartTime = CurStateInfo.StartTime, + EndTime = now, + State = CurStateInfo.State + }; + + var handler = DeviceStateChangeEvent; + handler?.BeginInvoke(this, prevStateInfo, null, null); + } + + // 更新为新的当前状态 + _DeviceState = value; + CurStateInfo = new StateInfo + { + StartTime = now, + EndTime = default, // 结束时间在下次状态变化时确定 + State = value + }; + _hasCurrentState = true; + } + } + + } + } + } + + /// + /// 状态信息 + /// + public class StateInfo + { + /// + /// 开始时间 + /// + public DateTime StartTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime EndTime { get; set; } + + /// + /// 值 + /// + public int State { get; set; } } } diff --git a/MoviconHub.App/Models/ClearData.cs b/MoviconHub.App/Models/ClearData.cs index b8f616c..5e642b9 100644 --- a/MoviconHub.App/Models/ClearData.cs +++ b/MoviconHub.App/Models/ClearData.cs @@ -181,6 +181,112 @@ namespace MoviconHub.App.Models [Column(Name = "Test_SteamSurveillance", StringLength = 100, IsNullable = true)] public string Test_SteamSurveillance { get; set; } + + + + + + + + + + ///// + ///// ​零部件车间桁架平移原位​​ + ///// + //[Column(Name = "Test_TrussMoveHome", StringLength = 100, IsNullable = true)] + //public string Test_TrussMoveHome { get; set; } + + + ///// + ///// ​零部件车间桁架平移后退极限位​​ + ///// + //[Column(Name = "Test_TrussMoveBackwardLimit", StringLength = 100, IsNullable = true)] + //public string Test_TrussMoveBackwardLimit { get; set; } + + + ///// + ///// ​零部件车间桁架平移前进极限位​​ + ///// + //[Column(Name = "Test_TrussMoveForwardLimit", StringLength = 100, IsNullable = true)] + //public string Test_TrussMoveForwardLimit { get; set; } + + + ///// + ///// ​零部件车间桁架吊装浸泡池吊装位​​ + ///// + //[Column(Name = "Test_TrussLiftPoolPos", StringLength = 100, IsNullable = true)] + //public string Test_TrussLiftPoolPos { get; set; } + + + ///// + ///// ​零部件车间桁架吊装下降极限位​​ + ///// + //[Column(Name = "Test_TrussLiftLowerLimit", StringLength = 100, IsNullable = true)] + //public string Test_TrussLiftLowerLimit { get; set; } + + + ///// + ///// ​零部件车间桁架吊装原位​​ + ///// + //[Column(Name = "Test_TrussLiftHome", StringLength = 100, IsNullable = true)] + //public string Test_TrussLiftHome { get; set; } + + + ///// + ///// ​零部件车间桁架吊装上升极限位​​ + ///// + //[Column(Name = "Test_TrussLiftRiseLimit", StringLength = 100, IsNullable = true)] + //public string Test_TrussLiftRiseLimit { get; set; } + + + ///// + ///// ​零部件车间桁架吊装漫射吊装位​​ + ///// + //[Column(Name = "Test_TrussLiftWashPos", StringLength = 100, IsNullable = true)] + //public string Test_TrussLiftWashPos { get; set; } + + + ///// + ///// ​ROB1_第7轴接近开关ROB1原位​​ + ///// + //[Column(Name = "Test_Rob1Axis7Home", StringLength = 100, IsNullable = true)] + //public string Test_Rob1Axis7Home { get; set; } + + + ///// + ///// ​ROB1_第7轴接近开关前进极限位正常​​ + ///// + //[Column(Name = "Test_Rob1Axis7ForwardLimitOK", StringLength = 100, IsNullable = true)] + //public string Test_Rob1Axis7ForwardLimitOK { get; set; } + + + ///// + ///// ​ROB1_第7轴接近开关后退极限位正常​​ + ///// + //[Column(Name = "Test_Rob1Axis7BackwardLimitOK", StringLength = 100, IsNullable = true)] + //public string Test_Rob1Axis7BackwardLimitOK { get; set; } + + + ///// + ///// ​ROB2_第7轴接近开关ROB2原位​​ + ///// + //[Column(Name = "Test_Rob2Axis7Home", StringLength = 100, IsNullable = true)] + //public string Test_Rob2Axis7Home { get; set; } + + + ///// + ///// ​ROB2_第7轴接近开关前进极限位正常​​ + ///// + //[Column(Name = "Test_Rob2Axis7ForwardLimitOK", StringLength = 100, IsNullable = true)] + //public string Test_Rob2Axis7ForwardLimitOK { get; set; } + + + ///// + ///// ​ROB2_第7轴接近开关后退极限位正常​​ + ///// + //[Column(Name = "Test_Rob2Axis7BackwardLimitOK", StringLength = 100, IsNullable = true)] + //public string Test_Rob2Axis7BackwardLimitOK { get; set; } + /// /// 创建时间 /// diff --git a/MoviconHub.App/Models/DeviceStatusChange.cs b/MoviconHub.App/Models/DeviceStatusChange.cs new file mode 100644 index 0000000..9787977 --- /dev/null +++ b/MoviconHub.App/Models/DeviceStatusChange.cs @@ -0,0 +1,60 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MoviconHub.App.Models +{ + /// + /// 设备状态改变 + /// + [Table(Name = "DeviceStatusChange")] + public class DeviceStatusChange + { + /// + /// 主键ID + /// + [Column(IsPrimary = true, IsIdentity = true)] + public long Id { get; set; } + + + /// + /// 设备码 + /// + [Column(Name = "DeviceCode", StringLength = 100, IsNullable = true)] + public string DeviceCode { get; set; } + + /// + /// 设备名称 + /// + [Column(Name = "DeviceName", StringLength = 100, IsNullable = true)] + public string DeviceName { get; set; } + + /// + /// 开始时间 + /// + [Column(Name = "StartTime", IsNullable = true)] + public DateTime StartTime { get; set; } + + /// + /// 结束时间 + /// + [Column(Name = "EndTime", IsNullable = true)] + public DateTime EndTime { get; set; } + + /// + /// 设备状态 + /// + [Column(Name = "DeviceState", IsNullable = true)] + public int? DeviceState { get; set; } + + + /// + /// 创建时间 + /// + [Column(ServerTime = DateTimeKind.Local, CanUpdate = false)] + public DateTime CreateTime { get; set; } + } +} diff --git a/MoviconHub.App/Models/TestData.cs b/MoviconHub.App/Models/TestData.cs index 0f853e1..b96bc48 100644 --- a/MoviconHub.App/Models/TestData.cs +++ b/MoviconHub.App/Models/TestData.cs @@ -209,6 +209,89 @@ namespace MoviconHub.App.Models [JsonProperty("Test_SteamSurveillance")] public string Test_SteamSurveillance { get; set; } + /// + /// ​零部件车间桁架平移原位​​ + /// + [JsonProperty("Test_TrussMoveHome")] + public string Test_TrussMoveHome { get; set; } + + /// + /// ​零部件车间桁架平移后退极限位​​ + /// + [JsonProperty("Test_TrussMoveBackwardLimit")] + public string Test_TrussMoveBackwardLimit { get; set; } + + /// + /// ​零部件车间桁架平移前进极限位​​ + /// + [JsonProperty("Test_TrussMoveForwardLimit")] + public string Test_TrussMoveForwardLimit { get; set; } + + /// + /// ​零部件车间桁架吊装浸泡池吊装位​​ + /// + [JsonProperty("Test_TrussLiftPoolPos")] + public string Test_TrussLiftPoolPos { get; set; } + + /// + /// ​零部件车间桁架吊装下降极限位​​ + /// + [JsonProperty("Test_TrussLiftLowerLimit")] + public string Test_TrussLiftLowerLimit { get; set; } + + /// + /// ​零部件车间桁架吊装原位​​ + /// + [JsonProperty("Test_TrussLiftHome")] + public string Test_TrussLiftHome { get; set; } + + /// + /// ​零部件车间桁架吊装上升极限位​​ + /// + [JsonProperty("Test_TrussLiftRiseLimit")] + public string Test_TrussLiftRiseLimit { get; set; } + + /// + /// ​零部件车间桁架吊装漫射吊装位​​ + /// + [JsonProperty("Test_TrussLiftWashPos")] + public string Test_TrussLiftWashPos { get; set; } + + /// + /// ​ROB1_第7轴接近开关ROB1原位​​ + /// + [JsonProperty("Test_Rob1Axis7Home")] + public string Test_Rob1Axis7Home { get; set; } + + /// + /// ​ROB1_第7轴接近开关前进极限位正常​​ + /// + [JsonProperty("Test_Rob1Axis7ForwardLimitOK")] + public string Test_Rob1Axis7ForwardLimitOK { get; set; } + + /// + /// ​ROB1_第7轴接近开关后退极限位正常​​ + /// + [JsonProperty("Test_Rob1Axis7BackwardLimitOK")] + public string Test_Rob1Axis7BackwardLimitOK { get; set; } + + /// + /// ​ROB2_第7轴接近开关ROB2原位​​ + /// + [JsonProperty("Test_Rob2Axis7Home")] + public string Test_Rob2Axis7Home { get; set; } + + /// + /// ​ROB2_第7轴接近开关前进极限位正常​​ + /// + [JsonProperty("Test_Rob2Axis7ForwardLimitOK")] + public string Test_Rob2Axis7ForwardLimitOK { get; set; } + + /// + /// ​ROB2_第7轴接近开关后退极限位正常​​ + /// + [JsonProperty("Test_Rob2Axis7BackwardLimitOK")] + public string Test_Rob2Axis7BackwardLimitOK { get; set; } /// /// 测试数据值集合 diff --git a/MoviconHub.App/MoviconHub.App.csproj b/MoviconHub.App/MoviconHub.App.csproj index 0506e40..2ae4016 100644 --- a/MoviconHub.App/MoviconHub.App.csproj +++ b/MoviconHub.App/MoviconHub.App.csproj @@ -128,6 +128,7 @@ + diff --git a/MoviconHub.App/Services/DBServices.cs b/MoviconHub.App/Services/DBServices.cs index f661309..b0383f1 100644 --- a/MoviconHub.App/Services/DBServices.cs +++ b/MoviconHub.App/Services/DBServices.cs @@ -257,7 +257,7 @@ namespace MoviconHub.App.Services Test_WaterTankAdd = webSocketData.TestData.Test_WaterTankAdd, Test_CleaningAgentTankHeat = webSocketData.TestData.Test_CleaningAgentTankHeat, Test_CleaningAgentTankAdd = webSocketData.TestData.Test_CleaningAgentTankAdd, - + // 监控信息 Test_ElectricSurveillance = webSocketData.TestData.Test_ElectricSurveillance, Test_SteamSurveillance = webSocketData.TestData.Test_SteamSurveillance diff --git a/MoviconHub.App/frmMain.cs b/MoviconHub.App/frmMain.cs index 65fe915..0978276 100644 --- a/MoviconHub.App/frmMain.cs +++ b/MoviconHub.App/frmMain.cs @@ -70,6 +70,7 @@ namespace MoviconHub.App ClearActionInstance = new ClearAction(); ClearActionInstance.ClearActionEvent += ClearActionInstance_ClearActionEvent; + ClearActionInstance.DeviceStateChangeEvent += ClearActionInstance_DeviceStateChangeEvent; ListAlarmModels = new List() { @@ -437,6 +438,29 @@ namespace MoviconHub.App } + private void ClearActionInstance_DeviceStateChangeEvent(object sender, StateInfo Value) + { + var Data = new DeviceStatusChange() + { + DeviceCode = "942010002", + DeviceName = "机车构架及大部件自动化智能清洗设备", + DeviceState = Value.State, + StartTime = Value.StartTime, + EndTime = Value.EndTime, + }; + + var Result = FRemoteSqlContext.FDb.Insert(Data).ExecuteInserted(); + if (Result != null && Result.Count > 0) + { + Logger.Info("设备数据状态改变保存完成"); + + BeginInvoke(new Action(() => + { + MainText.AppendText($"时间:{DateTime.Now}-Msg:设备数据状态改变保存完成 {Environment.NewLine}"); + })); + } + } + /// /// 清洗动作实例信息 /// @@ -532,7 +556,23 @@ namespace MoviconHub.App // 监控信息 Test_ElectricSurveillance = CurDBServices.RealtimeData.TestData.Test_ElectricSurveillance, - Test_SteamSurveillance = CurDBServices.RealtimeData.TestData.Test_SteamSurveillance + Test_SteamSurveillance = CurDBServices.RealtimeData.TestData.Test_SteamSurveillance, + + //Test_Rob1Axis7BackwardLimitOK = CurDBServices.RealtimeData.TestData.Test_Rob1Axis7BackwardLimitOK, + //Test_Rob1Axis7ForwardLimitOK = CurDBServices.RealtimeData.TestData.Test_Rob1Axis7ForwardLimitOK, + //Test_Rob1Axis7Home = CurDBServices.RealtimeData.TestData.Test_Rob1Axis7Home, + //Test_Rob2Axis7BackwardLimitOK = CurDBServices.RealtimeData.TestData.Test_Rob2Axis7BackwardLimitOK, + //Test_Rob2Axis7ForwardLimitOK = CurDBServices.RealtimeData.TestData.Test_Rob2Axis7ForwardLimitOK, + //Test_Rob2Axis7Home = CurDBServices.RealtimeData.TestData.Test_Rob2Axis7Home, + //Test_TrussLiftHome = CurDBServices.RealtimeData.TestData.Test_TrussLiftHome, + //Test_TrussLiftLowerLimit = CurDBServices.RealtimeData.TestData.Test_TrussLiftLowerLimit, + //Test_TrussLiftPoolPos = CurDBServices.RealtimeData.TestData.Test_TrussLiftPoolPos, + //Test_TrussLiftRiseLimit = CurDBServices.RealtimeData.TestData.Test_TrussLiftRiseLimit, + //Test_TrussLiftWashPos = CurDBServices.RealtimeData.TestData.Test_TrussLiftWashPos, + //Test_TrussMoveBackwardLimit = CurDBServices.RealtimeData.TestData.Test_TrussMoveBackwardLimit, + //Test_TrussMoveForwardLimit = CurDBServices.RealtimeData.TestData.Test_TrussMoveForwardLimit, + //Test_TrussMoveHome = CurDBServices.RealtimeData.TestData.Test_TrussMoveHome, + }; var Result = FRemoteSqlContext.FDb.Insert(curRunData).ExecuteInserted(); @@ -594,6 +634,8 @@ namespace MoviconHub.App /// private OperateResult OperateResultDeviceStateStatic { get; set; } + private OperateResult OperateResultDeviceStateChange { get; set; } + /// /// 通信初始化 /// @@ -677,18 +719,26 @@ namespace MoviconHub.App } } + OperateResultDeviceStateChange = MelsecMcNetDrive.ReadInt16("D4000"); + if (OperateResultDeviceStateChange.IsSuccess) + { + ClearActionInstance.DeviceState = OperateResultDeviceStateChange.Content; + } + //OperateResultClearEnd = MelsecMcNetDrive.ReadBool("M210"); //if (OperateResultClearEnd.IsSuccess) //{ // ClearActionInstance.ClearEnd = OperateResultClearEnd.Content; //} + //设备清洗结束 OperateResultClearEnd = MelsecMcNetDrive.ReadBool("M211"); if (OperateResultClearEnd.IsSuccess) { ClearActionInstance.ClearEnd = OperateResultClearEnd.Content; } + //设备关机 OperateResultDeviceClose = MelsecMcNetDrive.ReadBool("M210"); if (OperateResultDeviceClose.IsSuccess) { diff --git a/MoviconWebApi/API/ClearDataApi/Data.cs b/MoviconWebApi/API/ClearDataApi/Data.cs index 9f0107f..17bf1ab 100644 --- a/MoviconWebApi/API/ClearDataApi/Data.cs +++ b/MoviconWebApi/API/ClearDataApi/Data.cs @@ -1,10 +1,10 @@ -using MoviconWebApi.Entities; +using MoviconWebApi.Entities; namespace MoviconWebApi.API.ClearDataApi { public static class Data { - internal static async Task?> GetClearData(ClearDataRequest request, IFreeSql freeSql) + internal static async Task<(List Items, long Total)> GetClearData(ClearDataRequest request, IFreeSql freeSql) { try { @@ -29,11 +29,19 @@ namespace MoviconWebApi.API.ClearDataApi query = query.Where(x => x.CreateTime <= endTime); } - // 按创建时间降序排序 - query = query.OrderByDescending(x => x.CreateTime); + // 统计总数 + var total = await query.CountAsync(); - // 执行查询并映射到响应模型 - var result = await query.ToListAsync(x => new ClearDataResponse + // 参数兜底与限制 + var pageNo = request.PageNo <= 0 ? 1 : request.PageNo; + var pageSize = request.PageSize <= 0 ? 100 : request.PageSize; + if (pageSize > 100) pageSize = 100; + + // 按创建时间降序排序 + 分页 + 映射到响应模型 + var result = await query + .OrderByDescending(x => x.CreateTime) + .Page(pageNo, pageSize) + .ToListAsync(x => new ClearDataResponse { DeviceCode = x.DeviceCode, DeviceName = x.DeviceName, @@ -66,13 +74,13 @@ namespace MoviconWebApi.API.ClearDataApi CreateTime = x.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") }); - return result; + return (result ?? new List(), total); } catch (Exception ex) { // 记录异常日志(可以根据实际需求添加日志记录) Console.WriteLine($"获取清洗数据失败:{ex.Message}"); - return null; + throw; } } diff --git a/MoviconWebApi/API/ClearDataApi/Endpoint.cs b/MoviconWebApi/API/ClearDataApi/Endpoint.cs index ac83a14..2f48398 100644 --- a/MoviconWebApi/API/ClearDataApi/Endpoint.cs +++ b/MoviconWebApi/API/ClearDataApi/Endpoint.cs @@ -1,7 +1,6 @@ -using Azure; +using Azure; using Azure.Core; using FastEndpoints; -using MoviconWebApi.API.ClearDataQrApi; using MoviconWebApi.Common; namespace MoviconWebApi.API.ClearDataApi @@ -46,35 +45,30 @@ namespace MoviconWebApi.API.ClearDataApi { try { - // 调用Data层方法获取数据 - var dataList = await Data.GetClearData(request, _freeSql); + // 参数兜底 + if (request.PageNo <= 0) request.PageNo = 1; + if (request.PageSize <= 0) request.PageSize = 100; + if (request.PageSize > 100) request.PageSize = 100; - if (dataList == null || dataList.Count == 0) + // 新的分页数据(使用全限定名避免命名冲突) + (List, long) result = await MoviconWebApi.API.ClearDataApi.Data.GetClearData(request, _freeSql); + var items = result.Item1; + var total = result.Item2; + + var resp = ApiResponse>.Success(items ?? new List(), + items != null && items.Count > 0 ? "请求成功" : "暂无数据"); + + // 组装分页 + resp.pagination = new MoviconWebApi.Common.Pagination { - // 未找到数据,返回404 - //await Send.NotFoundAsync(ct); - //Response = dataList ?? new List(); + total = total, + count = items?.Count ?? 0, + pageNo = request.PageNo, + totalPage = request.PageSize > 0 ? (int)Math.Ceiling((double)total / request.PageSize) : 0, + pageSize = request.PageSize + }; - //await Send.OkAsync(new List(), ct); - - // 没有数据 - Response = ApiResponse>.Success( - new List(), - "暂无数据" - ); - - } - else - { - //await Send.OkAsync(dataList, ct); - - // 现在的代码 - Response = ApiResponse>.Success( - dataList, - "查询成功" - ); - - } + Response = resp; } catch (Exception ex) { @@ -84,7 +78,8 @@ namespace MoviconWebApi.API.ClearDataApi // 返回错误响应 Response = ApiResponse>.Error( "500", - "服务器内部错误" + "服务器内部错误", + new List() ); //// 记录错误日志 diff --git a/MoviconWebApi/API/ClearDataApi/Models.cs b/MoviconWebApi/API/ClearDataApi/Models.cs index 451d3b0..00b4272 100644 --- a/MoviconWebApi/API/ClearDataApi/Models.cs +++ b/MoviconWebApi/API/ClearDataApi/Models.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; namespace MoviconWebApi.API.ClearDataApi { @@ -19,6 +19,16 @@ namespace MoviconWebApi.API.ClearDataApi /// public string? EndTime { get; set; } + /// + /// 当前页码(从1开始) + /// + public int PageNo { get; set; } = 1; + + /// + /// 分页大小 + /// + public int PageSize { get; set; } = 100; + } public class ClearDataResponse diff --git a/MoviconWebApi/API/ClearDataQrApi/Data.cs b/MoviconWebApi/API/ClearDataQrApi/Data.cs index d0440e7..a35fa0a 100644 --- a/MoviconWebApi/API/ClearDataQrApi/Data.cs +++ b/MoviconWebApi/API/ClearDataQrApi/Data.cs @@ -1,4 +1,4 @@ -using MoviconWebApi.Entities; +using MoviconWebApi.Entities; namespace MoviconWebApi.API.ClearDataQrApi { @@ -13,7 +13,7 @@ namespace MoviconWebApi.API.ClearDataQrApi /// 查询请求参数 /// FreeSql实例 /// 清洗数据列表 - public static async Task> GetClearDataByQr( + public static async Task<(List Data, long Total)> GetClearDataByQr( ClearDataQrRequest request, IFreeSql freeSql) { @@ -34,11 +34,19 @@ namespace MoviconWebApi.API.ClearDataQrApi query = query.Where(x => x.part_qrid == request.PartQRCode); } - // 按创建时间降序排序 - query = query.OrderByDescending(x => x.CreateTime); + // 统计总数 + var total = await query.CountAsync(); - // 执行查询并映射到响应模型 - var result = await query.ToListAsync(x => new ClearDataQrResponse + // 参数兜底 + var pageNo = request.PageNo <= 0 ? 1 : request.PageNo; + var pageSize = request.PageSize <= 0 ? 100 : request.PageSize; + if (pageSize > 100) pageSize = 100; + + // 按创建时间降序排序 + 分页 + 映射 + var result = await query + .OrderByDescending(x => x.CreateTime) + .Page(pageNo, pageSize) + .ToListAsync(x => new ClearDataQrResponse { DeviceCode = x.DeviceCode, DeviceName = x.DeviceName, @@ -71,7 +79,7 @@ namespace MoviconWebApi.API.ClearDataQrApi CreateTime = x.CreateTime.ToString("yyyy-MM-dd HH:mm:ss") }); - return result; + return (result ?? new List(), total); } catch (Exception ex) { diff --git a/MoviconWebApi/API/ClearDataQrApi/Endpoint.cs b/MoviconWebApi/API/ClearDataQrApi/Endpoint.cs index 10ca686..d27bcd4 100644 --- a/MoviconWebApi/API/ClearDataQrApi/Endpoint.cs +++ b/MoviconWebApi/API/ClearDataQrApi/Endpoint.cs @@ -1,4 +1,4 @@ -using Azure; +using Azure; using FastEndpoints; using Microsoft.Extensions.Logging; using MoviconWebApi.Common; @@ -36,18 +36,29 @@ namespace MoviconWebApi.API.ClearDataQrApi { try { - var dataList = await Data.GetClearDataByQr(request, _freeSql); + // 参数兜底 + if (request.PageNo <= 0) request.PageNo = 1; + if (request.PageSize <= 0) request.PageSize = 100; + if (request.PageSize > 100) request.PageSize = 100; - if (dataList == null || dataList.Count == 0) + var result = await Data.GetClearDataByQr(request, _freeSql); + var dataList = result.Item1; + var total = result.Item2; + + var resp = ApiResponse>.Success( + dataList ?? new List(), + (dataList != null && dataList.Count > 0) ? "请求成功" : "暂无数据"); + + resp.pagination = new MoviconWebApi.Common.Pagination { - Response = ApiResponse>.Success( - new List(), "暂无数据");// "暂无数据" - } - else - { - Response = ApiResponse>.Success( - dataList, "查询成功");// "查询成功" - } + total = total, + count = dataList?.Count ?? 0, + pageNo = request.PageNo, + totalPage = request.PageSize > 0 ? (int)Math.Ceiling((double)total / request.PageSize) : 0, + pageSize = request.PageSize + }; + + Response = resp; } catch (Exception ex) { @@ -57,7 +68,8 @@ namespace MoviconWebApi.API.ClearDataQrApi Logger.LogError(ex, "根据二维码查询清洗数据失败"); Response = ApiResponse>.Error( "500", - "服务器内部错误" + "服务器内部错误", + new List() ); } diff --git a/MoviconWebApi/API/ClearDataQrApi/Models.cs b/MoviconWebApi/API/ClearDataQrApi/Models.cs index e55aec6..5bf5f82 100644 --- a/MoviconWebApi/API/ClearDataQrApi/Models.cs +++ b/MoviconWebApi/API/ClearDataQrApi/Models.cs @@ -1,4 +1,4 @@ -namespace MoviconWebApi.API.ClearDataQrApi +namespace MoviconWebApi.API.ClearDataQrApi { /// /// 清洗数据二维码查询请求模型 @@ -14,6 +14,16 @@ /// 部件二维码 /// public string? PartQRCode { get; set; } + + /// + /// 当前页码(从1开始) + /// + public int PageNo { get; set; } = 1; + + /// + /// 分页大小 + /// + public int PageSize { get; set; } = 100; } /// diff --git a/MoviconWebApi/API/ClearStaticApi/Data.cs b/MoviconWebApi/API/ClearStaticApi/Data.cs index 2fa9a1b..e061353 100644 --- a/MoviconWebApi/API/ClearStaticApi/Data.cs +++ b/MoviconWebApi/API/ClearStaticApi/Data.cs @@ -1,4 +1,5 @@ -using MoviconWebApi.Entities; +using MoviconWebApi.Entities; +using FreeSql; namespace MoviconWebApi.API.ClearStaticApi { @@ -22,56 +23,67 @@ namespace MoviconWebApi.API.ClearStaticApi var firstDayOfMonth = new DateTime(today.Year, today.Month, 1); var firstDayOfYear = new DateTime(today.Year, 1, 1); - // 构建基础查询 - var query = freeSql.Select(); - // 构建基础查询 - //var queryDeviceState = freeSql.Select(); - - var CurRunClearData = freeSql.Select().Where(a => a.Test_PartsEquipmentStatus == "1").OrderByDescending(a => a.CreateTime).First(); - - // 根据设备编号过滤 - if (!string.IsNullOrWhiteSpace(request.DeviceCode)) + // 本地辅助函数:把分钟(字符串)汇总为小时(四舍五入到2位小数) + static decimal SumMinutesToHours(IEnumerable minutesList) { - query = query.Where(x => x.DeviceCode == request.DeviceCode); + decimal totalMinutes = 0m; + foreach (var s in minutesList) + { + if (string.IsNullOrWhiteSpace(s)) continue; + if (decimal.TryParse(s, out var m)) totalMinutes += m; + } + return Math.Round(totalMinutes / 60m, 2); } - // 计算累计作业数量 - var totalJobCount = await query.CountAsync(); + // 帮助方法:为每个统计项单独构建基础选择器(避免条件累积) + ISelect BuildSelector() + { + var sel = freeSql.Select(); + if (!string.IsNullOrWhiteSpace(request.DeviceCode)) + sel = sel.Where(x => x.DeviceCode == request.DeviceCode); + return sel; + } + + // 计算累计作业数量(记录数即作业数) + var totalJobCount = await BuildSelector().CountAsync(); // 计算本年度作业数 - var yearJobCount = await query + var yearJobCount = await BuildSelector() .Where(x => x.CreateTime >= firstDayOfYear) .CountAsync(); // 计算本月作业数 - var monthJobCount = await query + var monthJobCount = await BuildSelector() .Where(x => x.CreateTime >= firstDayOfMonth) .CountAsync(); // 计算今日作业数 - var todayJobCount = await query + var todayJobCount = await BuildSelector() .Where(x => x.CreateTime >= today) .CountAsync(); - // 计算累计作业时长 - // 注意:这里假设ClearData表中有一个字段表示清洗时长,可能需要根据实际情况调整 - var totalJobHours = await query - .SumAsync(x => Convert.ToDecimal(x.RunTime)) / 60; // 假设时长单位是秒,转换为小时 + // 计算累计作业时长(来自 ClearData.Test_FrameworkPerModelCleaningDuration,单位:分钟) + var totalJobHours = SumMinutesToHours( + await BuildSelector().ToListAsync(x => x.Test_FrameworkPerModelCleaningDuration) + ); // 计算本年作业时长 - var yearJobHours = await query - .Where(x => x.CreateTime >= firstDayOfYear) - .SumAsync(x => Convert.ToDecimal(x.RunTime)) / 60; + var yearJobHours = SumMinutesToHours( + await BuildSelector().Where(x => x.CreateTime >= firstDayOfYear) + .ToListAsync(x => x.Test_FrameworkPerModelCleaningDuration) + ); // 计算本月作业时长 - var monthJobHours = await query - .Where(x => x.CreateTime >= firstDayOfMonth) - .SumAsync(x => Convert.ToDecimal(x.RunTime)) / 60; + var monthJobHours = SumMinutesToHours( + await BuildSelector().Where(x => x.CreateTime >= firstDayOfMonth) + .ToListAsync(x => x.Test_FrameworkPerModelCleaningDuration) + ); // 计算今日作业时长 - var todayJobHours = await query - .Where(x => x.CreateTime >= today) - .SumAsync(x => Convert.ToDecimal(x.RunTime)) / 60; + var todayJobHours = SumMinutesToHours( + await BuildSelector().Where(x => x.CreateTime >= today) + .ToListAsync(x => x.Test_FrameworkPerModelCleaningDuration) + ); // 返回结果 return new ClearStaticResponse @@ -84,10 +96,6 @@ namespace MoviconWebApi.API.ClearStaticApi YearJobHours = Math.Round(yearJobHours, 2), MonthJobHours = Math.Round(monthJobHours, 2), TodayJobHours = Math.Round(todayJobHours, 2), - CurrentVehicleModel = CurRunClearData != null ? CurRunClearData.vehicle_model : "", - CurrentLocomotiveNumber = CurRunClearData != null ? CurRunClearData.locomotive_number : "", - CurrentRepairProcess = CurRunClearData != null ? CurRunClearData.repair_process : "", - CurrentWheelNumber = "", // 假设part_num字段存储车轮编号 UpdateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; diff --git a/MoviconWebApi/API/ClearStaticApi/Models.cs b/MoviconWebApi/API/ClearStaticApi/Models.cs index f94332d..04717b1 100644 --- a/MoviconWebApi/API/ClearStaticApi/Models.cs +++ b/MoviconWebApi/API/ClearStaticApi/Models.cs @@ -56,25 +56,25 @@ /// public decimal TodayJobHours { get; set; } - /// - /// 当前机型 - /// - public string? CurrentVehicleModel { get; set; } + ///// + ///// 当前机型 + ///// + //public string? CurrentVehicleModel { get; set; } - /// - /// 当前车号 - /// - public string? CurrentLocomotiveNumber { get; set; } + ///// + ///// 当前车号 + ///// + //public string? CurrentLocomotiveNumber { get; set; } - /// - /// 当前修程 - /// - public string? CurrentRepairProcess { get; set; } + ///// + ///// 当前修程 + ///// + //public string? CurrentRepairProcess { get; set; } - /// - /// 车轮编号 - /// - public string? CurrentWheelNumber { get; set; } + ///// + ///// 车轮编号 + ///// + //public string? CurrentWheelNumber { get; set; } /// /// 更新时间 diff --git a/MoviconWebApi/API/DeviceAlarmApi/Data.cs b/MoviconWebApi/API/DeviceAlarmApi/Data.cs index a63262e..d02416d 100644 --- a/MoviconWebApi/API/DeviceAlarmApi/Data.cs +++ b/MoviconWebApi/API/DeviceAlarmApi/Data.cs @@ -1,4 +1,4 @@ -using MoviconWebApi.Entities; +using MoviconWebApi.Entities; namespace MoviconWebApi.API.DeviceAlarmApi { @@ -7,7 +7,7 @@ namespace MoviconWebApi.API.DeviceAlarmApi /// /// 获取设备报警列表 /// - public static async Task> GetDeviceAlarmList( + public static async Task<(List Items, long Total)> GetDeviceAlarmList( IFreeSql freeSql, DeviceAlarmRequest request) { @@ -30,8 +30,17 @@ namespace MoviconWebApi.API.DeviceAlarmApi query = query.Where(a => a.EndTime <= endTime); } + // 统计总数 + var total = await query.CountAsync(); + + // 参数兜底与限制 + var pageNo = request.PageNo <= 0 ? 1 : request.PageNo; + var pageSize = request.PageSize <= 0 ? 100 : request.PageSize; + if (pageSize > 100) pageSize = 100; + var data = await query .OrderByDescending(a => a.StartTime) + .Page(pageNo, pageSize) .ToListAsync(a => new DeviceAlarmResponse { DeviceCode = a.DeviceCode, @@ -42,7 +51,7 @@ namespace MoviconWebApi.API.DeviceAlarmApi EndTime = a.EndTime.ToString("yyyy-MM-dd HH:mm:ss") }); - return data ?? new List(); + return (data ?? new List(), total); } catch (Exception ex) { diff --git a/MoviconWebApi/API/DeviceAlarmApi/Endpoint.cs b/MoviconWebApi/API/DeviceAlarmApi/Endpoint.cs index 007e955..122ac03 100644 --- a/MoviconWebApi/API/DeviceAlarmApi/Endpoint.cs +++ b/MoviconWebApi/API/DeviceAlarmApi/Endpoint.cs @@ -1,4 +1,4 @@ -using Azure; +using Azure; using FastEndpoints; using MoviconWebApi.Common; using MoviconWebApi.Entities; @@ -35,12 +35,33 @@ namespace MoviconWebApi.API.DeviceAlarmApi { try { - var data = await DeviceAlarmData.GetDeviceAlarmList(_freeSql, req); - Response = ApiResponse>.Success(data, "success"); + // 参数兜底 + if (req.PageNo <= 0) req.PageNo = 1; + if (req.PageSize <= 0) req.PageSize = 100; + if (req.PageSize > 100) req.PageSize = 100; + + var listResult = await DeviceAlarmData.GetDeviceAlarmList(_freeSql, req); + var items = listResult.Item1; + var total = listResult.Item2; + + var resp = ApiResponse>.Success( + items ?? new List(), + (items != null && items.Count > 0) ? "请求成功" : "暂无数据"); + + resp.pagination = new MoviconWebApi.Common.Pagination + { + total = total, + count = items?.Count ?? 0, + pageNo = req.PageNo, + totalPage = req.PageSize > 0 ? (int)Math.Ceiling((double)total / req.PageSize) : 0, + pageSize = req.PageSize + }; + + Response = resp; } catch (Exception ex) { - Response = ApiResponse>.Error("500", $"获取数据失败: {ex.Message}"); + Response = ApiResponse>.Error("500", $"获取数据失败: {ex.Message}", new List()); } } } @@ -73,7 +94,9 @@ namespace MoviconWebApi.API.DeviceAlarmApi { try { - var (items, total) = await DeviceAlarmData.GetDeviceAlarmPagedList(_freeSql, req); + var result = await DeviceAlarmData.GetDeviceAlarmPagedList(_freeSql, req); + var items = result.Items; + var total = result.Total; var pagedResponse = new DeviceAlarmPagedResponse { Items = items, diff --git a/MoviconWebApi/API/DeviceAlarmApi/Models.cs b/MoviconWebApi/API/DeviceAlarmApi/Models.cs index 725eb7d..7bed65e 100644 --- a/MoviconWebApi/API/DeviceAlarmApi/Models.cs +++ b/MoviconWebApi/API/DeviceAlarmApi/Models.cs @@ -1,4 +1,4 @@ -namespace MoviconWebApi.API.DeviceAlarmApi +namespace MoviconWebApi.API.DeviceAlarmApi { /// /// 设备报警查询请求 @@ -24,6 +24,16 @@ /// 设备状态(0表示返回所有状态记录) /// public int DeviceState { get; set; } = 0; + + /// + /// 当前页码(从1开始) + /// + public int PageNo { get; set; } = 1; + + /// + /// 分页大小 + /// + public int PageSize { get; set; } = 100; } /// diff --git a/MoviconWebApi/API/DeviceStateApi/Endpoint.cs b/MoviconWebApi/API/DeviceStateApi/Endpoint.cs index c446c42..bea1d3e 100644 --- a/MoviconWebApi/API/DeviceStateApi/Endpoint.cs +++ b/MoviconWebApi/API/DeviceStateApi/Endpoint.cs @@ -1,4 +1,4 @@ -using Azure; +using Azure; using FastEndpoints; using MoviconWebApi.Common; @@ -73,7 +73,9 @@ namespace MoviconWebApi.API.DeviceStateApi { try { - var (items, total) = await Data.GetDeviceStatePagedAsync(_db, req); + var result = await Data.GetDeviceStatePagedAsync(_db, req); + var items = result.Item1; + var total = result.Item2; var pagedResponse = new DeviceStatePagedResponse { Items = items, diff --git a/MoviconWebApi/Common/ApiResponse.cs b/MoviconWebApi/Common/ApiResponse.cs index dcb1b8f..295bad1 100644 --- a/MoviconWebApi/Common/ApiResponse.cs +++ b/MoviconWebApi/Common/ApiResponse.cs @@ -1,4 +1,4 @@ -namespace MoviconWebApi.Common +namespace MoviconWebApi.Common { /// /// 统一的API响应结构 @@ -20,6 +20,11 @@ /// public T? data { get; set; } + /// + /// 分页信息(可选,仅在列表接口分页时返回) + /// + public Pagination? pagination { get; set; } + /// /// 创建成功响应 /// diff --git a/MoviconWebApi/Common/Pagination.cs b/MoviconWebApi/Common/Pagination.cs new file mode 100644 index 0000000..15264dc --- /dev/null +++ b/MoviconWebApi/Common/Pagination.cs @@ -0,0 +1,33 @@ +namespace MoviconWebApi.Common +{ + /// + /// 分页信息 + /// + public class Pagination + { + /// + /// 总条数 + /// + public long total { get; set; } + + /// + /// 当前条数 + /// + public int count { get; set; } + + /// + /// 当前页数(从1开始) + /// + public int pageNo { get; set; } + + /// + /// 总页数 + /// + public int totalPage { get; set; } + + /// + /// 每页条数 + /// + public int pageSize { get; set; } + } +}