瀏覽代碼

计算期满时间需求调整

xf 1 年之前
父節點
當前提交
4fbae08f67

+ 1 - 1
src/Hotline.Api/Controllers/CommonPController.cs

@@ -93,7 +93,7 @@ namespace Hotline.Api.Controllers
 			var time = DateTime.Parse(tadayTime);
 			var order = await _orderRepository.Queryable(false, false, false)
 				.Includes(o => o.Workflow, w => w.Steps)
-                .Where(o=> o.Workflow.Steps.Any(s => s.Status == EWorkflowStepStatus.Handled) && o.Workflow.ExpiredTime > time)
+                .Where(o=> o.Workflow.Steps.Any(s => s.Status == EWorkflowStepStatus.Handled) && o.ExpiredTime > time)
                 .GroupBy(o=>o.Id)
                 .Select(o => new {
 					tasksOkNum= SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(o.Workflow.HandlerUsers, "Key", _sessionContext.RequiredUserId) , 1, 0)),

+ 88 - 77
src/Hotline.Api/Controllers/OrderController.cs

@@ -1058,45 +1058,45 @@ public class OrderController : BaseController
             .FirstAsync(x => x.Id == id);
     }
 
-    /// <summary>
-    /// 发起重办
-    /// </summary>
-    [HttpPost("redo")]
-    [LogFilter("新增工单重办")]
-    public async Task<string> AddRedo([FromBody] OrderRedoStartFlowDto dto)
-    {
-        var redo = _mapper.Map<OrderRedo>(dto.Data);
-        redo.CreatorName = _sessionContext.UserName ?? string.Empty;
-        redo.CreatorOrgName = _sessionContext.OrgName ?? string.Empty;
-        //redo.TimeLimitCount = dto.Workflow.Extension.TimeLimitCount;
-        //redo.TimeLimitUnit = dto.Workflow.Extension.TimeLimitUnit;
-        //todo
-        var handler = dto.Workflow.NextHandlers.First();
-        redo.RedoOrgCode = handler.Key;
-        redo.RedoOrgCode = handler.Value;
-
-        var id = await _orderRedoRepository.AddAsync(redo, HttpContext.RequestAborted);
-
-        try
-        {
-            var order = await _orderRepository.GetAsync(dto.Data.OrderId, HttpContext.RequestAborted);
-            if (order == null)
-                throw UserFriendlyException.SameMessage("无效工单编号");
-            if (string.IsNullOrEmpty(order.WorkflowId))
-                throw UserFriendlyException.SameMessage("无效工单流程编号");
-
-            var redoFlowDto = _mapper.Map<RecallDto>(dto.Workflow);
-            redoFlowDto.WorkflowId = order.WorkflowId;
-
-            await _workflowApplication.RedoAsync(redoFlowDto, HttpContext.RequestAborted);
-            return id;
-        }
-        catch (Exception e)
-        {
-            await _orderRedoRepository.RemoveAsync(id, cancellationToken: HttpContext.RequestAborted);
-            throw new UserFriendlyException($"发起重办失败,{e.Message}");
-        }
-    }
+    ///// <summary>
+    ///// 发起重办
+    ///// </summary>
+    //[HttpPost("redo")]
+    //[LogFilter("新增工单重办")]
+    //public async Task<string> AddRedo([FromBody] OrderRedoStartFlowDto dto)
+    //{
+    //    var redo = _mapper.Map<OrderRedo>(dto.Data);
+    //    redo.CreatorName = _sessionContext.UserName ?? string.Empty;
+    //    redo.CreatorOrgName = _sessionContext.OrgName ?? string.Empty;
+    //    //redo.TimeLimitCount = dto.Workflow.Extension.TimeLimitCount;
+    //    //redo.TimeLimitUnit = dto.Workflow.Extension.TimeLimitUnit;
+    //    //todo
+    //    var handler = dto.Workflow.NextHandlers.First();
+    //    redo.RedoOrgCode = handler.Key;
+    //    redo.RedoOrgCode = handler.Value;
+
+    //    var id = await _orderRedoRepository.AddAsync(redo, HttpContext.RequestAborted);
+
+    //    try
+    //    {
+    //        var order = await _orderRepository.GetAsync(dto.Data.OrderId, HttpContext.RequestAborted);
+    //        if (order == null)
+    //            throw UserFriendlyException.SameMessage("无效工单编号");
+    //        if (string.IsNullOrEmpty(order.WorkflowId))
+    //            throw UserFriendlyException.SameMessage("无效工单流程编号");
+
+    //        var redoFlowDto = _mapper.Map<RecallDto>(dto.Workflow);
+    //        redoFlowDto.WorkflowId = order.WorkflowId;
+
+    //        await _workflowApplication.RedoAsync(redoFlowDto, HttpContext.RequestAborted);
+    //        return id;
+    //    }
+    //    catch (Exception e)
+    //    {
+    //        await _orderRedoRepository.RemoveAsync(id, cancellationToken: HttpContext.RequestAborted);
+    //        throw new UserFriendlyException($"发起重办失败,{e.Message}");
+    //    }
+    //}
 
     /// <summary>
     /// 重办基础数据
@@ -2328,6 +2328,26 @@ public class OrderController : BaseController
     [HttpPost("startflow")]
     public async Task StartFlow([FromBody] OrderStartFlowDto dto)
     {
+        ExpiredTimeWithConfig expiredTimeConfig;
+        if (dto.Workflow.NextHandlers.Any(d => d.Key == "001170" || d.Key == "001177"))
+        {
+            var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80);
+            expiredTimeConfig = new ExpiredTimeWithConfig
+            {
+                Count = 45,
+                TimeType = ETimeType.WorkDay,
+                TimeText = "45个工作日",
+                ExpiredTime = timeResult.EndTime,
+                NearlyExpiredTime = timeResult.NearlyExpiredTime
+            };
+        }
+        else
+        {
+            //期满时间
+            expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, dto.Data.AcceptTypeCode);
+        }
+        _mapper.Map(expiredTimeConfig, dto.Data);
+
         var id = dto.Data.Id;
         var isAdd = string.IsNullOrEmpty(dto.Data.Id);
         if (isAdd)
@@ -2341,29 +2361,12 @@ public class OrderController : BaseController
 
         try
         {
-            var expiredTimeConfig = new ExpiredTimeWithConfig();
-            if (dto.Workflow.NextHandlers.Any(d => d.Key == "001170" || d.Key == "001177"))
-            {
-                var s = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80);
-                expiredTimeConfig = new ExpiredTimeWithConfig
-                {
-                    Count = 45,
-                    TimeType = ETimeType.WorkDay,
-                    TimeText = "45个工作日",
-                    ExpiredTime = s.EndTime,
-                    NearlyExpiredTime = s.NearlyExpiredTime
-                };
-            }
-            else
-            {
-                //期满时间
-                expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.OrgToCenter, dto.Data.AcceptTypeCode);
-            }
-            // if(dto.Workflow.HandlerType is EHandlerType.AssignedOrg or EHandlerType.OrgLevel or EHandlerType.OrgType && dto.Workflow.NextStepCode)
+
+
             var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
             startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle;
             startDto.Title = dto.Data.Title;
-            await _workflowApplication.StartWorkflowAsync(startDto, id, expiredTimeConfig, HttpContext.RequestAborted);
+            await _workflowApplication.StartWorkflowAsync(startDto, id, expiredTimeConfig.ExpiredTime, HttpContext.RequestAborted);
         }
         catch (Exception e)
         {
@@ -2392,36 +2395,43 @@ public class OrderController : BaseController
     {
         var order = await _orderRepository.Queryable()
             .FirstAsync(d => d.WorkflowId == dto.WorkflowId, HttpContext.RequestAborted);
+        if (order is null)
+            throw new UserFriendlyException("无效工单编号");
         //if (await _orderDelayRepository.AnyAsync(x => x.OrderId == order.Id && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted))
         //{
         //    throw UserFriendlyException.SameMessage("该工单存在正在审核中的延期,不能办理");
         //}
-        if (order != null && await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == order.Id && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted))
+        if (await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == order.Id && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted))
         {
             throw UserFriendlyException.SameMessage("该工单存在正在审核中的退回,不能办理");
         }
 
