Easy.WorkFlow.Core 2.3.14

dotnet add package Easy.WorkFlow.Core --version 2.3.14
                    
NuGet\Install-Package Easy.WorkFlow.Core -Version 2.3.14
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Easy.WorkFlow.Core" Version="2.3.14" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Easy.WorkFlow.Core" Version="2.3.14" />
                    
Directory.Packages.props
<PackageReference Include="Easy.WorkFlow.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Easy.WorkFlow.Core --version 2.3.14
                    
#r "nuget: Easy.WorkFlow.Core, 2.3.14"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Easy.WorkFlow.Core@2.3.14
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Easy.WorkFlow.Core&version=2.3.14
                    
Install as a Cake Addin
#tool nuget:?package=Easy.WorkFlow.Core&version=2.3.14
                    
Install as a Cake Tool

Easy.WorkFlow.Core

Easy.WorkFlow.Core 是一个灵活、可扩展的工作流核心库,旨在简化工作流的定义、创建和执行过程。本库支持 .NET Standard 2.1、.NET 6、.NET 7、.NET 8 和 .NET 9。 Easy.WorkFlow.Core 目前仍在开发测试中,请谨慎使用。

功能特性

  • 灵活的工作流定义:支持自定义工作流结构和步骤逻辑
  • 多种步骤处理器类型:内置 SQL、Action(方法)和远程 URL 处理器
  • 表达式解析:支持条件表达式和参与者(步骤审批人)表达式的动态解析(从工作流表单数据中解析)
  • 可扩展架构:基于接口设计,易于扩展和自定义
  • 完整的生命周期管理:从工作流定义、实例创建到执行完成的全流程支持
  • 依赖注入支持:与 ASP.NET Core 依赖注入系统无缝集成

核心组件

  • 工作流构建器 (WorkFlow Builder):负责创建工作流定义
  • 工作流激活器 (WorkFlow Activator):负责创建工作流实例
  • 工作流调度器 (WorkFlow Scheduler):负责调度和执行工作流步骤
  • 步骤处理器 (Step Processor):处理不同类型的工作流步骤
  • 步骤执行器 (Step Processor Executor):执行步骤处理器并处理结果
  • 表达式解析器 (Expression Parser):解析条件表达式和参与者表达式

