فهرست منبع

merge conflict

xf 10 ماه پیش
والد
کامیت
a732576c32

+ 15 - 12
src/Hotline.Api/Controllers/OrderController.cs

@@ -2260,16 +2260,17 @@ public class OrderController : BaseController
         if (order == null)
             return new();
 
-        string? countersignId = null;
-        var canPrevious = false;
+        var dto = _mapper.Map<OrderDto>(order);
+
         if (!string.IsNullOrEmpty(order.WorkflowId))
         {
             var result = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
-                order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId,
+                order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles,
                 cancellationToken: HttpContext.RequestAborted);
-            order.Workflow = result.workflow;
-            countersignId = result.countersignId;
-            canPrevious = result.canPrevious;
+            //order.Workflow = result.Workflow;
+            dto.CountersignId = result.CountersignId;
+            dto.CanHandle = result.CanHandle;
+            dto.CanPrevious = result.CanPrevious;
 
             await _mediator.Publish(new GetOrderDetailNotify(order.Workflow,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
@@ -2277,9 +2278,9 @@ public class OrderController : BaseController
                 _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName));
         }
 
-        var dto = _mapper.Map<OrderDto>(order!);
-        dto.CountersignId = countersignId;
-        dto.CanHandle = order.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+        //var dto = _mapper.Map<OrderDto>(order!);
+        //dto.CountersignId = countersignId;
+        //dto.CanHandle = order.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
         dto.IsCanDelay = !order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining);
         if (order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining && x.ApplyOrgCode == _sessionContext.RequiredOrgId))
         {
@@ -2315,7 +2316,7 @@ public class OrderController : BaseController
             dto.DelayString = "";
         }
 
-        dto.CanPrevious = canPrevious;
+        //dto.CanPrevious = canPrevious;
 
         if (dto.FileJson != null && dto.FileJson.Any())
         {
@@ -2603,7 +2604,8 @@ public class OrderController : BaseController
             var averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]);
             if (dto.Workflow.BusinessType == EBusinessType.Send && averageSendOrder)
             {
-                dto.Workflow.NextHandlers = await _orderDomainService.AverageOrder(HttpContext.RequestAborted);
+                var handler = await _orderDomainService.AverageOrder(HttpContext.RequestAborted);
+                dto.Workflow.NextHandlers = new List<FlowStepHandler> { handler };
             }
             //是否市州互转
             if (dto.Data.Transpond.HasValue && dto.Data.Transpond.Value)
@@ -2709,7 +2711,8 @@ public class OrderController : BaseController
         // 平均派单
         if (dto.BusinessType == EBusinessType.Send && averageSendOrder)
         {
-            dto.NextHandlers = await _orderDomainService.AverageOrder(HttpContext.RequestAborted);
+            var handler = await _orderDomainService.AverageOrder(HttpContext.RequestAborted);
+            dto.NextHandlers = new List<FlowStepHandler> { handler };
         }
 
         await _workflowApplication.NextAsync(dto, _sessionContext, order.ExpiredTime, HttpContext.RequestAborted);

+ 1 - 1
src/Hotline.Api/StartupExtensions.cs

@@ -34,7 +34,7 @@ internal static class StartupExtensions
         services.AddHttpContextAccessor();
 
 #if DEBUG
-        builder.WebHost.UseUrls("http://*:50100");
+        builder.WebHost.UseUrls("http://*:51100");
 #endif
         
         //services.Configure<DeviceConfigs>(d => configuration.GetSection(nameof(DeviceConfigs)).Bind(d));

+ 3 - 0
src/Hotline.Application.Contracts/Validators/FlowEngine/StartWorkflowDtoValidator.cs

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
 using FluentValidation;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Application.Contracts.Validators;
+using Hotline.Share.Enums.FlowEngine;
 
 namespace Hotline.Application.Contracts.Validators.FlowEngine
 {
@@ -23,6 +24,8 @@ namespace Hotline.Application.Contracts.Validators.FlowEngine
             RuleFor(d => d.NextStepCode).NotEmpty();
             RuleFor(d => d.IsSms).NotNull();
             RuleFor(d => d.IsStartCountersign).NotNull();
+            RuleFor(d => d.NextHandlers.Count).LessThanOrEqualTo(1)
+                .Unless(d => d.IsStartCountersign);
             RuleFor(d => d.Opinion)
                 .Cascade(CascadeMode.Stop)
                 .NotEmpty()

+ 144 - 34
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -151,7 +151,15 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             current.RequiredOrgId, current.OrgName)};
 
         var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
-            new List<Kv> { new(current.RequiredUserId, current.UserName) },
+            new FlowStepHandler
+            {
+                Key = current.RequiredUserId,
+                Value = current.UserName,
+                UserId = current.UserId,
+                Username = current.UserName,
+                OrgId = current.RequiredOrgId,
+                OrgName = current.OrgName
+            },
             startStepHandles, expiredTime);
 
         var flowAssignInfo =
@@ -310,7 +318,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             throw UserFriendlyException.SameMessage("结束节点不支持撤回");
         //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
         var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
-            dto.NextHandlers, cancellationToken);
+            dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
 
         var stepHandlers = await GetNextStepHandlersAsync(workflow, targetStepDefine, dto, cancellationToken);
 
@@ -691,15 +699,22 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             {
                 //根据汇总对象id找到被汇总节点
                 var summaryTargetStep = workflow.Steps.FirstOrDefault(d =>
-                    d.Status == EWorkflowStepStatus.Handled &&
                     d.StepType == EStepType.Normal &&
                     d.Code == stepDefine.SummaryTargetCode &&
                     d.IsOrigin);
                 if (summaryTargetStep is null)
                     throw UserFriendlyException.SameMessage("未查询到汇总对象节点");
 
-                var handlers = summaryTargetStep.Handlers
-                    .Where(d => d.Key == summaryTargetStep.HandlerId || d.Key == summaryTargetStep.HandlerOrgId).ToList();
+                //var handlers = summaryTargetStep.Handlers
+                //    .Where(d => d.Key == summaryTargetStep.HandlerId || d.Key == summaryTargetStep.HandlerOrgId).ToList();
+
+                var handler = new FlowStepHandler
+                {
+                    Key = summaryTargetStep.HandlerId,
+                    Value = summaryTargetStep.HandlerName,
+                    UserId = summaryTargetStep.HandlerId,
+                    Username = summaryTargetStep.HandlerName
+                };
 
                 nextStepOption = new NextStepOption
                 {
@@ -707,8 +722,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     Value = stepDefine.Name,
                     StepType = stepDefine.StepType,
                     BusinessType = stepDefine.BusinessType,
-                    HandlerType = stepDefine.HandlerType,
-                    Items = handlers
+                    //HandlerType = stepDefine.HandlerType,
+                    HandlerType = EHandlerType.AssignedUser,//指定办理人(业务需求)
+                    Items = new List<FlowStepHandler> { handler }//handlers
                 };
             }
             else
@@ -728,10 +744,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         return stepOptions;
     }
 
-    public async Task<NextStepOption> GetConfigStepAsync(EFlowType flowType, StepDefine stepDefine,
-        CancellationToken cancellationToken)
+    public async Task<NextStepOption> GetConfigStepAsync(EFlowType flowType, StepDefine stepDefine, CancellationToken cancellationToken)
     {
-        var handlers = new List<Kv>();
+        var handlers = new List<FlowStepHandler>();
         if (stepDefine.StepType is EStepType.End)
         {
             return new NextStepOption
@@ -751,8 +766,31 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         switch (stepDefine.HandlerType)
         {
             case EHandlerType.AssignedUser:
+                handlers = await _userRepository.Queryable()
+                    .Includes(d => d.Organization)
+                    .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Id))
+                    .Select(d => new FlowStepHandler
+                    {
+                        Key = d.Id,
+                        Value = d.Name,
+                        UserId = d.Id,
+                        Username = d.Name,
+                        OrgId = d.OrgId,
+                        OrgName = d.Organization.Name,
+                    })
+                    .ToListAsync(cancellationToken);
+                break;
             case EHandlerType.AssignedOrg:
-                handlers = stepDefine.HandlerTypeItems;
+                handlers = await _organizeRepository.Queryable() //stepDefine.HandlerTypeItems;
+                    .Where(d => d.IsEnable && stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Id))
+                    .Select(d => new FlowStepHandler
+                    {
+                        Key = d.Id,
+                        Value = d.Name,
+                        OrgId = d.Id,
+                        OrgName = d.Name
+                    })
+                    .ToListAsync(cancellationToken);
                 break;
             case EHandlerType.Role:
                 //当前操作人所属部门的下级部门并且属于配置包含角色
@@ -760,7 +798,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     .Includes(
                         d => d.Accounts.Where(x =>
                             !x.IsDeleted && x.Status == EAccountStatus.Normal && x.AccountType == EAccountType.Personal).ToList(),
-                        x => x.User)
+                        x => x.User, s => s.Organization)
                     .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
                     .ToListAsync(cancellationToken);
                 _logger.LogInformation($"角色: {string.Join(",", roles.Select(d => d.Name))}");
@@ -771,7 +809,17 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     && (stepDefine.StepType != EStepType.Summary && stepDefine.BusinessType != EBusinessType.Center))
                     users1 = users1.Where(d => d.OrgId.StartsWith(levelOneOrgId));
 
-                handlers = users1.Where(d => d != null && !string.IsNullOrEmpty(d.Id)).Select(d => new Kv(d.Id, d.Name)).ToList();
+                handlers = users1.Where(d => d != null && !string.IsNullOrEmpty(d.Id))
+                    .Select(d => new FlowStepHandler
+                    {
+                        Key = d.Id,
+                        Value = d.Name,
+                        UserId = d.Id,
+                        Username = d.Name,
+                        OrgId = d.OrgId,
+                        OrgName = d.Organization.Name
+                    })
+                    .ToList();
                 break;
             case EHandlerType.OrgLevel:
                 //当前操作人所属部门的垂直部门并且属于配置orgLevel的部门
@@ -801,7 +849,14 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                         .ToListAsync(cancellationToken);
                 }
 
-                handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
+                handlers = orgs1.Select(d => new FlowStepHandler
+                {
+                    Key = d.Id,
+                    Value = d.Name,
+                    OrgId = d.Id,
+                    OrgName = d.Name
+                })
+                    .ToList();
                 break;
             case EHandlerType.OrgType:
                 var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