-        if (dto.FlowDirection.HasValue
-            && dto.External.TimeLimit.HasValue
-            && dto.External.TimeLimitUnit.HasValue)
+        ExpiredTimeWithConfig? expiredTimeConfig = null;
+        if (dto.NextHandlers.Any(d => d.Key == "001170" || d.Key == "001177"))
         {
-            var expiredTimeConfig = _timeLimitDomainService.CalcEndTime(DateTime.Now,
-                new TimeConfig(dto.External.TimeLimit.Value, dto.External.TimeLimitUnit.Value), order.AcceptTypeCode);
-            if (dto.FlowDirection is EFlowDirection.CenterToOrg)
-            {
-                order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
-                    expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
-                //写入质检
-                await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, HttpContext.RequestAborted);
-            }
-            else if(dto.FlowDirection is EFlowDirection.OrgToCenter)
+            var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80);
+            expiredTimeConfig = new ExpiredTimeWithConfig
             {
-                order.OrgToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
-                    expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
-            }
+                Count = 45,
+                TimeType = ETimeType.WorkDay,
+                TimeText = "45个工作日",
+                ExpiredTime = timeResult.EndTime,
+                NearlyExpiredTime = timeResult.NearlyExpiredTime
+            };
+        }
+        else if (dto.FlowDirection is EFlowDirection.CenterToOrg)
+        {
+            expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.AcceptTypeCode);
+            order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
+                expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
+            //写入质检
+            await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, HttpContext.RequestAborted);
         }
 
-        await _workflowApplication.NextAsync(dto, HttpContext.RequestAborted);
+        _mapper.Map(expiredTimeConfig, order);
+        await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+
+        await _workflowApplication.NextAsync(dto, expiredTimeConfig?.ExpiredTime ?? null, HttpContext.RequestAborted);
     }
 
     /// <summary>
@@ -2434,6 +2444,7 @@ public class OrderController : BaseController
         if (string.IsNullOrEmpty(order.WorkflowId))
             throw UserFriendlyException.SameMessage("该工单未开启流程");
         var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, HttpContext.RequestAborted);
+        dto.ExpiredTime = order.ExpiredTime;
         var rsp = _mapper.Map<NextStepsDto<RecommendStepOption>>(dto);
         foreach (var step in rsp.Steps)
         {

+ 15 - 15
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -337,7 +337,7 @@ public class WorkflowController : BaseController
     [HttpPost("next")]
     public async Task Next([FromBody] NextWorkflowDto dto)
     {
-        await _workflowApplication.NextAsync(dto, HttpContext.RequestAborted);
+        await _workflowApplication.NextAsync(dto, cancellationToken: HttpContext.RequestAborted);
     }
 
     /// <summary>
@@ -382,17 +382,17 @@ public class WorkflowController : BaseController
         return await _workflowApplication.GetJumpStepsAsync(workflowId, HttpContext.RequestAborted);
     }
 
-    /// <summary>
-    /// 跳转至任意节点(暂无需求设计)
-    /// </summary>
-    /// <param name="dto"></param>
-    /// <returns></returns>
-    [HttpPost("jump")]
-    [Obsolete]
-    public async Task Jump([FromBody] RecallDto dto)
-    {
-        await _workflowApplication.JumpAsync(dto, HttpContext.RequestAborted);
-    }
+    ///// <summary>
+    ///// 跳转至任意节点(暂无需求设计)
+    ///// </summary>
+    ///// <param name="dto"></param>
+    ///// <returns></returns>
+    //[HttpPost("jump")]
+    //[Obsolete]
+    //public async Task Jump([FromBody] RecallDto dto)
+    //{
+    //    await _workflowApplication.JumpAsync(dto, HttpContext.RequestAborted);
+    //}
 
     /// <summary>
     /// 获取重办可选节点
@@ -504,7 +504,7 @@ public class WorkflowController : BaseController
          */
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true,
             cancellationToken: HttpContext.RequestAborted);
-        
+
         //所有节点的待办对象
         return workflow.Steps
             .Where(d => d.StepType != EStepType.Start && d.StepType != EStepType.End)
@@ -552,10 +552,10 @@ public class WorkflowController : BaseController
     {
         RefAsync<int> total = 0;
         var query = _workflowCountersignRepository.Queryable()
-            .Includes(x=>x.Members)
+            .Includes(x => x.Members)
             .LeftJoin<Workflow>((c, w) => c.WorkflowId == w.Id)
             .InnerJoin<Order>((c, w, o) => w.ExternalId == o.Id)
-            .WhereIF(!_sessionContext.OrgIsCenter,x=>x.Members.Any(x=>x.Key== _sessionContext.OrgId))
+            .WhereIF(!_sessionContext.OrgIsCenter, x => x.Members.Any(x => x.Key == _sessionContext.OrgId))
             .WhereIF(dto.IsProvince.HasValue, (c, w, o) => o.IsProvince == dto.IsProvince.Value)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                 (c, w, o) => o.No.Contains(dto.Keyword) || o.Title.Contains(dto.Keyword));

+ 14 - 14
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -14,18 +14,18 @@ namespace Hotline.Application.FlowEngine
 {
     public interface IWorkflowApplication
     {
-        
+
 
         /// <summary>
         /// 开始流程
         /// </summary>
-        Task<string> StartWorkflowAsync(StartWorkflowDto dto, string externalId, ExpiredTimeWithConfig? expiredTimeConfig = null,
+        Task<string> StartWorkflowAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
             CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 流转至下一节点(节点办理)
         /// </summary>
-        Task<Workflow> NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken);
+        Task<Workflow> NextAsync(NextWorkflowDto dto, DateTime? expiredTime = null, CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 退回(返回前一节点)
@@ -37,15 +37,15 @@ namespace Hotline.Application.FlowEngine
         /// </summary>
         Task OrderPreviousAsync(PreviousWorkflowDto dto, string userId, CancellationToken cancellationToken);
 
-		/// <summary>
-		/// 撤回至任意节点
-		/// </summary>
-		Task RecallAsync(RecallDto dto, CancellationToken cancellationToken);
-
         /// <summary>
-        /// 跳转至任意节点
+        /// 撤回至任意节点
         /// </summary>
-        Task JumpAsync(RecallDto dto, CancellationToken cancellationToken);
+        Task RecallAsync(RecallDto dto, CancellationToken cancellationToken);
+
+        ///// <summary>
+        ///// 跳转至任意节点
+        ///// </summary>
+        //Task JumpAsync(RecallDto dto, CancellationToken cancellationToken);
 
         /// <summary>
         /// 跳转至结束节点(无视流程模板配置直接跳至结束节点)
@@ -54,10 +54,10 @@ namespace Hotline.Application.FlowEngine
             EReviewResult? reviewResult = EReviewResult.Unknown,
             CancellationToken cancellationToken = default);
 
-        /// <summary>
-        /// 重办
-        /// </summary>
-        Task RedoAsync(RecallDto dto, CancellationToken cancellationToken);
+        ///// <summary>
+        ///// 重办
+        ///// </summary>
+        //Task RedoAsync(RecallDto dto, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询流程开始节点的下一节点配置

+ 36 - 37
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -95,7 +95,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     }
 
     public async Task<string> StartWorkflowAsync(StartWorkflowDto dto, string externalId,
-        ExpiredTimeWithConfig? expiredTimeConfig = null, CancellationToken cancellationToken = default)
+        DateTime? expiredTime, CancellationToken cancellationToken = default)
     {
         var validator = new StartWorkflowDtoValidator();
         var validResult = validator.Validate(dto);
@@ -142,12 +142,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
         var workflow = await _workflowDomainService.CreateWorkflowAsync(wfModule, dto.Title,
             _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId,
-            externalId, expiredTimeConfig?.TimeText,
-            expiredTimeConfig?.Count, expiredTimeConfig?.TimeType,
-            expiredTimeConfig?.ExpiredTime, expiredTimeConfig?.NearlyExpiredTime, cancellationToken);
+            externalId, cancellationToken);
 
         var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
-            new List<Kv> { new(_sessionContext.RequiredUserId, _sessionContext.UserName) });
+            new List<Kv> { new(_sessionContext.RequiredUserId, _sessionContext.UserName) }, expiredTime);
 
         var flowAssignInfo =
             await GetNextStepFlowAssignInfoAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, cancellationToken);
@@ -156,7 +154,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
         //办理开始节点
         await _workflowDomainService.HandleStepAsync(startStep, workflow, dto, flowAssignInfo.FlowAssignType, counterSignType,
-            cancellationToken);
+            expiredTime, cancellationToken);
         //startStep.Handle(_sessionContext.RequiredUserId, _sessionContext.UserName,
         //    _sessionContext.RequiredOrgId, _sessionContext.OrgName,
         //    _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
@@ -185,7 +183,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             _sessionContext.OrgName);
 
         await _workflowDomainService.StartAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic,
-            flowAssignInfo, counterSignType, cancellationToken);
+            flowAssignInfo, counterSignType, expiredTime, cancellationToken);
 
         return workflow.Id;
     }
@@ -193,7 +191,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// <summary>
     /// 流转至下一节点(节点办理)
     /// </summary>
-    public async Task<Workflow> NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken)
+    public async Task<Workflow> NextAsync(NextWorkflowDto dto, DateTime? expiredTime = null, CancellationToken cancellationToken = default)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true, withCountersigns: true,
             cancellationToken: cancellationToken);
