tangjiang 1 month ago
parent
commit
91f1171d75

+ 87 - 70
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -45,6 +45,8 @@ using XF.Domain.Cache;
 using Hotline.Application.CallCenter;
 using Mapster;
 using Tr.Sdk;
+using Hotline.Configurations;
+using Hotline.Share.Enums.Order;
 
 namespace Hotline.Api.Controllers
 {
@@ -77,6 +79,7 @@ namespace Hotline.Api.Controllers
         private readonly IIPPbxApplication _iPPbxApplication;
         private readonly ICallTelClient _callTelClient;
         private readonly IRepository<TelOperation> _telOperationRepository;
+        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
 
         public IPPbxController(IMapper mapper, IUserDomainService userDomainService,
             ISessionContext sessionContext, IRepository<TrCallRecord> trCallRecordRepository,
@@ -88,7 +91,15 @@ namespace Hotline.Api.Controllers
             ITelApplication telApplication, IRepository<Quality.Quality> qualiteyRepository,
             IRepository<QualityTemplate> qualityTemplate,
             ISystemSettingCacheManager systemSettingCacheManager, IRepository<TelActionRecord> telActionRecordRepository,
-            ISystemMobilAreaApplication systemMobilAreaApplication, IRepository<Work> workRepository, Publisher publisher, ITrCallRecordRepository callRecordRepository, ITypedCache<Work> cacheWork, IIPPbxApplication iPPbxApplication, ICallTelClient callTelClient, IRepository<TelOperation> telOperationRepository)
+            ISystemMobilAreaApplication systemMobilAreaApplication,
+            IRepository<Work> workRepository,
+            Publisher publisher,
+            ITrCallRecordRepository callRecordRepository,
+            ITypedCache<Work> cacheWork,
+            IIPPbxApplication iPPbxApplication,
+            ICallTelClient callTelClient,
+            IRepository<TelOperation> telOperationRepository,
+           IOptionsSnapshot<AppConfiguration> appOptions)
         {
             _mapper = mapper;
             _userDomainService = userDomainService;
@@ -117,6 +128,7 @@ namespace Hotline.Api.Controllers
             _iPPbxApplication = iPPbxApplication;
             _callTelClient = callTelClient;
             _telOperationRepository = telOperationRepository;
+            _appOptions = appOptions;
         }
 
         #region 添添呼
@@ -131,7 +143,7 @@ namespace Hotline.Api.Controllers
         {
             var tels = await _callTelClient.QueryTelsAsync(new QueryTelRequest() { }, HttpContext.RequestAborted);
             var listenTels = _systemSettingCacheManager.GetSetting(SettingConstants.ListenTels)?.SettingValue;
-            tels = tels.Where(m => listenTels.Contains(m.TelNo) ==  false).ToList();
+            tels = tels.Where(m => listenTels.Contains(m.TelNo) == false).ToList();
             var returnlist = _mapper.Map<List<TrTelDto>>(tels);
             string callOutQueueId = _systemSettingCacheManager.GetSetting(SettingConstants.CallOutQueueId).SettingValue[0];
             returnlist.ForEach(x =>
@@ -152,18 +164,18 @@ namespace Hotline.Api.Controllers
         {
             var tels = await _callTelClient.QueryTelStateAsync(new QueryTelStateRequest() { State = state }, HttpContext.RequestAborted);
             var listenTels = _systemSettingCacheManager.GetSetting(SettingConstants.ListenTels)?.SettingValue;
-            var workList = await _workRepository.Queryable().Where(d=> 1 == 1 && !d.EndTime.HasValue).ToListAsync();
+            var workList = await _workRepository.Queryable().Where(d => 1 == 1 && !d.EndTime.HasValue).ToListAsync();
             var query = from tel in tels.AgentList
                         join works in workList on tel.TelNo equals works.TelNo into workD
                         from work in workD.DefaultIfEmpty()
                         select new TrTelStateDto
                         {
                             Id = tel.Id,
-                            TelNo =tel.TelNo,
-                            ChannelUUid =tel.ChannelUUid,
-                            TelName =tel.TelName,
+                            TelNo = tel.TelNo,
+                            ChannelUUid = tel.ChannelUUid,
+                            TelName = tel.TelName,
                             Type = tel.Type,
-                            Weight =tel.Weight,
+                            Weight = tel.Weight,
                             Queue = tel.Queue,
                             State = tel.State,
                             OldState = tel.OldState,
@@ -177,14 +189,14 @@ namespace Hotline.Api.Controllers
                             OtherNumber = tel.OtherNumber,
                             GateWay = tel.GateWay,
                             AnsweredAt = tel.AnsweredAt,
-                            WorkUserId = (work != null) ? work.UserId: "",
-                            WorkUserName = (work != null) ? work.UserName: "",
+                            WorkUserId = (work != null) ? work.UserId : "",
+                            WorkUserName = (work != null) ? work.UserName : "",
                         };
             //if (hasListen == false)
             //{
             //    query = query.Where(m => listenTels.Contains(m.TelNo) == false);
             //}
-            var list = query.OrderBy(x=>x.TelNo).OrderByDescending(x=>x.CreatedAt).ToList();
+            var list = query.OrderBy(x => x.TelNo).OrderByDescending(x => x.CreatedAt).ToList();
             return list;// _mapper.Map<IReadOnlyList<TrTelStateDto>>(tels.AgentList);
         }
 
@@ -195,7 +207,7 @@ namespace Hotline.Api.Controllers
         /// <returns></returns>
         [HttpGet("query-telstatebyno")]
         [AllowAnonymous]
-        public async Task<TrTelStateDto> TrQueryTelStateByTelNo([FromQuery]string? telno)
+        public async Task<TrTelStateDto> TrQueryTelStateByTelNo([FromQuery] string? telno)
         {
             var tels = await _callTelClient.QueryTelStateAsync(new QueryTelStateRequest() { TelNo = telno }, HttpContext.RequestAborted);
 
@@ -290,7 +302,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("on-duty")]
         public async Task<TrOnDutyResponseDto> OnDuty([FromBody] TrOnDutyDto dto)
         {
-            return await _callApplication.SignInAsync(new SignInDto() { TelNo = dto.TelNo, TelModelState = dto.TelModelState}, HttpContext.RequestAborted);
+            return await _callApplication.SignInAsync(new SignInDto() { TelNo = dto.TelNo, TelModelState = dto.TelModelState }, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -323,7 +335,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("change-telmodel")]
         public async Task ChangeTelModel([FromBody] ChangeTelModelDto dto)
         {
-            await _callApplication.ChangeTelModel(dto.isCallOut,HttpContext.RequestAborted);
+            await _callApplication.ChangeTelModel(dto.isCallOut, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -332,9 +344,9 @@ namespace Hotline.Api.Controllers
         /// <param name="telNo"></param>
         /// <returns></returns>
         [HttpGet("off-duty-manage")]
-        public async Task OffDuty([FromQuery]string telNo)
+        public async Task OffDuty([FromQuery] string telNo)
         {
-           await _telApplication.SignOutByTelNoAsync(telNo, HttpContext.RequestAborted);
+            await _telApplication.SignOutByTelNoAsync(telNo, HttpContext.RequestAborted);
         }
 
         //提供关闭浏览器事件触发调用
@@ -379,7 +391,7 @@ namespace Hotline.Api.Controllers
             var isResting = await _telRestRepository.IsRestingAsync(work.TelNo, HttpContext.RequestAborted);
             if (isResting)
                 throw UserFriendlyException.SameMessage("当前坐席正在休息");
-            
+
             var user = await _userRepository.GetAsync(work.UserId, HttpContext.RequestAborted);
             var telRest = new TelRest(work.TelNo, work.TelNo, work.UserId, work.UserName, dto.Reason, false, user.StaffNo);
             await _telRestRepository.AddAsync(telRest, HttpContext.RequestAborted);
@@ -405,7 +417,7 @@ namespace Hotline.Api.Controllers
             await _telRestRepository.UpdateAsync(telRest, HttpContext.RequestAborted);
 
             var telAction = await _telActionRecordRepository.GetAsync(x => x.TelNo == work.TelNo && x.ActionType == EActionType.TelRest && !x.EndTime.HasValue, HttpContext.RequestAborted);
-            if (telAction!=null)
+            if (telAction != null)
             {
                 telAction.EndAction();
                 await _telActionRecordRepository.UpdateAsync(telAction);
@@ -481,7 +493,7 @@ namespace Hotline.Api.Controllers
             model.RingTimes = 0;
             model.QueueTims = 0;
             model.OnState = Share.Enums.CallCenter.EOnState.NoOn;
-            
+
             //计算通话时长
             if (model.AnsweredTime != null)
             {
@@ -527,7 +539,7 @@ namespace Hotline.Api.Controllers
                         model.OperatorName = areaModel.OperatorName;
                     }
                 }
-                catch{}
+                catch { }
             }
             else
             {
@@ -542,10 +554,10 @@ namespace Hotline.Api.Controllers
                         model.OperatorName = areaModel.OperatorName;
                     }
                 }
-                catch{}
+                catch { }
             }
             //判断是否是内部通话(目前分机都为4位)
-            if (model.CPN.Length==4 && model.CDPN.Length ==4) //是内部通话
+            if (model.CPN.Length == 4 && model.CDPN.Length == 4) //是内部通话
             {
                 model.TelNo = model.CDPN;//如果是内部通话  响应分机为被叫号码
             }
@@ -553,7 +565,7 @@ namespace Hotline.Api.Controllers
             {
                 model.PhoneTypes = (EPhoneTypes)Convert.ToInt32(dto.phoneTypes);
             }
-            
+
 
             //获取关联 工单或是回访
             //var order = await _orderRepository.GetAsync(x => x.CallId == model.CallAccept, HttpContext.RequestAborted);//由CallAccept改为OtherAccept
@@ -573,39 +585,39 @@ namespace Hotline.Api.Controllers
                     if (teAny)
                     {
                         var quality = await _qualiteyRepository.Queryable().Where(x => x.OrderId == order.Id && x.Source == Share.Enums.Quality.EQualitySource.Accepted).FirstAsync();
-                        if (quality !=null)
+                        if (quality != null)
                         {
-							var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
-							//await _aiQualityService.CreateAiOrderQualityTask(quality, model, order, setting?.SettingValue[0], HttpContext.RequestAborted);
-
-							try
-							{
-								 //_aiQualityService.CreateAiOrderQualityTask(
-									//quality,
-									//model.RecordingAbsolutePath,
-									//model.CPN,
-									//model.CreatedTime,
-									//order, setting?.SettingValue[0], HttpContext.RequestAborted);
-								 var handler = new AiQualityHandler()
-								 {
-                                     Id = quality.Id,
-                                     Source = quality.Source.ToString(),
-									 AudioFile = model.RecordingAbsolutePath,
-									 FromNo = model.CPN,
-									 CallStartTime = model.CreatedTime,
-									 ViteRecordPrefix = setting?.SettingValue[0],
-								 };
-								await _publisher.PublishAsync(new AiOrderQualityNotify(handler), PublishStrategy.ParallelNoWait, HttpContext.RequestAborted);
-							}
-							catch (Exception e)
-							{
-								_logger.LogError($"写入智能质检异常!, \r\n{e.Message}");
-							}
-						
+                            var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
+                            //await _aiQualityService.CreateAiOrderQualityTask(quality, model, order, setting?.SettingValue[0], HttpContext.RequestAborted);
+
+                            try
+                            {
+                                //_aiQualityService.CreateAiOrderQualityTask(
+                                //quality,
+                                //model.RecordingAbsolutePath,
+                                //model.CPN,
+                                //model.CreatedTime,
+                                //order, setting?.SettingValue[0], HttpContext.RequestAborted);
+                                var handler = new AiQualityHandler()
+                                {
+                                    Id = quality.Id,
+                                    Source = quality.Source.ToString(),
+                                    AudioFile = model.RecordingAbsolutePath,
+                                    FromNo = model.CPN,
+                                    CallStartTime = model.CreatedTime,
+                                    ViteRecordPrefix = setting?.SettingValue[0],
+                                };
+                                await _publisher.PublishAsync(new AiOrderQualityNotify(handler), PublishStrategy.ParallelNoWait, HttpContext.RequestAborted);
+                            }
+                            catch (Exception e)
+                            {
+                                _logger.LogError($"写入智能质检异常!, \r\n{e.Message}");
+                            }
+
                         }
                     }
                 }
-                catch{}
+                catch { }
             }
             else
             {
@@ -632,7 +644,7 @@ namespace Hotline.Api.Controllers
             }
             await _trCallRecordRepository.AddAsync(model, HttpContext.RequestAborted);
 
