using DS.Module.Core.Extensions; using DS.Module.UserModule; using DS.WMS.Core.Flow.Dtos; using DS.WMS.Core.Flow.Entity; using Mapster; using Newtonsoft.Json; using SqlSugar; namespace DS.WMS.Core.Flow.Method; /// /// /// public class FlowRuntime { public FlowRuntime(FlowInstance instance, ISqlSugarClient _db) : this(instance, _db, null, null) { } /// /// 构造函数 /// public FlowRuntime(FlowInstance instance, ISqlSugarClient _db, ISqlSugarClient tenantDb, IUser user) { db = _db; BusinessId = instance.BusinessId; ColumnView = instance.ColumnView; this.tenantDb = tenantDb; this.user = user; InitNodes(instance.Content); //获取工作流模板内容的json对象; CurrentNodeId = instance.ActivityId == "" ? StartNodeId : instance.ActivityId; CurrentNodeType = GetNodeType(CurrentNodeId); PreviousId = instance.PreviousId; FlowInstanceId = instance.Id; //会签开始节点和流程结束节点没有下一步 if (CurrentNodeType == 0 || CurrentNodeType == 4) { NextNodeId = "-1"; NextNodeType = -1; } else if (CurrentNodeType == 5) { NextNodeId = GetNextConditionNodeId(CurrentNode); //下一个节点 NextNodeType = GetNodeType(NextNodeId); } else { NextNodeId = GetNextNodeId(CurrentNodeId); //下一个节点 NextNodeType = GetNodeType(NextNodeId); } } public long BusinessId { get; set; } public string ColumnView { get; set; } ISqlSugarClient db { get; set; } ISqlSugarClient tenantDb { get; set; } IUser user { get; set; } /// /// 运行实例的Id /// public long FlowInstanceId { get; set; } /// /// 开始节点的ID /// public string StartNodeId { get; set; } /// /// 当前节点的ID /// public string CurrentNodeId { get; set; } /// /// 当前节点类型 0会签开始,1会签结束,2一般节点,开始节点,4流程运行结束 /// public int CurrentNodeType { get; set; } /// /// 当前节点的对象 /// public FlowChild CurrentNode => ChildNodes.First(x => x.Id == CurrentNodeId); /// /// 下一个节点 /// public string NextNodeId { get; set; } /// /// 下一个节点类型 -1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束,5同级审批 /// public int NextNodeType { get; set; } /// /// 下一个节点对象 /// public FlowChild? NextNode => NextNodeId != "-1" ? ChildNodes.First(x => x.Id == NextNodeId) : null; /// /// 上一个节点 /// public string PreviousId { get; set; } /// /// 实例节点集合 /// public List ChildNodes { get; set; } public string? Note { get; set; } /// /// 获取工作流节点的字典列表:key节点id /// /// /// private void InitNodes(string schemeContentJson) { ChildNodes = new List(); var root = JsonConvert.DeserializeObject(schemeContentJson); if (root.Type == FlowChild.START) { StartNodeId = root.Id; } if (root.Child.IsNotNull()) { var parent = root.Adapt(); ChildNodes.Add(parent); GetFlowChildsByParent(parent.Id, parent); } } /// /// 撤销流程,清空所有节点 /// public void Cancel() { foreach (var item in ChildNodes) { item.SetInfo = null; } } private void GetFlowChildsByParent(string nodeId, FlowChild parent) { if (parent.Type == FlowChild.Exclusive && parent.Children.IsNotNull() && parent.Children.Count > 0) { foreach (var item in parent.Children) { ChildNodes.Add(item); GetFlowChildsByParent(nodeId, item); } } if (parent.Child.IsNotNull()) { ChildNodes.Add(parent.Child); GetFlowChildsByParent(parent.Child.Id, parent.Child); } // var childs = new List(); } private List GetFlowConditions(FlowChild parent) { var conditionNodes = new List(); if (parent.Children != null) { foreach (var item in parent.Children) { conditionNodes.Add(item); } } return conditionNodes; } /// /// 获取下一个节点 /// /// private string GetNextNodeId(string nodeId = null) { if (nodeId == null) { return ChildNodes.Where(x => x.Pid == "root").First().Id; } else { if (ChildNodes.Exists(x => x.Pid == nodeId)) { var nextChild = ChildNodes.Where(x => x.Pid == nodeId).First(); if (nextChild.Type == FlowChild.Exclusive) //互斥条件 { return GetNextConditionNodeId(nextChild); //下一个节点 } else { return nextChild.Id; } } else { return ChildNodes.Where(x => x.Id == "end").First().Id; } // return ChildNodes.Where(x => x.Pid == nodeId).First().Id; } } /// /// 获取下一个条件节点 /// /// /// public string GetNextConditionNodeId(FlowChild parent) { var conditionNodes = GetFlowConditions(parent); var conditionId = string.Empty; for (int i = 0; i < conditionNodes.Count; i++) { if (i == conditionNodes.Count - 1) { // return ChildNodes.Where(x => x.Pid == conditionNodes[i].Id).First().Id; conditionId = conditionNodes[i].Id; } else { var nodeSection = conditionNodes[i].Conditions; var list = new List(); var conditionList = new List>(nodeSection.Conditions.Count); var whereType = Enum.Parse(nodeSection.LogicalOperator, true); foreach (var item in nodeSection.Conditions) { conditionList.Add(new KeyValuePair (whereType, new ConditionalModel { FieldName = item.Field, ConditionalType = GetConditionalType(item.Operator), FieldValue = item.Value }) ); } if (conditionList.Count > 0) { list.Add(new ConditionalCollections { ConditionalList = conditionList }); } var groupList = new List>(); foreach (var group in nodeSection.Groups) { WhereType whereType2 = Enum.Parse(group.LogicalOperator, true); for (int j = 0; j < group.Conditions.Count; j++) { var item1 = group.Conditions[j]; groupList.Add(new KeyValuePair (j == 0 ? whereType : whereType2, new ConditionalModel { FieldName = item1.Field, ConditionalType = GetConditionalType(item1.Operator), FieldValue = item1.Value }) ); } } if (groupList.Count > 0) { list.Add(new ConditionalCollections { ConditionalList = groupList }); } if (list.Count == 0) //跳过默认条件 continue; //string json = JsonConvert.SerializeObject(list); //db.Utilities.JsonToConditionalModels(json); List conditionalModels = [.. list]; ISqlSugarClient sugarClient = tenantDb ?? db; var exists = sugarClient.Queryable().AS(ColumnView).Where("Id=@Id", new { Id = BusinessId }).Where(conditionalModels).Any(); if (exists) { conditionId = conditionNodes[i].Id; break; } } } return ChildNodes.Where(x => x.Pid == conditionId).FirstOrDefault()?.Id; } /// /// 获取下一个节点 /// /// /// public FlowChild GetNextNode(string? nodeId = null) { if (nodeId == null) return ChildNodes.Where(x => x.Pid == "root").First(); if (ChildNodes.Exists(x => x.Pid == nodeId)) { var nextChild = ChildNodes.Where(x => x.Pid == nodeId).First(); if (nextChild.Type == FlowChild.Exclusive) { var childId = GetNextConditionNodeId(nextChild); return ChildNodes.Where(x => x.Id == childId).First(); //下一个节点 } //todo:前端组织JSON结构有误,加入临时修复代码,待前端改正后移除 else if (nextChild.Type == null) { nextChild.Id = nextChild.Type = FlowChild.END; nextChild.Name = "结束"; Note = "JSON结构有误,检测到没有指定类型的节点"; return nextChild; } return nextChild; } else { return ChildNodes.Where(x => x.Id == "end").First(); } } /// /// 转换FlowRoot /// /// public FlowRoot ToFlowRoot() { var root = ChildNodes.First(x => x.Id == "root"); var list = ChildNodes.Where(x => x.Id != "root").ToList(); var info = root.Adapt(); info.Child = list.First(x => x.Pid == "root"); UpdateChild(info.Child); return info; } private void UpdateChild(FlowChild parent) { if (parent.Type == FlowChild.Exclusive) { if (ChildNodes.Exists(x => x.Pid == parent.Id && x.Type != "condition")) { var child = ChildNodes.Where(x => x.Pid == parent.Id && x.Type != "condition").First(); parent.Child = child; UpdateChild(child); } var childs = ChildNodes.Where(x => x.Pid == parent.Id && x.Type == "condition").ToList(); parent.Children = childs; foreach (var item in childs) { UpdateChild(item); } } else if (parent.Type != FlowChild.Exclusive && ChildNodes.Exists(x => x.Pid == parent.Id)) { var child = ChildNodes.Where(x => x.Pid == parent.Id).First(); parent.Child = child; UpdateChild(parent.Child); } } private void UpdateFlowChild(string nodeId, FlowChild parent) { // var childs = new List(); if (parent.Type == FlowChild.Exclusive && parent.Children.IsNotNull() && parent.Children.Count > 0) { for (int i = 0; i < parent.Children.Count; i++) { if (parent.Children[0].Id == nodeId) { var newNode = ChildNodes.First(x => x.Id == nodeId); parent.Children[0] = newNode; } } } if (parent.Child.IsNotNull()) { if (parent.Child.Id == nodeId) { var newNode = ChildNodes.First(x => x.Id == nodeId); parent.Child = newNode; } } } /// /// 获取实例接下来运行的状态 /// /// -1无法运行,0开始,1结束,2一般节点,4流程运行结束 public int GetNextNodeType() { if (NextNodeId != "-1") { return GetNodeType(NextNodeId); } return -1; } /// /// 转换SqlSugar 条件操作符 /// /// /// private static ConditionalType GetConditionalType(string conditionalType) { switch (conditionalType) { //等于 case "equal": return ConditionalType.Equal; //不等于 case "not_equal": return ConditionalType.NoEqual; //大于 case "GreaterThan": return ConditionalType.GreaterThan; //大于等于 case "GreaterThanOrEqual": return ConditionalType.GreaterThanOrEqual; //小于 case "LessThan": return ConditionalType.LessThan; //小于等于 case "LessThanOrEqual": return ConditionalType.GreaterThanOrEqual; //包含 case "contains": return ConditionalType.In; //不包含 case "not_contain": return ConditionalType.NotIn; //默认 default: return ConditionalType.Equal; } } /// /// 获取节点类型 0会签开始,1会签结束,2一般节点,3开始节点,4流程运行结束 /// /// /// public int GetNodeType(string nodeId) { switch (ChildNodes.Where(x => x.Id == nodeId).First().Type) { //会签开始节点 case FlowChild.Approval: return 0; //会签结束节点 case FlowChild.JOIN: return 1; //结束节点 case FlowChild.END: return 4; //开始节点 case FlowChild.START: return 3; //互斥条件 case FlowChild.Exclusive: return 5; //一般节点 default: return 2; } } //获取上一个节点 private FlowChild GetPreNode(string nodeId = null) { var child = ChildNodes.Where(x => x.Pid == nodeId).First(); if (child.IsNull()) { throw new Exception("无法找到上一个点"); } return child; } /// /// 驳回 /// /// 驳回类型。null:使用节点配置的驳回类型/0:前一步/1:第一步/2:指定节点,使用NodeRejectStep /// public string RejectNode(string rejectType) { var node = ChildNodes.Where(x => x.Id == CurrentNodeId).First(); if (node.SetInfo != null && string.IsNullOrEmpty(rejectType)) { rejectType = node.SetInfo.NodeRejectType; } if (rejectType == "0") { return PreviousId; } if (rejectType == "1") { return GetNextNodeId(StartNodeId); } return PreviousId; } /// /// 标记节点 1通过,2不通过,3驳回 /// /// public void MakeTagNode(string nodeId, FlowTag tag) { // var node = ChildNodes.First(x => x.Id == nodeId); foreach (var item in ChildNodes) { if (item.Id == nodeId) { if (item.SetInfo == null) { item.SetInfo = new Setinfo(); } item.SetInfo.Taged = tag.Taged; item.SetInfo.UserId = tag.UserId; item.SetInfo.UserName = tag.UserName; item.SetInfo.Description = tag.Description; item.SetInfo.TagedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm"); break; } } } /// /// 节点审核 /// /// 会签时,currentNodeId是会签开始节点。这个表示当前正在处理的节点 /// 节点标签 /// -1不通过,1等待,其它通过 public string NodeConfluence(string nodeId, FlowTag tag) { var forkNode = ChildNodes.First(x => x.Id == CurrentNodeId); //会签开始节点 FlowChild nextNode = GetNextNode(nodeId); //获取当前处理的下一个节点 int forkNumber = 0; if (forkNode.AssigneeType == "user") { forkNumber = forkNode.Users.Count; } else if (forkNode.AssigneeType == "role") { forkNumber = forkNode.Roles.Count; } else { forkNumber = 0; } // int forkNumber = FromNodeLines[currentNodeId].Count; //直接与会签节点连接的点,即会签分支数目 string res = string.Empty; //记录会签的结果,默认正在会签 //或签 if (forkNode.Multi == "single") //有一个步骤通过即可 { if (tag.Taged == (int)TagState.Ok) { res = nextNode.Id; } else if (tag.Taged == (int)TagState.No) { if (forkNode.SetInfo.ConfluenceNo == null) { forkNode.SetInfo.ConfluenceNo = 1; if (forkNode.SetInfo.ConfluenceNo == forkNumber) { res = TagState.No.ToString("D"); } } else if (forkNode.SetInfo.ConfluenceNo == (forkNumber - 1)) { res = TagState.No.ToString("D"); } else { forkNode.SetInfo.ConfluenceNo++; // 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 (forkNode.SetInfo.ConfluenceOk == null) { forkNode.SetInfo.ConfluenceOk = 1; if (forkNode.SetInfo.ConfluenceOk == forkNumber) { res = nextNode.Id; } else { //同一节点的会签,未达到所有审核人同意时,节点类型设置为5 NextNodeType = 5; res = nodeId; return res; } } else { forkNode.SetInfo.ConfluenceOk++; if (forkNode.SetInfo.ConfluenceOk == forkNumber) //会签成功 { res = nextNode.Id; } else { //同一节点的会签,未达到所有审核人同意时,节点类型设置为5 NextNodeType = 5; res = nodeId; return res; } } } } if (res == TagState.No.ToString("D")) { tag.Taged = (int)TagState.No; MakeTagNode(nextNode.Id, tag); NextNodeId = nextNode.Id; NextNodeType = GetNodeType(nextNode.Id); } 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; } internal string GetOtherUsers(FlowTag tag) { var forkNode = ChildNodes.First(x => x.Id == CurrentNodeId); //int index = forkNode.Users.IndexOf(tag.UserId); //if (index > -1 && index <= forkNode.Users.Count - 2) // return forkNode.Users[index + 1]; if (!forkNode.Users.IsNullOrEmpty()) { return string.Join(',', forkNode.Users.Except([tag.UserId])); } return string.Empty; } }