diff --git a/src/CncRepository/Impl/DailyProductionRepository.cs b/src/CncRepository/Impl/DailyProductionRepository.cs index 8b0be80..f019f6b 100644 --- a/src/CncRepository/Impl/DailyProductionRepository.cs +++ b/src/CncRepository/Impl/DailyProductionRepository.cs @@ -30,94 +30,48 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - // 混合查询:已汇总日期用daily_production,未汇总日期从segment实时计算 - string baseSql = @" - SELECT dp.id, dp.machine_id AS MachineId, m.name AS MachineName, dp.production_date AS ProductionDate, - dp.program_name AS ProgramName, dp.total_quantity AS TotalQuantity, dp.segment_count AS SegmentCount, - dp.total_run_time AS TotalRunTime, dp.total_cutting_time AS TotalCuttingTime, dp.total_cycle_time AS TotalCycleTime - FROM cnc_daily_production dp - LEFT JOIN cnc_machine m ON dp.machine_id = m.id - WHERE 1=1"; - string realtimeSql = @" - SELECT 0 AS Id, seg.machine_id AS MachineId, m.name AS MachineName, seg.production_date AS ProductionDate, - seg.program_name AS ProgramName, - SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity - ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) AS TotalQuantity, - COUNT(*) AS SegmentCount, - cr_runtime.run_hours AS TotalRunTime, - cr_runtime.cut_hours AS TotalCuttingTime, - NULL AS TotalCycleTime - FROM cnc_production_segment seg - LEFT JOIN cnc_machine m ON seg.machine_id = m.id - LEFT JOIN ( - SELECT cr.machine_id, DATE(cr.collect_time) AS d, - COALESCE(ROUND(SUM(max_min.delta)/3600,1), 0) AS run_hours, - COALESCE(ROUND(SUM(max_min.delta)/3600,1), 0) AS cut_hours - FROM cnc_collect_record cr - JOIN ( - SELECT machine_id, DATE(collect_time) AS dd, MAX(cutting_time)-MIN(cutting_time) AS delta - FROM cnc_collect_record GROUP BY machine_id, DATE(collect_time) - ) max_min ON cr.machine_id = max_min.machine_id AND DATE(cr.collect_time) = max_min.dd - GROUP BY cr.machine_id, DATE(cr.collect_time) - ) cr_runtime ON cr_runtime.machine_id = seg.machine_id AND cr_runtime.d = seg.production_date - WHERE NOT EXISTS ( - SELECT 1 FROM cnc_daily_production dp - WHERE dp.machine_id = seg.machine_id AND dp.production_date = seg.production_date - )"; - var parameters = new DynamicParameters(); - // 日期过滤 - if (query?.StartDate.HasValue == true) - { - baseSql += " AND dp.production_date >= @StartDate"; - realtimeSql += " AND seg.production_date >= @StartDate"; - parameters.Add("StartDate", query.StartDate); - } - if (query?.EndDate.HasValue == true) - { - baseSql += " AND dp.production_date <= @EndDate"; - realtimeSql += " AND seg.production_date <= @EndDate"; - parameters.Add("EndDate", query.EndDate); - } - // 兼容旧的单日期查询 - if (query?.Date.HasValue == true && query.StartDate == null) - { - baseSql += " AND dp.production_date = @Date"; - realtimeSql += " AND seg.production_date = @Date"; - parameters.Add("Date", query.Date); - } - // 车间过滤 + string baseSql = @"SELECT dp.machine_id AS MachineId, m.name AS MachineName, + dp.program_name AS ProgramName, dp.production_date AS ProductionDate, + CAST(dp.total_quantity AS SIGNED) AS Quantity, + dp.segment_count AS SegmentCount, + dp.total_run_time AS TotalRunTime, dp.total_cutting_time AS TotalCuttingTime + FROM cnc_daily_production dp + JOIN cnc_machine m ON dp.machine_id = m.id + WHERE dp.total_quantity > 0"; + string realtimeSql = @"SELECT seg.machine_id AS MachineId, m.name AS MachineName, + seg.program_name AS ProgramName, seg.production_date AS ProductionDate, + CAST(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity + ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) AS SIGNED) AS Quantity, + COUNT(*) AS SegmentCount, 0 AS TotalRunTime, 0 AS TotalCuttingTime + FROM cnc_production_segment seg + JOIN cnc_machine m ON seg.machine_id = m.id + WHERE 1=1"; if (query?.WorkshopId.HasValue == true) { baseSql += " AND m.workshop_id = @WorkshopId"; realtimeSql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", query.WorkshopId); } - // 机床过滤 if (query?.MachineId.HasValue == true) { baseSql += " AND dp.machine_id = @MachineId"; realtimeSql += " AND seg.machine_id = @MachineId"; parameters.Add("MachineId", query.MachineId); } - // 工人过滤(通过worker_machine关联表) if (query?.WorkerId.HasValue == true) { baseSql += " AND EXISTS (SELECT 1 FROM cnc_worker_machine wm WHERE wm.machine_id = dp.machine_id AND wm.worker_id = @WorkerId)"; realtimeSql += " AND EXISTS (SELECT 1 FROM cnc_worker_machine wm WHERE wm.machine_id = seg.machine_id AND wm.worker_id = @WorkerId)"; parameters.Add("WorkerId", query.WorkerId); } - realtimeSql += " GROUP BY seg.machine_id, seg.production_date, seg.program_name, m.name"; - string unionSql = $"{baseSql} UNION ALL {realtimeSql}"; string countSql = $"SELECT COUNT(*) FROM ({unionSql}) AS t"; - int offset = (query.Page - 1) * query.PageSize; string paging = $" ORDER BY ProductionDate DESC, MachineName LIMIT @Limit OFFSET @Offset"; parameters.Add("Limit", query.PageSize); parameters.Add("Offset", offset); - var items = conn.Query(unionSql + paging, parameters).ToList(); int total = conn.ExecuteScalar(countSql, parameters); return new PagedResult @@ -143,7 +97,10 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - string sql = @"SELECT dp.* FROM cnc_daily_production dp LEFT JOIN cnc_machine m ON dp.machine_id = m.id WHERE dp.production_date BETWEEN @Start AND @End ORDER BY dp.production_date DESC"; + string sql = @"SELECT dp.* FROM cnc_daily_production dp + LEFT JOIN cnc_machine m ON dp.machine_id = m.id + WHERE dp.production_date BETWEEN @Start AND @End + ORDER BY dp.production_date DESC"; return conn.Query(sql, new { Start = startDate, End = endDate }).ToList(); } } @@ -152,7 +109,9 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - string sql = @"SELECT SUM(dp.total_quantity) FROM cnc_daily_production dp LEFT JOIN cnc_machine m ON dp.machine_id = m.id WHERE dp.production_date BETWEEN @Start AND @End"; + string sql = @"SELECT SUM(dp.total_quantity) FROM cnc_daily_production dp + LEFT JOIN cnc_machine m ON dp.machine_id = m.id + WHERE dp.production_date BETWEEN @Start AND @End"; if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; @@ -166,7 +125,8 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - string sql = @"SELECT SUM(total_quantity) FROM cnc_daily_production WHERE production_date BETWEEN @Start AND @End"; + string sql = @"SELECT SUM(total_quantity) FROM cnc_daily_production + WHERE production_date BETWEEN @Start AND @End"; var res = conn.ExecuteScalar(sql, new { Start = startDate, End = endDate }); return res ?? 0m; } @@ -176,12 +136,15 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - string sql = @"SELECT m.id AS Id, m.id AS MachineId, m.name AS MachineName, SUM(dp.total_quantity) AS TotalQuantity, NULL AS ProgramName, NULL AS ProductionDate, NULL AS SegmentCount, NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime - FROM cnc_daily_production dp - JOIN cnc_machine m ON dp.machine_id = m.id - WHERE dp.production_date BETWEEN @Start AND @End - GROUP BY m.id, m.name - ORDER BY SUM(dp.total_quantity) DESC LIMIT @Top"; + string sql = @"SELECT m.id AS Id, m.id AS MachineId, m.name AS MachineName, + SUM(dp.total_quantity) AS TotalQuantity, NULL AS ProgramName, + NULL AS ProductionDate, NULL AS SegmentCount, + NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime + FROM cnc_daily_production dp + JOIN cnc_machine m ON dp.machine_id = m.id + WHERE dp.production_date BETWEEN @Start AND @End + GROUP BY m.id, m.name + ORDER BY SUM(dp.total_quantity) DESC LIMIT @Top"; return conn.Query(sql, new { Start = startDate, End = endDate, Top = top }).ToList(); } } @@ -190,20 +153,20 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - string sql = @"SELECT 0 AS Id, NULL AS MachineId, NULL AS MachineName, SUM(total_quantity) AS TotalQuantity, NULL AS ProductionDate, NULL AS ProgramName, NULL AS SegmentCount, NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime - FROM cnc_daily_production - WHERE production_date BETWEEN @Start AND @End - GROUP BY machine_id - ORDER BY SUM(total_quantity) DESC LIMIT @Top"; + string sql = @"SELECT 0 AS Id, NULL AS MachineId, NULL AS MachineName, + SUM(total_quantity) AS TotalQuantity, NULL AS ProductionDate, + NULL AS ProgramName, NULL AS SegmentCount, + NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime + FROM cnc_daily_production + WHERE production_date BETWEEN @Start AND @End + GROUP BY machine_id + ORDER BY SUM(total_quantity) DESC LIMIT @Top"; return conn.Query(sql, new { Start = startDate, End = endDate, Top = top }).ToList(); } } #region 三维度产量报表 - /// - /// 机床维度统计卡片(从cnc_production_segment实时计算) - /// public MachineProductionSummaryResponse GetMachineSummary(DateTime startDate, DateTime endDate, int? workshopId) { using (var conn = CreateConnection()) @@ -214,48 +177,29 @@ namespace CncRepository.Impl FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; - var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); - if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", workshopId.Value); } - var result = conn.QuerySingleOrDefault(sql, parameters); - if (result == null) - { - return new MachineProductionSummaryResponse(); - } - - // 计算平均单机产量 + if (result == null) return new MachineProductionSummaryResponse(); if (result.RunningMachineCount > 0) - { result.AvgPerMachine = Math.Round((decimal)result.TotalQuantity / result.RunningMachineCount, 1); - } - - // 查询最高单产机床名称 string topSql = @"SELECT m.name FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; - if (workshopId.HasValue) - { - topSql += " AND m.workshop_id = @WorkshopId"; - } - topSql += @" GROUP BY seg.machine_id - ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; + if (workshopId.HasValue) topSql += " AND m.workshop_id = @WorkshopId"; + topSql += @" GROUP BY seg.machine_id ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity + ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; result.TopMachineName = conn.ExecuteScalar(topSql, parameters) ?? ""; - return result; } } - /// - /// 机床维度明细列表(按机床+程序聚合,产量降序) - /// public List GetMachineList(DateTime startDate, DateTime endDate, int? workshopId, int? machineId) { using (var conn = CreateConnection()) @@ -268,49 +212,27 @@ namespace CncRepository.Impl LEFT JOIN cnc_machine m ON seg.machine_id = m.id LEFT JOIN ( SELECT cr.machine_id, DATE(cr.collect_time) AS d, - COALESCE(ROUND(SUM(max_min.delta)/3600,1), 0) AS run_hours + COALESCE(ROUND(SUM(max_min.delta)/3600,1), 0) AS run_hours FROM cnc_collect_record cr - JOIN ( - SELECT machine_id, DATE(collect_time) AS dd, MAX(cutting_time)-MIN(cutting_time) AS delta - FROM cnc_collect_record GROUP BY machine_id, DATE(collect_time) - ) max_min ON cr.machine_id = max_min.machine_id AND DATE(cr.collect_time) = max_min.dd + JOIN (SELECT machine_id, DATE(collect_time) AS dd, + MAX(cutting_time)-MIN(cutting_time) AS delta + FROM cnc_collect_record GROUP BY machine_id, DATE(collect_time)) max_min + ON cr.machine_id = max_min.machine_id AND DATE(cr.collect_time) = max_min.dd GROUP BY cr.machine_id, DATE(cr.collect_time) ) cr_runtime ON cr_runtime.machine_id = seg.machine_id AND cr_runtime.d = seg.production_date WHERE seg.production_date BETWEEN @Start AND @End"; - var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); - - if (workshopId.HasValue) - { - sql += " AND m.workshop_id = @WorkshopId"; - parameters.Add("WorkshopId", workshopId.Value); - } - if (machineId.HasValue) - { - sql += " AND seg.machine_id = @MachineId"; - parameters.Add("MachineId", machineId.Value); - } - + if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", workshopId.Value); } + if (machineId.HasValue) { sql += " AND seg.machine_id = @MachineId"; parameters.Add("MachineId", machineId.Value); } sql += " GROUP BY seg.machine_id, seg.program_name, m.name, cr_runtime.run_hours ORDER BY TotalQuantity DESC"; - var items = conn.Query(sql, parameters).ToList(); - - // 计算排行和日夜班标识 - for (int i = 0; i < items.Count; i++) - { - items[i].Rank = i + 1; - items[i].DayStatus = items[i].DayStatus ?? ""; - } - + for (int i = 0; i < items.Count; i++) { items[i].Rank = i + 1; items[i].DayStatus = items[i].DayStatus ?? ""; } return items; } } - /// - /// 员工维度统计卡片(通过cnc_worker_machine关联产量分段表) - /// public WorkerProductionSummaryResponse GetWorkerSummary(DateTime startDate, DateTime endDate) { using (var conn = CreateConnection()) @@ -322,35 +244,21 @@ namespace CncRepository.Impl JOIN cnc_worker_machine wm ON seg.machine_id = wm.machine_id JOIN cnc_worker w ON wm.worker_id = w.id WHERE seg.production_date BETWEEN @Start AND @End"; - var result = conn.QuerySingleOrDefault(sql, new { Start = startDate, End = endDate }); - if (result == null) - { - return new WorkerProductionSummaryResponse(); - } - - // 计算人均产量 + if (result == null) return new WorkerProductionSummaryResponse(); if (result.ActiveWorkerCount > 0) - { result.AvgPerWorker = Math.Round((decimal)result.TotalQuantity / result.ActiveWorkerCount, 1); - } - - // 查询最高产量员工名称 string topSql = @"SELECT w.name FROM cnc_production_segment seg JOIN cnc_worker_machine wm ON seg.machine_id = wm.machine_id JOIN cnc_worker w ON wm.worker_id = w.id WHERE seg.production_date BETWEEN @Start AND @End - GROUP BY w.id, w.name - ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; + GROUP BY w.id, w.name ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity + ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; result.TopWorkerName = conn.ExecuteScalar(topSql, new { Start = startDate, End = endDate }) ?? ""; - return result; } } - /// - /// 员工维度明细列表(通过cnc_worker_machine关联,产量降序) - /// public List GetWorkerList(DateTime startDate, DateTime endDate, int? workerId) { using (var conn = CreateConnection()) @@ -364,41 +272,25 @@ namespace CncRepository.Impl JOIN cnc_worker_machine wm ON wm.worker_id = w.id LEFT JOIN cnc_production_segment seg ON seg.machine_id = wm.machine_id AND seg.production_date BETWEEN @Start AND @End"; - var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); - - if (workerId.HasValue) - { - sql += " AND w.id = @WorkerId"; - parameters.Add("WorkerId", workerId.Value); - } - + if (workerId.HasValue) { sql += " AND w.id = @WorkerId"; parameters.Add("WorkerId", workerId.Value); } sql += " GROUP BY w.id, w.name ORDER BY TotalQuantity DESC"; - var items = conn.Query(sql, parameters).ToList(); - if (items.Count == 0) return items; - - // 计算总量用于百分比 - int grandTotal = items.Sum(x => x.TotalQuantity); - - for (int i = 0; i < items.Count; i++) + if (items.Count > 0) { - items[i].Rank = i + 1; - if (grandTotal > 0) + int grandTotal = items.Sum(x => x.TotalQuantity); + for (int i = 0; i < items.Count; i++) { - items[i].Percentage = Math.Round((decimal)items[i].TotalQuantity / grandTotal * 100, 1); + items[i].Rank = i + 1; + if (grandTotal > 0) items[i].Percentage = Math.Round((decimal)items[i].TotalQuantity / grandTotal * 100, 1); } } - return items; } } - /// - /// 程序维度统计卡片(按program_name聚合) - /// public ProgramProductionSummaryResponse GetProgramSummary(DateTime startDate, DateTime endDate, int? workshopId) { using (var conn = CreateConnection()) @@ -409,48 +301,25 @@ namespace CncRepository.Impl FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; - var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); - - if (workshopId.HasValue) - { - sql += " AND m.workshop_id = @WorkshopId"; - parameters.Add("WorkshopId", workshopId.Value); - } - + if (workshopId.HasValue) { sql += " AND m.workshop_id = @WorkshopId"; parameters.Add("WorkshopId", workshopId.Value); } var result = conn.QuerySingleOrDefault(sql, parameters); - if (result == null) - { - return new ProgramProductionSummaryResponse(); - } - - // 计算平均单程序产量 + if (result == null) return new ProgramProductionSummaryResponse(); if (result.RunningProgramCount > 0) - { result.AvgPerProgram = Math.Round((decimal)result.TotalQuantity / result.RunningProgramCount, 1); - } - - // 查询最高产量程序名称 string topSql = @"SELECT seg.program_name FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; - if (workshopId.HasValue) - { - topSql += " AND m.workshop_id = @WorkshopId"; - } - topSql += @" GROUP BY seg.program_name - ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; + if (workshopId.HasValue) topSql += " AND m.workshop_id = @WorkshopId"; + topSql += @" GROUP BY seg.program_name ORDER BY SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity + ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) DESC LIMIT 1"; result.TopProgramName = conn.ExecuteScalar(topSql, parameters) ?? ""; - return result; } } - /// - /// 程序维度明细列表(按program_name聚合,产量降序) - /// public List GetProgramList(DateTime startDate, DateTime endDate, string programName) { using (var conn = CreateConnection()) @@ -462,38 +331,22 @@ namespace CncRepository.Impl FROM cnc_production_segment seg LEFT JOIN cnc_machine m ON seg.machine_id = m.id WHERE seg.production_date BETWEEN @Start AND @End"; - var parameters = new DynamicParameters(); parameters.Add("Start", startDate); parameters.Add("End", endDate); - - if (!string.IsNullOrWhiteSpace(programName)) - { - sql += " AND seg.program_name = @ProgramName"; - parameters.Add("ProgramName", programName); - } - + if (!string.IsNullOrWhiteSpace(programName)) { sql += " AND seg.program_name = @ProgramName"; parameters.Add("ProgramName", programName); } sql += " GROUP BY seg.program_name ORDER BY TotalQuantity DESC"; - var items = conn.Query(sql, parameters).ToList(); - if (items.Count == 0) return items; - - // 计算总量用于百分比 - int grandTotal = items.Sum(x => x.TotalQuantity); - - for (int i = 0; i < items.Count; i++) + if (items.Count > 0) { - items[i].Rank = i + 1; - if (items[i].MachineCount > 0) + int grandTotal = items.Sum(x => x.TotalQuantity); + for (int i = 0; i < items.Count; i++) { - items[i].AvgPerMachine = Math.Round((decimal)items[i].TotalQuantity / items[i].MachineCount, 1); - } - if (grandTotal > 0) - { - items[i].Percentage = Math.Round((decimal)items[i].TotalQuantity / grandTotal * 100, 1); + items[i].Rank = i + 1; + if (items[i].MachineCount > 0) items[i].AvgPerMachine = Math.Round((decimal)items[i].TotalQuantity / items[i].MachineCount, 1); + if (grandTotal > 0) items[i].Percentage = Math.Round((decimal)items[i].TotalQuantity / grandTotal * 100, 1); } } - return items; } } diff --git a/src/CncRepository/Impl/MachineLatestTagRepository.cs b/src/CncRepository/Impl/MachineLatestTagRepository.cs new file mode 100644 index 0000000..a6131de --- /dev/null +++ b/src/CncRepository/Impl/MachineLatestTagRepository.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dapper; +using MySqlConnector; +using Newtonsoft.Json.Linq; +using CncModels.Dto.Machine; +using CncRepository.Base; +using CncRepository.Interface; + +namespace CncRepository.Impl +{ + /// + /// 设备最新Tag数据仓储(查询日志库 raw_json,按 Tag ID 提取指标) + /// + public class MachineLatestTagRepository : LogRepository, IMachineLatestTagRepository + { + private readonly string _businessConn; + + /// + /// 初始化,同时持有日志库和业务库连接字符串 + /// + /// cnc_log 连接字符串 + /// cnc_business 连接字符串 + public MachineLatestTagRepository(string logConn, string businessConn) : base(logConn) + { + _businessConn = businessConn; + } + + /// + /// 获取指定设备的最新6个Tag及其采集时间 + /// + /// 设备ID + /// 6个Tag数据列表(找不到时返回空列表) + public List GetLatestTags(int machineId) + { + // 1. 从业务库获取设备的 device_code + string deviceCode; + using (var bconn = new MySqlConnection(_businessConn)) + { + deviceCode = bconn.ExecuteScalar( + "SELECT device_code FROM cnc_machine WHERE id = @Id", + new { Id = machineId }); + } + if (string.IsNullOrEmpty(deviceCode)) + return new List(); + + // 2. 从日志库获取最新一条成功的 raw_json + string rawJson; + using (var conn = CreateConnection()) + { + rawJson = conn.ExecuteScalar( + "SELECT raw_json FROM log_collect_raw WHERE is_success = 1 ORDER BY request_time DESC LIMIT 1"); + } + if (string.IsNullOrEmpty(rawJson)) + return new List(); + + // 3. 解析 JSON,提取6个目标 Tag + var targetTags = new[] { "_io_status", "Tag5", "Tag8", "Tag1", "Tag9", "Tag26" }; + var result = new List(); + + try + { + var devices = JArray.Parse(rawJson); + foreach (JObject d in devices.OfType()) + { + string dev = d?.Value("device") ?? ""; + // 模糊匹配:raw_json 中的 device 可能是 device_code 的一部分(分隔符可能不同) + if (!deviceCode.Contains(dev) && !dev.Contains(deviceCode.Replace("_", "-"))) + continue; + + var tags = d?.Value("tags"); + if (tags == null) + continue; + + foreach (JObject t in tags.OfType()) + { + string tagId = t?.Value("id") ?? ""; + if (!targetTags.Contains(tagId)) + continue; + + string timeStr = t?.Value("time") ?? ""; + DateTime? collectTime = null; + if (DateTime.TryParse(timeStr, out var ct)) + collectTime = ct; + + result.Add(new MachineLatestTagItem + { + Id = tagId, + Desc = t?.Value("desc") ?? "", + Value = t?.Value("value") ?? "", + CollectTime = collectTime + }); + } + break; // 找到匹配设备后退出 + } + } + catch + { + // JSON 解析失败返回空列表 + } + + return result; + } + } +} diff --git a/src/CncRepository/Interface/IMachineLatestTagRepository.cs b/src/CncRepository/Interface/IMachineLatestTagRepository.cs new file mode 100644 index 0000000..0fbfbc0 --- /dev/null +++ b/src/CncRepository/Interface/IMachineLatestTagRepository.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using CncModels.Dto.Machine; + +namespace CncRepository.Interface +{ + /// + /// 设备最新Tag数据仓储接口(查询日志库) + /// + public interface IMachineLatestTagRepository + { + /// + /// 获取指定设备的最新6个Tag及其采集时间 + /// + /// 设备ID + /// 6个Tag数据列表 + List GetLatestTags(int machineId); + } +} diff --git a/src/CncService/Impl/MachineService.cs b/src/CncService/Impl/MachineService.cs index 2700db0..7124273 100644 --- a/src/CncService/Impl/MachineService.cs +++ b/src/CncService/Impl/MachineService.cs @@ -18,17 +18,23 @@ namespace CncService.Impl private readonly ICollectAddressRepository _addressRepository; private readonly IWorkerMachineRepository _workerMachineRepository; private readonly IBrandRepository _brandRepository; + private readonly IMachineLatestTagRepository _latestTagRepository; + private readonly ICollectAnalysisRepository _collectAnalysisRepository; public MachineService( IMachineRepository machineRepository, ICollectAddressRepository addressRepository, IWorkerMachineRepository workerMachineRepository, - IBrandRepository brandRepository) + IBrandRepository brandRepository, + IMachineLatestTagRepository latestTagRepository, + ICollectAnalysisRepository collectAnalysisRepository) { _machineRepository = machineRepository ?? throw new ArgumentNullException(nameof(machineRepository)); _addressRepository = addressRepository ?? throw new ArgumentNullException(nameof(addressRepository)); _workerMachineRepository = workerMachineRepository ?? throw new ArgumentNullException(nameof(workerMachineRepository)); _brandRepository = brandRepository ?? throw new ArgumentNullException(nameof(brandRepository)); + _latestTagRepository = latestTagRepository ?? throw new ArgumentNullException(nameof(latestTagRepository)); + _collectAnalysisRepository = collectAnalysisRepository ?? throw new ArgumentNullException(nameof(collectAnalysisRepository)); } /// @@ -157,12 +163,19 @@ namespace CncService.Impl } /// - public List GetCollectRecords(int id) + public List GetCollectRecords(int id, DateTime? date = null) { if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的机床ID"); var machine = _machineRepository.GetById(id); if (machine == null) throw new BusinessException(ErrorCode.NotFound, "机床未找到"); - return _machineRepository.GetRecentCollectRecords(id); + var queryDate = date ?? DateTime.Today; + return _collectAnalysisRepository.GetRecordsByMachineAndDate(id, queryDate); + } + + /// + public List GetLatestTags(int machineId) + { + return _latestTagRepository.GetLatestTags(machineId); } } } diff --git a/src/CncService/Interface/IMachineService.cs b/src/CncService/Interface/IMachineService.cs index 407b085..7314b66 100644 --- a/src/CncService/Interface/IMachineService.cs +++ b/src/CncService/Interface/IMachineService.cs @@ -82,10 +82,18 @@ namespace CncService.Interface List GetProductionTrend(int id); /// - /// 获取机床近期采集记录 + /// 获取机床采集记录(从日志库log_collect_analysis查询,支持日期筛选) /// /// 机床ID + /// 筛选日期,默认今天 /// 采集记录列表 - List GetCollectRecords(int id); + List GetCollectRecords(int id, DateTime? date = null); + + /// + /// 获取设备最新Tag数据(6个指标各带独立采集时间) + /// + /// 设备ID + /// 6个Tag数据列表 + List GetLatestTags(int machineId); } } diff --git a/src/CncWebApi/Controllers/MachineController.cs b/src/CncWebApi/Controllers/MachineController.cs index a4e24c8..4d957af 100644 --- a/src/CncWebApi/Controllers/MachineController.cs +++ b/src/CncWebApi/Controllers/MachineController.cs @@ -1,3 +1,4 @@ +using System; using System.Web.Http; using CncModels.Dto; using CncModels.Dto.Machine; @@ -155,5 +156,17 @@ namespace CncWebApi.Controllers var result = _machineService.GetCollectRecords(id); return Ok(ApiResponse.Success(new { items = result })); } + + /// + /// 获取设备最新Tag数据(6个指标各带独立采集时间) + /// GET /api/admin/machine/{id}/latest-tags + /// + [HttpGet] + [Route("{id:int}/latest-tags")] + public IHttpActionResult GetLatestTags(int id) + { + var result = _machineService.GetLatestTags(id); + return Ok(ApiResponse.Success(new { items = result })); + } } } diff --git a/src/CncWebApi/Infrastructure/ServiceResolver.cs b/src/CncWebApi/Infrastructure/ServiceResolver.cs index 89b0c3f..71a67da 100644 --- a/src/CncWebApi/Infrastructure/ServiceResolver.cs +++ b/src/CncWebApi/Infrastructure/ServiceResolver.cs @@ -127,7 +127,9 @@ namespace CncWebApi.Infrastructure new CncRepository.Impl.MachineRepository(_businessConn), new CncRepository.Impl.CollectAddressRepository(_businessConn), new CncRepository.Impl.WorkerMachineRepository(_businessConn), - new CncRepository.Impl.BrandRepository(_businessConn)); + new CncRepository.Impl.BrandRepository(_businessConn), + new CncRepository.Impl.MachineLatestTagRepository(_logConn, _businessConn), + new CncRepository.Impl.Log.CollectAnalysisRepository(_logConn)); } private IBrandService ResolveBrandService()