@@ -250,7 +248,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             await GetNextStepFlowAssignInfoAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic, cancellationToken);
 
         await _workflowDomainService.NextAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic,
-            flowAssignInfo, cancellationToken);
+            flowAssignInfo, expiredTime, cancellationToken);
 
         return workflow;
     }
@@ -294,25 +292,26 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
         var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign, dto.NextHandlers,
                 cancellationToken);
-        await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
+
+        await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, null, cancellationToken);
     }
 
-    /// <summary>
-    /// 跳转至任意节点
-    /// </summary>
-    public async Task JumpAsync(RecallDto dto, CancellationToken cancellationToken)
-    {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
-                cancellationToken: cancellationToken);
+    ///// <summary>
+    ///// 跳转至任意节点
+    ///// </summary>
+    //public async Task JumpAsync(RecallDto dto, CancellationToken cancellationToken)
+    //{
+    //    var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
+    //            cancellationToken: cancellationToken);
 
-        await _orderDomainService.ReadyToRecallAsync(workflow.ExternalId, cancellationToken);
+    //    await _orderDomainService.ReadyToRecallAsync(workflow.ExternalId, cancellationToken);
 
-        var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
-        //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
-        var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
-            dto.NextHandlers, cancellationToken);
-        await _workflowDomainService.JumpAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
-    }
+    //    var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
+    //    //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
+    //    var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
+    //        dto.NextHandlers, cancellationToken);
+    //    await _workflowDomainService.JumpAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
+    //}
 
     /// <summary>
     /// 跳转至结束节点(无视流程模板配置直接跳至结束节点)
@@ -338,18 +337,18 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             reviewResult, cancellationToken);
     }
 
-    /// <summary>
-    /// 重办
-    /// </summary>
-    public async Task RedoAsync(RecallDto dto, CancellationToken cancellationToken)
-    {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
-            cancellationToken: cancellationToken);
-        var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
-        var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
-            dto.NextHandlers, cancellationToken);
-        await _workflowDomainService.RedoAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
-    }
+    ///// <summary>
+    ///// 重办
+    ///// </summary>
+    //public async Task RedoAsync(RecallDto dto, CancellationToken cancellationToken)
+    //{
+    //    var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
+    //        cancellationToken: cancellationToken);
+    //    var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
+    //    var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
+    //        dto.NextHandlers, cancellationToken);
+    //    await _workflowDomainService.RedoAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
+    //}
 
     public async Task<DefinedStepDto> GetStartOptionsAsync(string moduleCode, CancellationToken cancellationToken)
     {
@@ -532,7 +531,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var dto = new NextStepsDto<NextStepOption>
         {
             CanReject = workflow.IsReviewType() && currentStep.CanReject,
-            ExpiredTime = workflow.ExpiredTime,
+            //ExpiredTime = workflow.ExpiredTime,
             CanStartCountersign = currentStep.CanStartCountersign,
             CurrentStepBusinessType = currentStep.BusinessType,
             TimeTypeOptions = EnumExts.GetDescriptions<ETimeType>().ToList(),

+ 35 - 35
src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs

@@ -98,39 +98,39 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                 order.CheckIfFiled();
                 _mapper.Map(workflow, order);
 
-                var expiredTimeChanged = false;
-                if (data.FlowDirection.HasValue
-                    && data.External.TimeLimit.HasValue                   
-                    && data.External.TimeLimitUnit.HasValue)
-                {
-                    // 1. calc expiredTime 2. update order.expiredTime 3. update workflow.expiredTime 4. publish province
-
-                    // var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
-                    //     data.External.TimeLimitUnit.Value,
-                    //     data.External.TimeLimit.Value, data.FlowDirection is EFlowDirection.OrgToCenter);
-
-                    var expiredTimeConfig = _timeLimitDomainService.CalcEndTime(DateTime.Now,
-                        new TimeConfig(data.External.TimeLimit.Value, data.External.TimeLimitUnit.Value), order.AcceptTypeCode);
-
-                    if (data.FlowDirection is EFlowDirection.OrgToCenter)
-                    {
-                        order.OrgToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
-                            expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
-                    }
-                    else if (data.FlowDirection is EFlowDirection.CenterToOrg)
-                    {
-                        order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
-                            expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
-                        //写入质检
-                        await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken);
-                    }
-
-                    await _workflowDomainService.UpdateExpiredTimeAsync(workflow,
-                        expiredTimeConfig.ExpiredTime, expiredTimeConfig.TimeText,
-                        expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
-
-                    expiredTimeChanged = true;
-                }
+                //var expiredTimeChanged = false;
+                //if (data.FlowDirection.HasValue
+                //    && data.External.TimeLimit.HasValue                   
+                //    && data.External.TimeLimitUnit.HasValue)
+                //{
+                //    // 1. calc expiredTime 2. update order.expiredTime 3. update workflow.expiredTime 4. publish province
+
+                //    // var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
+                //    //     data.External.TimeLimitUnit.Value,
+                //    //     data.External.TimeLimit.Value, data.FlowDirection is EFlowDirection.OrgToCenter);
+
+                //    var expiredTimeConfig = _timeLimitDomainService.CalcEndTime(DateTime.Now,
+                //        new TimeConfig(data.External.TimeLimit.Value, data.External.TimeLimitUnit.Value), order.AcceptTypeCode);
+
+                //    if (data.FlowDirection is EFlowDirection.OrgToCenter)
+                //    {
+                //        order.OrgToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
+                //            expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
+                //    }
+                //    else if (data.FlowDirection is EFlowDirection.CenterToOrg)
+                //    {
+                //        order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
+                //            expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
+                //        //写入质检
+                //        await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken);
+                //    }
+
+                //    await _workflowDomainService.UpdateExpiredTimeAsync(workflow,
+                //        expiredTimeConfig.ExpiredTime, expiredTimeConfig.TimeText,
+                //        expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
+
+                //    expiredTimeChanged = true;
+                //}
 
                 await _orderRepository.UpdateAsync(order, cancellationToken);
 
@@ -139,8 +139,8 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                 {
                     Order = orderDto,
                     WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace),
-                    ExpiredTimeChanged = expiredTimeChanged,
-                    HandlerOrgLevel = notification.HandlerOrgCode.CalcOrgLevel()
+                    ExpiredTimeChanged = notification.ExpiredTimeChanged,
+                    HandlerOrgLevel = notification.HandlerOrgId.CalcOrgLevel()
                 }, cancellationToken: cancellationToken);
                
                 break;

+ 17 - 17
src/Hotline.Application/Handlers/FlowEngine/WorkflowPreviousHandler.cs

@@ -82,25 +82,25 @@ namespace Hotline.Application.Handlers.FlowEngine
                     }
 
                     await _orderRepository.UpdateAsync(order, cancellationToken);
-                    if (notification.IsOrgToCenter)
-                    {
-                        var expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.OrgToCenter, order.AcceptTypeCode);
+                    //if (notification.IsOrgToCenter)
+                    //{
+                    //    var expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.OrgToCenter, order.AcceptTypeCode);
 
-                        await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime,
-                            expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
+                    //    await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime,
+                    //        expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
 
-                        var dto = _mapper.Map<OrderDto>(order);
-                        await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, dto, cancellationToken: cancellationToken);
-                        //try
-                        //{
-                        //    await _provinceService.HotlineOrderFlowRecalled(dto, cancellationToken);
-                        //}
-                        //catch (Exception e)
-                        //{
-                        //    _logger.LogError("_provinceService.HotlineOrderFlowRecalled throw exception: {ex}",
-                        //        e.Message);
-                        //}
-                    }
+                    //    var dto = _mapper.Map<OrderDto>(order);
+                    //    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, dto, cancellationToken: cancellationToken);
+                    //    //try
+                    //    //{
+                    //    //    await _provinceService.HotlineOrderFlowRecalled(dto, cancellationToken);
+                    //    //}
+                    //    //catch (Exception e)
+                    //    //{
+                    //    //    _logger.LogError("_provinceService.HotlineOrderFlowRecalled throw exception: {ex}",
+                    //    //        e.Message);
+                    //    //}
+                    //}
                     try
                     {
                         var user = await _userRepository.GetAsync(notification.TargetStep.HandlerId);

+ 10 - 10
src/Hotline.Application/Handlers/FlowEngine/WorkflowRecallHandler.cs

@@ -63,18 +63,18 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
 
                 await _orderRepository.UpdateAsync(order, cancellationToken);
 
-                if (data.External != null && data.External.TimeLimit.HasValue && data.External.TimeLimitUnit.HasValue)
-                {
-                    var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
-                        data.External.TimeLimitUnit.Value,
-                        data.External.TimeLimit.Value, order.AcceptTypeCode);
+                //if (data.External != null && data.External.TimeLimit.HasValue && data.External.TimeLimitUnit.HasValue)
+                //{
+                //    var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
+                //        data.External.TimeLimitUnit.Value,
+                //        data.External.TimeLimit.Value, order.AcceptTypeCode);
 
-                    await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTime.EndTime,
-                        expiredTime.RuleStr, data.External.TimeLimit, data.External.TimeLimitUnit, expiredTime.NearlyExpiredTime, cancellationToken);
+                //    await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTime.EndTime,
+                //        expiredTime.RuleStr, data.External.TimeLimit, data.External.TimeLimitUnit, expiredTime.NearlyExpiredTime, cancellationToken);
 
