using System; using System.Collections.Generic; using System.Data; using Dapper; using MySql.Data.MySqlClient; using CncModels.Enum; using CncModels.Entity; using log4net; namespace CncCollector.Core { /// /// 零件产量分段跟踪引擎:维护内存中的活跃段状态,并定期写入数据库。 /// public class ProductionTracker { private readonly string _connectionString; private readonly object _lock = new object(); private static readonly ILog Log = LogManager.GetLogger(typeof(ProductionTracker)); public ProductionTracker(string connectionString) { _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString)); } /// /// 处理一个采集记录后的产量跟踪逻辑。 /// public void Track(int machineId, string programName, int partCount, DateTime collectTime) { lock (_lock) { using (var conn = new MySqlConnection(_connectionString)) { conn.Open(); // 查找当前未结算的活跃段 var active = conn.QueryFirstOrDefault( "SELECT * FROM cnc_production_segment WHERE machine_id=@MachineId AND is_settled=0 AND end_time IS NULL", new { MachineId = machineId }); if (active == null) { // 开新段 const string sqlStart = @"INSERT INTO cnc_production_segment (machine_id, program_name, production_date, start_time, start_part_count, is_settled) VALUES (@MachineId, @ProgramName, @ProductionDate, @StartTime, @StartPartCount, 0)"; conn.Execute(sqlStart, new { MachineId = machineId, ProgramName = programName, ProductionDate = collectTime.Date, StartTime = collectTime, StartPartCount = partCount }); } else { // 程序名变更则结账并开新段 if (!string.Equals(active.ProgramName, programName, StringComparison.OrdinalIgnoreCase)) { const string sqlClose = @"UPDATE cnc_production_segment SET end_time=@EndTime, end_part_count=@EndPartCount, is_settled=1, close_reason=@Reason WHERE id=@Id"; conn.Execute(sqlClose, new { EndTime = collectTime, EndPartCount = active.EndPartCount ?? active.StartPartCount, Id = active.Id, Reason = SegmentCloseReason.ProgramChange.ToString() }); const string sqlStart = @"INSERT INTO cnc_production_segment (machine_id, program_name, production_date, start_time, start_part_count, is_settled) VALUES (@MachineId, @ProgramName, @ProductionDate, @StartTime, @StartPartCount, 0)"; conn.Execute(sqlStart, new { MachineId = machineId, ProgramName = programName, ProductionDate = collectTime.Date, StartTime = collectTime, StartPartCount = partCount }); } else { // 更新当前段的结束时间与结束时的部件数 const string sqlUpdate = @"UPDATE cnc_production_segment SET end_time=@EndTime, end_part_count=@EndPartCount WHERE id=@Id"; conn.Execute(sqlUpdate, new { EndTime = collectTime, EndPartCount = partCount, Id = active.Id }); } } } } } } }