xf 1 year ago
parent
commit
0cb36a1ed2

+ 45 - 8
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -144,12 +144,19 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId,
             _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId,
             externalId, cancellationToken);
             externalId, cancellationToken);
 
 
+        var startStepHandles = new List<WorkflowStepHandler>{WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
+            EFlowAssignType.User, _sessionContext.RequiredUserId, _sessionContext.UserName,
+            _sessionContext.RequiredOrgId, _sessionContext.OrgName)};
+
         var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
         var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
-            new List<Kv> { new(_sessionContext.RequiredUserId, _sessionContext.UserName) }, expiredTime);
+            new List<Kv> { new(_sessionContext.RequiredUserId, _sessionContext.UserName) },
+            startStepHandles, expiredTime);
 
 
         var flowAssignInfo =
         var flowAssignInfo =
             await GetNextStepFlowAssignInfoAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, cancellationToken);
             await GetNextStepFlowAssignInfoAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, cancellationToken);
 
 
+        
+
         var counterSignType = _workflowDomainService.GetCounterSignType(startStep.BusinessType);
         var counterSignType = _workflowDomainService.GetCounterSignType(startStep.BusinessType);
 
 
         //办理开始节点
         //办理开始节点
@@ -302,7 +309,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             dto.NextHandlers,
             dto.NextHandlers,
             cancellationToken);
             cancellationToken);
 
 
-        await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, expiredTime, cancellationToken);
+        var stepHandlers = await GetNextStepHandlersAsync(workflow, targetStepDefine, dto, cancellationToken);
+
+        await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, stepHandlers, expiredTime, cancellationToken);
     }
     }
 
 
     ///// <summary>
     ///// <summary>
@@ -339,10 +348,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             throw new UserFriendlyException("未找到实际办理节点");
             throw new UserFriendlyException("未找到实际办理节点");
 
 
         await _workflowDomainService.EndAsync(workflow, new BasicWorkflowDto
         await _workflowDomainService.EndAsync(workflow, new BasicWorkflowDto
-            {
-                Opinion = opinion,
-                Files = files
-            }, endStepDefine, currentStep,
+        {
+            Opinion = opinion,
+            Files = files
+        }, endStepDefine, currentStep,
             reviewResult, cancellationToken);
             reviewResult, cancellationToken);
     }
     }
 
 
@@ -623,13 +632,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             throw new UserFriendlyException("无效当前节点编号");
             throw new UserFriendlyException("无效当前节点编号");
         var quer = workflow.Steps.Where(d =>
         var quer = workflow.Steps.Where(d =>
             d.StepType != EStepType.End &&
             d.StepType != EStepType.End &&
-            d.IsOrigin );
+            d.IsOrigin);
         if (!isEnd)
         if (!isEnd)
         {
         {
             quer = quer.Where(d => d.Id != currentStep.Id);
             quer = quer.Where(d => d.Id != currentStep.Id);
         }
         }
         var originSteps = quer.ToList();
         var originSteps = quer.ToList();
-		var stepCodes = originSteps.Select(d => d.Code).ToList();
+        var stepCodes = originSteps.Select(d => d.Code).ToList();
         var stepDefines = workflow.WorkflowDefinition.FindStepDefines(stepCodes);
         var stepDefines = workflow.WorkflowDefinition.FindStepDefines(stepCodes);
 
 
         var dto = new NextStepsDto<RecallStepOption>
         var dto = new NextStepsDto<RecallStepOption>
@@ -1203,6 +1212,34 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             cancellationToken);
             cancellationToken);
     }
     }
 
 
+    private async ValueTask<List<WorkflowStepHandler>> GetNextStepHandlersAsync(Workflow workflow,
+        StepDefine nextStepDefine, BasicWorkflowDto dto, CancellationToken cancellationToken)
+    {
+        var assignType = FlowAssignInfo.GetAssignType(nextStepDefine.HandlerType);
+        //var assignType = AssignInfo.GetAssignType(nextStepDefine.HandlerType, dto.NextHandlers.Any());
+        switch (assignType)
+        {
+            case EFlowAssignType.Org:
+                return dto.NextHandlers.Select(d => WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
+                    assignType, orgId: d.Key, orgName: d.Value)).ToList();
+            case EFlowAssignType.User:
+                var userIds = dto.NextHandlers.Select(d => d.Key).ToList();
+                var users = await _userRepository.Queryable()
+                    .Includes(d => d.Organization)
+                    .Where(d => userIds.Contains(d.Id))
+                    .ToListAsync(cancellationToken);
+                return users.Select(d => WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
+                        assignType, d.Id, d.Name, d.OrgId, d.Organization.Name))
+                    .ToList();
+            //case EFlowAssignType.Role:
+            //    handlers = dto.NextHandlers.Select(d => WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
+            //        assignType, roleId: d.Key, roleName: d.Value)).ToList();
+            //    break;
+            default:
+                throw new ArgumentOutOfRangeException();
+        }
+    }
+
     /// <summary>
     /// <summary>
     /// 按流程模板配置创建下一步办理对象
     /// 按流程模板配置创建下一步办理对象
     /// </summary>
     /// </summary>

