一、新建项目:ElsaFlowDemo
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\项目\OpenSourceProject\elsa-core-1.2.2\src\activities\Elsa.Activities.Console\Elsa.Activities.Console.csproj" />
<ProjectReference Include="..\..\..\..\项目\OpenSourceProject\elsa-core-1.2.2\src\activities\Elsa.Activities.Http\Elsa.Activities.Http.csproj" />
<ProjectReference Include="..\..\..\..\项目\OpenSourceProject\elsa-core-1.2.2\src\activities\Elsa.Activities.Workflows\Elsa.Activities.Workflows.csproj" />
<ProjectReference Include="..\..\..\..\项目\OpenSourceProject\elsa-core-1.2.2\src\core\Elsa\Elsa.csproj" />
<ProjectReference Include="..\..\..\..\项目\OpenSourceProject\elsa-core-1.2.2\src\persistence\Elsa.Persistence.EntityFrameworkCore\Elsa.Persistence.EntityFrameworkCore.csproj" />
</ItemGroup>
</Project>
Program.cs
using Elsa;
using Elsa.Activities;
using Elsa.Activities.Console;
using Elsa.Activities.Console.Activities;
using Elsa.Activities.Console.Extensions;
using Elsa.Activities.ControlFlow.Activities;
using Elsa.Activities.UserTask.Activities;
using Elsa.Activities.Workflows.Activities;
using Elsa.Expressions;
using Elsa.Extensions;
using Elsa.Models;
using Elsa.Persistence;
using Elsa.Persistence.EntityFrameworkCore.DbContexts;
using Elsa.Persistence.EntityFrameworkCore.Extensions;
using Elsa.Scripting.JavaScript;
using Elsa.Scripting.Liquid;
using Elsa.Services;
using Elsa.Services.Extensions;
using Elsa.Services.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ElsaFlowDemo
{
internal class Program
{
//Data Source=192.168.31.132;Initial Catalog=elsa;Persist Security Info=True;User ID=sa;Password=SQLOnLinux132"
static async Task Main(string[] args)
{
var services = BuildServices();
using var scope = services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<ElsaContext>();
// Ensure DB exists.
await dbContext.Database.EnsureCreatedAsync();
// Create a workflow definition.
var registry = services.GetService<IWorkflowRegistry>();
var workflowDefinition = await registry.GetWorkflowDefinitionAsync<HelloWorldWorkflow>();
// Mark this definition as the "latest" version.
//workflowDefinition.IsLatest = true;
workflowDefinition.Version = 1;
// Persist the workflow definition.
var definitionStore = scope.ServiceProvider.GetRequiredService<IWorkflowDefinitionStore>();
await definitionStore.SaveAsync(workflowDefinition);
// Flush to DB.
await dbContext.SaveChangesAsync();
// Load the workflow definition.
workflowDefinition = await definitionStore.GetByIdAsync(
workflowDefinition.DefinitionId,
VersionOptions.SpecificVersion(1));//VersionOptions.Latest
// Execute the workflow.
var invoker = scope.ServiceProvider.GetRequiredService<IWorkflowInvoker>();
var correlationId = Guid.NewGuid().ToString("N");
var executionContext = await invoker.StartAsync(workflowDefinition, new Variables() { ["Operator"] = new Variable("zhangshan") }, correlationId: correlationId);
// Persist the workflow instance.
var instanceStore = scope.ServiceProvider.GetRequiredService<IWorkflowInstanceStore>();
var workflowInstance = executionContext.Workflow.ToInstance();
await instanceStore.SaveAsync(workflowInstance);
// Flush to DB.
await dbContext.SaveChangesAsync();
//一级审批
Console.WriteLine("What action will you take? Choose one of: Approve, Reject, Needs Work");
var userAction = "Approve";
var instance = await instanceStore.GetByCorrelationIdAsync(correlationId);
var input = new Variables { ["Signal"] = new Variable(userAction), ["Operator"] = new Variable("zhangshan") };
WorkflowExecutionContext workflowContext = null;
if (instance.Status == WorkflowStatus.Faulted && instance.Fault != null)
{
workflowContext = await invoker.ResumeAsync(instance, input, startActivityIds: new string[] { instance.Fault.FaultedActivityId });
}
workflowContext = (await invoker.TriggerAsync(nameof(Signaled), input, correlationId: correlationId)).FirstOrDefault();
//查询指定实例当前的活动
instance = await instanceStore.GetByCorrelationIdAsync(correlationId);
if (!(instance.Status == WorkflowStatus.Aborted || instance.Status == WorkflowStatus.Finished || !instance.Scopes.Any(s => s.Variables.Any())))
{
var scopes = instance.Scopes.ToList();
var variables = instance.Scopes.LastOrDefault().Variables;
var variable = variables.Skip(variables.Count - 1).Take(1).FirstOrDefault();
var v = variable.Value.Value.ToString();
}
//查询指定实例审批等级及审批人
instance = await instanceStore.GetByCorrelationIdAsync(correlationId);
if (instance.Scopes.Any(s => s.Variables.Any()))
{
var scopes = instance.Scopes.ToList();
var variables = instance.Scopes.LastOrDefault().Variables;
var v = variables["Approvers"].Value.ToString();
}
//二级审批(拒绝)
Console.WriteLine("What action will you take? Choose one of: Approve, Reject, Needs Work");
userAction = "Reject";
instance = await instanceStore.GetByCorrelationIdAsync(correlationId);
input = new Variables { ["Signal"] = new Variable(userAction), ["Operator"] = new Variable("zhangshan") };
if (instance.Status == WorkflowStatus.Faulted && instance.Fault != null)
{
workflowContext = await invoker.ResumeAsync(instance, input, startActivityIds: new string[] { instance.Fault.FaultedActivityId });
}
workflowContext = (await invoker.TriggerAsync(nameof(Signaled), input, correlationId: correlationId)).FirstOrDefault();
//从暂停的位置开始
userAction = "Approve";
input = new Variables { ["Signal"] = new Variable(userAction), ["Operator"] = new Variable("zhangshan") };
instance = await instanceStore.GetByCorrelationIdAsync(correlationId);
workflowContext = (await invoker.TriggerAsync(nameof(Signaled), input, correlationId: correlationId)).FirstOrDefault();
}
private static IServiceProvider BuildServices()
{
return new ServiceCollection()
.AddElsa(
x => x.AddEntityFrameworkStores<SqlServerContext>(
options => options
.UseSqlServer(@"Data Source=192.168.31.132;Initial Catalog=elsa;Persist Security Info=True;User ID=sa;Password=SQLOnLinux132")))
.AddConsoleActivities()
.AddWorkflow<HelloWorldWorkflow>()
.AddActivity<DemoActivity>()
.AddActivity<DemoLegalActivity>()
.BuildServiceProvider();
}
}
public class HelloWorldWorkflow : IWorkflow
{
private void SetCurrentApprovers(DemoActivity demoActivity, List<string> approvers)
{
demoActivity.Approvers = approvers;
demoActivity.CurrentApprover = new LiquidExpression<string>("{{Input.Operator}}");
}
private void SetCurrentApprovers(DemoLegalActivity demoActivity, List<string> approvers)
{
demoActivity.Approvers = approvers;
demoActivity.CurrentApprover = new LiquidExpression<string>("{{Input.Operator}}");
}
private List<string> GetApprovers()
{
return new List<string> { "王五" };
}
public void Build(IWorkflowBuilder builder)
{
builder
.StartWith<WriteLine>(activity => activity.TextExpression = new LiteralExpression("Hello Worlduuuu!"))
.Then<SetVariable>(p => { p.VariableName = "name"; p.ValueExpression = new LiteralExpression<string>("李四"); })
.Then<SetVariable>(x =>
{
x.VariableName = "Approvers";
var approvers = new Dictionary<string, List<string>>() { { "一级", new List<string> { "a001员工" } }, { "二级", new List<string> { "a001员工" } } };
x.ValueExpression = new LiteralExpression<string>(Newtonsoft.Json.JsonConvert.SerializeObject(approvers));
})
.Then<DemoActivity>(x => SetCurrentApprovers(x, GetApprovers()))
//一级审批
.Then<Fork>(x => { x.Branches = new[] { "Approve", "Reject" }; }, fork =>
{
fork
.When($"Approve")
.Then<Signaled>(x => x.Signal = new LiteralExpression("Approve"))
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("一级审批Great! Your work has been accepted."))
.Then($"Join_0001");
fork
.When($"Reject")
.Then<Signaled>(x => x.Signal = new LiteralExpression("Reject"))
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("一级审批Sorry! Your work has been rejected."))
.Then($"Join_0001");
})
.Then<Join>(x => x.Mode = Join.JoinMode.WaitAny).WithName($"Join_0001")
.Then<SetVariable>(
x =>
{
x.VariableName = $"Approved_v0001";
x.ValueExpression = new JavaScriptExpression<object>("input('Signal') === 'Approve'");
}
)
.Then<IfElse>(
x => x.ConditionExpression = new JavaScriptExpression<bool>($"!!Approved_v0001"),
ifElse =>
{
ifElse
.When(OutcomeNames.True)
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("一级审批OutcomeNames.True"))
.Then($"Approvel_0001");
ifElse
.When(OutcomeNames.False)
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("一级审批OutcomeNames.False"))
.Then($"Approvel_0001");
}
)
.Then<Join>(x => x.Mode = Join.JoinMode.WaitAny).WithName($"Approvel_0001")
//二级审批
.Then<DemoActivity>(x => SetCurrentApprovers(x, GetApprovers()))
.Then<Fork>(x => { x.Branches = new[] { "Approve", "Reject" }; }, fork =>
{
fork
.When($"Approve")
.Then<Signaled>(x => x.Signal = new LiteralExpression("Approve"))
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("二级审批Great! Your work has been accepted."))
.Then($"Join_0002");
fork
.When($"Reject")
.Then<Signaled>(x => x.Signal = new LiteralExpression("Reject"))
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("二级审批Sorry! Your work has been rejected."))
.Then<DemoLegalActivity>(x => SetCurrentApprovers(x, GetApprovers()))//校验
.Then($"Join_0002");
})
.Then<Join>(x => x.Mode = Join.JoinMode.WaitAny).WithName($"Join_0002")
.Then<SetVariable>(
x =>
{
x.VariableName = $"Approved_v0002";
x.ValueExpression = new JavaScriptExpression<object>("input('Signal') === 'Approve'");
}
)
.Then<IfElse>(
x => x.ConditionExpression = new JavaScriptExpression<bool>($"!!Approved_v0002"),
ifElse =>
{
ifElse
.When(OutcomeNames.True)
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("二级审批OutcomeNames.True"))
.Then($"Approvel_0002");
ifElse
.When(OutcomeNames.False)
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("二级审批OutcomeNames.False"));
//.Then($"Approvel_0002");
}
)
.Then<Join>(x => x.Mode = Join.JoinMode.WaitAny).WithName($"Approvel_0002")
.Then<WriteLine>(activity => activity.TextExpression = new LiteralExpression("Workflow finished."));
}
}
}
DemoLegalActivity.cs
using Elsa;
using Elsa.Attributes;
using Elsa.Expressions;
using Elsa.Results;
using Elsa.Services;
using Elsa.Services.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ElsaFlowDemo
{
/// <summary>
/// 校验.
/// </summary>
[ActivityDefinition(
Category = "Workflow",
Description = "校验.",
Type = "",
Outcomes = new[] { OutcomeNames.Done }
)]
public class DemoLegalActivity : Activity
{
[ActivityProperty(Hint = "合法操作人.")]
public List<string> Approvers
{
get => GetState<List<string>>();
set => SetState(value);
}
[ActivityProperty(Hint = "当前操作人.")]
public WorkflowExpression<string> CurrentApprover
{
get => GetState(() => LiteralEvaluator.Expression<string>(null));
set => SetState(value);
}
protected override async Task<ActivityExecutionResult> OnExecuteAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
{
var employeeId = await workflowContext.EvaluateAsync(CurrentApprover, cancellationToken);
if (Approvers != null && !Approvers.Any(a => a == employeeId))
{
var conn = workflowContext.Workflow.Connections.FirstOrDefault(c => c.Target.Activity.Id == workflowContext.CurrentActivity.Id);
await conn.Source.Activity.ResumeAsync(workflowContext);
workflowContext.Halt(conn.Source.Activity);
return Halt();
}
if (workflowContext.Workflow.Status == Elsa.Models.WorkflowStatus.Faulted) workflowContext.Start();
return Done();
}
}
}
DemoActivity.cs
using Elsa;
using Elsa.Attributes;
using Elsa.Expressions;
using Elsa.Results;
using Elsa.Services;
using Elsa.Services.Models;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ElsaFlowDemo
{
[ActivityDefinition(
Category = "Workflow",
Description = "DemoActivity",
Type = "",
Outcomes = new[] { OutcomeNames.Done }
)]
public class DemoActivity : Activity
{
public DemoActivity()
{
}
[ActivityProperty(Hint = "审核操作人.")]
public List<string> Approvers
{
get => GetState<List<string>>();
set => SetState(value);
}
[ActivityProperty(Hint = "当前操作人.")]
public WorkflowExpression<string> CurrentApprover
{
get => GetState(() => LiteralEvaluator.Expression<string>(null));
set => SetState(value);
}
protected override async Task<ActivityExecutionResult> OnExecuteAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
{
var empl= await workflowContext.EvaluateAsync(CurrentApprover, cancellationToken);
return Done();
}
}
}
数据库:
delete from [dbo].ActivityDefinitions
delete from [dbo].ActivityInstances
delete from [dbo].BlockingActivities
delete from [dbo].ConnectionDefinitions
delete from [dbo].WorkflowDefinitionVersions
delete from [dbo].WorkflowInstances
select * from [dbo].ActivityDefinitions
select * from [dbo].ActivityInstances
select * from [dbo].BlockingActivities
select * from [dbo].ConnectionDefinitions
select * from [dbo].WorkflowDefinitionVersions
select * from [dbo].WorkflowInstances
运行效果: