Kaynağa Gözat

取消WorkflowApplication.StartWorkflowAsync的引用

xfe 2 ay önce
ebeveyn
işleme
939c87c8c2

+ 5 - 3
src/Hotline.Api/Controllers/OrderController.cs

@@ -2027,10 +2027,11 @@ public class OrderController : BaseController
             startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderDelay;
             startDto.Opinion = model.DelayReason;
             startDto.Title = "申请延期流程";
-            string workFlowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id,
-                cancellationToken: HttpContext.RequestAborted);
+            // string workFlowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id,
+            //     cancellationToken: HttpContext.RequestAborted);
             //model.WorkflowId = workFlowId;
             //await _orderDelayRepository.UpdateAsync(model, HttpContext.RequestAborted);
+            await _workflowDomainService.StartAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
         }
         catch (Exception ex)
         {
@@ -2609,13 +2610,14 @@ public class OrderController : BaseController
             startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderScreen;
             startDto.Opinion = dto.Data.Content;
             startDto.Title = "申请甄别流程";
-            workflowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
+            //workflowId = await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
             //var screen = await _orderScreenRepository.GetAsync(model.Id, HttpContext.RequestAborted);
             //if (screen != null)
             //{
             //    screen.WorkflowId = workflowId;
             //    await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
             //}
+            await _workflowDomainService.StartAsync(startDto,model.Id, cancellationToken: HttpContext.RequestAborted);
         }
         catch (Exception e)
         {

+ 2 - 1
src/Hotline.Api/Controllers/OrderRevocationController.cs

@@ -153,7 +153,8 @@ namespace Hotline.Api.Controllers
                                     Title = order.Title,
                                     Opinion = dto.RevocationReason,
                                 };
-                                await _workflowApplication.StartToEndAsync(startDto, order.Id, order.ExpiredTime, HttpContext.RequestAborted);
+                                // await _workflowApplication.StartToEndAsync(startDto, order.Id, order.ExpiredTime, HttpContext.RequestAborted);
+                                await _workflowDomainService.StartToEndAsync(startDto, order.Id, order.ExpiredTime, HttpContext.RequestAborted);
                             }
                             else
                             {

+ 2 - 1
src/Hotline.Api/Controllers/OrderTerminateController.cs

@@ -175,7 +175,8 @@ namespace Hotline.Api.Controllers
 				startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderTerminate;
 				startDto.Opinion = dto.Data.Content;
 				startDto.Title = "申请终止流程";
-				await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
+				// await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
+				await _workflowDomainService.StartAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
 			}
 			catch (Exception e)
 			{

+ 8 - 2
src/Hotline.Api/Controllers/PbxController.cs

@@ -32,6 +32,7 @@ using Microsoft.Extensions.Options;
 using XF.Domain.Repository;
 using Tr.Sdk;
 using Hotline.Configurations;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 
 namespace Hotline.Api.Controllers
@@ -56,6 +57,7 @@ namespace Hotline.Api.Controllers
         private readonly IRepository<TrunkIvrManager> _trunkIvrManagerRepository;
         private readonly IIvrCategoryRepository _ivrCategoryRepository;
         private readonly IWorkflowApplication _workflowApplication;
+        private readonly IWorkflowDomainService _workflowDomainService;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
         private readonly IIvrDomainService _ivrDomainService;
         private readonly IIvrCacheManager _ivrCacheManager;
@@ -84,6 +86,7 @@ namespace Hotline.Api.Controllers
             IRepository<TrunkIvrManager> trunkIvrManagerRepository,
             IIvrCategoryRepository ivrCategoryRepository,
             IWorkflowApplication workflowApplication,
+            IWorkflowDomainService workflowDomainService,
             ISystemSettingCacheManager systemSettingCacheManager,
             IIvrDomainService ivrDomainService,
             IIvrCacheManager ivrCacheManager,
@@ -110,6 +113,7 @@ namespace Hotline.Api.Controllers
             _trunkIvrManagerRepository = trunkIvrManagerRepository;
             _ivrCategoryRepository = ivrCategoryRepository;
             _workflowApplication = workflowApplication;
+            _workflowDomainService = workflowDomainService;
             _systemSettingCacheManager = systemSettingCacheManager;
             _ivrDomainService = ivrDomainService;
             _ivrCacheManager = ivrCacheManager;
@@ -301,7 +305,8 @@ namespace Hotline.Api.Controllers
                 startWorkflowDto.DefinitionModuleCode = WorkflowModuleConsts.TelRestApply;
                 startWorkflowDto.Opinion = dto.Reason;
                 startWorkflowDto.Title = "分机休息申请流程";
-				await _workflowApplication.StartWorkflowAsync(startWorkflowDto, telRest.Id, cancellationToken: HttpContext.RequestAborted);
+				// await _workflowApplication.StartWorkflowAsync(startWorkflowDto, telRest.Id, cancellationToken: HttpContext.RequestAborted);
+				await _workflowDomainService.StartAsync(startWorkflowDto, telRest.Id, cancellationToken: HttpContext.RequestAborted);
             }
         }
 
