瀏覽代碼

device modify

admin 1 年之前
父節點
當前提交
0957d4db9e
共有 19 個文件被更改,包括 242 次插入43 次删除
  1. 2 2
      src/Hotline.Api/Controllers/PbxController.cs
  2. 8 0
      src/Hotline.Api/Realtimes/RealtimeMethods.cs
  3. 32 0
      src/Hotline.Api/Realtimes/RealtimeService.cs
  4. 22 9
      src/Hotline.Application/Handlers/CallCenter/CallState/AlertExtToExtNotificationHandler.cs
  5. 11 2
      src/Hotline.Application/Handlers/CallCenter/CallState/AlertExtToOuterNotificationHandler.cs
  6. 7 13
      src/Hotline.Application/Handlers/CallCenter/CallState/RingVisitorToExtNotificationHandler.cs
  7. 34 1
      src/Hotline.Application/Handlers/CallCenter/ExtState/IdleNotificationHandler.cs
  8. 16 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/AnswerExtToOuterNotificationHandler.cs
  9. 11 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/AnswerViisitorToExtNotificationHandler.cs
  10. 16 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/AnsweredExtToOuterNotificationHandler.cs
  11. 4 1
      src/Hotline.Application/Handlers/CallCenter/FlowControl/AnsweredExtToOuterToExtNotificationHandler.cs
  12. 16 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/ByeExtAndOuterOneNotificationHandler.cs
  13. 18 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/ByeExtAndOuterTwoNotificationHandler.cs
  14. 1 1
      src/Hotline.Application/Handlers/CallCenter/System/BootupNotificationHandler.cs
  15. 16 2
      src/Hotline.NewRock/DeviceManager.cs
  16. 22 0
      src/Hotline.Share/Dtos/Realtime/AlertDto.cs
  17. 1 1
      src/Hotline/Caching/Services/CallCacheManager.cs
  18. 1 1
      src/Hotline/CallCenter/Devices/IDeviceManager.cs
  19. 4 0
      src/Hotline/Realtimes/IRealtimeService.cs

+ 2 - 2
src/Hotline.Api/Controllers/PbxController.cs

@@ -182,7 +182,7 @@ namespace Hotline.Api.Controllers
 
             await _deviceManager.AssginConfigGroupAsync(
                 dto.No,
-                dto.Distribution.ToString().ToLower(),
+                dto.Distribution,
                 ext: works.Select(d => d.TelNo).ToList(),
                 voiceFile: dto.Voice ?? null,
             cancellationToken: HttpContext.RequestAborted);
@@ -207,7 +207,7 @@ namespace Hotline.Api.Controllers
 
             await _deviceManager.AssginConfigGroupAsync(
                 dto.No,
-                dto.Distribution.ToString().ToLower(),
+                dto.Distribution,
                 ext: works.Select(d => d.TelNo).ToList(),
                 voiceFile: dto.Voice ?? null,
             cancellationToken: HttpContext.RequestAborted);

+ 8 - 0
src/Hotline.Api/Realtimes/RealtimeMethods.cs

@@ -22,6 +22,14 @@
         /// 电话队列通知
         /// </summary>
         public static string CallQueue = "CallQueue";
+        /// <summary>
+        /// 回铃(去电)
+        /// </summary>
+        public static string Alert = "Alert";
+        /// <summary>
+        /// 话机空闲
+        /// </summary>
+        public static string Idle = "Idle";
     }
 }
     

+ 32 - 0
src/Hotline.Api/Realtimes/RealtimeService.cs

@@ -19,6 +19,23 @@ public class RealtimeService : IRealtimeService, IScopeDependency
         _userCacheManager = userCacheManager;
     }
 
+    /// <summary>
+    /// 回铃事件通知
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="dto"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    /// <exception cref="UserFriendlyException"></exception>
+    public async Task AlertAsync(string userId, AlertDto dto, CancellationToken cancellationToken)
+    {
+        var work = _userCacheManager.GetWorkByUser(userId);
+        if(string.IsNullOrEmpty(work.SignalRId))
+            throw new UserFriendlyException("无效signalr.connectionId");
+        await _hubContext.Clients.Client(work.SignalRId).SendAsync(RealtimeMethods.Alert, dto, cancellationToken);
+    }
+
+
     /// <summary>
     /// 振铃事件通知
     /// </summary>
