dss 2 lat temu
rodzic
commit
7decc68e3a

+ 82 - 1
src/Hotline.Api/Controllers/PbxController.cs

@@ -6,7 +6,9 @@ using Hotline.CallCenter.Manage;
 using Hotline.CallCenter.Tels;
 using Hotline.Permissions;
 using Hotline.Repository.SqlSugar.CallCenter;
+using Hotline.Settings;
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Trunk;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Requests;
 using Hotline.Users;
@@ -35,6 +37,7 @@ namespace Hotline.Api.Controllers
         private readonly IUserCacheManager _userCacheManager;
         private readonly ISessionContext _sessionContext;
         private readonly ICallRepository _callRepository;
+        private readonly ITrunkIvrManagerRepository _trunkIvrManagerRepository;
 
         public PbxController(
             ITelRepository telRepository,
@@ -47,7 +50,8 @@ namespace Hotline.Api.Controllers
             IDeviceManager deviceManager,
             IUserCacheManager userCacheManager,
             ISessionContext sessionContext,
-            ICallRepository callRepository)
+            ICallRepository callRepository,
+            ITrunkIvrManagerRepository trunkIvrManagerRepository)
         {
             _telRepository = telRepository;
             _telDomainService = telDomainService;
@@ -60,6 +64,7 @@ namespace Hotline.Api.Controllers
             _userCacheManager = userCacheManager;
             _sessionContext = sessionContext;
             _callRepository = callRepository;
+            _trunkIvrManagerRepository = trunkIvrManagerRepository;
         }
 
         #region 话机
@@ -584,6 +589,82 @@ namespace Hotline.Api.Controllers
 
         #endregion
 
+        #endregion
+
+        #region 线路管理
+
+        /// <summary>
+        /// 获取线路列表
+        /// </summary>
+        /// <returns></returns>
+        [Permission(EPermission.GetTrunkList)]
+        [HttpGet("turnk-list")]
+        public async Task<List<TrunkIvrManager>> GetTrunkList()
+        {
+            return await _trunkIvrManagerRepository.QueryAsync();
+        }
+
+        /// <summary>
+        /// 获取线路对象
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [Permission(EPermission.GetTrunk)]
+        [HttpGet("trunk/{id}")]
+        public async Task<TrunkIvrManager> GetTrunk(string id)
+        {
+            var trunk = await _trunkIvrManagerRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (trunk is null)
+                throw UserFriendlyException.SameMessage("无效线路");
+            return trunk;
+        }
+
+        /// <summary>
+        /// 新增线路
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.AddTrunk)]
+        [HttpPost("addtrunk")]
+        public async Task AddTrunk([FromBody] AddTrunkDto dto)
+        {
+            var trunk = _mapper.Map<TrunkIvrManager>(dto);
+            await _trunkIvrManagerRepository.AddAsync(trunk, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 修改线路
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.UpdateTrunk)]
+        [HttpPost("updatetrunk")]
+        public async Task UpdateTrunk([FromBody] UpdateTrunkDto dto)
+        {
+            var trunk = await _trunkIvrManagerRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
+            if (trunk is null)
+                throw UserFriendlyException.SameMessage("无效线路");
+
+            _mapper.Map(dto, trunk);
+            await _trunkIvrManagerRepository.UpdateAsync(trunk, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 删除线路
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [Permission(EPermission.RemoveTrunk)]
+        [HttpGet("removetrunk/{id}")]
+        public async Task RemoveTrunk(string id)
+        {
+            var trunk = await _trunkIvrManagerRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (trunk is null)
+                throw UserFriendlyException.SameMessage("无效线路");
+            await _trunkIvrManagerRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
+        }
+
+
         #endregion
     }
 }

+ 2 - 1
src/Hotline.Api/Controllers/SettingController.cs

