服务端的TigerApi 框架,基于.NET6 2024 版本
Ben Lin
2024-08-20 37fc700892a509346d5be0a1af2d3de1fe8d3a9e
Tiger.Business.MES/Transaction/Position.cs
@@ -55,8 +55,11 @@
        public MES_SHIFT_SYS CurShiftSys { get; set; }
        public WorkBatch CurBatch { get; set; }
        public IWorkBatch WorkBatch => CurBatch;
        public MES_WIP_DATA CurWipSN { get; set; }
        public MES_WIP_HIS CurWipSNHis { get; set; }
        public List<MES_WIP_DATA> CurWipSNs { get; set; } = new();
        public string CurSN => (CurWipSNs.Any() ? (CurWipSNs.First().TRAY_SN.IsNullOrEmpty() ? CurWipSNs.First().SN : CurWipSNs.First().TRAY_SN) : "");
        public List<MES_WIP_HIS> CurWipSNHiss { get; set; } = new();
        public List<MES_WIP_DFT> CurDefects { get; set; } = new();
        public Dictionary<string, object> Context { get; set; } = new();
        public List<WorkStep> Steps { get; set; } = new();
        public WorkStep CurStep { get; set; }
        public List<WorkStep> NextSteps { get; set; } = new();
@@ -64,6 +67,14 @@
        public bool IsFinishAllSteps => !Steps.Any() || !Steps.Any(q => !q.IsFinished);
        //public int CurStep => Steps.Where(q => !q.IsFinished).OrderBy(q => q.Sequence).FirstOrDefault()?.Sequence ?? 0;
        private DbClient CommitDB;
        /// <summary>
        /// 是否需要临时存储数据库提交操作,待需要的时候再提交
        /// </summary>
        public bool NeedTemporaryStoreDBCommitAction { get; set; } = false;
        protected List<Action> DBCommitList { get; set; } = new();
        protected List<Position> NodeCommitList { get; set; } = new();
        protected Dictionary<string, OperInfo> OperInfoDic { get; set; } = new();
        protected OperInfo CurOperInfo { get; set; }
        #endregion Propertys & Variables
        #region Functions
@@ -115,6 +126,11 @@
                    WoContext.WoBatchDic.Add(wb.Batch.BATCH_NO, wb);
                }
                CurBatch = WoContext.GetBatch(input.OrderNo, CurLine.LINE_CODE);
                if (!OperInfoDic.ContainsKey(CurBatch.Batch.BATCH_NO))
                {
                    OperInfoDic.Add(CurBatch.Batch.BATCH_NO, new());
                }
                action.Data = new { WorkOrder = CurBatch.WO, Bacth = CurBatch.Batch };
            }
            catch (Exception ex)
@@ -146,12 +162,49 @@
        }
        /// <summary>
        /// 重置当前工步
        /// 重置工序操作
        /// </summary>
        public void ResetSteps()
        /// <returns></returns>
        public ApiAction Reset()
        {
            var action = new ApiAction();
            ResetNode();
            action.IsSuccessed = true;
            action.LocaleMsg = new($"工序操作已重置,请重新扫描进站产品条码");
            action.LocaleMsg = new("MES.Transaction.Position.ResetNode");
            return action;
        }
        /// <summary>
        /// 重置当前工序,有需要则重写此方法
        /// </summary>
        public virtual void ResetNode()
        {
            Steps.Clear();
            CurWipSN = null;
            CurWipSNs.Clear();
            CurWipSNHiss.Clear();
            CurStep = null;
            CurDefects.Clear();
        }
        /// <summary>
        /// 设置当前条码的工序信息
        /// </summary>
        public OperInfo SetOperNodeInfo(OperInfo info)
        {
            if (CurWipSNs.Any())
            {
                info.CurNode = CurWipSNs.First().NODE_NAME;
                info.NextNode = string.Join(",", CurBatch.GetNextNodes(CurWipSNs.First()).Select(q => q.NODE_NAME));
            }
            else
            {
                info.CurNode = "   —   ";
                info.NextNode = "   —   ";
            }
            return info;
        }
        /// <summary>
