基于elsa工作流封装一套变量、组件的体系

前言

定义一套支持自定义数据类型的变量管理功能。
通过自定义组件、自定义活动的方式来实现业务组件与工作流组件逻辑分离。
业务组件可以通过不同的版本来保障业务不受更新影响。

nuget

使用DynamicExpresso.Core.2.19.3
Elsa 3.5.3
Elsa.EntityFrameworkCore 3.5.3
Elsa.EntityFrameworkCore.Postgresql 3.5.3

基础类型定义

定义数据结构支持的字段类型

/// <summary>
/// Json数据类型
/// </summary>
public enum JsonDataType
{
    /// <summary>
    /// 未设定
    /// </summary>
    None = 0,
    /// <summary>
    /// 字符串
    /// </summary>
    String,
    /// <summary>
    /// 整形
    /// </summary>
    Integer,
    /// <summary>
    /// 长整形
    /// </summary>
    Long,
    /// <summary>
    /// Double类型
    /// </summary>
    Double,
    /// <summary>
    /// Decimal类型
    /// </summary>
    Decimal,
    /// <summary>
    /// 布尔
    /// </summary>
    Boolean,
    /// <summary>
    /// 日期时间
    /// </summary>
    DateTime,
    /// <summary>
    /// UUID
    /// </summary>
    Guid,
    /// <summary>
    /// 对象
    /// </summary>
    Object,
    /// <summary>
    /// 数组
    /// </summary>
    Array,
    /// <summary>
    /// Null类型
    /// </summary>
    Null,

    Dynamic = 12,
    /// <summary>
    /// 分页列表
    /// </summary>
    PagedList = 13,

    /// <summary>
    /// List<string>
    /// </summary>
    ListStr = 14,

    /// <summary>
    ///  List<int>
    /// </summary>
    ListInt = 15
}

变量类型定义

定义底层处理时支持的变量的类型,其中链式表达式可以支持配置复杂的条件与或非等逻辑

public enum AssignTypeEnum
{
    /// <summary>
    /// 引用
    /// </summary>
    [Description("引用变量")]
    Ref = 0,

    /// <summary>
    /// 常量(手写)
    /// </summary>
    [Description("常量")]
    ConstValue = 1,

    [Description("系统变量")]
    SystemValue = 2,


    /// <summary>
    /// 链式表达式
    /// </summary>
    [Description("表达式")]
    LinkExpression = 3,
}

参数解析帮助类

辅助转换入参为具体类型

public class FlowParameterUtil
{
    public static List<Variable> ParameterParse(List<FlowParameterEntity> parameters)
    {
        if (parameters == null || parameters.Count == 0)
        {
            return new();
        }

        var result = new List<Variable>();
        foreach (var parameter in parameters)
        {
            object paraItem = ParseDefaultValue(parameter.ParameterType, parameter.DefaultValue);

            var variable = ParseFlowParameter(paraItem, parameter.ParameterNo);
            result.Add(variable);
        }

        return result;
    }

    public static Variable ParameterParse(JsonDataType dataType, string parameterNo, string value)
    {
        //TODO 补充异常入参校验

        object paraItem = ParseDefaultValue(dataType, value);

        var variable = ParseFlowParameter(paraItem, parameterNo);

        return variable;
    }

    public static Input<T> ParseFlowInput<T>(object obj, string paraName)
    {
        var para = new Input<T>((T)obj, paraName);
        return para;
    }

    public static Variable<T> ParseFlowParameter<T>(object obj, string paraName)
    {
        var variable = new Variable<T>(paraName, (T)obj);
        return variable;
    }

    public static Variable ParseFlowParameter(object obj, string paraName)
    {
        var variable = new Variable(paraName, obj);
        return variable;
    }