@@ -811,7 +866,14 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     .WhereIF(!isCenter, d => d.Id.StartsWith(levelOneOrgId))
                     .ToListAsync(cancellationToken);
 
-                handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
+                handlers = orgs2.Select(d => new FlowStepHandler
+                {
+                    Key = d.Id,
+                    Value = d.Name,
+                    OrgId = d.Id,
+                    OrgName = d.Name
+                })
+                    .ToList();
                 break;
             default:
                 throw new ArgumentOutOfRangeException();
@@ -839,6 +901,15 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var handlers = prevStep.Handlers
             .Where(d => d.Key == prevStep.HandlerId || d.Key == prevStep.HandlerOrgId).ToList();
         //var handler = prevStep.GetActualHandler()?.GetHandler();
+        var handler = new FlowStepHandler
+        {
+            Key = prevStep.HandlerId,
+            Value = prevStep.HandlerName,
+            UserId = prevStep.HandlerId,
+            Username = prevStep.HandlerName,
+            OrgId = prevStep.HandlerOrgId,
+            OrgName = prevStep.HandlerOrgName
+        };
 
         return new NextStepOption
         {
@@ -847,8 +918,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             BackToCountersignEnd = true,
             StepType = EStepType.Summary,
             BusinessType = prevStep.BusinessType,
-            HandlerType = prevStep.HandlerType,
-            Items = handlers //new List<Kv> { new(prevStep.HandlerId, prevStep.HandlerName) },
+            //HandlerType = prevStep.HandlerType,
+            HandlerType = EHandlerType.AssignedUser,//指定办理人(业务需求)
+            Items = new List<FlowStepHandler> { handler }//handlers //new List<Kv> { new(prevStep.HandlerId, prevStep.HandlerName) },
         };
     }
 
@@ -892,7 +964,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         EBusinessType currentBusinessType, CancellationToken cancellationToken)
     {
         int orgLevel;
-        List<Kv> items;
+        List<FlowStepHandler> items;
         string upperOrgId;
         EBusinessType businessType;
         EFlowDirection? flowDirection = null;
@@ -910,7 +982,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
                     items = await _organizeRepository.Queryable()
                         .Where(d => d.IsCenter)
-                        .Select(d => new Kv { Key = d.Id, Value = d.Name })
+                        .Select(d => new FlowStepHandler
+                        {
+                            Key = d.Id,
+                            Value = d.Name,
+                            OrgId = d.Id,
+                            OrgName = d.Name
+                        })
                         .ToListAsync(cancellationToken);
                 }
                 else
@@ -921,7 +999,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     upperOrgId = _sessionContext.RequiredOrgId.GetHigherOrgId(orgLevel);
                     items = await _organizeRepository.Queryable()
                         .Where(d => d.Id == upperOrgId)
-                        .Select(d => new Kv { Key = d.Id, Value = d.Name })
+                        .Select(d => new FlowStepHandler
+                        {
+                            Key = d.Id,
+                            Value = d.Name,
+                            OrgId = d.Id,
+                            OrgName = d.Name
+                        })
                         .ToListAsync(cancellationToken);
                 }
 
@@ -938,7 +1022,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                 upperOrgId = _sessionContext.RequiredOrgId.GetHigherOrgId(orgLevel);
                 items = await _organizeRepository.Queryable()
                     .Where(d => d.Id == upperOrgId)
-                    .Select(d => new Kv { Key = d.Id, Value = d.Name })
+                    .Select(d => new FlowStepHandler
+                    {
+                        Key = d.Id,
+                        Value = d.Name,
+                        OrgId = d.Id,
+                        OrgName = d.Name
+                    })
                     .ToListAsync(cancellationToken);
                 break;
             case EDynamicPolicy.OrgDownCenterTop:
@@ -948,7 +1038,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     orgLevel = 1;
                     items = await _organizeRepository.Queryable()
                         .Where(d => !d.IsCenter && d.Level == orgLevel)
-                        .Select(d => new Kv { Key = d.Id, Value = d.Name })
+                        .Select(d => new FlowStepHandler
+                        {
+                            Key = d.Id,
+                            Value = d.Name,
+                            OrgId = d.Id,
+                            OrgName = d.Name
+                        })
                         .ToListAsync(cancellationToken);
                 }
                 else
@@ -957,7 +1053,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     items = await _organizeRepository.Queryable()
                         .Where(d => !d.IsCenter && d.Level == orgLevel &&
                                     d.Id.StartsWith(_sessionContext.RequiredOrgId))
-                        .Select(d => new Kv { Key = d.Id, Value = d.Name })
+                        .Select(d => new FlowStepHandler
+                        {
+                            Key = d.Id,
+                            Value = d.Name,
+                            OrgId = d.Id,
+                            OrgName = d.Name
+                        })
                         .ToListAsync(cancellationToken);
                 }
 
@@ -967,7 +1069,13 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                 orgLevel = _sessionContext.OrgLevel + 1;
                 items = await _organizeRepository.Queryable()
                     .Where(d => d.Level == orgLevel && d.Id.StartsWith(_sessionContext.RequiredOrgId))
-                    .Select(d => new Kv { Key = d.Id, Value = d.Name })
+                    .Select(d => new FlowStepHandler
+                    {
+                        Key = d.Id,
+                        Value = d.Name,
+                        OrgId = d.Id,
+                        OrgName = d.Name
+                    })
                     .ToListAsync(cancellationToken);
                 break;
             default:
@@ -995,7 +1103,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (nextStepDefine.StepType is EStepType.End) return new();
 
         var isStartCountersign = dto.IsStartCountersign;
-        var handlers = dto.NextHandlers;
+        var handlers = dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList();
 
         if (isStartCountersign)
         {
@@ -1103,13 +1211,15 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             case EHandlerType.Role:
                 if (!handlers.Any())
                 {
-                    var roles = await _roleRepository.Queryable()
-                        .Includes(d => d.Accounts, x => x.User)
-                        .Where(d => nextStepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
-                        .ToListAsync(cancellationToken);
-                    handlers = roles.SelectMany(d => d.Accounts).Distinct()
-                        .Select(d => new Kv(d.Id, d.User.Name))
-                        .ToList();
+                    //var roles = await _roleRepository.Queryable()
+                    //    .Includes(d => d.Accounts, x => x.User)
+                    //    .Where(d => nextStepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
+                    //    .ToListAsync(cancellationToken);
+                    //handlers = roles.SelectMany(d => d.Accounts).Distinct()
+                    //    .Select(d => new Kv(d.Id, d.User.Name))
+                    //    .ToList();
+                    handlers = nextStepDefine.HandlerTypeItems;
+                    return FlowAssignInfo.Create(EFlowAssignType.Role, handlers, isStartCountersign);
                 }
 
                 return FlowAssignInfo.Create(EFlowAssignType.User, handlers, isStartCountersign);
@@ -1195,9 +1305,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true, withTraces: true,
             cancellationToken: cancellationToken);
-        var step = workflow.Steps.FirstOrDefault(d => 
+        var step = workflow.Steps.FirstOrDefault(d =>
             d.StepHandlers.Any(d => d.OrgId == "001171" || d.OrgId == "001178"));
-        if(step is not null)
+        if (step is not null)
         {
             step.FileJson = await _fileRepository.AddFileAsync(files, workflow.ExternalId, step.Id, cancellationToken);
             var trace = workflow.Traces.First(d => d.StepId == step.Id);

+ 385 - 381
src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs

@@ -26,406 +26,410 @@ using Hotline.Share.Enums.FlowEngine;
 
 namespace Hotline.Application.Orders
 {
-	public class OrderSecondaryHandlingApplication : IOrderSecondaryHandlingApplication, IScopeDependency
-	{
-		private readonly IMapper _mapper;
-		private readonly IRepository<OrderSecondaryHandling> _orderSecondaryHandlingRepository;
-		private readonly IFileRepository _fileRepository;
-		private readonly IRepository<OrderVisit> _orderVisitRepository;
-		private readonly ISessionContext _sessionContext;
-		private readonly IOrderRepository _orderRepository;
-		private readonly ITimeLimitDomainService _timeLimitDomainService;
-		private readonly ICapPublisher _capPublisher;
-		private readonly IWorkflowApplication _workflowApplication;
-		private readonly IRepository<OrderPublish> _orderPublishRepository;
-		private readonly IRepository<OrderPublishHistory> _orderPublishHistoryRepository;
-		private readonly IWorkflowDomainService _workflowDomainService;
-		private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
+    public class OrderSecondaryHandlingApplication : IOrderSecondaryHandlingApplication, IScopeDependency
+    {
+        private readonly IMapper _mapper;
+        private readonly IRepository<OrderSecondaryHandling> _orderSecondaryHandlingRepository;
+        private readonly IFileRepository _fileRepository;
+        private readonly IRepository<OrderVisit> _orderVisitRepository;
+        private readonly ISessionContext _sessionContext;
+        private readonly IOrderRepository _orderRepository;
+        private readonly ITimeLimitDomainService _timeLimitDomainService;
+        private readonly ICapPublisher _capPublisher;
+        private readonly IWorkflowApplication _workflowApplication;
+        private readonly IRepository<OrderPublish> _orderPublishRepository;
+        private readonly IRepository<OrderPublishHistory> _orderPublishHistoryRepository;
+        private readonly IWorkflowDomainService _workflowDomainService;
+        private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
 
-		public OrderSecondaryHandlingApplication(
-			IMapper mapper,
-			IRepository<OrderSecondaryHandling> orderSecondaryHandlingRepository,
-			IFileRepository fileRepository,
-			IRepository<OrderVisit> orderVisitRepository,
-			ISessionContext sessionContext,
-			IOrderRepository orderRepository,
-			ITimeLimitDomainService timeLimitDomainService,
-			ICapPublisher capPublisher,
-			IWorkflowApplication workflowApplication,
-			IRepository<OrderPublish> orderPublishRepository,
-			IRepository<OrderPublishHistory> orderPublishHistoryRepository,
-			IWorkflowDomainService workflowDomainService,
-			IRepository<OrderVisitDetail> orderVisitedDetailRepository
-			) {
-			_mapper = mapper;
-			_orderSecondaryHandlingRepository = orderSecondaryHandlingRepository;
-			_fileRepository = fileRepository;
-			_orderVisitRepository = orderVisitRepository;
-			_sessionContext = sessionContext;
-			_orderRepository = orderRepository;
-			_timeLimitDomainService = timeLimitDomainService;
-			_capPublisher = capPublisher;
-			_workflowApplication = workflowApplication;
-			_orderPublishRepository = orderPublishRepository;
-			_orderPublishHistoryRepository = orderPublishHistoryRepository;
-			_workflowDomainService = workflowDomainService;
-			_orderVisitedDetailRepository = orderVisitedDetailRepository;
-		}
+        public OrderSecondaryHandlingApplication(
+            IMapper mapper,
+            IRepository<OrderSecondaryHandling> orderSecondaryHandlingRepository,
+            IFileRepository fileRepository,
+            IRepository<OrderVisit> orderVisitRepository,
+            ISessionContext sessionContext,
+            IOrderRepository orderRepository,
+            ITimeLimitDomainService timeLimitDomainService,
+            ICapPublisher capPublisher,
+            IWorkflowApplication workflowApplication,
+            IRepository<OrderPublish> orderPublishRepository,
+            IRepository<OrderPublishHistory> orderPublishHistoryRepository,
+            IWorkflowDomainService workflowDomainService,
+            IRepository<OrderVisitDetail> orderVisitedDetailRepository
+            )
+        {
+            _mapper = mapper;
+            _orderSecondaryHandlingRepository = orderSecondaryHandlingRepository;
+            _fileRepository = fileRepository;
+            _orderVisitRepository = orderVisitRepository;
+            _sessionContext = sessionContext;
+            _orderRepository = orderRepository;
+            _timeLimitDomainService = timeLimitDomainService;
+            _capPublisher = capPublisher;
+            _workflowApplication = workflowApplication;
+            _orderPublishRepository = orderPublishRepository;
+            _orderPublishHistoryRepository = orderPublishHistoryRepository;
+            _workflowDomainService = workflowDomainService;
+            _orderVisitedDetailRepository = orderVisitedDetailRepository;
+        }
 
-		/// <summary>
-		///  二次办理新增
-		/// </summary>
-		/// <returns></returns>
-		public async Task AddAsync(AddOrderSecondaryHandlingDto dto, CancellationToken cancellationToken)
-		{
-			var model = _mapper.Map<OrderSecondaryHandling>(dto);
-			if (string.IsNullOrEmpty(dto.Id))
-			{
-				model.InitId();
-			}
-			else {
-				model = await _orderSecondaryHandlingRepository.GetAsync(dto.Id , cancellationToken);
-				model.Content = dto.Content;
-			}
-			model.State = ESecondaryHandlingState.Apply;
-			model.ApplyOrgId = _sessionContext.OrgId;
-			model.ApplyOrgName = _sessionContext.OrgName;
-		
-			if (dto.Files.Any())
-				model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", cancellationToken);
+        /// <summary>
+        ///  二次办理新增
+        /// </summary>
+        /// <returns></returns>
+        public async Task AddAsync(AddOrderSecondaryHandlingDto dto, CancellationToken cancellationToken)
+        {
+            var model = _mapper.Map<OrderSecondaryHandling>(dto);
+            if (string.IsNullOrEmpty(dto.Id))
+            {
+                model.InitId();
+            }
+            else
+            {
+                model = await _orderSecondaryHandlingRepository.GetAsync(dto.Id, cancellationToken);
+                model.Content = dto.Content;
+            }
+            model.State = ESecondaryHandlingState.Apply;
+            model.ApplyOrgId = _sessionContext.OrgId;
+            model.ApplyOrgName = _sessionContext.OrgName;
 
-			var visit = await _orderVisitRepository.GetAsync(x => x.Id  == dto.VisitId && x.VisitState != EVisitState.None, cancellationToken);
-			if (visit != null)
-			{
-				model.VisitState = visit.VisitState;
-				visit.VisitState = EVisitState.None;
-				await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
-			}
+            if (dto.Files.Any())
+                model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", cancellationToken);
 
-			if (!string.IsNullOrEmpty(dto.Id))
-			{
-				await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
-			}
-			else {
-				await _orderSecondaryHandlingRepository.AddAsync(model, cancellationToken);
-			}
-		}
+            var visit = await _orderVisitRepository.GetAsync(x => x.Id == dto.VisitId && x.VisitState != EVisitState.None, cancellationToken);
+            if (visit != null)
+            {
+                model.VisitState = visit.VisitState;
+                visit.VisitState = EVisitState.None;
+                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+            }
 
-		public async Task SendBackAsync(SendBackOrderSecondaryHandlingDto dto, CancellationToken cancellationToken) 
-		{
-			var model =await _orderSecondaryHandlingRepository.GetAsync(dto.Id, cancellationToken);
-			model.State = ESecondaryHandlingState.NotApply;
-			model.SendBackContent = dto.SendBackContent;
-			model.AuditUser = _sessionContext.UserName;
-			model.AuditTime = DateTime.Now;
-			model.SendBackNum = model.SendBackNum is null ? 1 : model.SendBackNum + 1;
-			await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
-			var visit = await _orderVisitRepository.GetAsync(x => x.Id == model.VisitId , cancellationToken);
-			if (visit != null)
-			{
-				visit.VisitState = model.VisitState;
-				await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
-			}
-		}
+            if (!string.IsNullOrEmpty(dto.Id))
+            {
+                await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
+            }
+            else
+            {
+                await _orderSecondaryHandlingRepository.AddAsync(model, cancellationToken);
+            }
+        }
 
+        public async Task SendBackAsync(SendBackOrderSecondaryHandlingDto dto, CancellationToken cancellationToken)
+        {
+            var model = await _orderSecondaryHandlingRepository.GetAsync(dto.Id, cancellationToken);
+            model.State = ESecondaryHandlingState.NotApply;
+            model.SendBackContent = dto.SendBackContent;
+            model.AuditUser = _sessionContext.UserName;
+            model.AuditTime = DateTime.Now;
+            model.SendBackNum = model.SendBackNum is null ? 1 : model.SendBackNum + 1;
+            await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
+            var visit = await _orderVisitRepository.GetAsync(x => x.Id == model.VisitId, cancellationToken);
+            if (visit != null)
+            {
+                visit.VisitState = model.VisitState;
+                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+            }
+        }
 
-		/// <summary>
-		/// 二次办理审批
-		/// </summary>
-		/// <returns></returns>
-		public async Task AuditAsync(AuditOrderSecondaryHandlingDto dto, OrderSecondaryHandling model, CancellationToken cancellationToken)
-		{
-			model.State = dto.State;
-			model.AuditContent = dto.AuditContent;
-			model.AuditId = _sessionContext.UserId;
-			model.AuditUser = _sessionContext.UserName;
-			model.AuditTime = DateTime.Now;
-			if (model.State == ESecondaryHandlingState.End)
-			{
-				var order = await _orderRepository.GetAsync(x => x.Id == model.OrderId, cancellationToken);
-				if (string.IsNullOrEmpty(order.WorkflowId))
-					throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程信息!");
-				var step = await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, model.ApplyOrgId, cancellationToken);
-				if (step == null)
-					throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程节点!");
-				var recall = new RecallDto
-				{
-					WorkflowId = order.WorkflowId!,
-					NextStepCode = step.Code,
-					NextStepName = step.Name,
-					NextHandlers = step.Handlers,
-					Opinion = dto.AuditContent,
-					FlowDirection = Share.Enums.FlowEngine.EFlowDirection.CenterToOrg,
-					HandlerType = step.HandlerType,
-					BusinessType = step.BusinessType
-				};
-				var reTransactNum = order.ReTransactNum is null ? 1 : order.ReTransactNum + 1;
-				var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
-				var processType = step.FlowDirection == EFlowDirection.OrgToCenter || step.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban;
-				await _orderRepository.Updateable().SetColumns(o => new Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, ReTransactNum = reTransactNum, ProcessType = processType })
-					.Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
-				var orderDto = _mapper.Map<OrderDto>(order);
-				await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: cancellationToken);
 
-				await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, cancellationToken);
-				var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == model.OrderId);
-				if (publish != null)
-				{
-					var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-					publishHistory.OrderPublishId = publish.Id;
-					publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-					publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-					publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-					publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-					publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-					publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-					await _orderPublishHistoryRepository.AddAsync(publishHistory, cancellationToken);
-					await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
-				}
-			}
-			else {
-				var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == model.OrderId, cancellationToken);
-				visit.VisitState = model.VisitState;
-				await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
-			}
-			await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
-		}
+        /// <summary>
+        /// 二次办理审批
+        /// </summary>
+        /// <returns></returns>
+        public async Task AuditAsync(AuditOrderSecondaryHandlingDto dto, OrderSecondaryHandling model, CancellationToken cancellationToken)
+        {
+            model.State = dto.State;
+            model.AuditContent = dto.AuditContent;
+            model.AuditId = _sessionContext.UserId;
+            model.AuditUser = _sessionContext.UserName;
+            model.AuditTime = DateTime.Now;
+            if (model.State == ESecondaryHandlingState.End)
+            {
+                var order = await _orderRepository.GetAsync(x => x.Id == model.OrderId, cancellationToken);
+                if (string.IsNullOrEmpty(order.WorkflowId))
+                    throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程信息!");
+                var step = await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, model.ApplyOrgId, cancellationToken);
+                if (step == null)
+                    throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程节点!");
+                var recall = new RecallDto
+                {
+                    WorkflowId = order.WorkflowId!,
+                    NextStepCode = step.Code,
+                    NextStepName = step.Name,
+                    NextHandlers = new List<FlowStepHandler> { step.GetWorkflowStepHandler() },
+                    Opinion = dto.AuditContent,
+                    FlowDirection = Share.Enums.FlowEngine.EFlowDirection.CenterToOrg,
+                    HandlerType = step.HandlerType,
+                    BusinessType = step.BusinessType
+                };
+                var reTransactNum = order.ReTransactNum is null ? 1 : order.ReTransactNum + 1;
+                var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
+                var processType = step.FlowDirection == EFlowDirection.OrgToCenter || step.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban;
+                await _orderRepository.Updateable().SetColumns(o => new Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, ReTransactNum = reTransactNum, ProcessType = processType })
+                    .Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
+                var orderDto = _mapper.Map<OrderDto>(order);
+                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: cancellationToken);
 