-                    var dto = _mapper.Map<OrderDto>(order);
-                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, dto, cancellationToken: cancellationToken);
-                }
+                //    var dto = _mapper.Map<OrderDto>(order);
+                //    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, dto, cancellationToken: cancellationToken);
+                //}
 
                 break;
             case WorkflowModuleConsts.KnowledgeAdd:

+ 17 - 4
src/Hotline.Application/Mappers/OrderMapperConfigs.cs

@@ -1,6 +1,7 @@
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.Settings;
 using Mapster;
 
 namespace Hotline.Application.Mappers;
@@ -17,6 +18,11 @@ public class OrderMapperConfigs : IRegister
         config.ForType<AddOrderDto, Order>()
             .IgnoreIf((s, d) => s.OrderExtension == null, d => d.OrderExtension)
             .Map(d => d.Additions, s => s.Files)
+            .IgnoreIf((s, d) => !s.ExpiredTime.HasValue, d => d.ExpiredTime)
+            .IgnoreIf((s, d) => !s.NearlyExpiredTime.HasValue, d => d.NearlyExpiredTime)
+            .IgnoreIf((s, d) => string.IsNullOrEmpty(s.TimeLimit), d => d.TimeLimit)
+            .IgnoreIf((s, d) => !s.TimeLimitCount.HasValue, d => d.TimeLimitCount)
+            .IgnoreIf((s, d) => !s.TimeLimitUnit.HasValue, d => d.TimeLimitUnit)
             ;
 
         config.ForType<UpdateOrderDto, Order>()
@@ -47,8 +53,8 @@ public class OrderMapperConfigs : IRegister
             .Map(d => d.PublishMan, s => s.OrderPublish.CreatorName);
 
 
-        config.ForType<OrderPublish,PublishedDto>()
-           
+        config.ForType<OrderPublish, PublishedDto>()
+
             .Map(d => d.PublishState, s => s.PublishState)
             .Map(d => d.ArrangeContent, s => s.ArrangeContent)
             .Map(d => d.PublishTime, s => s.CreationTime)
@@ -67,10 +73,17 @@ public class OrderMapperConfigs : IRegister
 
         config.ForType<OrderDelay, OrderDelayDto>()
             //.Inherits<Order, OrderDto>()
-            .Map(d=>d.CurrentStepName,s=>s.Workflow.ActualHandleStepName)
-            .Map(d=>d.ActualHandlerName,s=>s.Workflow.ActualHandlerName)
+            .Map(d => d.CurrentStepName, s => s.Workflow.ActualHandleStepName)
+            .Map(d => d.ActualHandlerName, s => s.Workflow.ActualHandlerName)
             .IgnoreIf((s, d) => s.Workflow == null, d => d.CurrentStepName)
             .IgnoreIf((s, d) => s.Workflow == null, d => d.ActualHandlerName);
 
+        config.ForType<ExpiredTimeWithConfig, UpdateOrderDto>()
+            .Map(d => d.TimeLimit, s => s.TimeText)
+            .Map(d => d.TimeLimitCount, s => s.Count)
+            .Map(d => d.TimeLimitUnit, s => s.TimeType);
+
+        config.ForType<ExpiredTimeWithConfig, Order>()
+            .Inherits<ExpiredTimeWithConfig, UpdateOrderDto>();
     }
 }

+ 5 - 5
src/Hotline.Application/Orders/OrderApplication.cs

@@ -75,11 +75,11 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         order.ExpiredTime = expiredTimeConfig.ExpiredTime;
         order.NearlyExpiredTime = expiredTimeConfig.NearlyExpiredTime;
 
-        if (string.IsNullOrEmpty(order.WorkflowId))
-            throw new UserFriendlyException("该工单流程id异常");
-        var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, cancellationToken: cancellationToken);
-        await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime,
-            expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
+        //if (string.IsNullOrEmpty(order.WorkflowId))
+        //    throw new UserFriendlyException("该工单流程id异常");
+        //var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, cancellationToken: cancellationToken);
+        //await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime,
+        //    expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
 
         await _orderRepository.UpdateAsync(order, cancellationToken);
     }

+ 23 - 19
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -65,16 +65,6 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public DateTime? StartTime { get; set; }
 
-        /// <summary>
-        /// 过期时间
-        /// </summary>
-        public DateTime? ExpiredTime { get; set; }
-
-        /// <summary>
-        /// 即将超期时间
-        /// </summary>
-        public DateTime? NearlyExpiredTime { get; set; }
-
         /// <summary>
         /// 交办时间(中心交部门办理时间)
         /// </summary>
@@ -102,15 +92,6 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public double AllDuration { get; set; }
 
-        /// <summary>
-        /// 办理时间限制(如:24小时、7个工作日)
-        /// </summary>
-        public string? TimeLimit { get; set; }
-
-        public int? TimeLimitCount { get; set; }
-
-        public ETimeType? TimeLimitUnit { get; set; }
-
         #region 实际办理信息(节点,部门,意见)
 
         /// <summary>
@@ -658,6 +639,29 @@ namespace Hotline.Share.Dtos.Order
         /// 外部工单唯一标识
         /// </summary>
         public string? ExternalId { get; set; }
+
+        #region 期满时间
+
+        /// <summary>
+        /// 过期时间
+        /// </summary>
+        public DateTime? ExpiredTime { get; set; }
+
+        /// <summary>
+        /// 即将超期时间
+        /// </summary>
+        public DateTime? NearlyExpiredTime { get; set; }
+
+        /// <summary>
+        /// 办理时间限制(如:24小时、7个工作日)
+        /// </summary>
+        public string? TimeLimit { get; set; }
+
+        public int? TimeLimitCount { get; set; }
+
+        public ETimeType? TimeLimitUnit { get; set; }
+
+        #endregion
     }
 
     public record CanLinkCallRecordOrderDto : PagedKeywordRequest

+ 2 - 2
src/Hotline/FlowEngine/Notifications/WorkflowNotify.cs

@@ -10,8 +10,8 @@ public record WorkflowNotify(Workflow Workflow, BasicWorkflowDto Dto) : INotific
 
 public record StartWorkflowNotify(Workflow Workflow, BasicWorkflowDto Dto, FlowAssignInfo FlowAssignInfo, WorkflowTrace Trace) : WorkflowNotify(Workflow, Dto);
 
-public record NextStepNotify(Workflow Workflow, BasicWorkflowDto Dto, FlowAssignInfo FlowAssignInfo, WorkflowTrace Trace, 
-    StepDefine NextStepDefine, string HandlerOrgCode) : WorkflowNotify(Workflow, Dto);
+public record NextStepNotify(Workflow Workflow, BasicWorkflowDto Dto, FlowAssignInfo FlowAssignInfo, WorkflowTrace Trace,
+    StepDefine NextStepDefine, string HandlerOrgId, bool ExpiredTimeChanged) : WorkflowNotify(Workflow, Dto);
 
 public record AcceptWorkflowNotify(Workflow Workflow) : INotification;
 

+ 21 - 22
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -16,14 +16,13 @@ namespace Hotline.FlowEngine.Workflows
         /// 创建流程
         /// </summary>
         Task<Workflow> CreateWorkflowAsync(WorkflowModule wfModule, string title, string userId, string userCode,
-            string? externalId = null, string? timelimitText = null, int? timelimitCount = null, ETimeType? timeType = null, DateTime? expiredTime = null, DateTime? nearlyExpiredTime = null,
-            CancellationToken cancellationToken = default);
+            string? externalId = null, CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 进行流程的开始节点
         /// </summary>
         Task StartAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto, StepDefine firstStepDefine,
-            bool isNextDynamic, FlowAssignInfo flowAssignInfo, ECounterSignType counterSignType, CancellationToken cancellationToken);
+            bool isNextDynamic, FlowAssignInfo flowAssignInfo, ECounterSignType counterSignType, DateTime? expiredTime, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询工作流
@@ -48,7 +47,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理(流转至下一节点)
         /// </summary>
         Task NextAsync(Workflow workflow, WorkflowStep currentStep, NextWorkflowDto dto, StepDefine nextStepDefine,
-            bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken);
+            bool isNextDynamic, FlowAssignInfo flowAssignInfo, DateTime? expiredTime, CancellationToken cancellationToken);
 
         /// <summary>
         /// 退回(返回前一节点)