@@ -198,12 +251,12 @@
                {
                    var next = new WorkStep(IWorkStep.Types.Action, this)
                    {
                        NodeID = act.ID,
                        Sequence = parent.Sequence + 1,
                        Node = parent.Node,
                        NodeAct = act,
                        Setting = CurBatch.ActionSets.FirstOrDefault(q => q.ACT_ID == act.ID),
                    };
                    next.Init();
                    next.PrepNodeIDs.Add(parent.NodeID);
                    next.PrepNodeIDs.AddRange(parent.PrepNodeIDs);
                    next.PrepNodeIDs = next.PrepNodeIDs.Distinct().ToList();
@@ -233,7 +286,7 @@
                }
            }
            //如果当前工步没有可执行的后续工步,则在前置工步查找还有没有后续工步没完成的工步,有则执行
            if (!result.Any())
            if (!result.Any() && Steps.Any())
            {
                //查找有没有前置工步未完成,若有则先完成未完成的前置工步
                var prepIDs = curStep.PrepNodeIDs.Where(id => CurBatch.Edges.Any(e => e.SRC_NODE == id && Steps.Any(q => !q.IsFinished && e.TGT_NODE == q.NodeID))).ToList();
@@ -262,39 +315,33 @@
        /// <param name="input"></param>
        public ApiAction<SubmitOutput> BeginNextActionStep(SubmitInput input)
        {
            var result = new ApiAction<SubmitOutput>();
            var result = new ApiAction<SubmitOutput>(new SubmitOutput());
            //设置后续可执行的工步列表
            NextSteps = GetNextSteps(CurStep);
            //尝试有没有可以直接开始的后续工步
            foreach (var step in NextSteps)
            {
                //尝试执行后续工步
                var canBegin = step.TryBegin(input);
                //如果后续工步可以直接开始则直接执行
                if (canBegin.IsSuccessed)
                {
                    //更新当前执行工步为已开始工步
                    CurStep = step;
                    //更新后续可执行的工步列表
                    NextSteps = GetNextSteps(CurStep);
                    //返回结果到客户端
                    result = canBegin;
                    result.Data.IsFinished = IsFinishAllSteps;
                    result.Data.CurWO = CurBatch.WO.ORDER_NO;
                    result.Data.CurBatch = CurBatch.Batch.BATCH_NO;
                    result.Data.CurNode = CurStep.NodeAct.ACT_NAME;
                    result.Data.StepActCode = CurStep.NodeAct.ACT_CODE;
                    result.Data.NextStepID = CurStep.ID;
                    result.Data.SetValue(CurBatch, CurStep, CurStep?.ID, IsFinishAllSteps);
                    return result;
                }
            }
            //根据后续工步返回ApiAction
            result.Data.IsFinished = IsFinishAllSteps;
            result.Data.CurWO = CurBatch.WO.ORDER_NO;
            result.Data.CurBatch = CurBatch.Batch.BATCH_NO;
            result.Data.CurNode = CurStep.Node.NODE_NAME;
            result.Data.StepActCode = CurStep.NodeAct.ACT_CODE;
            result.Data.NextStepID = "";
            //没有可以直接开始的后续工步,根据后续工步返回ApiAction
            result.Data.SetValue(CurBatch, CurStep, "", IsFinishAllSteps);
            //根据后续可执行工步列表返回相应的操作提示
            //没有可以直接开始的后续工步,根据后续可执行工步列表返回相应的操作提示
            if (NextSteps.Count == 1)
            {
                result.LocaleMsg = NextSteps.First().GetBeginMsg();
@@ -306,7 +353,184 @@
            }
            return result;
        }
        /// <summary>
        /// 保存工步的数据库提交操作到数据库
        /// </summary>
        protected void SaveStepsCommitActionToDB()
        {
            //保存工步的数据库提交操作到提交操作列表
            foreach (var step in Steps.OrderBy(q => q.Sequence))
            {
                DBCommitList.Add(step.DBSubmitAction);
            }
            //如果不需要临时存储数据库提交操作,则把提交操作列表提交到数据库
            if (!NeedTemporaryStoreDBCommitAction)
            {
                //恢复临时存储标记为false
                NeedTemporaryStoreDBCommitAction = false;
                var dbTran = GetCommitDB().UseTran(() =>
                {
                    //在同一个事务中保存所有工步的数据
                    foreach (var action in DBCommitList)
                    {
                        action.Invoke();
                    }
                });
                if (dbTran.IsSuccess)
                {
                    //保存成功则清空提交操作列表
                    DBCommitList.Clear();
                }
                else
                {
                    //抛出异常
                    throw dbTran.ErrorException;
                }
            }
        }
        protected void DoSaveToDB()
        {
            var dbTran = GetCommitDB().UseTran(() =>
            {
                //在同一个事务中保存所有工步的数据
                foreach (var step in Steps.OrderBy(q => q.Sequence))
                {
                    step.DBSubmitAction.Invoke();
                }
            });
            if (!dbTran.IsSuccess)
            {
                //抛出异常
                throw dbTran.ErrorException;
            }
        }
        /// <summary>
        /// 获取打印标签模板过程变量值
        /// </summary>
        /// <param name="labelPVs">过程变量列表</param>
        /// <param name="label">标签模板</param>
        /// <returns></returns>
        public BAS_LABEL_TEMP SetLabelVariables(List<BAS_LABEL_PV> labelPVs, BAS_LABEL_TEMP label)
        {
            foreach (var item in label.Variables)
            {
                switch (item.VAR_TYPE.GetEnum<BAS_LABEL_VAR.VAR_TYPEs>())
                {
                    case BAS_LABEL_VAR.VAR_TYPEs.Constant:
                        item.Value = item.VAR_VALUE;
                        break;
                    case BAS_LABEL_VAR.VAR_TYPEs.ProcessVariable:
                        item.Value = GetPrintProcessValue(labelPVs, item);
                        break;
                    case BAS_LABEL_VAR.VAR_TYPEs.DateVariable:
                        item.Value = DateTime.Now.ToString(item.VAR_VALUE);
                        break;
                    case BAS_LABEL_VAR.VAR_TYPEs.BarcodeGenerate:
                        item.Value = GetGeneratePValue(labelPVs, item);
                        break;
                    case BAS_LABEL_VAR.VAR_TYPEs.CustomVariable:
                    default:
                        item.Value = "";
                        break;
                }
            }
            return label;
        }
        /// <summary>
        /// 获取打印标签模板过程变量值
        /// </summary>
        /// <param name="labelPVs">过程变量列表</param>
        /// <param name="lv">标签模板变量</param>
        /// <returns></returns>
        public string GetPrintProcessValue(List<BAS_LABEL_PV> labelPVs, BAS_LABEL_VAR lv)
        {
            var pv = labelPVs.FirstOrDefault(q => q.VAR_CODE == lv.VAR_VALUE);
            if (!pv.IsNullOrEmpty())
            {
                switch (pv.VAR_TYPE.GetEnum<BAS_LABEL_PV.VAR_TYPEs>())
                {
                    case BAS_LABEL_PV.VAR_TYPEs.ServerMethod:
                        {
                            switch (pv.VAR_METHOD)
                            {
                                case "GetSN":
                                    return CurSN;
                                case "GetBAS_ITEM":
                                    return WorkBatch.Product.ToJson();
                                case "GetCustomer":
                                    return WorkBatch.Batch.ToJson();
                                case "GetVarByWo":
                                    return GetLabelVarWo(lv);
                                default:
                                    return "";
                            }
                        }
                    case BAS_LABEL_PV.VAR_TYPEs.WebApi:
                        break;
                    case BAS_LABEL_PV.VAR_TYPEs.StoredProcedure:
                        break;
                    default:
                        break;
                }
            }
            return "";
        }
        /// <summary>
        /// 获取根据条码规则生成标签模板的过程变量值
        /// </summary>
        /// <param name="labelPVs"></param>
        /// <param name="lv"></param>
        /// <returns></returns>
        public string GetGeneratePValue(List<BAS_LABEL_PV> labelPVs, BAS_LABEL_VAR lv)
        {
            var pv = labelPVs.FirstOrDefault(q => q.VAR_CODE == lv.VAR_VALUE);
            if (!pv.IsNullOrEmpty())
            {
                switch (pv.VAR_TYPE.GetEnum<BAS_LABEL_PV.VAR_TYPEs>())
                {
                    case BAS_LABEL_PV.VAR_TYPEs.BarcodeGenerate:
                        {
                            switch (pv.VAR_METHOD)
                            {
                                case "GetCartonGenerate":
                                    return Biz.CodeRule[lv.BARCODE_RULE ?? ""]?.Generate($"{WorkBatch.Batch.BATCH_NO}-{WorkBatch.Batch.PLAN_QTY}-").Data.ToString() ?? "";
                                default:
                                    return "";
                            }
                        }
                    default:
                        break;
                }
            }
            return "";
        }
        /// <summary>
        /// 获取工单维护的模板变量
        /// </summary>
        /// <param name="labelId"></param>
        /// <returns></returns>
        private string GetLabelVarWo(BAS_LABEL_VAR lv)
        {
            string result = "";
            var labelVarwos = Biz.Db.Queryable<BAS_LABEL_VAR_WO>().Where(x => x.LABEL_ID == lv.LABEL_ID && x.VAR_NAME == lv.VAR_NAME).ToList();
            if (labelVarwos.Any(q => q.WORK_ORDER == WorkBatch.Batch.ORDER_NO))
            {
                result = labelVarwos.First(q => q.WORK_ORDER == WorkBatch.Batch.ORDER_NO).VAR_VALUE;
            }
            else
            {
                result = labelVarwos.Count > 0 ? labelVarwos[0].DEFAULT_VALUE : "";
            }
            return result;
        }
        #endregion Functions
        public override bool Close(bool needSaveHistoryLog = false)