-           
+
             var publishCallRecordDto = new PublishCallRecrodDto() { };
             if (order != null)
             {
@@ -706,7 +718,7 @@ namespace Hotline.Api.Controllers
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpPost("calls/call-list/export")]
-        public async Task<FileStreamResult> GetCallListExport([FromBody]ExportExcelDto<GetCallListDto> dto)
+        public async Task<FileStreamResult> GetCallListExport([FromBody] ExportExcelDto<GetCallListDto> dto)
         {
             var query = _callRecordRepository.GetCallList(dto.QueryDto);
             List<TrCallRecord> data;
@@ -724,11 +736,11 @@ namespace Hotline.Api.Controllers
 
             dto.ColumnInfos.ForEach(x =>
             {
-                if (x.Prop=="cpn")
+                if (x.Prop == "cpn")
                 {
-                    x.Prop ="CPN";
+                    x.Prop = "CPN";
                 }
-                if (x.Prop=="cdpn")
+                if (x.Prop == "cdpn")
                 {
                     x.Prop = "CDPN";
                 }
@@ -763,16 +775,16 @@ namespace Hotline.Api.Controllers
         }
 
 
-		#endregion
+        #endregion
 
-		#region 关联
+        #region 关联
 
-		/// <summary>
-		/// 可关联工单
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("canlink-order")]
+        /// <summary>
+        /// 可关联工单
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("canlink-order")]
         public async Task<PagedDto<OrderDto>> CanLinkCallRecordOrder([FromQuery] CanLinkCallRecordOrderDto dto)
         {
             var (total, items) = await _orderRepository.Queryable()
@@ -810,7 +822,7 @@ namespace Hotline.Api.Controllers
         public async Task LinkCallRecord([FromBody] LinkCallRecordDto dto)
         {
             //var trRecord = await _trCallRecordRepository.GetAsync(x => x.CallAccept == dto.CallId, HttpContext.RequestAborted);//由CallAccept改为OtherAccept
-            
+
             if (dto.IsOrder)
             {
                 var trRecords = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == dto.CallId).ToListAsync(HttpContext.RequestAborted);
@@ -846,7 +858,7 @@ namespace Hotline.Api.Controllers
                 trRecord.ExternalId = visit.Id;
                 await _trCallRecordRepository.UpdateAsync(trRecord, HttpContext.RequestAborted);
             }
-           
+
         }
 
 