@@ -60,24 +59,24 @@ namespace Hotline.FlowEngine.Workflows
         /// 撤回(返回到之前任意节点)
         /// </summary>
         Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
-            CancellationToken cancellationToken);
+          DateTime? expiredTime, CancellationToken cancellationToken);
 
         /// <summary>
         /// 撤回至开始节点
         /// </summary>
         Task RecallToStartStepAsync(string workflowId, string opinion, CancellationToken cancellationToken);
 
-        /// <summary>
-        /// 跳转(直接将流程跳转至任意节点)
-        /// </summary>
-        Task JumpAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
-            CancellationToken cancellationToken);
+        ///// <summary>
+        ///// 跳转(直接将流程跳转至任意节点)
+        ///// </summary>
+        //Task JumpAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
+        //    CancellationToken cancellationToken);
 
-        /// <summary>
-        /// 重办
-        /// </summary>
-        Task RedoAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
-            CancellationToken cancellationToken);
+        ///// <summary>
+        ///// 重办
+        ///// </summary>
+        //Task RedoAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine, FlowAssignInfo flowAssignInfo,
+        //    CancellationToken cancellationToken);
 
         /// <summary>
         /// 否决(审批流程不通过)
@@ -130,11 +129,11 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task CancelAsync(CancelDto dto, CancellationToken cancellationToken);
 
-        /// <summary>
-        /// 更新期满时间
-        /// </summary>
-        Task UpdateExpiredTimeAsync(Workflow workflow, DateTime expiredTime, string timelimit, int? timelimiteCount,
-            ETimeType? timelimitUnit, DateTime nearlyExpiredTime, CancellationToken cancellationToken);
+        ///// <summary>
+        ///// 更新期满时间
+        ///// </summary>
+        //Task UpdateExpiredTimeAsync(Workflow workflow, DateTime expiredTime, string timelimit, int? timelimiteCount,
+        //    ETimeType? timelimitUnit, DateTime nearlyExpiredTime, CancellationToken cancellationToken);
 
         /// <summary>
         /// 新增流程流转记录
@@ -144,7 +143,7 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 创建开始节点
         /// </summary>
-        WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto, List<Kv> handlers);
+        WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto, List<Kv> handlers, DateTime? expiredTime);
 
         /// <summary>
         /// 查询未完成节点
@@ -190,7 +189,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理节点
         /// </summary>
         Task HandleStepAsync(WorkflowStep step, Workflow workflow, BasicWorkflowDto dto,
-            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, CancellationToken cancellationToken);
+            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, DateTime? expiredTime, CancellationToken cancellationToken);
 
         /// <summary>
         /// 获取会签类型

+ 16 - 16
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -42,28 +42,28 @@ public partial class Workflow : CreationEntity
     /// </summary>
     public string Title { get; set; }
 
-    /// <summary>
-    /// 到期时间(期满时间)
-    /// </summary>
-    public DateTime ExpiredTime { get; set; }
+    ///// <summary>
+    ///// 到期时间(期满时间)
+    ///// </summary>
+    //public DateTime ExpiredTime { get; set; }
 
-    /// <summary>
-    /// 即将超期时间
-    /// </summary>
-    public DateTime? NearlyExpiredTime { get; set; }
+    ///// <summary>
+    ///// 即将超期时间
+    ///// </summary>
+    //public DateTime? NearlyExpiredTime { get; set; }
 
-    #region 办理时限
+    //#region 办理时限
 
-    /// <summary>
-    /// 办理时间限制(如:24小时、7个工作日)
-    /// </summary>
-    public string? TimeLimit { get; set; }
+    ///// <summary>
+    ///// 办理时间限制(如:24小时、7个工作日)
+    ///// </summary>
+    //public string? TimeLimit { get; set; }
 
-    public int? TimeLimitCount { get; set; }
+    //public int? TimeLimitCount { get; set; }
 
-    public ETimeType? TimeLimitUnit { get; set; } = ETimeType.WorkDay;
+    //public ETimeType? TimeLimitUnit { get; set; } = ETimeType.WorkDay;
 
-    #endregion
+    //#endregion
 
     /// <summary>
     /// end节点办理完成时间

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

@@ -62,14 +62,12 @@ namespace Hotline.FlowEngine.Workflows
 
         public async Task<Workflow> CreateWorkflowAsync(WorkflowModule wfModule, string title, string userId,
             string userCode,
-            string? externalId = null, string? timelimit = null, int? timelimitCount = null, ETimeType? timeType = null,
-            DateTime? expiredTime = null, DateTime? nearlyExpiredTime = null,
+            string? externalId = null,
             CancellationToken cancellationToken = default)
         {
             var definition = wfModule.Definition;
             if (definition is null)
                 throw new UserFriendlyException("无效流程模板");
-            timelimit ??= "1个自然日";
             var workflow = new Workflow
             {
                 Title = title,
@@ -78,11 +76,11 @@ namespace Hotline.FlowEngine.Workflows
                 ModuleCode = wfModule.Code,
                 DefinitionId = definition.Id,
                 Status = EWorkflowStatus.Runnable,
-                TimeLimit = timelimit,
-                TimeLimitCount = timelimitCount,
-                TimeLimitUnit = timeType,
-                ExpiredTime = expiredTime.HasValue ? expiredTime.Value : DateTime.Now.AddDays(1),
-                NearlyExpiredTime = nearlyExpiredTime,
+                //TimeLimit = timelimit,
+                //TimeLimitCount = timelimitCount,
+                //TimeLimitUnit = timeType,
+                //ExpiredTime = expiredTime.HasValue ? expiredTime.Value : DateTime.Now.AddDays(1),
+                //NearlyExpiredTime = nearlyExpiredTime,
                 Steps = new(),
                 Traces = new(),
                 WorkflowDefinition = definition,
@@ -102,7 +100,7 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         public async Task StartAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto,
             StepDefine firstStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo,
-            ECounterSignType counterSignType, CancellationToken cancellationToken)
+            ECounterSignType counterSignType, DateTime? expiredTime, CancellationToken cancellationToken)
         {
             //1. 创建first节点 (和trace)2.办理开始节点 
 
@@ -124,7 +122,8 @@ namespace Hotline.FlowEngine.Workflows
             }
 
             //firststeps
-            var firstSteps = await CreateNextStepsAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, flowAssignInfo, cancellationToken);
+            var firstSteps = await CreateNextStepsAsync(workflow, startStep, dto, firstStepDefine,
+                isNextDynamic, flowAssignInfo, expiredTime, cancellationToken);
             if (firstSteps.Any())
                 workflow.Steps.AddRange(firstSteps);
 
@@ -328,7 +327,8 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理(流转至下一节点)
         /// </summary>
         public async Task NextAsync(Workflow workflow, WorkflowStep currentStep, NextWorkflowDto dto,
-            StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+            StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo,
+            DateTime? expiredTime, CancellationToken cancellationToken)
         {
             ValidatePermission(workflow, _sessionContext.RequiredOrgId, _sessionContext.RequiredUserId);
             //CheckWhetherRunnable(workflow.Status);
@@ -375,8 +375,8 @@ namespace Hotline.FlowEngine.Workflows
                 }
             }
 
-            await HandleStepAsync(currentStep, workflow, dto, flowAssignInfo.FlowAssignType, counterSignType,
-                cancellationToken);
+            await HandleStepAsync(currentStep, workflow, dto, flowAssignInfo.FlowAssignType,
+                counterSignType, expiredTime, cancellationToken);
 
             currentStep.IsActualHandled = CheckIsActualHandle(workflow, currentStep, nextStepDefine, dto);
 
@@ -476,7 +476,7 @@ namespace Hotline.FlowEngine.Workflows
 
             //创建下一/N个节点(会签汇总节点:会签未全部办理时不创建,最后一个会签办理节点创建会签汇总节点)
             var nextSteps = await CreateNextStepsAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic,
-                    flowAssignInfo, cancellationToken);
+                    flowAssignInfo, expiredTime, cancellationToken);
 
             //赋值当前节点的下级办理节点
             if (dto.IsStartCountersign
@@ -542,7 +542,8 @@ namespace Hotline.FlowEngine.Workflows
             #endregion
 
             await _mediator.Publish(
-                new NextStepNotify(workflow, dto, flowAssignInfo, trace, nextStepDefine, _sessionContext.RequiredOrgId),
+                new NextStepNotify(workflow, dto, flowAssignInfo, trace, nextStepDefine,
+                    _sessionContext.RequiredOrgId, expiredTime.HasValue),
                 cancellationToken);
         }
 
@@ -703,7 +704,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 撤回(返回到之前任意节点)
         /// </summary>
         public async Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