@@ -101,4 +118,19 @@ public class RealtimeService : IRealtimeService, IScopeDependency
         }
     }
 
+    /// <summary>
+    /// 话机空闲通知
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    /// <exception cref="UserFriendlyException"></exception>
+    public async Task IdleAsync(string userId, CancellationToken cancellationToken)
+    {
+        var work = _userCacheManager.GetWorkByUser(userId);
+        if (string.IsNullOrEmpty(work.SignalRId))
+            throw new UserFriendlyException("无效signalr.connectionId");
+        await _hubContext.Clients.Client(work.SignalRId).SendAsync(RealtimeMethods.Idle, new { EventName = "Idle" }, cancellationToken);
+    }
+
 }

+ 22 - 9
src/Hotline.Application/Handlers/CallCenter/CallState/AlertExtToExtNotificationHandler.cs

@@ -1,26 +1,39 @@
 using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
+using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+
 
 namespace Hotline.Application.Handlers.CallCenter.CallState
 {
     public class AlertExtToExtNotificationHandler : INotificationHandler<AlertExtToExtNotification>
     {
+        private readonly IRealtimeService _realtimeService;
+        private readonly IUserCacheManager _userCacheManager;
 
-        public AlertExtToExtNotificationHandler()
+        public AlertExtToExtNotificationHandler(IRealtimeService realtimeService,IUserCacheManager userCacheManager)
         {
-            
+            _realtimeService = realtimeService;
+            _userCacheManager = userCacheManager;
         }
 
         public async Task Handle(AlertExtToExtNotification notification, CancellationToken cancellationToken)
         {
-            
+            //通知前端主叫
+            //获取主叫工作信息
+            var fromWork = _userCacheManager.GetWorkByTel(notification.FromTelNo);
+            if (fromWork != null)
+            {
+                await _realtimeService.AlertAsync(fromWork.UserId, new AlertDto() { Id = notification.FromTelNo, From = notification.FromTelNo, To = notification.ToTelNo, CallType = ECallType.ExtToExt }, cancellationToken);
+            }
+            //通知前端被叫
+            var toWork = _userCacheManager.GetWorkByTel(notification.ToTelNo);
+            if (toWork != null)
+            {
+                await _realtimeService.AlertAsync(toWork.UserId, new AlertDto() { Id = notification.ToTelNo, From = notification.FromTelNo, To = notification.ToTelNo, CallType = ECallType.ExtToExt }, cancellationToken);
+            }
         }
     }
 }

+ 11 - 2
src/Hotline.Application/Handlers/CallCenter/CallState/AlertExtToOuterNotificationHandler.cs

@@ -1,5 +1,7 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using Hotline.Tools;
@@ -12,12 +14,14 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
         private readonly IUserCacheManager _userCacheManager;
+        private readonly IRealtimeService _realtimeService;
 
-        public AlertExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IUserCacheManager userCacheManager)
+        public AlertExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IUserCacheManager userCacheManager,IRealtimeService realtimeService)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
             _userCacheManager = userCacheManager;
+            _realtimeService = realtimeService;
         }
 
         public async Task Handle(AlertExtToOuterNotification notification, CancellationToken cancellationToken)
@@ -26,6 +30,7 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
             if (!string.IsNullOrEmpty(telNo))
             {
                 var model =await _callRepository.GetAsync(x => x.ConversationId==notification.Outer.Id && x.ToNo==notification.Outer.To && x.Trunk==notification.Outer.Trunk && x.CreationTime>=DateTime.Now.AddHours(-2),true,x=>x.CreationTime, cancellationToken);
+                var workModel = _userCacheManager.GetWorkByTel(telNo);
                 //如果存在
                 if (model!=null)
                 {
@@ -42,11 +47,13 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
                         ToNo = notification.Outer.To
                     };
                     await _callDetailRepository.AddAsync(detail, cancellationToken);
+
+                    await _realtimeService.AlertAsync(workModel.UserId, new AlertDto() { Id = model.Id, From = telNo, To = notification.Outer.To, CallType = ECallType.ExtToOuter, ConversationId = notification.Outer.Id }, cancellationToken);
+
                 }
                 //如果不存在
                 else
                 {
-                    var workModel = _userCacheManager.GetWorkByTel(telNo);
                     var isp = PhoneIspTool.GetPhoneIsp(notification.Outer.To);
                     var callModel = new Call()
                     {
@@ -75,6 +82,8 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
                         ToNo = notification.Outer.To,
                     };
                     await _callDetailRepository.AddAsync(detail, cancellationToken);
+
+                    await _realtimeService.AlertAsync(workModel.UserId, new AlertDto() { Id = callId, From = telNo, To = notification.Outer.To, CallType = ECallType.ExtToOuter, ConversationId = notification.Outer.Id }, cancellationToken);
                 }
             }
 