@@ -17,6 +17,7 @@ namespace Hotline.Api.Controllers
         private readonly ISystemSettingRepository _systemSettingsRepository;
         private readonly ISystemSettingGroupRepository _systemSettingGroupRepository;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+        
 
         public SettingController(IVoiceFileDomainService voiceFileDomainService, ISystemSettingRepository systemSettingsRepository, ISystemSettingGroupRepository systemSettingGroupRepository,ISystemSettingCacheManager systemSettingCacheManager)
         {
@@ -92,7 +93,7 @@ namespace Hotline.Api.Controllers
 
         #endregion
 
-
+       
 
     }
 }

+ 7 - 0
src/Hotline.Api/Controllers/SysController.cs

@@ -1,12 +1,15 @@
 using Hotline.Permissions;
+using Hotline.Repository.SqlSugar.System;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Dic;
 using Hotline.Share.Dtos.Menu;
+using Hotline.Share.Dtos.Trunk;
 using Hotline.Share.Requests;
 using MapsterMapper;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
+using System.Diagnostics.CodeAnalysis;
 using XF.Domain.Exceptions;
 using XF.Utility.UnifyResponse;
 
@@ -24,6 +27,7 @@ namespace Hotline.Api.Controllers
         private readonly ISystemButtonRepository _systemButtonRepository;
         private readonly ISysDicTypeRepository _sysDicTypeRepository;
         private readonly ISysDicDataRepository _sysDicDataRepository;
+        
 
         /// <summary>
         /// 系统管理相关接口
@@ -348,5 +352,8 @@ namespace Hotline.Api.Controllers
         }
 
         #endregion
+
+
+       
     }
 }

+ 28 - 0
src/Hotline.Api/Permissions/EPermission.cs

@@ -240,6 +240,7 @@ namespace Hotline.Permissions
         [Display(GroupName ="系统设置",Name ="修改字典数据",Description ="修改字典数据")]
         UpdateDicData = 100604,
         #endregion
+        
         #endregion
 
         #region 通话相关接口(200)
@@ -405,6 +406,33 @@ namespace Hotline.Permissions
         #endregion
         #endregion
 
+        #region 线路IVR管理
+        /// <summary>
+        /// 获取线路管理列表
+        /// </summary>
+        [Display(GroupName = "系统设置", Name = "线路管理", Description = "线路管理")]
+        GetTrunkList = 300500,
+        /// <summary>
+        /// 获取线路对象
+        /// </summary>
+        [Display(GroupName = "系统设置", Name = "获取线路对象", Description = "获取线路对象")]
+        GetTrunk = 300501,
+        /// <summary>
+        /// 新增线路
+        /// </summary>
+        [Display(GroupName = "系统设置", Name = "新增线路", Description = "新增线路")]
+        AddTrunk = 300502,
+        /// <summary>
+        /// 修改线路
+        /// </summary>
+        [Display(GroupName = "系统设置", Name = "修改线路", Description = "修改线路")]
+        UpdateTrunk = 300503,
+        /// <summary>
+        /// 删除线路
+        /// </summary>
+        [Display(GroupName = "系统设置", Name = "删除线路", Description = "删除线路")]
+        RemoveTrunk = 300504,
+        #endregion
         #endregion
 
         #region 公用(999)

+ 42 - 6
src/Hotline.Application/Handlers/CallCenter/CallState/AlertExtToOuterNotificationHandler.cs

@@ -1,6 +1,8 @@
-using Hotline.CallCenter.Calls;
+using Hotline.Caches;
+using Hotline.CallCenter.Calls;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications;
+using Hotline.Tools;
 using MediatR;
 
 namespace Hotline.Application.Handlers.CallCenter.CallState