+                await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, cancellationToken);
+                var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == model.OrderId);
+                if (publish != null)
+                {
+                    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+                    publishHistory.OrderPublishId = publish.Id;
+                    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+                    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+                    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+                    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+                    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+                    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+                    await _orderPublishHistoryRepository.AddAsync(publishHistory, cancellationToken);
+                    await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
+                }
+            }
+            else
+            {
+                var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == model.OrderId, cancellationToken);
+                visit.VisitState = model.VisitState;
+                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+            }
+            await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
+        }
 
-		/// <summary>
-		/// 获取申请列表
-		/// </summary>
-		/// <returns></returns>
-		public ISugarQueryable<OrderVisitDetail> ApplyQuery(MayScreenListDto dto, CancellationToken cancellationToken)
-		{
-			dto.CreationTimeEnd = DateTime.Now;
-			//dto.CreationTimeStart = DateTime.Now;
-			dto.CreationTimeStart = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
 
-			var query = _orderVisitedDetailRepository.Queryable(false, true)
-				.Includes(x => x.OrderVisit)
-				.Includes(x => x.OrderVisit, y => y.Order)
-				.Includes(x => x.OrderVisit, y => y.Employee)
-				.Includes(x => x.SecondaryHandling)
-				.LeftJoin<OrderScreen>((x, s) => x.Id == s.VisitDetailId && s.Status < EScreenStatus.End && s.IsDeleted == false)
-				.Where((x, s) => s.Id == null && (x.SecondaryHandling.State == ESecondaryHandlingState.NotApply || x.SecondaryHandling.Id == null))
-				.Where(x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart)
-				.WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order!.No!.Contains(dto.No!))
-				.WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince)
-				.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order!.Title!.Contains(dto.Title!))
-				.WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.OrderVisit.Order!.SourceChannelCode! == dto.SourceChannel!)
-				.WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.OrderVisit.Order!.AcceptTypeCode! == dto.AcceptType!)
-				.WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.OrderVisit.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!))
-				.WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order!.ActualHandleOrgName!.Contains(dto.ActualHandleOrgName!))
-				.WhereIF(dto.ActualHandleTime.HasValue && dto.EndActualHandleTime.HasValue, x => x.OrderVisit.Order!.ActualHandleTime >= dto.ActualHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndActualHandleTime)
-				.WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue, x => x.OrderVisit.Order!.FiledTime == dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime)
-				.WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue, x => x.OrderVisit.Order!.CreationTime == dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime)
-				.WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue, x => x.OrderVisit.VisitTime == dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime)
-				.WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitOrgName!.Contains(dto.VisitOrgName!))
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude), x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude))
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason), x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
-				.Where((x, s) => x.OrderVisit.VisitState != EVisitState.None && x.OrderVisit.IsCanHandle)
-				.Where((x, s) => x.OrderVisit.Order.CounterSignType == null && x.OrderVisit.Order.ActualHandleOrgCode == _sessionContext.OrgId)
-				;
-			if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
-			{
-				query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-						(x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
-								  x.OrderVisit.Order.No.Contains(dto.Keyword!))
-					.Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.StartsWith(_sessionContext.OrgId) && (
-						SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
-						SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
-						|| SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
-						SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
-					));
-			}
-			else
-			{
-				query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-						(x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
-								  x.OrderVisit.Order.No.Contains(dto.Keyword!))
-					.Where((x, s) => x.VisitTarget == EVisitTarget.Org && (
-						SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
-						SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
-						|| SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
-						SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
-					));
-			}
+        /// <summary>
+        /// 获取申请列表
+        /// </summary>
+        /// <returns></returns>
+        public ISugarQueryable<OrderVisitDetail> ApplyQuery(MayScreenListDto dto, CancellationToken cancellationToken)
+        {
+            dto.CreationTimeEnd = DateTime.Now;
+            //dto.CreationTimeStart = DateTime.Now;
+            dto.CreationTimeStart = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
 
-			return query.OrderByDescending((x, s) => x.CreationTime);
-		}
+            var query = _orderVisitedDetailRepository.Queryable(false, true)
+                .Includes(x => x.OrderVisit)
+                .Includes(x => x.OrderVisit, y => y.Order)
+                .Includes(x => x.OrderVisit, y => y.Employee)
+                .Includes(x => x.SecondaryHandling)
+                .LeftJoin<OrderScreen>((x, s) => x.Id == s.VisitDetailId && s.Status < EScreenStatus.End && s.IsDeleted == false)
+                .Where((x, s) => s.Id == null && (x.SecondaryHandling.State == ESecondaryHandlingState.NotApply || x.SecondaryHandling.Id == null))
+                .Where(x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart)
+                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order!.No!.Contains(dto.No!))
+                .WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince)
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order!.Title!.Contains(dto.Title!))
+                .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.OrderVisit.Order!.SourceChannelCode! == dto.SourceChannel!)
+                .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.OrderVisit.Order!.AcceptTypeCode! == dto.AcceptType!)
+                .WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.OrderVisit.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!))
+                .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order!.ActualHandleOrgName!.Contains(dto.ActualHandleOrgName!))
+                .WhereIF(dto.ActualHandleTime.HasValue && dto.EndActualHandleTime.HasValue, x => x.OrderVisit.Order!.ActualHandleTime >= dto.ActualHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndActualHandleTime)
+                .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue, x => x.OrderVisit.Order!.FiledTime == dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime)
+                .WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue, x => x.OrderVisit.Order!.CreationTime == dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime)
+                .WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue, x => x.OrderVisit.VisitTime == dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime)
+                .WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitOrgName!.Contains(dto.VisitOrgName!))
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude), x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude))
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason), x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
+                .Where((x, s) => x.OrderVisit.VisitState != EVisitState.None && x.OrderVisit.IsCanHandle)
+                .Where((x, s) => x.OrderVisit.Order.CounterSignType == null && x.OrderVisit.Order.ActualHandleOrgCode == _sessionContext.OrgId)
+                ;
+            if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
+            {
+                query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
+                        (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
+                                  x.OrderVisit.Order.No.Contains(dto.Keyword!))
+                    .Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.StartsWith(_sessionContext.OrgId) && (
+                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
+                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
+                        || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
+                        SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
+                    ));
+            }
+            else
+            {
+                query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
+                        (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
+                                  x.OrderVisit.Order.No.Contains(dto.Keyword!))
+                    .Where((x, s) => x.VisitTarget == EVisitTarget.Org && (
+                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
+                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
+                        || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
+                        SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
+                    ));
+            }
 
-		/// <summary>
-		/// 二次办理列表查询
-		/// </summary>
-		/// <returns></returns>
-		public ISugarQueryable<OrderSecondaryHandling> Query(SecondaryHandlingListDto dto, CancellationToken cancellationToken)
-		{
-			if (dto.CreationTimeEnd.HasValue)
-				dto.CreationTimeEnd = dto.CreationTimeEnd.Value.AddDays(1).AddSeconds(-1);
-			return _orderSecondaryHandlingRepository.Queryable()
-				.Includes(x => x.Order)
-				.Includes(x => x.VisitDetail)
-				.Includes(x => x.Visit, d => d.Order)
-				.Where(x=>x.State> ESecondaryHandlingState.NotApply)
-				.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-					x => x.Visit.Order.Title.Contains(dto.Keyword!) || x.Visit.Order.No.Contains(dto.Keyword!))
-				.WhereIF(dto.Status is ESecondaryHandlingState.Apply, x => x.State == ESecondaryHandlingState.Apply)
-				.WhereIF(dto.Status is ESecondaryHandlingState.Handled, x => x.State != ESecondaryHandlingState.Apply)
-				.WhereIF(dto.Status is ESecondaryHandlingState.End, x => x.State == ESecondaryHandlingState.End)
-				.WhereIF(dto.Status is ESecondaryHandlingState.Refuse, x => x.State == ESecondaryHandlingState.Refuse)
-				.WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
-				.WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrderId), x => x.OrderId == dto.OrderId)
-				.OrderByDescending(x => x.CreationTime);
-		}
+            return query.OrderByDescending((x, s) => x.CreationTime);
+        }
 
-		/// <summary>
-		/// 获取实体
-		/// </summary>
-		/// <returns></returns>
-		public async Task<OrderSecondaryHandling> Entity(string id, CancellationToken cancellationToken)
-		{
-			return await _orderSecondaryHandlingRepository.Queryable()
-				.FirstAsync(x => x.Id == id, cancellationToken);
-		}
+        /// <summary>
+        /// 二次办理列表查询
+        /// </summary>
+        /// <returns></returns>
+        public ISugarQueryable<OrderSecondaryHandling> Query(SecondaryHandlingListDto dto, CancellationToken cancellationToken)
+        {
+            if (dto.CreationTimeEnd.HasValue)
+                dto.CreationTimeEnd = dto.CreationTimeEnd.Value.AddDays(1).AddSeconds(-1);
+            return _orderSecondaryHandlingRepository.Queryable()
+                .Includes(x => x.Order)
+                .Includes(x => x.VisitDetail)
+                .Includes(x => x.Visit, d => d.Order)
+                .Where(x => x.State > ESecondaryHandlingState.NotApply)
+                .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
+                    x => x.Visit.Order.Title.Contains(dto.Keyword!) || x.Visit.Order.No.Contains(dto.Keyword!))
+                .WhereIF(dto.Status is ESecondaryHandlingState.Apply, x => x.State == ESecondaryHandlingState.Apply)
+                .WhereIF(dto.Status is ESecondaryHandlingState.Handled, x => x.State != ESecondaryHandlingState.Apply)
+                .WhereIF(dto.Status is ESecondaryHandlingState.End, x => x.State == ESecondaryHandlingState.End)
+                .WhereIF(dto.Status is ESecondaryHandlingState.Refuse, x => x.State == ESecondaryHandlingState.Refuse)
+                .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
+                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrderId), x => x.OrderId == dto.OrderId)
+                .OrderByDescending(x => x.CreationTime);
+        }
 