+ 7 - 13
src/Hotline.Application/Handlers/CallCenter/CallState/RingVisitorToExtNotificationHandler.cs

@@ -13,15 +13,13 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
         private readonly ICallDetailRepository _callDetailRepository;
         private readonly IRealtimeService _realtimeService;
         private readonly IUserCacheManager _userCacheManager;
-        private readonly ICallCacheManager _callCacheManager;
 
-        public RingVisitorToExtNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IRealtimeService realtimeService, IUserCacheManager userCacheManager, ICallCacheManager callCacheManager)
+        public RingVisitorToExtNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IRealtimeService realtimeService, IUserCacheManager userCacheManager)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
             _realtimeService = realtimeService;
             _userCacheManager = userCacheManager;
-            _callCacheManager = callCacheManager;
         }
 
 
@@ -30,7 +28,7 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
             var model = await _callRepository.GetAsync(
                 x => x.ConversationId == notification.Visitor.Id &&
                      x.FromNo == notification.Visitor.From && x.CreationTime>=DateTime.Now.AddHours(-2),true,x=>x.CreationTime, cancellationToken);
-            var workModel = _userCacheManager.GetWorkByTel(notification.TelNo);
+            
             if (model!=null)
             {
                 model.CallStatus = ECallStatus.Ring;
@@ -48,16 +46,12 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
                 };
                 await _callDetailRepository.AddAsync(detail, cancellationToken);
 
-                //处理排队缓存数据
-                //_callCacheManager.RemoveCallCache(model.Id);
-
                 //调用业务弹屏 通知前端
-                await _realtimeService.RingAsync(workModel.UserId, new Share.Dtos.Realtime.RingDto() { From = notification.Visitor.From, Id = model.Id, To= notification.TelNo, CallType = ECallType.VisitorCallIn }, cancellationToken);
-            }
-            //无记录的情况下
-            else
-            {
-                //var isp = 
+                var workModel = _userCacheManager.GetWorkByTel(notification.TelNo);
+                if (workModel!=null)
+                {
+                    await _realtimeService.RingAsync(workModel.UserId, new Share.Dtos.Realtime.RingDto() { From = notification.Visitor.From, Id = model.Id, To = notification.TelNo, CallType = ECallType.VisitorCallIn }, cancellationToken);
+                }
             }
         }
     }

+ 34 - 1
src/Hotline.Application/Handlers/CallCenter/ExtState/IdleNotificationHandler.cs

@@ -1,9 +1,14 @@
 using Hotline.Caching.Interfaces;