@@ -9,20 +11,22 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
     {
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
+        private readonly IUserCacheManager _userCacheManager;
 
-
-        public AlertExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository)
+        public AlertExtToOuterNotificationHandler(ICallRepository callRepository, ICallDetailRepository callDetailRepository,IUserCacheManager userCacheManager)
         {
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
+            _userCacheManager = userCacheManager;
         }
 
         public async Task Handle(AlertExtToOuterNotification notification, CancellationToken cancellationToken)
         {
-            if (!string.IsNullOrEmpty(notification.TelNo))
+            string telNo = notification.Outer.From != "" ? notification.Outer.From : notification.TelNo;
+            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), cancellationToken);
-
+                //如果存在
                 if (model!=null)
                 {
                     model.CallStatus = ECallStatus.Alert;
@@ -39,7 +43,39 @@ namespace Hotline.Application.Handlers.CallCenter.CallState
                     };
                     await _callDetailRepository.AddAsync(detail, cancellationToken);
                 }
-
+                //如果不存在
+                else
+                {
+                    var workModel = _userCacheManager.GetWorkByTel(telNo);
+                    var isp = PhoneIspTool.GetPhoneIsp(notification.Outer.To);
+                    var callModel = new Call()
+                    {
+                        CallStatus = ECallStatus.Alert,
+                        CallDirection = ECallDirection.Out,
+                        CallType = ECallType.ExtToOuter,
+                        ConversationId = notification.Outer.Id,
+                        FromNo = telNo,
+                        ToNo = notification.Outer.To,
+                        Trunk = notification.Outer.Trunk,
+                        UserId = workModel?.UserId,
+                        UserName = workModel?.UserName,
+                        PhoneIsp = isp
+                    };
+                    callModel.Modified();
+                    var callId = await _callRepository.AddAsync(callModel, cancellationToken);
+                    //写入明细
+                    var detail = new CallDetail()
+                    {
+                        CallId = callId,
+                        CallStatus = ECallStatus.Alert,
+                        ConversationId = notification.Outer.Id,
+                        OMCallId = notification.Outer.CallId,
+                        EventName = "ALERT",
+                        FromNo = telNo,
+                        ToNo = notification.Outer.To,
+                    };
+                    await _callDetailRepository.AddAsync(detail, cancellationToken);
+                }
             }
 
         }

+ 1 - 0
src/Hotline.Application/Handlers/CallCenter/FlowControl/IncomingNotificationHandler.cs

@@ -106,6 +106,7 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                             Visitor = new VisitorToMenuVisitor() { Id = notification.Visitor.Id }
                         },
                         _options.Value.ReceiveKey, _options.Value.Expired, cancellationToken);
