/// <summary>
        /// 送审
        /// </summary>
        /// <typeparam name="T">送审的单据信息类型</typeparam>
        /// <param name="wfInstanceId">流程实例id</param>
        /// <param name="nodeInstanceId">当前操作节点id</param>
        /// <param name="bussiness">送审的单据</param>
        /// <param name="opinions">意见</param>
        /// <returns></returns>
        public async Task <bool> Send <T>(Guid wfInstanceId, Guid nodeInstanceId, T bussiness, string opinions, string userName, Dictionary <Guid, Tuple <Guid, string> > nextNodeUserConfig)
        {
            var wf = GetWFInstanceById(wfInstanceId);

            if (wf == null)
            {
                return(false);
            }

            //找出节点,找出输出线,计算输出
            var curNode = wf.Nodes.FirstOrDefault(p => p.NodeDefine.Id == nodeInstanceId);

            if (curNode == null)
            {
                return(false);
            }

            if (curNode.State == WFState.WaitSend ||
                curNode.State == WFState.BeBackSent)
            {
                //找出当前节点,更改状态记录日志
                curNode.State = WFState.Sent;
                if (curNode.NodeLogs == null)
                {
                    curNode.NodeLogs = new List <NodeActionLog>();
                }

                curNode.NodeLogs.Add(new NodeActionLog()
                {
                    Action      = WFOperation.Send,
                    OperateTime = TimeHelper.GetTimeStamp(),
                    Opinions    = opinions,
                    UserName    = userName
                });

                //计算输出条件
                var outlines = curNode.OutLines;

                if (outlines == null || outlines.Count == 0)
                {
                    throw new Exception("下一节点未正确配置,请联系管理员!");
                }

                foreach (var item in outlines)
                {
                    //todo:扩充权限字段
                    var state = await judger.Predicte(item.ConditionFuncStr, bussiness);

                    if (state)
                    {
                        //判断下一节点是否为ConditionNode,如果是,则进行多条件计算判断操作
                        //如果不是,则直接更改下一节点状态
                        var nextNode = wf.Nodes.FirstOrDefault(p => p.WFNodeId == item.ENodeId);

                        if (nextNode.NodeDefine.NodeType == NodeType.Condition)
                        {
                            var nextOutLines = nextNode.OutLines;
                            if (nextOutLines == null || nextOutLines.Count == 0)
                            {
                                throw new Exception("下一节点未正确配置,请联系管理员!");
                            }

                            //查找该分流聚合节点所有入线的起始节点是否已完成审核,如果完成,则加入到已完成线的集合

                            var finishedInLines = new List <long>();
                            finishedInLines.Add(item.NodeCode);

                            nextNode.InLines.ForEach(line =>
                            {
                                if (wf.Nodes.FirstOrDefault(p => p.WFNodeId == line.SNodeId).State == WFState.Sent)
                                {
                                    finishedInLines.Add(line.NodeCode);
                                }
                            });

                            finishedInLines = finishedInLines.Distinct().ToList();

                            foreach (var line in nextOutLines)
                            {
                                if (await judger.Predicte(line.ConditionFuncStr, bussiness, finishedInLines))
                                {
                                    var nextAuditNode = wf.Nodes.FirstOrDefault(p => p.WFNodeId == line.ENodeId);
                                    nextAuditNode.State = WFState.WaitSend;
                                    nextAuditNode.BId   = wf.BId;
                                    nextAuditNode.BType = wf.BType;
                                    //说明此节点没有配置审核人员
                                    if (nextAuditNode.UserId == null || nextAuditNode.UserId == new Guid())
                                    {
                                        if (!nextNodeUserConfig.ContainsKey(nextAuditNode.Id))
                                        {
                                            throw new Exception("下一节点未配置审核人员,请配置");
                                        }
                                        else
                                        {
                                            nextAuditNode.UserId   = nextNodeUserConfig[nextAuditNode.Id].Item1;
                                            nextAuditNode.UserName = nextNodeUserConfig[nextAuditNode.Id].Item2;
                                        }
                                    }
                                    else
                                    {
                                        //如果先前配置了,但是配置错了,后面需要更改
                                        if (string.IsNullOrWhiteSpace(nextAuditNode.NodeDefine.UserId))
                                        {
                                            if (nextNodeUserConfig.ContainsKey(nextAuditNode.Id))
                                            {
                                                nextAuditNode.UserId   = nextNodeUserConfig[nextAuditNode.Id].Item1;
                                                nextAuditNode.UserName = nextNodeUserConfig[nextAuditNode.Id].Item2;
                                            }
                                        }
                                        else
                                        {
                                            //说明模板配置过的,则不允许更改
                                        }
                                    }
                                }
                            }
                        }
                        else if (nextNode.NodeDefine.NodeType == NodeType.Audit)
                        {
                            if (nextNode.UserId == null || nextNode.UserId == new Guid())
                            {
                                if (!nextNodeUserConfig.ContainsKey(nextNode.Id))
                                {
                                    throw new Exception("下一节点未配置审核人员,请配置");
                                }
                                else
                                {
                                    nextNode.UserId   = nextNodeUserConfig[nextNode.Id].Item1;
                                    nextNode.UserName = nextNodeUserConfig[nextNode.Id].Item2;
                                }
                            }
                            else
                            {
                                //如果先前配置了,但是配置错了,后面需要更改
                                if (string.IsNullOrWhiteSpace(nextNode.NodeDefine.UserId))
                                {
                                    if (nextNodeUserConfig.ContainsKey(nextNode.Id))
                                    {
                                        nextNode.UserId   = nextNodeUserConfig[nextNode.Id].Item1;
                                        nextNode.UserName = nextNodeUserConfig[nextNode.Id].Item2;
                                    }
                                }
                                else
                                {
                                    //说明模板配置过的,则不允许更改
                                }
                            }

                            nextNode.State = WFState.WaitSend;
                            if (nextNode.NodeLogs == null)
                            {
                                nextNode.NodeLogs = new List <NodeActionLog>();
                            }
                        }
                        else if (nextNode.NodeDefine.NodeType == NodeType.End)
                        {
                            nextNode.State = WFState.Completed;
                            //所有有日志的节点上,状态都更改为已完成
                            wf.Nodes.ForEach(p =>
                            {
                                if (p.NodeLogs != null && p.NodeLogs.Count > 0)
                                {
                                    p.State = WFState.Completed;
                                }
                            });
                        }
                    }
                }
            }
            else
            {
                return(false);
            }

            //更新流程到流程池,到数据库
            //只有节点信息需要更新

            for (int i = 0; i < wf.Nodes.Count; i++)
            {
                var node = mapper.Map <WFNodeInstance>(wf.Nodes[i]);
                node        = wFContext.WFNodeInstance.Add(node).Entity;
                wf.Nodes[i] = mapper.Map(node, wf.Nodes[i]);
            }

            WFInstanceViewModel oldWF;

            if (!iWFPool.WFs.TryRemove(wf.Id, out oldWF))
            {
                return(false);
            }
            else
            {
                if (!iWFPool.WFs.TryAdd(wf.Id, wf))
                {
                    return(false);
                }
            }

            wFContext.BulkSaveChanges();

            return(true);
        }
        /// <summary>
        /// 新增或者修改
        ///
        /// 流程图设计过程中,Node的Id由设计器产生。也就是说Node更新步骤是检查数据库是否有该id,如果有则更新,没有则新增
        ///
        /// </summary>
        /// <param name="wFTemplateViewModel"></param>
        /// <returns></returns>
        public WFTemplateViewModel AddOrUpdate(WFTemplateViewModel wFTemplateViewModel)
        {
            try
            {
                if (wFTemplateViewModel.Id == new Guid())
                {
                    //新增
                    wFTemplateViewModel.CreateTime = TimeHelper.GetTimeStamp();
                    var model = wFContext.WFTemplate.Add(mapper.Map <WFTemplate>(wFTemplateViewModel));

                    wFTemplateViewModel = mapper.Map(model.Entity, wFTemplateViewModel);
                }
                else
                {
                    wFTemplateViewModel.UpdateTime = TimeHelper.GetTimeStamp();
                    var model = wFContext.WFTemplate.Update(mapper.Map <WFTemplate>(wFTemplateViewModel));

                    wFTemplateViewModel = mapper.Map(model.Entity, wFTemplateViewModel);
                }

                //先删除掉所有节点
                wFContext.WFNode.Where(p => p.WFId == wFTemplateViewModel.Id).Delete();
                if (wFTemplateViewModel.Nodes != null)
                {
                    //然后新增所有节点
                    for (int i = 0; i < wFTemplateViewModel.Nodes.Count; i++)
                    {
                        wFTemplateViewModel.Nodes[i].WFId = wFTemplateViewModel.Id;
                        var item = mapper.Map <WFNodeViewModel, WFNode>(wFTemplateViewModel.Nodes[i]);
                        item.Id = new Guid();
                        var model = wFContext.WFNode.Add(item);

                        wFTemplateViewModel.Nodes[i] = mapper.Map(model.Entity, wFTemplateViewModel.Nodes[i]);
                    }
                }

                wFContext.WFLine.Where(p => p.WFId == wFTemplateViewModel.Id).Delete();

                if (wFTemplateViewModel.Lines != null)
                {
                    for (int i = 0; i < wFTemplateViewModel.Lines.Count; i++)
                    {
                        wFTemplateViewModel.Lines[i].WFId = wFTemplateViewModel.Id;
                        var item = mapper.Map <WFLine>(wFTemplateViewModel.Lines[i]);
                        item.LineId = wFTemplateViewModel.Lines[i].LineDefine.Id;
                        item.Id     = new Guid();
                        var model = wFContext.WFLine.Add(item);

                        wFTemplateViewModel.Lines[i] = mapper.Map(model.Entity, wFTemplateViewModel.Lines[i]);
                    }
                }

                wFContext.WFToolTip.Where(p => p.WFId == wFTemplateViewModel.Id).Delete();

                if (wFTemplateViewModel.ToolTips != null)
                {
                    for (int i = 0; i < wFTemplateViewModel.ToolTips.Count; i++)
                    {
                        wFTemplateViewModel.ToolTips[i].WFId  = wFTemplateViewModel.Id;
                        wFTemplateViewModel.ToolTips[i].TipId = wFTemplateViewModel.ToolTips[i].Id;
                        wFTemplateViewModel.ToolTips[i].Id    = new Guid();
                        var model = wFContext.WFToolTip.Add(wFTemplateViewModel.ToolTips[i]);
                    }
                }
                wFContext.BulkSaveChanges();
                return(wFTemplateViewModel);
            }
            catch (Exception ex)
            {
            }

            return(null);
        }