-		/// <summary>
-		/// 二次办理统计
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		public  ISugarQueryable<SecondaryHandlingVo> SecondaryHandlingReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
-		{
-			if (dto.EndTime.HasValue)
-				dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			return _orderSecondaryHandlingRepository.Queryable()
-				.WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
-				.WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
-				.Where(x => x.State == ESecondaryHandlingState.End)
-				.GroupBy(x => new { x.ApplyOrgId, x.ApplyOrgName })
-				.Select(x => new SecondaryHandlingVo
-				{
-					OrgId = x.ApplyOrgId,
-					OrgName = x.ApplyOrgName,
-					Num = SqlFunc.AggregateCount(x.Id)
-				})
-				.OrderByIF(dto.SortRule == 0, x => x.Num, OrderByType.Asc)
-				.OrderByIF(dto.SortRule == 1, x => x.Num, OrderByType.Desc);
-		}
+        /// <summary>
+        /// 获取实体
+        /// </summary>
+        /// <returns></returns>
+        public async Task<OrderSecondaryHandling> Entity(string id, CancellationToken cancellationToken)
+        {
+            return await _orderSecondaryHandlingRepository.Queryable()
+                .FirstAsync(x => x.Id == id, cancellationToken);
+        }
 
-		/// <summary>
-		/// 二次办理统计明细
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
-		{
-			if (dto.EndTime.HasValue)
-				dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			return _orderSecondaryHandlingRepository.Queryable()
-				.Includes(x=>x.Order)
-				.Includes(x=>x.Visit)
-				.Includes(x=>x.VisitDetail)
-				.WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
-				.WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
-				.Where(x=>x.ApplyOrgId == dto.OrgId)
-				.Where(x => x.State == ESecondaryHandlingState.End);
-		}
+        /// <summary>
+        /// 二次办理统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<SecondaryHandlingVo> SecondaryHandlingReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
+        {
+            if (dto.EndTime.HasValue)
+                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            return _orderSecondaryHandlingRepository.Queryable()
+                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
+                .Where(x => x.State == ESecondaryHandlingState.End)
+                .GroupBy(x => new { x.ApplyOrgId, x.ApplyOrgName })
+                .Select(x => new SecondaryHandlingVo
+                {
+                    OrgId = x.ApplyOrgId,
+                    OrgName = x.ApplyOrgName,
+                    Num = SqlFunc.AggregateCount(x.Id)
+                })
+                .OrderByIF(dto.SortRule == 0, x => x.Num, OrderByType.Asc)
+                .OrderByIF(dto.SortRule == 1, x => x.Num, OrderByType.Desc);
+        }
 
+        /// <summary>
+        /// 二次办理统计明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
+        {
+            if (dto.EndTime.HasValue)
+                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            return _orderSecondaryHandlingRepository.Queryable()
+                .Includes(x => x.Order)
+                .Includes(x => x.Visit)
+                .Includes(x => x.VisitDetail)
+                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
+                .Where(x => x.ApplyOrgId == dto.OrgId)
+                .Where(x => x.State == ESecondaryHandlingState.End);
+        }
 
-		/// <summary>
-		/// 二次办理满意度统计
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		public ISugarQueryable<SecondaryHandlingSatisfactionVo> SecondaryHandlingSatisfactionReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken) 
-		{
-			if (dto.EndTime.HasValue)
-				dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			return _orderSecondaryHandlingRepository.Queryable()
-				.Includes(x => x.Order)
-				.Includes(x => x.Visit)
-				.Includes(x => x.VisitDetail)
-				.Includes(x => x.Order, o => o.CallRecord)
-				.LeftJoin<SystemOrganize>((x, o) => x.ApplyOrgId == o.Id)
-				.WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
-				.WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
-				.WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
-				.GroupBy((x,o) => new { x.ApplyOrgId, x.ApplyOrgName,o.OrgType })
-				.Select((x, o) => new SecondaryHandlingSatisfactionVo()
-				{
-					OrgId = x.ApplyOrgId,
-					OrgName = x.ApplyOrgName,
-					OrgType = o.OrgType,
-					TotalSumCount = SqlFunc.AggregateCount(x.Id),
-					VerySatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
-					SatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
-					RegardedAsSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
-					DefaultSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
-					NoSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
-					NoEvaluateCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
-					NoPutThroughCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
-				});
-		}
 
-		/// <summary>
-		///  二次办理满意度统计明细
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingSatisfactionDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
-		{
-			var key = string.Empty;
-			if (dto.EndTime.HasValue)
-				dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			if (!string.IsNullOrEmpty(dto.Header))
-			{
-				switch (dto.Header)
-				{
-					case "verySatisfiedCount":
-						key = "5";
-						break;
-					case "satisfiedCount":
-						key = "4";
-						break;
-					case "regardedAsSatisfiedCount":
-						key = "-1";
-						break;
-					case "defaultSatisfiedCount":
-						key = "0";
-						break;
-					case "noSatisfiedCount":
-						key = "2";
-						break;
-					case "noEvaluateCount":
-						key = "7";
-						break;
-					case "noPutThroughCount":
-						key = "6";
-						break;
-				}
-			}
+        /// <summary>
+        /// 二次办理满意度统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<SecondaryHandlingSatisfactionVo> SecondaryHandlingSatisfactionReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
+        {
+            if (dto.EndTime.HasValue)
+                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            return _orderSecondaryHandlingRepository.Queryable()
+                .Includes(x => x.Order)
+                .Includes(x => x.Visit)
+                .Includes(x => x.VisitDetail)
+                .Includes(x => x.Order, o => o.CallRecord)
+                .LeftJoin<SystemOrganize>((x, o) => x.ApplyOrgId == o.Id)
+                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
+                .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
+                .GroupBy((x, o) => new { x.ApplyOrgId, x.ApplyOrgName, o.OrgType })
+                .Select((x, o) => new SecondaryHandlingSatisfactionVo()
+                {
+                    OrgId = x.ApplyOrgId,
+                    OrgName = x.ApplyOrgName,
+                    OrgType = o.OrgType,
+                    TotalSumCount = SqlFunc.AggregateCount(x.Id),
+                    VerySatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
+                    SatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
+                    RegardedAsSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
+                    DefaultSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
+                    NoSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
+                    NoEvaluateCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
+                    NoPutThroughCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
+                });
+        }
 
-			return _orderSecondaryHandlingRepository.Queryable()
-				.Includes(x => x.Order)
-				.Includes(x => x.Visit)
-				.Includes(x => x.VisitDetail)
-				.Includes(x => x.Order, o => o.CallRecord)
-				.WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
-				.WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
-				.WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
-				.WhereIF(dto.TypeId is 1 && !string.IsNullOrEmpty(key), x=> SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == key)
-				.WhereIF(dto.TypeId is 2 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == key)
-				.Where(x => x.ApplyOrgId == dto.OrgId)
-				.Where(x => x.State == ESecondaryHandlingState.End);
-		}
+        /// <summary>
+        ///  二次办理满意度统计明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingSatisfactionDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
+        {
+            var key = string.Empty;
+            if (dto.EndTime.HasValue)
+                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            if (!string.IsNullOrEmpty(dto.Header))
+            {
+                switch (dto.Header)
+                {
+                    case "verySatisfiedCount":
+                        key = "5";
+                        break;
+                    case "satisfiedCount":
+                        key = "4";
+                        break;
+                    case "regardedAsSatisfiedCount":
+                        key = "-1";
+                        break;
+                    case "defaultSatisfiedCount":
+                        key = "0";
+                        break;
+                    case "noSatisfiedCount":
+                        key = "2";
+                        break;
+                    case "noEvaluateCount":
+                        key = "7";
+                        break;
+                    case "noPutThroughCount":
+                        key = "6";
+                        break;
+                }
+            }
 
-	}
+            return _orderSecondaryHandlingRepository.Queryable()
+                .Includes(x => x.Order)
+                .Includes(x => x.Visit)
+                .Includes(x => x.VisitDetail)
+                .Includes(x => x.Order, o => o.CallRecord)
+                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
+                .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
+                .WhereIF(dto.TypeId is 1 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == key)
+                .WhereIF(dto.TypeId is 2 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == key)
+                .Where(x => x.ApplyOrgId == dto.OrgId)
+                .Where(x => x.State == ESecondaryHandlingState.End);
+        }
+
+    }
 }

+ 6 - 1
src/Hotline.Share/Dtos/FlowEngine/BasicWorkflowDto.cs

@@ -32,7 +32,7 @@ public class BasicWorkflowDto : EndWorkflowDto
     /// 部门等级/分类为:depCodes, 角色为:userIds
     /// </example>
     /// </summary>
-    public List<Kv> NextHandlers { get; set; } = new();
+    public List<FlowStepHandler> NextHandlers { get; set; } = new();
 
     /// <summary>
     /// 是否短信通知
@@ -49,6 +49,11 @@ public class BasicWorkflowDto : EndWorkflowDto
     /// </summary>
     public bool IsStartCountersign { get; set; }
 
+    ///// <summary>
+    ///// 办理方式
+    ///// </summary>
+    //public EHandleMode HandleMode => IsStartCountersign ? EHandleMode.StartCountersign : EHandleMode.Normal;
+
     /// <summary>
     /// 外部业务参数
     /// </summary>

+ 14 - 1
src/Hotline.Share/Dtos/FlowEngine/NextStepOption.cs

@@ -37,7 +37,7 @@ public class NextStepOption : Kv
     /// <summary>
     /// 节点下可选办理对象
     /// </summary>
-    public IReadOnlyList<Kv> Items { get; set; }
+    public IReadOnlyList<FlowStepHandler> Items { get; set; }
 }
 
 public class RecallStepOption : NextStepOption
@@ -46,4 +46,17 @@ public class RecallStepOption : NextStepOption
     /// 该节点原办理对象
     /// </summary>
     public Kv Handler { get; set; }
+}
+
+/// <summary>
+/// 流程办理对象
+/// </summary>
+public class FlowStepHandler : Kv
+{
+    public string? UserId { get; set; }
+    public string? Username { get; set; }
+    public string? OrgId { get; set; }
+    public string? OrgName { get; set; }
+    public string? RoleId { get; set; }
+    public string? RoleName { get; set; }
 }

+ 3 - 2
src/Hotline.Share/Dtos/Order/OrderSpecialDto.cs

@@ -7,6 +7,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using XF.Utility.EnumExtensions;
 using Hotline.Share.Enums.FlowEngine;
@@ -37,7 +38,7 @@ namespace Hotline.Share.Dtos.Order
 		/// 部门等级/分类为:depCodes, 角色为:userIds
 		/// </example>
 		/// </summary>
-		public List<Kv> NextHandlers { get; set; } = new();
+		public List<FlowStepHandler> NextHandlers { get; set; } = new();
 
 		/// <summary>
 		/// 特提原因