+using Hotline.Caching.Services;
+using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Tels;
+using Hotline.Realtimes;
+using Hotline.Repository.SqlSugar.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;
 using XF.Domain.Cache;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Application.Handlers.CallCenter.ExtState
 {
@@ -12,11 +17,20 @@ namespace Hotline.Application.Handlers.CallCenter.ExtState
         private readonly ITelRepository _telRepository;
         private readonly ITelCacheManager _telCacheManager;
         private readonly ITypedCache<Tel> _typedCache;
-        public IdleNotificationHandler(ITelRepository telRepository, ITelCacheManager telCacheManager, ITypedCache<Tel> typedCache)
+        private readonly IUserCacheManager _userCacheManager;
+        private readonly IRealtimeService _realtimeService;
+        private readonly IDeviceManager _deviceManager;
+        private readonly ITelRestRepository _telRestRepository;
+
+        public IdleNotificationHandler(ITelRepository telRepository, ITelCacheManager telCacheManager, ITypedCache<Tel> typedCache,IUserCacheManager userCacheManager,IRealtimeService realtimeService,IDeviceManager deviceManager,ITelRestRepository telRestRepository)
         {
             _telRepository = telRepository;
             _telCacheManager = telCacheManager;
             _typedCache = typedCache;
+            _userCacheManager = userCacheManager;
+            _realtimeService = realtimeService;
+            _deviceManager = deviceManager;
+            _telRestRepository = telRestRepository;
         }
 
         public async Task Handle(IdleNotification notification, CancellationToken cancellationToken)
@@ -25,6 +39,25 @@ namespace Hotline.Application.Handlers.CallCenter.ExtState
             telModel.TelStatus = ETelStatus.Ready;
             //await _telRepository.UpdateAsync(telModel, cancellationToken);
             _typedCache.Set(notification.TelNo, telModel);
+
+            var iswork = await _userCacheManager.IsWorkingByTelAsync(notification.TelNo, cancellationToken);
+            if (!iswork)
+                throw new UserFriendlyException(notification.TelNo + "未查询到工作记录");
+            var restingTel = await _telRestRepository.GetAsync(d => d.TelId == telModel.Id && !d.EndTime.HasValue, cancellationToken);
+            if (restingTel != null)
+                throw new UserFriendlyException("未查询到分机休息信息");
+
+            foreach (var group in telModel.Groups)
+            {
+                await _deviceManager.AssginConfigGroupAsync(group.No, group.Distribution, new List<string>() { notification.TelNo }, group.Voice, cancellationToken);
+            }
+
+
+            var workModel = _userCacheManager.GetWorkByTel(notification.TelNo);
+            if (workModel != null)
+            {
+                await _realtimeService.IdleAsync(workModel.UserId, cancellationToken);
+            }
         }
     }
 }

+ 16 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/AnswerExtToOuterNotificationHandler.cs

@@ -1,4 +1,7 @@
-using Hotline.CallCenter.Calls;
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;
@@ -9,11 +12,15 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
     {
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
+        private readonly IUserCacheManager _userCacheManager;
+        private readonly IRealtimeService _realtimeService;
 
-        public AnswerExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository)
+        public AnswerExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IUserCacheManager userCacheManager,IRealtimeService realtimeService)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
+            _userCacheManager = userCacheManager;
+            _realtimeService = realtimeService;
         }
 
         public async Task Handle(AnswerExtToOuterNotification notification, CancellationToken cancellationToken)
@@ -37,6 +44,13 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                     ToNo = notification.Outer.To,
                 };
                 await _callDetailRepository.AddAsync(detail, cancellationToken);
+
+                //调用业务通知 通知前端
+                var workModel = _userCacheManager.GetWorkByTel(notification.Outer.From);
+                if (workModel != null)
+                {
+                    await _realtimeService.AnsweredAsync(workModel.UserId, new AnsweredDto() { ConversationId = notification.Outer.Id, From = notification.Outer.From, Id = model.Id, To = notification.Outer.To, CallType = ECallType.ExtToOuter }, cancellationToken);
+                }
             }
         }
     }

+ 11 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/AnswerViisitorToExtNotificationHandler.cs

@@ -1,5 +1,4 @@
 using Hotline.Caching.Interfaces;
-using Hotline.Caching.Services;
 using Hotline.CallCenter.Calls;
 using Hotline.Realtimes;
 using Hotline.Share.Dtos.Realtime;
@@ -14,15 +13,17 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
         private readonly ICallCacheManager _callCacheManager;
+        private readonly IUserCacheManager _userCacheManager;
         private readonly IRealtimeService _realtimeService;
 
 
-        public AnswerViisitorToExtNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,ICallCacheManager callCacheManager,IRealtimeService realtimeService)
+        public AnswerViisitorToExtNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,ICallCacheManager callCacheManager,IUserCacheManager userCacheManager,IRealtimeService realtimeService)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
             _callCacheManager = callCacheManager;
             _realtimeService = realtimeService;
+            _userCacheManager = userCacheManager;
         }
 
         public async Task Handle(AnswerViisitorToExtNotification notification, CancellationToken cancellationToken)
@@ -51,6 +52,14 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                 //处理排队缓存数据
                 _callCacheManager.RemoveCallCache(model.Id);
                 await _realtimeService.CallQueueAsync(_callCacheManager.GetCallQueueList(), cancellationToken);
