xf 9 months ago
parent
commit
0876e0cc10

+ 5 - 15
src/Hotline.Api/Controllers/CallController.cs

@@ -94,22 +94,12 @@ namespace Hotline.Api.Controllers
         }
 
         /// <summary>
-        /// 关联通话记录与工单或回访
+        /// 查询坐席操作记录(固定数据量)
         /// </summary>
+        /// <param name="dto"></param>
         /// <returns></returns>
-        [HttpPost("relate-call-to-order")]
-        public Task RelateCallToOrder([FromBody] LinkCallRecordDto dto) =>
-            _callApplication.RelateCallToOrderAsync(dto, HttpContext.RequestAborted);
-
-        ///// <summary>
-        ///// 查询坐席操作记录(固定数据量)
-        ///// </summary>
-        ///// <param name="dto"></param>
-        ///// <returns></returns>
-        //[HttpGet("tel-operations-fixed")]
-        //public Task<IReadOnlyList<TelOperation>> QueryTelOperationsFixed([FromQuery] QueryTelOperationsFixedDto dto)
-        //{
-
-        //}
+        [HttpGet("tel-operations-fixed")]
+        public Task<IReadOnlyList<TelOperation>> QueryTelOperationsFixed([FromQuery] QueryTelOperationsFixedDto dto) => 
+            _callApplication.QueryTelOperationsAsync(dto, HttpContext.RequestAborted);
     }
 }

+ 69 - 69
src/Hotline.Api/Controllers/OrderController.cs

@@ -2310,10 +2310,8 @@ public class OrderController : BaseController
     [HttpGet("fixed")]
     public async Task<IReadOnlyList<OrderDto>> QueryFixed([FromQuery] QueryOrderFixedDto dto)
     {
-        var count = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.FixedQueryCount)
-            .SettingValue[0]);
         var query = _orderApplication.QueryOrders(dto);
-        var orders = await query.ToFixedListAsync(dto.QueryIndex, count, HttpContext.RequestAborted);
+        var orders = await query.ToFixedListAsync(dto.QueryIndex, cancellationToken: HttpContext.RequestAborted);
         return _mapper.Map<IReadOnlyList<OrderDto>>(orders);
     }
 
@@ -2420,40 +2418,42 @@ public class OrderController : BaseController
         if (!string.IsNullOrEmpty(order.WorkflowId))
         {
             bool canInsteadHandle = false;
-			//班长代办
-			var settingEnable = _systemSettingCacheManager.GetSetting(SettingConstants.ChargeDAffaires);
+            //班长代办
+            var settingEnable = _systemSettingCacheManager.GetSetting(SettingConstants.ChargeDAffaires);
             var isEnable = settingEnable != null && settingEnable.SettingValue.Any() ? int.Parse(settingEnable?.SettingValue[0]) : 0;
-			if (isEnable > 0)
-			{
-				var setting = _systemSettingCacheManager.GetSetting(SettingConstants.SeatsMonitor);
-				var settingStr = setting?.SettingValue;
-				var roles = _sessionContext.Roles;
-				foreach (var item in settingStr)
-				{
+            if (isEnable > 0)
+            {
+                var setting = _systemSettingCacheManager.GetSetting(SettingConstants.SeatsMonitor);
+                var settingStr = setting?.SettingValue;
+                var roles = _sessionContext.Roles;
+                foreach (var item in settingStr)
+                {
                     if (roles != null && roles.Contains(item))
-                    { 
-                        canInsteadHandle = true; 
-                    }else {
+                    {
+                        canInsteadHandle = true;
+                    }
+                    else
+                    {
                         canInsteadHandle = false;
                     };
-				}
-				if (canInsteadHandle)
-				{
-					var unhandleSteps =
-						await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
-					// 会签多节点 不允许班长代办
-					if (unhandleSteps.Count > 1)
-						canInsteadHandle = false;
-					if (isEnable < 3 && unhandleSteps.Count == 1)
+                }
+                if (canInsteadHandle)
+                {
+                    var unhandleSteps =
+                        await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+                    // 会签多节点 不允许班长代办
+                    if (unhandleSteps.Count > 1)
+                        canInsteadHandle = false;
+                    if (isEnable < 3 && unhandleSteps.Count == 1)
                     {
                         var type = isEnable - 1;
-						var step = unhandleSteps.FirstOrDefault(d => d.BusinessType == (EBusinessType)type);
-						canInsteadHandle = step != null && !string.IsNullOrEmpty(step.Id);
-						if (canInsteadHandle && step.IsInCountersign())
-							canInsteadHandle = false;
-					}
-				}
-			}
+                        var step = unhandleSteps.FirstOrDefault(d => d.BusinessType == (EBusinessType)type);
+                        canInsteadHandle = step != null && !string.IsNullOrEmpty(step.Id);
+                        if (canInsteadHandle && step.IsInCountersign())
+                            canInsteadHandle = false;
+                    }
+                }
+            }
             var result = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
                 order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles,
                 cancellationToken: HttpContext.RequestAborted);
