using LocalhostMES.Core; using LocalhostMES.DataBase; using LocalhostMES.Enums; using LocalhostMES.Helpers; using LocalhostMES.Models; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Web.Http; namespace LocalhostMES.Api.Controllers { [RoutePrefix("api/mes")] public class MesController : ApiController { private static int _snCounter = 1; private Management management; public MesController() { management = Management.GetManagement(); } #region 2.1 厂级MES下发工单信息 [HttpPost] [Route("receiveWorkOrder")] public IHttpActionResult ReceiveWorkOrder([FromBody] WorkOrderRequest request) { try { LogHelper.WriteLogInfo("厂级MES下发工单信息"); // 验证必填字段 if ( string.IsNullOrEmpty(request.WorkOrderNo) || string.IsNullOrEmpty(request.MaterialCode) || string.IsNullOrEmpty(request.MaterialName) || string.IsNullOrEmpty(request.LineCode) ) { LogHelper.WriteLogInfo("必填字段不能为空"); return BadRequest("必填字段不能为空"); } // 工单状态验证 if ( !IsValidStatus(request.Status) ) { LogHelper.WriteLogInfo("无效的工单状态"); return BadRequest($"无效的工单状态: {request.Status}"); } // 创建或更新工单信息 var workOrder = new WorkOrderInfo { WorkOrderNo = request.WorkOrderNo, MaterialCode = request.MaterialCode, OrderNo = request.OrderNo, MaterialName = request.MaterialName, PlannedQuantity = int.TryParse(request.WorkOrderNum, out var qty) ? qty : 0, CompletedQuantity = 0, Status = request.Status, LineCode = request.LineCode, CreateTime = DateTime.Now, StartTime = DateTime.Now.AddSeconds(2), EndTime = DateTime.Now.AddSeconds(5) }; if ( DatabaseHelper.InsertWorkOrderInfo(workOrder) ) { var response = new ApiResponse { code = "200", success = true, msg = "工单接收成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = true }; LogHelper.WriteLogInfo("工单接收成功"); return Ok(response); } else { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"工单接收失败:数据库插入异常", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; LogHelper.WriteLogInfo("数据库插入异常"); return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"工单接收失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } [HttpGet] [Route("getWorkOrders")] public IHttpActionResult GetWorkOrders() { try { LogHelper.WriteLogInfo("接口getWorkOrders收到消息"); var workOrders = DatabaseHelper.SelectWorkOrderInfo(null); var response = new ApiResponse> { code = "200", success = true, msg = "获取成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = workOrders }; return Ok(response); } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"获取工单失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } #endregion #region 2.2 SN打印请求 [HttpPost] [Route("requestSnPrint")] public async Task RequestSnPrint([FromBody] SnPrintRequest request) { try { // 验证请求头 if ( !ValidateHeaders() ) { return Unauthorized(); } // 验证必填字段 if ( string.IsNullOrEmpty(request.workOrderNo) || request.count <= 0 ) { return BadRequest("工单号和数量为必填项且数量必须大于0"); } var workOrder = DatabaseHelper.SelectWorkOrderInfo(request.workOrderNo); // 验证工单是否存在 if ( workOrder.Count == 0 ) { return BadRequest($"工单 {request.workOrderNo} 不存在"); } // 验证打印类型 if ( request.printType < 1 || request.printType > 4 ) { return BadRequest($"无效的打印类型: {request.printType}"); } LogHelper.WriteLogInfo("请求参数:"); LogHelper.WriteLogInfo(JsonConvert.SerializeObject(request, Formatting.Indented)); if ( workOrder[ 0 ].IsLocalhost ) { var Manualsninfo = DatabaseHelper.SelectSnInfo(request.workOrderNo); var WorkOrder= DatabaseHelper.SelectWorkOrderInfo(request.workOrderNo); DatabaseHelper.InsertSnInfo(new SnInfo() { Sn = WorkOrder[ 0 ].MaterialCode + "000001" + DateCodeConverter.GetYearCode(DateTime.Now.Year) + DateCodeConverter.GetMonthCode(DateTime.Now.Month) + DateCodeConverter.GetDayCode(DateTime.Now.Day) + "00000" + ( Manualsninfo.Count + 1 ), IsUsed = false, WorkOrderNo = request.workOrderNo, GenerateTime = DateTime.Now, PrintType = "1", }); } else { var hassninfo = DatabaseHelper.SelectSnInfo(request.workOrderNo, true, false); if ( hassninfo.Count == 0 ) { ApiResponse mesres = await management.ApiClient.RequestSnPrintAsync(request); if ( mesres.success && mesres.data != null && mesres.data.Sn.Count != 0 ) { for ( int i = 0; i < mesres.data.Sn.Count; i++ ) { if ( !DatabaseHelper.InsertSnInfo(new SnInfo() { WorkOrderNo = mesres.data.WorkOrderNo, Sn = mesres.data.Sn[ i ].Sn, GenerateTime = DateTime.Now, PrintType = "1", IsUsed = false, }) ) { mesres.msg = "插入SN到数据库出错"; mesres.success = false; return Content(System.Net.HttpStatusCode.InternalServerError, mesres); } } return Ok(mesres); } return Content(System.Net.HttpStatusCode.InternalServerError, mesres); } } var sninfo = DatabaseHelper.SelectSnInfo(request.workOrderNo, true, false); // 生成SN列表 var snList = new List(); if ( sninfo.Count != 0 ) { snList.Add(new SnItem { Sn = sninfo[ 0 ].Sn }); var responseData = new SnPrintResponseData { Sn = snList, OrderNo = request.orderNo ?? "", WorkOrderNo = request.workOrderNo, Line = request.line ?? "", VehicleCode = workOrder[0].MaterialCode, MaterialDesc = workOrder[0].MaterialName }; var response = new ApiResponse { code = "200", success = true, msg = "SN生成成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = responseData }; return Ok(response); } var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"SN获取失败", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"SN生成失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } [HttpGet] [Route("getSns/{workOrderNo}")] public IHttpActionResult GetSns(string workOrderNo) { try { var sninfo = DatabaseHelper.SelectSnInfo(workOrderNo, true, false); if ( sninfo.Count != 0 ) { var response = new ApiResponse> { code = "200", success = true, msg = "获取成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = sninfo }; return Ok(response); } var errorResponse = new ErrorResponse { code = "55001", success = false, msg = $"工单 {workOrderNo} 没有SN记录", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.NotFound, errorResponse); } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"获取SN失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } #endregion #region 2.3 接收SN和关键件 [HttpPost] [Route("receiveSnComponent")] public async Task ReceiveSnComponent([FromBody] SnKeyComponentRequest request) { try { LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件"); // 验证请求头 if ( !ValidateHeaders() ) { return Unauthorized(); } // 验证必填字段 if ( string.IsNullOrEmpty(request.plant) || string.IsNullOrEmpty(request.stationCode) || string.IsNullOrEmpty(request.positionCode) || // string.IsNullOrEmpty(request.sn) || //之前这里需要扫SN,客户新需求 不扫码。直接按顺序走 string.IsNullOrEmpty(request.scanTime) ) { return BadRequest("必填字段不能为空"); } var res = DatabaseHelper.SelectWorkOrderInfo(); string stationOrder = ""; string _materialCode=""; if ( request.stationCode.Split('-')[ 2 ] == "L" ) { stationOrder = res.LeftOrderNo; _materialCode = res.LeftCheckCode; } else { stationOrder = res.RightOrderNo; _materialCode = res.RightCheckCode; } var workOrder = DatabaseHelper.SelectWorkOrderInfo(stationOrder); // 验证工单是否存在 if ( workOrder.Count == 0 ) { return BadRequest($"工单 {res.LeftOrderNo} 不存在"); } if ( string.IsNullOrEmpty(request.sn) ) { List partInfos= DatabaseHelper.SelectPartInfo(_materialCode, request.stationCode); if ( partInfos.Count != 0 ) { SnInfo info= DatabaseHelper.SelectSnInfoForStation(stationOrder, partInfos[ 0 ].StationType); if ( info != null ) { request.sn = info.Sn; } } else { return BadRequest($"工站信息不存在"); } } if ( workOrder[ 0 ].IsLocalhost ) { return Ok(new ApiResponse() { data = true }); } // 处理关键件绑定 if ( request.part != null && request.part.Count > 0 ) { foreach ( var part in request.part ) { if ( string.IsNullOrEmpty(part.partNum) ) { return BadRequest("关键件条码不能为空"); } var bindRecord = new BindRecord { Sn = request.sn, PartNum = part.partNum, StationCode = request.stationCode, BindTime = DateTime.TryParse(request.scanTime, out var scanTime) ? scanTime : DateTime.Now, Employee = request.employee ?? "", ScanType = request.scanTpye }; DatabaseHelper.InsertBindRecord(bindRecord); if ( workOrder[ 0 ].IsLocalhost ) { //if (DatabaseHelper.GetProductProductionRecords(request.sn) == 0) //{ var response = new ApiResponse { code = "200", success = true, msg = "已存在记录", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = true }; return Ok(response); } } } else { var bindRecord = new BindRecord { Sn = request.sn, PartNum ="", StationCode = request.stationCode, BindTime = DateTime.TryParse(request.scanTime, out var scanTime) ? scanTime : DateTime.Now, Employee = request.employee ?? "", ScanType = request.scanTpye }; DatabaseHelper.InsertBindRecord(bindRecord); } if ( workOrder[ 0 ].IsLocalhost ) { LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件 成功"); return Ok(new ApiResponse() { data = true }); } var okresponse = await management.ApiClient.SendSnComponentAsync(request); if ( okresponse.success && okresponse.code == "200" ) { LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件 成功"); return Ok(okresponse); } else { LogHelper.WriteLogInfo($"收到请求: 接收SN和关键件 失败\r\n" + okresponse.ToString()); okresponse.success = false; return Content(System.Net.HttpStatusCode.InternalServerError, okresponse); } } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"SN和关键件接收失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } [HttpGet] [Route("getBindRecords")] public IHttpActionResult GetBindRecords() { try { var records = DatabaseHelper.SelectBindRecord(); var response = new ApiResponse> { code = "200", success = true, msg = "获取成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = records }; return Ok(response); } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"获取绑定记录失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } #endregion #region 2.4 接收工件加工参数 [HttpPost] [Route("receiveProcessParameters")] public async Task ReceiveProcessParameters([FromBody] ProcessParameterRequest request) { try { LogHelper.WriteLogInfo($"收到请求:接收工件加工参数 "); // 验证请求头 if ( !ValidateHeaders() ) { return Unauthorized(); } // 验证必填字段 if ( string.IsNullOrEmpty(request.plant) || string.IsNullOrEmpty(request.station) || //string.IsNullOrEmpty(request.sn) || string.IsNullOrEmpty(request.overallResult) ) { return BadRequest("必填字段不能为空"); } // 验证总结果 if ( request.overallResult != "OK" && request.overallResult != "NG" ) { return BadRequest($"无效的总结果: {request.overallResult}"); } var res = DatabaseHelper.SelectWorkOrderInfo(); string stationOrder = ""; string _materialCode=""; StationType stationtype= StationType.OP10; if ( request.station.Split('-')[ 2 ] == "L" ) { stationOrder = res.LeftOrderNo; _materialCode = res.LeftCheckCode; } else { stationOrder = res.RightOrderNo; _materialCode = res.RightCheckCode; } var workOrder = DatabaseHelper.SelectWorkOrderInfo(stationOrder); // 验证工单是否存在 if ( workOrder.Count == 0 ) { return BadRequest($"工单 {stationOrder} 不存在"); } if ( string.IsNullOrEmpty(request.sn) ) { List partInfos= DatabaseHelper.SelectPartInfo(_materialCode, request.station); if ( partInfos.Count != 0 ) { stationtype= partInfos[0].StationType; SnInfo info= DatabaseHelper.SelectSnInfoForStation(stationOrder, partInfos[ 0 ].StationType); if ( info != null ) { request.sn = info.Sn; } } else { return BadRequest($"工站信息不存在"); } } // 保存加工记录 var processRecord = new ProcessRecord { Sn = request.sn, Station = request.station, OverallResult = request.overallResult, ProcessTime = DateTime.Now, Equipment = request.equipment ?? "" }; DatabaseHelper.InsertProcessRecord(processRecord); if ( workOrder[ 0 ].IsLocalhost ) { var response = new ApiResponse { code = "200", success = true, msg = "加工参数接收成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = true }; LogHelper.WriteLogInfo($"收到请求:接收工件加工参数 成功"); DatabaseHelper.UpdateSnInfo(request.sn, stationOrder,stationtype); return Ok(response); } var okresponse = await management.ApiClient.SendProcessParametersAsync(request); if ( okresponse.success && okresponse.code == "200" ) { LogHelper.WriteLogInfo($"收到请求: 接收工件加工参数 成功"); DatabaseHelper.UpdateSnInfo(request.sn, stationOrder, stationtype); return Ok(okresponse); } else { LogHelper.WriteLogInfo($"收到请求: 接收工件加工参数 失败\r\n" + okresponse.ToString()); okresponse.success = false; return Content(System.Net.HttpStatusCode.InternalServerError, okresponse); } } catch ( Exception ex ) { LogHelper.WriteLogInfo("出错"); var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"加工参数接收失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } [HttpGet] [Route("getProcessRecords")] public IHttpActionResult GetProcessRecords() { try { var records = DatabaseHelper.SelectProcessRecord(); var response = new ApiResponse> { code = "200", success = true, msg = "获取成功", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24), data = records }; return Ok(response); } catch ( Exception ex ) { var errorResponse = new ErrorResponse { code = "55000", success = false, msg = $"获取加工记录失败: {ex.Message}", msgTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), traceId = Guid.NewGuid().ToString("N").Substring(0, 24) }; return Content(System.Net.HttpStatusCode.InternalServerError, errorResponse); } } #endregion #region 辅助方法 private bool ValidateHeaders() { // 简单的token验证 if ( Request.Headers.TryGetValues("app-key", out var appKeyValues) && Request.Headers.TryGetValues("token", out var tokenValues) ) { var appKey = appKeyValues.FirstOrDefault(); var token = tokenValues.FirstOrDefault(); // 这里使用简单的验证 return appKey == "test-app-key" && token == "test-token-123"; } return false; } private bool IsValidStatus(string status) { var validStatuses = new[] { "0", "1", "2", "3", "4", "5", "6", "7" }; return validStatuses.Contains(status); } private string GenerateSn(WorkOrderInfo workOrder, int printType) { var prefix = GetPrintTypePrefix(printType); var timestamp = DateTime.Now.ToString("yyMMddHHmm"); var randomStr = Guid.NewGuid().ToString("N").Substring(0, 6).ToUpper(); var counter = Interlocked.Increment(ref _snCounter); return $"{prefix}-{workOrder.MaterialCode}-{timestamp}-{counter:D4}-{randomStr}"; } private string GetPrintTypePrefix(int printType) { switch ( printType ) { case 1: return "P"; case 2: return "C"; case 3: return "Q"; case 4: return "B"; default: return "U"; } } private string GetPrintTypeName(int printType) { switch ( printType ) { case 1: return "产品码"; case 2: return "零件码"; case 3: return "合格码"; case 4: return "装箱码"; default: return "未知"; } } #endregion } }