+
+
+                //调用业务通知 通知前端
+                var workModel = _userCacheManager.GetWorkByTel(notification.TelNo);
+                if (workModel != null)
+                {
+                    await _realtimeService.AnsweredAsync(workModel.UserId, new AnsweredDto() { ConversationId = notification.Visitor.Id, From = notification.Visitor.From, Id = model.Id, To = notification.TelNo, CallType = ECallType.VisitorCallIn }, cancellationToken);
+                }
             }
         }
     }

+ 16 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/AnsweredExtToOuterNotificationHandler.cs

@@ -1,4 +1,7 @@
-using Hotline.CallCenter.Calls;
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;
@@ -9,11 +12,15 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
     {
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
+        private readonly IUserCacheManager _userCacheManager;
+        private readonly IRealtimeService _realtimeService;
 
-        public AnsweredExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository)
+        public AnsweredExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IUserCacheManager userCacheManager,IRealtimeService realtimeService)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
+            _userCacheManager = userCacheManager;
+            _realtimeService = realtimeService;
         }
 
         public async Task Handle(AnsweredExtToOuterNotification notification, CancellationToken cancellationToken)
@@ -38,6 +45,13 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                     ToNo = notification.Outer.To
                 };
                 await _callDetailRepository.AddAsync(detail, cancellationToken);
+
+                //调用业务通知 通知前端
+                var workModel = _userCacheManager.GetWorkByTel(notification.Outer.From);
+                if (workModel != null)
+                {
+                    await _realtimeService.AnsweredAsync(workModel.UserId, new AnsweredDto() { ConversationId = notification.Outer.Id, From = notification.Outer.From, Id = model.Id, To = notification.Outer.To, CallType = ECallType.ExtToOuter }, cancellationToken);
+                }
             }
         }
     }

+ 4 - 1
src/Hotline.Application/Handlers/CallCenter/FlowControl/AnsweredExtToOuterToExtNotificationHandler.cs

@@ -1,4 +1,7 @@
-using Hotline.CallCenter.Calls;
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;

+ 16 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/ByeExtAndOuterOneNotificationHandler.cs

@@ -1,4 +1,7 @@
-using Hotline.CallCenter.Calls;
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;
@@ -9,11 +12,15 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
     {
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
+        private readonly IUserCacheManager _userCacheManager;
+        private readonly IRealtimeService _realtimeService;
 
-        public ByeExtAndOuterOneNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository)
+        public ByeExtAndOuterOneNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository, IUserCacheManager userCacheManager, IRealtimeService realtimeService)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
+            _userCacheManager = userCacheManager;
+            _realtimeService = realtimeService;
         }
 
 
@@ -41,6 +48,13 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                     Recording = notification.Recording,
                 };
                 await _callDetailRepository.AddAsync(detail, cancellationToken);
+
+                //调用业务通知 通知前端
+                var workModel = _userCacheManager.GetWorkByTel(notification.TelNo);
+                if (workModel != null)
+                {
+                    await _realtimeService.ByeAsync(workModel.UserId, new ByeDto() { Id = model.Id }, cancellationToken);
+                }
             }
         }
     }

+ 18 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/ByeExtAndOuterTwoNotificationHandler.cs

@@ -1,4 +1,8 @@
-using Hotline.CallCenter.Calls;
+using Hotline.Caching.Interfaces;
+using Hotline.Caching.Services;
+using Hotline.CallCenter.Calls;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Realtime;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
 using MediatR;
@@ -9,11 +13,15 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
     {
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
+        private readonly IUserCacheManager _userCacheManager;
+        private readonly IRealtimeService _realtimeService;
 
-        public ByeExtAndOuterTwoNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository)
+        public ByeExtAndOuterTwoNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IUserCacheManager userCacheManager,IRealtimeService realtimeService)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
+            _userCacheManager = userCacheManager;
+            _realtimeService = realtimeService;
         }
 
         public async Task Handle(ByeExtAndOuterTwoNotification notification, CancellationToken cancellationToken)
@@ -39,6 +47,14 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                     Recording = notification.Recording
                 };
                 await _callDetailRepository.AddAsync(detail, cancellationToken);
+
+
+                //调用业务通知 通知前端
+                var workModel = _userCacheManager.GetWorkByTel(notification.Outer.From);
+                if (workModel != null)
+                {
+                    await _realtimeService.ByeAsync(workModel.UserId, new ByeDto() { Id = model.Id }, cancellationToken);
+                }
             }
         }
     }