@@ -2464,12 +2464,12 @@ public class OrderController : BaseController
             dto.CanInsteadHandle = !dto.CanHandle && canInsteadHandle;
             dto.PreviousOpinion = result.previousOpinion;
 
-			await _mediator.Publish(new GetOrderDetailNotify(result.Workflow,
+            await _mediator.Publish(new GetOrderDetailNotify(result.Workflow,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
                 _sessionContext.RequiredOrgId, _sessionContext.OrgName,
                 _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName));
         }
-       
+
 
         //var dto = _mapper.Map<OrderDto>(order!);
         //dto.CountersignId = countersignId;
@@ -2602,7 +2602,7 @@ public class OrderController : BaseController
         }
 
         //内容分词
-        await _orderApplication.OrderParticiple(dto.Content, order.Id,order.CreationTime, HttpContext.RequestAborted);
+        await _orderApplication.OrderParticiple(dto.Content, order.Id, order.CreationTime, HttpContext.RequestAborted);
         //敏感分词
         await _orderApplication.OrderSensitiveParticiple(dto.Content, order.Id, HttpContext.RequestAborted);
         //sms
@@ -2963,38 +2963,38 @@ public class OrderController : BaseController
     [HttpGet("nextsteps_commission/{orderId}")]
     public async Task<NextStepsWithOpinionDto<RecommendStepOption>> GetNextStepsWithRecommendCommission(string orderId)
     {
-	    var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: HttpContext.RequestAborted);
-	    if (string.IsNullOrEmpty(order.WorkflowId))
-		    throw UserFriendlyException.SameMessage("该工单未开启流程");
-	    var unhandleSteps =
-		    await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
-	    if (unhandleSteps.Count > 1)
-		    throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
-	    if (unhandleSteps.Count < 1)
-		    throw UserFriendlyException.SameMessage("未查询到流程信息");
+        var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: HttpContext.RequestAborted);
+        if (string.IsNullOrEmpty(order.WorkflowId))
+            throw UserFriendlyException.SameMessage("该工单未开启流程");
+        var unhandleSteps =
+            await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+        if (unhandleSteps.Count > 1)
+            throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
+        if (unhandleSteps.Count < 1)
+            throw UserFriendlyException.SameMessage("未查询到流程信息");
         var stepOne = unhandleSteps.First();
         if (stepOne.IsInCountersign())