    /// <summary>
    /// support type for string、int 、long、double、decimal、bool、datetime
    /// </summary>
    /// <param name="jsonDataType"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    /// <exception cref="System.Exception"></exception>
    /// <exception cref="System.FormatException"></exception>
    public static object ParseDefaultValue(JsonDataType jsonDataType, string defaultValue)
    {
        if (string.IsNullOrEmpty(defaultValue))
        {
            return GetDefaultValueForType(jsonDataType);
        }

        switch (jsonDataType)
        {
            case JsonDataType.String:
                return defaultValue;
            case JsonDataType.Integer:
                return int.TryParse(defaultValue, out var intResult) ? intResult : throw new System.FormatException($"ErrInt:'{defaultValue}'");
            case JsonDataType.Long:
                return long.TryParse(defaultValue, out var longResult) ? longResult : throw new System.FormatException($"ErrLong:'{defaultValue}'");
            case JsonDataType.Double:
                return double.TryParse(defaultValue, out var doubleResult) ? doubleResult : throw new System.FormatException($"ErrDouble:'{defaultValue}'");
            case JsonDataType.Decimal:
                return decimal.TryParse(defaultValue, out var decimalResult) ? decimalResult : throw new System.FormatException($"ErrDecimal:'{defaultValue}'");
            case JsonDataType.Boolean:
                return bool.TryParse(defaultValue, out var boolResult) ? boolResult : throw new System.FormatException($"ErrBoolean:'{defaultValue}'");
            case JsonDataType.DateTime:
                return System.DateTime.TryParse(defaultValue, out var dateTimeResult) ? dateTimeResult : throw new System.FormatException($"ErrDateTime:'{defaultValue}'");
            case JsonDataType.Guid:
                return System.Guid.TryParse(defaultValue, out var guidResult) ? guidResult : throw new System.FormatException($"ErrGuid:'{defaultValue}'");
            case JsonDataType.Object:
            case JsonDataType.Array:
            case JsonDataType.Null:
            case JsonDataType.Dynamic:
            case JsonDataType.PagedList:
            case JsonDataType.ListStr:
            case JsonDataType.ListInt:
            case JsonDataType.None:
            default:
                throw new System.Exception($"UnsupportDataType: {jsonDataType}");
        }
    }

    private static object GetDefaultValueForType(JsonDataType jsonDataType)
    {
        switch (jsonDataType)
        {
            case JsonDataType.None:
                return null;
            case JsonDataType.String:
                return string.Empty;
            case JsonDataType.Integer:
                return 0;
            case JsonDataType.Long:
                return 0L;
            case JsonDataType.Double:
                return 0.0;
            case JsonDataType.Decimal:
                return 0.0m;
            case JsonDataType.Boolean:
                return false;
            case JsonDataType.DateTime:
                return System.DateTime.MinValue;
            case JsonDataType.Guid:
                return System.Guid.Empty;
            case JsonDataType.Object:
                return null;
            case JsonDataType.Array:
                return null;
            case JsonDataType.Null:
                return null;
            case JsonDataType.Dynamic:
                return null;
            case JsonDataType.PagedList:
                return null;
            case JsonDataType.ListStr:
                return null;
            case JsonDataType.ListInt:
                return null;
            default:
                return null;
        }
    }
}

系统变量类型

 public enum SysValueTypeEnum
 {
     GUID = 0,
     SystemTime = 1,
     LoginUser = 2,
     LoginUserNo = 3,
     EmptyStr = 4,
     NULL = 5
 }

系统变量解析

public class ExpSysValue
{
    public SysValueTypeEnum ValueType { get; set; }

    public object Parse()
    {
        switch (ValueType)
        {
            case SysValueTypeEnum.GUID:
                return ObjectId.NewId();
            case SysValueTypeEnum.SystemTime:
                return DateTime.Now;
            case SysValueTypeEnum.LoginUser:
                return "Passport.UserId";
            case SysValueTypeEnum.LoginUserNo:
                return "Passport.UserId";
            case SysValueTypeEnum.EmptyStr:
                return string.Empty;
            case SysValueTypeEnum.NULL:
                return null;
            default:
                throw new NotImplementedException("ErrSysValueType");
        }
    }
}