+ 1 - 1
src/Hotline.Application/Handlers/CallCenter/System/BootupNotificationHandler.cs

@@ -38,7 +38,7 @@ namespace Hotline.Application.Handlers.CallCenter.System
 
                 }
                 //轮循还原设备分机组信息
-                await _deviceManager.AssginConfigGroupAsync(groupItem.No, groupItem.Distribution.ToString(), exts, groupItem.Voice,
+                await _deviceManager.AssginConfigGroupAsync(groupItem.No, groupItem.Distribution, exts, groupItem.Voice,
                     cancellationToken);
             }
 

+ 16 - 2
src/Hotline.NewRock/DeviceManager.cs

@@ -330,7 +330,7 @@ namespace Hotline.NewRock
         /// <param name="ext"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task AssginConfigGroupAsync(string groupId, string distribution, List<string> ext, string? voiceFile = "",CancellationToken cancellationToken=default)
+        public async Task AssginConfigGroupAsync(string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "",CancellationToken cancellationToken=default)
         {
             if (!int.TryParse(groupId, out int mId))
                 throw new UserFriendlyException("请输入数字");
@@ -341,9 +341,23 @@ namespace Hotline.NewRock
             var groupModel = new Group()
             {
                 Id = groupId,
-                Distribution = distribution,
                 Ext = ext,
             };
+            switch (distribution)
+            {
+                case EDistribution.Sequential:
+                    groupModel.Distribution = "sequential";
+                    break;
+                case EDistribution.Group:
+                    groupModel.Distribution = "group";
+                    break;
+                case EDistribution.Circular:
+                    groupModel.Distribution = "circular";
+                    break;
+                default:
+                    break;
+            }
+
             if (!string.IsNullOrEmpty(voiceFile))
                 groupModel.Voicefile = voiceFile;
 

+ 22 - 0
src/Hotline.Share/Dtos/Realtime/AlertDto.cs

@@ -0,0 +1,22 @@
+using Hotline.Share.Enums.CallCenter;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Realtime
+{
+    public record class AlertDto
+    {
+        public string Id { get; set; }
+
+        public string From { get; set; }
+
+        public string To { get; set; }
+
+        public ECallType CallType { get; set; }
+
+        public string ConversationId { get; set; }
+    }
+}

+ 1 - 1
src/Hotline/Caching/Services/CallCacheManager.cs

@@ -28,7 +28,7 @@ namespace Hotline.Caching.Services
         /// <param name="list"></param>
         public void AddCallCache(Call call)
         {
-            _cacheCall.Set(call.Id, new CallDtoRedis { FromNo = call.FromNo, ToNo = call.ToNo, InGroupTime = DateTime.Now });
+            _cacheCall.Set(call.Id, new CallDtoRedis { FromNo = call.FromNo, ToNo = call.ToNo, InGroupTime = DateTime.Now },TimeSpan.FromSeconds(90)); ;
         }
 
         /// <summary>

+ 1 - 1
src/Hotline/CallCenter/Devices/IDeviceManager.cs

@@ -103,7 +103,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="ext"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task AssginConfigGroupAsync(string groupId, string distribution, List<string> ext, string? voiceFile = "", CancellationToken cancellationToken = default);
+        Task AssginConfigGroupAsync(string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "", CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 更新分机组

+ 4 - 0
src/Hotline/Realtimes/IRealtimeService.cs

@@ -5,6 +5,8 @@ namespace Hotline.Realtimes
 {
     public interface IRealtimeService
     {
+        Task AlertAsync(string userId, AlertDto dto, CancellationToken cancellationToken);
+
         Task RingAsync(string userId, RingDto dto, CancellationToken cancellationToken);
 
         Task AnsweredAsync(string userId, AnsweredDto dto, CancellationToken cancellationToken);
@@ -14,5 +16,7 @@ namespace Hotline.Realtimes
         Task RestApplyPassAsync(string userId, CancellationToken cancellationToken);
 
         Task CallQueueAsync(List<CallDtoRedis> list, CancellationToken cancellationToken);
+
+        Task IdleAsync(string userId, CancellationToken cancellationToken);
     }
 }