@@ -337,7 +342,8 @@ namespace Hotline.Api.Controllers
             startWorkflowDto.DefinitionModuleCode = WorkflowModuleConsts.TelRestApply;
             startWorkflowDto.Opinion = dto.Reason;
             startWorkflowDto.Title = "分机休息申请流程";
-			await _workflowApplication.StartWorkflowAsync(startWorkflowDto, telRest.Id, cancellationToken: HttpContext.RequestAborted);
+			// await _workflowApplication.StartWorkflowAsync(startWorkflowDto, telRest.Id, cancellationToken: HttpContext.RequestAborted);
+			await _workflowDomainService.StartAsync(startWorkflowDto, telRest.Id, cancellationToken: HttpContext.RequestAborted);
         }
 
 

+ 0 - 6
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -112,12 +112,6 @@ namespace Hotline.Application.FlowEngine
             GetPreviousInformationAsync(string workflowId, string operatorId, string operatorOrgId, string[] roles,
                 CancellationToken cancellationToken);
 
-        /// <summary>
-        /// 开启流程直接归档
-        /// </summary>
-        Task StartToEndAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
-            CancellationToken cancellationToken = default);
-
         /// <summary>
         /// 更新省平台办理结果节点附件
         /// </summary>

+ 0 - 21
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -1841,27 +1841,6 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         return (currentStep, prevStep, isOrgToCenter, isSecondToFirstOrgLevel);
     }
 
-    /// <summary>
-    /// 开启流程直接归档
-    /// </summary>
-    public async Task StartToEndAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
-        CancellationToken cancellationToken = default)
-    {
-        var wfModule = await GetWorkflowModuleAsync(dto.DefinitionModuleCode, cancellationToken);
-        var definition = wfModule.Definition;
-        if (definition == null)
-            throw new UserFriendlyException("无效模板编码");
-        if (definition.Status is not EDefinitionStatus.Enable)
-            throw new UserFriendlyException("该模板不可用");
-
-        var endStepDefine = definition.FindEndStepDefine();
-        dto.NextStepCode = endStepDefine.Code;
-        dto.NextStepName = endStepDefine.Name;
-        dto.FlowDirection = EFlowDirection.CenterToFile;
-
-        await StartWorkflowAsync(dto, externalId, expiredTime, cancellationToken);
-    }
-
     /// <summary>
     /// 更新省平台办理结果节点附件
     /// </summary>

+ 16 - 12
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -32,14 +32,15 @@ namespace Hotline.FlowEngine.Workflows
         /// new 
         /// </summary>
         Task<(Workflow, WorkflowStep)> StartAsync(StartWorkflowDto dto, string externalId,
-            DateTime? expiredTime, CancellationToken cancellationToken = default);
+            DateTime? expiredTime = null, CancellationToken cancellationToken = default);
 
         /// <summary>
         /// new
         /// </summary>
         Task<List<WorkflowStep>> NextAsync(ISessionContext current, NextWorkflowDto dto,
             DateTime? expiredTime = null, bool isAutoFillSummaryOpinion = false,
-            Action<WorkflowStep>? stepConfig = null, CancellationToken cancellationToken = default);
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
+            CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 查询工作流
@@ -88,21 +89,25 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task<bool> RecallAsync(RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Action<WorkflowStep>? stepConfig = null,  CancellationToken cancellationToken = default);
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,  
+            CancellationToken cancellationToken = default);
 
         Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo, StepDefine targetStepDefine,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Action<WorkflowStep>? stepConfig = null,  CancellationToken cancellationToken = default);
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,  
+            CancellationToken cancellationToken = default);
 
         Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Action<WorkflowStep>? stepConfig = null,  CancellationToken cancellationToken = default);
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,  
+            CancellationToken cancellationToken = default);
 
         Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
             WorkflowStep targetStep, EWorkflowTraceType traceType,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, 
