xf 2 сар өмнө
parent
commit
26c6e1dc8c

+ 106 - 89
src/Hotline.Api/Controllers/OrderController.cs

@@ -606,7 +606,7 @@ public class OrderController : BaseController
             orgDetail.VisitOrgCode = item.Key;
             orgDetail.VisitOrgCode = item.Key;
             orgDetail.VisitOrgName = item.Value;
             orgDetail.VisitOrgName = item.Value;
             orgDetail.VisitTarget = EVisitTarget.Org;
             orgDetail.VisitTarget = EVisitTarget.Org;
-            if (order is { CounterSignType: null, FileOrgIsCenter: true } )
+            if (order is { CounterSignType: null, FileOrgIsCenter: true })
             {
             {
                 var satisfy = new Kv() { Key = "4", Value = "满意" };
                 var satisfy = new Kv() { Key = "4", Value = "满意" };
                 orgDetail.OrgProcessingResults = satisfy;
                 orgDetail.OrgProcessingResults = satisfy;
@@ -2827,47 +2827,47 @@ public class OrderController : BaseController
         return rspModel;
         return rspModel;
     }
     }
 
 
-	/// <summary>
-	/// 甄别详情
-	/// </summary>
-	/// <param name="id"></param>
-	/// <returns></returns>
-	[HttpGet("screen/visitdetail/{id}")]
-	public async Task<OrderScreenListDto> VisitDetailScreenEntity(string id)
-	{
-		var model = await _orderScreenRepository.Queryable(canView: false)
-			.Includes(x => x.Order)
-			.Includes(x => x.Workflow, d => d.Steps)
-			.Includes(x => x.Visit, d => d.Order)
-			.FirstAsync(x => x.VisitDetailId  == id);
-		var rspModel = _mapper.Map<OrderScreenListDto>(model);
-		//rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
-		rspModel.IsCanHandle = model.Workflow?.IsCanHandle(
-			_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles) ?? false;
-		if (model.Status == EScreenStatus.SendBack && model.SendBackApply)
-			rspModel.IsCanHandle = false;
-		rspModel.Handle = false;
-		if (!string.IsNullOrEmpty(rspModel.WorkflowId))
-		{
-			rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId,
-				_sessionContext.RequiredOrgId, HttpContext.RequestAborted);
-		}
-
-		if (rspModel.FileJson != null && rspModel.FileJson.Any())
-		{
-			var ids = rspModel.FileJson.Select(x => x.Id).ToList();
-			rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
-		}
-
-		return rspModel;
-	}
-
-	/// <summary>
-	/// 更新甄别提起截至时限
-	/// </summary>
-	/// <param name="dto"></param>
-	/// <returns></returns>
-	[HttpPut("order_screen_endtime")]
+    /// <summary>
+    /// 甄别详情
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
+    [HttpGet("screen/visitdetail/{id}")]
+    public async Task<OrderScreenListDto> VisitDetailScreenEntity(string id)
+    {
+        var model = await _orderScreenRepository.Queryable(canView: false)
+            .Includes(x => x.Order)
+            .Includes(x => x.Workflow, d => d.Steps)
+            .Includes(x => x.Visit, d => d.Order)
+            .FirstAsync(x => x.VisitDetailId == id);
+        var rspModel = _mapper.Map<OrderScreenListDto>(model);
+        //rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+        rspModel.IsCanHandle = model.Workflow?.IsCanHandle(
+            _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles) ?? false;
+        if (model.Status == EScreenStatus.SendBack && model.SendBackApply)
+            rspModel.IsCanHandle = false;
+        rspModel.Handle = false;
+        if (!string.IsNullOrEmpty(rspModel.WorkflowId))
+        {
+            rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId,
+                _sessionContext.RequiredOrgId, HttpContext.RequestAborted);
+        }
+
+        if (rspModel.FileJson != null && rspModel.FileJson.Any())
+        {
+            var ids = rspModel.FileJson.Select(x => x.Id).ToList();
+            rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
+        }
+
+        return rspModel;
+    }
+
+    /// <summary>
+    /// 更新甄别提起截至时限
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPut("order_screen_endtime")]
     [LogFilter("更新甄别提起截至时限")]
     [LogFilter("更新甄别提起截至时限")]
     public async Task Update([FromBody] OrderScreenEndTimeDto dto)
     public async Task Update([FromBody] OrderScreenEndTimeDto dto)
     {
     {
@@ -6011,10 +6011,10 @@ public class OrderController : BaseController
             {
             {
                 if (order.Status < EOrderStatus.Filed)
                 if (order.Status < EOrderStatus.Filed)
                 {
                 {
-					await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
-				   new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(model) },
-				   cancellationToken: HttpContext.RequestAborted);
-				}
+                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
+                        new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(model) },
+                        cancellationToken: HttpContext.RequestAborted);
+                }
 
 
                 //try
                 //try
                 //{
                 //{
