using Hh.Mes.Common.log; using Hh.Mes.POJO.Entity; using Hh.Mes.POJO.EnumEntitys; using Hh.Mes.POJO.Response; using Hh.Mes.POJO.ViewModel; using Hh.Mes.Service.Repository; using System; using System.Collections.Generic; using System.Data; using System.Linq; namespace Hh.Mes.Service.Material { /// <summary> /// 套料计算 /// </summary> public class CutPlanCalculateService : RepositorySqlSugar<dynamic> { #region 属性 /// <summary> /// 同步锁,套料要避免同步并发 /// </summary> public static object LockNesting { get; set; } = new object(); //套料结果 public TotalData totalData { get; set; } = new TotalData(); /// <summary> /// 获取字典的废料长度 /// </summary> public decimal CutPlanLength { get { var CutPlan = GetDictionaryDictValue("CuttingWasteLength", "CutConfig"); if (CutPlan == null) CutPlan = "250"; return decimal.Parse(CutPlan); } } /// <summary> /// 获取字典的管材长度 /// </summary> public decimal PipeLength { get { var PipeLength = GetDictionaryDictValue("PipeLengthConfig", "CutConfig"); if (PipeLength == null) PipeLength = "5950"; return decimal.Parse(PipeLength); } } /// <summary> /// 获取字典的切割损耗 /// </summary> public decimal CutFlanLength { get { var cutFlan = GetDictionaryDictValue("CutFlanConfig", "CutConfig"); if (cutFlan == null) cutFlan = "0"; return decimal.Parse(cutFlan); } } /// <summary> /// 登陆用户 /// </summary> private string SysUser { get { return sysWebUser?.Account; } } #endregion #region 套料相关 /// <summary> /// 套料计算 /// </summary> /// <param name="cutHeadIds">套料指定的工单头表ID</param> /// <returns></returns> public dynamic Calculation(string cutHeadIds) { var response = new Response(); try { lock (LockNesting) { #region 套料计算 if (string.IsNullOrWhiteSpace(cutHeadIds)) { return response.ResponseError($"请选择工单!"); } List<int> cutHeadList = cutHeadIds.Split(',').Select(t => int.Parse(t)).ToList(); //工单 var workOrderHeadQueryable = Context.Queryable<bus_workOrder_head>() .Where(x => cutHeadList.Contains(x.id) && !x.isScrap && x.nowOprSequenceCode == EnumoprSequenceCode.套料).ToList(); if (workOrderHeadQueryable.Count == 0) { return response.ResponseError($"没有状态为【套料】工序的工单,不能套料!"); } var headKeysList = workOrderHeadQueryable.Select(x => x.keys).Distinct().ToList(); //工单明细 var workOrderDetailQueryable = Context.Queryable<bus_workOrder_detail>() .Where(x => headKeysList.Contains(x.headKeys) && x.state == (int)EnumOrderBodyStatus.初始化 && x.workCenterCode == EnumoprSequenceCode.套料).ToList(); if (workOrderDetailQueryable.Count == 0) { return response.ResponseError($"没有状态为【初始】的工单明细,不能套料!"); } //物料分组 var cutMaterCodeList = workOrderDetailQueryable.Select(t => t.cutMaterCode).ToList().Distinct().ToList(); //单管的管段明细,按照物料类型分组暂存到List var spoolList = new List<List<bus_workOrder_detail>>(); #region 数据筛选 通过切割工单明细物料,从小到大排序,然后套料 foreach (var materCode in cutMaterCodeList) { var cutDetailTemp = workOrderDetailQueryable.Where(x => x.cutMaterCode == materCode).ToList(); cutDetailTemp = cutDetailTemp.OrderBy(x => x.cuttingLength).ToList(); spoolList.Add(cutDetailTemp); } foreach (var partList in spoolList) { //管段匹配的最大的管材长度 var pipeLengthMax = PipeLength; //单根管段匹配的最小长度 var pipeLength = pipeLengthMax - CutPlanLength; //1.找出管段长度大于"单根管段匹配的最小长度"小于"管段匹配的最大的管材长度"的管段,进行整个单管套料 var partList1 = partList.Where(x => x.cuttingLength >= pipeLength && x.cuttingLength <= pipeLengthMax).ToList(); //整根套料,添加套料方案 if (partList1.Count > 0) AddScheme(workOrderHeadQueryable, partList1); //2.找出管段长度小于"单根管段匹配的最小长度"的管段,进行多管段套料 var partList2 = partList.Where(x => x.cuttingLength < pipeLength).ToList(); if (partList2.Count > 0) PartCalculation(workOrderHeadQueryable, partList2); //记录未套料工单明细 var partList3 = partList.Where(x => x.cuttingLength > pipeLengthMax).ToList(); partList3.ForEach(x => totalData.notWorkOrderDetailList.Add(x)); //记录未套料工单 var headKeyList = partList3.Select(x => x.headKeys).ToList().Distinct().ToList(); var notworkOrderHeadList = workOrderHeadQueryable.Where(x => headKeyList.Contains(x.keys)).ToList(); notworkOrderHeadList.ForEach(x => totalData.notWorkOrderheadList.Add(x)); //移除不能套料工单(已经把可以套料的管段都进行了套料,剩下的就是不能套料的管段,把不能套料的明细关联的工单头移除,剩下的工单都是已经套料完的) workOrderHeadQueryable.RemoveAll(x => notworkOrderHeadList.Exists(y => y.keys == x.keys)); } //记录工单 totalData.workOrderheadList = workOrderHeadQueryable; #endregion response.Message = "计算成功!"; return response; #endregion } } catch (Exception ex) { return response.ResponseError($"套料计算发生异常,原因:{ex.Message}"); } } /// <summary> /// 对管段进行套料计算,按照最大利用来套料,可能出现一个工单的管段分散在多个管材上 /// </summary> private void PartCalculation(List<bus_workOrder_head> workOrderHeadList, List<bus_workOrder_detail> workOrderDetailList) { #region 循环套料 //循环套料 while (workOrderDetailList.Count > 0) { //管段组 var detailGroup = new List<bus_workOrder_detail>(); //损耗 decimal loss = 0; //配置的管材长度 var pipeLength = PipeLength; //配置的废料长度 var cutPlanLength = CutPlanLength; //配置的切割余量 var cutFlanLength = CutFlanLength; var Detail = new List<bus_workOrder_detail>(); foreach (var part in workOrderDetailList) { //"管段+废料长度+切割余量+损耗"小于管材长度,就可用 if (pipeLength >= part.cuttingLength + cutPlanLength + cutFlanLength + loss) { detailGroup.Add(part); loss = loss + part.cuttingLength + cutFlanLength; Detail.Add(part); } } // 移除已经套料管段 workOrderDetailList.RemoveAll(x => Detail.Exists(y => y.bodyKeys == x.bodyKeys)); if (detailGroup.Count > 0) AddScheme(workOrderHeadList, detailGroup); } #endregion } /// <summary> /// 添加套料方案 /// </summary> /// <param name="workOrderHeadList">工单头表</param> /// <param name="workOrderDetailList">工单明细表</param> private void AddScheme(List<bus_workOrder_head> workOrderHeadList, List<bus_workOrder_detail> workOrderDetailList) { #region 添加套料方案 TotalModel totalModel = new TotalModel(); var loss = workOrderDetailList.Select(x => x.cuttingLength); // 总切割长度 = 总损耗长度 + 总管段长度 var sumProducts = workOrderDetailList.Sum(x => x.cuttingLength + CutFlanLength); //利用率 = 总切割长度 / 管材长度 var percentage = sumProducts / PipeLength; //表头Key var keys = Guid.NewGuid(); //余料码 var oddmentsCode = GetOddmentsCode(PipeLength - sumProducts, workOrderDetailList[0].id); //套料方案头 var cutplanHead = new bus_cutplan_head(); cutplanHead.keys = keys; cutplanHead.materialCode = workOrderDetailList[0].cutMaterCode; cutplanHead.pipeLength = PipeLength; cutplanHead.lossCount = percentage; cutplanHead.oddmentsCode = oddmentsCode; cutplanHead.oddmentsLength = PipeLength - sumProducts; //cutplanHead.lineCode = "线体"; cutplanHead.planStartTime = DateTime.Now.ToString("yyyy-MM-dd"); cutplanHead.level = 1; cutplanHead.state = (int)EnumCutPlanHeadStatus.初始; cutplanHead.createTime = DateTime.Now.ToString(); cutplanHead.createBy = SysUser; //套料明细 List<bus_cutplan_detail> detaillis = new List<bus_cutplan_detail>(); //切割优先级 var Level = workOrderDetailList.Count; foreach (var item in workOrderDetailList) { //明细对应头表 var cutplan = workOrderHeadList.Where(x => x.keys == item.headKeys).First(); //追踪码 //var barCode = GetBarCode(item.id); var bodyKeys = Guid.NewGuid(); var cutplanDetail = new bus_cutplan_detail(); cutplanDetail.id = item.id; cutplanDetail.bodyKeys = bodyKeys; cutplanDetail.headKeys = keys; cutplanDetail.workOrderHeadKeys = cutplan.keys; cutplanDetail.workOrderDetailKeys = item.bodyKeys; cutplanDetail.iwpNo = cutplan.workOrderCode; cutplanDetail.barCode = item.barCode; cutplanDetail.cuttingLength = item.cuttingLength; cutplanDetail.cutFlanConfig = CutFlanLength; cutplanDetail.cutState = (int)EnumCutPlanDetailStatus.初始; cutplanDetail.cutLevel = Level; cutplanDetail.isendproduct = item.isEndProduct; cutplanDetail.createTime = DateTime.Now; cutplanDetail.createBy = SysUser; //页面展示使用 cutplanDetail.parentTypeId = keys; cutplanDetail.keys = bodyKeys; detaillis.Add(cutplanDetail); //工单明细记录追踪码,套料保存时使用 //item.barCode = barCode; item.state = (int)EnumOrderBodyStatus.已完成; item.actualEndTime = DateTime.Now; item.updateBy = SysUser; item.updateTime = DateTime.Now; totalData.workOrderDetailList.Add(item); Level--; } //记录套料 totalModel.cutplanHead = cutplanHead; totalModel.planDetailList = detaillis; totalModel.Percentage = percentage.ToString("0.00%"); totalData.totalModel.Add(totalModel); #endregion } /// <summary> /// 生成余料编码 /// </summary> /// <returns></returns> private string GetOddmentsCode(decimal Length, int ID) { //码前缀 string prefix = "Y"; //废料长度 var cutPlanLength = CutPlanLength; if (cutPlanLength > Length) { prefix = "F"; } string Code = DateTime.Now.ToString("yyMMdd"); return prefix + Code + ID.ToString(); } /// <summary> /// 生成追踪码 /// </summary> /// <returns></returns> //private string GetBarCode(int ID) //{ // return (100000 + ID).ToString(); //} /// <summary> /// 查询可套料工单 /// </summary> /// <param name="time"></param> /// <returns></returns> public dynamic GetCutterInfo(string time) { var response = new Response(); try { #region 查询 工单头、明细 List<bus_workOrder_detail> cutList = new List<bus_workOrder_detail>(); if (string.IsNullOrWhiteSpace(time)) { return response.ResponseError($"请选择日期!"); } //工单 var workOrderHeadQueryable = Context.Queryable<bus_workOrder_head>() .Where(x => SqlSugar.SqlFunc.DateIsSame(x.planStartTime, DateTime.Parse(time)) && x.nowOprSequenceCode == EnumoprSequenceCode.套料).ToList(); if (workOrderHeadQueryable.Count == 0) { return response.ResponseError($"未查询到可以【套料】的工单。条件:计划时间是【{time}】当前工序【{EnumoprSequenceCode.套料}】!"); } //工单明细 foreach (var item in workOrderHeadQueryable) { var detailList = Context.Queryable<bus_workOrder_detail>() .Where(x => x.headKeys == item.keys && x.state == (int)EnumOrderBodyStatus.初始化 && x.workCenterCode == EnumoprSequenceCode.套料).ToList(); detailList.ForEach(x => { x.parentTypeId = x.headKeys; x.keys = x.bodyKeys; }); //添加一个父对象,页面展示需要 bus_workOrder_detail workOrderDetail = new bus_workOrder_detail(); workOrderDetail.id = item.id; workOrderDetail.keys = item.keys; workOrderDetail.workOrderCode = item.workOrderCode; workOrderDetail.parentTypeId = Guid.Parse("00000000-0000-0000-0000-000000000000"); cutList.Add(workOrderDetail); detailList.ForEach(x => cutList.Add(x)); } response.Code = 200; response.Result = cutList; return response; #endregion } catch (Exception ex) { return response.ResponseError($"查询发生异常,原因:{ex.Message}"); } } /// <summary> /// 页面套料计算 /// </summary> /// <param name="cutHeadIds">套料指定的工单头表ID</param> /// <returns></returns> public dynamic GteCalculation(string cutHeadIds) { var response = new Response(); try { lock (LockNesting) { #region 页面套料计算 if (string.IsNullOrWhiteSpace(cutHeadIds)) { return response.ResponseError($"请选择工单!"); } var result = Calculation(cutHeadIds); if (result.Code != 200) return result; #region 处理数据,转换为页面使用格式 /// 套料结果 List<TotalModel> totalModel = totalData.totalModel; List<bus_cutplan_detail> cutplanDetail = new List<bus_cutplan_detail>(); foreach (var item in totalModel) { bus_cutplan_detail model = new bus_cutplan_detail(); model.keys = item.cutplanHead.keys; model.workOrderHeadKeys = item.cutplanHead.keys; model.parentTypeId = Guid.Parse("00000000-0000-0000-0000-000000000000"); model.materialCode = item.cutplanHead.materialCode; model.lossCount = item.cutplanHead.lossCount; model.pipeLength = item.cutplanHead.pipeLength; model.oddmentsLength = item.cutplanHead.oddmentsLength; cutplanDetail.Add(model); item.planDetailList.ForEach(x => { x.parentTypeId = item.cutplanHead.keys; cutplanDetail.Add(x); }); } // 未套料工单头表 List<bus_workOrder_head> notWorkOrderheadList = totalData.notWorkOrderheadList; // 未套料工单明细 List<bus_workOrder_detail> notWorkOrderDetailList = totalData.notWorkOrderDetailList; //返回结果处理 List<bus_workOrder_detail> returnNotWorkOrderDetailList = new List<bus_workOrder_detail>(); foreach (var item in notWorkOrderheadList) { //添加一个父对象,页面展示需要 bus_workOrder_detail workOrderDetail = new bus_workOrder_detail(); workOrderDetail.id = item.id; workOrderDetail.keys = item.keys; workOrderDetail.workOrderCode = item.workOrderCode; workOrderDetail.parentTypeId = Guid.Parse("00000000-0000-0000-0000-000000000000"); returnNotWorkOrderDetailList.Add(workOrderDetail); var DetailList = notWorkOrderDetailList.Where(x => x.headKeys == item.keys).ToList(); if (DetailList.Count > 0) { DetailList.ForEach(x => { x.keys = Guid.NewGuid(); x.parentTypeId = item.keys; returnNotWorkOrderDetailList.Add(x); }); } } response.Message = "计算成功!"; response.Result = new { cutplanList = cutplanDetail, notWorkOrderList = returnNotWorkOrderDetailList }; return response; #endregion #endregion } } catch (Exception ex) { return response.ResponseError($"套料计算发生异常,原因:{ex.Message}"); } } /// <summary> /// 套料并且保存 /// </summary> /// <param name="cutHeadIds">套料指定的工单头表ID</param> /// <returns></returns> public dynamic SaveCutPlan(string cutHeadIds) { var response = new Response(); try { lock (LockNesting) { #region 套料保存 if (string.IsNullOrWhiteSpace(cutHeadIds)) { return response.ResponseError($"请选择工单!"); } var result = Calculation(cutHeadIds); if (result.Code != 200) return result; if (totalData.totalModel.Count <= 0) { return response.ResponseError($"没有可以保存的套料方案!"); } //工单头 List<bus_workOrder_head> workOrderHeadList = totalData.workOrderheadList; workOrderHeadList.ForEach(x => { x.nowOprSequenceCode = EnumoprSequenceCode.切割坡口; x.nowStationCode = GetStation(EnumoprSequenceCode.切割坡口); x.updateBy = SysUser; x.updateTime = DateTime.Now; }); //更新工单头 Context.Updateable(workOrderHeadList).UpdateColumns(t => new { t.nowOprSequenceCode, t.nowStationCode, t.updateBy, t.updateTime }).AddQueue(); //工单明细 List<bus_workOrder_detail> workOrderDetailList = totalData.workOrderDetailList; //更新工单明细 Context.Updateable(workOrderDetailList).UpdateColumns(t => new { t.state,t.actualEndTime, t.updateBy, t.updateTime }).AddQueue(); //套料结果 List<TotalModel> totalModel = totalData.totalModel; foreach (var item in totalModel) { //添加套料结果 Context.Insertable(item.cutplanHead).AddQueue(); Context.Insertable(item.planDetailList).AddQueue(); } var updateCount = ExecuteQueues(Context); if (updateCount == 0) { return response.ResponseError($"套料方案方案保存数据库失败!"); } else { //套料完工反馈 CutWeldService cutWeldService = new CutWeldService(); foreach (var item1 in totalModel) { foreach (var item2 in item1.planDetailList) { //工序完工反馈 cutWeldService.SendIWPTechnologylineProcess(item2.barCode, (int)EnumCutHeadState.已套料); } } } response.Message = "保存成功!"; return response; #endregion } } catch (Exception ex) { return response.ResponseError($"套料保存发生异常,原因:{ex.Message}"); } } /// <summary> /// 工位查询 /// </summary> /// <param name="workCenterCode"></param> /// <returns></returns> public string GetStation(string workCenterCode) { return Context.Queryable<base_work_center_station_rel>().Where(x => x.workCenterCode == workCenterCode).First()?.workStationCode; } /// <summary> /// 手动完成套料方案,并且发送完工状态 /// </summary> /// <param name="ID">ID</param> /// <returns></returns> public dynamic CompleteExecute(int ID) { var response = new Response(); try { lock (LockNesting) { #region 手动完成套料方案 //获取套料方案头表 var cutPlanHead = Context.Queryable<bus_cutplan_head>().Where(t => t.id == ID).First(); if (cutPlanHead == null) { return response.ResponseError($"没有套料方案,请核对!"); } if (cutPlanHead.state > (int)EnumCutPlanHeadStatus.初始) { return response.ResponseError($"已经开始执行或执行完成,不需要再次确认完成!"); } //获取套料方案明细表 var cutPlanDetails = Context.Queryable<bus_cutplan_detail>().Where(t => t.headKeys == cutPlanHead.keys).ToList(); if (cutPlanDetails.Count == 0) { return response.ResponseError($"没有方案明细,请核对!"); } #region 套料状态-手动完成 //把套料方案头改为 手动完成 cutPlanHead.state = (int)EnumCutPlanHeadStatus.手动完成; cutPlanHead.actualEndTime = DateTime.Now.ToString(); cutPlanHead.cutEndTime = DateTime.Now.ToString(); cutPlanHead.updateBy = SysUser; cutPlanHead.updateTime = DateTime.Now.ToString(); Context.Updateable(cutPlanHead).UpdateColumns(t => new { t.state, t.actualEndTime, t.cutEndTime, t.updateBy, t.updateTime }).AddQueue(); //把套料方案明细改为 切割完成 Context.Updateable<bus_cutplan_detail>() .SetColumns(t => t.cutState == (int)EnumCutPlanDetailStatus.切割完成) .SetColumns(t => t.cutEndTime == DateTime.Now.ToString()) .SetColumns(t => t.updateTime == DateTime.Now.ToString()) .SetColumns(t => t.updateBy == SysUser) .Where(t => t.headKeys == cutPlanHead.keys) .AddQueue(); #endregion #region 工单切割工序完成 //获取工单头表,如果工单头对应的明细实体都切割完毕,需要更新工单下一工序 var workOrderHeadList = cutPlanDetails.Select(x => x.workOrderHeadKeys).ToList().Distinct().ToList(); //本次完成的工单明细keys var workOrderDetailList = cutPlanDetails.Select(x => x.workOrderDetailKeys).ToList().Distinct().ToList(); //分工单处理 foreach (var item in workOrderHeadList) { #region 更新工单切割工序明细为完成 //套料工序工单明细 var workOrderDetail = Context.Queryable<bus_workOrder_detail>().Where(x => x.headKeys == item && workOrderDetailList.Contains(x.bodyKeys)).ToList(); //已经套料工单明细barCode var barCodeList = workOrderDetail.Select(x => x.barCode).ToList().Distinct().ToList(); //更新工单切割工序为完成 Context.Updateable<bus_workOrder_detail>() .SetColumns(t => t.state == (int)EnumOrderBodyStatus.已完成) .SetColumns(t => t.actualStartTime == DateTime.Now) .SetColumns(t => t.updateTime == DateTime.Now) .SetColumns(t => t.updateBy == SysUser) .Where(t => t.headKeys == item&& barCodeList.Contains(t.barCode)&&t.oprSequenceCode== EnumoprSequenceCode.切割坡口) .AddQueue(); #endregion #region 更新工单头是否到下一个工序 //套料工单头 var workOrderHead = Context.Queryable<bus_workOrder_head>().Where(x => x.keys == item && x.nowOprSequenceCode == EnumoprSequenceCode.切割坡口).First(); //排除本次完成的切割工序明细 var cutplanDetail = Context.Queryable<bus_workOrder_detail>().Where(x => x.headKeys == item && !barCodeList.Contains(x.barCode) && x.state < (int)EnumOrderBodyStatus.已完成 &&x.oprSequenceCode== EnumoprSequenceCode.切割坡口).ToList(); //排除本次完成的明细,切割工序都已经完成,就需要更新工单工序到下一工序 if (workOrderHead != null && cutplanDetail==null) { workOrderHead.nowOprSequenceCode = EnumoprSequenceCode.打磨; workOrderHead.nowStationCode = GetStation(EnumoprSequenceCode.打磨); workOrderHead.updateBy = SysUser; workOrderHead.updateTime = DateTime.Now; Context.Updateable(workOrderHead).UpdateColumns(t => new { t.nowOprSequenceCode, t.nowStationCode, t.updateBy, t.updateTime }).AddQueue(); } #endregion } #endregion //打包执行处理 if (ExecuteQueues(Context) > 0) { //给上游完工反馈 CutWeldService cutWeldService = new CutWeldService(); cutPlanDetails.ForEach(x => cutWeldService.SendIWPTechnologylineProcess(x.barCode, (int)EnumCutHeadState.切割完成) ) ; return response; } else { return response.ResponseError($"手动完成套料方案数据库失败!"); } #endregion } } catch (Exception ex) { return response.ResponseError($"手动完成发生异常,原因:{ex.Message}"); } } /// <summary> /// 手动取消套料方案 /// </summary> /// <param name="ID"></param> /// <returns></returns> public dynamic CancelPlan(int ID) { var response = new Response(); try { lock (LockNesting) { #region 手动取消套料方案 //获取套料方案头表 var cutPlanHead = Context.Queryable<bus_cutplan_head>().Where(t => t.id == ID).First(); if (cutPlanHead == null) { return response.ResponseError($"没有套料方案,请核对!"); } if (cutPlanHead.state > (int)EnumCutPlanHeadStatus.初始) { return response.ResponseError($"已经开始执行或执行完成,不能取消!"); } //获取套料方案明细表 var cutPlanDetails = Context.Queryable<bus_cutplan_detail>().Where(t => t.headKeys == cutPlanHead.keys).ToList(); if (cutPlanDetails.Count == 0) { return response.ResponseError($"没有方案明细,请核对!"); } //删除套料方案头 Context.Deleteable<bus_cutplan_head>().Where(t => t.id == ID).AddQueue(); //删除套料方案明细 Context.Deleteable<bus_cutplan_detail>().Where(t => t.headKeys == cutPlanHead.keys).AddQueue(); //获取工单头表 var workOrderHead = cutPlanDetails.Select(x => x.workOrderHeadKeys).ToList().Distinct().ToList(); //把工单改为套料工序 Context.Updateable<bus_workOrder_head>() .SetColumns(t => t.nowOprSequenceCode == EnumoprSequenceCode.套料) .SetColumns(t => t.nowStationCode == GetStation(EnumoprSequenceCode.套料)) .SetColumns(t => t.updateTime == DateTime.Now) .SetColumns(t => t.updateBy == SysUser) .Where(t => workOrderHead.Contains(t.keys)) .AddQueue(); //工单套料工序明细状态改为初始 var workOrderDetails = cutPlanDetails.Select(x => x.workOrderDetailKeys).ToList(); Context.Updateable<bus_workOrder_detail>() .SetColumns(t => t.state == (int)EnumOrderBodyStatus.初始化) .SetColumns(t => t.updateTime == DateTime.Now) .SetColumns(t => t.updateBy == SysUser) .Where(t => workOrderDetails.Contains(t.bodyKeys)) .AddQueue(); //打包执行处理 if (ExecuteQueues(Context) > 0) { //反馈上游套料取消 return response; } else { return response.ResponseError($"手动完成套料方案数据库失败!"); } #endregion } } catch (Exception ex) { return response.ResponseError($"手动取消发生异常,原因:{ex.Message}"); } } #endregion } }