更新日志

  • 2.3.14
    • 新增:处理器上下文支持工作流执行上下文中提取属性值的占位符,如[WFInstanceId][WFName]等
  • 2.3.13
    • 新增:新增工作流实例显示名称(方便搜索)。
    • 修复:修复工作流处理器部分参数绑定无效问题。
  • 2.3.12
    • 修复:修复默认远程处理器token传递到错误的header字段。
  • 2.3.11
    • 新增:WorkflowHandler部分钩子函数增加了WorkflowExecutionContext参数,表示工作流的执行上下文。
  • 2.3.10
    • 修复:修复工作流调度器事务嵌套导致事务不生效的问题
  • 2.3.9
    • 调整:取消IServiceResolver,改为原生的IServiceProvider。
  • 2.3.8
    • 新增:Workflow执行上下文及请求上下文添加IServiceResolver服务解析器(抽象接口),在需要时可以通过它解析依赖注入的服务。
  • 2.3.7
    • 调整:调整默认序列化配置,运用常用配置项。
  • 2.3.6
    • 调整:调整ParserOptions的UserIdKey及UserNameKey,支持多键名匹配。
  • 2.3.5
    • 新增:新增了IUnitOfWork接口,工作流调度器使用IUnitOfWork进行事务控制。
  • 2.3.4
    • 调整:调整了默认序列化器的配置,添加了long转换器及日期转换器,支持string转long,long转string防止精度丢失,支持非iso格式的日期转换。
    • 新增:WorkFlowBuilderContext新增UpdateMode属性,表示是否更新模式,当UpdateMode为true时,更新模式下会忽略AutoGenerateId属性,直接使用传入的工作流定义对象的Id。
  • 2.3.3
    • 修复:修复了net6.0/7.0/standard2.1包依赖版本不正确的问题。
  • 2.3.2
    • 升级:底层依赖包升级到9.0.7版本
    • 修复:修复了当注册了自定义IExpressionParser服务时未注册ParserOptions的错误。
    • 调整:调整IExpressionParser接口方法为异步方法。
  • 2.3.1
    • 修复:修复了DefaultWorkFlowBuilder默认构建器step步骤id赋值错误的问题
  • 2.3.0
    • 修复:修复了When条件表达式当运算符前后存在空格无法正常解析的问题;修复默认的action处理器无法正常绑定外部参数的问题。
    • 新增:WorkFlowBuilderContext新增AutoGenerateId属性,用于控制在工作流构建过程中是否使用自动生成id。
    • 新增:WorkFlowService在构建完工作流后根据id查找是否已存在工作流决定是新增工作流还是更新现有工作流。
    • 新增:IJsonSerializer添加Deserialize及GetDefaultJsonSerializerOptions方法。
    • 新增:IRemoteProcessor、IActionProcessor、ISqlProcessor的ExecuteSqlProcessorAsync方法增加表示工作流执行上下文的参数;默认的处理器添加了OnExcute虚方法,方便重写实现自定义逻辑。
    • 新增:WorkFlowExcutionContex执行上下文参数增加HasNext属性(表示是否有下一步骤)及Next委托(Next委托用于自我执行下一步骤,在FluentBuilder构建的基于类的处理器中可方便实现自我执行下一步)
    • 调整:一些逻辑的重构调整
    • 其他:新增了Easy.WorkFlow.FluentBuilder包,可通过Fluent Api以编程的方式构建工作流。
  • 2.2.2
    • WorkFlowBuilderContext新增Extras附加数据属性,允许在工作流构建过程中传递额外信息。
    • WorkFlowHandler的OnBuildedAsync方法新增WF参数(构建成功后返回的表示工作流定义的.net 对象),允许在工作流构建完成后进行额外处理。
  • 2.2.1
    • 添加注释文档
    • 完善使用说明
  • 2.2.0
    • 新增WorkFlow专用异常类WorkFlowException。
    • 新增WorkFlow统一规范化结果返回WorkFlowResult。
    • 新增统一结果提供服务IWorkFlowResultProvider,支持统一结果内容的返回处理。
    • 调整原工作流核心装饰器服务名称为WorkFlowHandler(工作流服务处理器)。
    • 新增基于约定的工作流服务处理器注册方式,继承WorkFlowHandler即可被WorkFlow扫描发现。
    • 新增统一结果提供服务的注册,可通过UseWorkFlowResultProvider<T>注册或直接实现一个IWorkFlowResultProvider类即可被WorkFlow扫描发现。
  • 2.1.0
    • 新增全局异常处理
    • 新增日志记录
    • 支持自定义工作流核心装饰器服务
    • 支持自定义工作流全局异常处理器

快速开始

1. 安装包

dotnet add package Easy.WorkFlow.Core

2. 注册服务

Program.csStartup.cs 中注册工作流服务:

// 基本注册
services.AddWorkFlow();