@@ -6065,17 +6065,19 @@ public class OrderController : BaseController
 
 
         var model = _mapper.Map<OrderSpecial>(dto);
         var model = _mapper.Map<OrderSpecial>(dto);
 
 
-        var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, withSteps: true,
-            cancellationToken: HttpContext.RequestAborted);
-        var currentStep = workflow.Steps.FirstOrDefault(x => x.Status != EWorkflowStepStatus.Handled);
-        if (currentStep is null)
-            currentStep = workflow.Steps.OrderByDescending(x => x.CreationTime).FirstOrDefault(x => x.StepType == EStepType.End);
-
-        model.OrgId = currentStep is null ? _sessionContext.RequiredOrgId : currentStep.HandlerOrgId;
-        model.OrgName = currentStep is null ? _sessionContext.OrgName : currentStep.HandlerOrgName;
-        var step = await _workflowDomainService.FindLastStepAsync(model.WorkflowId, HttpContext.RequestAborted);
-        model.StepName = step.Name;
-        model.StepCode = step.Code;
+        // var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, withSteps: true,
+        //     cancellationToken: HttpContext.RequestAborted);
+        // var currentStep = workflow.Steps.FirstOrDefault(x => x.Status != EWorkflowStepStatus.Handled);
+        // if (currentStep is null)
+        //     currentStep = workflow.Steps.OrderByDescending(x => x.CreationTime).FirstOrDefault(x => x.StepType == EStepType.End);
+
+        // model.OrgId = currentStep is null ? _sessionContext.RequiredOrgId : currentStep.HandlerOrgId;
+        // model.OrgName = currentStep is null ? _sessionContext.OrgName : currentStep.HandlerOrgName;
+        model.OrgId = _sessionContext.RequiredOrgId;
+        model.OrgName = _sessionContext.OrgName;
+        // var step = await _workflowDomainService.FindLastStepAsync(model.WorkflowId, HttpContext.RequestAborted);
+        // model.StepName = step.Name;
+        // model.StepCode = step.Code;
         model.State = 1;
         model.State = 1;
         model.SpecialType = dto.SpecialType;
         model.SpecialType = dto.SpecialType;
         model.LastFileOpinion = order.FileOpinion;
         model.LastFileOpinion = order.FileOpinion;
@@ -6086,7 +6088,7 @@ public class OrderController : BaseController
         model.InitId();
         model.InitId();
         if (dto.Files.Any())
         if (dto.Files.Any())
             model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted);
             model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", HttpContext.RequestAborted);
