Elsa-审批流实现

一、新建项目: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

运行效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大熊程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值