+ 2 - 2
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -62,7 +62,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 撤回(返回到之前任意节点)
         /// 撤回(返回到之前任意节点)
         /// </summary>
         /// </summary>
         Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
         Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
-            DateTime? expiredTime, CancellationToken cancellationToken);
+            List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime, CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
         /// 撤回至开始节点
         /// 撤回至开始节点
@@ -147,7 +147,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 创建开始节点
         /// 创建开始节点
         /// </summary>
         /// </summary>
         WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto,
         WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto,
-            List<Kv> handlers, DateTime? expiredTime);
+            List<Kv> handlers, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime);
 
 
         /// <summary>
         /// <summary>
         /// 查询未完成节点
         /// 查询未完成节点

+ 10 - 8
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -717,7 +717,8 @@ namespace Hotline.FlowEngine.Workflows
         /// 撤回(返回到之前任意节点)
         /// 撤回(返回到之前任意节点)
         /// </summary>
         /// </summary>
         public async Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
         public async Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
-            FlowAssignInfo flowAssignInfo, DateTime? expiredTime, CancellationToken cancellationToken)
+            FlowAssignInfo flowAssignInfo, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime,
+            CancellationToken cancellationToken)
         {
         {
             var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
             var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
             if (targetStep is null)
             if (targetStep is null)
@@ -727,7 +728,7 @@ namespace Hotline.FlowEngine.Workflows
             await RecallTraceAsync(workflow.Id, dto.Opinion, cancellationToken);
             await RecallTraceAsync(workflow.Id, dto.Opinion, cancellationToken);
 
 
             var isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStep,
             var isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStep,
-                EWorkflowTraceStatus.Recall, expiredTime, cancellationToken);
+                EWorkflowTraceStatus.Recall, stepHandlers, expiredTime, cancellationToken);
 
 
             workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
             workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
 
 
@@ -1075,7 +1076,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 创建开始节点
         /// 创建开始节点
         /// </summary>
         /// </summary>
         public WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine,
         public WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine,
-            BasicWorkflowDto dto, List<Kv> handles, DateTime? expiredTime)
+            BasicWorkflowDto dto, List<Kv> handles, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime)
         {
         {
             //startstep
             //startstep
             var nextSteps = _mapper.Map<List<StepSimple>>(startStepDefine.NextSteps);
             var nextSteps = _mapper.Map<List<StepSimple>>(startStepDefine.NextSteps);
@@ -1090,6 +1091,7 @@ namespace Hotline.FlowEngine.Workflows
             _mapper.Map(dto, startStep);
             _mapper.Map(dto, startStep);
             _mapper.Map(workflow, startStep);
             _mapper.Map(workflow, startStep);
             startStep.Handlers = handles;
             startStep.Handlers = handles;
+            startStep.StepHandlers = stepHandlers;
             startStep.NextSteps = nextSteps;
             startStep.NextSteps = nextSteps;
             startStep.IsMain = true;
             startStep.IsMain = true;
             startStep.IsOrigin = true;
             startStep.IsOrigin = true;
@@ -1222,10 +1224,10 @@ namespace Hotline.FlowEngine.Workflows
         }
         }
 
 
         private async Task<WorkflowStep> CreateStartStepAsync(Workflow workflow, StepDefine startStepDefine,
         private async Task<WorkflowStep> CreateStartStepAsync(Workflow workflow, StepDefine startStepDefine,
-            BasicWorkflowDto dto, List<Kv> handles, EWorkflowTraceStatus traceStatus, DateTime? expiredTime,
-            CancellationToken cancellationToken)
+            BasicWorkflowDto dto, List<Kv> handles, List<WorkflowStepHandler> stepHandlers, EWorkflowTraceStatus traceStatus,
+            DateTime? expiredTime, CancellationToken cancellationToken)
         {
         {
-            var startStep = CreateStartStep(workflow, startStepDefine, dto, handles, expiredTime);
+            var startStep = CreateStartStep(workflow, startStepDefine, dto, handles, stepHandlers, expiredTime);
             await _workflowStepRepository.AddAsync(startStep, cancellationToken);
             await _workflowStepRepository.AddAsync(startStep, cancellationToken);
             await CreateTraceAsync(workflow, startStep, traceStatus, cancellationToken);
             await CreateTraceAsync(workflow, startStep, traceStatus, cancellationToken);
             return startStep;
             return startStep;
@@ -1723,7 +1725,7 @@ namespace Hotline.FlowEngine.Workflows
 
 
         private async Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, FlowAssignInfo flowAssignInfo,
         private async Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, FlowAssignInfo flowAssignInfo,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceStatus traceStatus,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceStatus traceStatus,
-            DateTime? expiredTime, CancellationToken cancellationToken)
+            List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime, CancellationToken cancellationToken)
         {
         {
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
 
 
@@ -1750,7 +1752,7 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.SetStatusRunnable();
                 workflow.SetStatusRunnable();
 
 
             var targetStepNew = targetIsStartStep
             var targetStepNew = targetIsStartStep
-                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, traceStatus, expiredTime,
+                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, stepHandlers, traceStatus, expiredTime,
                     cancellationToken)
                     cancellationToken)
                 : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                 : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers,