-	        throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
-		var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, stepOne.Id, HttpContext.RequestAborted);
-	    dto.ExpiredTime = order.ExpiredTime;
-	    var rsp = _mapper.Map<NextStepsWithOpinionDto<RecommendStepOption>>(dto);
-	    foreach (var step in rsp.Steps)
-	    {
-		    if (dto.CurrentStepBusinessType is not EBusinessType.Send ||
-		        step.BusinessType is not EBusinessType.Department) continue;
-		    var org = await _organizeRepository.GetAsync(d => d.AreaCode == order.AreaCode, HttpContext.RequestAborted);
-		    if (org is null) continue;
-		    step.RecommendOrgId = org.Id;
-		    step.RecommendOrgName = org.Name;
-	    }
-
-	    return rsp;
-    }
-
-	/// <summary>
-	/// 结束会签
-	/// </summary>
-	[HttpPost("endcs")]
+            throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
+        var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, stepOne.Id, HttpContext.RequestAborted);
+        dto.ExpiredTime = order.ExpiredTime;
+        var rsp = _mapper.Map<NextStepsWithOpinionDto<RecommendStepOption>>(dto);
+        foreach (var step in rsp.Steps)
+        {
+            if (dto.CurrentStepBusinessType is not EBusinessType.Send ||
+                step.BusinessType is not EBusinessType.Department) continue;
+            var org = await _organizeRepository.GetAsync(d => d.AreaCode == order.AreaCode, HttpContext.RequestAborted);
+            if (org is null) continue;
+            step.RecommendOrgId = org.Id;
+            step.RecommendOrgName = org.Name;
+        }
+
+        return rsp;
+    }
+
+    /// <summary>
+    /// 结束会签
+    /// </summary>
+    [HttpPost("endcs")]
     public async Task EndCountersign([FromBody] EndCountersignDto dto)
     {
         var workflow = await _workflowDomainService.TerminalCountersignAsync(dto.CountersignId, HttpContext.RequestAborted);
@@ -3227,7 +3227,7 @@ public class OrderController : BaseController
         //}
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
-    
+
     /// <summary>
     /// 查询坐席待办
     /// </summary>
@@ -3244,7 +3244,7 @@ public class OrderController : BaseController
             dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
         var query = _orderRepository.Queryable();
-        if(dto.IsHandled.HasValue)
+        if (dto.IsHandled.HasValue)
         {
             var hasHandled = dto.IsHandled.Value;
             query = query.Where(d => SqlFunc.Subqueryable<WorkflowTrace>()
@@ -3253,8 +3253,8 @@ public class OrderController : BaseController
                                (!hasHandled || step.Status == EWorkflowStepStatus.Handled && step.TraceState != EWorkflowTraceState.StepRemoveByPrevious) &&
                                ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
                                 (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
-                                (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)))).Any() || 
-                                     (string.IsNullOrEmpty(d.WorkflowId) && 
+                                (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)))).Any() ||
+                                     (string.IsNullOrEmpty(d.WorkflowId) &&
                                       (string.IsNullOrEmpty(d.SignerId) || d.SignerId == _sessionContext.RequiredUserId))
             );
         }
@@ -3311,7 +3311,7 @@ public class OrderController : BaseController
 
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
-    
+
     /// <summary>
     /// 查询中心待办
     /// </summary>

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

@@ -113,7 +113,7 @@ internal static class StartupExtensions
                 break;
             case "TianRun":
                 services
-                    .AddScoped<ICallApplication, TianRunCallApplication>()
+                    //.AddScoped<ICallApplication, TianRunCallApplication>()
                     .AddScoped<ITrApplication, TrApplication>()
                     .AddHostedService<CurrentWaitNumService>()
                     .AddHostedService<TelsStatusRefreshService>()

+ 2 - 2
src/Hotline.Api/StartupHelper.cs

@@ -263,8 +263,8 @@ namespace Hotline.Api
                 switch (callCenterConfiguration.CallCenterType)
                 {
                     case "XingTang":
-                        var getCallsJobKey = new JobKey(nameof(GetXingTangCallsJob));
-                        d.AddJob<GetXingTangCallsJob>(getCallsJobKey);
+                        var getCallsJobKey = new JobKey(nameof(XingTangCallsSyncJob));
+                        d.AddJob<XingTangCallsSyncJob>(getCallsJobKey);
                         d.AddTrigger(d => d
                             .WithIdentity("get-callsxt-trigger")
                             .ForJob(getCallsJobKey)

+ 5 - 3
src/Hotline.Application/CallCenter/ICallApplication.cs

@@ -5,6 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Tels;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.TrCallCenter;
 using XingTang.Sdk;
@@ -53,10 +54,11 @@ namespace Hotline.Application.CallCenter
         /// 定量查询通话记录
         /// </summary>
         Task<IReadOnlyList<CallNativeDto>> QueryCallsFixedAsync(QueryCallsFixedDto dto, CancellationToken cancellationToken);
-
+        
         /// <summary>
-        /// 关联通话记录与工单或回访
+        /// 查询分机操作记录(定量)
         /// </summary>
-        Task RelateCallToOrderAsync(LinkCallRecordDto dto, CancellationToken cancellationToken);
+        Task<IReadOnlyList<TelOperation>> QueryTelOperationsAsync(QueryTelOperationsFixedDto dto,
+            CancellationToken cancellationToken);
     }
 }