@@ -863,7 +875,7 @@ namespace Hotline.Api.Controllers
         [HttpGet("telaction-list")]
         public async Task<PagedDto<TelActionListRep>> TelActionList([FromQuery] TelActionListDto dto)
         {
-            var (total,items) = await _telActionRecordRepository.Queryable()
+            var (total, items) = await _telActionRecordRepository.Queryable()
                 .WhereIF(string.IsNullOrEmpty(dto.TelNo) == false, x => x.TelNo.Contains(dto.TelNo))
                 .WhereIF(dto.ActionTtype != null, x => x.ActionType == dto.ActionTtype)
                 .WhereIF(string.IsNullOrEmpty(dto.UserName) == false, x => x.UserName.Contains(dto.UserName))
@@ -881,9 +893,14 @@ namespace Hotline.Api.Controllers
         [HttpGet("telaction-basedata")]
         public async Task<object> TelActionBaseData()
         {
+            var actionType = EnumExts.GetDescriptions<EActionType>();
+            if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
+            {
+                actionType = actionType.Where(m => new int[] { 4, 5 }.Contains(m.Key) == false).ToList();
+            }
             return new
             {
-                ActionType = EnumExts.GetDescriptions<EActionType>(),
+                ActionType = actionType,
             };
         }
         #endregion
@@ -918,7 +935,7 @@ namespace Hotline.Api.Controllers
             try
             {
                 var list = await _workRepository.Queryable().Where(x => 1 == 1 && !x.EndTime.HasValue).ToListAsync();
-                var tellist = await _callTelClient.QueryTelStateAsync(new QueryTelStateRequest { },HttpContext.RequestAborted);
+                var tellist = await _callTelClient.QueryTelStateAsync(new QueryTelStateRequest { }, HttpContext.RequestAborted);
                 foreach (var item in list)
                 {
                     var telmodel = tellist.AgentList.First(x => x.TelNo == item.TelNo);
@@ -926,7 +943,7 @@ namespace Hotline.Api.Controllers
                     {
                         if (telmodel.State == "logout")
                         {
-                            await _iPPbxApplication.ResetTelStatus(item.Id,null, HttpContext.RequestAborted);
+                            await _iPPbxApplication.ResetTelStatus(item.Id, null, HttpContext.RequestAborted);
                             //var telRest = await _telRestRepository.GetAsync(x => x.TelNo == item.TelNo && !x.EndTime.HasValue, HttpContext.RequestAborted);
                             //if (telRest is not null)
                             //{

+ 23 - 1
src/Hotline.Application/CallCenter/DefaultCallApplication.cs

@@ -54,6 +54,7 @@ public abstract class DefaultCallApplication : ICallApplication
     private readonly IOrderRepository _orderRepository;
     private readonly IOrderVisitRepository _orderVisitRepository;
     private readonly ISystemLogRepository _systemLogRepository;
+    private readonly IRepository<TelActionRecord> _telActionRecordRepository;
 
     public DefaultCallApplication(
         IRepository<Tel> telRepository,
@@ -74,7 +75,8 @@ public abstract class DefaultCallApplication : ICallApplication
         ISystemSettingCacheManager systemSettingCacheManager,
         ICapPublisher capPublisher,
         IOrderRepository orderRepository,
-        ISystemLogRepository systemLogRepository)
+        ISystemLogRepository systemLogRepository,
+        IRepository<TelActionRecord> telActionRecordRepository)
     {
         _telRepository = telRepository;
         _telGroupRepository = telGroupRepository;
@@ -95,6 +97,7 @@ public abstract class DefaultCallApplication : ICallApplication
         _capPublisher = capPublisher;
         _orderRepository = orderRepository;
         _systemLogRepository = systemLogRepository;
+        _telActionRecordRepository = telActionRecordRepository;
     }
 
     public DefaultCallApplication()
@@ -198,6 +201,11 @@ public abstract class DefaultCallApplication : ICallApplication
             dto.GroupId, _sessionContext.StaffNo, null);
         await _workRepository.AddAsync(work, cancellationToken);
 
+        //记录签入日志
+        var actionRecord = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, EActionType.SignIn);
+
+        await _telActionRecordRepository.AddAsync(actionRecord, cancellationToken);
+
         return new TrOnDutyResponseDto
         {
             TelNo = dto.TelNo,
@@ -226,6 +234,13 @@ public abstract class DefaultCallApplication : ICallApplication
         await _workRepository.UpdateAsync(work, cancellationToken);
         await _cacheWork.RemoveAsync(work.GetKey(KeyMode.UserId), cancellationToken);
         await _cacheWork.RemoveAsync(work.GetKey(KeyMode.TelNo), cancellationToken);
+
+        var list = await _telActionRecordRepository.Queryable().Where(x => x.TelNo == work.TelNo && !x.EndTime.HasValue).ToListAsync();
+        foreach (var item in list)
+        {
+            item.EndAction();
+            await _telActionRecordRepository.UpdateAsync(item);
+        }
     }
 
     /// <summary>
@@ -248,6 +263,13 @@ public abstract class DefaultCallApplication : ICallApplication
         await _workRepository.UpdateAsync(work, cancellationToken);
         await _cacheWork.RemoveAsync(work.GetKey(KeyMode.UserId), cancellationToken);
         await _cacheWork.RemoveAsync(work.GetKey(KeyMode.TelNo), cancellationToken);
+
+        var list = await _telActionRecordRepository.Queryable().Where(x => x.TelNo == work.TelNo && !x.EndTime.HasValue).ToListAsync();
+        foreach (var item in list)
+        {
+            item.EndAction();
+            await _telActionRecordRepository.UpdateAsync(item);
+        }
     }
 
     /// <summary>