|
|
|
|
using DS.Module.Core.Extensions;
|
|
|
|
|
using DS.WMS.Core.Flow.Dtos;
|
|
|
|
|
using DS.WMS.Core.Flow.Entity;
|
|
|
|
|
using LanguageExt;
|
|
|
|
|
using Mapster;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
|
|
|
|
namespace DS.WMS.Core.Flow.Method;
|
|
|
|
|
|
|
|
|
|
public class FlowRuntimeService
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 构造函数
|
|
|
|
|
/// </summary>
|
|
|
|
|
public FlowRuntimeService(FlowInstance instance)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
InitNodes(instance.Content);//获取工作流模板内容的json对象;
|
|
|
|
|
|
|
|
|
|
CurrentNodeId = (instance.ActivityId == "" ? StartNodeId : instance.ActivityId);
|
|
|
|
|
CurrentNodeType = GetNodeType(CurrentNodeId);
|
|
|
|
|
|
|
|
|
|
// ti = schemeContentJson.title;
|
|
|
|
|
// initNum = schemeContentJson.initNum?? 0;
|
|
|
|
|
PreviousId = instance.PreviousId;
|
|
|
|
|
FlowInstanceId = instance.Id;
|
|
|
|
|
|
|
|
|
|
//会签开始节点和流程结束节点没有下一步
|
|
|
|
|
if (CurrentNodeType == 0 || CurrentNodeType == 4)
|
|
|
|
|
{
|
|
|
|
|
NextNodeId = "-1";
|
|
|
|
|
NextNodeType = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NextNodeId = GetNextNodeId();//下一个节点
|
|
|
|
|
NextNodeType = GetNodeType(NextNodeId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
///
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
|
|
|
|
public int initNum { 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 FlowChild 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 FlowChild NextNode => NextNodeId != "-1"? ChildNodes.First(x=>x.Id ==NextNodeId) : null;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上一个节点
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string PreviousId { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 实例节点集合
|
|
|
|
|
/// </summary>
|
|
|
|
|
public Dictionary<string, FlowChild> Nodes { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 实例节点集合
|
|
|
|
|
/// </summary>
|
|
|
|
|
public List<FlowChild> ChildNodes { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取工作流节点的字典列表:key节点id
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="schemeContentJson"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private void InitNodes(string schemeContentJson)
|
|
|
|
|
{
|
|
|
|
|
Nodes = new Dictionary<string, FlowChild>();
|
|
|
|
|
ChildNodes = new List<FlowChild>();
|
|
|
|
|
|
|
|
|
|
var root = JsonConvert.DeserializeObject<FlowRoot>(schemeContentJson);
|
|
|
|
|
if (root.Type == FlowChild.START)
|
|
|
|
|
{
|
|
|
|
|
this.StartNodeId = root.Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (root.Child.IsNotNull())
|
|
|
|
|
{
|
|
|
|
|
var parent = root.Adapt<FlowChild>();
|
|
|
|
|
ChildNodes.Add(parent);
|
|
|
|
|
GetFlowChildsByParent(parent.Id, parent);
|
|
|
|
|
// ChildNodes.Add(root.Child);
|
|
|
|
|
// var childs = GetFlowChildsByParent(parent.Id,parent);
|
|
|
|
|
// ChildNodes.AddRange(childs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void GetFlowChildsByParent(string nodeId,FlowChild parent)
|
|
|
|
|
{
|
|
|
|
|
// var childs = new List<FlowChild>();
|
|
|
|
|
if (parent.Type == FlowChild.Exclusive && parent.Childen.IsNotNull() && parent.Childen.Count>0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in parent.Childen)
|
|
|
|
|
{
|
|
|
|
|
GetFlowChildsByParent(nodeId, item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (parent.Child.IsNotNull())
|
|
|
|
|
{
|
|
|
|
|
ChildNodes.Add(parent.Child);
|
|
|
|
|
GetFlowChildsByParent(parent.Child.Id, parent.Child);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<FlowChild> GetFlowConditions(FlowChild parent)
|
|
|
|
|
{
|
|
|
|
|
var conditionNodes = new List<FlowChild>();
|
|
|
|
|
foreach (var item in parent.Childen)
|
|
|
|
|
{
|
|
|
|
|
conditionNodes.Add(item);
|
|
|
|
|
}
|
|
|
|
|
return conditionNodes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// private static List<FlowChild> GetFlowChilds(string nodeId, FlowChild parent)
|
|
|
|
|
// {
|
|
|
|
|
// if (parent.Type == FlowChild.Exclusive && parent.Childen.IsNotNull() && parent.Childen.Count>0)
|
|
|
|
|
// {
|
|
|
|
|
// foreach (var item in parent.Childen)
|
|
|
|
|
// {
|
|
|
|
|
// GetFlowChildsByParent(nodeId, item);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// if (parent.Child.IsNotNull())
|
|
|
|
|
// {
|
|
|
|
|
// childs.Add(parent.Child);
|
|
|
|
|
// GetFlowChildsByParent(parent.Child.Id, parent.Child);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// return NotImplementedException();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <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
|
|
|
|
|
{
|
|
|
|
|
#region 特殊处理条件节点
|
|
|
|
|
var nextNode = ChildNodes.Where(x => x.Pid == nodeId).First();
|
|
|
|
|
if (nextNode.Type== FlowChild.Exclusive)
|
|
|
|
|
{
|
|
|
|
|
var conditionNodes = GetFlowConditions(nextNode);
|
|
|
|
|
for (int i = 0; i < conditionNodes.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var conditions = conditionNodes[0].Conditions;
|
|
|
|
|
|
|
|
|
|
if (conditions.LogicalOperator=="and")
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion 特殊处理条件节点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ChildNodes.Where(x => x.Pid == nodeId).First().Id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取下一个节点
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="nodeId"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public FlowChild GetNextNode(string nodeId = null)
|
|
|
|
|
{
|
|
|
|
|
if (nodeId == null)
|
|
|
|
|
{
|
|
|
|
|
return ChildNodes.Where(x => x.Pid == "root").First();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return ChildNodes.Where(x => x.Pid == nodeId).First();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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 (ChildNodes.Where(x => x.Id == nodeId).First().Type)
|
|
|
|
|
{
|
|
|
|
|
//会签开始节点
|
|
|
|
|
case FlowChild.Exclusive:
|
|
|
|
|
return 0;
|
|
|
|
|
//会签结束节点
|
|
|
|
|
case FlowChild.JOIN:
|
|
|
|
|
return 1;
|
|
|
|
|
//结束节点
|
|
|
|
|
case FlowChild.END:
|
|
|
|
|
return 4;
|
|
|
|
|
//开始节点
|
|
|
|
|
case FlowChild.START:
|
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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 GetNextNodeId(StartNodeId);
|
|
|
|
|
}
|
|
|
|
|
return PreviousId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 撤销流程,清空所有节点
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void ReCall()
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in Nodes)
|
|
|
|
|
{
|
|
|
|
|
item.Value.SetInfo = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// 标记节点 1通过,-1不通过,0驳回
|
|
|
|
|
/// </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>
|
|
|
|
|
public class Tag
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 1: 通过
|
|
|
|
|
/// 2:不通过
|
|
|
|
|
/// 3:驳回
|
|
|
|
|
/// </summary>
|
|
|
|
|
public int Taged { get; set; }
|
|
|
|
|
|
|
|
|
|
public string UserId { get; set; }
|
|
|
|
|
public string UserName { get; set; }
|
|
|
|
|
public string Description { get; set; }
|
|
|
|
|
public string TagedTime { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|