@@ -102,7 +103,7 @@ namespace Hotline.Share.Dtos.Order
 		/// 部门等级/分类为:depCodes, 角色为:userIds
 		/// </example>
 		/// </summary>
-		public List<Kv> NextHandlers { get; set; } = new();
+		public List<FlowStepHandler> NextHandlers { get; set; } = new();
 
 		//public string? OrgId { get; set; }
 

+ 22 - 0
src/Hotline.Share/Enums/FlowEngine/EHandleMode.cs

@@ -0,0 +1,22 @@
+namespace Hotline.Share.Enums.FlowEngine;
+
+/// <summary>
+/// 办理方式
+/// </summary>
+public enum EHandleMode
+{
+    /// <summary>
+    /// 正常办理
+    /// </summary>
+    Normal = 0,
+
+    /// <summary>
+    /// 开启会签
+    /// </summary>
+    StartCountersign = 1,
+
+    /// <summary>
+    /// 开启或签
+    /// </summary>
+    StartSignCountersign = 2
+}

+ 6 - 0
src/Hotline.Share/Enums/FlowEngine/EWorkflowStepStatus.cs

@@ -25,6 +25,12 @@ public enum EWorkflowStepStatus
     [Description("已办理")]
     Handled = 2,
 
+    ///// <summary>
+    ///// 无需办理(或签流程未办理节点)
+    ///// </summary>
+    //[Description("无需办理")]
+    //NoNeedInSingleCountersign = 3,
+
     ///// <summary>
     ///// 未办理,由结束会签结束掉
     ///// </summary>

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

@@ -36,8 +36,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 查询工作流包含当前用户办理权限(是否可办理)
         /// </summary>
-        Task<(Workflow workflow, string? countersignId, bool canPrevious)> GetWorkflowHandlePermissionAsync(
-            string workflowId, string userId, string orgId, CancellationToken cancellationToken = default);
+        Task<(Workflow Workflow, string? CountersignId, bool CanHandle, bool CanPrevious)> GetWorkflowHandlePermissionAsync(
+            string workflowId, string userId, string orgId, string[] roleIds, CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 受理,接办
@@ -147,7 +147,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 创建开始节点
         /// </summary>
         WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto,
-            List<Kv> handlers, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime);
+            FlowStepHandler handler, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime);
 
         /// <summary>
         /// 查询未完成节点

+ 41 - 2
src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs

@@ -1,5 +1,6 @@
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.File;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Definition;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Enums.FlowEngine;
@@ -14,6 +15,9 @@ public abstract class StepBasicEntity : CreationEntity
 {
     public string WorkflowId { get; set; }
 
+    /// <summary>
+    /// 业务唯一标识
+    /// </summary>
     public string? ExternalId { get; set; }
 
     #region 业务模块(冗余)
@@ -206,6 +210,13 @@ public abstract class StepBasicEntity : CreationEntity
     /// </summary>
     public DateTime? HandleTime { get; set; }
 
+    /// <summary>
+    /// 角色id(如果指派给角色)
+    /// </summary>
+    public string? RoleId { get; set; }
+
+    public string? RoleName { get; set; }
+
     #endregion
 
     #region Definition
@@ -293,7 +304,7 @@ public abstract class StepBasicEntity : CreationEntity
     /// </example>
     /// </summary>
     [SugarColumn(ColumnDataType = "json", IsJson = true)]
-    public List<Kv> NextHandlers { get; set; } = new();
+    public List<FlowStepHandler> NextHandlers { get; set; } = new();
 
     /// <summary>
     /// 下一节点主办,(NextHandlers其中一个, 如果不是会签则只有一个)
@@ -403,10 +414,38 @@ public abstract class StepBasicEntity : CreationEntity
         }
     }
 
+    /// <summary>
+    /// 指派
+    /// </summary>
+    public void Assign(
+        string? handlerId, string? handlerName,
+        string? handlerOrgId, string? handlerOrgName,
+        string? roleId, string? roleName)
+    {
+        HandlerId = handlerId;
+        HandlerName = handlerName;
+        HandlerOrgId = handlerOrgId;
+        HandlerOrgName = handlerOrgName;
+        RoleId = roleId;
+        RoleName = roleName;
+    }
+
     /// <summary>
     /// 是否处于会签流程中(不包含顶层发起会签节点)
     /// </summary>
     public bool IsInCountersign() => CountersignPosition != ECountersignPosition.None;
 
     #endregion
-}
+}
+
+/*
+feature: 
+1. step增加字段记录roleId, roleName
+2. 指派时为对应办理对象赋值,办理时为所有办理对象字段赋值
+3. 配置办理对象为角色时,如果未指定办理人则指派给角色办理
+4. thk从默认派单池中分配给对应办理人时指定办理对象
+refactor:
+1. step增加字段记录发起会签或是或签
+2. status增加或签无需办理状态
+3. 办理节点时判断是否立即结束会签或者等全部节点办完再结束
+ */

+ 9 - 4
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -719,9 +719,14 @@ public partial class Workflow
     /// 当前用户是否可以办理该流程
     /// </summary>
     /// <returns></returns>
-    public bool CanHandle(string userId, string orgCode) =>
-        Status is EWorkflowStatus.Runnable &&
-        (HandlerUsers.Any(d => d.Key == userId) || HandlerOrgs.Any(d => d.Key == orgCode));
+    public bool CanHandle(string userId, string orgId, string[] roleIds)
+    {
+        if (!Steps.Any())
+            throw new UserFriendlyException("未查询节点信息");
+        return Status is EWorkflowStatus.Runnable &&
+               //(HandlerUsers.Any(d => d.Key == userId) || HandlerOrgs.Any(d => d.Key == orgCode));
+               Steps.Any(d => d.HandlerId == userId || d.HandlerOrgId == orgId || roleIds.Contains(d.RoleId));
+    }
 
     private void RemoveCurrentHandleGroup(string handlerId, string handlerOrg)
     {
@@ -818,7 +823,7 @@ public partial class Workflow
         ResetOption();
         Status = EWorkflowStatus.Runnable;
     }
-    
+
     public void SetAllDuration()
     {
         if (!EndTime.HasValue)

+ 90 - 84
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -76,11 +76,6 @@ 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,
                 Steps = new(),
                 Traces = new(),
                 WorkflowDefinition = definition,
@@ -113,9 +108,6 @@ namespace Hotline.FlowEngine.Workflows
                     current.RequiredOrgId, current.OrgName,
                     current.OrgAreaCode, current.OrgAreaName,
                     current.OrgLevel);
-                //workflow.ActualHandlerKey = current.RequiredUserId;
-                //workflow.ActualHandlerValue = current.UserName;
-                //workflow.ActualHandlerType = EHandlerType.AssignedUser;
 
                 var endTrace = await EndAsync(workflow, dto, firstStepDefine, startStep, current, cancellationToken);
                 return;
@@ -234,14 +226,15 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 查询工作流包含当前用户结束会签权限(是否可结束)
         /// </summary>
-        public async Task<(Workflow, string?, bool)> GetWorkflowHandlePermissionAsync(
-            string workflowId, string userId, string orgId, CancellationToken cancellationToken = default)
+        public async Task<(Workflow Workflow, string? CountersignId, bool CanHandle, bool CanPrevious)> GetWorkflowHandlePermissionAsync(
+            string workflowId, string userId, string orgId, string[] roleIds, CancellationToken cancellationToken = default)
         {
             var workflow = await GetWorkflowAsync(workflowId, withSteps: true, withCountersigns: true,
                 cancellationToken: cancellationToken);
 
+            var canHandle = workflow.CanHandle(userId, orgId, roleIds);
             var canPrevious = false;
-            if (workflow.CanHandle(userId, orgId))
+            if (canHandle)
             {
                 var currentStep = FindCurrentStepWaitForHandle(workflow, userId, orgId);
                 if (currentStep.Status is not EWorkflowStepStatus.Handled)
@@ -253,12 +246,12 @@ namespace Hotline.FlowEngine.Workflows
 
             var unCompletedCountersign = workflow.Countersigns
                 .FirstOrDefault(d => !d.IsCompleted() && d.StarterId == userId);
-            if (unCompletedCountersign is null) return (workflow, null, canPrevious);
+            if (unCompletedCountersign is null) return (workflow, null, canHandle, canPrevious);
 
             //var existCountersignEndStep = workflow.Steps.Exists(d =>
             //    d.IsCountersignEndStep && d.CountersignStartStepId == unCompletedCountersign.StartStepId);
             //return (workflow, existCountersignEndStep ? null : unCompletedCountersign.Id, canPrevious);
-            return (workflow, unCompletedCountersign.Id, canPrevious);
+            return (workflow, unCompletedCountersign.Id, canHandle, canPrevious);
         }
 
         /// <summary>
@@ -270,7 +263,7 @@ namespace Hotline.FlowEngine.Workflows
             string? orgAreaCode, string? orgAreaName,
             CancellationToken cancellationToken)
         {
-            if (!workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId)) return;
+            if (!workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles)) return;
             //工单完成以后查看的场景
             if (workflow.Status != EWorkflowStatus.Runnable) return;
 