+ 113 - 104
src/Hotline.Application/CallCenter/TianRunCallApplication.cs

@@ -1,118 +1,127 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Hotline.Application.CallCenter.Calls;
-using Hotline.Application.Tels;
-using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.BlackLists;
-using Hotline.CallCenter.Calls;
-using Hotline.Settings;
-using Hotline.Share.Dtos.CallCenter;
-using Hotline.Share.Dtos.TrCallCenter;
-using Hotline.Share.Enums.CallCenter;
-using Microsoft.AspNetCore.Http;
-using XF.Domain.Authentications;
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Text;
+//using System.Threading.Tasks;
+//using Hotline.Application.CallCenter.Calls;
+//using Hotline.Application.Tels;
+//using Hotline.Caching.Interfaces;
+//using Hotline.CallCenter.BlackLists;
+//using Hotline.CallCenter.Calls;
+//using Hotline.CallCenter.Tels;
+//using Hotline.Settings;
+//using Hotline.Share.Dtos.CallCenter;
+//using Hotline.Share.Dtos.TrCallCenter;
+//using Hotline.Share.Enums.CallCenter;
+//using Microsoft.AspNetCore.Http;
+//using XF.Domain.Authentications;
 
-namespace Hotline.Application.CallCenter
-{
-    public class TianRunCallApplication : ICallApplication
-    {
-        private readonly ISessionContext _sessionContext;
-        private readonly ITrApplication _trApplication;
-        private readonly ITelApplication _telApplication;
-        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+//namespace Hotline.Application.CallCenter
+//{
+//    public class TianRunCallApplication : ICallApplication
+//    {
+//        private readonly ISessionContext _sessionContext;
+//        private readonly ITrApplication _trApplication;
+//        private readonly ITelApplication _telApplication;
+//        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
 
-        public TianRunCallApplication(
-            ISessionContext sessionContext,
-            ITrApplication trApplication,
-            ITelApplication telApplication,
-            ISystemSettingCacheManager systemSettingCacheManager
-            )
-        {
-            _sessionContext = sessionContext;
-            _trApplication = trApplication;
-            _telApplication = telApplication;
-            _systemSettingCacheManager = systemSettingCacheManager;
-        }
+//        public TianRunCallApplication(
+//            ISessionContext sessionContext,
+//            ITrApplication trApplication,
+//            ITelApplication telApplication,
+//            ISystemSettingCacheManager systemSettingCacheManager
+//            )
+//        {
+//            _sessionContext = sessionContext;
+//            _trApplication = trApplication;
+//            _telApplication = telApplication;
+//            _systemSettingCacheManager = systemSettingCacheManager;
+//        }
 
-        /// <summary>
-        /// 查询分机
-        /// </summary>
-        public Task<IReadOnlyList<TelDto>> QueryTelsAsync(CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        /// <summary>
+//        /// 查询分机
+//        /// </summary>
+//        public Task<IReadOnlyList<TelDto>> QueryTelsAsync(CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        /// <summary>
-        /// 查询分机组
-        /// </summary>
-        public Task<IReadOnlyList<TelGroupDto>> QueryTelGroupsAsync(CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        /// <summary>
+//        /// 查询分机组
+//        /// </summary>
+//        public Task<IReadOnlyList<TelGroupDto>> QueryTelGroupsAsync(CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        public Task<string> AddBlackListAsync(AddBlacklistDto dto, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        public Task<string> AddBlackListAsync(AddBlacklistDto dto, CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        public Task RemoveBlackListAsync(string id, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        public Task RemoveBlackListAsync(string id, CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        public Task<List<Blacklist>> QueryBlackListsAsync(CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        public Task<List<Blacklist>> QueryBlackListsAsync(CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        /// <summary>
-        /// 签入
-        /// </summary>
-        public Task<TrOnDutyResponseDto> SignInAsync(SignInDto dto, CancellationToken cancellationToken) =>
-            _trApplication.OnSign(_sessionContext.RequiredUserId, dto.TelNo, (ETelModel)dto.TelModelState, cancellationToken);
+//        /// <summary>
+//        /// 签入
+//        /// </summary>
+//        public Task<TrOnDutyResponseDto> SignInAsync(SignInDto dto, CancellationToken cancellationToken) =>
+//            _trApplication.OnSign(_sessionContext.RequiredUserId, dto.TelNo, (ETelModel)dto.TelModelState, cancellationToken);
 
-        /// <summary>
-        /// 签出
-        /// </summary>
-        public Task SingOutAsync(CancellationToken cancellationToken) =>
-            _telApplication.SignOutAsync(_sessionContext.RequiredUserId, cancellationToken);
+//        /// <summary>
+//        /// 签出
+//        /// </summary>
+//        public Task SingOutAsync(CancellationToken cancellationToken) =>
+//            _telApplication.SignOutAsync(_sessionContext.RequiredUserId, cancellationToken);
 
-        public Task SingOutAsync(string telNo, CancellationToken cancellationToken) =>
-            _telApplication.SignOutByTelNoAsync(telNo, cancellationToken);
+//        public Task SingOutAsync(string telNo, CancellationToken cancellationToken) =>
+//            _telApplication.SignOutByTelNoAsync(telNo, cancellationToken);
 
-        /// <summary>
-        /// 查询当前用户的分机状态
-        /// </summary>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        public Task<TrOnDutyResponseDto> GetTelStateAsync(CancellationToken cancellationToken) =>
-            _trApplication.TelState(_sessionContext.RequiredUserId, cancellationToken);
+//        /// <summary>
+//        /// 查询当前用户的分机状态
+//        /// </summary>
+//        /// <param name="cancellationToken"></param>
+//        /// <returns></returns>
+//        public Task<TrOnDutyResponseDto> GetTelStateAsync(CancellationToken cancellationToken) =>
+//            _trApplication.TelState(_sessionContext.RequiredUserId, cancellationToken);
 
-        /// <summary>
-        /// 定量查询通话记录
-        /// </summary>
-        Task<IReadOnlyList<CallNativeDto>> ICallApplication.QueryCallsFixedAsync(QueryCallsFixedDto dto, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        /// <summary>
+//        /// 定量查询通话记录
+//        /// </summary>
+//        Task<IReadOnlyList<CallNativeDto>> ICallApplication.QueryCallsFixedAsync(QueryCallsFixedDto dto, CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        /// <summary>
-        /// 关联通话记录与工单或回访
-        /// </summary>
-        public Task RelateCallToOrderAsync(LinkCallRecordDto dto, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
+//        /// <summary>
+//        /// 关联通话记录与工单或回访
+//        /// </summary>
+//        public Task RelateCallToOrderAsync(LinkCallRecordDto dto, CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
 
-        /// <summary>
-        /// 定量查询通话记录
-        /// </summary>
-        public async Task<IReadOnlyList<CallNative>> QueryCallsFixedAsync(QueryCallsFixedDto dto, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}
+//        /// <summary>
+//        /// 查询分机操作记录(定量)
+//        /// </summary>
+//        public async Task<IReadOnlyList<TelOperation>> QueryTelOperationsAsync(QueryTelOperationsFixedDto dto, CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
+
+//        /// <summary>
+//        /// 定量查询通话记录
+//        /// </summary>
+//        public async Task<IReadOnlyList<CallNative>> QueryCallsFixedAsync(QueryCallsFixedDto dto, CancellationToken cancellationToken)
+//        {
+//            throw new NotImplementedException();
+//        }
+//    }
+//}

+ 16 - 51
src/Hotline.Application/CallCenter/XingTangCallApplication.cs

@@ -35,12 +35,9 @@ namespace Hotline.Application.CallCenter
         private readonly IWorkRepository _workRepository;
         private readonly ITelRestRepository _telRestRepository;
         private readonly IRepository<CallNative> _callNativeRepository;
-        private readonly IOrderRepository _orderRepository;
-        private readonly IRepository<OrderVisit> _orderVisitRepository;
+        private readonly IRepository<TelOperation> _teloperationRepository;
         private readonly ITypedCache<Work> _cacheWork;
         private readonly IUserCacheManager _userCacheManager;
-        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
-        private readonly ICapPublisher _capPublisher;
         private readonly ISessionContext _sessionContext;
         private readonly IMapper _mapper;
 
@@ -50,12 +47,9 @@ namespace Hotline.Application.CallCenter
             IWorkRepository workRepository,
             ITelRestRepository telRestRepository,
             IRepository<CallNative> callNativeRepository,
-            IOrderRepository orderRepository,
-            IRepository<OrderVisit> orderVisitRepository,
+            IRepository<TelOperation> teloperationRepository,
             ITypedCache<Work> cacheWork,
             IUserCacheManager userCacheManager,
-            ISystemSettingCacheManager systemSettingCacheManager,
-            ICapPublisher capPublisher,
             ISessionContext sessionContext,
             IMapper mapper)
         {
@@ -64,12 +58,9 @@ namespace Hotline.Application.CallCenter
             _workRepository = workRepository;
             _telRestRepository = telRestRepository;
             _callNativeRepository = callNativeRepository;
-            _orderRepository = orderRepository;
-            _orderVisitRepository = orderVisitRepository;
+            _teloperationRepository = teloperationRepository;
             _cacheWork = cacheWork;
             _userCacheManager = userCacheManager;
-            _systemSettingCacheManager = systemSettingCacheManager;
-            _capPublisher = capPublisher;
             _sessionContext = sessionContext;
             _mapper = mapper;
         }
@@ -206,14 +197,13 @@ namespace Hotline.Application.CallCenter
         /// </summary>
         public async Task<IReadOnlyList<CallNativeDto>> QueryCallsFixedAsync(QueryCallsFixedDto dto, CancellationToken cancellationToken)
         {
-            var count = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.FixedQueryCount).SettingValue[0]);
             return await _callNativeRepository.Queryable()
                 .LeftJoin<Order>((d, o) => d.CallNo == o.CallId)
                 .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), (d, o) => o.No == dto.OrderNo)
                 .WhereIF(!string.IsNullOrEmpty(dto.FromNo), d => d.FromNo == dto.FromNo)
-                .WhereIF(!string.IsNullOrEmpty(dto.ToNo), d => d.FromNo == dto.ToNo)
-                .WhereIF(!string.IsNullOrEmpty(dto.UserName), d => d.FromNo == dto.UserName)
-                .WhereIF(!string.IsNullOrEmpty(dto.TelNo), d => d.FromNo == dto.TelNo)
+                .WhereIF(!string.IsNullOrEmpty(dto.ToNo), d => d.ToNo == dto.ToNo)
+                .WhereIF(!string.IsNullOrEmpty(dto.UserName), d => d.UserName == dto.UserName)
+                .WhereIF(!string.IsNullOrEmpty(dto.TelNo), d => d.TelNo == dto.TelNo)
                 .WhereIF(dto.EndBy != null, d => d.EndBy == dto.EndBy)
                 .WhereIF(dto.CallStartTimeBT != null, d => d.BeginIvrTime >= dto.CallStartTimeBT)
                 .WhereIF(dto.CallStartTimeLT != null, d => d.BeginIvrTime <= dto.CallStartTimeLT)
@@ -225,45 +215,20 @@ namespace Hotline.Application.CallCenter
                     OrderNo = o.No,
                     Title = o.Title,
                 }, true)