-        await _orderSpecialRepository.AddAsync(model, HttpContext.RequestAborted);
+        // await _orderSpecialRepository.AddAsync(model, HttpContext.RequestAborted);
         if (dto.ReTransactError != null && dto.ReTransactError.Any())
         if (dto.ReTransactError != null && dto.ReTransactError.Any())
         {
         {
             List<OrderSpecialDetail> details = new();
             List<OrderSpecialDetail> details = new();
@@ -6189,7 +6191,8 @@ public class OrderController : BaseController
             // }
             // }
 
 
             // var reverseFlowStepAssignInfo = _orderDomainService.GetOrderRecallAssignInfo(dto.BusinessType, stepAssignInfo);
             // var reverseFlowStepAssignInfo = _orderDomainService.GetOrderRecallAssignInfo(dto.BusinessType, stepAssignInfo);
-            await _workflowDomainService.RecallAsync(recall, recall.NextHandlers.FirstOrDefault(), EWorkflowTraceType.Redo,
+            var (workflow, targetStepDefine, currentStep, targetStep, newStep, isOrgToCenter) = await _workflowDomainService.RecallAsync(
+                recall, recall.NextHandlers.FirstOrDefault(), EWorkflowTraceType.Redo,
                 endTime, order.Status >= EOrderStatus.Filed, EHandleMode.Redo,
                 endTime, order.Status >= EOrderStatus.Filed, EHandleMode.Redo,
                 async (workflow, prevStepDefine, prevStep, newStep) =>
                 async (workflow, prevStepDefine, prevStep, newStep) =>
                 {
                 {
@@ -6200,21 +6203,27 @@ public class OrderController : BaseController
                     var validator = new StepAssignInfoValidator();
                     var validator = new StepAssignInfoValidator();
                     await validator.ValidateAndThrowAsync(stepAssignInfo, HttpContext.RequestAborted);
                     await validator.ValidateAndThrowAsync(stepAssignInfo, HttpContext.RequestAborted);
                     newStep.Assign(stepAssignInfo);
                     newStep.Assign(stepAssignInfo);
+                }, HttpContext.RequestAborted);
 
 
-                    // await _orderSpecialRepository.Updateable().SetColumns(x => new OrderSpecial
-                    //         { NextHandlers = new List<StepAssignInfo> { stepAssignInfo } })
-                    //     .Where(x => x.Id == model.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
-                    await _orderSpecialRepository.Updateable(model)
-                        .UpdateColumns(d => new { NextHandlers = new List<StepAssignInfo> { stepAssignInfo } })
-                        .ExecuteCommandAsync(HttpContext.RequestAborted);
 
 
-                    if (dto.BusinessType == EBusinessType.Send)
-                    {
-                        await _orderRepository.Updateable().SetColumns(o => new Orders.Order()
-                                { CenterToOrgHandlerId = stepAssignInfo.UserId, CenterToOrgHandlerName = stepAssignInfo.Username })
-                            .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
-                    }
-                }, HttpContext.RequestAborted);
+            if (string.IsNullOrEmpty(currentStep?.HandlerOrgId))
+            {
+                model.OrgId = currentStep.HandlerOrgId;
+                model.OrgName = currentStep.HandlerOrgName;
+                model.StepName = currentStep.Name;
+                model.StepCode = currentStep.Code;
+            }
+
+            if (_appOptions.Value.IsZiGong && dto.BusinessType == EBusinessType.Send)
+            {
+                model.NextHandlers = new List<StepAssignInfo> { newStep.GetWorkflowStepHandler() };
+            }
+
+            if (dto.BusinessType == EBusinessType.Send)
+            {
+                order.CenterToOrgHandlerId = newStep.HandlerId;
+                order.CenterToOrgHandlerName = newStep.HandlerName;
+            }
 
 
             //await _workflowApplication.RecallAsync(recall, endTime, order.Status >= EOrderStatus.Filed, EWorkflowTraceType.Redo,
             //await _workflowApplication.RecallAsync(recall, endTime, order.Status >= EOrderStatus.Filed, EWorkflowTraceType.Redo,
             //    HttpContext.RequestAborted);
             //    HttpContext.RequestAborted);
@@ -6244,10 +6253,16 @@ public class OrderController : BaseController
             }
             }
 
 
             //ReTransactNum = reTransactNum,
             //ReTransactNum = reTransactNum,