@@ -318,7 +311,7 @@ namespace Hotline.FlowEngine.Workflows
             DateTime? expiredTime, List<WorkflowStepHandler> stepHandlers, ISessionContext current,
             CancellationToken cancellationToken)
         {
-            ValidatePermission(workflow, current.RequiredOrgId, current.RequiredUserId);
+            ValidatePermission(workflow, current.RequiredOrgId, current.RequiredUserId, current.Roles);
             //CheckWhetherRunnable(workflow.Status);
 
             #region 办理当前节点
@@ -524,7 +517,7 @@ namespace Hotline.FlowEngine.Workflows
         public async Task<EFlowDirection> PreviousAsync(Workflow workflow, PreviousWorkflowDto dto, User operater,
            ISessionContext current, CancellationToken cancellationToken)
         {
-            ValidatePermission(workflow, operater.OrgId, operater.Id);
+            //ValidatePermission(workflow, operater.OrgId, operater.Id);
 
             var (currentStep, prevStep, countersignStartStep) = GetPreviousStep(workflow, operater.Id, operater.OrgId);
 
@@ -1217,7 +1210,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 创建开始节点
         /// </summary>
         public WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine,
-            BasicWorkflowDto dto, List<Kv> handles, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime)
+            BasicWorkflowDto dto, FlowStepHandler handler, List<WorkflowStepHandler> stepHandlers, DateTime? expiredTime)
         {
             //startstep
             var nextSteps = _mapper.Map<List<StepSimple>>(startStepDefine.NextSteps);
@@ -1231,7 +1224,7 @@ namespace Hotline.FlowEngine.Workflows
             var startStep = _mapper.Map<WorkflowStep>(startStepDefine);
             _mapper.Map(workflow, startStep);
             startStep.FlowAssignType = EFlowAssignType.User;
-            startStep.Handlers = handles;
+            startStep.Handlers = new List<Kv> { new(handler.Key, handler.Value) };
             startStep.StepHandlers = stepHandlers;
             startStep.NextSteps = nextSteps;
             startStep.IsMain = true;
@@ -1240,6 +1233,10 @@ namespace Hotline.FlowEngine.Workflows
             startStep.PrevChosenStepCode = null;
             startStep.StepExpiredTime = expiredTime;
 
+            startStep.Assign(handler.UserId, handler.Username,
+                handler.OrgId, handler.OrgName,
+                handler.RoleId, handler.RoleName);
+
             startStep.InitId();
             return startStep;
         }
@@ -1311,16 +1308,6 @@ namespace Hotline.FlowEngine.Workflows
             if (dto.IsStartCountersign && !counterSignType.HasValue)
                 throw new UserFriendlyException("缺少会签类型参数");
 
-            ////创建会签数据
-            //if (dto.IsStartCountersign)
-            //{
-            //    var exists = workflow.Countersigns.Any(d =>
-            //        !d.IsCompleted() && d.StarterId == _sessionContext.RequiredUserId);
-            //    if (exists)
-            //        throw new UserFriendlyException("该用户在当前流程存在未结束会签");
-            //    await StartCountersignAsync(workflow, step, dto, flowAssignType, counterSignType, expiredTime, cancellationToken);
-            //}
-
             //办理参数
             //_mapper.Map(dto, step);
             step.NextHandlers = dto.NextHandlers;
@@ -1375,10 +1362,10 @@ namespace Hotline.FlowEngine.Workflows
         }
 
         private async Task<WorkflowStep> CreateStartStepAsync(Workflow workflow, StepDefine startStepDefine,
-            BasicWorkflowDto dto, List<Kv> handles, List<WorkflowStepHandler> stepHandlers, EWorkflowTraceType traceType,
+            BasicWorkflowDto dto, FlowStepHandler handler, List<WorkflowStepHandler> stepHandlers, EWorkflowTraceType traceType,
             DateTime? expiredTime, CancellationToken cancellationToken)
         {
-            var startStep = CreateStartStep(workflow, startStepDefine, dto, handles, stepHandlers, expiredTime);
+            var startStep = CreateStartStep(workflow, startStepDefine, dto, handler, stepHandlers, expiredTime);
             //await _workflowStepRepository.AddAsync(startStep, cancellationToken);
             await _workflowStepRepository.AddNav(startStep)
                 .Include(d => d.StepHandlers)
@@ -1509,7 +1496,7 @@ namespace Hotline.FlowEngine.Workflows
                 _ => throw new ArgumentOutOfRangeException()
             };
 
-            return await CreateStepsAsync(workflow, nextStepDefine, prevStep, dto, dto.IsStartCountersign,
+            return await CreateStepsAsync(workflow, nextStepDefine, prevStep, dto,
                 flowAssignInfo.FlowAssignType, dto.NextHandlers, stepHandlers, null, EWorkflowStepStatus.WaitForAccept,
                 ECountersignPosition.None, false, EWorkflowTraceType.Normal, handlerType, expiredTime,
                 cancellationToken: cancellationToken);
@@ -1544,7 +1531,7 @@ namespace Hotline.FlowEngine.Workflows
                 ? ECountersignPosition.Multi
                 : ECountersignPosition.Single;
 
-            return CreateStepsAsync(workflow, stepDefine, prevStep, dto, isStartCountersign, flowAssignType, dto.NextHandlers,
+            return CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignType, dto.NextHandlers,
                 stepHandlers, countersignId, EWorkflowStepStatus.WaitForAccept, nextStepCountersignPosition,
                 false, EWorkflowTraceType.Normal, handlerType, expiredTime, cancellationToken: cancellationToken);
         }
@@ -1652,7 +1639,8 @@ namespace Hotline.FlowEngine.Workflows
             EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, DateTime? expiredTime,
             CancellationToken cancellationToken)
         {
-            var countersign = await CreateCountersignAsync(current, workflow, startStep, dto.NextHandlers, flowAssignType,
+            var countersign = await CreateCountersignAsync(current, workflow, startStep,
+                dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), flowAssignType,
                 counterSignType, expiredTime, startStep.CountersignId, cancellationToken);
             startStep.StartCountersign(countersign.Id);
         }
@@ -1951,14 +1939,13 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.SetStatusRunnable();
 
             var targetStepNew = targetIsStartStep
-                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, stepHandlers, traceType, expiredTime,
-                    cancellationToken)
-                : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto, false,
+                ? await CreateStartStepAsync(workflow, targetStepDefine, dto,
+                    dto.NextHandlers.First(), stepHandlers, traceType, expiredTime, cancellationToken)
+                : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers, stepHandlers,
                     null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceType,
                     null, expiredTime, cancellationToken: cancellationToken)).First();
 
-
             //更新实际办理节点信息
             workflow.UpdateActualStepWhenAssign(targetStepNew, targetStep.HandlerOrgName, targetStep.HandlerOrgId);
 
@@ -1998,9 +1985,9 @@ namespace Hotline.FlowEngine.Workflows
                 throw UserFriendlyException.SameMessage("当前流程状态不可继续流转");
         }
 
-        private void ValidatePermission(Workflow workflow, string OrgId, string UserId)
+        private void ValidatePermission(Workflow workflow, string OrgId, string UserId, string[] roleIds)
         {
-            if (!workflow.CanHandle(UserId, OrgId))
+            if (!workflow.CanHandle(UserId, OrgId, roleIds))
                 throw UserFriendlyException.SameMessage("无办理权限");
         }
 
@@ -2015,10 +2002,18 @@ namespace Hotline.FlowEngine.Workflows
             if (workflow.Steps.Any(d => d.StepType == EStepType.End))
                 throw UserFriendlyException.SameMessage("无法重复创建结束节点");
 
-            var handler = new Kv { Key = _sessionContext.UserId, Value = _sessionContext.UserName };
+            var handler = new FlowStepHandler
+            {
+                Key = current.UserId,
+                Value = current.UserName,
+                UserId = current.RequiredUserId,
+                Username = current.UserName,
+                OrgId = current.OrgId,
+                OrgName = current.OrgName,
+            };
 
-            var step = CreateStep(workflow, endStepDefine, prevStep, null, new List<Kv> { handler },
-                stepHandlers, null, null, null, EWorkflowStepStatus.WaitForAccept,
+            var step = CreateStep(workflow, endStepDefine, prevStep, null, handler,
+                stepHandlers, null, null, EWorkflowStepStatus.WaitForAccept,
                 ECountersignPosition.None, DateTime.Now, endStepDefine.Name, true);
 
             //step.Accept(_sessionContext.RequiredUserId, _sessionContext.UserName,
@@ -2046,26 +2041,31 @@ namespace Hotline.FlowEngine.Workflows
             List<WorkflowStepHandler> stepHandlers,
             CancellationToken cancellationToken)
         {
-            List<Kv> handlers;
-            if (stepDefine.HandlerType is EHandlerType.AssignedUser or EHandlerType.AssignedOrg)
+            //List<Kv> handlers;
+            //if (stepDefine.HandlerType is EHandlerType.AssignedUser or EHandlerType.AssignedOrg)
+            //{
+            //    handlers = stepDefine.HandlerTypeItems;
+            //}
+            //else
+            //{
+            List<FlowStepHandler> handlers;
+            if (stepDefine.HandlerType != EHandlerType.Role && !dto.NextHandlers.Any())
+                throw new UserFriendlyException("未指定节点处理者");
+            if (stepDefine.HandlerType == EHandlerType.Role && !dto.NextHandlers.Any())
             {
-                handlers = stepDefine.HandlerTypeItems;
+                var handler = stepDefine.HandlerTypeItems.First();
+                handlers = new List<FlowStepHandler>
+                {
+                    new(){Key = handler.Key, Value = handler.Value, RoleId = handler.Key, RoleName = handler.Value}
+                }; //flowAssignInfo.GetHandlers();
             }
             else
             {
-                if (stepDefine.HandlerType != EHandlerType.Role && !dto.NextHandlers.Any())
-                    throw new UserFriendlyException("未指定节点处理者");
-                if (stepDefine.HandlerType == EHandlerType.Role && !dto.NextHandlers.Any())
-                {
-                    handlers = flowAssignInfo.GetHandlers();
-                }
-                else
-                {
-                    handlers = dto.NextHandlers;
-                }
+                handlers = dto.NextHandlers;
             }
+            //}
 
-            return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, dto.IsStartCountersign,
+            return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, /*dto.IsStartCountersign,*/
                 flowAssignInfo.FlowAssignType, handlers, stepHandlers, null,
                 EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None,
                 true, traceType, null, expiredTime, cancellationToken);
@@ -2076,9 +2076,9 @@ namespace Hotline.FlowEngine.Workflows
             StepDefine stepDefine,
             WorkflowStep prevStep,
             BasicWorkflowDto dto,
-            bool isStartCountersign,
+            //bool isStartCountersign,
             EFlowAssignType? flowAssignType,
-            List<Kv> handlers,
+            List<FlowStepHandler> handlers,
             List<WorkflowStepHandler> stepHandlers,
             string? countersignId,
             EWorkflowStepStatus stepStatus,