-                .ToFixedListAsync(dto, count, cancellationToken);
+                .ToFixedListAsync(dto, cancellationToken);
         }
-
+        
         /// <summary>
-        /// 关联通话记录与工单或回访
+        /// 查询分机操作记录(定量)
         /// </summary>
-        public async Task RelateCallToOrderAsync(LinkCallRecordDto dto, CancellationToken cancellationToken)
+        public async Task<IReadOnlyList<TelOperation>> QueryTelOperationsAsync(QueryTelOperationsFixedDto dto, CancellationToken cancellationToken)
         {
-            var call = await _callNativeRepository.GetAsync(d => d.CallNo == dto.CallId, cancellationToken);
-            if (call is null) throw UserFriendlyException.SameMessage("无效通话记录编号");
-            if (dto.IsOrder)
-            {
-                //工单
-                var order = await _orderRepository.GetAsync(x => x.Id == dto.Id, cancellationToken);
-                if (order is null) throw UserFriendlyException.SameMessage("无效工单编号");
-                if (!string.IsNullOrEmpty(order.CallId))
-                    throw UserFriendlyException.SameMessage("通话记录已经关联工单");
-
-                order.CallId = dto.CallId;
-                order.FromPhone = call.FromNo;
-                order.TransferPhone = call.ToNo;
-                await _orderRepository.UpdateAsync(order, cancellationToken);
-
-                //推省上
-                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineCallConnectWithOrder,
-                    new PublishCallRecrodDto()
-                    {
-                        Order = _mapper.Map<OrderDto>(order),
-                        TrCallRecordDto = _mapper.Map<TrCallDto>(call)
-                    });
-            }
-            else
-            {
-                //回访
-                var visit = await _orderVisitRepository.GetAsync(x => x.Id == dto.Id, cancellationToken);
-                if (visit is null) throw UserFriendlyException.SameMessage("无效回访记录编号");
-                visit.CallId = dto.CallId;
-                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
-            }
+            return await _teloperationRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.UserName), d => d.UserName == dto.UserName)
+                .WhereIF(!string.IsNullOrEmpty(dto.StaffNo), d => d.StaffNo == dto.StaffNo)
+                .WhereIF(!string.IsNullOrEmpty(dto.GroupId), d => d.GroupId == dto.GroupId)
+                .WhereIF(dto.OperateState != null, d => d.OperateState == dto.OperateState)
+                .ToFixedListAsync(dto, cancellationToken);
         }
     }
 }