+                    //处理队列
                 }
                 else
                 {

+ 19 - 0
src/Hotline.Repository.SqlSugar/System/TrunkIvrManagerRepository.cs

@@ -0,0 +1,19 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Settings;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.System
+{
+    public class TrunkIvrManagerRepository : BaseRepository<TrunkIvrManager>, ITrunkIvrManagerRepository, IScopeDependency
+    {
+        public TrunkIvrManagerRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
+        {
+        }
+    }
+}

+ 28 - 0
src/Hotline.Share/Dtos/Trunk/TrunkDto.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Trunk
+{
+    public class AddTrunkDto
+    {
+        public string TurnkId { get; set; }
+        public string MorningBegin { get; set; }
+        public string MorningEnd { get;set; }
+        public string AfterBegin { get; set; }
+        public string AfterEnd { get; set; }
+        public string WorkDay { get; set; }
+        public string WorkCategory { get; set; }
+        public string RestCategory { get; set; }
+        public string WorkToGroup { get; set; }
+        public string RestToGroup { get; set; }
+        public bool IsEnable { get; set; }
+    }
+
+    public class UpdateTrunkDto:AddTrunkDto
+    {
+        public string Id { get; set; }
+    }
+}

+ 16 - 9
src/Hotline/Caches/CallCacheManager.cs

@@ -6,10 +6,10 @@ namespace Hotline.Caches
 {
     public class CallCacheManager:ICallCacheManager, IScopeDependency
     {
-        private readonly ITypedCache<IReadOnlyList<Call>> _cacheCall;
+        private readonly ITypedCache<List<Call>> _cacheCall;
         private const string CallKey = "CallQueue";
 
-        public CallCacheManager(ITypedCache<IReadOnlyList<Call>> cacheCall)
+        public CallCacheManager(ITypedCache<List<Call>> cacheCall)
         {
             _cacheCall = cacheCall;
         }
@@ -18,17 +18,24 @@ namespace Hotline.Caches
         /// 获取队列
         /// </summary>
         /// <returns></returns>
-        public IReadOnlyList<Call> GetCallQueueList()
+        public List<Call>? GetCallQueueList()
         {
-            return _cacheCall.Get(CallKey)??new List<Call>();
+            var list = _cacheCall.GetOrAdd(CallKey, k =>
+            {
+                return new List<Call>();
+            });
+            return list;
         }
 
-        /// <summary>
-        /// 新增或修改队列
-        /// </summary>
-        /// <param name="list"></param>
-        public void AddOrUpdateCallCache(List<Call> list)
+        
+        public void AddCallCache(Call call)
         {
+            var list = GetCallQueueList();
+            if (list==null)
+            {
+                list = new List<Call>();
+            }
+            list.Add(call);
             _cacheCall.AddOrUpdate(CallKey, list);
         }
 

+ 2 - 2
src/Hotline/Caches/ICallCacheManager.cs

@@ -9,9 +9,9 @@ namespace Hotline.Caches
 {
     public interface ICallCacheManager
     {
-        IReadOnlyList<Call> GetCallQueueList();
+        List<Call>? GetCallQueueList();
 
-        void AddOrUpdateCallCache(List<Call> list);
+        void AddCallCache(Call call);
 
         void RemoveCallCache(string id);
     }

+ 9 - 0
src/Hotline/Settings/ITrunkIvrManagerRepository.cs

@@ -0,0 +1,9 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Settings
+{
+    public interface ITrunkIvrManagerRepository: IRepository<TrunkIvrManager>
+    {
+
+    }
+}

+ 64 - 0
src/Hotline/Settings/TrunkIvrManager.cs

@@ -0,0 +1,64 @@
+using SqlSugar;
+using System.ComponentModel;
+using XF.Domain.Repository;
+
+namespace Hotline.Settings
+{
+    [Description("线路IVR配置")]
+    public class TrunkIvrManager: CreationEntity
+    {
+        /// <summary>
+        /// 线路ID
+        /// </summary>
+        public string TrunkId { get; set; }
+
+        /// <summary>
+        /// 早上开始时间
+        /// </summary>
+        public string MorningBegin { get; set; }
+
+        /// <summary>
+        /// 早上结束时间
+        /// </summary>
+        public string MorningEnd { get; set; }
+
+        /// <summary>
+        /// 下午开始时间
+        /// </summary>
+        public string AfterBegin { get; set; }    
+
+        /// <summary>
+        /// 下午结束时间
+        /// </summary>
+        public string AfterEnd { get; set; }
+
+        /// <summary>
+        /// 工作日
+        /// </summary>
+        public string WorkDay { get; set; }
+
+        /// <summary>
+        /// 工作时间IVR
+        /// </summary>
+        [SugarColumn(IsNullable = true)]
+        public string WorkCategory { get; set; }
+
+        /// <summary>
+        /// 休息时间IVR
+        /// </summary>
+        [SugarColumn(IsNullable = true)]
+        public string RestCategory { get; set; }
+
+        /// <summary>
+        /// 工作时间直接转分机组
+        /// </summary>
+        [SugarColumn(IsNullable = true)]
+        public string WorkToGroup { get; set; }
+
+        /// <summary>
+        /// 休息时间直接转分机组
+        /// </summary>
+        [SugarColumn(IsNullable = true)]
+        public string RestToGroup { get; set; }
+    }
+}