diff --git a/frontend/src/views/production/ProductionPage.vue b/frontend/src/views/production/ProductionPage.vue index df5f452..58d8db9 100644 --- a/frontend/src/views/production/ProductionPage.vue +++ b/frontend/src/views/production/ProductionPage.vue @@ -141,8 +141,8 @@ async function loadData() { const params = { page: page.page, pageSize: page.pageSize, - dateFrom: filters.dateRange?.[0] ?? '', - dateTo: filters.dateRange?.[1] ?? '', + startDate: filters.dateRange?.[0] ?? '', + endDate: filters.dateRange?.[1] ?? '', workshopId: filters.workshopId ?? '', machineId: filters.machineId ?? '', workerId: filters.workerId ?? '', diff --git a/src/CncModels/Dto/Production/ProductionQuery.cs b/src/CncModels/Dto/Production/ProductionQuery.cs index 6cc67fa..aa54e6a 100644 --- a/src/CncModels/Dto/Production/ProductionQuery.cs +++ b/src/CncModels/Dto/Production/ProductionQuery.cs @@ -8,9 +8,12 @@ namespace CncModels.Dto.Production public class ProductionQuery : PagedQuery { public System.DateTime? Date { get; set; } + public System.DateTime? StartDate { get; set; } + public System.DateTime? EndDate { get; set; } public int? WorkshopId { get; set; } public int? MachineId { get; set; } public int? WorkerId { get; set; } public string DataStatus { get; set; } + public string ProgramName { get; set; } } } diff --git a/src/CncRepository/Impl/DailyProductionRepository.cs b/src/CncRepository/Impl/DailyProductionRepository.cs index 4508546..dc05a4d 100644 --- a/src/CncRepository/Impl/DailyProductionRepository.cs +++ b/src/CncRepository/Impl/DailyProductionRepository.cs @@ -30,25 +30,74 @@ namespace CncRepository.Impl { using (var conn = CreateConnection()) { - string baseSql = @"SELECT dp.id, dp.machine_id, m.name AS MachineName, dp.production_date, dp.program_name, dp.total_quantity, dp.segment_count, dp.total_run_time, dp.total_cutting_time, dp.total_cycle_time - FROM cnc_daily_production dp - LEFT JOIN cnc_machine m ON dp.machine_id = m.id - WHERE 1=1"; - string countSql = @"SELECT COUNT(*) FROM cnc_daily_production dp LEFT JOIN cnc_machine m ON dp.machine_id = m.id WHERE 1=1"; + // 混合查询:已汇总日期用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, NULL AS TotalRunTime, NULL AS TotalCuttingTime, NULL AS TotalCycleTime + FROM cnc_production_segment seg + LEFT JOIN cnc_machine m ON seg.machine_id = m.id + 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?.Date.HasValue == true) + // 日期过滤 + 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"; - countSql += " AND dp.production_date = @Date"; + realtimeSql += " AND seg.production_date = @Date"; parameters.Add("Date", query.Date); } + // 车间过滤 + 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); + } + + 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 dp.production_date DESC LIMIT @Limit OFFSET @Offset"; + string paging = $" ORDER BY ProductionDate DESC, MachineName LIMIT @Limit OFFSET @Offset"; parameters.Add("Limit", query.PageSize); parameters.Add("Offset", offset); - var items = conn.Query(baseSql + paging, parameters).ToList(); + var items = conn.Query(unionSql + paging, parameters).ToList(); int total = conn.ExecuteScalar(countSql, parameters); return new PagedResult { diff --git a/src/CncRepository/Impl/ProductionSegmentRepository.cs b/src/CncRepository/Impl/ProductionSegmentRepository.cs index 66b41aa..2478feb 100644 --- a/src/CncRepository/Impl/ProductionSegmentRepository.cs +++ b/src/CncRepository/Impl/ProductionSegmentRepository.cs @@ -70,5 +70,26 @@ namespace CncRepository.Impl return affected > 0; } } + + /// + /// 实时统计指定日期范围的产量(从分段表计算) + /// + public decimal GetTotalByDateRange(DateTime startDate, DateTime endDate, int? workshopId = null) + { + using (var conn = CreateConnection()) + { + string sql = @"SELECT COALESCE(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), 0) + 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) + { + sql += " AND m.workshop_id = @WorkshopId"; + return conn.ExecuteScalar(sql, new { Start = startDate, End = endDate, WorkshopId = workshopId.Value }); + } + return conn.ExecuteScalar(sql, new { Start = startDate, End = endDate }); + } + } } } diff --git a/src/CncRepository/Interface/IProductionSegmentRepository.cs b/src/CncRepository/Interface/IProductionSegmentRepository.cs index e497aae..bad1949 100644 --- a/src/CncRepository/Interface/IProductionSegmentRepository.cs +++ b/src/CncRepository/Interface/IProductionSegmentRepository.cs @@ -15,5 +15,6 @@ namespace CncRepository.Interface int Create(ProductionSegment entity); bool CloseSegment(long id, decimal? endPartCount, decimal? quantity, string closeReason, DateTime endTime); bool SettleByDate(DateTime date); + decimal GetTotalByDateRange(DateTime startDate, DateTime endDate, int? workshopId = null); } } diff --git a/src/CncService/Impl/ProductionService.cs b/src/CncService/Impl/ProductionService.cs index 1fa994d..7d36040 100644 --- a/src/CncService/Impl/ProductionService.cs +++ b/src/CncService/Impl/ProductionService.cs @@ -40,6 +40,11 @@ namespace CncService.Impl { var targetDate = date ?? DateTime.Today; var total = _dailyProductionRepository.GetTotalByDateRange(targetDate, targetDate, workshopId); + // 如果汇总表无数据,从产量分段实时计算 + if (total == 0) + { + total = _productionSegmentRepository.GetTotalByDateRange(targetDate, targetDate, workshopId); + } return new DailySummaryResponse { TotalQuantity = (int)total,