// 带配置的注册
services.AddWorkFlow(options =>
{
    //2.2.0新增
    // 自定义注册工作流处理器服务(2.1.0原名称:UseWorkFlowDecoratorService)
    // 或在你的项目中可直接继承默认的 WorkFlowHandler,无需注册即可被扫描发现。
    options.UseWorkFlowHandler<YourWorkFlowHandler>(); 

    //2.2.0新增
    // 自定义注册统一结果提供服务
    // 或在你的项目中直接实现IWorkFlowResultProvider,无需注册即可被扫描发现。
    options.UseWorkFlowResultProvider<YourResultProvider>();
    
    // 2.1.0新增
    options.EnableGlobalExceptionHandling=true; // 启用全局异常处理,默认开启
    options.RethrowExceptions=false; // 是否重新抛出异常,默认不抛出。

    // 2.1.0新增(2.2.0用UseWorkFlowHandler替代)
    // 自定义注册工作流核心装饰器服务,建议继承自默认的 WorkFlowHandler 类实现
    // 该装饰器可以在工作流执行前后添加额外的逻辑,可重写on开头的钩子方法。
    //options.UseWorkFlowDecoratorService<YourWorkFlowDecorator>();

    // 2.1.0新增
    // 自定义注册工作流全局异常处理器,需实现 IWorkFlowExceptionHandler 接口。
    options.UseExceptionHandler<YourWorkFlowExceptionHandler>();

    // 配置是否等待处理器完成
    options.WaitForProcessor = true;

    // 配置工作流表单数据的默认序列化行为
    options.JsonSerializer=(object? data)=>{
        // 使用你项目中安装的序列化器去序列化工作流表单数据,不配置默认使用System.Tex.Json序列化
       return JsonConvert.SerializeObject(jtoken); 
    };

    // 自定义工作流构建器,需实现IWorkFlowBuilder,不配置默认采用库自带的构建器,自带的构建器是从内存对象直接构建的,你可以实现基于json或xml的构建
    options.UseWorkFlowBuilder<Yourbuilder>();
    
    //自定义Id生成器,工作流实例Id生成器,需实现 IIdGenerator 接口,默认有个DefaultIdGenerator 可以生成分布式id
    options.UseIdGenerator<YourIdGenerator>();

    //你的自定义Action处理器;工作流处理器类型为Action时会调用该处理器,需实现 IActionProcessor 接口,不配置就使用库自带的默认处理器
    options.UseActionProcessor<YourActionProcessor>();

    //你的SQL处理器;工作流处理器类型为SQL时会调用该处理器,需实现 ISqlProcessor 接口,不配置就使用库自带的默认处理器
    //Easy.WorkFlow.SqlSugar包提供了基于SqlSugar的Sql处理器,可以实现基于sql的步骤处理。
    options.UseSqlProcessor<YourSqlProcessor>(); 

    //你的远程处理器;工作流处理器类型为远程URL时会调用该处理器,需实现 IRemoteProcessor 接口,不配置就使用库自带的默认处理器
    // 默认远程处理器基于HttpClient发生远程请求
    options.UseRemoteProcessor<YourRemoteProcessor>();  

    //你的步骤处理器执行器;当定义了工作流处理器该执行器会调用相应的处理器,
    //需实现IStepProcessorExecutor接口或者继承自DefaultStepProcessorExecutor类重写 ExecuteAsync 方法
    options.UseStepProcessorExecutor<YourStepProcessorExecutor>();

    // 自定义表达式解析器,包含了工作流Actors参与者表达式、工作流步骤条件表达式,需实现 IExpressionParser 接口或者继承自 DefaultExpressionParser 类重写相关方法
    //options.UseExpressionParser<YourExpressionParser>();

    // 自定义工作流实例激活器,用于激活工作流实例(实例化)及工作流步骤处理记录;需实现 IWorkFlowActivator 接口,默认有个 DefaultWorkFlowActivator 实现
    options.UseWorkFlowActivator<YourWorkFlowActivator>();

    // 自定义工作流存储仓储服务,需实现 IWorkFlowRepository 接口,默认有个 DefaultWorkFlowRepository 实现,你也可以使用基于SqlSugar的Easy.WorkFlow.SqlSugar包
    options.UseWorkFlowRepository<YourWorkFlowRepository>();

    // 配置远程处理器配置选项
    options.RemoteProcessorRequsetOptions = (configure) =>
    {
        // 远程请求的基础地址
        configure.BaseAddress = new Uri("https://api.example.com/");
        configure.DefaultRequestHeaders.Add("ApiKey", "your-api-key");
    };

    // 审批参与者表达式从工作流表单的解析配置
    options.ParserOptions = (configure) =>
    {
        configure.UserIdKey = "userId"; // 指定表单中UserIdKey的key
        configure.UserNameKey = "userName"; // 指定表单中UserNameKey的key
        configure.IsIgnoreCase = true; // 是否忽略大小写
    };
    
    // 更多配置...
});

3. 创建工作流定义

1、手动创建工作流定义对象:DL_WF(不推荐)