+ 5 - 10
src/Hotline.Application/Jobs/GetXingTangCallsJob.cs → src/Hotline.Application/Jobs/XingTangCallsSyncJob.cs

@@ -13,20 +13,20 @@ namespace Hotline.Application.Jobs
     /// <summary>
     /// 查询兴唐通话记录
     /// </summary>
-    public class GetXingTangCallsJob : IJob, IDisposable
+    public class XingTangCallsSyncJob : IJob, IDisposable
     {
         private readonly IRepository<CallNative> _callRepository;
         private readonly IRepository<User> _userRepository;
         private readonly IMapper _mapper;
-        private readonly ILogger<GetXingTangCallsJob> _logger;
+        private readonly ILogger<XingTangCallsSyncJob> _logger;
         private readonly ISqlSugarClient _db;
 
-        public GetXingTangCallsJob(
+        public XingTangCallsSyncJob(
             ISugarUnitOfWork<XingTangDbContext> uow,
             IRepository<CallNative> callRepository,
             IRepository<User> userRepository,
             IMapper mapper,
-            ILogger<GetXingTangCallsJob> logger)
+            ILogger<XingTangCallsSyncJob> logger)
         {
             _callRepository = callRepository;
             _userRepository = userRepository;
@@ -65,11 +65,6 @@ namespace Hotline.Application.Jobs
 
                 foreach (var call in calls)
                 {
-                    //if (trCall.CallDirection is ECallDirection.Out &&
-                    //    string.IsNullOrEmpty(trCall.RecordingAbsolutePath))
-                    //    continue;
-                    Console.WriteLine();
-
                     var user = users.FirstOrDefault(d => d.StaffNo == call.StaffNo);
                     if (user is not null)
                     {
@@ -98,7 +93,7 @@ namespace Hotline.Application.Jobs
         /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
         public void Dispose()
         {
-            _logger.LogInformation($"{nameof(GetXingTangCallsJob)} disposed");
+            _logger.LogInformation($"{nameof(XingTangCallsSyncJob)} disposed");
         }
     }
 }

+ 36 - 0
src/Hotline.Application/Jobs/XingTangTelOperationSyncJob.cs

@@ -0,0 +1,36 @@
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Jobs
+{
+    public class XingTangTelOperationSyncJob : IJob, IDisposable
+    {
+        /// <summary>
+        /// Called by the <see cref="T:Quartz.IScheduler" /> when a <see cref="T:Quartz.ITrigger" />
+        /// fires that is associated with the <see cref="T:Quartz.IJob" />.
+        /// </summary>
+        /// <remarks>
+        /// The implementation may wish to set a  result object on the
+        /// JobExecutionContext before this method exits.  The result itself
+        /// is meaningless to Quartz, but may be informative to
+        /// <see cref="T:Quartz.IJobListener" />s or
+        /// <see cref="T:Quartz.ITriggerListener" />s that are watching the job's
+        /// execution.
+        /// </remarks>
+        /// <param name="context">The execution context.</param>
+        public async Task Execute(IJobExecutionContext context)
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
+        public void Dispose()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 4 - 1
src/Hotline.Application/Mappers/CallMapperConfigs.cs

@@ -83,7 +83,10 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.AudioFile, s => s.AudioFile)
                 .AfterMapping((s, d) =>
                 {
-                    d.EndBy = EEndBy.From;
+                    //todo 等待兴唐补全Disposition字段
+                    d.EndBy = d.Direction == ECallDirection.In
+                        ? EEndBy.From
+                        : EEndBy.To;
                 });
 
             config.ForType<CallNative, TrCallDto>()

+ 6 - 4
src/Hotline.Repository.SqlSugar/Extensions/SqlSugarRepositoryExtensions.cs

@@ -34,16 +34,18 @@ namespace Hotline.Repository.SqlSugar.Extensions
         /// 分批次查询固定数量
         /// </summary>
         /// <returns></returns>
-        public static Task<List<TEntity>> ToFixedListAsync<TEntity>(this ISugarQueryable<TEntity> query, QueryFixedDto dto, int count, CancellationToken cancellationToken)
+        public static Task<List<TEntity>> ToFixedListAsync<TEntity>(this ISugarQueryable<TEntity> query, QueryFixedDto dto, CancellationToken cancellationToken)
         where TEntity : class, new()
         {
-            return query.Skip(dto.QueryIndex * count).Take(count).ToListAsync(cancellationToken);
+            if (dto.QueryCount == 0) dto.QueryCount = 50;
+            return query.Skip(dto.QueryIndex * dto.QueryCount).Take(dto.QueryCount).ToListAsync(cancellationToken);
         }
 
-        public static Task<List<TEntity>> ToFixedListAsync<TEntity>(this ISugarQueryable<TEntity> query, int queryIndex, int count, CancellationToken cancellationToken)
+        public static Task<List<TEntity>> ToFixedListAsync<TEntity>(this ISugarQueryable<TEntity> query, int queryIndex, int? queryCount = null, CancellationToken cancellationToken = default)
             where TEntity : class, new()
         {
-            return query.Skip(queryIndex * count).Take(count).ToListAsync(cancellationToken);
+            if (queryCount is null or 0) queryCount = 50;
+            return query.Skip(queryIndex * queryCount.Value).Take(queryCount.Value).ToListAsync(cancellationToken);
         }
     }
 }

+ 31 - 0
src/Hotline.Share/Dtos/CallCenter/QueryTelOperationsFixedDto.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.CallCenter
+{
+    public class QueryTelOperationsFixedDto : QueryFixedDto
+    {
+        /// <summary>
+        /// 姓名
+        /// </summary>
+        public string? UserName { get; set; }
+
+        /// <summary>
+        /// 工号
+        /// </summary>
+        public string? StaffNo { get; set; }
+
+        /// <summary>
+        /// 工作组
+        /// </summary>
+        public string? GroupId { get; set; }
+
+        /// <summary>
+        /// 操作类型
+        /// </summary>
+        public int? OperateState { get; set; }
+    }
+}

+ 5 - 0
src/Hotline.Share/QueryFixedDto.cs

@@ -12,5 +12,10 @@ namespace Hotline.Share
         /// 查询批次
         /// </summary>
         public int QueryIndex { get; set; }
+
+        /// <summary>
+        /// 单次总数据量
+        /// </summary>
+        public int QueryCount { get; set; } = 50;
     }
 }

+ 0 - 5
src/Hotline/Settings/SettingConstants.cs

@@ -345,11 +345,6 @@ namespace Hotline.Settings
         /// </summary>
         public const string CanUpdateOrderSender = "CanUpdateOrderSender";
 
-        /// <summary>
-        /// 定量查询数据条数上限
-        /// </summary>
-        public const string FixedQueryCount = "FixedQueryCount";
-
         /// <summary>
         /// 是否开启重复工单
         /// </summary>