-            var Status = model.StepType == EStepType.Start ? orderStartStatus : orderStatus;
-            await _orderRepository.Updateable()
-                .SetColumns(o => new Orders.Order() { ProcessType = processType, Status = Status })
-                .Where(o => o.Id == order.Id)
+            order.Status = model.StepType == EStepType.Start ? orderStartStatus : orderStatus;
+            order.ProcessType = processType;
+            await _orderRepository.Updateable(order)
+                .UpdateColumns(d=>new
+                {
+                    d.CenterToOrgHandlerId,
+                    d.CenterToOrgHandlerName,
+                    d.ProcessType,
+                    d.Status
+                })
                 .ExecuteCommandAsync(HttpContext.RequestAborted);
                 .ExecuteCommandAsync(HttpContext.RequestAborted);
 
 
             // 重办清空已取消发布的工单的回访信息
             // 重办清空已取消发布的工单的回访信息
@@ -6259,6 +6274,8 @@ public class OrderController : BaseController
             //    await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
             //    await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
             //}
             //}
         }
         }
+
+        await _orderSpecialRepository.AddAsync(model, HttpContext.RequestAborted);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -6439,13 +6456,12 @@ public class OrderController : BaseController
                                   cityBase.CityProvinceAssign.OrgId.Equals(special.OrgId) || cityBase.CityEnterprise.OrgId.Equals(special.OrgId) ||
                                   cityBase.CityProvinceAssign.OrgId.Equals(special.OrgId) || cityBase.CityEnterprise.OrgId.Equals(special.OrgId) ||
                                   cityBase.PublicSecurity.OrgId.Equals(special.OrgId)))
                                   cityBase.PublicSecurity.OrgId.Equals(special.OrgId)))
             {
             {
-                if (order.Status < EOrderStatus.Filed) 
+                if (order.Status < EOrderStatus.Filed)
                 {
                 {
-					await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
-						new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(special) },
-						cancellationToken: HttpContext.RequestAborted);
-				}
-					
+                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
+                        new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(special) },
+                        cancellationToken: HttpContext.RequestAborted);
+                }
             }
             }
         }
         }
         else
         else
@@ -6632,12 +6648,12 @@ public class OrderController : BaseController
                                       cityBase.CityEnterprise.OrgId.Equals(special.OrgId) ||
                                       cityBase.CityEnterprise.OrgId.Equals(special.OrgId) ||
                                       cityBase.PublicSecurity.OrgId.Equals(special.OrgId)))
                                       cityBase.PublicSecurity.OrgId.Equals(special.OrgId)))
                 {
                 {
-                    if (order.Status < EOrderStatus.Filed) 
+                    if (order.Status < EOrderStatus.Filed)
                     {
                     {
-						await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
-							new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(special) },
-							cancellationToken: HttpContext.RequestAborted);
-					}
+                        await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
+                            new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(special) },
+                            cancellationToken: HttpContext.RequestAborted);
+                    }
                 }
                 }
             }
             }
             else
             else
@@ -6917,9 +6933,10 @@ public class OrderController : BaseController
 
 
             if (!order.FileOrgIsCenter.Value)
             if (!order.FileOrgIsCenter.Value)
             {
             {
-				if (step.Steps.Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1).Any())
+                if (step.Steps.Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1).Any())
                 {
                 {
-                    var stepdDefault = step.Steps.Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1 && x.StepType == EStepType.Normal)
+                    var stepdDefault = step.Steps
+                        .Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1 && x.StepType == EStepType.Normal)
                         .FirstOrDefault();
                         .FirstOrDefault();
                     defaultStepKey = stepdDefault.Key;
                     defaultStepKey = stepdDefault.Key;
                     defaultHandlerKey = stepdDefault.Handler.Key;
                     defaultHandlerKey = stepdDefault.Handler.Key;

+ 6 - 3
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -96,17 +96,20 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// <summary>
         /// 撤回(返回到之前任意节点)
         /// 撤回(返回到之前任意节点)
         /// </summary>
         /// </summary>
-        Task<bool> RecallAsync(RecallDto dto, StepAssignInfo stepAssignInfo,
+        Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            RecallDto dto, StepAssignInfo stepAssignInfo,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
             CancellationToken cancellationToken = default);
 
 