-            Action<WorkflowStep>? stepConfig = null,  CancellationToken cancellationToken = default);
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,  
+            CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 撤回至开始节点
@@ -250,12 +255,11 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task<List<WorkflowStep>> GetStepsBelongsToAsync(string userId, CancellationToken cancellationToken);
 
-        ///// <summary>
-        ///// 批量改派工单至指定用户
-        ///// </summary>
-        //Task<ICollection<string>> ChangeHandlerRangeAsync(string sendPoolId,
-        //    IReadOnlyList<(string userId, string username, string orgId, string orgName, IReadOnlyList<string> stepIds)> handlers,
-        //    CancellationToken cancellationToken);
+        /// <summary>
+        /// 开启流程直接归档
+        /// </summary>
+        Task StartToEndAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
+            CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 批量修改工单办理对象

+ 6 - 6
src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs

@@ -398,6 +398,12 @@ public abstract class StepBasicEntity : CreationEntity
     #endregion
     #endregion
 
+    /// <summary>
+    /// 老系统Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "老系统Id")]
+    public string? OldStepId { get; set; }
+    
     [Navigate(NavigateType.ManyToOne, nameof(WorkflowId))]
     public Workflow Workflow { get; set; }
 
@@ -630,12 +636,6 @@ public abstract class StepBasicEntity : CreationEntity
     }
 
 	#endregion
-
-	/// <summary>
-	/// 老系统Id
-	/// </summary>
-	[SugarColumn(ColumnDescription = "老系统Id")]
-	public string? OldStepId { get; set; }
 }
 
 /*

+ 42 - 171
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -163,7 +163,7 @@ namespace Hotline.FlowEngine.Workflows
         /// new(开启流程并停留在开始节点,开始节点为待办节点,指派给当前操作人)
         /// </summary>
         public async Task<(Workflow, WorkflowStep)> StartAsync(StartWorkflowDto dto,
-            string externalId, DateTime? expiredTime, CancellationToken cancellationToken = default)
+            string externalId, DateTime? expiredTime = null, CancellationToken cancellationToken = default)
         {
             //     var validator = new StartWorkflowDtoValidator();
             // var validResult = await validator.ValidateAsync(dto, cancellationToken);
@@ -275,7 +275,8 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         public async Task<List<WorkflowStep>> NextAsync(ISessionContext current, NextWorkflowDto dto,
             DateTime? expiredTime = null, bool isAutoFillSummaryOpinion = false,
-            Action<WorkflowStep>? stepConfig = null, CancellationToken cancellationToken = default)
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
+            CancellationToken cancellationToken = default)
         {
             var workflow = await GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
                 withTraces: true, withCountersigns: true, cancellationToken: cancellationToken);
@@ -338,7 +339,7 @@ namespace Hotline.FlowEngine.Workflows
              0.动态、会签固定指派方式
              1.普通办理方式:依据配置决定指派对象,结合dto选择的nextHandlers
              2.下一节点是按角色办理时可以不选办理对象,此时需指派给配置的角色
-             3.下一节点是汇总节点未选办理对象时:a.依据原节点办理人办理 b.依据原节点配置办理
+             3.下一节点是汇总节点未选办理对象时:a.依据原节点办理人办理 b.依据原节点配置办理
              4.开放action,允许按业务逻辑任意指派
              5.任意场景下优先级:action > dto选择办理对象 > 业务逻辑指定
              */
@@ -686,160 +687,6 @@ namespace Hotline.FlowEngine.Workflows
             return workflow.ActualHandleStepAcceptTime;
         }
 
-        // /// <summary>
-        // /// 退回(返回前一节点)
-        // /// </summary>
-        // /// <returns></returns>
-        // public async Task<EFlowDirection> PreviousAsync(Workflow workflow, PreviousWorkflowDto dto,
-        //     string applicantId, string applicantName,
-        //     string applicantOrgId, string applicantOrgName,
-        //     string applicantOrgAreaCode, string applicantOrgAreaName,
-        //     bool applicantIsCenter, string[] applicantRoleIds,
-        //     CancellationToken cancellationToken)
-        // {
-        //     //ValidatePermission(workflow, operater.OrgId, operater.Id);
-        //
-        //     var (currentStep, prevStep, countersignStartStep) =
-        //         GetPreviousStep(workflow, applicantId, applicantOrgId, applicantRoleIds);
-        //
-        //     //保存附件
-        //     if (dto.Files.Any())
-        //         currentStep.FileJson = await _fileRepository.AddFileAsync(
-        //             dto.Files, workflow.ExternalId, currentStep.Id, cancellationToken);
-        //
-        //     // add prev current to remove list
-        //     var removeSteps = new List<WorkflowStep> { currentStep, prevStep };
-        //
-        //     if (countersignStartStep is not null)
-        //     {
-        //         //add cs steps to remove list
-        //         SearchCountersignSteps(countersignStartStep, workflow.Steps, ref removeSteps);
-        //
-        //         //end cs
-        //         var currentCountersign =
-        //             workflow.Countersigns.FirstOrDefault(d => d.Id == countersignStartStep.StartCountersignId);
-        //         if (currentCountersign is null)
-        //             throw new UserFriendlyException(
-        //                 $"未查询到对应会签信息,workflowId:{workflow.Id}, countersignId:{currentStep.CountersignId}",
-        //                 "无效会签编号");
-        //
-        //         //结束step会签信息
-        //         countersignStartStep.CountersignEnd();
-        //         await _workflowStepRepository.UpdateAsync(countersignStartStep, cancellationToken);
-        //         //updateSteps.Add(countersignStartStep);
-        //
-        //         //结束会签
-        //         //currentCountersign.End(currentStep.Id, currentStep.Code, currentStep.BusinessType,
-        //         //    current.RequiredUserId, current.UserName,
-        //         //    current.RequiredOrgId, current.OrgName,
-        //         //    current.OrgAreaCode, current.OrgAreaName);
-        //         currentCountersign.End(currentStep.Id, currentStep.Code, currentStep.BusinessType,
-        //             applicantId, applicantName,
-        //             applicantOrgId, applicantOrgName,
-        //             applicantOrgAreaCode, applicantOrgAreaName);
-        //
-        //         await _workflowCountersignRepository.UpdateAsync(currentCountersign, cancellationToken);
-        //
-        //         //update workflow cs status
-        //         if (workflow.CheckIfCountersignOver())
-        //             workflow.EndCountersign();
-        //     }
-        //
-        //     //update trace
-        //     //var trace = await PreviousTraceAsync(workflow.Id, dto, currentStep,
-        //     //    applicantId, applicantName,
-        //     //    applicantOrgId, applicantOrgName,
-        //     //    applicantOrgAreaCode, applicantOrgAreaName,
-        //     //    applicantIsCenter, cancellationToken);
-        //     var trace = workflow.Traces.First(t => t.StepId == currentStep.Id);
-        //     // _mapper.Map(dto, trace);
-        //     trace.FileJson = currentStep.FileJson;
-        //     trace.IsSms = dto.AcceptSms;
-        //     trace.Opinion = dto.Opinion;
-        //
-        //     //HandleTrace(trace, dto.Opinion, current);
-        //
-        //     trace.Handle(applicantId, applicantName,
-        //         applicantOrgId, applicantOrgName,
-        //         applicantOrgAreaCode, applicantOrgAreaName,
-        //         applicantIsCenter, EHandleMode.Previous, dto.Opinion);
-        //
-        //     //await _workflowTraceRepository.UpdateAsync(trace, cancellationToken);
-        //
-        //     //如果有传入期满时间 新节点为传入的期满时间
-        //     if (dto.ExpiredTime.HasValue)
-        //         prevStep.StepExpiredTime = dto.ExpiredTime;
-        //
-        //     if (workflow.FlowType == EFlowType.Handle)
-        //     {
-        //         prevStep.FlowAssignType = prevStep.BusinessType is EBusinessType.Seat ? EFlowAssignType.Role :
-        //             prevStep.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Org;
-        //     }
-        //     //甄别退回到最开始节点到部门
-        //     if (workflow.FlowType == EFlowType.Review && workflow.ModuleCode == WorkflowModuleConsts.OrderScreen)
-        //     {
-        //         prevStep.FlowAssignType = prevStep.StepType == EStepType.Start ? EFlowAssignType.Org : prevStep.FlowAssignType;
-        //     }
-        //
-        //     dto.ReverseFlowStepAssignInfo ??= new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
-        //     var prevStepDefine = workflow.WorkflowDefinition.FindStepDefine(prevStep.Code);
-        //     var stepAssignInfo = GetStepAssignInfo(dto.ReverseFlowStepAssignInfo, prevStep, prevStepDefine);
-        //
-        //     //复制上一个节点为待接办
-        //     // var newPrevStep =
-        //     //     await DuplicateStepWithTraceAsync(workflow, prevStep, EWorkflowTraceType.Previous, cancellationToken);
-        //     var newPrevStep = DuplicateStep(prevStep, EWorkflowTraceType.Previous, stepAssignInfo, dto.ExpiredTime);
-        //     ////退给派单组节点,需按照平均分配原则派给一个派单员 禅道299 TODO
-        //     //if (dto.ReverseFlowStepAssignInfo != null) //todo 改为按策略判断
-        //     //{
-        //     //    var handle = dto.ReverseFlowStepAssignInfo.StepAssignInfo;
-        //     //    newPrevStep.Assign(handle.UserId, handle.Username, handle.OrgId, handle.OrgName, handle.RoleId, handle.RoleName);
-        //     //}
-        //
-        //     await _workflowStepRepository.AddAsync(newPrevStep, cancellationToken);
-        //     await CreateTraceAsync(workflow, newPrevStep, EWorkflowTraceType.Previous, cancellationToken);
-        //
-        //     //remove workflow.steps
-        //     await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
-        //
-        //     var stepIds = removeSteps.Select(d => d.Id).ToList();
-        //     var updateTraces = workflow.Traces.Where(d => stepIds.Contains(d.StepId)).ToList();
-        //     await UpdateTracesStateAsync(updateTraces, EWorkflowTraceState.StepRemoveByPrevious, cancellationToken);
-        //
-        //     if (workflow.Status is EWorkflowStatus.Completed)
-        //         workflow.SetStatusRunnable();
-        //
-        //     //更新实际办理节点信息
-        //     workflow.UpdateActualStepWhenAssign(newPrevStep, new FlowStepHandler
-        //     {
-        //         UserId = newPrevStep.HandlerId,
-        //         Username = newPrevStep.HandlerName,
-        //         OrgId = newPrevStep.HandlerOrgId,
-        //         OrgName = newPrevStep.HandlerOrgName,
-        //     });
-        //
-        //     workflow.UpdateCurrentStepWhenAssign(newPrevStep, new FlowStepHandler
-        //     {
-        //         UserId = newPrevStep.HandlerId,
-        //         Username = newPrevStep.HandlerName,
-        //         OrgId = newPrevStep.HandlerOrgId,
-        //         OrgName = newPrevStep.HandlerOrgName,
-        //     });
-        //
-        //     // //更新流程可办理对象
-        //     // workflow.UpdatePreviousHandlers(applicantId, applicantOrgId, prevStep);
-        //
-        //     //orgToCenter会触发重新计算期满时间,1.无需审核按当前时间进行计算 2.需审核按审核通过时间计算
-        //     var isOrgToCenter = prevStep.BusinessType is EBusinessType.Send && prevStep.IsOrigin;
-        //
-        //     await _workflowRepository.UpdateAsync(workflow, cancellationToken);
-        //
-        //     await _publisher.PublishAsync(new PreviousNotify(workflow, newPrevStep, dto, isOrgToCenter),
-        //         PublishStrategy.ParallelWhenAll, cancellationToken);
-        //
-        //     return GetFlowDirection(currentStep.BusinessType, prevStep.BusinessType);
-        // }
-
         /// <summary>
         /// 退回(new)
         /// </summary>
@@ -1029,6 +876,27 @@ namespace Hotline.FlowEngine.Workflows
 
             return (currentStep, prevStep, countersignStartStep);
         }
+        
+        /// <summary>
+        /// 开启流程直接归档
+        /// </summary>
+        public async Task StartToEndAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
+            CancellationToken cancellationToken = default)
+        {
+            var wfModule = await GetWorkflowModuleAsync(dto.DefinitionModuleCode, cancellationToken);
+            var definition = wfModule.Definition;
+            if (definition == null)
+                throw new UserFriendlyException("无效模板编码");
+            if (definition.Status is not EDefinitionStatus.Enable)
+                throw new UserFriendlyException("该模板不可用");
+
+            var endStepDefine = definition.FindEndStepDefine();
+            dto.NextStepCode = endStepDefine.Code;
+            dto.NextStepName = endStepDefine.Name;
+            dto.FlowDirection = EFlowDirection.CenterToFile;
+
+            await StartAsync(dto, externalId, expiredTime, cancellationToken);
+        }
 
         /// <summary>
         /// 查询派单池中流程节点id
@@ -1462,7 +1330,8 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         public async Task<bool> RecallAsync(RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Action<WorkflowStep>? stepConfig = null, CancellationToken cancellationToken = default)
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
+            CancellationToken cancellationToken = default)
         {
             var workflow = await GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
                 withTraces: true, withCountersigns: true, cancellationToken: cancellationToken);
@@ -1483,8 +1352,9 @@ namespace Hotline.FlowEngine.Workflows
         /// 撤回(返回到之前任意节点)
         /// </summary>
         public Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
-            StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled,
-            EHandleMode handleMode, Action<WorkflowStep>? stepConfig = null, CancellationToken cancellationToken = default)
+            StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, 
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
+            CancellationToken cancellationToken = default)
         {
             var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
             if (targetStep is null)
@@ -1495,8 +1365,9 @@ namespace Hotline.FlowEngine.Workflows
         }
 
         public Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
-            WorkflowStep targetStep, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled,
-            EHandleMode handleMode, Action<WorkflowStep>? stepConfig = null, CancellationToken cancellationToken = default)
+            WorkflowStep targetStep, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
+            CancellationToken cancellationToken = default)
         {
             var targetStepDefine = GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
             if (targetStepDefine.StepType is EStepType.End)
@@ -1509,7 +1380,8 @@ namespace Hotline.FlowEngine.Workflows
 
         public async Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
-            DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, Action<WorkflowStep>? stepConfig = null,
+            DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, 
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
@@ -2394,7 +2266,8 @@ namespace Hotline.FlowEngine.Workflows
         private async Task<List<WorkflowStep>> CreateNextStepsAsync(Workflow workflow, WorkflowStep currentStep,
             BasicWorkflowDto dto, StepDefine nextStepDefine, UserInfo assigner, bool isNextDynamic,
             DateTime? expiredTime, bool isStartCountersign, bool isAutoFillSummaryOpinion = false,
-            Action<WorkflowStep>? stepConfig = null, CancellationToken cancellationToken = default)
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null, 
+            CancellationToken cancellationToken = default)
         {
             List<WorkflowStep> nextSteps = new();
             if (currentStep.IsInCountersign())
@@ -2496,7 +2369,7 @@ namespace Hotline.FlowEngine.Workflows
             BasicWorkflowDto dto,
             UserInfo assigner,
             DateTime? expiredTime,
-            Action<WorkflowStep>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var handlerType = nextStepDefine.InstancePolicy switch
@@ -2528,7 +2401,7 @@ namespace Hotline.FlowEngine.Workflows
             BasicWorkflowDto dto,
             UserInfo assigner,
             DateTime? expiredTime,
-            Action<WorkflowStep>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default
         )
         {
@@ -3275,7 +3148,7 @@ namespace Hotline.FlowEngine.Workflows
             EWorkflowTraceType traceType,
             DateTime? expiredTime,
             bool isAutoFillSummaryOpinion = false,
-            Action<WorkflowStep>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             // List<FlowStepHandler> handlers;
@@ -3320,7 +3193,7 @@ namespace Hotline.FlowEngine.Workflows
             EHandlerType? handlerType = null,
             DateTime? expiredTime = null,
             string? opinion = null,
-            Action<WorkflowStep>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default
         )
         {
@@ -3332,7 +3205,7 @@ namespace Hotline.FlowEngine.Workflows
                     handler, assigner, dto.NextStepCode, countersignId, stepStatus, csPosition, expiredTime,
                     dto.NextStepName, isOrigin, isMain, handlerType, dto.BusinessType, dto.FlowDirection, opinion);
 
-                stepConfig?.Invoke(step);
+                stepConfig?.Invoke(workflow, stepDefine, prevStep, step);
                 steps.Add(step);
             }
 
@@ -3767,8 +3640,6 @@ namespace Hotline.FlowEngine.Workflows
             string? opinion = null
         )
         {
-            //if (!handlers.Any())
-            //    throw new UserFriendlyException($"非法参数, handlers为空, method: {nameof(CreateStep)}");
             var step = _mapper.Map<WorkflowStep>(stepDefine);
             _mapper.Map(workflow, step);
             step.FlowAssignType = flowAssignType;