You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

798 lines
26 KiB
C#

11 months ago
using DS.Module.Core.Extensions;
7 months ago
using DS.Module.UserModule;
11 months ago
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Flow.Entity;
using Mapster;
using Newtonsoft.Json;
using SqlSugar;
11 months ago
namespace DS.WMS.Core.Flow.Method;
/// <summary>
///
/// </summary>
public class FlowRuntime
11 months ago
{
public FlowRuntime(FlowInstance instance, ISqlSugarClient _db) : this(instance, _db, null, null)
7 months ago
{
}
11 months ago
/// <summary>
/// 构造函数
/// </summary>
public FlowRuntime(FlowInstance instance, ISqlSugarClient _db, ISqlSugarClient tenantDb, IUser user)
{
db = _db;
BusinessId = instance.BusinessId;
ColumnView = instance.ColumnView;
this.tenantDb = tenantDb;
7 months ago
this.user = user;
InitNodes(instance.Content); //获取工作流模板内容的json对象;
11 months ago
CurrentNodeId = instance.ActivityId == "" ? StartNodeId : instance.ActivityId;
11 months ago
CurrentNodeType = GetNodeType(CurrentNodeId);
PreviousId = instance.PreviousId;
FlowInstanceId = instance.Id;
//会签开始节点和流程结束节点没有下一步
if (CurrentNodeType == 0 || CurrentNodeType == 4)
11 months ago
{
NextNodeId = "-1";
NextNodeType = -1;
}
else if (CurrentNodeType == 5)
{
NextNodeId = GetNextConditionNodeId(CurrentNode); //下一个节点
NextNodeType = GetNodeType(NextNodeId);
}
11 months ago
else
{
NextNodeId = GetNextNodeId(CurrentNodeId); //下一个节点
11 months ago
NextNodeType = GetNodeType(NextNodeId);
}
}
public long BusinessId { get; set; }
public string ColumnView { get; set; }
11 months ago
ISqlSugarClient db { get; set; }
ISqlSugarClient tenantDb { get; set; }
IUser user { get; set; }
11 months ago
/// <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 FlowChild CurrentNode => ChildNodes.First(x => x.Id == CurrentNodeId);
11 months ago
/// <summary>
/// 下一个节点
/// </summary>
public string NextNodeId { get; set; }
/// <summary>
/// 下一个节点类型 -1无法运行,0会签开始,1会签结束,2一般节点,4流程运行结束,5同级审批
11 months ago
/// </summary>
public int NextNodeType { get; set; }
/// <summary>
/// 下一个节点对象
/// </summary>
public FlowChild? NextNode => NextNodeId != "-1" ? ChildNodes.First(x => x.Id == NextNodeId) : null;
11 months ago
/// <summary>
/// 上一个节点
/// </summary>
public string PreviousId { get; set; }
/// <summary>
/// 实例节点集合
/// </summary>
public List<FlowChild> ChildNodes { get; set; }
public string? Note { get; set; }
11 months ago
/// <summary>
/// 获取工作流节点的字典列表:key节点id
/// </summary>
/// <param name="schemeContentJson"></param>
/// <returns></returns>
private void InitNodes(string schemeContentJson)
{
ChildNodes = new List<FlowChild>();
var root = JsonConvert.DeserializeObject<FlowRoot>(schemeContentJson);
if (root.Type == FlowChild.START)
{
StartNodeId = root.Id;
11 months ago
}
if (root.Child.IsNotNull())
{
11 months ago
var parent = root.Adapt<FlowChild>();
ChildNodes.Add(parent);
GetFlowChildsByParent(parent.Id, parent);
11 months ago
}
}
/// <summary>
/// 撤销流程,清空所有节点
/// </summary>
public void Cancel()
{
foreach (var item in ChildNodes)
{
item.SetInfo = null;
}
}
private void GetFlowChildsByParent(string nodeId, FlowChild parent)
11 months ago
{
if (parent.Type == FlowChild.Exclusive && parent.Children.IsNotNull() && parent.Children.Count > 0)
{
foreach (var item in parent.Children)
11 months ago
{
ChildNodes.Add(item);
11 months ago
GetFlowChildsByParent(nodeId, item);
}
}
11 months ago
if (parent.Child.IsNotNull())
{
11 months ago
ChildNodes.Add(parent.Child);
GetFlowChildsByParent(parent.Child.Id, parent.Child);
11 months ago
}
// var childs = new List<FlowChild>();
11 months ago
}
11 months ago
private List<FlowChild> GetFlowConditions(FlowChild parent)
{
var conditionNodes = new List<FlowChild>();
if (parent.Children != null)
11 months ago
{
foreach (var item in parent.Children)
{
conditionNodes.Add(item);
}
}
11 months ago
return conditionNodes;
}
11 months ago
11 months ago
/// <summary>
/// 获取下一个节点
/// <param name="nodeId"></param>
/// </summary>
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;
}
}
/// <summary>
/// 获取下一个条件节点
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
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)
11 months ago
{
// return ChildNodes.Where(x => x.Pid == conditionNodes[i].Id).First().Id;
conditionId = conditionNodes[i].Id;
}
else
{
var conditions = conditionNodes[i].Conditions;
var conditionalCollections = new List<ConditionalCollections>();
if (conditions.LogicalOperator == "and")
{
var conditionList = new List<KeyValuePair<WhereType, ConditionalModel>>();
foreach (var item in conditions.Conditions)
11 months ago
{
conditionList.Add(new KeyValuePair<WhereType, ConditionalModel>
(WhereType.And,
new ConditionalModel
{
FieldName = item.Field,
ConditionalType = GetConditionalType(item.Operator),
FieldValue = item.Value
})
);
7 months ago
}
if (conditionList.Count > 0)
7 months ago
{
conditionalCollections.Add(new ConditionalCollections
7 months ago
{
ConditionalList = conditionList
7 months ago
}
)
;
7 months ago
}
var groupList = new List<KeyValuePair<WhereType, ConditionalModel>>();
foreach (var group in conditions.Groups)
7 months ago
{
if (group.LogicalOperator == "and")
7 months ago
{
foreach (var item1 in group.Conditions)
{
groupList.Add(new KeyValuePair<WhereType, ConditionalModel>
(WhereType.And,
new ConditionalModel
{
FieldName = item1.Field,
ConditionalType = GetConditionalType(item1.Operator),
FieldValue = item1.Value
})
);
}
}
else
{
foreach (var item1 in group.Conditions)
{
groupList.Add(new KeyValuePair<WhereType, ConditionalModel>
(WhereType.Or,
new ConditionalModel
{
FieldName = item1.Field,
ConditionalType = GetConditionalType(item1.Operator),
FieldValue = item1.Value
})
);
}
7 months ago
}
}
if (groupList.Count > 0)
{
conditionalCollections.Add(new ConditionalCollections
{
ConditionalList = groupList
}
)
;
}
7 months ago
}
else
7 months ago
{
var conditionList = new List<KeyValuePair<WhereType, ConditionalModel>>();
foreach (var item in conditions.Conditions)
7 months ago
{
conditionList.Add(new KeyValuePair<WhereType, ConditionalModel>
(WhereType.Or,
new ConditionalModel
{
FieldName = item.Field,
ConditionalType = GetConditionalType(item.Operator),
FieldValue = item.Value
})
);
7 months ago
}
if (conditionList.Count > 0)
7 months ago
{
conditionalCollections.Add(new ConditionalCollections
7 months ago
{
ConditionalList = conditionList
7 months ago
}
)
;
7 months ago
}
var groupList = new List<KeyValuePair<WhereType, ConditionalModel>>();
foreach (var group in conditions.Groups)
7 months ago
{
if (group.LogicalOperator == "and")
{
foreach (var item1 in group.Conditions)
{
groupList.Add(new KeyValuePair<WhereType, ConditionalModel>
(WhereType.And,
new ConditionalModel
{
FieldName = item1.Field,
ConditionalType = GetConditionalType(item1.Operator),
FieldValue = item1.Value
})
);
}
}
else
7 months ago
{
foreach (var item1 in group.Conditions)
{
groupList.Add(new KeyValuePair<WhereType, ConditionalModel>
(WhereType.Or,
new ConditionalModel
{
FieldName = item1.Field,
ConditionalType = GetConditionalType(item1.Operator),
FieldValue = item1.Value
})
);
}
7 months ago
}
}
if (groupList.Count > 0)
7 months ago
{
conditionalCollections.Add(new ConditionalCollections
{
ConditionalList = groupList
}
)
;
}
}
7 months ago
var conditionalModels = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(JsonConvert.SerializeObject(conditionalCollections));
if (conditionalModels.Count == 0) //跳过默认条件
continue;
ISqlSugarClient sugarClient = tenantDb ?? db;
var exists = sugarClient.Queryable<object>().AS(ColumnView).Where("Id=@Id", new { Id = BusinessId }).Where(conditionalModels).Any();
if (exists)
{
conditionId = conditionNodes[i].Id;
break;
}
11 months ago
}
11 months ago
}
return ChildNodes.Where(x => x.Pid == conditionId).FirstOrDefault()?.Id;
11 months ago
}
11 months ago
/// <summary>
/// 获取下一个节点
/// </summary>
/// <param name="nodeId"></param>
/// <returns></returns>
public FlowChild GetNextNode(string? nodeId = null)
11 months ago
{
if (nodeId == null)
return ChildNodes.Where(x => x.Pid == "root").First();
if (ChildNodes.Exists(x => x.Pid == nodeId))
11 months ago
{
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();
11 months ago
}
}
/// <summary>
/// 转换FlowRoot
/// </summary>
/// <returns></returns>
public FlowRoot ToFlowRoot()
{
var root = ChildNodes.First(x => x.Id == "root");
var list = ChildNodes.Where(x => x.Id != "root").ToList();
var info = root.Adapt<FlowRoot>();
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<FlowChild>();
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;
}
}
}
11 months ago
/// <summary>
/// 获取实例接下来运行的状态
/// </summary>
/// <returns>-1无法运行,0开始,1结束,2一般节点,4流程运行结束</returns>
public int GetNextNodeType()
{
if (NextNodeId != "-1")
{
return GetNodeType(NextNodeId);
}
11 months ago
return -1;
}
10 months ago
/// <summary>
/// 转换SqlSugar 条件操作符
/// </summary>
/// <param name="conditionalType"></param>
/// <returns></returns>
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;
}
}
11 months ago
/// <summary>
/// 获取节点类型 0会签开始,1会签结束,2一般节点,3开始节点,4流程运行结束
11 months ago
/// </summary>
/// <param name="nodeId"></param>
/// <returns></returns>
public int GetNodeType(string nodeId)
{
switch (ChildNodes.Where(x => x.Id == nodeId).First().Type)
{
//会签开始节点
case FlowChild.Approval:
11 months ago
return 0;
11 months ago
//会签结束节点
case FlowChild.JOIN:
return 1;
11 months ago
//结束节点
case FlowChild.END:
return 4;
//开始节点
case FlowChild.START:
return 3;
//互斥条件
case FlowChild.Exclusive:
return 5;
10 months ago
//一般节点
11 months ago
default:
return 2;
}
}
11 months ago
//获取上一个节点
private FlowChild GetPreNode(string nodeId = null)
{
11 months ago
var child = ChildNodes.Where(x => x.Pid == nodeId).First();
if (child.IsNull())
{
throw new Exception("无法找到上一个点");
}
return child;
}
/// <summary>
/// 驳回
/// </summary>
/// <param name="rejectType">驳回类型。null:使用节点配置的驳回类型/0:前一步/1:第一步/2指定节点使用NodeRejectStep</param>
/// <returns></returns>
public string RejectNode(string rejectType)
{
var node = ChildNodes.Where(x => x.Id == CurrentNodeId).First();
11 months ago
if (node.SetInfo != null && string.IsNullOrEmpty(rejectType))
{
rejectType = node.SetInfo.NodeRejectType;
}
11 months ago
if (rejectType == "0")
{
return PreviousId;
}
11 months ago
if (rejectType == "1")
{
return GetNextNodeId(StartNodeId);
}
return PreviousId;
}
11 months ago
///<summary>
/// 标记节点 1通过2不通过3驳回
11 months ago
/// </summary>
/// <param name="nodeId"></param>
public void MakeTagNode(string nodeId, FlowTag tag)
11 months ago
{
// var node = ChildNodes.First(x => x.Id == nodeId);
foreach (var item in ChildNodes)
11 months ago
{
if (item.Id == nodeId)
11 months ago
{
if (item.SetInfo == null)
11 months ago
{
item.SetInfo = new Setinfo();
11 months ago
}
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");
11 months ago
break;
}
}
}
/// <summary>
/// 节点审核
/// </summary>
/// <param name="nodeId">会签时currentNodeId是会签开始节点。这个表示当前正在处理的节点</param>
/// <param name="tag">节点标签</param>
/// <returns>-1不通过,1等待,其它通过</returns>
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;
}
11 months ago
}