// <summary> // 一个正在运行中的流程实例 //</summary> // *********************************************************************** using Myshipping.Core; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; namespace Myshipping.FlowCenter.Entity; /// <summary> /// 流程运行类 /// </summary> public class FlowRuntime { /// <summary> /// 构造函数 /// </summary> public FlowRuntime(FlcFlowinstance instance) { var schemeContentJson = instance.SchemeContent.ToObject<Flow>();//获取工作流模板内容的json对象; InitFlow(schemeContentJson); currentNodeId = (string.IsNullOrEmpty(instance.ActivityId)? startNodeId : instance.ActivityId); currentNodeType = GetNodeType(currentNodeId); FrmData = instance.FrmData; previousId = GetPreviousNodeId(currentNodeId); flowInstanceId = instance.Id; //会签开始节点和流程结束节点没有下一步 if (currentNodeType == 0 || currentNodeType == 4) { nextNodeId = "-1"; nextNodeType = -1; } else { nextNodeId = GetNextNodeId();//下一个节点 nextNodeType = GetNodeType(nextNodeId); } } #region 私有方法 /// <summary> /// 获取工作流信息 /// </summary> /// <param name="schemeContentJson"></param> /// <returns></returns> private void InitFlow(Flow schemeContentJson) { flow = schemeContentJson; InitLines(schemeContentJson); InitNodes(schemeContentJson); } /// <summary> /// 获取工作流节点的字典列表:key节点id /// </summary> /// <param name="schemeContentJson"></param> /// <returns></returns> private void InitNodes(Flow schemeContentJson) { Nodes = new Dictionary<string, FlowNode>(); foreach (var item in schemeContentJson.nodeList) { var node = item; if (!Nodes.ContainsKey(node.id)) { Nodes.Add(node.id, node); } if (node.type == FlowNode.START) { this.startNodeId = node.id; } } } private void InitLines(Flow schemeContentJson) { Lines = new List<FlowLine>(); FromNodeLines = new Dictionary<string, List<FlowLine>>(); ToNodeLines = new Dictionary<string, List<FlowLine>>(); foreach (var item in schemeContentJson.linkList) { var line = item; Lines.Add(line); if (!FromNodeLines.ContainsKey(line.sourceId)) { List<FlowLine> d = new List<FlowLine> { line }; FromNodeLines.Add(line.sourceId, d); } else { FromNodeLines[line.sourceId].Add(line); } if (!ToNodeLines.ContainsKey(line.targetId)) { List<FlowLine> d = new List<FlowLine> { line }; ToNodeLines.Add(line.targetId, d); } else { ToNodeLines[line.targetId].Add(line); } } } /// <summary> /// 获取下一个节点 /// </summary> private string GetNextNodeId(string nodeId = null) { var lines = nodeId == null ? FromNodeLines[currentNodeId] : FromNodeLines[nodeId]; if (lines.Count == 0) { throw new Exception("无法寻找到下一个节点"); } if (string.IsNullOrEmpty(FrmData)) return lines[0].targetId; FrmData = FrmData.ToLower();//统一转小写 var frmDataJson = FrmData.ToJObject();//获取数据内容 foreach (var l in lines) { if (l.Compares==null) { l.Compares = new List<DataCompare>(); } if (l.Compares.Count>0 &&l.Compare(frmDataJson)) { return l.targetId; } } return lines[0].targetId; } /// <summary> /// 获取上一个节点 /// </summary> private string GetPreviousNodeId(string nodeId = null) { try { var lines = nodeId == null ? ToNodeLines[currentNodeId] : ToNodeLines[nodeId]; if (lines.Count == 0) { return string.Empty; } if (FrmData == "") return lines[0].sourceId; FrmData = FrmData.ToLower();//统一转小写 var frmDataJson = FrmData.ToJObject();//获取数据内容 foreach (var l in lines) { if (l.Compares == null) { l.Compares = new List<DataCompare>(); } if (l.Compares.Count > 0 && l.Compare(frmDataJson)) { return l.sourceId; } } return lines[0].sourceId; } catch (Exception) { return string.Empty; } } #endregion 私有方法 #region 共有方法 /// <summary> /// 获取下一个节点 /// </summary> /// <param name="nodeId"></param> /// <returns></returns> public FlowNode GetNextNode(string nodeId = null) { return Nodes[GetNextNodeId(nodeId)]; } /// <summary> /// 获取实例接下来运行的状态 /// </summary> /// <returns>-1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束</returns> public int GetNextNodeType() { if (nextNodeId != "-1") { return GetNodeType(nextNodeId); } return -1; } /// <summary> /// 获取节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束 /// </summary> /// <param name="nodeId"></param> /// <returns></returns> public int GetNodeType(string nodeId) { switch (Nodes[nodeId].type) { //会签开始节点 case FlowNode.FORK: return 0; //会签结束节点 case FlowNode.JOIN: return 1; //结束节点 case FlowNode.END: return 4; //开始节点 case FlowNode.START: return 3; default: return 2; } } /// <summary> /// 删除节点 /// </summary> /// <param name="nodeId"></param> public void RemoveNode(string nodeId) { var node = Nodes[nodeId]; if (node != null && node.setInfo != null) { node.setInfo.Taged = null; node.setInfo.UserName = null; node.setInfo.UserId = null; node.setInfo.Description = null; node.setInfo.TagedTime = null; } } /// <summary> /// 删除全部节点 /// </summary> public void RemoveNodes() { foreach (var item in Nodes) { var node = item.Value; if (node != null && node.setInfo != null) { node.setInfo.Taged = null; node.setInfo.UserName = null; node.setInfo.UserId = null; node.setInfo.Description = null; node.setInfo.TagedTime = null; } } } /// <summary> /// 节点会签审核 /// </summary> /// <param name="nodeId">会签时,currentNodeId是会签开始节点。这个表示当前正在处理的节点</param> /// <param name="tag"></param> /// <returns>-1不通过,1等待,其它通过</returns> public string NodeConfluence(string nodeId, Tag tag) { var forkNode = Nodes[currentNodeId]; //会签开始节点 FlowNode nextNode = GetNextNode(nodeId); //获取当前处理的下一个节点 int forkNumber = FromNodeLines[currentNodeId].Count; //直接与会签节点连接的点,即会签分支数目 string res =string.Empty; //记录会签的结果,默认正在会签 if (forkNode.setInfo.NodeConfluenceType == "one") //有一个步骤通过即可 { if (tag.Taged == (int) TagState.Ok) { if (nextNode.type == FlowNode.JOIN) //下一个节点是会签结束,则该线路结束 { res = GetNextNodeId(nextNode.id); } } else if(tag.Taged ==(int) TagState.No) { if (forkNode.setInfo.ConfluenceNo == null) { forkNode.setInfo.ConfluenceNo = 1; } else if (forkNode.setInfo.ConfluenceNo == (forkNumber - 1)) { res = TagState.No.ToString("D"); } else { bool isFirst = true; //是不是从会签开始到现在第一个 var preNode = GetPreNode(nodeId); while (preNode.id != forkNode.id) //反向一直到会签开始节点 { if (preNode.setInfo != null && preNode.setInfo.Taged == (int) TagState.No) { isFirst = false; break; } } if (isFirst) { forkNode.setInfo.ConfluenceNo++; } } } } else //默认所有步骤通过 { if (tag.Taged == (int) TagState.No) //只要有一个不同意,那么流程就结束 { res = TagState.No.ToString("D"); } else if(tag.Taged == (int)TagState.Ok) { if (nextNode.type == FlowNode.JOIN) //这种模式下只有坚持到【会签结束】节点之前才有意义,是否需要判定这条线所有的节点都通过,不然直接执行这个节点?? { if (forkNode.setInfo.ConfluenceOk == null) { forkNode.setInfo.ConfluenceOk = 1; } else if (forkNode.setInfo.ConfluenceOk == (forkNumber - 1)) //会签成功 { res = GetNextNodeId(nextNode.id); } else { forkNode.setInfo.ConfluenceOk++; } } } } if (res == TagState.No.ToString("D")) { tag.Taged = (int) TagState.No; MakeTagNode(nextNode.id, tag); } else if (!string.IsNullOrEmpty(res)) //会签结束,标记合流节点 { tag.Taged = (int) TagState.Ok; MakeTagNode(nextNode.id, tag); nextNodeId = res; nextNodeType = GetNodeType(res); } else { nextNodeId = nextNode.id; nextNodeType = GetNodeType(nextNode.id); } return res; } /// <summary> /// 获取上一个节点 /// </summary> /// <param name="nodeId"></param> /// <returns></returns> /// <exception cref="Exception"></exception> private FlowNode GetPreNode(string nodeId = null) { var lines = nodeId == null ? ToNodeLines[currentNodeId] : ToNodeLines[nodeId]; if (lines.Count == 0) { throw new Exception("无法找到上一个点"); } return Nodes[lines[0].sourceId]; } /// <summary> /// 驳回 /// </summary> /// <param name="rejectType">驳回类型。null:使用节点配置的驳回类型/0:前一步/1:第一步/2:指定节点,使用NodeRejectStep</param> /// <returns></returns> public string RejectNode(string rejectType) { dynamic node = Nodes[currentNodeId]; if (node.setInfo != null && string.IsNullOrEmpty(rejectType)) { rejectType = node.setInfo.NodeRejectType; } if (rejectType == "0") { return previousId; } if (rejectType == "1") { return startNodeId; } return previousId; } ///<summary> /// 标记节点1通过,2不通过,3驳回 /// </summary> /// <param name="nodeId"></param> public void MakeTagNode(string nodeId, Tag tag) { foreach (var item in Nodes) { if (item.Key == nodeId) { if (item.Value.setInfo == null) { item.Value.setInfo = new Setinfo(); } item.Value.setInfo.Taged = tag.Taged; item.Value.setInfo.UserId = tag.UserId; item.Value.setInfo.UserName = tag.UserName; item.Value.setInfo.Description = tag.Description; item.Value.setInfo.TagedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm"); break; } } } /// <summary> /// 获取流程 /// </summary> /// <returns></returns> public Flow ToSchemeObj() { flow.linkList = Lines; flow.nodeList = Nodes.Select(u => u.Value).ToList(); return flow; } /// <summary> /// 通知三方系统,节点执行情况 /// </summary> public void NotifyThirdParty(HttpClient client, Tag tag) { if (currentNode.setInfo == null || string.IsNullOrEmpty(currentNode.setInfo.ThirdPartyUrl)) { return; } var postData = new { flowInstanceId, nodeName=currentNode.name, nodeId = currentNodeId, userId = tag.UserId, userName = tag.UserName, result=tag.Taged, //1:通过;2:不通过;3驳回 description = tag.Description, execTime = tag.TagedTime, isFinish = currentNodeType == 4 }; HttpContent httpContent = new StringContent(postData.ToJsonString(), Encoding.UTF8); httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); client.PostAsync(currentNode.setInfo.ThirdPartyUrl, httpContent); } #endregion 共有方法 #region 属性 /// <summary> /// 流程 /// </summary> public Flow flow { get; set; } /// <summary> /// 运行实例的Id /// </summary> public long flowInstanceId { get; set; } /// <summary> /// 开始节点的ID /// </summary> public string startNodeId { get; set; } /// <summary> /// 当前节点的ID /// </summary> public string currentNodeId { get; set; } /// <summary> /// 当前节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束 /// </summary> public int currentNodeType { get; set; } /// <summary> /// 当前节点的对象 /// </summary> public FlowNode currentNode => Nodes[currentNodeId]; /// <summary> /// 下一个节点 /// </summary> public string nextNodeId { get; set; } /// <summary> /// 下一个节点类型 -1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束 /// </summary> /// <value>The type of the next node.</value> public int nextNodeType { get; set; } /// <summary> /// 下一个节点对象 /// </summary> public FlowNode nextNode => Nodes[nextNodeId]; /// <summary> /// 上一个节点 /// </summary> public string previousId { get; set; } /// <summary> /// 实例节点集合 /// </summary> public Dictionary<string, FlowNode> Nodes { get; set; } /// <summary> /// 流程实例中所有的线段 /// </summary> public List<FlowLine> Lines { get; set; } /// <summary> /// 从节点发出的线段集合 /// </summary> public Dictionary<string, List<FlowLine>> FromNodeLines { get; set; } /// <summary> /// 到达节点的线段集合 /// </summary> public Dictionary<string, List<FlowLine>> ToNodeLines { get; set; } /// <summary> /// 表单数据 /// </summary> public string FrmData { get; set; } #endregion 属性 }