// 从内存中创建工作流定义,建议使用Easy.WorkFlow.JsonBuilder从json中解析工作流定义
var workflowDefinition = new DL_WF
{
    Name = "简单审批流程",
    Description = "一个简单的两步审批流程示例",
    Version = 1,
    CreatedTime = DateTime.Now,
    CreatedUserId = 1,
    CreatedUserName = "Admin",
    Steps = new List<DL_WFStep>
    {
        new DL_WFStep
        {
            Id = 1,
            Number = 0, // 初始步骤
            Name = "提交申请",
            ActorType = ActorType.User,
            Actors = new List<long> { 2 }, // 指定处理人ID
            ActorNames = new List<string> { "审批人A" }
        },
        new DL_WFStep
        {
            Id = 2,
            Number = 1,
            Name = "经理审批",
            ActorType = ActorType.User,
            Actors = new List<long> { 3 }, // 指定处理人ID
            ActorNames = new List<string> { "经理" }
        }
    }
};

// 构建工作流
var context = new WorkFlowBuilderContext<DL_WF>
{
    Data = workflowDefinition
};

var result = await _workflowService.BuildAsync(context);

2、使用json构建工作流(推荐)

{
  "id": 1001,
  "name": "请假工作流",
  "description": "请假审批",
  "version": 1,
  "steps": [
    {
      "id": 1,
      "wfId": 1001,
      "number": 0,
      "name": "请假申请",
      "description": "请假申请",
      "when": null,
      "processor": null,  
      "processorType": 1,
      "processorContext": null,
      "actors": null,
      "actorNames": null,
      "actorsExpression": null,
      "actorType": 1,
      "actionBtns": [
        {
          "name": "提交",
          "type": 1,
          "callback": null
        }
      ],
      "next": [
        2
      ]
    },
    {
      "id": 2,
      "wfId": 1001,
      "number": 1,
      "name": "审批",
      "description": "请假审批",
      "when": null, 
      "processor": null,
      "processorType": null,
      "processorContext": null,
      "actors": null,
      "actorNames": null,
      "actorsExpression": "[user]", 
      "actorType": 2,
      "actionBtns": [
        {
          "name": "同意",
          "type": 1,
          "callback": null
        },
        {
          "name": "拒绝",
          "type": 2,
          "callback": null
        }
      ],
      "next": null
    }
  ],
  "formName": "请假表单.json",
  "createdTime": "2025-06-18",
  "createdUserName": "cxj",
  "createdUserId": 10001
}

// program.cs或startup.cs中注册JsonBuilder
services.AddWorkFlow()
.AddJsonBuilder(options =>
    {
        // 配置json工作流定义文件存放路径(可选),如使用从json字符串构建工作流则不需要配置
        options.BasePath = Path.Combine(Directory.GetCurrentDirectory(), "json"); 
    });

var builderContext = new WorkFlowBuilderContext<string>
{
    SourceType = "json",
    Source = "工作流定义.json", // 从json文件中构建工作流定义
};

// 构建工作流并存储到仓储
var result = await workflowService.BuildAsync(builderContext);

// 或者从json字符串构建工作流定义
var builderContext = new WorkFlowBuilderContext<string>
{
    SourceType = "json",
    Source = null, 
    Data="json字符串"
};

// 构建工作流并存储到仓储
var result = await workflowService.BuildAsync(builderContext);

响应/返回结果内容示例:

{
    "code": 200,
    "isSuccess": true,
    "message": "构建成功",
    "data": {
        "id": 330182630739939328,
        "name": "请假工作流",
        "description": "请假审批",
        "version": 1,
        "steps": [
            {
                "id": 330182630752522240,
                "parentId": 0,
                "wfId": 330182630739939328,
                "number": 0,
                "name": "请假申请",
                "description": "请假申请",
                "when": null,
                "processor": "api/text",
                "processorType": 3,
                "processorContext": "{\"method\":\"post\",\"content\":\"userid=[user.userid]&username=[user.username]\"}",
                "actors": null,
                "actorNames": null,
                "actorsExpression": null,
                "actorType": 1,
                "actionBtns": [
                    {
                        "name": "提交",
                        "type": 1,
                        "callback": null
                    }
                ],
                "next": [
                    {
                        "id": 330182630773493760,
                        "parentId": 330182630752522240,
                        "wfId": 330182630739939328,
                        "number": 1,
                        "name": "审批",
                        "description": "请假审批",
                        "when": null,
                        "processor": "Insert INTO WF_Text (Name,date) VALUES (@name,@date)",
                        "processorType": 1,
                        "processorContext": "name=[user.username]&date=[date]",
                        "actors": null,
                        "actorNames": null,
                        "actorsExpression": "[user]",
                        "actorType": 2,
                        "actionBtns": [
                            {
                                "name": "同意",
                                "type": 1,
                                "callback": null
                            },
                            {
                                "name": "拒绝",
                                "type": 2,
                                "callback": null
                            }
                        ],
                        "next": null
                    }
                ]
            },
            {
                "id": 330182630773493760,
                "parentId": 330182630752522240,
                "wfId": 330182630739939328,
                "number": 1,
                "name": "审批",
                "description": "请假审批",
                "when": null,
                "processor": "Insert INTO WF_Text (Name,date) VALUES (@name,@date)",
                "processorType": 1,
                "processorContext": "name=[user.username]&date=[date]",
                "actors": null,
                "actorNames": null,
                "actorsExpression": "[user]",
                "actorType": 2,
                "actionBtns": [
                    {
                        "name": "同意",
                        "type": 1,
                        "callback": null
                    },
                    {
                        "name": "拒绝",
                        "type": 2,
                        "callback": null
                    }
                ],
                "next": null
            }
        ],
        "formName": "请假表单.json",
        "createdTime": "2025-06-18T06:14:30.894Z",
        "createdUserName": "cxj",
        "createdUserId": 10001,
        "updatedUserName": null,
        "updatedUserId": null,
        "updatedTime": null
    }
}

返回结果包含的内容太多?请参照自定义工作流结果提供服务

4. 启动工作流

 // 审批人信息,表示要从工作流表单中获取审批人信息
var approvalUser = new { UserId = 1002, UserName = "李四" };

// 创建启动请求
var request = new WorkFlowRequestContext
{
    WorkFlowId = workflowId, // 工作流定义ID
    UserId = 1002, // 发起人ID
    UserName = "李四", // 发起人姓名
    Data = new { Title = "请假申请", Days = 3, Reason = "个人事务",User=approvalUser } // 工作流表单数据,工作流步骤中可以通过表达式解析审批人信息("actorsExpression":"[user]")
};

// 启动工作流
var result = await _workflowService.StartAsync(request);

响应内容示例:

{
    "code": 200,
    "isSuccess": true,
    "message": "执行成功",
    "data": {
        "wfInstanceId": 330183486885466112,
        "stepId": 330182630773493760,
        "wfProcessId": 330183486898049024,
        "wfId": 330182630739939328,
        "stepName": "审批",
        "wfName": "请假工作流",
        "actorIds": [
            10002
        ],
        "actorNames": [
            "张三"
        ],
        "authorId": 10001,
        "authorName": "cxj",
        "jsonData": "{\"user\":{\"userid\":10002,\"username\":\"张三\"},\"date\":\"2025-06-24\"}",
        "processStatus": 1,
        "processResult": "发起",
        "processorExcutionResult": {
            "isSuccess": true,
            "message": "远程请求处理器执行成功",
            "startTime": "2025-06-30T11:11:17.8632144+08:00",
            "endTime": "2025-06-30T11:11:21.2433563+08:00",
            "duration": "00:00:03.3801419"
        },
        "waitForProcessor": true
    }
}

返回结果包含的内容太多?请参照自定义工作流结果提供服务

5. 运行工作流步骤(审批)

// 创建处理请求
var request = new WorkFlowRequestContext
{
    WorkFlowInstanceId = instanceId, // 工作流实例ID
    UserId = 10001, // 审批人ID
    UserName = "张三", // 审批人姓名
    ProcessingMessage = "同意请假申请", // 审批意见
    ProcessingSuggestion = ProcessStatus.Approve //审批意见枚举,Approve:同意,Reject:拒绝
};

// 处理步骤
var result =await _workflowService.RunStepAsync(request);

响应内容示例:

{
    "code": 200,
    "isSuccess": true,
    "message": "执行成功",
    "data": {
        "wfInstanceId": 330183486885466112,
        "stepId": 330182630773493760,
        "wfProcessId": 330183501666193408,
        "wfId": 330182630739939328,
        "stepName": "审批",
        "wfName": "请假工作流",
        "actorIds": null,
        "actorNames": null,
        "authorId": 10002,
        "authorName": "张三",
        "jsonData": "{\"user\":{\"userid\":10002,\"username\":\"张三\"},\"date\":\"2025-06-24\"}",
        "processStatus": 1,
        "processResult": "同意请假",
        "processorExcutionResult": {
            "isSuccess": true,
            "message": "SQL处理器执行成功",
            "startTime": "2025-06-30T11:12:57.1946878+08:00",
            "endTime": "2025-06-30T11:12:57.205425+08:00",
            "duration": "00:00:00.0107372"
        },
        "waitForProcessor": true
    }
}

返回结果包含的内容太多?请参照自定义工作流结果提供服务

在Asp.NetCore web项目中建议搭配使用Easy.WorkFlow.AspNetCore包,集成了工作流核心流程的处理请求中间件,无需实现api接口 使用方式:app.UseWorkFlow();

扩展点

Easy.WorkFlow.Core 提供了多个扩展点,允许您自定义工作流行为:

  • 自定义 ID 生成器:实现 IIdGenerator 接口
  • 自定义工作流仓储:实现 IWorkFlowRepository 接口
  • 自定义处理器:实现 IActionProcessorISqlProcessorIRemoteProcessor 接口
  • 自定义表达式解析器:实现 IExpressionParser 接口
  • 自定义工作流构建器:实现 IWorkFlowBuilder 接口

存储适配器

Easy.WorkFlow.Core 支持通过实现 IWorkFlowRepository 接口来适配不同的存储方式。 官方提供了以下存储适配器:

  • Easy.WorkFlow.SqlSugar:基于 SqlSugar ORM 的存储适配器,支持多种数据库

高级用法

使用步骤处理器

步骤处理器允许您在工作流步骤中执行自定义处理逻辑: 比如工作流步骤可能需要执行 SQL 语句、调用 Action 方法或执行远程API请求。

// SQL 处理器
var sqlStep = new DL_WFStep
{
    // 其他属性...
    ProcessorType = ProcessorType.SQL, //json定义:1表示SQL处理器,2表示Action处理器,3表示远程URL处理器
    Processor = "UPDATE Test SET Name =@name WHERE Id = @id", // SQL 语句
    ProcessorContext = "name=[user.username]&id=[id]" // 处理器上下文,从工作流表单数据中获取
};


// 远程处理器
var remoteStep = new DL_WFStep
{
    // 其他属性...
    ProcessorType = ProcessorType.URL,
    Processor = "api/orders/approve",
    ProcessorContext = "{\"method\":\"post\",\"content\":\"userid=[user.userid]&username=[user.username]\"}"
};

注意:远程处理器的上下文是一个对象

{
    "method": "post", // 请求方法
    "content": "userid=[user.userid]&username=[user.username]" // 请求体内容
}

使用参与者(审批人)表达式

从工作流表单中动态获取审批人或者你可以实现针对你项目的IExpressionParser。 默认的解析器使用工作流表单数据中的字段来解析参与者表达式,要求工作流表单属性值包含userid和username字段。

var dynamicActorStep = new DL_WFStep
{
    // 其他属性...
    ActorType = ActorType.Expression, //json定义:1表示用户,2表示表达式
    ActorsExpression = "[user]" // 从工作流表单中动态获取[user]属性值对应的审批人
};

工作流表单数据示例:

{
"user": {
    "userId": 1002,
    "userName": "李四"
  }"
}

ActorsExpression = "[user]"表示将从工作流表单数据中获取"user"属性对应的审批人信息。 你可以配置解析选项来指定工作流表单数据中参与者的字段名称。

    // 审批参与者表达式从工作流表单的解析配置
    options.ParserOptions = (configure) =>
    {
        configure.UserIdKey = "userId"; // 指定表单中UserIdKey的key
        configure.UserNameKey = "userName"; // 指定表单中UserNameKey的key
        configure.IsIgnoreCase = true; // 是否忽略大小写
    };