-        Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo, 
+        Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
             StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
             CancellationToken cancellationToken = default);
 
 
-        Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
+        Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
             WorkflowStep targetStep, EWorkflowTraceType traceType,
             WorkflowStep targetStep, EWorkflowTraceType traceType,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,

+ 21 - 6
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -1498,7 +1498,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// <summary>
         /// 撤回(返回到之前任意节点)
         /// 撤回(返回到之前任意节点)
         /// </summary>
         /// </summary>
-        public async Task<bool> RecallAsync(RecallDto dto, StepAssignInfo stepAssignInfo,
+        public async Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            RecallDto dto, StepAssignInfo stepAssignInfo,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
             CancellationToken cancellationToken = default)
@@ -1521,7 +1522,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// <summary>
         /// 撤回(返回到之前任意节点)
         /// 撤回(返回到之前任意节点)
         /// </summary>
         /// </summary>
-        public Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
+        public Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
             StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
             CancellationToken cancellationToken = default)
@@ -1535,7 +1537,8 @@ namespace Hotline.FlowEngine.Workflows
         }
         }
 
 
 
 
-        public Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
+        public Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
             WorkflowStep targetStep, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             WorkflowStep targetStep, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
             CancellationToken cancellationToken = default)
@@ -1549,7 +1552,13 @@ namespace Hotline.FlowEngine.Workflows
                 expiredTime, isOrderFiled, handleMode, stepConfig, cancellationToken);
                 expiredTime, isOrderFiled, handleMode, stepConfig, cancellationToken);
         }
         }
 
 
-        private async Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
+        /// <summary>
+        /// 特提
+        /// </summary>
+        /// <returns>workflow, targetStepDefine, currentStep, targetStep, newStep, isOrgToCenter</returns>
+        /// <exception cref="UserFriendlyException"></exception>
+        private async Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
+            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
@@ -1558,6 +1567,12 @@ namespace Hotline.FlowEngine.Workflows
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
             var updateTraces = new List<WorkflowTrace>();
             var updateTraces = new List<WorkflowTrace>();
 
 
+            var currentStep = workflow.Steps.Where(x => x.Status != EWorkflowStepStatus.Handled)
+                                  .MaxBy(d => d.CreationTime) ??
+                              workflow.Steps.Where(x => x.StepType == EStepType.End)
+                                  .MaxBy(d => d.CreationTime) ??
+                              workflow.Steps.MaxBy(d => d.CreationTime);
+
             //update uncomplete traces
             //update uncomplete traces
             var uncompleteTraces = workflow.Traces.Where(d => d.Status != EWorkflowStepStatus.Handled).ToList();
             var uncompleteTraces = workflow.Traces.Where(d => d.Status != EWorkflowStepStatus.Handled).ToList();
             if (uncompleteTraces.Any())
             if (uncompleteTraces.Any())
@@ -1690,7 +1705,7 @@ namespace Hotline.FlowEngine.Workflows
             await _publisher.PublishAsync(new RecallNotify(workflow, targetStep, dto, isOrgToCenter),
             await _publisher.PublishAsync(new RecallNotify(workflow, targetStep, dto, isOrgToCenter),
                 PublishStrategy.ParallelWhenAll, cancellationToken);
                 PublishStrategy.ParallelWhenAll, cancellationToken);
 
 
-            return isOrgToCenter;
+            return (workflow, targetStepDefine, currentStep, targetStep, targetStepNew, isOrgToCenter);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1798,7 +1813,7 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         /// </summary>
         /// <returns>true 派单组  false 话务部</returns>
         /// <returns>true 派单组  false 话务部</returns>
         public async Task<(bool, Workflow workflow)> RecallToCenterFirstToSendAsync(string workflowId, string opinion,
         public async Task<(bool, Workflow workflow)> RecallToCenterFirstToSendAsync(string workflowId, string opinion,
-            bool isOrderFiled, DateTime? expiredTime, EHandleMode handleMode, 
+            bool isOrderFiled, DateTime? expiredTime, EHandleMode handleMode,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
             CancellationToken cancellationToken = default)
         {
         {