常量解析

public class ExpConst
{
    public string Value { get; set; }

    /// <summary>
    /// 常量时使用
    /// </summary>
    public JsonDataType ValueDataType { get; set; }

    public object Parse(ActivityExecutionContext context)
    {
        var variable = FlowParameterUtil.ParseDefaultValue(ValueDataType, Value);
        return variable;
    }
}

变量解析

public class ExpRef
{
    /// <summary>
    /// 引用变量的编号
    /// </summary>
    public string RefParamateNo { get; set; }


    public object Parse(ActivityExecutionContext context)
    {
        var variable = context.GetVariable<string>(RefParamateNo);

        return variable;
    }
}

动态表达式

public enum ExpLinkTypeEnum
{
    /// <summary>
    /// 除法运算 (a / b)
    /// </summary>
    Divide = 1,

    /// <summary>
    /// 等于比较 (a == b)
    /// </summary>
    Equal = 2,

    /// <summary>
    /// 按位或逻辑异或运算 (a ^ b)
    /// </summary>
    ExclusiveOr = 3,

    /// <summary>
    /// 大于比较 (a > b)
    /// </summary>
    GreaterThan = 4,

    /// <summary>
    /// 大于等于比较 (a >= b)
    /// </summary>
    GreaterThanOrEqual = 5,

    /// <summary>
    /// 小于比较 (a < b)
    /// </summary>
    LessThan = 6,

    /// <summary>
    /// 小于等于比较 (a <= b)
    /// </summary>
    LessThanOrEqual = 7,

    /// <summary>
    /// 算术取余运算 (a % b)
    /// </summary>
    Modulo = 8,

    /// <summary>
    /// 乘法运算 (a * b)
    /// </summary>
    Multiply = 9,

    /// <summary>
    /// 算术取反运算 (-a)
    /// </summary>
    Negate = 10,

    /// <summary>
    /// 按位取反或逻辑非运算 (~a 或 !a)
    /// </summary>
    Not = 11,

    /// <summary>
    /// 不等于比较 (a != b)
    /// </summary>
    NotEqual = 12,

    /// <summary>
    /// 按位或逻辑或运算 (a | b)
    /// </summary>
    Or = 13,

    /// <summary>
    /// 短路条件或运算 (a || b)
    /// </summary>
    OrElse = 14,

    /// <summary>
    /// 减法运算 (a - b)
    /// </summary>
    Subtract = 15,

    /// <summary>
    /// 一元递减运算 (a - 1)
    /// </summary>
    Decrement = 16,