-            FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+            FlowAssignInfo flowAssignInfo, DateTime? expiredTime, CancellationToken cancellationToken)
         {
             var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
             if (targetStep is null)
@@ -713,7 +714,7 @@ namespace Hotline.FlowEngine.Workflows
             await RecallTraceAsync(workflow.Id, dto.Opinion, cancellationToken);
 
             var isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStep,
-                EWorkflowTraceStatus.Recall, cancellationToken);
+                EWorkflowTraceStatus.Recall, expiredTime, cancellationToken);
 
             workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
 
@@ -764,116 +765,116 @@ namespace Hotline.FlowEngine.Workflows
             await _mediator.Publish(new RecallNotify(workflow, startStep, dto, isOrgToCenter), cancellationToken);
         }
 
-        /// <summary>
-        /// 跳转(直接将流程跳转至任意节点)
-        /// </summary>
-        public async Task JumpAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
-            FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
-        {
-            //todo 跳转至结束节点,(自动办理)
-            //if (targetStepDefine.StepType is EStepType.Start or EStepType.End)
-            //    throw UserFriendlyException.SameMessage("开始/结束节点不支持跳转");
+        ///// <summary>
+        ///// 跳转(直接将流程跳转至任意节点)
+        ///// </summary>
+        //public async Task JumpAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
+        //    FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+        //{
+        //    //todo 跳转至结束节点,(自动办理)
+        //    //if (targetStepDefine.StepType is EStepType.Start or EStepType.End)
+        //    //    throw UserFriendlyException.SameMessage("开始/结束节点不支持跳转");
 
-            //update uncompleted traces
-            await JumpTraceAsync(workflow.Id, dto, cancellationToken);
+        //    //update uncompleted traces
+        //    await JumpTraceAsync(workflow.Id, dto, cancellationToken);
 
-            bool isOrgToCenter = false, isCenterToOrg = false;
-            var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
-            if (targetStep == null)
-            {
-                //向后跳转
-
-                //此场景并非按配置流转,默认最靠后的节点做为targetStep的prevStep
-                var lastStep = workflow.Steps.Where(d => d.IsOrigin).MaxBy(d => d.CreationTime);
-                if (lastStep is null || lastStep.StepType is EStepType.End)
-                    throw new UserFriendlyException($"流程流转数据异常,未结束流程出现endStep, flowId: {workflow.Id}", "流程流转数据异常");
-
-                var targetSteps = await CreateConfigStepsAsync(workflow, targetStepDefine, lastStep, dto,
-                    flowAssignInfo, EWorkflowTraceStatus.Jump, cancellationToken);
-                targetStep = targetSteps.First();
-
-                workflow.EndCountersign();
-                workflow.ResetOption();
-
-                ////更新当前办理节点信息
-                //workflow.UpdateWorkflowCurrentStepInfo(dto.IsStartCountersign,
-                //    _sessionContext.RequiredUserId, _sessionContext.UserName,
-                //    _sessionContext.RequiredOrgId, _sessionContext.OrgName,
-                //    _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
-                //    nextStep: targetStep);
-
-                //calc workflow expired time
-                isCenterToOrg = CheckIfFlowFromCenterToOrg(workflow, targetStep);
-                //if (isCenterToOrg)
-                //    workflow.ExpiredTime = CalculateExpiredTime("");//todo calc expiredTime
-
-                #region 补充中间节点处理方案(暂不需要)
-
-                //var completeStepCodes = workflow.StepBoxes.Select(d => d.Code);
-                //var uncompleteStepDefines = workflow.Definition.Steps.Where(d => !completeStepCodes.Contains(d.Code));
-                //创建当前节点与目标节点中间节点
-                //var jumpDto = new BasicWorkflowDto
-                //{
-                //    Opinion = "跳转补充"
-                //};
-
-                //foreach (var stepDefine in uncompleteStepDefines)
-                //{
-                //    var previousStepId = lastStepBox.Steps.Count > 1 ? lastStepBox.Id : lastStepBox.Steps.First().Id;
-                //    if (dto.TargetStepCode == stepDefine.Code)
-                //    {
-                //        await CreateStepAsync(workflow, stepDefine, dto, lastStepBox.Id, previousStepId, cancellationToken);
-                //        break;
-                //    }
-
-                //    //jump业务下,如果当前节点为会签节点,第一个补充节点的subStep.PreviousId无法确定从哪个子节点跳转过来,统一处理为当前节点的stepBox.Id
-                //    lastStepBox = await CreateStepAsync(workflow, stepDefine, dto, lastStepBox.Id, previousStepId, cancellationToken);
-                //} 
-
-                #endregion
-            }
-            else
-            {
-                //返回之前节点
-                isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStep,
-                    EWorkflowTraceStatus.Jump, cancellationToken);
-            }
+        //    bool isOrgToCenter = false, isCenterToOrg = false;
+        //    var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
+        //    if (targetStep == null)
+        //    {
+        //        //向后跳转
+
+        //        //此场景并非按配置流转,默认最靠后的节点做为targetStep的prevStep
+        //        var lastStep = workflow.Steps.Where(d => d.IsOrigin).MaxBy(d => d.CreationTime);
+        //        if (lastStep is null || lastStep.StepType is EStepType.End)
+        //            throw new UserFriendlyException($"流程流转数据异常,未结束流程出现endStep, flowId: {workflow.Id}", "流程流转数据异常");
+
+        //        var targetSteps = await CreateConfigStepsAsync(workflow, targetStepDefine, lastStep, dto,
+        //            flowAssignInfo, EWorkflowTraceStatus.Jump, cancellationToken);
+        //        targetStep = targetSteps.First();
+
+        //        workflow.EndCountersign();
+        //        workflow.ResetOption();
+
+        //        ////更新当前办理节点信息
+        //        //workflow.UpdateWorkflowCurrentStepInfo(dto.IsStartCountersign,
+        //        //    _sessionContext.RequiredUserId, _sessionContext.UserName,
+        //        //    _sessionContext.RequiredOrgId, _sessionContext.OrgName,
+        //        //    _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
+        //        //    nextStep: targetStep);
+
+        //        //calc workflow expired time
+        //        isCenterToOrg = CheckIfFlowFromCenterToOrg(workflow, targetStep);
+        //        //if (isCenterToOrg)
+        //        //    workflow.ExpiredTime = CalculateExpiredTime("");//todo calc expiredTime
+
+        //        #region 补充中间节点处理方案(暂不需要)
+
+        //        //var completeStepCodes = workflow.StepBoxes.Select(d => d.Code);
+        //        //var uncompleteStepDefines = workflow.Definition.Steps.Where(d => !completeStepCodes.Contains(d.Code));
+        //        //创建当前节点与目标节点中间节点
+        //        //var jumpDto = new BasicWorkflowDto
+        //        //{
+        //        //    Opinion = "跳转补充"
+        //        //};
+
+        //        //foreach (var stepDefine in uncompleteStepDefines)
+        //        //{
+        //        //    var previousStepId = lastStepBox.Steps.Count > 1 ? lastStepBox.Id : lastStepBox.Steps.First().Id;
+        //        //    if (dto.TargetStepCode == stepDefine.Code)
+        //        //    {
+        //        //        await CreateStepAsync(workflow, stepDefine, dto, lastStepBox.Id, previousStepId, cancellationToken);
+        //        //        break;
+        //        //    }
+
+        //        //    //jump业务下,如果当前节点为会签节点,第一个补充节点的subStep.PreviousId无法确定从哪个子节点跳转过来,统一处理为当前节点的stepBox.Id
+        //        //    lastStepBox = await CreateStepAsync(workflow, stepDefine, dto, lastStepBox.Id, previousStepId, cancellationToken);
+        //        //} 
+
+        //        #endregion
+        //    }
+        //    else
+        //    {
+        //        //返回之前节点
+        //        isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStep,
+        //            EWorkflowTraceStatus.Jump, cancellationToken);
+        //    }
 
-            workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
-            await _workflowRepository.UpdateAsync(workflow, cancellationToken);
+        //    workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
+        //    await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
-            await _mediator.Publish(
-                new JumpNotify(workflow, targetStep, dto, flowAssignInfo, isCenterToOrg, isOrgToCenter),
-                cancellationToken);
-        }
+        //    await _mediator.Publish(
+        //        new JumpNotify(workflow, targetStep, dto, flowAssignInfo, isCenterToOrg, isOrgToCenter),
+        //        cancellationToken);
+        //}
 
-        /// <summary>
-        /// 重办
-        /// </summary>
-        public async Task RedoAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
-            FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
-        {
-            if (targetStepDefine.StepType is EStepType.Start or EStepType.End)
-                throw UserFriendlyException.SameMessage("开始/结束节点不支持重办");
+        ///// <summary>
+        ///// 重办
+        ///// </summary>
+        //public async Task RedoAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
+        //    FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+        //{
+        //    if (targetStepDefine.StepType is EStepType.Start or EStepType.End)
+        //        throw UserFriendlyException.SameMessage("开始/结束节点不支持重办");
 
-            var targetStepBox = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode);
-            if (targetStepBox is null)
-                throw UserFriendlyException.SameMessage("未找到该节点配置");
+        //    var targetStepBox = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode);
+        //    if (targetStepBox is null)
+        //        throw UserFriendlyException.SameMessage("未找到该节点配置");
 
