leiqunqing
2026-02-06 15b3879cd259108e7ebb755fe02c190f28f1e20c
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/BoxingDetailService.cs
@@ -1,20 +1,396 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.PLCEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
namespace WIDESEAWCS_BasicInfoService
{
    public class BoxingDetailService : ServiceBase<Dt_BoxingDetail, IRepository<Dt_BoxingDetail>>, IBoxingDetailService
    {
        public BoxingDetailService(IRepository<Dt_BoxingDetail> BaseDal) : base(BaseDal)
        private readonly IBoxingService _boxingService;
        private readonly IFormulaService _formulaService;
        private readonly IFormulaDetailService _formulaDetailService;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        public BoxingDetailService(
            IRepository<Dt_BoxingDetail> BaseDal,
            IFormulaService formulaService,
            IBoxingService boxingService,
            IFormulaDetailService formulaDetailService,
            IUnitOfWorkManage unitOfWorkManage
            ) : base(BaseDal)
        {
            _formulaService = formulaService;
            _boxingService = boxingService;
            _formulaDetailService = formulaDetailService;
            _unitOfWorkManage = unitOfWorkManage;
        }
        public IRepository<Dt_BoxingDetail> Repository => BaseDal;
        /// <summary>
        /// æ¯”较零件是否齐全
        /// </summary>
        /// <param name="boxingDetails">实际装箱的零件集合</param>
        /// <param name="formulaDetails">配方要求的零件集合</param>
        /// <returns>是否完全匹配</returns>
        public bool CheckComponentsMatchExactly(List<string> boxingDetails, List<string> formulaDetails)
        {
            // 1. åŸºç¡€æ ¡éªŒï¼šç©ºå€¼/数量不一致直接返回不匹配
            if (boxingDetails == null || formulaDetails == null || boxingDetails.Count != formulaDetails.Count)
            {
                return false;
            }
            // 2. ä¸¤ä¸ªç©ºé›†åˆç›´æŽ¥åˆ¤å®šä¸ºåŒ¹é…ï¼ˆæ— é›¶ä»¶=零件齐全)
            if (boxingDetails.Count == 0)
            {
                return true;
            }
            // 3. ç»Ÿè®¡ç¬¬ä¸€ä¸ªé›†åˆçš„元素出现次数(严格键匹配,处理重复元素)
            var elementCountDict = new Dictionary<string, int>();
            foreach (var item in boxingDetails)
            {
                // å¤„理集合中的null元素,转为空字符串避免字典键为null报错
                var key = item ?? string.Empty;
                if (elementCountDict.ContainsKey(key))
                {
                    elementCountDict[key]++;
                }
                else
                {
                    elementCountDict[key] = 1;
                }
            }
            // 4. éåŽ†ç¬¬äºŒä¸ªé›†åˆï¼ŒæŠµæ¶ˆè®¡æ•°ï¼šæ— æ­¤å…ƒç´ /数量不匹配直接返回false
            foreach (var item in formulaDetails)
            {
                var key = item ?? string.Empty;
                if (!elementCountDict.ContainsKey(key))
                {
                    return false; // å­˜åœ¨é…æ–¹æ²¡æœ‰/装箱多出来的零件
                }
                elementCountDict[key]--;
                if (elementCountDict[key] == 0)
                {
                    elementCountDict.Remove(key); // è®¡æ•°æ¸…零则移除,避免干扰最终判断
                }
            }
            // 5. å­—典为空 = æ‰€æœ‰å…ƒç´ ç§ç±»+数量完全匹配
            return elementCountDict.Count == 0;
        }
        /// <summary>
        /// æ£€æŸ¥é›¶ä»¶
        /// </summary>
        /// <param name="boxingDetails"></param>
        /// <param name="formulaDetails"></param>
        /// <returns></returns>
        public string IsComponentCodesEqual(List<string> boxingDetails, List<string> formulaDetails)
        {
            // å¤„理null集合,规避空指针异常
            var boxList = boxingDetails ?? new List<string>();
            var formulaList = formulaDetails ?? new List<string>();
            var validBoxCodes = boxList.Where(code => !string.IsNullOrEmpty(code)).ToList();
            var validFormulaCodes = formulaList.Where(code => !string.IsNullOrEmpty(code)).ToList();
            foreach (var group in validBoxCodes.GroupBy(code => code))
            {
                string componentCode = group.Key;
                int boxCount = group.Count();
                int formulaCount = validFormulaCodes.Count(code => code == componentCode);
                if (formulaCount == 0 || formulaCount < boxCount)
                {
                    return componentCode;
                }
            }
            return null;
        }
        /// <summary>
        /// æ·»åŠ /修改组盘信息(一体化接口:传工装板编号存在则修改,不存在则新增)
        /// </summary>
        /// <param name="toolingBoardSubmitDto"></param>
        /// <returns></returns>
        public WebResponseContent SaveToolingBoardNo(ToolingBoardSubmitDto toolingBoardSubmitDto)
        {
            using (var uow = _unitOfWorkManage.CreateUnitOfWork())
            {
                try
                {
                    // 1. å‚数校验
                    if (toolingBoardSubmitDto == null)
                    {
                        return WebResponseContent.Instance.Error("提交参数不能为空");
                    }
                    string productCode = toolingBoardSubmitDto.FinishedProductCode?.Trim();
                    if (!string.IsNullOrWhiteSpace(productCode))
                    {
                        string proCode = string.Empty;
                        string proOther = string.Empty;
                        var proCodeMatch = System.Text.RegularExpressions.Regex.Match(productCode, @"TX(\d+)(?=\s|\||$)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                        if (proCodeMatch.Success)
                        {
                            proCode = $"TX{proCodeMatch.Groups[1].Value.Trim()}"; // æ‹¼æŽ¥TX+数字,保持格式统一
                        }
                        // æ­£åˆ™2:匹配连续的10位纯数字(全局匹配,取第一个符合的即可)
                        var proOtherMatch = System.Text.RegularExpressions.Regex.Match(productCode, @"\d{10}");
                        if (proOtherMatch.Success)
                        {
                            proOther = proOtherMatch.Value.Trim();
                        }
                        toolingBoardSubmitDto.PartsList = toolingBoardSubmitDto.PartsList.Where(code => !string.IsNullOrEmpty(code)).ToList();
                        // 2. æŸ¥è¯¢æˆå“é…æ–¹ä¿¡æ¯
                        Dt_Formula formulaModel = _formulaService.Repository.QueryFirst(x => x.ProductCode == proCode);
                        if (formulaModel == null)
                        {
                            return WebResponseContent.Instance.Error("无成品配方,请核对成品编码");
                        }
                        List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == formulaModel.Id && x.IsScanned == 1);
                        List<string> Codelist = dt_FormulaDetails.Select(x => x.ComponentCode).ToList();
                        string IsCode = IsComponentCodesEqual(toolingBoardSubmitDto.PartsList, Codelist);
                        if (IsCode != null)
                        {
                            return WebResponseContent.Instance.Error($"物料【{IsCode}】错误,请核对物料编号");
                        }
                        //Dt_Boxing existBoxinModel = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        //if (existBoxinModel == null)
                        //{
                        //    return WebResponseContent.Instance.Error($"托盘未添加,请稍后重试");
                        //}
                        if (!CheckComponentsMatchExactly(toolingBoardSubmitDto.PartsList, Codelist))
                        {
                            throw new InvalidOperationException("零件与配方表中不同");
                        }
                        var PalletCode = TcpClientExample.Start("192.168.2.120", 2001);
                        if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                        {
                            throw new InvalidOperationException("托盘码未扫到,请重试");
                        }
                        Dt_Boxing existBoxinModel = new Dt_Boxing();
                        existBoxinModel.PalletCode = PalletCode;
                        existBoxinModel.ProductCode = proCode;
                        existBoxinModel.BoxingNo = proOther;
                        int id = _boxingService.Repository.AddData(existBoxinModel);
                        foreach (var item in dt_FormulaDetails)
                        {
                            Dt_BoxingDetail dt_BoxingDetail = new Dt_BoxingDetail()
                            {
                                BoxingId = id,
                                ComponentCode = item.ComponentCode,
                                ComponentName = item.ComponentName,
                                Creater = "admin",
                                CreateDate = new DateTime()
                            };
                            BaseDal.AddData(dt_BoxingDetail);
                        }
                        uow.Commit();
                    }
                    OtherDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceName == "主控PLC") as OtherDevice;
                    if (device == null) throw new Exception("未找到主控PLC设备信息");
                    if (!device.IsConnected) throw new Exception($"主控PLC设备通讯异常");
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                    Thread.Sleep(500);
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, false);
                    //    if (existBoxinModel == null)
                    //{
                    //    #region æ–°å¢žé€»è¾‘ - åŽŸé€»è¾‘ä¼˜åŒ–ç‰ˆ
                    //    Dt_Boxing dt_boxin = new Dt_Boxing()
                    //    {
                    //        PalletCode = palletCode,
                    //        ProductCode = productCode,
                    //        ProductName = formulaModel.ProductName.Trim(),
                    //        Creater = "admin",
                    //        CreateDate = DateTime.Now
                    //    };
                    //    int newBoxingId = _boxingService.Repository.AddData(dt_boxin);
                    //    // æ‰¹é‡æ·»åŠ æ˜Žç»†è¡¨æ•°æ®
                    //    if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                    //    {
                    //        List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                    //        foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                    //        {
                    //            if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                    //            string ComponentCodeTrim = ComponentCode.Trim();
                    //            Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                    //            if (formulaDetail == null)
                    //            {
                    //                return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料编号");
                    //            }
                    //            Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                    //            {
                    //                BoxingId = newBoxingId,
                    //                ComponentCode = ComponentCodeTrim,
                    //                ComponentName = formulaDetail.ComponentName,
                    //                Creater = "admin",
                    //                CreateDate = DateTime.Now
                    //            };
                    //            detailList.Add(detailModel);
                    //        }
                    //        if (detailList.Count > 0)
                    //        {
                    //            BaseDal.AddData(detailList);
                    //        }
                    //    }
                    //    #endregion
                    //}
                    //else
                    //{
                    //    #region ä¿®æ”¹é€»è¾‘ - æ–°å¢žæ ¸å¿ƒé€»è¾‘
                    //    // 1. æ›´æ–°ä¸»è¡¨æ•°æ®
                    //    existBoxinModel.ProductCode = productCode;
                    //    existBoxinModel.ProductName = formulaModel.ProductName.Trim();
                    //     existBoxinModel.Modifier = "admin";
                    //    existBoxinModel.ModifyDate = DateTime.Now;
                    //    _boxingService.Repository.UpdateData(existBoxinModel);
                    //    int boxingId = existBoxinModel.Id;
                    //    // 2. åˆ é™¤è¯¥ç»„盘下的【原有全部明细表数据】
                    //    List<Dt_BoxingDetail> oldDetailList = BaseDal.QueryData(x => x.BoxingId == boxingId);
                    //    if (oldDetailList != null && oldDetailList.Count > 0)
                    //    {
                    //        BaseDal.DeleteData(oldDetailList);
                    //    }
                    //    // 3. é‡æ–°æ’入修改后的明细表数据
                    //    if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                    //    {
                    //        List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                    //        foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                    //        {
                    //            if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                    //            string ComponentCodeTrim = ComponentCode.Trim();
                    //            Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                    //            if (formulaDetail == null)
                    //            {
                    //                return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料名称");
                    //            }
                    //            Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                    //            {
                    //                BoxingId = boxingId,
                    //                ComponentCode = ComponentCodeTrim,
                    //                ComponentName = formulaDetail.ComponentName,
                    //                Creater = "admin",
                    //                CreateDate = DateTime.Now
                    //            };
                    //            detailList.Add(detailModel);
                    //        }
                    //        if (detailList.Count > 0)
                    //        {
                    //            BaseDal.AddData(detailList);
                    //        }
                    //    }
                    //    #endregion
                    //}
                    //uow.Commit();
                    //string msg = existBoxinModel == null ? "组盘信息新增成功!" : "组盘信息修改成功!";
                    return WebResponseContent.Instance.OK();
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"保存工装板组盘信息异常:{ex.Message},堆栈:{ex.StackTrace}");
                    return WebResponseContent.Instance.Error($"提交失败:{ex.Message}");
                }
            }
        }
        /// <summary>
        /// èŽ·å–æˆå“ç¼–å·å’Œé›¶ä»¶ç¼–å·
        /// </summary>
        /// <param name="palletCode"></param>
        /// <returns></returns>
        public WebResponseContent GetProductAndPartsByBoardNo(string palletCode)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(palletCode))
                {
                    return WebResponseContent.Instance.OK("查询成功", new
                    {
                        finishedProductCode = "",
                        partsList = Enumerable.Repeat("", 10).ToList()
                    });
                }
                Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (dt_Boxing == null)
                {
                    return WebResponseContent.Instance.OK("未查询到该工装板对应的成品信息", new
                    {
                        finishedProductCode = "",
                        partsList = Enumerable.Repeat("", 10).ToList()
                    });
                }
                List<Dt_BoxingDetail> dt_BoxingDetails = BaseDal.QueryData(x => x.BoxingId == dt_Boxing.Id)?.ToList() ?? new List<Dt_BoxingDetail>();
                // å–零件编号
                List<string> partsList = dt_BoxingDetails.Select(d => d.ComponentCode).ToList();
                List<string> resultPartsList = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    if (i < partsList.Count)
                    {
                        resultPartsList.Add(partsList[i] ?? "");
                    }
                    else
                    {
                        resultPartsList.Add("");
                    }
                }
                return WebResponseContent.Instance.OK("零件编号列表查询成功", new
                {
                    finishedProductCode = dt_Boxing.ProductCode ?? "",
                    partsList = resultPartsList
                });
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"查询零件编号列表异常:{ex.Message}");
            }
        }
    }
}