    /// <summary>
    /// 一元递增运算 (a + 1)
    /// </summary>
    Increment = 17,
}
 public class ExpLink
 {
     public ExpressionConfig LeftExp { get; set; }

     public ExpressionConfig RightExp { get; set; }

     public ExpLinkTypeEnum LinkType { get; set; }

     public object Parse(ActivityExecutionContext context)
     {
         //null值校验
         ExceptionHelper.CheckNull(LeftExp, "LeftExpNotNull");
         //允许右值为空
         //ExceptionHelper.CheckNull(RightExp, "RightExpNotNull");

         var leftValue = LeftExp.Parse(context);
         object rightValue = null;
         if (RightExp != null)
         {
             rightValue = RightExp.Parse(context);
         }

         var result = Parse(leftValue, rightValue, LinkType);
         return result;
     }

     private object Parse(object leftValue, object rightValue, ExpLinkTypeEnum linkType)
     {
         var interpreter = new Interpreter();

         switch (linkType)
         {
             case ExpLinkTypeEnum.Divide:
                 return interpreter.Eval("leftValue/rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.Equal:
                 return leftValue.Equals(rightValue);
             case ExpLinkTypeEnum.ExclusiveOr:
                 return interpreter.Eval("leftValue^rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.GreaterThan:
                 return interpreter.Eval("leftValue>rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.GreaterThanOrEqual:
                 return interpreter.Eval("leftValue>=rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.LessThan:
                 return interpreter.Eval("leftValue<rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.LessThanOrEqual:
                 return interpreter.Eval("leftValue<=rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.Modulo:
                 return interpreter.Eval("leftValue%rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.Multiply:
                 return interpreter.Eval("leftValue*rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.Negate:
                 return interpreter.Eval("-leftValue",
                     new Parameter("leftValue", leftValue)
                     );
             case ExpLinkTypeEnum.Not:
                 return interpreter.Eval("!leftValue",
                     new Parameter("leftValue", leftValue)
                     );
             case ExpLinkTypeEnum.NotEqual:
                 return !leftValue.Equals(rightValue);
             case ExpLinkTypeEnum.Or:
                 return interpreter.Eval("leftValue | rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.OrElse:

                 return interpreter.Eval("leftValue || rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.Subtract:
                 return interpreter.Eval("leftValue - rightValue",
                     new Parameter("leftValue", leftValue),
                     new Parameter("rightValue", rightValue)
                     );
             case ExpLinkTypeEnum.Decrement:
                 return interpreter.Eval("leftValue - 1",
                     new Parameter("leftValue", leftValue)
                     );
             case ExpLinkTypeEnum.Increment:
                 return interpreter.Eval("leftValue + 1",
                     new Parameter("leftValue", leftValue)
                     );
             default:
                 break;
         }

         return leftValue;
     }
 }

变量解析

/// <summary>
/// 单个表达式节点解析
/// </summary>
public class ExpressionConfig
{
    public AssignTypeEnum ExpressionNodeType { get; set; }

    public string ConfigValue { get; set; }

    public object Parse(ActivityExecutionContext context)
    {
        if (string.IsNullOrEmpty(ConfigValue))
        {
            throw new System.Exception("ExpConfigNotNUll");
        }
        switch (ExpressionNodeType)
        {
            case AssignTypeEnum.Ref:
                var refData = JsonConvert.DeserializeObject<ExpRef>(ConfigValue);
                return refData.Parse(context);
            case AssignTypeEnum.ConstValue:
                var constValue = JsonConvert.DeserializeObject<ExpConst>(ConfigValue);
                return constValue.Parse(context);
            case AssignTypeEnum.SystemValue:
                var systemValueConfig = JsonConvert.DeserializeObject<ExpSysValue>(ConfigValue);
                return systemValueConfig.Parse();
            case AssignTypeEnum.LinkExpression:
                var link = JsonConvert.DeserializeObject<ExpLink>(ConfigValue);
                return link.Parse(context);
            default:
                throw new System.Exception("errExpression");
        }
    }
}

组件定义

public abstract class IBaseComponent
{
    public string NodeID { get; set; }
    public string NodeNo { get; set; }
    public string NodeName { get; set; }

    /// <summary>
    /// 节点类型
    /// </summary>
    public FlowComponentType NodeType { get; set; }

    /// <summary>
    /// 节点版本
    /// </summary>
    public int NodeTypeVersion { get; set; }

    [JsonIgnore]
    public Activity FlowNode { get; set; }


    /// <summary>
    /// 解析组件基础结构
    /// </summary>
    /// <returns></returns>
    public abstract IBaseComponent Parse(FlowParseContext parseContext);

    /// <summary>
    /// 解析组件额外属性
    /// 所有组件基础结构完成后再次解析配置
    /// 用于识别嵌套、递归的子组件等逻辑
    /// </summary>
    /// <returns></returns>
    public abstract void ParseExtra(FlowParseContext parseContext);


    /// <summary>
    /// 
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static IBaseComponent ParseAPIComponent(FlowComponentItem item)
    {
        ExceptionHelper.Check(string.IsNullOrEmpty(item.ConfigValue), $"EmptyNodeConfig:{item.NodeName}");

        Type componentType = null;

        try
        {
            componentType = ICompFactory.GetAPIComponent(item.NodeType, item.ComponentVersionLevel);

        }
        catch (Exception)
        {
            throw new Exception($"NodeTypeParseErr:{item.NodeName}");
        }
        IBaseComponent component = null;

        try
        {
            component = JsonConvert.DeserializeObject(item.ConfigValue, componentType) as IBaseComponent;
        }
        catch (Exception)
        {
            throw new Exception($"NodeParseErr:{item.NodeName}");
        }

        component.NodeID = item.NodeID;
        component.NodeNo = item.NodeNo;
        component.NodeName = item.NodeName;
        component.NodeType = item.NodeType;
        component.NodeTypeVersion = item.ComponentVersionLevel;

        return component;
    }

    protected void InitActivity()
    {
        if (FlowNode is not Activity activity)
        {
            throw new Exception("FlowNode is not ActivityNode");
        }

        activity.Id = NodeID;
        activity.NodeId = NodeID;
        activity.Name = NodeName;
    }
}

组件工厂

public interface ICompFactory
{
    public abstract Type CreateComponent(int compLevel);

    public static Type GetAPIComponent(FlowComponentType nodeType, int compLevel)
    {
        var compFactory = CompFactoryContainer.GetOrAddFactory(nodeType);
        var componentType = compFactory.CreateComponent(compLevel);
        return componentType;
    }
}

internal static class CompFactoryContainer
{
    private static readonly ConcurrentDictionary<FlowComponentType, ICompFactory> _factoryCache = new();

    static CompFactoryContainer()
    {
        // 预初始化所有工厂实例
        _factoryCache.TryAdd(FlowComponentType.StartComp, new StartCompFactory());
        _factoryCache.TryAdd(FlowComponentType.EndComp, new EndCompFactory());
        _factoryCache.TryAdd(FlowComponentType.LevelExceptionComp, new LevelExceptionCompFactory());
        _factoryCache.TryAdd(FlowComponentType.IFComp, new IFCompFactory());
    }

    public static ICompFactory GetOrAddFactory(FlowComponentType nodeType)
    {
        if (_factoryCache.TryGetValue(nodeType, out var factory))
        {
            return factory;
        }

        throw new NotImplementedException($"ComponentFactoryNotFound: {nodeType}");
    }
}

示例组件 IF组件

  public class IFCompFactory : ICompFactory
  {
      public Type CreateComponent(int compLevel)
      {
          switch (compLevel)
          {
              case 1:
                  return typeof(IFComponent);
              default:
                  throw new ArgumentException("UnsupportComponentVersion");
          }
      }
  }


public class IFComponent : IBaseComponent
{
    /// <summary>
    /// 条件
    /// </summary>
    public ExpressionConfig Condition { get; set; }

    public string IFNodeNo { get; set; }

    public string ElseNodeNo { get; set; }


    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override IBaseComponent Parse(FlowParseContext parseContext)
    {
        //TODO 解析节点和流程配置
        FlowNode = new IFActivity();

        InitActivity();

        return this;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override void ParseExtra(FlowParseContext parseContext)
    {
        ExceptionHelper.CheckNull(Condition, $"ConditionNull:{NodeName}");

        if (FlowNode is not IFActivity ifNode)
        {
            throw new System.Exception($"ErrIFNode:{NodeName}");
        }

        ifNode.Condition = Condition;

        //基础解析完成后,解析子节点
        if (IFNodeNo != null)
        {
            var ifBodeNode = parseContext.FindNode(IFNodeNo);
            ifNode.IFBody = ifBodeNode.FlowNode;
        }

        if (ElseNodeNo != null)
        {
            var elseNode = parseContext.FindNode(ElseNodeNo);
            ifNode.ElseBody = elseNode.FlowNode;
        }
    }
}

public class IFActivity : CodeActivity<bool>, IActivityNode
{

    public ExpressionConfig Condition { get; set; }
    public Activity IFBody { get; set; }
    public Activity ElseBody { get; set; }

    protected override ValueTask ExecuteAsync(ActivityExecutionContext context)
    {
        var conditionValue = Condition.Parse(context);

        Console.WriteLine("if");

        if (conditionValue is not bool boolConditionValue)
        {
            throw new Exception($"ErrIFCondition:{conditionValue}");
        }

        var nextActivity = boolConditionValue ? IFBody : ElseBody;

        context.Set(Result, boolConditionValue);

        if (nextActivity != null)
        {
            context.ScheduleActivityAsync(nextActivity, OnChildCompleted);
        }

        return base.ExecuteAsync(context);
    }

    private async ValueTask OnChildCompleted(ActivityCompletedContext context)
    {
        await context.TargetContext.CompleteActivityAsync();
    }
}

组件执行

public class FlowExecuter
{
    /// <summary>
    /// 执行流程
    /// 可以在保存时直接执行,避免多次调用数据库
    /// </summary>
    public static async Task<RunWorkflowResult> ExecFlow(IWorkflowRunner workflowRunner, FlowParseResult parseResult, string instanceID = null, string bookmarkID = null)
    {
        var parseContext = new FlowParseContext
        {
            ParseResult = parseResult,
        };

        var workflow = new Flowchart();
        workflow.Activities = new List<IActivity>();

        //解析基础结构
        foreach (var item in parseResult.ComponentList)
        {
            item.Parse(parseContext);
        }

        if (parseResult.FlowVariableList.IsObjNotNull())
        {
            workflow.Variables = [.. parseResult.FlowVariableList];
        }

        //解析扩展数据 需要等所有的组件和变量完成后进行处理
        foreach (var item in parseResult.ComponentList)
        {
            item.ParseExtra(parseContext);
        }

        //生成执行节点
        foreach (var item in parseResult.ComponentList)
        {
            if (item.FlowNode is not Activity activity)
            {
                throw new Exception("ErrActivity");
            }
            workflow.Activities.Add(activity);
        }

        //节点连线处理
        if (parseResult.StepEntityList.IsObjNotNull())
        {
            workflow.Connections = new List<Connection>();

            foreach (var item in parseResult.StepEntityList)
            {
                var fromAct = workflow.Activities.FirstOrDefault(f => f.Id == item.FromId);
                var toAct = workflow.Activities.FirstOrDefault(f => f.Id == item.ToId);
                ExceptionHelper.CheckNull(fromAct, $"NodeNull,NodeID:{item.FromId}");
                ExceptionHelper.CheckNull(toAct, $"NodeNull,NodeID:{item.ToId}");

                var connectionItem = new Connection(fromAct, toAct);
                workflow.Connections.Add(connectionItem);
            }
        }

        return await workflowRunner.RunAsync(workflow);
    }

    /// <summary>
    /// 根据流程id和实例数据执行流程
    /// 简化调用
    /// 执行具体版本的流程
    /// version为空时执行最新的流程
    /// </summary>
    /// <returns></returns>
    public static async Task<RunWorkflowResult> ExecFlow(IServiceProvider serviceProvider, string flowID, string version, string instanceID = null, string bookmarkID = null)
    {
        //执行具体版本
        var nodeService = serviceProvider.GetService<FlowNodeService>();
        var stepService = serviceProvider.GetService<FlowStepService>();
        var flowService = serviceProvider.GetService<FlowVersionService>();

        var flowVersion = flowService.GetCanvasVersionData(flowID, version);

        var dto = JsonConvert.DeserializeObject<FlowCompSaveDto>(flowVersion.FlowData);

        var parseNode = ParseConfig(dto);

        var runner = serviceProvider.GetService<IWorkflowRunner>();

        return await ExecFlow(runner, parseNode, instanceID, bookmarkID);
    }

    #region 流程数据解析

    /// <summary>
    /// 解析前端配置
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    public static List<IBaseComponent> ParseNode(FlowCompSaveDto dto)
    {
        ExceptionHelper.CheckNullOrEmpty(dto.ComponentItems, "NodeNull");

        List<IBaseComponent> parseResult = new();
        foreach (var item in dto.ComponentItems)
        {
            var parseItem = IBaseComponent.ParseAPIComponent(item);
            ExceptionHelper.CheckNull(parseItem, $"ParseResultNull,NodeName:{item.NodeName}");

            parseResult.Add(parseItem);
        }

        return parseResult;
    }

    /// <summary>
    /// 根据入参和解析结果,生成需要保存的节点数据
    /// </summary>
    /// <param name="dto"></param>
    /// <param name="parseResult"></param>
    /// <returns></returns>
    public static List<FlowNodeEntity> ConvertNodeEntity(FlowCompSaveDto dto, List<IBaseComponent> parseResult)
    {
        List<FlowNodeEntity> nodeList = new();

        foreach (var item in parseResult)
        {
            ExceptionHelper.Check(item == null, "NodeParseNull");

            var nodeItem = new FlowNodeEntity();
            nodeItem.Id = item.NodeID;
            nodeItem.FlowId = dto.FlowID;

            var rawConfig = dto.ComponentItems.FirstOrDefault(x => x.NodeID == item.NodeID);
            ExceptionHelper.Check(rawConfig == null, "NodeConfigNull");

            nodeItem.NodeName = rawConfig.NodeName;
            nodeItem.NodeNo = rawConfig.NodeNo;
            nodeItem.NodeType = rawConfig.NodeType;
            nodeItem.IsStartNode = rawConfig.ISFirst;

            nodeList.Add(nodeItem);
        }

        return nodeList;
    }

    public static List<FlowStepEntity> ParseConnections(FlowCompSaveDto dto)
    {
        if (dto == null || dto.Connections.IsObjNull())
        {
            return null;
        }

        var result = new List<FlowStepEntity>();
        foreach (var item in dto.Connections)
        {
            var step = new FlowStepEntity
            {
                Id = Guid.NewGuid().ToString(),
                FlowId = dto.FlowID,
                FromId = item.FromID,
                ToId = item.ToID,
            };

            result.Add(step);
        }
        return result;
    }

    public static List<FlowParameterEntity> ParseParameter(FlowCompSaveDto dto)
    {
        if (dto.IsObjNull() || dto.ParameterList.IsObjNull())
        {
            return null;
        }

        var result = new List<FlowParameterEntity>();
        foreach (var item in dto.ParameterList)
        {
            var parameter = new FlowParameterEntity
            {
                Id = Guid.NewGuid().ToString(),
                FlowId = dto.FlowID,
                ParameterNo = item.ParameterNo,
                ParameterName = item.ParameterName,
                ParameterType = item.DataType,
                DefaultValue = item.DefaultValue,
                Description = item.Description,
            };
            result.Add(parameter);

        }
        return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static FlowParseResult ParseConfig(FlowCompSaveDto dto)
    {
        var parseResult = FlowExecuter.ParseNode(dto);
        var nodeList = FlowExecuter.ConvertNodeEntity(dto, parseResult);
        var stepList = FlowExecuter.ParseConnections(dto);
        var paraList = FlowExecuter.ParseParameter(dto);

        var result = new FlowParseResult
        {
            ComponentList = parseResult,
            FlowNodeEntityList = nodeList,
            StepEntityList = stepList,
            ParameterEntityList = paraList
        };

        if (paraList.IsObjNotNull())
        {
            //解析变量
            var variable = FlowParameterUtil.ParameterParse(paraList);
            result.FlowVariableList = [.. variable];
        }

        return result;
    }
posted @ 2026-01-30 13:17  Hey,Coder!  阅读(3)  评论(0)    收藏  举报