如果需要实现诸如基于角色、部门领导等更复杂的表达式解析逻辑,可以自定义实现IExpressionParser 接口。

使用条件表达式

工作流步骤支持条件分支表达式,允许您根据工作流表单数据动态决定下一步执行的步骤。 当同一级别有多个步骤时,可以使用When属性来定义条件表达式。

{
    "id": 1002,
    "name": "盖章申请",
    "description": "盖章申请",
    "version": 1,
    "steps": [
        {
            "id": 1,
            "wfId": 1002,
            "number": 0,
            "name": "盖章申请",
            "description": "盖章申请",
            "when": null,
            "processor": null,
            "processorType": null,
            "actors": null,
            "actorNames": null,
            "actorsExpression": null,
            "actorType": 1,
            "actionBtns": [
                {
                    "name": "提交",
                    "type": 1,
                    "callback": null
                }
            ],
            "next": [
                2,
                3
            ]
        },
        {
            "id": 2,
            "wfId": 1001,
            "number": 1,
            "name": "管理层审批",
            "description": "管理层审批",
            "when": "[type]==\"公章\" && [file]==\"方案\"",
            "processor": null,
            "processorType": null,
            "actors": null,
            "actorNames": null,
            "actorsExpression": "[approval.users]",
            "actorType": 2,
            "actionBtns": [
                {
                    "name": "同意",
                    "type": 1,
                    "callback": null
                },
                {
                    "name": "拒绝",
                    "type": 2,
                    "callback": null
                }
            ],
            "next": null
        },
        {
            "id": 3,
            "wfId": 1001,
            "number": 1,
            "name": "部门审批",
            "description": "部门审批",
            "when": "[type]==\"检测章\" && [file]==\"报告\"",
            "processor": null,
            "processorType": null,
            "actors": null,
            "actorNames": null,
            "actorsExpression": "[approval.users]",
            "actorType": 2,
            "actionBtns": [
                {
                    "name": "同意",
                    "type": 1,
                    "callback": null
                },
                {
                    "name": "拒绝",
                    "type": 2,
                    "callback": null
                }
            ],
            "next": null
        }
    ],
    "formName": "盖章申请表单.json",
    "createdTime": "2025-06-18T06:14:30.894Z",
    "createdUserName": "cxj",
    "createdUserId": 10001
}

上述示例中,步骤2和步骤3属于同一级别的步骤,将根据工作流表单数据中的type字段值及file字段进行条件判断,决定执行哪个步骤。 条件表达式支持运算符如下:

  • ==:等于
  • !=:不等于
  • &&:与
  • ||:或
  • >:大于
  • <:小于
  • >=:大于等于
  • <=:小于等于
  • 支持日期比较,如[date] > '2025-01-01'

如需实现更复杂的条件表达式解析逻辑,可以自定义实现IExpressionParser接口。

自定义工作流服务处理

您可以通过继承 WorkFlowHandler 类来实现自定义的工作流服务处理器。 重写 OnBuildingAsyncOnBuildedAsyncOnStartingAsyncOnStartedAsyncOnStepRunningAsyncOnStepRunedAsync 等方法来添加自定义逻辑。

public class CustomWorkFlowHandler : WorkFlowHandler
{
    // 在工作流启动前执行
    public override Task OnStartingAsync(WorkFlowRequestContext request)
        {
            logger.LogInformation("我启动了一个工作流");
            return Task.CompletedTask;
        }
}
// 其他钩子方法同理

实现后无需注册,WorkFlow会自动扫描。 你也可以通过 options.UseWorkFlowHandler<YourWorkFlowHandler>() 显式注册。

自定义工作流结果提供服务

您可以通过实现 IWorkFlowResultProvider 接口来自定义工作流结果的返回处理。