@@ -2091,29 +2091,30 @@ namespace Hotline.FlowEngine.Workflows
         )
         {
             List<WorkflowStep> steps = new();
-            if (isStartCountersign)
-            {
-                foreach (var handler in handlers)
-                {
-                    var step = CreateStep(workflow, stepDefine, prevStep, flowAssignType,
-                        new List<Kv> { handler }, new(), dto.NextStepCode,
-                        dto.NextMainHandler, countersignId, stepStatus, csPosition, expiredTime,
-                        dto.NextStepName, isOrigin, handlerType, dto.BusinessType);
-
-                    var stepHandler = stepHandlers.First(d => d.GetHandler().Key == handler.Key);
-                    step.StepHandlers = new List<WorkflowStepHandler> { stepHandler };
+            //if (isStartCountersign)
+            //{
 
-                    steps.Add(step);
-                }
-            }
-            else
+            foreach (var handler in handlers)
             {
-                var step = CreateStep(workflow, stepDefine, prevStep, flowAssignType, handlers,
-                    stepHandlers, dto.NextStepCode, dto.NextMainHandler, countersignId, stepStatus,
-                    csPosition, expiredTime, dto.NextStepName, isOrigin, handlerType, dto.BusinessType);
+                var isMain = handlers.Count == 1 || (handlers.Count > 1 && handler.Key == dto.NextMainHandler);
+                var step = CreateStep(workflow, stepDefine, prevStep, flowAssignType,
+                    handler, stepHandlers, dto.NextStepCode, countersignId, stepStatus, csPosition, expiredTime,
+                    dto.NextStepName, isOrigin, isMain, handlerType, dto.BusinessType);
+
+                //var stepHandler = stepHandlers.First(d => d.GetHandler().Key == handler.Key);
+                //step.StepHandlers = new List<WorkflowStepHandler> { stepHandler };
 
                 steps.Add(step);
             }
+            //}
+            //else
+            //{
+            //    var step = CreateStep(workflow, stepDefine, prevStep, flowAssignType, handlers,
+            //        stepHandlers, dto.NextStepCode, dto.NextMainHandler, countersignId, stepStatus,
+            //        csPosition, expiredTime, dto.NextStepName, isOrigin, handlerType, dto.BusinessType);
+
+            //    steps.Add(step);
+            //}
 
             //await _workflowStepRepository.AddRangeAsync(steps, cancellationToken);
             await _workflowStepRepository.AddNav(steps)
@@ -2370,32 +2371,33 @@ namespace Hotline.FlowEngine.Workflows
             StepDefine stepDefine,
             WorkflowStep prevStep,
             EFlowAssignType? flowAssignType,
-            List<Kv> handlers,
+            FlowStepHandler handler,
             List<WorkflowStepHandler> stepHandlers,
             string nextStepCode,
-            string? nextMainHandler,
             string? countersignId,
             EWorkflowStepStatus stepStatus,
             ECountersignPosition countersignPosition,
             DateTime? expiredTime,
             string stepName,
             bool isOrigin,
+            bool isMainHandler = false,
             EHandlerType? handlerType = null, //动态节点依据动态策略判断
             EBusinessType? businessType = null
         )
         {
-            if (!handlers.Any())
-                throw new UserFriendlyException($"非法参数, handlers为空, method: {nameof(CreateStep)}");
+            //if (!handlers.Any())
+            //    throw new UserFriendlyException($"非法参数, handlers为空, method: {nameof(CreateStep)}");
             var step = _mapper.Map<WorkflowStep>(stepDefine);
             _mapper.Map(workflow, step);
-            var handlerIds = handlers.Select(d => d.Key).ToList();
-            var isMain = handlers.Count == 1 || (handlers.Count > 1 || handlerIds.First() == nextMainHandler);
+            //todo mainhandler 未赋值
+            //var handlerIds = handlers.Select(d => d.Key).ToList();
+            //var isMain = handlers.Count == 1 || (handlers.Count > 1 || handlerIds.First() == nextMainHandler);
 
             step.FlowAssignType = flowAssignType;
-            step.Handlers = handlers;
+            step.Handlers = new List<Kv> { new(handler.Key, handler.Value) };
             step.StepHandlers = stepHandlers;
             step.NextStepCode = step.StepType is EStepType.End ? string.Empty : nextStepCode;
-            step.IsMain = isMain;
+            step.IsMain = isMainHandler;
             step.PrevStepId = prevStep.Id;
             step.PrevStepCode = prevStep.Code;
             step.CountersignId = countersignId;
@@ -2406,6 +2408,10 @@ namespace Hotline.FlowEngine.Workflows
             step.IsOrigin = isOrigin;
             step.Name = stepName;
 
+            step.Assign(handler.UserId, handler.Username,
+                handler.OrgId, handler.OrgName,
+                handler.RoleId, handler.RoleName);
+
             if (handlerType.HasValue)
                 step.HandlerType = handlerType.Value;
             if (businessType.HasValue)

+ 37 - 0
src/Hotline/FlowEngine/Workflows/WorkflowStep.cs

@@ -1,9 +1,11 @@
 using Hotline.File;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Definition;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Enums.FlowEngine;
 using SqlSugar;
+using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 
 namespace Hotline.FlowEngine.Workflows;
@@ -186,6 +188,41 @@ public class WorkflowStep : StepBasicEntity
     public WorkflowStepHandler? GetActualHandler() =>
         StepHandlers.FirstOrDefault(d => d.IsActualHandler);
 
+    public FlowStepHandler GetWorkflowStepHandler()
+    {
+        switch (FlowAssignType)
+        {
+            case EFlowAssignType.Org:
+                return new FlowStepHandler
+                {
+                    Key = HandlerOrgId,
+                    Value = HandlerOrgName,
+                    OrgId = HandlerOrgId,
+                    OrgName = HandlerOrgName
+                };
+            case EFlowAssignType.User:
+                return new FlowStepHandler
+                {
+                    Key = HandlerId,
+                    Value = HandlerName,
+                    UserId = HandlerId,
+                    Username = HandlerName,
+                    OrgId = HandlerOrgId,
+                    OrgName = HandlerOrgName
+                };
+            case EFlowAssignType.Role:
+                return new FlowStepHandler
+                {
+                    Key = RoleId,
+                    Value = RoleName,
+                    RoleId = RoleId,
+                    RoleName = RoleName,
+                };
+            default:
+                throw new ArgumentOutOfRangeException();
+        }
+    }
+
     #endregion
 }
 

+ 2 - 1
src/Hotline/Orders/IOrderDomainService.cs

@@ -1,4 +1,5 @@
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
 
 namespace Hotline.Orders
@@ -60,7 +61,7 @@ namespace Hotline.Orders
         /// 平均派单
         /// </summary>
         /// <returns></returns>
-        Task<List<Kv>> AverageOrder(CancellationToken cancellationToken);
+        Task<FlowStepHandler> AverageOrder(CancellationToken cancellationToken);
         
         /// <summary>
         /// 登录平均派单

+ 25 - 7
src/Hotline/Orders/OrderDomainService.cs

@@ -16,6 +16,7 @@ using Hotline.Schedulings;
 using Hotline.Users;
 using Hotline.Share.Dtos;
 using Hotline.Settings.Hotspots;
+using Hotline.Share.Dtos.FlowEngine;
 
 namespace Hotline.Orders;
 
@@ -182,21 +183,38 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     /// 平均派单
     /// </summary>
     /// <returns></returns>
-    public async Task<List<Kv>> AverageOrder(CancellationToken cancellationToken)
+    public async Task<FlowStepHandler> AverageOrder(CancellationToken cancellationToken)
     {
         var time = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd"));
         var scheduling = await _schedulingRepository.Queryable().Includes(x => x.SchedulingUser)
             .Where(x => x.SchedulingTime == time && x.WorkingTime <= DateTime.Now.TimeOfDay && x.OffDutyTime >= DateTime.Now.TimeOfDay && x.AtWork == true)
             .OrderBy(x => x.SendOrderNum).FirstAsync(cancellationToken);
         if (scheduling is null)
-            return new List<Kv> { new(OrderDefaults.SourceChannel.SendPoolId, "待派单池") };
-
-        var user = await _userRepository.GetAsync(x => x.Id == scheduling.SchedulingUser.UserId, cancellationToken);
-        if (user is null)
-            throw new UserFriendlyException("无效用户编号");
+            //return new List<Kv> { new(OrderDefaults.SourceChannel.SendPoolId, "待派单池") };
+            return new FlowStepHandler
+            {
+                Key = OrderDefaults.SourceChannel.SendPoolId,
+                Value = "待派单池",
+                UserId = OrderDefaults.SourceChannel.SendPoolId,
+                Username = "待派单池",
+            };
+
+        //var user = await _userRepository.GetAsync(x => x.Id == scheduling.SchedulingUser.UserId, cancellationToken);
+        //if (user is null)
+        //    throw new UserFriendlyException("无效用户编号");
         scheduling.SendOrderNum++;
         await _schedulingRepository.UpdateAsync(scheduling, cancellationToken);
-        return new List<Kv> { new(user.Id, user.Name) };
+        //return new List<Kv> { new(user.Id, user.Name) };
+        var user = scheduling.SchedulingUser;
+        return new FlowStepHandler
+        {
+            Key = user.UserId,
+            Value = user.UserName,
+            UserId = user.UserId,
+            Username = user.UserName,
+            OrgId = user.OrgId,
+            OrgName = user.OrgIdName
+        };
     }
 
     /// <summary>

+ 2 - 1
src/Hotline/Orders/OrderSpecial.cs

@@ -7,6 +7,7 @@ using System.Threading.Tasks;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.File;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
@@ -46,7 +47,7 @@ namespace Hotline.Orders
         public string? StepName { get; set; } = string.Empty;
 
 		[SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
-		public List<Kv> NextHandlers { get; set; }
+		public List<FlowStepHandler> NextHandlers { get; set; }
 
 		/// <summary>
 		/// 特提原因

+ 1 - 1
src/Hotline/README.md

@@ -31,7 +31,7 @@ master, hotfix, fix, dev, feature, release
 | hotfix | 紧急bug修复分支,拉取自master |
 | fix | 非紧急bug修复分支,拉取自dev |
 | dev | 开发分支,开发环境共有分支,提供前后端对接环境 |
-| feature | 功能开发分支,一般拉取至dev |
+| feature | 功能开发分支 |
 | release | 发布分支 |
 
 #### 分支命名规范

+ 4 - 4
src/XF.Domain/Entities/IWorkflow.cs

@@ -72,10 +72,10 @@ public enum EFlowAssignType
     /// </summary>
     User = 1,
 
-    ///// <summary>
-    ///// 指派到角色
-    ///// </summary>
-    //Role = 2,
+    /// <summary>
+    /// 指派到角色
+    /// </summary>
+    Role = 2,
 }
 
 /// <summary>