using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using WIDESEA_Core; using WIDESEA_Core.BaseController; using WIDESEA_DTO.MES; using WIDESEA_IStockService; using WIDESEA_IBasicService; using WIDESEA_IMesService; using WIDESEA_ISystemService; using WIDESEA_Model.Models; using System.Diagnostics; namespace WIDESEA_WMSServer.Controllers.Stock { /// /// 库存明细 /// [Route("api/StockInfoDetail")] [ApiController] public class StockInfoDetailController : ApiBaseController { private readonly IMesLogService _mesLogService; private readonly IMesService _mesService; private readonly ISys_DictionaryService _sysDictionaryService; public StockInfoDetailController( IStockInfoDetailService service, IMesLogService mesLogService, IMesService mesService, ISys_DictionaryService sysDictionaryService) : base(service) { _mesLogService = mesLogService; _mesService = mesService; _sysDictionaryService = sysDictionaryService; } /// /// 托盘电芯绑定 - 调用MES接口 /// /// 绑定请求参数 /// 操作结果 [HttpPost("bindContainer")] public async Task BindContainer([FromBody] BindContainerRequestDto dto) { var response = new WebResponseContent(); var stopwatch = Stopwatch.StartNew(); try { // 1. 参数验证 if (string.IsNullOrWhiteSpace(dto.PalletCode)) { return response.Error("托盘编号不能为空"); } if (dto.SfcList == null || !dto.SfcList.Any()) { return response.Error("电芯码列表不能为空"); } // 2. 验证电芯状态(非'已锁定'状态允许绑定) var stockDetails = await Service.Repository.QueryDataAsync(x => dto.SfcList.Contains(x.SerialNumber)); if (stockDetails != null && stockDetails.Any(d => d.Status == 99)) { return response.Error("当前库存明细包含已锁定状态,不允许执行绑定操作"); } // 3. 获取系统配置 var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); // 3. 构造MES请求 - 将电芯列表转换为ContainerSfcItem格式 var mesRequest = new BindContainerRequest { EquipmentCode = equipmentCode, ResourceCode = resourceCode, LocalTime = DateTime.Now, ContainerCode = dto.PalletCode, ContainerSfcList = dto.SfcList.Select(sfc => new ContainerSfcItem { Sfc = sfc, Location = dto.Location ?? "" }).ToList(), OperationType = dto.OperationType }; string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); // 4. 调用MES接口(同步方法) var mesResult = _mesService.BindContainer(mesRequest); stopwatch.Stop(); // 5. 记录日志 await _mesLogService.LogAsync(new MesApiLogDto { ApiType = "BindContainer", RequestJson = requestJson, ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), IsSuccess = mesResult.IsSuccess, ErrorMessage = mesResult.ErrorMessage, ElapsedMs = (int)stopwatch.ElapsedMilliseconds, Creator = App.User.UserName }); // 6. 返回结果 if (mesResult.IsSuccess) { return response.OK("托盘电芯绑定成功"); } else { return response.Error($"MES接口调用失败: {mesResult.ErrorMessage}"); } } catch (System.Exception ex) { stopwatch.Stop(); // 记录错误日志 await _mesLogService.LogAsync(new MesApiLogDto { ApiType = "BindContainer", IsSuccess = false, ErrorMessage = ex.Message, ElapsedMs = (int)stopwatch.ElapsedMilliseconds, Creator = App.User.UserName }); return response.Error($"托盘电芯绑定失败: {ex.Message}"); } } /// /// 托盘电芯解绑 - 调用MES接口 /// /// 解绑请求参数 /// 操作结果 [HttpPost("unbindContainer")] public async Task UnbindContainer([FromBody] UnbindContainerRequestDto dto) { var response = new WebResponseContent(); var stopwatch = Stopwatch.StartNew(); try { // 1. 参数验证 if (string.IsNullOrWhiteSpace(dto.PalletCode)) { return response.Error("托盘编号不能为空"); } if (dto.SfcList == null || !dto.SfcList.Any()) { return response.Error("电芯码列表不能为空"); } // 2. 验证电芯状态(非'已锁定'状态允许解绑) var stockDetails = await Service.Repository.QueryDataAsync(x => dto.SfcList.Contains(x.SerialNumber)); if (stockDetails != null && stockDetails.Any(d => d.Status == 99)) { return response.Error("当前库存明细包含已锁定状态,不允许执行解绑操作"); } // 3. 获取系统配置 var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); // 3. 构造MES请求 var mesRequest = new UnBindContainerRequest { EquipmentCode = equipmentCode, ResourceCode = resourceCode, LocalTime = DateTime.Now, ContainCode = dto.PalletCode, SfcList = dto.SfcList }; string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); // 4. 调用MES接口(同步方法) var mesResult = _mesService.UnBindContainer(mesRequest); stopwatch.Stop(); // 5. 记录日志 await _mesLogService.LogAsync(new MesApiLogDto { ApiType = "UnbindContainer", RequestJson = requestJson, ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), IsSuccess = mesResult.IsSuccess, ErrorMessage = mesResult.ErrorMessage, ElapsedMs = (int)stopwatch.ElapsedMilliseconds, Creator = App.User.UserName }); // 6. 返回结果 if (mesResult.IsSuccess) { return response.OK("托盘电芯解绑成功"); } else { return response.Error($"MES接口调用失败: {mesResult.ErrorMessage}"); } } catch (System.Exception ex) { stopwatch.Stop(); // 记录错误日志 await _mesLogService.LogAsync(new MesApiLogDto { ApiType = "UnbindContainer", IsSuccess = false, ErrorMessage = ex.Message, ElapsedMs = (int)stopwatch.ElapsedMilliseconds, Creator = App.User.UserName }); return response.Error($"托盘电芯解绑失败: {ex.Message}"); } } /// /// 托盘NG电芯上报 - 调用MES接口 /// /// NG上报请求参数 /// 操作结果 [HttpPost("containerNgReport")] public async Task ContainerNgReport([FromBody] ContainerNgReportRequestDto dto) { var response = new WebResponseContent(); var stopwatch = Stopwatch.StartNew(); try { // 1. 参数验证 if (string.IsNullOrWhiteSpace(dto.PalletCode)) { return response.Error("托盘编号不能为空"); } if (dto.NgSfcList == null || !dto.NgSfcList.Any()) { return response.Error("NG电芯列表不能为空"); } // 2. 验证电芯状态(非'已锁定'状态允许NG上报) var sfcList = dto.NgSfcList.Select(x => x.Sfc).ToList(); var stockDetails = await Service.Repository.QueryDataAsync(x => sfcList.Contains(x.SerialNumber)); if (stockDetails != null && stockDetails.Any(d => d.Status == 99)) { return response.Error("当前库存明细包含已锁定状态,不允许执行NG上报操作"); } // 3. 获取系统配置 var configs = _sysDictionaryService.GetVueDictionary(new[] { "MES_EquipmentCode", "MES_ResourceCode" }); string equipmentCode = GetConfigValue(configs, "MES_EquipmentCode", "WCS_001"); string resourceCode = GetConfigValue(configs, "MES_ResourceCode", "RESOURCE_001"); // 3. 构造MES请求 - 将DTO格式转换为MES请求格式 var mesRequest = new ContainerNgReportRequest { EquipmentCode = equipmentCode, ResourceCode = resourceCode, LocalTime = DateTime.Now, ContainerCode = dto.PalletCode, NgSfcList = dto.NgSfcList.Select(ng => new NgSfcItem { Sfc = ng.Sfc, NgCode = ng.NgCode, NgEquipmentCode = ng.NgEquipmentCode, NgResourceCode = ng.NgResourceCode }).ToList() }; string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest); // 4. 调用MES接口(同步方法) var mesResult = _mesService.ContainerNgReport(mesRequest); stopwatch.Stop(); // 5. 记录日志 await _mesLogService.LogAsync(new MesApiLogDto { ApiType = "ContainerNgReport", RequestJson = requestJson, ResponseJson = System.Text.Json.JsonSerializer.Serialize(mesResult), IsSuccess = mesResult.IsSuccess, ErrorMessage = mesResult.ErrorMessage, ElapsedMs = (int)stopwatch.ElapsedMilliseconds, Creator = App.User.UserName }); // 6. 返回结果 if (mesResult.IsSuccess) { return response.OK("NG电芯上报成功"); } else { return response.Error($"MES接口调用失败: {mesResult.ErrorMessage}"); } } catch (System.Exception ex) { stopwatch.Stop(); // 记录错误日志 await _mesLogService.LogAsync(new MesApiLogDto { ApiType = "ContainerNgReport", IsSuccess = false, ErrorMessage = ex.Message, ElapsedMs = (int)stopwatch.ElapsedMilliseconds, Creator = App.User.UserName }); return response.Error($"NG电芯上报失败: {ex.Message}"); } } /// /// 从配置字典中获取配置值 /// /// 配置字典列表 /// 配置键 /// 默认值 /// 配置值 private string GetConfigValue(System.Collections.Generic.List configs, string key, string defaultValue = "") { if (configs != null) { var config = configs.FirstOrDefault(c => c.DicNo == key); if (config != null && config.Data != null) { // Data是dynamic类型,尝试获取第一个元素的value属性 try { // 使用dynamic来访问匿名类型的属性 dynamic data = config.Data; if (data != null) { // data可能是IEnumerable或者单个对象 var enumerable = data as System.Collections.IEnumerable; if (enumerable != null) { foreach (var item in enumerable) { // 获取第一个元素 dynamic firstItem = item; var value = firstItem.value; return value?.ToString() ?? defaultValue; } } } } catch { // 如果无法获取,返回默认值 return defaultValue; } } } return defaultValue; } } }