public class CustomWorkFlowResultProvider : IWorkFlowResultProvider
{
    /// <summary>
        /// 工作流构建异常结果处理
        /// </summary>
        /// <typeparam name="T">构建源类型</typeparam>
        /// <param name="exception">异常<see cref="WorkFlowException"/></param>
        /// <param name="context">构建上下文</param>
        /// <returns></returns>
        public Task<WorkFlowResult> OnBuildException<T>(WorkFlowException exception, WorkFlowBuilderContext<T> context) where T : class
        {
            if (exception.ValidationException)
            {
                return Task.FromResult(WorkFlowResult.BadRequest(exception.Message)
                    .WithData(context));
            }
            return Task.FromResult(WorkFlowResult.Fail(exception.Message)
                .WithData(context));
        }

        /// <summary>
        /// 工作流构建成功结果处理
        /// </summary>
        /// <typeparam name="T">构建源类型</typeparam>
        /// <param name="workFlow">构建完成的<see cref="WF"/></param>
        /// <param name="context">构建上下文</param>
        /// <returns></returns>
        public Task<WorkFlowResult> OnBuildSuccess<T>(WF workFlow, WorkFlowBuilderContext<T> context) where T : class
        {
            return Task.FromResult(WorkFlowResult.Success("构建成功").WithData(workFlow));
        }

        /// <summary>
        /// 工作流执行异常结果处理
        /// </summary>
        /// <param name="exception">异常<see cref="WorkFlowException"/></param>
        /// <param name="context">工作流执行上下文</param>
        /// <returns></returns>
        public Task<WorkFlowResult> OnExcutionException(WorkFlowException exception, WorkFlowRequestContext context)
        {
           // 你的异常结果处理逻辑

        }

        /// <summary>
        /// 工作流执行成功结果处理
        /// </summary>
        /// <param name="context">工作流执行上下文</param>
        /// <returns></returns>
        public Task<WorkFlowResult> OnExcutionSuccess(WorkFlowExcutionContext context)
        {
           // 你的成功结果处理逻辑
        }
}

WorkFlowResult是一个规范化的统一结果包装类,包含了状态码、是否成功、消息、额外数据等信息。 默认情况下,WorkFlow会使用内置的结果提供服务来返回包含特定内容的WorkFlowResult结果。 实现IWorkFlowResultProvider接口后可以自定义WorkFlowResult返回的内容,你可以自定义状态码、消息、额外数据等。 IWorkFlowResultProvider实现后无需注册,WorkFlow会自动扫描。 你也可以通过 options.UseWorkFlowResultProvider<YourResultProvider>() 显式注册。

自定义工作流全局异常处理器

您可以通过实现 IWorkFlowExceptionHandler 接口来自定义工作流全局异常处理器。

public class CustomWorkFlowExceptionHandler : IWorkFlowExceptionHandler
{
    public Task HandleExceptionAsync(Exception exception, string methodName, object context)
    {
        // 你的异常处理
        // 比如记录日志、发送通知等
        
    }
}

使用optipns.UseExceptionHandler<YourWorkFlowExceptionHandler>()注册即可。

注意事项

  • Easy.WorkFlow.Core使用内存存储工作流相关的领域数据,实际项目中你应该使用数据库存储。为此请实现IWorkFlowRepository,或者使用现有的包。
  • 在web项目中始终建议从json构建工作流,无需定义工作流对象。为此请使用Easy.WorkFlow.JsonBuilder包,或者实现你自己的Builder。
  • 如需定义内置的强类型的工作流,可使用Easy.WorkFlow.FluentBuilder包,使用提供的Fluent api以编程的方法构建工作流。

许可证

Easy.WorkFlow.Core 使用 MIT 许可证

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Easy.WorkFlow.Core:

Package Downloads
Easy.WorkFlow.SqlSugar

基于SqlSugar ORM的Easy.WorkFlow工作流存储适配器。

Easy.WorkFlow.AspNetCore

工作流请求处理中间件包,提供对工作流的构建、启动、执行、停止、挂起、恢复等请求的处理。

Easy.WorkFlow.JsonBuilder

基于json的工作流构建包,支持从json文件或json字符串构建工作流。

Easy.WorkFlow.FluentBuilder

支持Fluent Api以编程的方式构建持久化的工作流

GitHub repositories

This package is not used by any popular GitHub repositories.