-            var isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStepBox,
-                EWorkflowTraceStatus.Redo, cancellationToken);
+        //    var isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStepBox,
+        //        EWorkflowTraceStatus.Redo, cancellationToken);
 
-            workflow.Redo();
-            workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
+        //    workflow.Redo();
+        //    workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
 
-            //todo calc expiredTime
-            //dto.Extension.TimeLimitCount
+        //    //todo calc expiredTime
+        //    //dto.Extension.TimeLimitCount
 
 
-            await _workflowRepository.UpdateAsync(workflow, cancellationToken);
+        //    await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
-            await _mediator.Publish(new RedoNotify(workflow, dto, isOrgToCenter), cancellationToken);
-        }
+        //    await _mediator.Publish(new RedoNotify(workflow, dto, isOrgToCenter), cancellationToken);
+        //}
 
         /// <summary>
         /// 否决(审批流程不通过)
@@ -883,7 +884,8 @@ namespace Hotline.FlowEngine.Workflows
         {
             var currentStep = GetUnHandleStep(workflow.Steps, _sessionContext.RequiredOrgId,
                 _sessionContext.RequiredUserId);
-            await HandleStepAsync(currentStep, workflow, dto, null, null, cancellationToken);
+            await HandleStepAsync(currentStep, workflow, dto, null,
+                null, null, cancellationToken);
 
             var endStepDefine = workflow.WorkflowDefinition.FindEndStepDefine();
             var endTrace = await EndAsync(workflow, dto, endStepDefine, currentStep, EReviewResult.Failed,
@@ -1020,20 +1022,20 @@ namespace Hotline.FlowEngine.Workflows
             await _mediator.Publish(new CancelWorkflowNotify(workflow), cancellationToken);
         }
 
-        /// <summary>
-        /// 更新期满时间
-        /// </summary>
-        public async Task UpdateExpiredTimeAsync(Workflow workflow, DateTime expiredTime, string timelimit,
-            int? timelimiteCount,
-            ETimeType? timelimitUnit, DateTime nearlyExpiredTime, CancellationToken cancellationToken)
-        {
-            workflow.ExpiredTime = expiredTime;
-            workflow.NearlyExpiredTime = nearlyExpiredTime;
-            workflow.TimeLimit = timelimit;
-            workflow.TimeLimitUnit = timelimitUnit;
-            workflow.TimeLimitCount = timelimiteCount;
-            await _workflowRepository.UpdateAsync(workflow, cancellationToken);
-        }
+        ///// <summary>
+        ///// 更新期满时间
+        ///// </summary>
+        //public async Task UpdateExpiredTimeAsync(Workflow workflow, DateTime expiredTime, string timelimit,
+        //    int? timelimiteCount,
+        //    ETimeType? timelimitUnit, DateTime nearlyExpiredTime, CancellationToken cancellationToken)
+        //{
+        //    workflow.ExpiredTime = expiredTime;
+        //    workflow.NearlyExpiredTime = nearlyExpiredTime;
+        //    workflow.TimeLimit = timelimit;
+        //    workflow.TimeLimitUnit = timelimitUnit;
+        //    workflow.TimeLimitCount = timelimiteCount;
+        //    await _workflowRepository.UpdateAsync(workflow, cancellationToken);
+        //}
 
         /// <summary>
         /// 新增流程流转记录
@@ -1051,8 +1053,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 创建开始节点
         /// </summary>
-        public WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto,
-            List<Kv> handles)
+        public WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine,
+            BasicWorkflowDto dto, List<Kv> handles, DateTime? expiredTime)
         {
             //startstep
             var nextSteps = _mapper.Map<List<StepSimple>>(startStepDefine.NextSteps);
@@ -1072,7 +1074,7 @@ namespace Hotline.FlowEngine.Workflows
             startStep.IsOrigin = true;
             startStep.Status = EWorkflowStepStatus.WaitForHandle;
             startStep.PrevChosenStepCode = null;
-            startStep.StepExpiredTime = workflow.ExpiredTime;
+            startStep.StepExpiredTime = expiredTime;
 
             startStep.InitId();
             return startStep;
@@ -1087,9 +1089,10 @@ namespace Hotline.FlowEngine.Workflows
         #region private method
 
         public async Task<WorkflowStep> CreateStartStepAsync(Workflow workflow, StepDefine startStepDefine,
-            BasicWorkflowDto dto, List<Kv> handles, EWorkflowTraceStatus traceStatus, CancellationToken cancellationToken)
+            BasicWorkflowDto dto, List<Kv> handles, EWorkflowTraceStatus traceStatus, DateTime? expiredTime,
+            CancellationToken cancellationToken)
         {
-            var startStep = CreateStartStep(workflow, startStepDefine, dto, handles);
+            var startStep = CreateStartStep(workflow, startStepDefine, dto, handles, expiredTime);
             await _workflowStepRepository.AddAsync(startStep, cancellationToken);
             await CreateTraceAsync(workflow, startStep, traceStatus, cancellationToken);
             return startStep;
@@ -1112,8 +1115,9 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 创建下1/N个节点
         /// </summary>
-        private async Task<List<WorkflowStep>> CreateNextStepsAsync(Workflow workflow, WorkflowStep currentStep, BasicWorkflowDto dto,
-            StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+        private async Task<List<WorkflowStep>> CreateNextStepsAsync(Workflow workflow, WorkflowStep currentStep,
+            BasicWorkflowDto dto, StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo,
+            DateTime? expiredTime, CancellationToken cancellationToken)
         {
             List<WorkflowStep> nextSteps = new();
             if (currentStep.IsInCountersign())
@@ -1128,13 +1132,13 @@ namespace Hotline.FlowEngine.Workflows
                         {
                             //依据会签策略创建会签下一级节点
                             nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
-                                flowAssignInfo.FlowAssignType, cancellationToken);
+                                flowAssignInfo.FlowAssignType, expiredTime, cancellationToken);
                         }
                         else
                         {
                             //创建普通节点(根据配置)
                             nextSteps = await CreateConfigStepsAsync(workflow, nextStepDefine, currentStep, dto,
-                                flowAssignInfo, EWorkflowTraceStatus.Normal, cancellationToken);
+                                flowAssignInfo, EWorkflowTraceStatus.Normal, expiredTime, cancellationToken);
                         }
                     }
                     else
@@ -1145,8 +1149,7 @@ namespace Hotline.FlowEngine.Workflows
                         if (csStartStep is null)
                             throw new UserFriendlyException("未查询到会签节点");
 
-                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, csStartStep, dto,
-                            cancellationToken);
+                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, csStartStep, dto, expiredTime, cancellationToken);
                     }
                 }
                 else
@@ -1154,14 +1157,13 @@ namespace Hotline.FlowEngine.Workflows
                     if (dto.BackToCountersignEnd)
                     {
                         //todo check if cs all complete, create next
-                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, currentStep, dto,
-                            cancellationToken);
+                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, currentStep, dto, expiredTime, cancellationToken);
                     }
                     else
                     {
                         //依据会签策略创建会签下一级节点
                         nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
-                            flowAssignInfo.FlowAssignType, cancellationToken);
+                            flowAssignInfo.FlowAssignType, expiredTime, cancellationToken);
                     }
                 }
             }
@@ -1169,19 +1171,19 @@ namespace Hotline.FlowEngine.Workflows
             {
                 //依据会签策略创建会签下一级节点
                 nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
-                    flowAssignInfo.FlowAssignType, cancellationToken);
+                    flowAssignInfo.FlowAssignType, expiredTime, cancellationToken);
             }
             else if (isNextDynamic)
             {
                 //创建动态下一级节点
                 nextSteps = await CreateDynamicStepsAsync(workflow, nextStepDefine, currentStep, dto, flowAssignInfo,
-                    cancellationToken);
+                    expiredTime, cancellationToken);
             }
             else
             {
                 //创建普通节点(根据配置)
                 nextSteps = await CreateConfigStepsAsync(workflow, nextStepDefine, currentStep, dto, flowAssignInfo,
-                    EWorkflowTraceStatus.Normal, cancellationToken);
+                    EWorkflowTraceStatus.Normal, expiredTime, cancellationToken);
             }
 
             return nextSteps;
@@ -1193,6 +1195,7 @@ namespace Hotline.FlowEngine.Workflows
             WorkflowStep prevStep,
             BasicWorkflowDto dto,
             FlowAssignInfo flowAssignInfo,
