Elsa 3.0 审批流实战:2级审批与自定义活动开发(附完整代码)

发布时间:2026/7/11 8:00:18

Elsa 3.0 审批流实战:2级审批与自定义活动开发(附完整代码) Elsa 3.0 审批流实战构建高效的两级审批系统与自定义活动开发在当今企业数字化转型浪潮中工作流引擎已成为提升业务流程自动化水平的核心组件。Elsa Workflows作为.NET生态中备受瞩目的开源工作流引擎凭借其灵活的设计和强大的扩展能力正在改变开发者构建复杂业务流程的方式。本文将深入探讨如何利用Elsa 3.0构建一个完整的两级审批系统涵盖从基础架构到高级定制的全方位实践。1. 环境准备与项目初始化在开始构建审批流之前我们需要搭建合适的开发环境。确保已安装以下组件.NET 6.0或更高版本Visual Studio 2022或VS CodeSQL Server或其它支持的数据库创建新项目并添加必要的NuGet包dotnet new console -n ElsaApprovalDemo cd ElsaApprovalDemo dotnet add package Elsa.Core dotnet add package Elsa.Persistence.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.SqlServer基础服务配置是项目成功的关键。在Program.cs中配置Elsa服务var services new ServiceCollection() .AddElsa(elsa elsa .UseEntityFrameworkPersistence(ef ef.UseSqlServer(connectionString)) .AddConsoleActivities() .AddWorkflowApprovalWorkflow() .AddActivityDemoActivity() .AddActivityDemoLegalActivity()) .BuildServiceProvider();关键配置说明配置项说明推荐值Persistence工作流持久化方式EntityFrameworkCoreActivities可用活动类型根据需求添加Workflows注册的工作流定义自定义工作流类2. 审批流核心架构设计两级审批系统的核心在于状态的流转与控制。我们需要设计清晰的审批状态模型graph TD A[提交申请] -- B{一级审批} B --|通过| C{二级审批} B --|拒绝| D[流程终止] C --|通过| E[流程完成] C --|拒绝| F[退回修改] F -- B状态转换关键点审批层级控制明确区分一级和二级审批的权限边界状态持久化确保每次审批操作都能正确记录和恢复异常处理考虑审批超时、审批人缺席等异常场景数据库表设计应考虑以下核心字段CREATE TABLE WorkflowInstances ( Id NVARCHAR(450) PRIMARY KEY, DefinitionId NVARCHAR(450) NOT NULL, Status INT NOT NULL, CorrelationId NVARCHAR(450), CreatedAt DATETIME2 NOT NULL, LastExecutedAt DATETIME2, Data NVARCHAR(MAX) -- 存储审批相关变量 );3. 自定义审批活动开发Elsa的强大之处在于允许开发者创建完全自定义的活动。我们首先实现基础的DemoActivity[ActivityDefinition( Category Approval, Description 基础审批活动, Outcomes new[] { Approved, Rejected, NeedsWork })] public class DemoActivity : Activity { [ActivityProperty(Hint 审批人列表)] public Liststring Approvers { get; set; } new(); [ActivityProperty(Hint 当前操作人)] public WorkflowExpressionstring CurrentApprover { get; set; } new(); protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) { var operatorId await context.EvaluateAsync(CurrentApprover, context.CancellationToken); if (!Approvers.Contains(operatorId)) { context.JournalData.Add(Error, 操作人无审批权限); await context.CompleteActivityAsync(Rejected); return; } // 实际业务中这里可以添加更复杂的审批逻辑 await context.CompleteActivityAsync(Approved); } }对于需要法律合规审查的场景我们可以扩展专门的LegalApprovalActivitypublic class DemoLegalActivity : DemoActivity { [ActivityProperty(Hint 法律条款引用)] public string LegalClause { get; set; } protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) { // 先执行基础审批逻辑 await base.ExecuteAsync(context); // 添加法律合规检查 if (!CheckLegalCompliance(LegalClause)) { context.JournalData.Add(LegalIssue, $违反法律条款: {LegalClause}); await context.CompleteActivityAsync(Rejected); } } private bool CheckLegalCompliance(string clause) { // 实际项目中这里实现具体的法律合规检查 return true; } }自定义活动最佳实践清晰的属性标注使用[ActivityProperty]提供元数据完善的错误处理记录详细的日志信息可测试性设计确保活动可以独立于工作流测试文档注释为每个活动添加XML注释说明用法4. 完整的两级审批工作流实现结合自定义活动我们可以构建完整的两级审批工作流。以下是核心实现代码public class ApprovalWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) { builder .StartWithSetVariable(set set.VariableName ApprovalLevel) .WithName(SetInitialLevel) .ThenSetVariable(set set.VariableName ApprovalStatus) // 第一级审批 .ThenDemoActivity(act { act.Approvers new Liststring { manager1, manager2 }; act.CurrentApprover new JavaScriptExpressionstring(input.Operator); }).WithName(FirstLevelApproval) .ThenFork(fork fork.Branches new[] { Approve, Reject }, fork { fork.When(Approve) .ThenWriteLine(w w.Text 一级审批通过) .Then(Join_Level1); fork.When(Reject) .ThenWriteLine(w w.Text 一级审批拒绝) .ThenSetVariable(set set.VariableName ApprovalStatus) .Then(Join_Level1); }) // 第二级审批 .ThenJoin(join join.Mode Join.JoinMode.WaitAny).WithName(Join_Level1) .ThenIfElse(ifElse ifElse.Condition new JavaScriptExpressionbool(getVariable(ApprovalStatus) Approved), ifElse { ifElse.When(OutcomeNames.True) .ThenDemoLegalActivity(act { act.Approvers new Liststring { director1 }; act.CurrentApprover new JavaScriptExpressionstring(input.Operator); act.LegalClause GDPR Compliance; }).WithName(SecondLevelApproval) .ThenFork(fork fork.Branches new[] { Approve, Reject }, fork { fork.When(Approve) .ThenWriteLine(w w.Text 二级审批通过) .Then(Join_Level2); fork.When(Reject) .ThenWriteLine(w w.Text 二级审批拒绝) .ThenSetVariable(set set.VariableName ApprovalStatus) .Then(Join_Level2); }); ifElse.When(OutcomeNames.False) .ThenWriteLine(w w.Text 流程终止); }) // 流程结束 .ThenJoin(join join.Mode Join.JoinMode.WaitAny).WithName(Join_Level2) .ThenWriteLine(w w.Text 审批流程结束); } }工作流设计要点状态管理使用变量跟踪审批状态分支逻辑清晰处理各种审批结果活动命名为关键活动添加有意义的名称错误处理考虑所有可能的异常路径5. 数据库集成与状态查询持久化是审批系统的核心需求。Elsa提供了多种持久化方案我们使用Entity Framework Core实现// 配置EF Core持久化 services.AddElsa(elsa elsa .UseEntityFrameworkPersistence(ef ef.UseSqlServer(Configuration.GetConnectionString(Default)))); // 查询特定工作流实例 var instance await workflowInstanceStore.GetByCorrelationIdAsync(correlationId); // 获取审批历史 var activities await activityExecutionLogStore.ListAsync( new ActivityExecutionLogRecordFilter { WorkflowInstanceId instance.Id });常见查询场景示例-- 获取待审批项 SELECT * FROM WorkflowInstances WHERE Status 3 -- Suspended状态 AND JSON_VALUE(Data, $.CurrentApprover) user123 -- 统计审批效率 SELECT AVG(DATEDIFF(MINUTE, CreatedAt, LastExecutedAt)) as AvgApprovalTime, COUNT(CASE WHEN JSON_VALUE(Data, $.Result) Approved THEN 1 END) as ApprovedCount FROM WorkflowInstances WHERE DefinitionId ApprovalWorkflow6. 高级功能与性能优化对于企业级应用我们需要考虑更高级的功能和性能优化审批委派机制public class DelegatedApprovalActivity : DemoActivity { [ActivityProperty(Hint 委派审批人)] public WorkflowExpressionstring DelegateTo { get; set; } protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) { var delegateTo await context.EvaluateAsync(DelegateTo, context.CancellationToken); if (!string.IsNullOrEmpty(delegateTo)) { context.SetVariable(CurrentApprover, delegateTo); } await base.ExecuteAsync(context); } }性能优化策略批量操作对大量审批项使用批量处理缓存机制缓存频繁访问的工作流定义异步处理非关键路径采用异步执行索引优化为常用查询字段添加数据库索引监控与审计// 添加审计日志中间件 services.AddElsa(elsa elsa .AddActivityAuditLogActivity() .AddWorkflowMiddlewareAuditMiddleware()); public class AuditMiddleware : IWorkflowMiddleware { public async Task InvokeAsync(WorkflowMiddlewareContext context, WorkflowMiddlewareDelegate next) { var workflow context.Workflow; Log.Information($Workflow {workflow.Id} started by {workflow.CreatedBy}); await next(); Log.Information($Workflow {workflow.Id} completed with status {workflow.Status}); } }7. 测试与调试策略可靠的审批系统需要完善的测试覆盖单元测试示例[Test] public async Task DemoActivity_ShouldReject_WhenInvalidApprover() { // 准备 var activity new DemoActivity { Approvers new Liststring { user1 }, CurrentApprover new LiteralExpressionstring(user2) }; var context new ActivityExecutionContext( serviceProvider: new ServiceCollection().BuildServiceProvider(), workflowExecutionContext: new WorkflowExecutionContext(), activity: activity); // 执行 await activity.ExecuteAsync(context); // 断言 Assert.AreEqual(Rejected, context.Outcomes.First()); }集成测试要点完整流程测试验证从提交到最终审批的全流程异常场景测试模拟网络中断、数据库故障等情况性能测试评估系统在高负载下的表现安全测试确保审批权限控制有效调试技巧// 在开发环境启用详细日志 services.AddLogging(logging logging .AddConsole() .AddDebug() .SetMinimumLevel(LogLevel.Debug)); // 使用Elsa仪表盘实时监控 services.AddElsaDashboard();8. 部署与扩展建议将审批系统投入生产环境需要考虑以下方面容器化部署FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app COPY ./publish . ENTRYPOINT [dotnet, ElsaApprovalDemo.dll]扩展架构水平扩展无状态工作流实例允许横向扩展消息队列使用RabbitMQ或Azure Service Bus处理高吞吐量微服务集成将审批服务作为独立微服务部署未来扩展方向移动审批开发配套移动端应用AI辅助引入机器学习预测审批结果区块链存证重要审批上链存证多租户支持服务多个独立客户通过本文的实践我们构建了一个基于Elsa 3.0的完整两级审批系统。从基础架构到高级定制从数据库设计到性能优化这套方案可以满足大多数企业的审批流程需求。Elsa的灵活性和扩展性使得它能够适应各种复杂的业务场景是.NET生态中工作流实现的优秀选择。

相关新闻