+ 84 - 2
src/Hotline/FlowEngine/Workflows/WorkflowStepHandler.cs

@@ -1,5 +1,7 @@
-using SqlSugar;
+using Hotline.Share.Dtos;
+using SqlSugar;
 using XF.Domain.Entities;
 using XF.Domain.Entities;
+using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Domain.Repository;
 
 
 namespace Hotline.FlowEngine.Workflows;
 namespace Hotline.FlowEngine.Workflows;
@@ -27,6 +29,86 @@ public class WorkflowStepHandler : CreationEntity
     /// </summary>
     /// </summary>
     public bool IsActualHandler { get; set; }
     public bool IsActualHandler { get; set; }
 
 
-    [Navigate(NavigateType.ManyToOne, nameof(WorkflowStepHandler.WorkflowStepId))]
+    [Navigate(NavigateType.ManyToOne, nameof(WorkflowStepId))]
     public WorkflowStep WorkflowStep { get; set; }
     public WorkflowStep WorkflowStep { get; set; }
+
+    #region method
+
+    public static WorkflowStepHandler Create(string workflowId, string externalId, EFlowAssignType flowAssignType, string? userId = null, string? username = null,
+        string? orgId = null, string? orgName = null, string? roleId = null, string? roleName = null)
+    {
+        var handler = new WorkflowStepHandler
+        {
+            WorkflowId = workflowId,
+            ExternalId = externalId,
+        };
+        handler.Assign(flowAssignType, userId, username, orgId, orgName, roleId, roleName);
+        return handler;
+    }
+
+    public void Assign(EFlowAssignType assignType, string? userId, string? username,
+        string? orgId, string? orgName, string? roleId, string? roleName)
+    {
+        FlowAssignType = assignType;
+        switch (assignType)
+        {
+            case EFlowAssignType.Org:
+                if (string.IsNullOrEmpty(orgId) || string.IsNullOrEmpty(orgName))
+                    throw new ArgumentNullException(nameof(orgId));
+                OrgId = orgId;
+                OrgName = orgName;
+                break;
+            case EFlowAssignType.User:
+                if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(username) ||
+                   string.IsNullOrEmpty(orgId) || string.IsNullOrEmpty(orgName))
+                    throw new ArgumentNullException(nameof(userId));
+                UserId = userId;
+                Username = username;
+                OrgId = orgId;
+                OrgName = orgName;
+                break;
+            //case EFlowAssignType.Role:
+            //    if (string.IsNullOrEmpty(roleId) || string.IsNullOrEmpty(roleName))
+            //        throw new ArgumentNullException(nameof(roleId));
+            //    RoleId = roleId;
+            //    RoleName = roleName;
+            //    break;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(assignType), assignType, null);
+        }
+    }
+
+    public bool IsHandler(ICollection<string> roleIds, string? userId = null, string? orgId = null)
+    {
+        switch (FlowAssignType)
+        {
+            case EFlowAssignType.Org:
+                if (string.IsNullOrEmpty(OrgId))
+                    throw new UserFriendlyException($"数据异常, {nameof(OrgId)}");
+                return OrgId.Equals(orgId, StringComparison.OrdinalIgnoreCase);
+            case EFlowAssignType.User:
+                if (string.IsNullOrEmpty(UserId))
+                    throw new UserFriendlyException($"数据异常, {nameof(UserId)}");
+                return UserId.Equals(userId, StringComparison.OrdinalIgnoreCase);
+            //case EFlowAssignType.Role:
+            //    if (string.IsNullOrEmpty(RoleId))
+            //        throw new UserFriendlyException($"数据异常, {nameof(RoleId)}");
+            //    return roleIds.Any() && roleIds.Contains(RoleId, StringComparer.OrdinalIgnoreCase);
+            default:
+                throw new ArgumentOutOfRangeException();
+        }
+    }
+
+    public Kv GetHandler()
+    {
+        return FlowAssignType switch
+        {
+            EFlowAssignType.Org => new Kv(OrgId, OrgName),
+            EFlowAssignType.User => new Kv(UserId, Username),
+            //EFlowAssignType.Role => new Kv(RoleId, RoleName),
+            _ => throw new ArgumentOutOfRangeException()
+        };
+    }
+
+    #endregion
 }
 }