+            DateTime? expiredTime,
             CancellationToken cancellationToken)
         {
             var handlerType = nextStepDefine.InstancePolicy switch
@@ -1207,7 +1210,7 @@ namespace Hotline.FlowEngine.Workflows
 
             return await CreateStepsAsync(workflow, nextStepDefine, prevStep, dto,
                 flowAssignInfo.FlowAssignType, dto.NextHandlers, null, EWorkflowStepStatus.WaitForAccept,
-                ECountersignPosition.None, false, EWorkflowTraceStatus.Normal, handlerType, cancellationToken);
+                ECountersignPosition.None, false, EWorkflowTraceStatus.Normal, handlerType, expiredTime, cancellationToken);
         }
 
         private Task<List<WorkflowStep>> CreateCountersignStepsAsync(
@@ -1216,7 +1219,7 @@ namespace Hotline.FlowEngine.Workflows
             WorkflowStep prevStep,
             BasicWorkflowDto dto,
             EFlowAssignType flowAssignType,
-            //DateTime expiredTime,
+            DateTime? expiredTime,
             CancellationToken cancellationToken
         )
         {
@@ -1235,14 +1238,14 @@ namespace Hotline.FlowEngine.Workflows
             return CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignType, dto.NextHandlers,
                 countersignId,
                 EWorkflowStepStatus.WaitForAccept, prevStep.GetNextStepCountersignPosition(),
-                false, EWorkflowTraceStatus.Normal, handlerType, cancellationToken);
+                false, EWorkflowTraceStatus.Normal, handlerType, expiredTime, cancellationToken);
         }
 
         /// <summary>
         /// 根据传入节点的上一节点创建会签汇总节点(汇总传入节点的前一节点)
         /// </summary>
         private async Task<List<WorkflowStep>> CreateCsEndStepsByPrevStepAsync(Workflow workflow, WorkflowStep step,
-            BasicWorkflowDto dto, CancellationToken cancellationToken)
+            BasicWorkflowDto dto, DateTime? expiredTime, CancellationToken cancellationToken)
         {
             var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == step.PrevStepId);
             if (prevStep is null)
@@ -1253,7 +1256,7 @@ namespace Hotline.FlowEngine.Workflows
             {
                 //todo 创建会签汇总节点
                 var countersignEndStep =
-                    await CreateCountersignEndStepAsync(prevStep, dto, workflow.ExpiredTime, cancellationToken);
+                    await CreateCountersignEndStepAsync(prevStep, dto, expiredTime, cancellationToken);
                 nextSteps = new List<WorkflowStep> { countersignEndStep };
 
                 //create trace
@@ -1266,7 +1269,7 @@ namespace Hotline.FlowEngine.Workflows
         }
 
         private async Task<WorkflowStep> CreateCountersignEndStepAsync(WorkflowStep countersignStartStep,
-            BasicWorkflowDto dto, DateTime expiredTime, CancellationToken cancellationToken)
+            BasicWorkflowDto dto, DateTime? expiredTime, CancellationToken cancellationToken)
         {
             var csEndStep = _mapper.Map<WorkflowStep>(countersignStartStep);
             csEndStep.Status = EWorkflowStepStatus.WaitForAccept;
@@ -1335,7 +1338,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理节点
         /// </summary>
         public async Task HandleStepAsync(WorkflowStep step, Workflow workflow, BasicWorkflowDto dto,
-            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, CancellationToken cancellationToken)
+            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, DateTime? expiredTime, CancellationToken cancellationToken)
         {
             if (step.Status is EWorkflowStepStatus.Handled)
                 throw UserFriendlyException.SameMessage("当前节点状态已办理");
@@ -1353,7 +1356,7 @@ namespace Hotline.FlowEngine.Workflows
                     !d.IsCompleted() && d.StarterId == _sessionContext.RequiredUserId);
                 if (exists)
                     throw new UserFriendlyException("该用户在当前流程存在未结束会签");
-                await StartCountersignAsync(workflow, step, dto, flowAssignType, counterSignType, cancellationToken);
+                await StartCountersignAsync(workflow, step, dto, flowAssignType, counterSignType, expiredTime, cancellationToken);
             }
 
             //办理参数
@@ -1396,11 +1399,11 @@ namespace Hotline.FlowEngine.Workflows
         /// 开始会签(创建会签数据,更新currentStep会签数据)
         /// </summary>
         private async Task StartCountersignAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto,
-            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, CancellationToken cancellationToken)
+            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, DateTime? expiredTime, CancellationToken cancellationToken)
         {
             var countersign = await CreateCountersignAsync(
                 workflow, startStep, dto.NextHandlers, flowAssignType,
-                counterSignType, workflow.ExpiredTime,
+                counterSignType, expiredTime,
                 startStep.CountersignId, cancellationToken);
             startStep.StartCountersign(countersign.Id);
         }
@@ -1491,7 +1494,7 @@ namespace Hotline.FlowEngine.Workflows
 
         private async Task<WorkflowCountersign> CreateCountersignAsync(
             Workflow workflow, WorkflowStep startStep, List<Kv> handlers, EFlowAssignType? flowAssignType,
-            ECounterSignType? counterSignType, DateTime expiredTime, string? parentId = null,
+            ECounterSignType? counterSignType, DateTime? expiredTime, string? parentId = null,
             CancellationToken cancellationToken = default)
         {
             var members = handlers.Select(d => new WorkflowCountersignMember
@@ -1654,8 +1657,8 @@ namespace Hotline.FlowEngine.Workflows
         }
 
         private async Task<bool> RecallAsync(Workflow workflow, BasicWorkflowDto dto, FlowAssignInfo flowAssignInfo,
-            StepDefine targetStepDefine, WorkflowStep targetStep,
-            EWorkflowTraceStatus traceStatus, CancellationToken cancellationToken)
+            StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceStatus traceStatus,
+            DateTime? expiredTime, CancellationToken cancellationToken)
         {
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
 
@@ -1682,12 +1685,11 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.SetStatusRunnable();
 
             var targetStepNew = targetIsStartStep
-                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, traceStatus,
-                    cancellationToken)
+                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, traceStatus, expiredTime, cancellationToken)
                 : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers,
                     null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
-                    null, cancellationToken)).First();
+                    null, expiredTime, cancellationToken)).First();
 
 
             //更新当前办理节点信息
@@ -1767,8 +1769,8 @@ namespace Hotline.FlowEngine.Workflows
             WorkflowStep prevStep,
             BasicWorkflowDto dto,
             FlowAssignInfo flowAssignInfo,
-            //DateTime expiredTime,
             EWorkflowTraceStatus traceStatus,
+            DateTime? expiredTime,
             CancellationToken cancellationToken)
         {
             List<Kv> handlers;
@@ -1792,7 +1794,7 @@ namespace Hotline.FlowEngine.Workflows
 
             return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignInfo.FlowAssignType, handlers,
                 null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
-                null, cancellationToken);
+                null, expiredTime, cancellationToken);
         }
 
         private async Task<List<WorkflowStep>> CreateStepsAsync(
@@ -1805,10 +1807,10 @@ namespace Hotline.FlowEngine.Workflows
             string? countersignId,
             EWorkflowStepStatus stepStatus,
             ECountersignPosition csPosition,
-            //DateTime expiredTime,
             bool isOrigin,
             EWorkflowTraceStatus traceStatus,
             EHandlerType? handlerType = null,
+            DateTime? expiredTime = null,
             CancellationToken cancellationToken = default
         )
         {
@@ -1823,7 +1825,7 @@ namespace Hotline.FlowEngine.Workflows
                 {
                     var step = CreateStep(stepDefine, prevStep, workflow.Id, flowAssignType, new List<Kv> { handler },
                         dto.NextStepCode, dto.NextMainHandler, countersignId,
-                        stepStatus, csPosition, workflow.ExpiredTime, dto.NextStepName, isOrigin, handlerType);
+                        stepStatus, csPosition, expiredTime, dto.NextStepName, isOrigin, handlerType);
 
                     steps.Add(step);
                 }
@@ -1832,7 +1834,7 @@ namespace Hotline.FlowEngine.Workflows
             {
                 var step = CreateStep(stepDefine, prevStep, workflow.Id, flowAssignType, handlers,
                     dto.NextStepCode, dto.NextMainHandler, countersignId,
-                    stepStatus, csPosition, workflow.ExpiredTime, dto.NextStepName, isOrigin, handlerType);
+                    stepStatus, csPosition, expiredTime, dto.NextStepName, isOrigin, handlerType);
 
                 steps.Add(step);
             }
@@ -2089,7 +2091,7 @@ namespace Hotline.FlowEngine.Workflows
             string? countersignId,
             EWorkflowStepStatus stepStatus,
             ECountersignPosition countersignPosition,
-            DateTime expiredTime,
+            DateTime? expiredTime,
             string stepName,
             bool isOrigin,
             EHandlerType? handlerType = null//动态节点依据动态策略判断