Parcourir la source

merge xingtang to dev

xf il y a 10 mois
Parent
commit
2a8b9f671c
62 fichiers modifiés avec 1067 ajouts et 530 suppressions
  1. 7 0
      Hotline.sln
  2. 1 0
      src/Hotline.Api/Controllers/AiController.cs
  3. 15 15
      src/Hotline.Api/Controllers/HomeController.cs
  4. 35 30
      src/Hotline.Api/Controllers/PbxController.cs
  5. 3 1
      src/Hotline.Api/Controllers/ReportController.cs
  6. 30 24
      src/Hotline.Api/Controllers/TelController.cs
  7. 48 4
      src/Hotline.Api/Controllers/TestController.cs
  8. 82 81
      src/Hotline.Api/Controllers/TestSdkController.cs
  9. 39 20
      src/Hotline.Api/Controllers/UserController.cs
  10. 50 23
      src/Hotline.Api/StartupExtensions.cs
  11. 16 4
      src/Hotline.Api/StartupHelper.cs
  12. 14 2
      src/Hotline.Api/config/appsettings.Development.json
  13. 4 3
      src/Hotline.Application/CallCenter/Calls/CurrentWaitNumService.cs
  14. 3 2
      src/Hotline.Application/CallCenter/Calls/TelsStatusRefreshService.cs
  15. 1 1
      src/Hotline.Application/CallCenter/Calls/TrApplication.cs
  16. 10 9
      src/Hotline.Application/Handlers/CallCenter/BaseHandler.cs
  17. 1 0
      src/Hotline.Application/Handlers/CallCenter/CallState/DtmfNotificationHandler.cs
  18. 10 2
      src/Hotline.Application/Handlers/CallCenter/ExtState/IdleNotificationHandler.cs
  19. 1 0
      src/Hotline.Application/Handlers/CallCenter/FlowControl/EndOfAnnOuterToMenuNotificationHandler.cs
  20. 1 0
      src/Hotline.Application/Handlers/CallCenter/FlowControl/EndOfAnnVisitorToMenuNotificationHandler.cs
  21. 3 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/IncomingNotificationHandler.cs
  22. 3 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/InviteNotificationHandler.cs
  23. 9 3
      src/Hotline.Application/Handlers/CallCenter/System/BootupNotificationHandler.cs
  24. 1 0
      src/Hotline.Application/Hotline.Application.csproj
  25. 112 0
      src/Hotline.Application/Jobs/GetCallsJob.cs
  26. 0 35
      src/Hotline.Application/Jobs/ReloadTotalsJob.cs
  27. 30 4
      src/Hotline.Application/Mappers/CallMapperConfigs.cs
  28. 139 130
      src/Hotline.NewRock/DeviceManager.cs
  29. 9 7
      src/Hotline.NewRock/Handlers/DeviceEventHandler.cs
  30. 13 0
      src/Hotline.NewRock/IDeviceEventHandler.cs
  31. 9 4
      src/Hotline.NewRock/NewRockStartupExtensions.cs
  32. 24 0
      src/Hotline.Repository.SqlSugar/Extensions/XingTangDbExtensions.cs
  33. 8 0
      src/Hotline.Repository.SqlSugar/XingTangDbContext.cs
  34. 5 0
      src/Hotline.Share/Dtos/Users/UserDto.cs
  35. 5 3
      src/Hotline.Wex/WexStartupExtensions.cs
  36. 1 1
      src/Hotline.Wex/WexTokenManager.cs
  37. 20 11
      src/Hotline/CallCenter/Calls/CallDomainService.cs
  38. 3 1
      src/Hotline/CallCenter/Calls/TrCallRecord.cs
  39. 14 0
      src/Hotline/CallCenter/Configs/CallCenterConfiguration.cs
  40. 2 2
      src/Hotline/CallCenter/Configs/NewRockConfiguration.cs
  41. 2 2
      src/Hotline/CallCenter/Configs/TianrunConfiguration.cs
  42. 1 1
      src/Hotline/CallCenter/Configs/WexConfiguration.cs
  43. 7 0
      src/Hotline/CallCenter/Configs/XingTangConfiguration.cs
  44. 0 10
      src/Hotline/CallCenter/Devices/CallCenterConfiguration.cs
  45. 41 40
      src/Hotline/CallCenter/Devices/IDeviceManager.cs
  46. 0 8
      src/Hotline/CallCenter/Devices/WexConfiguration.cs
  47. 0 12
      src/Hotline/CallCenter/IDeviceEventHandler.cs
  48. 7 2
      src/Hotline/CallCenter/Ivrs/IvrDomainService.cs
  49. 8 4
      src/Hotline/CallCenter/Manage/VoiceFileDomainService.cs
  50. 2 3
      src/Hotline/CallCenter/Tels/Tel.cs
  51. 9 8
      src/Hotline/CallCenter/Tels/TelDomainService.cs
  52. 1 1
      src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs
  53. 1 1
      src/Hotline/FlowEngine/Workflows/Workflow.cs
  54. 2 1
      src/Hotline/Orders/Order.cs
  55. 5 0
      src/Hotline/Users/User.cs
  56. 12 8
      src/Hotline/Users/UserDomainService.cs
  57. 1 1
      src/NewRock.Sdk/Security/AuthorizeGenerator.cs
  58. 1 0
      src/XF.Domain.Repository/Entity.cs
  59. 4 2
      src/XF.Domain/Dependency/DependencyInjectionExtensions.cs
  60. 6 0
      src/XF.Domain/Dependency/IIgnoreDependency.cs
  61. 13 0
      src/XingTang.Sdk/XingTang.Sdk.csproj
  62. 163 0
      src/XingTang.Sdk/XingtangCall.cs

+ 7 - 0
Hotline.sln

@@ -49,6 +49,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hotline.Ai.Jths", "src\Hotl
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hotline.YbEnterprise.Sdk", "src\Hotline.YbEnterprise.Sdk\Hotline.YbEnterprise.Sdk.csproj", "{C3F289D5-C50B-46DB-852C-9543EF9B0355}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XingTang.Sdk", "src\XingTang.Sdk\XingTang.Sdk.csproj", "{CF2A8B80-FF4E-4291-B383-D735BB629F32}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -123,6 +125,10 @@ Global
 		{C3F289D5-C50B-46DB-852C-9543EF9B0355}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C3F289D5-C50B-46DB-852C-9543EF9B0355}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C3F289D5-C50B-46DB-852C-9543EF9B0355}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CF2A8B80-FF4E-4291-B383-D735BB629F32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CF2A8B80-FF4E-4291-B383-D735BB629F32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CF2A8B80-FF4E-4291-B383-D735BB629F32}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CF2A8B80-FF4E-4291-B383-D735BB629F32}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -149,6 +155,7 @@ Global
 		{EEF30056-A626-43B2-9762-632935C1AF31} = {25C73963-4D5E-4654-804A-D2E2D360134B}
 		{1634234A-379C-44DC-BFEC-7BBDEF50B47B} = {D041C554-B78E-4AAF-B597-E309DC8EEF4F}
 		{C3F289D5-C50B-46DB-852C-9543EF9B0355} = {D041C554-B78E-4AAF-B597-E309DC8EEF4F}
+		{CF2A8B80-FF4E-4291-B383-D735BB629F32} = {D041C554-B78E-4AAF-B597-E309DC8EEF4F}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {4B8EA790-BD13-4422-8D63-D6DBB77B823F}

+ 1 - 0
src/Hotline.Api/Controllers/AiController.cs

@@ -689,6 +689,7 @@ namespace Hotline.Api.Controllers
                                 aiOrderVisitDetail.OrderVisit.VisitTime = DateTime.Now;
                                 aiOrderVisitDetail.OrderVisit.RecordUrl = recordUrl;
                                 aiOrderVisitDetail.OrderVisit.IsPutThrough = true;
+                                aiOrderVisitDetail.OrderVisit.RecordUrl = recordUrl;
                                 aiOrderVisitDetail.OrderVisit.VisitType = Share.Enums.Order.EVisitType.ChipVoiceVisit;
                                 aiOrderVisitDetail.OrderVisit.AiVisitTime();
                                 aiOrderVisitDetail.IsSuccess = true;

+ 15 - 15
src/Hotline.Api/Controllers/HomeController.cs

@@ -86,21 +86,21 @@ public class HomeController : BaseController
         throw UserFriendlyException.SameMessage("无效登录信息");
     }
 
-    [AllowAnonymous]
-    [HttpGet("createdb")]
-    public Task CreateDb()
-    {
-        var db = _uow.Db;
-        db.DbMaintenance.CreateDatabase();
-        //db.CodeFirst.InitTables<Blacklist,Call,CallDetail,CallRecord,TelHold>();
-        //db.CodeFirst.InitTables<Ivr, IvrCategory, Tel, TelGroup, TelRest>();
-        db.CodeFirst.InitTables<KnowledgeType>();
-        //db.CodeFirst.InitTables<KnowledgeType, Orders.Order, OrderTemporary, OrgUser>();
-        //db.CodeFirst.InitTables<SystemAuthority, SystemButton, SystemDataAuthority, SystemDataTable, SystemMenu>();
-        //db.CodeFirst.InitTables<SystemOrganize, SystemSetting, SystemSettingGroup, UserFastMenu>();
-        //db.CodeFirst.InitTables<User, Work,SysDicType,SysDicData, TrunkIvrManager>();
-        return Task.CompletedTask;
-    }
+    //[AllowAnonymous]
+    //[HttpGet("createdb")]
+    //public Task CreateDb()
+    //{
+    //    var db = _uow.Db;
+    //    db.DbMaintenance.CreateDatabase();
+    //    //db.CodeFirst.InitTables<Blacklist,Call,CallDetail,CallRecord,TelHold>();
+    //    //db.CodeFirst.InitTables<Ivr, IvrCategory, Tel, TelGroup, TelRest>();
+    //    db.CodeFirst.InitTables<KnowledgeType>();
+    //    //db.CodeFirst.InitTables<KnowledgeType, Orders.Order, OrderTemporary, OrgUser>();
+    //    //db.CodeFirst.InitTables<SystemAuthority, SystemButton, SystemDataAuthority, SystemDataTable, SystemMenu>();
+    //    //db.CodeFirst.InitTables<SystemOrganize, SystemSetting, SystemSettingGroup, UserFastMenu>();
+    //    //db.CodeFirst.InitTables<User, Work,SysDicType,SysDicData, TrunkIvrManager>();
+    //    return Task.CompletedTask;
+    //}
 
     /// <summary>
     /// 获取可选快捷入口

+ 35 - 30
src/Hotline.Api/Controllers/PbxController.cs

@@ -23,9 +23,11 @@ using XF.Domain.Constants;
 using XF.Domain.Exceptions;
 using XF.Utility.EnumExtensions;
 using System.Linq;
+using Hotline.CallCenter.Configs;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.Share.Dtos;
 using Microsoft.AspNetCore.Authorization;
+using Microsoft.Extensions.Options;
 using XF.Domain.Repository;
 using Tr.Sdk;
 
@@ -59,6 +61,7 @@ namespace Hotline.Api.Controllers
         private readonly IRepository<User> _userRepository;
         private readonly IWexClient _wexClient;
         private readonly IWexTelGroupRepository _wexTelGroupRepository;
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
         private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
 
 
@@ -86,6 +89,7 @@ namespace Hotline.Api.Controllers
             IRepository<User> userRepository,
             IWexClient wexClient,
             IWexTelGroupRepository wexTelGroupRepository,
+            IOptionsSnapshot<CallCenterConfiguration> options,
             ISystemDicDataCacheManager systemDicDataCacheManager)
         {
             _telRepository = telRepository;
@@ -111,6 +115,7 @@ namespace Hotline.Api.Controllers
             _userRepository = userRepository;
             _wexClient = wexClient;
             _wexTelGroupRepository = wexTelGroupRepository;
+            _options = options;
             _systemDicDataCacheManager = systemDicDataCacheManager;
         }
 
@@ -197,7 +202,7 @@ namespace Hotline.Api.Controllers
             var works = await _workRepository.QueryAsync(d => dto.TelNos.Contains(d.TelNo) && !d.EndTime.HasValue);
 
             await _deviceManager.AssginConfigGroupAsync(
-                dto.No,
+                _options.Value.NewRock, dto.No,
                 dto.Distribution,
                 ext: works.Select(d => d.TelNo).ToList(),
                 voiceFile: dto.Voice ?? null,
@@ -221,7 +226,7 @@ namespace Hotline.Api.Controllers
             var works = await _workRepository.QueryAsync(d => dto.TelNos.Contains(d.TelNo) && !d.EndTime.HasValue);
 
             await _deviceManager.AssginConfigGroupAsync(
-                dto.No,
+                _options.Value.NewRock, dto.No,
                 dto.Distribution,
                 ext: works.Select(d => d.TelNo).ToList(),
                 voiceFile: dto.Voice ?? null,
@@ -479,7 +484,7 @@ namespace Hotline.Api.Controllers
                 throw UserFriendlyException.SameMessage("转接分机未进行工作");
 
             //判断分机状态
-            var telState = await _deviceManager.QueryTelState(dto.TelNo, HttpContext.RequestAborted);
+            var telState = await _deviceManager.QueryTelState(_options.Value.NewRock, dto.TelNo, HttpContext.RequestAborted);
             if (telState != ETelStatus.Ready)
                 throw UserFriendlyException.SameMessage("被叫分机不在线或正在通话中");
 
@@ -487,7 +492,7 @@ namespace Hotline.Api.Controllers
             if (isRest)
                 throw new UserFriendlyException("被叫分机正在休息不能转接");
 
-            await _deviceManager.ExtToExtAsync(work.TelNo, dto.TelNo, HttpContext.RequestAborted);
+            await _deviceManager.ExtToExtAsync(_options.Value.NewRock, work.TelNo, dto.TelNo, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -501,7 +506,7 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            await _deviceManager.ExtToOuterAsync(work.TelNo, dto.OuterNo, HttpContext.RequestAborted);
+            await _deviceManager.ExtToOuterAsync(_options.Value.NewRock, work.TelNo, dto.OuterNo, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -517,7 +522,7 @@ namespace Hotline.Api.Controllers
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
             string newOuter = dto.LineId + "," + dto.OuterNo;
-            await _deviceManager.ExtToOuterAsync(work.TelNo, newOuter, HttpContext.RequestAborted);
+            await _deviceManager.ExtToOuterAsync(_options.Value.NewRock, work.TelNo, newOuter, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -535,7 +540,7 @@ namespace Hotline.Api.Controllers
             if (toWork is null)
                 throw UserFriendlyException.SameMessage("转接分机未进行工作");
 
-            var totelState = await _deviceManager.QueryTelState(dto.TelNo, HttpContext.RequestAborted);
+            var totelState = await _deviceManager.QueryTelState(_options.Value.NewRock, dto.TelNo, HttpContext.RequestAborted);
             if (totelState != ETelStatus.Ready)
                 throw UserFriendlyException.SameMessage("被叫分机不在线或正在通话中");
 
@@ -544,9 +549,9 @@ namespace Hotline.Api.Controllers
                 throw new UserFriendlyException("被叫分机正在休息不能转接");
 
 
-            var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
+            var tel = await _deviceManager.QueryTelAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(tel.ConversationId))
-                await _deviceManager.VisitorToExtAsync(tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
+                await _deviceManager.VisitorToExtAsync(_options.Value.NewRock, tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
             else
                 throw UserFriendlyException.SameMessage("当前分机没有通话");
         }
@@ -562,9 +567,9 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
+            var tel = await _deviceManager.QueryTelAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(tel.ConversationId))
-                await _deviceManager.VisitorToOuterAsync(tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
+                await _deviceManager.VisitorToOuterAsync(_options.Value.NewRock, tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
             else
                 throw UserFriendlyException.SameMessage("当前分机没有通话");
         }
@@ -581,9 +586,9 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
+            var tel = await _deviceManager.QueryTelAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(tel.ConversationId))
-                await _deviceManager.VisitorToGroupAsync(tel.ConversationId, dto.groupid, HttpContext.RequestAborted);
+                await _deviceManager.VisitorToGroupAsync(_options.Value.NewRock, tel.ConversationId, dto.groupid, HttpContext.RequestAborted);
             else
                 throw UserFriendlyException.SameMessage("当前分机没有通话");
         }
@@ -600,9 +605,9 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
+            var tel = await _deviceManager.QueryTelAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(tel.ConversationId))
-                await _deviceManager.OuterToOuterAsync(tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
+                await _deviceManager.OuterToOuterAsync(_options.Value.NewRock, tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
             else
                 throw UserFriendlyException.SameMessage("当前分机没有通话");
         }
@@ -623,7 +628,7 @@ namespace Hotline.Api.Controllers
             if (toWork is null)
                 throw UserFriendlyException.SameMessage("转接分机未进行工作");
 
-            var totelState = await _deviceManager.QueryTelState(dto.TelNo, HttpContext.RequestAborted);
+            var totelState = await _deviceManager.QueryTelState(_options.Value.NewRock, dto.TelNo, HttpContext.RequestAborted);
             if (totelState != ETelStatus.Ready)
                 throw UserFriendlyException.SameMessage("被叫分机不在线或正在通话中");
 
@@ -631,9 +636,9 @@ namespace Hotline.Api.Controllers
             if (isRest)
                 throw new UserFriendlyException("被叫分机正在休息不能转接");
 
-            var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
+            var tel = await _deviceManager.QueryTelAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(tel.ConversationId))
-                await _deviceManager.OuterToExtAsync(tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
+                await _deviceManager.OuterToExtAsync(_options.Value.NewRock, tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
             else
                 throw UserFriendlyException.SameMessage("当前分机没有通话");
         }
@@ -655,9 +660,9 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
+            var tel = await _deviceManager.QueryTelAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(tel.ConversationId))
-                await _deviceManager.ConferenceMeetingAsync(dto.TelNo, HttpContext.RequestAborted);
+                await _deviceManager.ConferenceMeetingAsync(_options.Value.NewRock, dto.TelNo, HttpContext.RequestAborted);
             else
                 throw UserFriendlyException.SameMessage("当前分机没有通话");
         }
@@ -673,7 +678,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("monitor-ext")]
         public async Task MonitorExt([FromBody] MonitorExtRequest request)
         {
-            await _deviceManager.MonitorExtAsync(request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
+            await _deviceManager.MonitorExtAsync(_options.Value.NewRock, request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
         }
 
 
@@ -688,7 +693,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("monitor-ext-to-talk")]
         public async Task MonitorExtToTalk([FromBody] MonitorExtToTalkRequest request)
         {
-            await _deviceManager.MonitorExtToTalkAsync(request.telNo, HttpContext.RequestAborted);
+            await _deviceManager.MonitorExtToTalkAsync(_options.Value.NewRock, request.telNo, HttpContext.RequestAborted);
         }
 
 
@@ -703,7 +708,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("monitor-ext-to-listen")]
         public async Task MonitorExtToListen([FromBody] MonitorExtToListenRequest request)
         {
-            await _deviceManager.MonitorExtToListenAsync(request.telNo, HttpContext.RequestAborted);
+            await _deviceManager.MonitorExtToListenAsync(_options.Value.NewRock, request.telNo, HttpContext.RequestAborted);
         }
 
 
@@ -722,7 +727,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("bargein-ext")]
         public async Task BargeinExt([FromBody] BargeinExtRequest request)
         {
-            await _deviceManager.BargeinExtAsync(request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
+            await _deviceManager.BargeinExtAsync(_options.Value.NewRock, request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
         }
 
         #endregion
@@ -744,7 +749,7 @@ namespace Hotline.Api.Controllers
             //if (call.CallStatus == ECallStatus.Bye)
             //    throw UserFriendlyException.SameMessage("通话已结束");
 
-            await _deviceManager.ClearExtAsync(request.CallId, HttpContext.RequestAborted);
+            await _deviceManager.ClearExtAsync(_options.Value.NewRock, request.CallId, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -761,7 +766,7 @@ namespace Hotline.Api.Controllers
                 throw UserFriendlyException.SameMessage("无效通话,无法挂断");
             if (call.CallStatus == ECallStatus.Bye)
                 throw UserFriendlyException.SameMessage("通话已结束");
-            await _deviceManager.ClearVisitorAsync(call.ConversationId, HttpContext.RequestAborted);
+            await _deviceManager.ClearVisitorAsync(_options.Value.NewRock, call.ConversationId, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -778,7 +783,7 @@ namespace Hotline.Api.Controllers
                 throw UserFriendlyException.SameMessage("无效通话,无法挂断");
             if (call.CallStatus == ECallStatus.Bye)
                 throw UserFriendlyException.SameMessage("通话已结束");
-            await _deviceManager.ClearOuterAsync(call.ConversationId, HttpContext.RequestAborted);
+            await _deviceManager.ClearOuterAsync(_options.Value.NewRock, call.ConversationId, HttpContext.RequestAborted);
         }
 
         #endregion
@@ -795,7 +800,7 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            await _deviceManager.MuteAsync(work.TelNo, HttpContext.RequestAborted);
+            await _deviceManager.MuteAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -808,7 +813,7 @@ namespace Hotline.Api.Controllers
             var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
             if (work is null)
                 throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
-            await _deviceManager.UnMuteAsync(work.TelNo, HttpContext.RequestAborted);
+            await _deviceManager.UnMuteAsync(_options.Value.NewRock, work.TelNo, HttpContext.RequestAborted);
         }
 
         #endregion
@@ -964,7 +969,7 @@ namespace Hotline.Api.Controllers
 
             await _callDetailRepository.AddAsync(detail, HttpContext.RequestAborted);
 
-            await _deviceManager.VisitorToMenuAsync(call.ConversationId, ivr.No, HttpContext.RequestAborted);
+            await _deviceManager.VisitorToMenuAsync(_options.Value.NewRock, call.ConversationId, ivr.No, HttpContext.RequestAborted);
         }
 
         #endregion

+ 3 - 1
src/Hotline.Api/Controllers/ReportController.cs

@@ -1,5 +1,7 @@
 using Hotline.CallCenter;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
+using Hotline.NewRock;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -23,6 +25,6 @@ public class ReportController : ControllerBase
     [HttpGet]
     public async Task ReceiveEvents()
     {
-        await _deviceEventHandler.HandleAsync(Request.Body, _options.Value, HttpContext.RequestAborted);
+        await _deviceEventHandler.HandleAsync(Request.Body, _options.Value.NewRock, HttpContext.RequestAborted);
     }
 }

+ 30 - 24
src/Hotline.Api/Controllers/TelController.cs

@@ -1,11 +1,13 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Devices;
+using Hotline.CallCenter.Tels;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
 using XF.Domain.Authentications;
+using XF.Domain.Repository;
 
 namespace Hotline.Api.Controllers
 {
@@ -14,38 +16,42 @@ namespace Hotline.Api.Controllers
     /// </summary>
     public class TelController : BaseController
     {
-        private readonly IUserCacheManager _userCacheManager;
-        private readonly ITelCacheManager _telCacheManager;
-        private readonly IDeviceManager _deviceManager;
         private readonly IMapper _mapper;
-        private readonly ICallRepository _callRepository;
-        private readonly ISessionContext _sessionContext;
+        private readonly IRepository<Tel> _telRepository;
+        private readonly IRepository<TelGroup> _telGroupRepository;
 
-        /// <summary>
-        /// 构造
-        /// </summary>
-        /// <param name="userCacheManager"></param>
-        /// <param name="telCacheManager"></param>
-        /// <param name="deviceManager"></param>
-        /// <param name="mapper"></param>
-        /// <param name="callRepository"></param>
-        /// <param name="sessionContext"></param>
         public TelController(
-            IUserCacheManager userCacheManager,
-            ITelCacheManager telCacheManager,
-            IDeviceManager deviceManager,
             IMapper mapper,
-            ICallRepository callRepository,
-            ISessionContext sessionContext)
+            IRepository<Tel> telRepository,
+            IRepository<TelGroup> telGroupRepository)
         {
-            _userCacheManager = userCacheManager;
-            _telCacheManager = telCacheManager;
-            _deviceManager = deviceManager;
             _mapper = mapper;
-            _callRepository = callRepository;
-            _sessionContext = sessionContext;
+            _telRepository = telRepository;
+            _telGroupRepository = telGroupRepository;
         }
 
+        /// <summary>
+        /// 查询分机
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        public async Task<IReadOnlyList<TelDto>> Query()
+        {
+            return await _telRepository.Queryable()
+                  .Select<TelDto>()
+                  .ToListAsync(HttpContext.RequestAborted);
+        }
 
+        /// <summary>
+        /// 查询分机组(技能组)
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("groups")]
+        public async Task<IReadOnlyList<TelGroupDto>> QueryTelGroup()
+        {
+            return await _telGroupRepository.Queryable()
+                .Select<TelGroupDto>()
+                .ToListAsync(HttpContext.RequestAborted);
+        }
     }
 }

+ 48 - 4
src/Hotline.Api/Controllers/TestController.cs

@@ -11,6 +11,7 @@ using Hotline.Application.JudicialManagement;
 using Hotline.Application.Quality;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.FlowEngine.WorkflowModules;
@@ -587,6 +588,7 @@ public class TestController : BaseController
             .OrderBy(d => d.CreationTime)
             .ToListAsync(HttpContext.RequestAborted);
 
+        _logger.LogWarning($"取到steps: {steps.Count} 条");
         var updateOrders = new List<Order>();
         foreach (var order in orders)
         {
@@ -621,13 +623,11 @@ public class TestController : BaseController
             updateOrders.Add(order);
         }
 
+        _logger.LogWarning($"更新工单:{updateOrders.Count} 条");
         await _orderRepository.UpdateRangeAsync(updateOrders, HttpContext.RequestAborted);
     }
 
-    /// <summary>
-    /// 赋值handlerId
-    /// </summary>
-    /// <returns></returns>
+
     [AllowAnonymous]
     [HttpPost("t4")]
     public async Task TestExportExcel1()
@@ -744,6 +744,50 @@ public class TestController : BaseController
         await _orderRepository.UpdateRangeAsync(updateOrders, HttpContext.RequestAborted);
     }
 
+    [AllowAnonymous]
+    [HttpGet("t5")]
+    public async Task Test5()
+    {
+        var steps = await _workflowStepRepository.Queryable()
+            .Includes(d => d.WorkflowTrace)
+            .Where(d => d.Status == EWorkflowStepStatus.Handled && d.HandlerOrgAreaCode == null)
+            .ToListAsync(HttpContext.RequestAborted);
+
+        var orgIds = steps.Select(d => d.HandlerOrgId).ToList();
+        var orgs = await _systemOrganizeRepository.Queryable()
+            .Where(d => orgIds.Contains(d.Id))
+            .ToListAsync(HttpContext.RequestAborted);
+
+        var updateSteps = new List<WorkflowStep>();
+        foreach (var step in steps)
+        {
+            var org = orgs.FirstOrDefault(d => d.Id == step.HandlerOrgId);
+            if (org == null)
+            {
+                _logger.LogWarning($"未找到部门,Id:{step.HandlerOrgId}");
+                continue;
+            }
+
+            if (!step.HandlerOrgIsCenter.HasValue)
+                step.HandlerOrgIsCenter = org.IsCenter;
+            if (string.IsNullOrEmpty(step.HandlerOrgAreaCode))
+                step.HandlerOrgAreaCode = org.AreaCode;
+            if (string.IsNullOrEmpty(step.HandlerOrgAreaName))
+                step.HandlerOrgAreaName = org.AreaName;
+
+            step.WorkflowTrace.HandlerOrgIsCenter = step.HandlerOrgIsCenter;
+            step.WorkflowTrace.HandlerOrgAreaCode = step.HandlerOrgAreaCode;
+            step.WorkflowTrace.HandlerOrgAreaName = step.HandlerOrgAreaName;
+
+            updateSteps.Add(step);
+        }
+
+        _logger.LogWarning($"更新数据:{updateSteps.Count} 条");
+        await _workflowStepRepository.UpdateNav(updateSteps)
+            .Include(d => d.WorkflowTrace)
+            .ExecuteCommandAsync();
+    }
+
     [HttpGet("rsa")]
     public async Task<string> Rsa()
     {

+ 82 - 81
src/Hotline.Api/Controllers/TestSdkController.cs

@@ -1,4 +1,5 @@
-using Hotline.CallCenter.Devices;
+using Hotline.CallCenter.Configs;
+using Hotline.CallCenter.Devices;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -48,8 +49,8 @@ namespace Hotline.Api.Controllers
         {
             var result = await _client.QueryDeviceInfo(
                 new QueryDeviceInfoRequest { Attribute = "Query", DeviceInfo = string.Empty },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryDeviceInfoResponse?>(result));
         }
@@ -64,8 +65,8 @@ namespace Hotline.Api.Controllers
         {
             var result = await _client.QueryExt(
                 new QueryExtRequest() { Attribute = "Query", Ext = new Ext() { Id = extid } },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted
             );
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryExtResponse?>(result));
@@ -83,8 +84,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Query",
                 Group = new QueryExtGroup() { Id = groupid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryExtGroupResponse?>(result));
         }
@@ -101,8 +102,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Query",
                 Menu = new QueryMenuMenu() { Id = menuid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryMenuResponse?>(result));
         }
@@ -121,8 +122,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Query",
                 Trunk = new QueryTrunkTrunk() { Id = trunkid }
             },
-               _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+               _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryTrunkResponse?>(result));
         }
@@ -139,8 +140,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Query",
                 Visitor = new QueryVisitorVisitor() { Id = visitorid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryVisitorResponse?>(result));
         }
@@ -158,8 +159,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Query",
                 Outer = new QueryOuterOuter() { Id = outerid }
             },
-               _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+               _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<QueryOuterResponse?>(result));
         }
@@ -183,8 +184,8 @@ namespace Hotline.Api.Controllers
                 {
                     Id = extid
                 },
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -203,8 +204,8 @@ namespace Hotline.Api.Controllers
                 {
                     Id = visitorId
                 }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -223,8 +224,8 @@ namespace Hotline.Api.Controllers
                 {
                     Id = outerId
                 }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -261,8 +262,8 @@ namespace Hotline.Api.Controllers
                     Api = "7"
                 }
             },
-           _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+           _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
             HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<AssginConfigExtResponse?>(result));
         }
@@ -289,8 +290,8 @@ namespace Hotline.Api.Controllers
                         "210"
                     }
                 }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
             HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<AssginConfigGroupResponse?>(result));
         }
@@ -313,8 +314,8 @@ namespace Hotline.Api.Controllers
                     Repeat = "3",
                     InfoLength = "5",
                 }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -333,8 +334,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Hold",
                 Ext = new Ext() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             //_logger.LogInformation(result.Manufacturer);
         }
@@ -350,8 +351,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Unhold",
                 Ext = new Ext() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -371,8 +372,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Mute",
                 Ext = new Ext() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -388,8 +389,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Unmute",
                 Ext = new Ext() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -414,8 +415,8 @@ namespace Hotline.Api.Controllers
                         new ExtToExtExt() { Id = fromextid },
                         new ExtToExtExt() { Id = toextid }
                     }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize(result));
         }
@@ -433,8 +434,8 @@ namespace Hotline.Api.Controllers
                 Ext = new ExtToOuterExtRequest() { Id = fromextid },
                 Outer = new ExtToOuterOuterRequest() { To = to }
             },
-               _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+               _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -450,8 +451,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Connect",
                 Visitor = new VisitorToExtVisitor() { Id = visid },
                 Ext = new VisitorToExtExt() { Id = toextid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -471,8 +472,8 @@ namespace Hotline.Api.Controllers
                 Visitor = new VisitorToOuterVisitor() { Id = visid },
                 Outer = new VisitorToOuterOuter() { To = outerphonenum, Display = display },
 
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -490,8 +491,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Connect",
                 Visitor = new VisitorToMenuVisitor() { Id = visid },
                 Menu = new VisitorToMenuMenu() { Id = menuid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -510,8 +511,8 @@ namespace Hotline.Api.Controllers
                 Outer = new OuterToExtOuter() { Id = outer },
                 Ext = new OuterToExtExt() { Id = extid }
             },
-               _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+               _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -529,8 +530,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Connect",
                 Outer = new List<OuterToOuterOuterModel>() { new OuterToOuterOuterModel() { Id = outerid }, new OuterToOuterOuterModel() { To = outerphonenum } },
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -548,8 +549,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Connect",
                 Outer = new OuterToMenuOuter() { Id = outerid },
                 Menu = new OuterToMenuMenu() { Id = menuid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -567,8 +568,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Connect",
                 Menu = new MenuToExtMenu() { Id = menuid },
                 Ext = new MenuToExtExt() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -586,8 +587,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Connect",
                 Menu = new MenuToOuterMenu() { Id = menuid },
                 Outer = new MenuToOuterOuter() { To = outernum }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -609,8 +610,8 @@ namespace Hotline.Api.Controllers
                         new TwoWayOuterOuter(){ To = outerone},
                         new TwoWayOuterOuter(){ To = outertwo}
                     }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -630,8 +631,8 @@ namespace Hotline.Api.Controllers
                 Ext = new VoiceNewsFlashExt() { Id = extid }
             };
 
-            var result = await _client.VoiceNewsFlash(model, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            var result = await _client.VoiceNewsFlash(model, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -651,8 +652,8 @@ namespace Hotline.Api.Controllers
                 Visitor = new VoiceNewsFlashVisitor() { Id = visiitorid }
             };
 
-            var result = await _client.VoiceNewsFlash(model, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            var result = await _client.VoiceNewsFlash(model, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -672,8 +673,8 @@ namespace Hotline.Api.Controllers
                 Outer = new VoiceNewsFlashOuter() { Id = outerid }
             };
 
-            var result = await _client.VoiceNewsFlash(model, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            var result = await _client.VoiceNewsFlash(model, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -695,8 +696,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Conference",
                 Ext = new ConferenceMeetingExt() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -719,8 +720,8 @@ namespace Hotline.Api.Controllers
                 Attribute = "Queue",
                 Visitor = new VisitorToExtQueueVisitor() { Id = visitorid },
                 Ext = new VisitorToExtQueueExt() { Id = extid }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -739,8 +740,8 @@ namespace Hotline.Api.Controllers
                 Visitor = new VisitorToGroupQueueVisitor() { Id = visitorid },
                 Group = new VisitorToGroupQueueGroup() { Id = groupid }
             },
-               _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+               _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -762,8 +763,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Query",
                 VoiceFile = ""
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
             _logger.LogInformation(System.Text.Json.JsonSerializer.Serialize<VoiceQueryListResponse?>(result));
         }
@@ -780,8 +781,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Remove",
                 VoiceFile = voiceFile
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
                 HttpContext.RequestAborted);
         }
 
@@ -802,8 +803,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Monitor",
                 Exts = new List<Ext>() { new Ext() { Id = firstTelNo }, new Ext() { Id = secondTelNo } }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
              HttpContext.RequestAborted) ;
         }
 
@@ -822,8 +823,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Talk",
                 Ext = new Ext() { Id=telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
               HttpContext.RequestAborted);
         }
 
@@ -842,8 +843,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "Listen",
                 Ext = new Ext() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
              HttpContext.RequestAborted);
         }
 
@@ -869,8 +870,8 @@ namespace Hotline.Api.Controllers
             {
                 Attribute = "BargeinExt",
                 Exts = new List<Ext>() { new Ext() { Id=firstTelNo },new Ext() { Id=secondTelNo } }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, _options.Value.NewRock.ReceiveKey,
+                _options.Value.NewRock.Expired,
              HttpContext.RequestAborted);
         }
 

+ 39 - 20
src/Hotline.Api/Controllers/UserController.cs

@@ -88,7 +88,8 @@ public class UserController : BaseController
     public async Task<PagedDto<RestDto>> RestApplyList([FromQuery] RestPagedDto dto)
     {
         var (total, items) = await _telRestRepository.Queryable(includeDeleted: false)
-            .WhereIF(!string.IsNullOrEmpty(dto.KeyWords), d => d.UserName.Contains(dto.KeyWords) || d.StaffNo.Contains(dto.KeyWords))
+            .WhereIF(!string.IsNullOrEmpty(dto.KeyWords),
+                d => d.UserName.Contains(dto.KeyWords) || d.StaffNo.Contains(dto.KeyWords))
             .WhereIF(dto.BeginTime != null && dto.BeginTime != DateTime.MinValue, d => d.CreationTime >= dto.BeginTime)
             .WhereIF(dto.EndTime != null && dto.EndTime != DateTime.MinValue, d => d.CreationTime <= dto.EndTime)
             .WhereIF(!string.IsNullOrEmpty(dto.Reason), d => d.Reason == dto.Reason)
@@ -109,7 +110,8 @@ public class UserController : BaseController
         return new
         {
             RestApplyStatus = EnumExts.GetDescriptions<ETelRestApplyStatus>(),
-            RestReason = _commonOpinionRepository.Queryable().Where(x => x.CommonType == Share.Enums.Settings.ECommonType.RestReason).ToList()
+            RestReason = _commonOpinionRepository.Queryable()
+                .Where(x => x.CommonType == Share.Enums.Settings.ECommonType.RestReason).ToList()
         };
     }
 
@@ -132,6 +134,7 @@ public class UserController : BaseController
                 throw UserFriendlyException.SameMessage("未设置默认分机号");
             telNo = user.DefaultTelNo;
         }
+
         var tel = _telCacheManager.GetTel(telNo);
         await _userDomainService.OnDutyAsync(_sessionContext.RequiredUserId, tel, HttpContext.RequestAborted);
     }
@@ -153,20 +156,21 @@ public class UserController : BaseController
     public async Task<PagedDto<UserDto>> QueryPaged([FromQuery] UserPagedDto dto)
     {
         var (total, items) = await _userRepository.Queryable(includeDeleted: true)
-             .Includes(d => d.Account)
-             .Includes(d => d.Roles)
-             .Includes(d => d.Organization)
-             .Where(d => d.Account.AccountType == EAccountType.Personal && d.Id != SysAccountSeedData.Id)
-             .WhereIF(_sessionContext.OrgIsCenter==false,d=>d.OrgId.StartsWith(_sessionContext.RequiredOrgId))
-             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-                 d => d.Name.Contains(dto.Keyword!) || d.PhoneNo.Contains(dto.Keyword!) || d.Account.UserName.Contains(dto.Keyword))
-             .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), d => d.OrgId == dto.OrgCode)
-             .WhereIF(!string.IsNullOrEmpty(dto.Role), d => d.Roles.Any(x => x.Id == dto.Role))
-             .OrderBy(d => d.Account.Status)
-             .OrderBy(d => d.Organization.OrgType)
-             //.OrderBy(d => d.Organization.Id)
-             .OrderByDescending(d => d.CreationTime)
-             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            .Includes(d => d.Account)
+            .Includes(d => d.Roles)
+            .Includes(d => d.Organization)
+            .Where(d => d.Account.AccountType == EAccountType.Personal && d.Id != SysAccountSeedData.Id)
+            .WhereIF(_sessionContext.OrgIsCenter == false, d => d.OrgId.StartsWith(_sessionContext.RequiredOrgId))
+            .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
+                d => d.Name.Contains(dto.Keyword!) || d.PhoneNo.Contains(dto.Keyword!) ||
+                     d.Account.UserName.Contains(dto.Keyword))
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), d => d.OrgId == dto.OrgCode)
+            .WhereIF(!string.IsNullOrEmpty(dto.Role), d => d.Roles.Any(x => x.Id == dto.Role))
+            .OrderBy(d => d.Account.Status)
+            .OrderBy(d => d.Organization.OrgType)
+            //.OrderBy(d => d.Organization.Id)
+            .OrderByDescending(d => d.CreationTime)
+            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
         return new PagedDto<UserDto>(total, _mapper.Map<IReadOnlyList<UserDto>>(items));
     }
@@ -180,6 +184,12 @@ public class UserController : BaseController
     [HttpPut]
     public async Task Update([FromBody] UpdateUserDto dto)
     {
+        //工号不能重复
+        var isStaffNoExists = await _userRepository.Queryable()
+            .AnyAsync(d => d.Id != dto.Id && d.StaffNo == dto.StaffNo, HttpContext.RequestAborted);
+        if (isStaffNoExists)
+            throw UserFriendlyException.SameMessage("工号已存在");
+
         var user = await _userRepository.Queryable()
             .Includes(d => d.Account)
             .FirstAsync(d => d.Id == dto.Id, HttpContext.RequestAborted);
@@ -206,6 +216,12 @@ public class UserController : BaseController
     [HttpPost]
     public async Task<string> Add([FromBody] AddUserDto dto)
     {
+        //工号不能重复
+        var isStaffNoExists = await _userRepository.Queryable()
+            .AnyAsync(d => d.StaffNo == dto.StaffNo, HttpContext.RequestAborted);
+        if (isStaffNoExists)
+            throw UserFriendlyException.SameMessage("工号已存在");
+
         var account = await _accountRepository.GetAsync(d => d.UserName == dto.UserName, HttpContext.RequestAborted);
         if (account is null)
         {
@@ -347,9 +363,10 @@ public class UserController : BaseController
         CheckAccountStatus(account);
 
         var result = await _accountDomainService.ResetPasswordAsync(account, dto.CurrentPassword, dto.NewPassword,
-             HttpContext.RequestAborted);
+            HttpContext.RequestAborted);
         if (!result.Succeeded)
-            throw UserFriendlyException.SameMessage(string.Join(',', result.Errors.Select(d => d.Description).ToList()));
+            throw UserFriendlyException.SameMessage(string.Join(',',
+                result.Errors.Select(d => d.Description).ToList()));
         account.PasswordChanged = true;
         await _accountRepository.UpdateAsync(account, HttpContext.RequestAborted);
     }
@@ -366,10 +383,12 @@ public class UserController : BaseController
         CheckAccountStatus(account);
 
         var accountOptions = _identityConfigurationAccessor.Value.Account;
-        var result = await _accountDomainService.ResetPasswordAsync(account, accountOptions.DefaultPassword, dto.NewPassword,
+        var result = await _accountDomainService.ResetPasswordAsync(account, accountOptions.DefaultPassword,
+            dto.NewPassword,
             HttpContext.RequestAborted);
         if (!result.Succeeded)
-            throw UserFriendlyException.SameMessage(string.Join(',', result.Errors.Select(d => d.Description).ToList()));
+            throw UserFriendlyException.SameMessage(string.Join(',',
+                result.Errors.Select(d => d.Description).ToList()));
         account.PasswordChanged = true;
         await _accountRepository.UpdateAsync(account, HttpContext.RequestAborted);
     }

+ 50 - 23
src/Hotline.Api/StartupExtensions.cs

@@ -19,8 +19,11 @@ using XF.EasyCaching;
 using XF.Utility.MQ;
 using Hotline.Ai.Jths;
 using Hotline.Api.Sdk;
+using Hotline.CallCenter.Configs;
 using Hotline.YbEnterprise.Sdk;
 using Hotline.Share.Dtos.SendSms;
+using Hotline.Wex;
+using Hotline.Application.CallCenter.Calls;
 
 namespace Hotline.Api;
 
@@ -37,8 +40,7 @@ internal static class StartupExtensions
 #if DEBUG
         builder.WebHost.UseUrls("http://*:50100");
 #endif
-        
-        //services.Configure<DeviceConfigs>(d => configuration.GetSection(nameof(DeviceConfigs)).Bind(d));
+
         services.Configure<IdentityConfiguration>(d => configuration.GetSection(nameof(IdentityConfiguration)).Bind(d));
         services.Configure<CallCenterConfiguration>(d => configuration.GetSection(nameof(CallCenterConfiguration)).Bind(d));
         services.Configure<AiVisitConfig>(d => configuration.GetSection("AiVisit").Bind(d));
@@ -94,35 +96,60 @@ internal static class StartupExtensions
             d.RegisterServicesFromAssembly(typeof(ApplicationStartupExtensions).Assembly);
         });
 
-        var callCenterConfiguration = configuration.GetSection("CallCenterConfiguration").Get<CallCenterConfiguration>();
-        //迅时IPPBX
-        services.AddNewRock(callCenterConfiguration.DeviceConfigs.Address);
-  
-        ////wex
-        //services.AddWex(callCenterConfiguration.Wex.Address);
-  
-        //tr
-        var trConfig = configuration.GetRequiredSection("Tr").Get<TrConfiguration>();
-        services.AddTrSdk(trConfig.Address, trConfig.Username, trConfig.Password);
-  
-		//jths 
-		services.AddAiJths(configuration.GetSection("AiQuality").Get<AiQualityConfig>().Url);
-  
+        //callcenter
+        var callCenterConfiguration = configuration
+            .GetRequiredSection(nameof(CallCenterConfiguration))
+            .Get<CallCenterConfiguration>();
+        services.AddNewRock(callCenterConfiguration.NewRock);
+        switch (callCenterConfiguration.CallCenterType)
+        {
+            case "XunShi":
+                break;
+            case "WerErXin":
+                services
+                    .AddWex(callCenterConfiguration.Wex)
+                    .AddWexDb(configuration);
+                break;
+            case "TianRun":
+                services
+                    .AddScoped<ITrApplication, TrApplication>()
+                    .AddHostedService<CurrentWaitNumService>()
+                    .AddHostedService<TelsStatusRefreshService>()
+                    .AddTrSdk(callCenterConfiguration.TianRun.Address,
+                        callCenterConfiguration.TianRun.Username,
+                        callCenterConfiguration.TianRun.Password);
+                break;
+            case "XingTang":
+                services.AddXingTangDb(callCenterConfiguration.XingTang);
+                break;
+            default:
+                break;
+        }
+
+
+
+
+        ////tr
+        //var trConfig = configuration.GetRequiredSection("Tr").Get<TianrunConfiguration>();
+
+
+        //jths 
+        services.AddAiJths(configuration.GetSection("AiQuality").Get<AiQualityConfig>().Url);
+
         //宜宾企业服务
         services.Configure<EnterpriseConfig>(d => configuration.GetSection("Enterprise").Bind(d));
         var enterpriseConfig = configuration.GetSection("Enterprise").Get<EnterpriseConfig>();
         services.AddYbEnterpriseSdk(enterpriseConfig?.AddressUrl);
-  
+
         var aiVisitConfig = configuration.GetSection("AiVisit").Get<AiVisitConfig>();
         services.AddAiVisitService(
-            aiVisitConfig.Url, 
-            aiVisitConfig.Appkey, 
+            aiVisitConfig.Url,
+            aiVisitConfig.Appkey,
             aiVisitConfig.ServiceVersion);
 
         //sqlsugar
         services.AddSqlSugar(configuration);
-        //services.AddWexDb(configuration);
-        
+
         //validator
         services.AddFluentValidationAutoValidation(config =>
         {
@@ -134,7 +161,7 @@ internal static class StartupExtensions
         services.AddMq(configuration);
 
         //job
-        services.RegisterJob();
+        services.RegisterJob(callCenterConfiguration);
 
         services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
         services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
@@ -157,7 +184,7 @@ internal static class StartupExtensions
                 //c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
             });
         }
-       
+
         app.UseCors(CorsOrigins);
 
         app.UseAuthentication();

+ 16 - 4
src/Hotline.Api/StartupHelper.cs

@@ -3,6 +3,7 @@ using System.Reflection;
 using System.Text;
 using Hotline.Application.Jobs;
 using Hotline.Application.Orders;
+using Hotline.CallCenter.Configs;
 using Hotline.Identity;
 using Hotline.Repository.SqlSugar;
 using Hotline.Repository.SqlSugar.Ts;
@@ -237,11 +238,10 @@ namespace Hotline.Api
                 options.Configuration.Password = cacheConfig.Password;
                 options.Configuration.DefaultDatabase = cacheConfig.Database;
             });
-
             return services;
         }
 
-        public static IServiceCollection RegisterJob(this IServiceCollection services)
+        public static IServiceCollection RegisterJob(this IServiceCollection services, CallCenterConfiguration callCenterConfiguration)
         {
             services.AddQuartz(d =>
             {
@@ -251,9 +251,8 @@ namespace Hotline.Api
                 d.MaxBatchSize = 3;
 
                 //load send order job
-                var autoSendOrderKey = new JobKey("task-send-order", "send order task");
+                var autoSendOrderKey = new JobKey(nameof(SendOrderJob), "send order task");
                 d.AddJob<SendOrderJob>(autoSendOrderKey);
-
                 d.AddTrigger(t => t
                     .WithIdentity("task-send-order-trigger")
                     .ForJob(autoSendOrderKey)
@@ -261,6 +260,19 @@ namespace Hotline.Api
                     .WithCronSchedule("0 10 9 * * ?")
                 );
 
+                switch (callCenterConfiguration.CallCenterType)
+                {
+                    //case "XingTang":
+                    //    var getCallsJobKey = new JobKey(nameof(GetCallsJob));
+                    //    d.AddJob<GetCallsJob>(getCallsJobKey);
+                    //    d.AddTrigger(d => d
+                    //        .WithIdentity("get-callsxt-trigger")
+                    //        .ForJob(getCallsJobKey)
+                    //        .StartNow()
+                    //        .WithCronSchedule("0/5 * * * * ?")
+                    //    );
+                    //    break;
+                }
             });
 
             services.AddQuartzServer(d =>

+ 14 - 2
src/Hotline.Api/config/appsettings.Development.json

@@ -1,8 +1,8 @@
 {
   "AllowedHosts": "*",
   "CallCenterConfiguration": {
-    "CallCenterType": "WeiErXin", //XunShi、WeiErXin、TianRun
-    "DeviceConfigs": {
+    "CallCenterType": "XingTang", //XunShi、WeiErXin、TianRun、XingTang
+    "NewRock": {
       "Address": "http://192.168.100.100/xml",
       "Authorize": true,
       "ReceiveKey": "E1BBD1BB-A269-44",
@@ -13,6 +13,18 @@
       "Address": "http://222.212.82.225:8083",
       "Username": "admin",
       "Password": "Wex@12345"
+    },
+    "TianRun": {
+      //"Address": "http://internal.ttf-cti.com:8080",
+      //"Username": "yscs",
+      //"Password": "123456",
+      "Address": "http://222.213.23.229:29003/",
+      "Username": "root",
+      "Password": "12345678aa",
+      "Ip": "222.213.23.229"
+    },
+    "XingTang": {
+      "DbConnectionString": "server=123.56.10.71;Database=callcenter_db;Uid=root;Pwd=Lhw1981!(*!"
     }
   },
   "ConnectionStrings": {

+ 4 - 3
src/Hotline.Application/CallCenter/Calls/CurrentWaitNumService.cs

@@ -9,10 +9,11 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Tr.Sdk;
+using XF.Domain.Dependency;
 
 namespace Hotline.Application.CallCenter.Calls
 {
-    public class CurrentWaitNumService : BackgroundService
+    public class CurrentWaitNumService : BackgroundService, IIgnoreDependency
     {
         private readonly IServiceScopeFactory _serviceScopeFactory;
 
@@ -29,7 +30,7 @@ namespace Hotline.Application.CallCenter.Calls
             var _trClient = scope.ServiceProvider.GetRequiredService<ITrClient>();
             int times = 3000;//5秒
             var callinQueueIds = _systemSettingCacheManager.GetSetting(SettingConstants.CallInQueueId)?.SettingValue.ToList();
-            while(!stoppingToken.IsCancellationRequested)
+            while (!stoppingToken.IsCancellationRequested)
             {
                 try
                 {
@@ -42,7 +43,7 @@ namespace Hotline.Application.CallCenter.Calls
 
                     await realtimeService.CurrentWaitNumAsync(count, stoppingToken);
                 }
-                catch{}
+                catch { }
                 await Task.Delay(times);
             }
 

+ 3 - 2
src/Hotline.Application/CallCenter/Calls/TelsStatusRefreshService.cs

@@ -7,11 +7,12 @@ using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
 using Tr.Sdk;
 using XF.Domain.Cache;
+using XF.Domain.Dependency;
 using XF.Domain.Repository;
 
 namespace Hotline.Application.CallCenter.Calls
 {
-    public class TelsStatusRefreshService : BackgroundService
+    public class TelsStatusRefreshService : BackgroundService, IIgnoreDependency
     {
         private readonly IServiceScopeFactory _serviceScopeFactory;
         public TelsStatusRefreshService(IServiceScopeFactory serviceScopeFactory)
@@ -35,7 +36,7 @@ namespace Hotline.Application.CallCenter.Calls
                 try
                 {
                     //var list = await _workRepository.Queryable().Where(x => !x.EndTime.HasValue).ToListAsync();
-                    var list = await _workRepository.Queryable().Where(x => 1==1 && !x.EndTime.HasValue).ToListAsync();
+                    var list = await _workRepository.Queryable().Where(x => 1 == 1 && !x.EndTime.HasValue).ToListAsync();
                     //var list = await _workRepository.Queryable().Where(x => x.EndTime is null).ToListAsync();
                     var tellist = await _trClient.QueryTelStateAsync(new Tr.Sdk.Tels.QueryTelStateRequest { }, stoppingToken);
                     foreach (var item in list)

+ 1 - 1
src/Hotline.Application/CallCenter/Calls/TrApplication.cs

@@ -17,7 +17,7 @@ using XF.Domain.Repository;
 
 namespace Hotline.Application.CallCenter.Calls
 {
-    public class TrApplication : ITrApplication, IScopeDependency
+    public class TrApplication : ITrApplication//, IScopeDependency
     {
         private readonly ITrClient _trClient;
         private readonly ISessionContext _sessionContext;

+ 10 - 9
src/Hotline.Application/Handlers/CallCenter/BaseHandler.cs

@@ -1,5 +1,6 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.Realtimes;
 using Hotline.Share.Dtos.CallCenter;
@@ -47,7 +48,7 @@ namespace Hotline.Application.Handlers.CallCenter
                                     Menu = new OuterToMenuMenu() { Id = tomenuId },
                                     Outer = new OuterToMenuOuter() { Id = model.ConversationId },
                                     //VoiceFile = string.IsNullOrEmpty(ivrAnswer.PreVoice) ? "" : ivrAnswer.PreVoice,
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             case ECallType.VisitorCallIn:
                                 await _newRockClient.VisitorToMenu(new VisitorToMenuRequest()
@@ -56,7 +57,7 @@ namespace Hotline.Application.Handlers.CallCenter
                                     Menu = new VisitorToMenuMenu() { Id = tomenuId },
                                     Visitor = new VisitorToMenuVisitor() { Id = model.ConversationId },
                                     //VoiceFile = string.IsNullOrEmpty(ivrAnswer.PreVoice) ? "" : ivrAnswer.PreVoice,
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             default:
                                 throw new ArgumentOutOfRangeException();
@@ -80,7 +81,7 @@ namespace Hotline.Application.Handlers.CallCenter
                                     Attribute = "Queue",
                                     Ext = new VisitorToExtQueueExt() { Id = telNo },
                                     Visitor = new VisitorToExtQueueVisitor() { Id = model.ConversationId }
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             case ECallType.ExtToOuter:
                                 await _newRockClient.OuterToExt(new OuterToExtRequest()
@@ -88,7 +89,7 @@ namespace Hotline.Application.Handlers.CallCenter
                                     Attribute = "Connect",
                                     Ext = new OuterToExtExt() { Id = telNo },
                                     Outer = new OuterToExtOuter() { Id = model.ConversationId }
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             default:
                                 throw new ArgumentOutOfRangeException();
@@ -103,7 +104,7 @@ namespace Hotline.Application.Handlers.CallCenter
                             Attribute = "Queue",
                             Group = new VisitorToGroupQueueGroup() { Id = groupId },
                             Visitor = new VisitorToGroupQueueVisitor() { Id = model.ConversationId }
-                        }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                        }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
 
                         //处理队列记录
                         _callCacheManager.AddCallCache(model);
@@ -125,7 +126,7 @@ namespace Hotline.Application.Handlers.CallCenter
                                         //TODO DISPLAY属性待定
                                     }
                                 },
-                                    _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                    _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             case ECallType.ExtToOuter:
                                 await _newRockClient.OuterToOuter(new OuterToOuterRequest()
@@ -135,7 +136,7 @@ namespace Hotline.Application.Handlers.CallCenter
                                         new(){Id = model.ConversationId},
                                             new(){To = phoneNo},
                                         }
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             default:
                                 throw new ArgumentOutOfRangeException();
@@ -150,14 +151,14 @@ namespace Hotline.Application.Handlers.CallCenter
                                 {
                                     Attribute = "Clear",
                                     Visitor = new ClearCallVisitor() { Id = model.ConversationId },
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                             case ECallType.ExtToOuter:
                                 await _newRockClient.ClearCall(new ClearCallRequest()
                                 {
                                     Attribute = "Clear",
                                     Outer = new ClearCallOuter() { Id = model.ConversationId },
-                                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                 break;
                         }
                         break;

+ 1 - 0
src/Hotline.Application/Handlers/CallCenter/CallState/DtmfNotificationHandler.cs

@@ -1,5 +1,6 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.Realtimes;

+ 10 - 2
src/Hotline.Application/Handlers/CallCenter/ExtState/IdleNotificationHandler.cs

@@ -1,5 +1,6 @@
 using Hotline.Caching.Interfaces;
 using Hotline.Caching.Services;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Tels;
 using Hotline.Realtimes;
@@ -7,6 +8,7 @@ using Hotline.Repository.SqlSugar.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Notifications.NewRockCallCenter;
 using MediatR;
+using Microsoft.Extensions.Options;
 using XF.Domain.Cache;
 using XF.Domain.Exceptions;
 
@@ -21,8 +23,13 @@ namespace Hotline.Application.Handlers.CallCenter.ExtState
         private readonly IRealtimeService _realtimeService;
         private readonly IDeviceManager _deviceManager;
         private readonly ITelRestRepository _telRestRepository;
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
 
-        public IdleNotificationHandler(ITelRepository telRepository, ITelCacheManager telCacheManager, ITypedCache<Tel> typedCache,IUserCacheManager userCacheManager,IRealtimeService realtimeService,IDeviceManager deviceManager,ITelRestRepository telRestRepository)
+        public IdleNotificationHandler(ITelRepository telRepository, ITelCacheManager telCacheManager, 
+            ITypedCache<Tel> typedCache,IUserCacheManager userCacheManager,
+            IRealtimeService realtimeService,IDeviceManager deviceManager,
+            ITelRestRepository telRestRepository,
+            IOptionsSnapshot<CallCenterConfiguration> options)
         {
             _telRepository = telRepository;
             _telCacheManager = telCacheManager;
@@ -31,6 +38,7 @@ namespace Hotline.Application.Handlers.CallCenter.ExtState
             _realtimeService = realtimeService;
             _deviceManager = deviceManager;
             _telRestRepository = telRestRepository;
+            _options = options;
         }
 
         public async Task Handle(IdleNotification notification, CancellationToken cancellationToken)
@@ -60,7 +68,7 @@ namespace Hotline.Application.Handlers.CallCenter.ExtState
             {
                 foreach (var group in telModel.Groups)
                 {
-                    await _deviceManager.AssginConfigGroupAsync(group.No, group.Distribution, new List<string>() { notification.TelNo }, group.Voice, cancellationToken);
+                    await _deviceManager.AssginConfigGroupAsync(_options.Value.NewRock, group.No, group.Distribution, new List<string>() { notification.TelNo }, group.Voice, cancellationToken);
                 }
             }
         }

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

@@ -1,5 +1,6 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.Realtimes;

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

@@ -1,5 +1,6 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.Realtimes;

+ 3 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/IncomingNotificationHandler.cs

@@ -1,5 +1,6 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.Realtimes;
 using Hotline.Settings;
@@ -104,7 +105,7 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                                     Menu = new VisitorToMenuMenu() { Id = ivr.No },
                                     Visitor = new VisitorToMenuVisitor() { Id = notification.Visitor.Id }
                                 },
-                                _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                                _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
 
                             //写入进入IVR流程
                             model.InIvrTime = DateTime.Now;
@@ -130,7 +131,7 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                                 Visitor = new VisitorToGroupQueueVisitor() { Id = notification.Visitor.Id },
                                 Group = new VisitorToGroupQueueGroup() { Id = correct.ReturnValue }
                             },
-                            _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                            _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                             model.InQueueTime = DateTime.Now;
                             await _callRepository.UpdateAsync(model, cancellationToken);
                             //处理队列记录

+ 3 - 2
src/Hotline.Application/Handlers/CallCenter/FlowControl/InviteNotificationHandler.cs

@@ -1,6 +1,7 @@
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.Settings;
 using Hotline.Share.Enums.CallCenter;
@@ -89,14 +90,14 @@ namespace Hotline.Application.Handlers.CallCenter.FlowControl
                     {
                         Id = notification.Visitor.Id
                     }
-                }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
             }
             else
             {
                 await _newRockClient.AcceptVisitor(
                     new AcceptVisitorRequest()
                     { Attribute = "Accept", Visitor = new AcceptVisitorModel() { Id = notification.Visitor.Id } },
-                    _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                    _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
             }
         }
     }

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

@@ -1,9 +1,11 @@
 using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.CallCenter.Tels;
 using Hotline.Share.Notifications.NewRockCallCenter;
 using MediatR;
+using Microsoft.Extensions.Options;
 
 namespace Hotline.Application.Handlers.CallCenter.System
 {
@@ -11,15 +13,19 @@ namespace Hotline.Application.Handlers.CallCenter.System
     {
         private readonly ITelGroupRepository _telGroupRepository;
         private readonly IIvrRepository _ivrRepository;
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
         private readonly IDeviceManager _deviceManager;
         private readonly IUserCacheManager _userCacheManager;
 
-        public BootupNotificationHandler(ITelGroupRepository telGroupRepository, IDeviceManager deviceManager, IUserCacheManager userCacheManager, IIvrRepository ivrRepository)
+        public BootupNotificationHandler(ITelGroupRepository telGroupRepository, IDeviceManager deviceManager,
+            IUserCacheManager userCacheManager, IIvrRepository ivrRepository,
+            IOptionsSnapshot<CallCenterConfiguration> options)
         {
             _telGroupRepository = telGroupRepository;
             _deviceManager = deviceManager;
             _userCacheManager = userCacheManager;
             _ivrRepository = ivrRepository;
+            _options = options;
         }
 
         public async Task Handle(BootupNotification notification, CancellationToken cancellationToken)
@@ -38,7 +44,7 @@ namespace Hotline.Application.Handlers.CallCenter.System
 
                 }
                 //轮循还原设备分机组信息
-                await _deviceManager.AssginConfigGroupAsync(groupItem.No, groupItem.Distribution, exts, groupItem.Voice,
+                await _deviceManager.AssginConfigGroupAsync(_options.Value.NewRock, groupItem.No, groupItem.Distribution, exts, groupItem.Voice,
                     cancellationToken);
             }
 
@@ -49,7 +55,7 @@ namespace Hotline.Application.Handlers.CallCenter.System
             var ivrlist = await _ivrRepository.QueryAsync();
             foreach (var item in ivrlist)
             {
-                await _deviceManager.AssginConfigMenuAsync(item.No, item.Voice, item.Repeat.ToString(), item.InfoLength.ToString(), item.Exit, cancellationToken);
+                await _deviceManager.AssginConfigMenuAsync(_options.Value.NewRock, item.No, item.Voice, item.Repeat.ToString(), item.InfoLength.ToString(), item.Exit, cancellationToken);
             }
             #endregion
 

+ 1 - 0
src/Hotline.Application/Hotline.Application.csproj

@@ -23,6 +23,7 @@
     <ProjectReference Include="..\Hotline\Hotline.csproj" />
     <ProjectReference Include="..\Tr.Sdk\Tr.Sdk.csproj" />
     <ProjectReference Include="..\XF.EasyCaching\XF.EasyCaching.csproj" />
+    <ProjectReference Include="..\XingTang.Sdk\XingTang.Sdk.csproj" />
   </ItemGroup>
 
 </Project>

+ 112 - 0
src/Hotline.Application/Jobs/GetCallsJob.cs

@@ -0,0 +1,112 @@
+using Quartz;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Hotline.CallCenter.Calls;
+using Hotline.Repository.SqlSugar;
+using Hotline.Share.Enums.CallCenter;
+using Hotline.Users;
+using MapsterMapper;
+using Microsoft.Extensions.Logging;
+using XF.Domain.Cache;
+using XF.Domain.Repository;
+using XingTang.Sdk;
+
+namespace Hotline.Application.Jobs
+{
+    /// <summary>
+    /// 查询通话记录
+    /// </summary>
+    public class GetCallsJob : IJob, IDisposable
+    {
+        private readonly IRepository<TrCallRecord> _trcallRepository;
+        private readonly IRepository<User> _userRepository;
+        private readonly IMapper _mapper;
+        private readonly ILogger<GetCallsJob> _logger;
+        private readonly ISqlSugarClient _db;
+
+        public GetCallsJob(
+            ISugarUnitOfWork<XingTangDbContext> uow,
+            IRepository<TrCallRecord> trcallRepository,
+            IRepository<User> userRepository,
+            IMapper mapper,
+            ILogger<GetCallsJob> logger)
+        {
+            _trcallRepository = trcallRepository;
+            _userRepository = userRepository;
+            _mapper = mapper;
+            _logger = logger;
+            _db = uow.Db;
+        }
+
+        public async Task Execute(IJobExecutionContext context)
+        {
+            var calls = await _db.Queryable<XingtangCall>()
+                .Where(d => !d.IsSync && d.Tries <= 50)
+                .Take(10)
+                .ToListAsync(context.CancellationToken);
+
+            var occupyCalls = new List<XingtangCall>();
+            foreach (var call in calls)
+            {
+                var rows = _db.Updateable(new XingtangCall
+                {
+                    Id = call.Id,
+                    IsSync = true,
+                    Tries = call.Tries + 1
+                }).ExecuteCommandWithOptLock();
+                if (rows > 0)
+                    occupyCalls.Add(call);
+            }
+
+            try
+            {
+                var trCalls = _mapper.Map<List<TrCallRecord>>(occupyCalls);
+                //填充user信息
+                var staffNos = calls.Select(d => d.UserCode).ToList();
+                var users = await _userRepository.Queryable()
+                    .Where(d => staffNos.Contains(d.StaffNo))
+                    .ToListAsync(context.CancellationToken);
+
+                foreach (var trCall in trCalls)
+                {
+                    //if (trCall.CallDirection is ECallDirection.Out &&
+                    //    string.IsNullOrEmpty(trCall.RecordingAbsolutePath))
+                    //    continue;
+                    Console.WriteLine(trCall.OtherAccept);
+                    
+                    var user = users.FirstOrDefault(d => d.StaffNo == trCall.StaffNo);
+                    if (user is not null)
+                    {
+                        trCall.UserId = user.Id;
+                        trCall.UserName = user.Name;
+                    }
+                }
+
+                await _trcallRepository.UpdateRangeAsync(trCalls, context.CancellationToken);
+            }
+            catch (Exception e)
+            {
+                //Console.WriteLine(e);
+                _logger.LogError($"获取通话记录异常:{e.Message} \n {e.StackTrace}");
+                foreach (var occupyCall in occupyCalls)
+                {
+                    occupyCall.IsSync = false;
+                }
+
+                await _db.Updateable(occupyCalls)
+                    .UpdateColumns(d => new { d.IsSync })
+                    .ExecuteCommandAsync(context.CancellationToken);
+            }
+        }
+
+        /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
+        public void Dispose()
+        {
+            _logger.LogInformation($"{nameof(GetCallsJob)} disposed");
+        }
+    }
+}

+ 0 - 35
src/Hotline.Application/Jobs/ReloadTotalsJob.cs

@@ -1,35 +0,0 @@
-using Quartz;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using XF.Domain.Cache;
-
-namespace Hotline.Application.Jobs
-{
-    /// <summary>
-    /// 刷新总数
-    /// </summary>
-    public class ReloadTotalsJob : IJob, IDisposable
-    {
-        private const string totalCachePrefix = "TotalsCache:";
-        private readonly ITypedCache<int> _totalsCache;
-
-        public ReloadTotalsJob(ITypedCache<int> totalsCache)
-        {
-            _totalsCache = totalsCache;
-        }
-
-        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();
-        }
-    }
-}

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

@@ -7,6 +7,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using XingTang.Sdk;
 
 namespace Hotline.Application.Mappers
 {
@@ -18,7 +19,10 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.User, x => x.user)
                 .Map(d => d.RecordingFileName, x => x.recording_file_name)
                 .Map(d => d.CallDirection, x => x.call_direction == "in" ? ECallDirection.In : ECallDirection.Out)
-                .Map(d => d.EndBy, x => x.hangup_side == "caller" ? EEndBy.From : (x.hangup_side == "callee" ? EEndBy.To : EEndBy.None))
+                .Map(d => d.EndBy,
+                    x => x.hangup_side == "caller"
+                        ? EEndBy.From
+                        : (x.hangup_side == "callee" ? EEndBy.To : EEndBy.None))
                 .Map(d => d.AgentTransferNumber, x => x.agent_transfer_number)
                 .Map(d => d.CallAccept, x => x.call_accept)
                 .Map(d => d.CPN, x => x.caller_id_number)
@@ -52,11 +56,34 @@ namespace Hotline.Application.Mappers
                 ;
 
 
-
             config.ForType<ReceiveCallEvaluateDto, TrCallEvaluate>()
                 .Map(d => d.Dtmf, x => x.dtmf)
                 .Map(d => d.CallAccept, x => x.call_accept)
                 .Map(d => d.Type, x => x.type);
+
+            config.ForType<XingtangCall, TrCallRecord>()
+                .Map(d => d.OtherAccept, s => s.CallGuid)
+                .Map(d => d.CallDirection, s => s.CallType)
+                .Map(d => d.CPN, s => s.Caller)
+                .Map(d => d.CDPN, s => s.Called)
+                .Map(d => d.TelNo, s => s.Ext)
+                .Map(d => d.StaffNo, s => s.UserCode)
+                .Map(d => d.AnsweredTime, s => s.ReceiveEndTime)
+                .Map(d => d.OverTime, s => s.CallEndTime)
+                .Map(d => d.BeginIvrTime, s => s.CallStartTime)
+                .Map(d => d.EndIvrTime, s => s.EnqueueTime)
+                .Map(d => d.BeginRingTime, s => s.RingStartTime)
+                //.Map(d=>d.EndRingTimg,s=>)
+                .Map(d => d.OlaQueue, s => s.SkillId.ToString())
+                .Map(d => d.Duration, s => s.Duration)
+                .Map(d => d.RingTimes, s => s.RingTime)
+                .Map(d => d.QueueTims, s => s.WaitTime)
+                .Map(d => d.RecordingAbsolutePath, s => s.AudioFile)
+                .AfterMapping((s, d) =>
+                {
+                    d.CreatedTime = DateTime.Now;
+                    d.OnState = s.ReceiveEndTime.HasValue ? EOnState.On : EOnState.NoOn;
+                });
         }
 
         private DateTime? FormatDateTime(string? time)
@@ -72,6 +99,5 @@ namespace Hotline.Application.Mappers
                 return null;
             }
         }
-
     }
-}
+}

+ 139 - 130
src/Hotline.NewRock/DeviceManager.cs

@@ -15,10 +15,11 @@ using NewRock.Sdk.Control.Response;
 using System.Text.RegularExpressions;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
-using Group = NewRock.Sdk.Control.Request.Group;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Configs;
+using Group = NewRock.Sdk.Control.Request.Group;
 
 namespace Hotline.NewRock
 {
@@ -26,17 +27,25 @@ namespace Hotline.NewRock
     {
         private readonly INewRockClient _newRockClient;
         private readonly ICallRepository _callRepository;
-        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
+        //private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
         private readonly IMapper _mapper;
         private readonly ITelGroupRepository _telGroupRepository;
         private readonly IUserCacheManager _userCacheManager;
         private readonly ITelRestRepository _telRestRepository;
         private readonly ITelCacheManager _telCacheManager;
 
-        public DeviceManager(INewRockClient newRockClient, IOptionsSnapshot<CallCenterConfiguration> options, IMapper mapper, ICallRepository callRepository, ITelGroupRepository telGroupRepository,IUserCacheManager userCacheManager, ITelRestRepository telRestRepository, ITelCacheManager telCacheManager)
+        public DeviceManager(
+            INewRockClient newRockClient, 
+            //IOptionsSnapshot<CallCenterConfiguration> options, 
+            IMapper mapper, 
+            ICallRepository callRepository, 
+            ITelGroupRepository telGroupRepository,
+            IUserCacheManager userCacheManager, 
+            ITelRestRepository telRestRepository,
+            ITelCacheManager telCacheManager)
         {
             _newRockClient = newRockClient;
-            _options = options;
+            //_options = options;
             _mapper = mapper;
             _callRepository = callRepository;
             _telGroupRepository = telGroupRepository;
@@ -47,13 +56,13 @@ namespace Hotline.NewRock
 
         #region 查询
 
-        public async Task<TelDto> QueryTelAsync(string TelNo, CancellationToken cancellationToken)
+        public async Task<TelDto> QueryTelAsync(NewRockConfiguration newRockConfiguration, string TelNo, CancellationToken cancellationToken)
         {
             try
             {
                 var result = await _newRockClient.QueryExt(
                 new QueryExtRequest() { Attribute = "Query", Ext = new Ext { Id = TelNo } },
-                _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                newRockConfiguration.ReceiveKey, newRockConfiguration.Expired, cancellationToken);
 
                 if (result?.Ext.Outer != null)
                 {
@@ -123,11 +132,11 @@ namespace Hotline.NewRock
         /// <param name="TelNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task<ETelStatus> QueryTelState(string TelNo, CancellationToken cancellationToken)
+        public async Task<ETelStatus> QueryTelState(NewRockConfiguration newRockConfiguration, string TelNo, CancellationToken cancellationToken)
         {
             var result = await _newRockClient.QueryExt(
                 new QueryExtRequest() { Attribute = "Query", Ext = new Ext { Id = TelNo } },
-                _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+                newRockConfiguration.ReceiveKey, newRockConfiguration.Expired, cancellationToken);
 
             switch (result.Ext.State)
             {
@@ -152,12 +161,12 @@ namespace Hotline.NewRock
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task<List<Tel>> QueryTelsAsync(CancellationToken cancellationToken)
+        public async Task<List<Tel>> QueryTelsAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken)
         {
             var result = await _newRockClient.QueryDeviceInfo(
                 new QueryDeviceInfoRequest { Attribute = "Query", DeviceInfo = string.Empty },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
             var exts = result.Devices.Ext;
             return _mapper.Map<List<Tel>>(exts);
@@ -168,12 +177,12 @@ namespace Hotline.NewRock
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task<List<TelGroup>> QueryTelGroupsAsync(CancellationToken cancellationToken)
+        public async Task<List<TelGroup>> QueryTelGroupsAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken)
         {
             var result = await _newRockClient.QueryDeviceInfo(
                 new QueryDeviceInfoRequest { Attribute = "Query", DeviceInfo = string.Empty },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
 
             var groups = result.Devices.Group;
@@ -185,24 +194,24 @@ namespace Hotline.NewRock
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task<string> VoiceQueryListAsync(CancellationToken cancellationToken)
+        public async Task<string> VoiceQueryListAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken)
         {
             var result = await _newRockClient.VoiceQueryList(new VoiceQueryListRequest()
                 {
                     Attribute = "Query",
                     VoiceFile = "",
-                }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
             return result?.VoiceFile;
         }
 
-        public async Task QueryGroupAsync(string groupId, CancellationToken cancellationToken)
+        public async Task QueryGroupAsync(NewRockConfiguration newRockConfiguration, string groupId, CancellationToken cancellationToken)
         {
             await _newRockClient.QueryExtGroup(new QueryExtGroupRequest()
                 { Attribute = "Query", Group = new QueryExtGroup() { Id = groupId } },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken
             );
         }
@@ -217,14 +226,14 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task TelRestAsync(string telNo, CancellationToken cancellationToken)
+        public async Task TelRestAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             var telModel = await _newRockClient.QueryExt(new QueryExtRequest()
             {
                 Attribute = "Query",
                 Ext = new Ext() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-            _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+            newRockConfiguration.Expired,
             cancellationToken);
 
             if (telModel == null)
@@ -232,8 +241,8 @@ namespace Hotline.NewRock
 
             await _newRockClient.ConfigExt(
                 new AssginConfigExtRequest() { Attribute = "Assign", Ext = new ConfigExt() { Lineid = telModel.Ext.LineId, Groups=Enumerable.Select<QueryExtGroup, string>(telModel.Ext.Group, x=>x.Id).ToList(), No_Disturb = "On" } },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -243,14 +252,14 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task TelEndRestAsync(string telNo, CancellationToken cancellationToken)
+        public async Task TelEndRestAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             var telModel = await _newRockClient.QueryExt(new QueryExtRequest()
             {
                 Attribute = "Query",
                 Ext = new Ext() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
 
             if (telModel == null)
@@ -258,8 +267,8 @@ namespace Hotline.NewRock
 
             await _newRockClient.ConfigExt(
                 new AssginConfigExtRequest() { Attribute = "Assign", Ext = new ConfigExt() { Lineid = telModel.Ext.LineId, Groups = Enumerable.Select<QueryExtGroup, string>(telModel.Ext.Group, x => x.Id).ToList(), No_Disturb = "Off" } },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -269,14 +278,14 @@ namespace Hotline.NewRock
         /// <param name="voiceName"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task RemoveVoiceFileAsync(string voiceName, CancellationToken cancellationToken)
+        public async Task RemoveVoiceFileAsync(NewRockConfiguration newRockConfiguration, string voiceName, CancellationToken cancellationToken)
         {
             await _newRockClient.RemoveVoiceFile(new RemoveVoiceFileRequest()
             {
                 Attribute = "Remove",
                 VoiceFile = voiceName
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -290,7 +299,7 @@ namespace Hotline.NewRock
         /// <param name="exit"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task AssginConfigMenuAsync(string menuId, string voiceFile, string repeat, string infoLength,
+        public async Task AssginConfigMenuAsync(NewRockConfiguration newRockConfiguration, string menuId, string voiceFile, string repeat, string infoLength,
             string exit,
             CancellationToken cancellationToken)
         {
@@ -318,8 +327,8 @@ namespace Hotline.NewRock
                     Exit = exit,
                     Repeat = repeat,
                 }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -332,7 +341,7 @@ namespace Hotline.NewRock
         /// <param name="ext"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task AssginConfigGroupAsync(string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "",CancellationToken cancellationToken=default)
+        public async Task AssginConfigGroupAsync(NewRockConfiguration newRockConfiguration, string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "",CancellationToken cancellationToken=default)
         {
             if (!int.TryParse(groupId, out int mId))
                 throw new UserFriendlyException("请输入数字");
@@ -367,8 +376,8 @@ namespace Hotline.NewRock
             {
                 Attribute = "Assign",
                 Group = groupModel
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -381,7 +390,7 @@ namespace Hotline.NewRock
         /// <param name="cancellationToken"></param>
         /// <param name="isAdd"></param>
         /// <returns></returns>
-        public async Task ModifyGroupExtAsync(string groupId, EDistribution distribution, string voicefile = "", string extId = "", bool isAdd = true, CancellationToken cancellationToken = default)
+        public async Task ModifyGroupExtAsync(NewRockConfiguration newRockConfiguration, string groupId, EDistribution distribution, string voicefile = "", string extId = "", bool isAdd = true, CancellationToken cancellationToken = default)
         {
             if (!int.TryParse(groupId, out int mId))
                 throw new UserFriendlyException("请输入数字");
@@ -391,7 +400,7 @@ namespace Hotline.NewRock
 
             #region 清除分机组设置
 
-            await _newRockClient.ConfigExtGroup(new AssginConfigGroupRequest() { Attribute = "Assign", Group = new Group() { Id = groupId } }, _options.Value.DeviceConfigs.ReceiveKey, _options.Value.DeviceConfigs.Expired, cancellationToken);
+            await _newRockClient.ConfigExtGroup(new AssginConfigGroupRequest() { Attribute = "Assign", Group = new Group() { Id = groupId } }, newRockConfiguration.ReceiveKey, newRockConfiguration.Expired, cancellationToken);
 
             #endregion
 
@@ -445,8 +454,8 @@ namespace Hotline.NewRock
             groupModel.Ext = exts;
             await _newRockClient.ConfigExtGroup(
                 new AssginConfigGroupRequest() { Attribute = "Assign", Group = groupModel, },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken
                 );
         }
@@ -458,14 +467,14 @@ namespace Hotline.NewRock
         /// <param name="staffNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task UpdateStaffNoAsync(string telNo, string staffNo,string lineId, CancellationToken cancellationToken)
+        public async Task UpdateStaffNoAsync(NewRockConfiguration newRockConfiguration, string telNo, string staffNo,string lineId, CancellationToken cancellationToken)
         {
             var telModel = await _newRockClient.QueryExt(new QueryExtRequest()
                 {
                     Attribute = "Query",
                     Ext = new Ext() { Id = telNo }
-                }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
 
             if (telModel == null)
@@ -473,8 +482,8 @@ namespace Hotline.NewRock
 
             await _newRockClient.ConfigExt(
                 new AssginConfigExtRequest() { Attribute = "Assign", Ext = new ConfigExt() { Id = telNo,Lineid = lineId, Staffid = staffNo } },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
         #endregion
@@ -487,11 +496,11 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task HoldAsync(string telNo, CancellationToken cancellationToken)
+        public async Task HoldAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.HoldOrUnHold(
-                new HoldSetRequest() { Attribute = "Hold", Ext = new Ext() { Id = telNo } }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                new HoldSetRequest() { Attribute = "Hold", Ext = new Ext() { Id = telNo } }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -501,11 +510,11 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task UnHoldAsync(string telNo, CancellationToken cancellationToken)
+        public async Task UnHoldAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.HoldOrUnHold(
-                new HoldSetRequest() { Attribute = "Unhold", Ext = new Ext() { Id = telNo } }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                new HoldSetRequest() { Attribute = "Unhold", Ext = new Ext() { Id = telNo } }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -515,11 +524,11 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task MuteAsync(string telNo, CancellationToken cancellationToken)
+        public async Task MuteAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.MuteOrUnMute(
-                new MuteSetRequest() { Attribute = "Mute", Ext = new Ext() { Id = telNo } }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                new MuteSetRequest() { Attribute = "Mute", Ext = new Ext() { Id = telNo } }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -529,12 +538,12 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task UnMuteAsync(string telNo, CancellationToken cancellationToken)
+        public async Task UnMuteAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.MuteOrUnMute(
                 new MuteSetRequest() { Attribute = "Unmute", Ext = new Ext() { Id = telNo } },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -544,7 +553,7 @@ namespace Hotline.NewRock
         /// <param name="extId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task ClearExtAsync(string extId, CancellationToken cancellationToken)
+        public async Task ClearExtAsync(NewRockConfiguration newRockConfiguration, string extId, CancellationToken cancellationToken)
         {
             await _newRockClient.ClearCall(new ClearCallRequest()
             {
@@ -553,8 +562,8 @@ namespace Hotline.NewRock
                 {
                     Id = extId
                 }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -564,14 +573,14 @@ namespace Hotline.NewRock
         /// <param name="visitorId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task ClearVisitorAsync(string visitorId, CancellationToken cancellationToken)
+        public async Task ClearVisitorAsync(NewRockConfiguration newRockConfiguration, string visitorId, CancellationToken cancellationToken)
         {
             await _newRockClient.ClearCall(new ClearCallRequest()
             {
                 Attribute = "Clear",
                 Visitor = new ClearCallVisitor() { Id = visitorId }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -581,14 +590,14 @@ namespace Hotline.NewRock
         /// <param name="outerId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task ClearOuterAsync(string outerId, CancellationToken cancellationToken)
+        public async Task ClearOuterAsync(NewRockConfiguration newRockConfiguration, string outerId, CancellationToken cancellationToken)
         {
             await _newRockClient.ClearCall(new ClearCallRequest()
             {
                 Attribute = "Clear",
                 Outer = new ClearCallOuter() { Id = outerId }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -598,14 +607,14 @@ namespace Hotline.NewRock
         /// <param name="visitorId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task AcceptVisitorAsync(string visitorId, CancellationToken cancellationToken)
+        public async Task AcceptVisitorAsync(NewRockConfiguration newRockConfiguration, string visitorId, CancellationToken cancellationToken)
         {
             await _newRockClient.AcceptVisitor(new AcceptVisitorRequest()
             {
                 Attribute = "Accept",
                 Visitor = new AcceptVisitorModel() { Id = visitorId }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
         #endregion
@@ -619,15 +628,15 @@ namespace Hotline.NewRock
         /// <param name="to">被叫分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task ExtToExtAsync(string from, string to, CancellationToken cancellationToken)
+        public async Task ExtToExtAsync(NewRockConfiguration newRockConfiguration, string from, string to, CancellationToken cancellationToken)
         {
             await _newRockClient.ExtensionToExtension(
                 new ExtensionToExtensionRequest()
                 {
                     Attribute = "Connect",
                     Exts = new List<ExtToExtExt>() { new ExtToExtExt() { Id = from }, new ExtToExtExt() { Id = to } }
-                }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -639,7 +648,7 @@ namespace Hotline.NewRock
         /// <param name="cancellationToken"></param>
         /// <param name="trunkid">指定中继线路(可为空),为空时默认由OM分配</param>
         /// <returns></returns>
-        public async Task ExtToOuterAsync(string from, string to, CancellationToken cancellationToken, string trunkid = "")
+        public async Task ExtToOuterAsync(NewRockConfiguration newRockConfiguration, string from, string to, CancellationToken cancellationToken, string trunkid = "")
         {
             await _newRockClient.ExtToOuter(
                     new ExtToOuterRequest()
@@ -649,8 +658,8 @@ namespace Hotline.NewRock
                         Outer = new ExtToOuterOuterRequest() { To = to },
                         Trunk = new ExtToOuterTrunkRequest() { Id = trunkid }
                     },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -662,15 +671,15 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task VisitorToExtAsync(string visitorId, string telNo, CancellationToken cancellationToken)
+        public async Task VisitorToExtAsync(NewRockConfiguration newRockConfiguration, string visitorId, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.VisitorToExt(new VisitorToExtRequest()
             {
                 Attribute = "Connect",
                 Visitor = new VisitorToExtVisitor() { Id = visitorId },
                 Ext = new VisitorToExtExt() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -682,7 +691,7 @@ namespace Hotline.NewRock
         /// <param name="cancellationToken"></param>
         /// <param name="display">来电号码,用来透传主叫号码,使去电方的来电显示号码为实际来电号码。</param>
         /// <returns></returns>
-        public async Task VisitorToOuterAsync(string visitorId, string outerPhoneNum, CancellationToken cancellationToken,
+        public async Task VisitorToOuterAsync(NewRockConfiguration newRockConfiguration, string visitorId, string outerPhoneNum, CancellationToken cancellationToken,
             string display = "")
         {
             await _newRockClient.VisitorToOuter(new VisitorToOuterRequest()
@@ -691,8 +700,8 @@ namespace Hotline.NewRock
                 Visitor = new VisitorToOuterVisitor() { Id = visitorId },
                 Outer = new VisitorToOuterOuter() { To = outerPhoneNum, Display = display },
 
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -704,15 +713,15 @@ namespace Hotline.NewRock
         /// <param name="menuId">菜单ID</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task VisitorToMenuAsync(string visitorId, string menuId, CancellationToken cancellationToken)
+        public async Task VisitorToMenuAsync(NewRockConfiguration newRockConfiguration, string visitorId, string menuId, CancellationToken cancellationToken)
         {
             await _newRockClient.VisitorToMenu(new VisitorToMenuRequest()
             {
                 Attribute = "Connect",
                 Visitor = new VisitorToMenuVisitor() { Id = visitorId },
                 Menu = new VisitorToMenuMenu() { Id = menuId }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -723,15 +732,15 @@ namespace Hotline.NewRock
         /// <param name="groupId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task VisitorToGroupAsync(string visitorId, string groupId, CancellationToken cancellationToken)
+        public async Task VisitorToGroupAsync(NewRockConfiguration newRockConfiguration, string visitorId, string groupId, CancellationToken cancellationToken)
         {
             await _newRockClient.VisitorToGroupQueue(new VisitorToGroupQueueRequest()
             {
                 Attribute = "Queue",
                 Visitor = new VisitorToGroupQueueVisitor() { Id = visitorId },
                 Group = new VisitorToGroupQueueGroup() { Id = groupId }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -742,7 +751,7 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task OuterToExtAsync(string outerId, string telNo, CancellationToken cancellationToken)
+        public async Task OuterToExtAsync(NewRockConfiguration newRockConfiguration, string outerId, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.OuterToExt(new OuterToExtRequest()
             {
@@ -750,8 +759,8 @@ namespace Hotline.NewRock
                 Outer = new OuterToExtOuter() { Id = outerId },
                 Ext = new OuterToExtExt() { Id = telNo }
             },
-                _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -762,7 +771,7 @@ namespace Hotline.NewRock
         /// <param name="outerPhoneNum">外部电话,外地电话加拨0</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task OuterToOuterAsync(string outerId, string outerPhoneNum, CancellationToken cancellationToken)
+        public async Task OuterToOuterAsync(NewRockConfiguration newRockConfiguration, string outerId, string outerPhoneNum, CancellationToken cancellationToken)
         {
             await _newRockClient.OuterToOuter(new OuterToOuterRequest()
             {
@@ -772,8 +781,8 @@ namespace Hotline.NewRock
                         new OuterToOuterOuterModel() { Id = outerId },
                         new OuterToOuterOuterModel() { To = outerPhoneNum }
                     },
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -785,15 +794,15 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task MenuToExtAsync(string menuId, string telNo, CancellationToken cancellationToken)
+        public async Task MenuToExtAsync(NewRockConfiguration newRockConfiguration, string menuId, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.MenuToExt(new MenuToExtRequest()
             {
                 Attribute = "Connect",
                 Menu = new MenuToExtMenu() { Id = menuId },
                 Ext = new MenuToExtExt() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -805,15 +814,15 @@ namespace Hotline.NewRock
         /// <param name="outerPhoneNum">外部电话,外地电话加拨0</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task MenuToOuterAsync(string menuId, string outerPhoneNum, CancellationToken cancellationToken)
+        public async Task MenuToOuterAsync(NewRockConfiguration newRockConfiguration, string menuId, string outerPhoneNum, CancellationToken cancellationToken)
         {
             await _newRockClient.MenuToOuter(new MenuToOuterRequest()
             {
                 Attribute = "Connect",
                 Menu = new MenuToOuterMenu() { Id = menuId },
                 Outer = new MenuToOuterOuter() { To = outerPhoneNum }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -824,7 +833,7 @@ namespace Hotline.NewRock
         /// <param name="outerTwo">被叫外部电话,外地电话加拨0</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task TwoWayOuterAsync(string outerOne, string outerTwo, CancellationToken cancellationToken)
+        public async Task TwoWayOuterAsync(NewRockConfiguration newRockConfiguration, string outerOne, string outerTwo, CancellationToken cancellationToken)
         {
             await _newRockClient.TwoWayOuter(new TwoWayOuterRequest()
             {
@@ -834,8 +843,8 @@ namespace Hotline.NewRock
                         new TwoWayOuterOuter(){ To = outerOne},
                         new TwoWayOuterOuter(){ To = outerTwo}
                     }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -846,15 +855,15 @@ namespace Hotline.NewRock
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task VoiceNewsFlashExtAsync(string voiceFileName, string telNo, CancellationToken cancellationToken)
+        public async Task VoiceNewsFlashExtAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.VoiceNewsFlash(new VoiceNewsFlashRequest
             {
                 Attribute = "Connect",
                 VoiceFile = voiceFileName,
                 Ext = new VoiceNewsFlashExt() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -865,7 +874,7 @@ namespace Hotline.NewRock
         /// <param name="visitorId">来电会话ID</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task VoiceNewsFlashVisitorAsync(string voiceFileName, string visitorId,
+        public async Task VoiceNewsFlashVisitorAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string visitorId,
             CancellationToken cancellationToken)
         {
             await _newRockClient.VoiceNewsFlash(
@@ -874,8 +883,8 @@ namespace Hotline.NewRock
                     Attribute = "Connect",
                     VoiceFile = voiceFileName,
                     Visitor = new VoiceNewsFlashVisitor() { Id = visitorId }
-                }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -886,7 +895,7 @@ namespace Hotline.NewRock
         /// <param name="outerId">去电会话ID</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task VoiceNewsFlashOuterAsync(string voiceFileName, string outerId, CancellationToken cancellationToken)
+        public async Task VoiceNewsFlashOuterAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string outerId, CancellationToken cancellationToken)
         {
             await _newRockClient.VoiceNewsFlash(
                 new VoiceNewsFlashRequest
@@ -894,8 +903,8 @@ namespace Hotline.NewRock
                     Attribute = "Connect",
                     VoiceFile = voiceFileName,
                     Outer = new VoiceNewsFlashOuter() { Id = outerId }
-                }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+                }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -905,14 +914,14 @@ namespace Hotline.NewRock
         /// <param name="telNo">发起方分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task ConferenceMeetingAsync(string telNo, CancellationToken cancellationToken)
+        public async Task ConferenceMeetingAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.ConferenceMeeting(new ConferenceMeetingRequest()
             {
                 Attribute = "Conference",
                 Ext = new ConferenceMeetingExt() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-                _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+                newRockConfiguration.Expired,
                 cancellationToken);
         }
 
@@ -923,7 +932,7 @@ namespace Hotline.NewRock
         /// <param name="ivrAnswer"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task HandleIvrAnswerAsync(CallDetail callDetail, IvrAnswer ivrAnswer, CancellationToken cancellationToken)
+        public async Task HandleIvrAnswerAsync(NewRockConfiguration newRockConfiguration, CallDetail callDetail, IvrAnswer ivrAnswer, CancellationToken cancellationToken)
         {
             if (string.IsNullOrEmpty(ivrAnswer.Content))
                 throw new UserFriendlyException("无效IVR应答参数");
@@ -944,14 +953,14 @@ namespace Hotline.NewRock
         /// <param name="secondTelNo">被监听方</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task MonitorExtAsync(string firstTelNo, string secondTelNo, CancellationToken cancellationToken)
+        public async Task MonitorExtAsync(NewRockConfiguration newRockConfiguration, string firstTelNo, string secondTelNo, CancellationToken cancellationToken)
         {
             await _newRockClient.MonitorExt(new MonitorExtRequest()
             {
                 Attribute = "Monitor",
                 Exts = new List<Ext>() { new Ext() { Id=firstTelNo },new Ext() { Id=secondTelNo } }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-             _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+             newRockConfiguration.Expired,
              cancellationToken) ;
         }
 
@@ -964,14 +973,14 @@ namespace Hotline.NewRock
         /// <param name="telNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task MonitorExtToTalkAsync(string telNo, CancellationToken cancellationToken)
+        public async Task MonitorExtToTalkAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.MonitorExtToTalk(new MonitorExtToTalkRequest()
             {
                 Attribute = "Talk",
                 Ext = new Ext() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-              _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+              newRockConfiguration.Expired,
               cancellationToken) ;
         }
 
@@ -985,14 +994,14 @@ namespace Hotline.NewRock
         /// <param name="telNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task MonitorExtToListenAsync(string telNo, CancellationToken cancellationToken)
+        public async Task MonitorExtToListenAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
         {
             await _newRockClient.MonitorExtToListen(new MonitorExtToListenRequest
             {
                 Attribute = "Listen",
                 Ext = new Ext() { Id = telNo }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-              _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+              newRockConfiguration.Expired,
               cancellationToken);
         }
 
@@ -1011,14 +1020,14 @@ namespace Hotline.NewRock
         /// <param name="secondTelNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        public async Task BargeinExtAsync(string firstTelNo,string secondTelNo,CancellationToken cancellationToken)
+        public async Task BargeinExtAsync(NewRockConfiguration newRockConfiguration, string firstTelNo,string secondTelNo,CancellationToken cancellationToken)
         {
             await _newRockClient.BargeinExt(new BargeinExtRequest()
             {
                 Attribute = "Bargein",
                 Exts = new List<Ext>() { new Ext() { Id = firstTelNo },new Ext() { Id=secondTelNo } }
-            }, _options.Value.DeviceConfigs.ReceiveKey,
-              _options.Value.DeviceConfigs.Expired,
+            }, newRockConfiguration.ReceiveKey,
+              newRockConfiguration.Expired,
               cancellationToken);
         }
 

+ 9 - 7
src/Hotline.NewRock/Handlers/DeviceEventHandler.cs

@@ -1,10 +1,12 @@
 using System.Security.Authentication;
 using Hotline.CallCenter;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.Share.Notifications.NewRockCallCenter;
 using MapsterMapper;
 using MediatR;
 using Microsoft.Extensions.Logging;
+using NewRock.Sdk;
 using NewRock.Sdk.Events;
 using NewRock.Sdk.Extensions;
 using NewRock.Sdk.Security;
@@ -29,7 +31,7 @@ namespace Hotline.NewRock.Handlers
             _logger = logger;
         }
 
-        public async Task HandleAsync(Stream eventStream, CallCenterConfiguration deviceConfigs,
+        public async Task HandleAsync(Stream eventStream, NewRockConfiguration newRockConfiguration,
             CancellationToken cancellationToken)
         {
             var sr = new StreamReader(eventStream);
@@ -42,8 +44,8 @@ namespace Hotline.NewRock.Handlers
                 //通话记录报告
                 var eventBase = content.DeserializeWithAuthorize<NewRockCdrEvent>();
                 if (eventBase.value == null) return;
-                if (deviceConfigs.DeviceConfigs.Authorize && (eventBase.authorize == null ||
-                                                !eventBase.authorize.IsAuthorized(deviceConfigs.DeviceConfigs.SendKey)))
+                if (newRockConfiguration.Authorize && (eventBase.authorize == null ||
+                                                       !eventBase.authorize.IsAuthorized(newRockConfiguration.SendKey)))
                     throw new AuthenticationException("无有效身份认证信息");
 
                 var cdrRcv = content.DeserializeWithAuthorize<CdrEvent>();
@@ -53,8 +55,8 @@ namespace Hotline.NewRock.Handlers
             {
                 var eventBase = content.DeserializeWithAuthorize<NewRockEvent>();
                 if (eventBase.value == null) return;
-                if (deviceConfigs.DeviceConfigs.Authorize && (eventBase.authorize == null ||
-                                                !eventBase.authorize.IsAuthorized(deviceConfigs.DeviceConfigs.SendKey)))
+                if (newRockConfiguration.Authorize && (eventBase.authorize == null ||
+                                                       !eventBase.authorize.IsAuthorized(newRockConfiguration.SendKey)))
                     throw new AuthenticationException("无有效身份认证信息");
 
                 switch (eventBase.value.Attribute)
@@ -191,7 +193,7 @@ namespace Hotline.NewRock.Handlers
                     case Event.BYE:
                         var byeRcv = content.DeserializeWithAuthorize<ByeEvent>();
                         //来电和分机的通话结束,来电挂断
-                        if (byeRcv.value?.Ext.Count==1 && byeRcv.value?.Visitor != null)
+                        if (byeRcv.value?.Ext.Count == 1 && byeRcv.value?.Visitor != null)
                         {
                             await _mediator.Publish(_mapper.Map<ByeVisitorAndExtNotification>(byeRcv.value!),
                                 cancellationToken);
@@ -209,7 +211,7 @@ namespace Hotline.NewRock.Handlers
                                 cancellationToken);
                         }
                         //分机和分机结束通话,挂断
-                        else if(byeRcv.value?.Ext.Count==2)
+                        else if (byeRcv.value?.Ext.Count == 2)
                         {
                             await _mediator.Publish(_mapper.Map<ByeExtAndExtNotification>(byeRcv.value!), cancellationToken);
                         }

+ 13 - 0
src/Hotline.NewRock/IDeviceEventHandler.cs

@@ -0,0 +1,13 @@
+using Hotline.CallCenter.Configs;
+using NewRock.Sdk;
+
+namespace Hotline.NewRock
+{
+    /// <summary>
+    /// 处理设备事件
+    /// </summary>
+    public interface IDeviceEventHandler
+    {
+        Task HandleAsync(Stream eventStream, NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken);
+    }
+}

+ 9 - 4
src/Hotline.NewRock/NewRockStartupExtensions.cs

@@ -1,20 +1,25 @@
-using Hotline.NewRock.Mappers;
+using Hotline.CallCenter.Configs;
+using Hotline.CallCenter.Devices;
+using Hotline.NewRock.Mappers;
 using Mapster;
+using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using NewRock.Sdk;
+using XF.Domain.Options;
 
 namespace Hotline.NewRock
 {
     public static class NewRockStartupExtensions
     {
-        public static IServiceCollection AddNewRock(this IServiceCollection services, string deviceAddress)
+        public static IServiceCollection AddNewRock(this IServiceCollection services, NewRockConfiguration newrockConfig)
         {
             services
-                .AddNewRockSdk(deviceAddress)
+                .AddNewRockSdk(newrockConfig.Address)
+                //.AddScoped<IDeviceManager, DeviceManager>()
                 ;
 
             TypeAdapterConfig.GlobalSettings.Scan(typeof(EventConfigs).Assembly);
-
+            
             return services;
         }
     }

+ 24 - 0
src/Hotline.Repository.SqlSugar/Extensions/XingTangDbExtensions.cs

@@ -0,0 +1,24 @@
+using Hotline.CallCenter.Configs;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using SqlSugar;
+
+namespace Hotline.Repository.SqlSugar.Extensions;
+
+public static class XingTangDbExtensions
+{
+    public static void AddXingTangDb(this IServiceCollection services, XingTangConfiguration xingTangConfiguration)
+    {
+        SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
+        {
+            DbType = DbType.MySql,
+            ConnectionString = xingTangConfiguration.DbConnectionString,
+            IsAutoCloseConnection = true,
+        },
+             db => { }
+         );
+
+        ISugarUnitOfWork<XingTangDbContext> context = new SugarUnitOfWork<XingTangDbContext>(sqlSugar);
+        services.AddSingleton(context);
+    }
+}

+ 8 - 0
src/Hotline.Repository.SqlSugar/XingTangDbContext.cs

@@ -0,0 +1,8 @@
+using SqlSugar;
+
+namespace Hotline.Repository.SqlSugar;
+
+public class XingTangDbContext : SugarUnitOfWork
+{
+
+}

+ 5 - 0
src/Hotline.Share/Dtos/Users/UserDto.cs

@@ -75,6 +75,11 @@ public record AddUserDto
     /// </summary>
     public string? DefaultTelNo { get; set; }
 
+    /// <summary>
+    /// 默认分机组(技能组)
+    /// </summary>
+    public string? DefaultTelGroup { get; set; }
+
     public string Email { get; set; }
 
     /// <summary>

+ 5 - 3
src/Hotline.Wex/WexStartupExtensions.cs

@@ -3,6 +3,8 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.CallCenter.Configs;
+using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Wex.Sdk;
 
@@ -10,10 +12,10 @@ namespace Hotline.Wex
 {
     public static class WexStartupExtensions
     {
-        public static IServiceCollection AddWex(this IServiceCollection services, string wexAddress)
+        public static IServiceCollection AddWex(this IServiceCollection services, WexConfiguration wexConfig)
         {
-            services.AddWexSdk(wexAddress);
-
+            services.AddWexSdk(wexConfig.Address);
+            
             return services;
         }
     }

+ 1 - 1
src/Hotline.Wex/WexTokenManager.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Options;
@@ -10,7 +11,6 @@ using Wex.Sdk;
 using XF.Domain.Cache;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
-using static System.Formats.Asn1.AsnWriter;
 
 namespace Hotline.Wex
 {

+ 20 - 11
src/Hotline/CallCenter/Calls/CallDomainService.cs

@@ -1,5 +1,7 @@
-using Hotline.CallCenter.Devices;
+using Hotline.CallCenter.Configs;
+using Hotline.CallCenter.Devices;
 using Hotline.Share.Requests;
+using Microsoft.Extensions.Options;
 using XF.Domain.Dependency;
 
 namespace Hotline.CallCenter.Calls
@@ -9,11 +11,18 @@ namespace Hotline.CallCenter.Calls
         private readonly IDeviceManager _deviceManager;
         private readonly ICallRepository _callRepository;
         private readonly ICallDetailRepository _callDetailRepository;
-        public CallDomainService(IDeviceManager deviceManager, ICallRepository callRepository, ICallDetailRepository callDetailRepository)
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
+
+        public CallDomainService(
+            IDeviceManager deviceManager, 
+            ICallRepository callRepository, 
+            ICallDetailRepository callDetailRepository,
+            IOptionsSnapshot<CallCenterConfiguration> options)
         {
             _deviceManager = deviceManager;
             _callRepository = callRepository;
             _callDetailRepository = callDetailRepository;
+            _options = options;
         }
 
         #region 来电
@@ -59,7 +68,7 @@ namespace Hotline.CallCenter.Calls
         public async Task VisitorToOuterAsync(VisitorToOuterRequest request, CancellationToken cancellationToken)
         {
             //调用设备接口转外线
-            await _deviceManager.VisitorToOuterAsync(request.VisitorId, request.OuterPhoneNum, cancellationToken);
+            await _deviceManager.VisitorToOuterAsync(_options.Value.NewRock, request.VisitorId, request.OuterPhoneNum, cancellationToken);
             //TODO 写入数据库通话记录
         }
 
@@ -72,7 +81,7 @@ namespace Hotline.CallCenter.Calls
         public async Task VisitorToIvrAsync(VisitorToIvrRequest request, CancellationToken cancellationToken)
         {
             //调用设备接口转语音菜单
-            await _deviceManager.VisitorToMenuAsync(request.VisitorId, request.MenuId, cancellationToken);
+            await _deviceManager.VisitorToMenuAsync(_options.Value.NewRock, request.VisitorId, request.MenuId, cancellationToken);
             //TODO 写入数据库通话记录
         }
 
@@ -84,7 +93,7 @@ namespace Hotline.CallCenter.Calls
         /// <returns></returns>
         public async Task VisitorToTelGroupAsync(VisitorToTelGroupRequest request, CancellationToken cancellationToken)
         {
-            await _deviceManager.VisitorToGroupAsync(request.VisitorId, request.GroupId, cancellationToken);
+            await _deviceManager.VisitorToGroupAsync(_options.Value.NewRock, request.VisitorId, request.GroupId, cancellationToken);
             //TODO 写入数据库通话记录
         }
 
@@ -119,7 +128,7 @@ namespace Hotline.CallCenter.Calls
             //};
             //await _callDetailRepository.AddAsync(detail, cancellationToken);
             //调用设备拨打电话
-            await _deviceManager.ExtToOuterAsync(request.ExtId, request.OuterPhoneNum, cancellationToken);
+            await _deviceManager.ExtToOuterAsync(_options.Value.NewRock, request.ExtId, request.OuterPhoneNum, cancellationToken);
         }
 
         #endregion
@@ -137,7 +146,7 @@ namespace Hotline.CallCenter.Calls
         public async Task AcceptVisitorAsync(AcceptVisitorRequest request, CancellationToken cancellationToken)
         {
             //调用设备受理
-            await _deviceManager.AcceptVisitorAsync(request.VisitorId, cancellationToken);
+            await _deviceManager.AcceptVisitorAsync(_options.Value.NewRock, request.VisitorId, cancellationToken);
         }
 
         #endregion
@@ -152,7 +161,7 @@ namespace Hotline.CallCenter.Calls
         /// <returns></returns>
         public async Task MonitorExt(MonitorExtRequest request,CancellationToken cancellationToken)
         {
-            await _deviceManager.MonitorExtAsync(request.firstTelNo, request.secondTelNo, cancellationToken);
+            await _deviceManager.MonitorExtAsync(_options.Value.NewRock, request.firstTelNo, request.secondTelNo, cancellationToken);
         }
 
         /// <summary>
@@ -166,7 +175,7 @@ namespace Hotline.CallCenter.Calls
         /// <returns></returns>
         public async Task MonitorExtToTalk(MonitorExtToTalkRequest request,CancellationToken cancellationToken)
         {
-            await _deviceManager.MonitorExtToTalkAsync(request.telNo, cancellationToken);
+            await _deviceManager.MonitorExtToTalkAsync(_options.Value.NewRock, request.telNo, cancellationToken);
         }
 
         /// <summary>
@@ -180,7 +189,7 @@ namespace Hotline.CallCenter.Calls
         /// <returns></returns>
         public async Task MonitorExtToListen(MonitorExtToListenRequest request,CancellationToken cancellationToken)
         {
-            await _deviceManager.MonitorExtToListenAsync(request.telNo, cancellationToken);
+            await _deviceManager.MonitorExtToListenAsync(_options.Value.NewRock, request.telNo, cancellationToken);
         }
 
         #endregion
@@ -198,7 +207,7 @@ namespace Hotline.CallCenter.Calls
         /// <returns></returns>
         public async Task BargeinExt(BargeinExtRequest request,CancellationToken cancellationToken)
         {
-            await _deviceManager.BargeinExtAsync(request.firstTelNo, request.secondTelNo, cancellationToken);
+            await _deviceManager.BargeinExtAsync(_options.Value.NewRock, request.firstTelNo, request.secondTelNo, cancellationToken);
         }
 
         #endregion

+ 3 - 1
src/Hotline/CallCenter/Calls/TrCallRecord.cs

@@ -6,6 +6,7 @@ using XF.Domain.Repository;
 
 namespace Hotline.CallCenter.Calls
 {
+    [SugarIndex("index_call_callid", nameof(TrCallRecord.OtherAccept), OrderByType.Asc)]
     public class TrCallRecord : CreationEntity
     {
         /// <summary>
@@ -89,7 +90,7 @@ namespace Hotline.CallCenter.Calls
         /// <summary>
         /// 状态码,语音信箱:999/其他:16
         /// </summary>
-        public string Status { get; set; }
+        public string? Status { get; set; }
         /// <summary>
         /// IVR开始时间
         /// </summary>
@@ -189,5 +190,6 @@ namespace Hotline.CallCenter.Calls
         public string? OperatorName { get; set; }
 
         #endregion
+        
     }
 }

+ 14 - 0
src/Hotline/CallCenter/Configs/CallCenterConfiguration.cs

@@ -0,0 +1,14 @@
+namespace Hotline.CallCenter.Configs;
+
+public class CallCenterConfiguration
+{
+    public string CallCenterType { get; set; }
+
+    public NewRockConfiguration NewRock { get; set; }
+
+    public WexConfiguration Wex { get; set; }
+
+    public TianrunConfiguration TianRun { get; set; }
+
+    public XingTangConfiguration XingTang { get; set; }
+}

+ 2 - 2
src/Hotline/CallCenter/Devices/DeviceConfigs.cs → src/Hotline/CallCenter/Configs/NewRockConfiguration.cs

@@ -1,6 +1,6 @@
-namespace Hotline.CallCenter.Devices
+namespace Hotline.CallCenter.Configs
 {
-    public class DeviceConfigs
+    public class NewRockConfiguration
     {
         public string Address { get; set; }
         public bool Authorize { get; set; }

+ 2 - 2
src/Tr.Sdk/TrConfiguration.cs → src/Hotline/CallCenter/Configs/TianrunConfiguration.cs

@@ -1,6 +1,6 @@
-namespace Tr.Sdk;
+namespace Hotline.CallCenter.Configs;
 
-public class TrConfiguration
+public class TianrunConfiguration
 {
     public string Address { get; set; }
     public string Username { get; set; }

+ 1 - 1
src/Wex.Sdk/WexConfiguration.cs → src/Hotline/CallCenter/Configs/WexConfiguration.cs

@@ -1,4 +1,4 @@
-namespace Wex.Sdk;
+namespace Hotline.CallCenter.Configs;
 
 public class WexConfiguration
 {

+ 7 - 0
src/Hotline/CallCenter/Configs/XingTangConfiguration.cs

@@ -0,0 +1,7 @@
+namespace Hotline.CallCenter.Configs
+{
+    public class XingTangConfiguration
+    {
+        public string DbConnectionString { get; set; }
+    }
+}

+ 0 - 10
src/Hotline/CallCenter/Devices/CallCenterConfiguration.cs

@@ -1,10 +0,0 @@
-namespace Hotline.CallCenter.Devices;
-
-public class CallCenterConfiguration
-{
-    public string CallCenterType { get; set; }
-
-    public DeviceConfigs DeviceConfigs { get; set; }
-
-    public WexConfiguration Wex { get; set; }
-}

+ 41 - 40
src/Hotline/CallCenter/Devices/IDeviceManager.cs

@@ -1,4 +1,5 @@
-using Hotline.CallCenter.Tels;
+using Hotline.CallCenter.Configs;
+using Hotline.CallCenter.Tels;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 
@@ -13,7 +14,7 @@ namespace Hotline.CallCenter.Devices
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task<TelDto> QueryTelAsync(string TelNo,CancellationToken cancellationToken);
+        Task<TelDto> QueryTelAsync(NewRockConfiguration newRockConfiguration, string TelNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询分机状态
@@ -21,28 +22,28 @@ namespace Hotline.CallCenter.Devices
         /// <param name="TelNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task<ETelStatus> QueryTelState(string TelNo, CancellationToken cancellationToken);
+        Task<ETelStatus> QueryTelState(NewRockConfiguration newRockConfiguration, string TelNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询所有分机
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task<List<Tel>> QueryTelsAsync(CancellationToken cancellationToken);
+        Task<List<Tel>> QueryTelsAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询所有分机组
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task<List<TelGroup>> QueryTelGroupsAsync(CancellationToken cancellationToken);
+        Task<List<TelGroup>> QueryTelGroupsAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询语音文件
         /// </summary>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task<string> VoiceQueryListAsync(CancellationToken cancellationToken);
+        Task<string> VoiceQueryListAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken);
         #endregion
 
         #region 配置
@@ -53,7 +54,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task TelRestAsync(string telNo, CancellationToken cancellationToken);
+        Task TelRestAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 分机结束休息
@@ -61,7 +62,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task TelEndRestAsync(string telNo, CancellationToken cancellationToken);
+        Task TelEndRestAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
 
         /// <summary>
@@ -71,7 +72,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="staffNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task UpdateStaffNoAsync(string telNo, string staffNo, string lineId, CancellationToken cancellationToken);
+        Task UpdateStaffNoAsync(NewRockConfiguration newRockConfiguration, string telNo, string staffNo, string lineId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 删除语音文件
@@ -79,7 +80,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="voiceName"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task RemoveVoiceFileAsync(string voiceName, CancellationToken cancellationToken);
+        Task RemoveVoiceFileAsync(NewRockConfiguration newRockConfiguration, string voiceName, CancellationToken cancellationToken);
 
         /// <summary>
         /// 配置语音菜单
@@ -91,7 +92,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="exit"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task AssginConfigMenuAsync(string menuId, string voiceFile, string repeat, string infoLength, string exit,
+        Task AssginConfigMenuAsync(NewRockConfiguration newRockConfiguration, string menuId, string voiceFile, string repeat, string infoLength, string exit,
             CancellationToken cancellationToken);
 
         /// <summary>
@@ -103,7 +104,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="ext"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task AssginConfigGroupAsync(string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "", CancellationToken cancellationToken = default);
+        Task AssginConfigGroupAsync(NewRockConfiguration newRockConfiguration, string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "", CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 更新分机组
@@ -113,7 +114,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="cancellationToken"></param>
         /// <param name="isAdd"></param>
         /// <returns></returns>
-        Task ModifyGroupExtAsync(string groupId, EDistribution distribution, string voicefile = "", string extId = "", bool isAdd= true, CancellationToken cancellationToken = default);
+        Task ModifyGroupExtAsync(NewRockConfiguration newRockConfiguration, string groupId, EDistribution distribution, string voicefile = "", string extId = "", bool isAdd = true, CancellationToken cancellationToken = default);
         #endregion
 
         #region 通话控制
@@ -124,7 +125,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task HoldAsync(string telNo, CancellationToken cancellationToken);
+        Task HoldAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 恢复通话(解除hold状态)
@@ -132,7 +133,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task UnHoldAsync(string telNo, CancellationToken cancellationToken);
+        Task UnHoldAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 开启静音
@@ -140,7 +141,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task MuteAsync(string telNo, CancellationToken cancellationToken);
+        Task MuteAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 解除静音命令
@@ -148,7 +149,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task UnMuteAsync(string telNo, CancellationToken cancellationToken);
+        Task UnMuteAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 强拆分机
@@ -156,7 +157,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="extId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task ClearExtAsync(string extId, CancellationToken cancellationToken);
+        Task ClearExtAsync(NewRockConfiguration newRockConfiguration, string extId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 强拆来电
@@ -164,7 +165,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="visitorId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task ClearVisitorAsync(string visitorId, CancellationToken cancellationToken);
+        Task ClearVisitorAsync(NewRockConfiguration newRockConfiguration, string visitorId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 强拆去电
@@ -172,7 +173,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="outerId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task ClearOuterAsync(string outerId, CancellationToken cancellationToken);
+        Task ClearOuterAsync(NewRockConfiguration newRockConfiguration, string outerId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 来电受理
@@ -180,7 +181,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="visitorId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task AcceptVisitorAsync(string visitorId, CancellationToken cancellationToken);
+        Task AcceptVisitorAsync(NewRockConfiguration newRockConfiguration, string visitorId, CancellationToken cancellationToken);
         #endregion
 
         #region 连接/呼叫
@@ -192,7 +193,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="to">被叫分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task ExtToExtAsync(string from, string to, CancellationToken cancellationToken);
+        Task ExtToExtAsync(NewRockConfiguration newRockConfiguration, string from, string to, CancellationToken cancellationToken);
 
         /// <summary>
         /// 分机呼外部电话
@@ -202,7 +203,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="cancellationToken"></param>
         /// <param name="trunkid">指定中继线路(可为空),为空时默认由OM分配</param>
         /// <returns></returns>
-        Task ExtToOuterAsync(string from, string to, CancellationToken cancellationToken, string trunkid = "");
+        Task ExtToOuterAsync(NewRockConfiguration newRockConfiguration, string from, string to, CancellationToken cancellationToken, string trunkid = "");
 
         /// <summary>
         /// 来电转分机
@@ -211,7 +212,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task VisitorToExtAsync(string visitorId, string telNo, CancellationToken cancellationToken);
+        Task VisitorToExtAsync(NewRockConfiguration newRockConfiguration, string visitorId, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 来电转外部电话
@@ -221,7 +222,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="cancellationToken"></param>
         /// <param name="display">来电号码,用来透传主叫号码,使去电方的来电显示号码为实际来电号码。</param>
         /// <returns></returns>
-        Task VisitorToOuterAsync(string visitorId, string outerPhoneNum, CancellationToken cancellationToken,
+        Task VisitorToOuterAsync(NewRockConfiguration newRockConfiguration, string visitorId, string outerPhoneNum, CancellationToken cancellationToken,
             string display = "");
 
         /// <summary>
@@ -231,7 +232,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="menuId">菜单ID</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task VisitorToMenuAsync(string visitorId, string menuId, CancellationToken cancellationToken);
+        Task VisitorToMenuAsync(NewRockConfiguration newRockConfiguration, string visitorId, string menuId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 来电转分机组
@@ -240,7 +241,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="groupId"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task VisitorToGroupAsync(string visitorId, string groupId, CancellationToken cancellationToken);
+        Task VisitorToGroupAsync(NewRockConfiguration newRockConfiguration, string visitorId, string groupId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 去电转分机
@@ -249,7 +250,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task OuterToExtAsync(string outerId, string telNo, CancellationToken cancellationToken);
+        Task OuterToExtAsync(NewRockConfiguration newRockConfiguration, string outerId, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 去电转外部电话
@@ -258,7 +259,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="outerPhoneNum">外部电话,外地电话加拨0</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task OuterToOuterAsync(string outerId, string outerPhoneNum, CancellationToken cancellationToken);
+        Task OuterToOuterAsync(NewRockConfiguration newRockConfiguration, string outerId, string outerPhoneNum, CancellationToken cancellationToken);
 
         /// <summary>
         /// 语音菜单呼叫分机
@@ -267,7 +268,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task MenuToExtAsync(string menuId, string telNo, CancellationToken cancellationToken);
+        Task MenuToExtAsync(NewRockConfiguration newRockConfiguration, string menuId, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 语音菜单呼外部电话
@@ -276,7 +277,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="outerPhoneNum">外部电话,外地电话加拨0</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task MenuToOuterAsync(string menuId, string outerPhoneNum, CancellationToken cancellationToken);
+        Task MenuToOuterAsync(NewRockConfiguration newRockConfiguration, string menuId, string outerPhoneNum, CancellationToken cancellationToken);
 
         /// <summary>
         /// 双向呼叫(回拨)
@@ -285,7 +286,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="outerTwo">被叫外部电话,外地电话加拨0</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task TwoWayOuterAsync(string outerOne, string outerTwo, CancellationToken cancellationToken);
+        Task TwoWayOuterAsync(NewRockConfiguration newRockConfiguration, string outerOne, string outerTwo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 语音插播(分机)
@@ -294,7 +295,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task VoiceNewsFlashExtAsync(string voiceFileName, string telNo, CancellationToken cancellationToken);
+        Task VoiceNewsFlashExtAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string telNo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 语音插播(来电)
@@ -303,7 +304,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="visitorId">来电会话ID</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task VoiceNewsFlashVisitorAsync(string voiceFileName, string visitorId, CancellationToken cancellationToken);
+        Task VoiceNewsFlashVisitorAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string visitorId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 语音插播(去电)
@@ -312,7 +313,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="outerId">去电会话ID</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task VoiceNewsFlashOuterAsync(string voiceFileName, string outerId, CancellationToken cancellationToken);
+        Task VoiceNewsFlashOuterAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string outerId, CancellationToken cancellationToken);
 
         /// <summary>
         /// 会议
@@ -320,7 +321,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo">发起方分机号</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task ConferenceMeetingAsync(string telNo, CancellationToken cancellationToken);
+        Task ConferenceMeetingAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
         #endregion
 
@@ -334,7 +335,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="secondTelNo">被监听方</param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task MonitorExtAsync(string firstTelNo, string secondTelNo, CancellationToken cancellationToken);
+        Task MonitorExtAsync(NewRockConfiguration newRockConfiguration, string firstTelNo, string secondTelNo, CancellationToken cancellationToken);
 
 
         /// <summary>
@@ -346,7 +347,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task MonitorExtToTalkAsync(string telNo, CancellationToken cancellationToken);
+        Task MonitorExtToTalkAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
 
         /// <summary>
@@ -358,7 +359,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="telNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task MonitorExtToListenAsync(string telNo, CancellationToken cancellationToken);
+        Task MonitorExtToListenAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken);
 
 
         #endregion
@@ -376,7 +377,7 @@ namespace Hotline.CallCenter.Devices
         /// <param name="secondTelNo"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
-        Task BargeinExtAsync(string firstTelNo, string secondTelNo, CancellationToken cancellationToken);
+        Task BargeinExtAsync(NewRockConfiguration newRockConfiguration, string firstTelNo, string secondTelNo, CancellationToken cancellationToken);
 
         #endregion
     }

+ 0 - 8
src/Hotline/CallCenter/Devices/WexConfiguration.cs

@@ -1,8 +0,0 @@
-namespace Hotline.CallCenter.Devices;
-
-public class WexConfiguration
-{
-    public string Address { get; set; }
-    public string Username { get; set; }
-    public string Password { get; set; }
-}

+ 0 - 12
src/Hotline/CallCenter/IDeviceEventHandler.cs

@@ -1,12 +0,0 @@
-using Hotline.CallCenter.Devices;
-
-namespace Hotline.CallCenter
-{
-    /// <summary>
-    /// 处理设备事件
-    /// </summary>
-    public interface IDeviceEventHandler
-    {
-        Task HandleAsync(Stream eventStream, CallCenterConfiguration deviceConfigs, CancellationToken cancellationToken);
-    }
-}

+ 7 - 2
src/Hotline/CallCenter/Ivrs/IvrDomainService.cs

@@ -1,10 +1,12 @@
 using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.Settings;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using MapsterMapper;
 using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
 using XF.Domain.Cache;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
@@ -23,6 +25,7 @@ public class IvrDomainService : IIvrDomainService, IScopeDependency
     private readonly IMapper _mapper;
     private readonly ILogger<IvrDomainService> _logger;
     private readonly ITypedCache<List<TrunkIvrManager>> _worktimeCache;
+    private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
     private readonly IRepository<TrunkIvrManager> _trunkIvrManagerRepository;
 
     public IvrDomainService(
@@ -35,6 +38,7 @@ public class IvrDomainService : IIvrDomainService, IScopeDependency
         IMapper mapper,
         ILogger<IvrDomainService> logger,
         ITypedCache<List<TrunkIvrManager>> worktimeCache,
+        IOptionsSnapshot<CallCenterConfiguration> options,
         IRepository<TrunkIvrManager> trunkIvrManagerRepository)
     {
         _deviceManager = deviceManager;
@@ -46,6 +50,7 @@ public class IvrDomainService : IIvrDomainService, IScopeDependency
         _mapper = mapper;
         _logger = logger;
         _worktimeCache = worktimeCache;
+        _options = options;
         _trunkIvrManagerRepository = trunkIvrManagerRepository;
     }
 
@@ -164,7 +169,7 @@ public class IvrDomainService : IIvrDomainService, IScopeDependency
         if (existNo)
             throw new UserFriendlyException("IVR编号已存在");
 
-        await _deviceManager.AssginConfigMenuAsync(ivr.No, ivr.Voice, ivr.Repeat.ToString(), ivr.InfoLength.ToString(), ivr.Exit, cancellationToken);
+        await _deviceManager.AssginConfigMenuAsync(_options.Value.NewRock, ivr.No, ivr.Voice, ivr.Repeat.ToString(), ivr.InfoLength.ToString(), ivr.Exit, cancellationToken);
 
         var exists = await _ivrRepository.AnyAsync(d => d.IvrCategoryId == ivr.IvrCategoryId, cancellationToken);
         ivr.IsRoot = !exists;
@@ -175,7 +180,7 @@ public class IvrDomainService : IIvrDomainService, IScopeDependency
 
     public async Task UpdateIvrAsync(Ivr ivr, CancellationToken cancellationToken = default)
     {
-        await _deviceManager.AssginConfigMenuAsync(ivr.No, ivr.Voice, ivr.Repeat.ToString(), ivr.InfoLength.ToString(), ivr.Exit, cancellationToken);
+        await _deviceManager.AssginConfigMenuAsync(_options.Value.NewRock, ivr.No, ivr.Voice, ivr.Repeat.ToString(), ivr.InfoLength.ToString(), ivr.Exit, cancellationToken);
 
         await _ivrRepository.UpdateWithoutStrategiesAsync(ivr, cancellationToken);
         _cacheIvrList.Remove(Ivr.Key);

+ 8 - 4
src/Hotline/CallCenter/Manage/VoiceFileDomainService.cs

@@ -1,5 +1,7 @@
-using Hotline.CallCenter.Devices;
+using Hotline.CallCenter.Configs;
+using Hotline.CallCenter.Devices;
 using Hotline.Share.Requests;
+using Microsoft.Extensions.Options;
 using XF.Domain.Dependency;
 
 namespace Hotline.CallCenter.Manage
@@ -7,10 +9,12 @@ namespace Hotline.CallCenter.Manage
     public class VoiceFileDomainService:IVoiceFileDomainService, IScopeDependency
     {
         private readonly IDeviceManager _deviceManager;
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
 
-        public VoiceFileDomainService(IDeviceManager deviceManager)
+        public VoiceFileDomainService(IDeviceManager deviceManager, IOptionsSnapshot<CallCenterConfiguration> options)
         {
             _deviceManager = deviceManager;
+            _options = options;
         }
 
         /// <summary>
@@ -20,7 +24,7 @@ namespace Hotline.CallCenter.Manage
         /// <returns></returns>
         public async Task<List<string>> VoiceQueryListAsync(CancellationToken cancellationToken)
         {
-            var result = await _deviceManager.VoiceQueryListAsync(cancellationToken);
+            var result = await _deviceManager.VoiceQueryListAsync(_options.Value.NewRock, cancellationToken);
             var list =  result.Replace(".dat","").Replace(".pcm","").Split("|").ToList();
 
             return list.Distinct().ToList();
@@ -34,7 +38,7 @@ namespace Hotline.CallCenter.Manage
         /// <returns></returns>
         public async Task RemoveVoiceFileAsync(RemoveVoiceFileRequest request, CancellationToken cancellationToken)
         {
-            await _deviceManager.RemoveVoiceFileAsync(request.VoiceFileNames, cancellationToken);
+            await _deviceManager.RemoveVoiceFileAsync(_options.Value.NewRock, request.VoiceFileNames, cancellationToken);
         }
 
 

+ 2 - 3
src/Hotline/CallCenter/Tels/Tel.cs

@@ -21,13 +21,12 @@ public class Tel : CreationSoftDeleteEntity
     /// <summary>
     /// 上线IP
     /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string RegisterIP { get; set; }
+    public string? RegisterIP { get; set; }
 
     /// <summary>
     /// 分机线路编号
     /// </summary>
-    public string LineId { get; set; }
+    public string? LineId { get; set; }
 
     /// <summary>
     /// 分机状态

+ 9 - 8
src/Hotline/CallCenter/Tels/TelDomainService.cs

@@ -8,6 +8,7 @@ using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Configs;
 using Microsoft.Extensions.Options;
 using Hotline.Share.Dtos.CallCenter;
 
@@ -48,7 +49,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
     /// <param name="cancellationToken"></param>
     /// <returns></returns>
     public Task<List<Tel>> QueryTelsAsync(CancellationToken cancellationToken)
-        => _deviceManager.QueryTelsAsync(cancellationToken);
+        => _deviceManager.QueryTelsAsync(_options.Value.NewRock, cancellationToken);
 
     /// <summary>
     /// 查询所有分机组
@@ -56,7 +57,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
     /// <param name="cancellationToken"></param>
     /// <returns></returns>
     public Task<List<TelGroup>> QueryTelGroupsAsync(CancellationToken cancellationToken)
-        => _deviceManager.QueryTelGroupsAsync(cancellationToken);
+        => _deviceManager.QueryTelGroupsAsync(_options.Value.NewRock, cancellationToken);
 
     /// <summary>
     /// 分机休息审批流程开始
@@ -137,7 +138,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
             var tel = _telCacheManager.GetTel(telRest.TelNo);
             foreach (var group in tel.Groups)
             {
-                await _deviceManager.ModifyGroupExtAsync(group.No, group.Distribution, group.Voice, tel.No, true, cancellationToken);
+                await _deviceManager.ModifyGroupExtAsync(_options.Value.NewRock, group.No, group.Distribution, group.Voice, tel.No, true, cancellationToken);
             }
             #endregion
         }
@@ -189,7 +190,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
             //更新分机组
             foreach (var group in telCache.Groups)
             {
-                await _deviceManager.ModifyGroupExtAsync(group.No, group.Distribution, group.Voice, "", true, cancellationToken);
+                await _deviceManager.ModifyGroupExtAsync(_options.Value.NewRock, group.No, group.Distribution, group.Voice, "", true, cancellationToken);
             }
 
             #endregion
@@ -211,7 +212,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
             var tel = await _telRepository.GetAsync(telId, cancellationToken);
             if (tel is null)
                 throw new UserFriendlyException("无效分机编号");
-            await _deviceManager.HoldAsync(tel.No, cancellationToken);
+            await _deviceManager.HoldAsync(_options.Value.NewRock, tel.No, cancellationToken);
             await _telHoldRepository.AddAsync(new Calls.TelHold() { TelId = telId, TelNo = tel.No, UserId = userId, UserName = userName, CallId = callId }, cancellationToken);
         }
     }
@@ -227,7 +228,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
         var tel = await _telRepository.GetAsync(telId, cancellationToken);
         if (tel is null)
             throw new UserFriendlyException("无效分机编号");
-        await _deviceManager.UnHoldAsync(tel.No, cancellationToken);
+        await _deviceManager.UnHoldAsync(_options.Value.NewRock, tel.No, cancellationToken);
         var holdingTel = await _telHoldRepository.GetAsync(d => d.TelId == telId && d.TelNo == tel.No && d.UserId == userId && d.CallId == callId && !d.EndTime.HasValue);
         if (holdingTel is null)
             throw new UserFriendlyException("未找到分机保持信息");
@@ -247,7 +248,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
         var tel = await _telRepository.GetAsync(telId, cancellationToken);
         if (tel is null)
             throw new UserFriendlyException("无效分机编号");
-        await _deviceManager.MuteAsync(tel.No, cancellationToken);
+        await _deviceManager.MuteAsync(_options.Value.NewRock, tel.No, cancellationToken);
     }
 
     /// <summary>
@@ -261,6 +262,6 @@ public class TelDomainService : ITelDomainService, IScopeDependency
         var tel = await _telRepository.GetAsync(telId, cancellationToken);
         if (tel is null)
             throw new UserFriendlyException("无效分机编号");
-        await _deviceManager.MuteAsync(tel.No, cancellationToken);
+        await _deviceManager.MuteAsync(_options.Value.NewRock, tel.No, cancellationToken);
     }
 }

+ 1 - 1
src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs

@@ -330,7 +330,7 @@ public abstract class StepBasicEntity : CreationEntity
     /// <summary>
     /// 办理意见
     /// </summary>
-    [SugarColumn(Length = 2000)]
+    [SugarColumn(Length = 8000)]
     public string? Opinion { get; set; }
 
     /// <summary>

+ 1 - 1
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -148,7 +148,7 @@ public partial class Workflow : CreationEntity
     /// <summary>
     /// 实际办理意见(办理中...or 最终办理意见)
     /// </summary>
-    [SugarColumn(Length = 2000)]
+    [SugarColumn(Length = 8000)]
     public string ActualOpinion { get; set; } = "办理中...";
 
     /// <summary>

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

@@ -316,6 +316,7 @@ namespace Hotline.Orders
         /// <summary>
         /// 交办意见
         /// </summary>
+        [SugarColumn(Length = 8000)]
         public string? CenterToOrgOpinion { get; set; }
 
         /// <summary>
@@ -466,7 +467,7 @@ namespace Hotline.Orders
         /// <summary>
         /// 实际办理意见(办理中...or 最终办理意见)
         /// </summary>
-        [SugarColumn(Length = 2000)]
+        [SugarColumn(Length = 8000)]
         public string ActualOpinion { get; set; } = "办理中...";
 
         /// <summary>

+ 5 - 0
src/Hotline/Users/User.cs

@@ -48,6 +48,11 @@ namespace Hotline.Users
         /// </summary>
         public string? DefaultTelNo { get; set; }
 
+        /// <summary>
+        /// 默认分机组(技能组)
+        /// </summary>
+        public string? DefaultTelGroup { get; set; }
+
         /// <summary>
         /// 用户类型
         /// </summary>

+ 12 - 8
src/Hotline/Users/UserDomainService.cs

@@ -7,6 +7,8 @@ using Hotline.Share.Dtos.Users;
 using MapsterMapper;
 using Microsoft.AspNetCore.Http;
 using System.Security.Cryptography;
+using Hotline.CallCenter.Configs;
+using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Cache;
 using XF.Domain.Constants;
@@ -27,7 +29,8 @@ namespace Hotline.Users
         private readonly IMapper _mapper;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
         private readonly ISessionContext _sessionContext;
-       
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
+
 
         public UserDomainService(
             IRepository<User> userRepository,
@@ -38,8 +41,8 @@ namespace Hotline.Users
             IMapper mapper,
             ITelCacheManager telCacheManager,
             ISystemSettingCacheManager systemSettingCacheManager,
-            ISessionContext sessionContext
-            )
+            ISessionContext sessionContext,
+            IOptionsSnapshot<CallCenterConfiguration> options)
         {
             _userRepository = userRepository;
             _workRepository = workRepository;
@@ -50,6 +53,7 @@ namespace Hotline.Users
             _telCacheManager = telCacheManager;
             _systemSettingCacheManager = systemSettingCacheManager;
             _sessionContext = sessionContext;
+            _options = options;
         }
 
         /// <summary>
@@ -77,12 +81,12 @@ namespace Hotline.Users
             await _workRepository.AddAsync(work, cancellationToken);
 
             if (!string.IsNullOrEmpty(user.StaffNo))
-                await _deviceManager.UpdateStaffNoAsync(tel.No, user.StaffNo, tel.LineId, cancellationToken);
+                await _deviceManager.UpdateStaffNoAsync(_options.Value.NewRock, tel.No, user.StaffNo, tel.LineId, cancellationToken);
 
             //更新分机组
             foreach (var group in tel.Groups)
             {
-                await _deviceManager.AssginConfigGroupAsync(group.No, group.Distribution, new List<string>() { tel.No }, group.Voice, cancellationToken);
+                await _deviceManager.AssginConfigGroupAsync(_options.Value.NewRock, group.No, group.Distribution, new List<string>() { tel.No }, group.Voice, cancellationToken);
             }
 
 
@@ -100,17 +104,17 @@ namespace Hotline.Users
             var tel = _telCacheManager.GetTel(work.TelNo);
             work.OffDuty();
             await _workRepository.UpdateAsync(work, cancellationToken);
-            await _deviceManager.UpdateStaffNoAsync(work.TelNo, string.Empty, tel.LineId, cancellationToken);
+            await _deviceManager.UpdateStaffNoAsync(_options.Value.NewRock, work.TelNo, string.Empty, tel.LineId, cancellationToken);
             _cacheWork.Remove(work.GetKey(KeyMode.UserId));
             _cacheWork.Remove(work.GetKey(KeyMode.TelNo));
             #region 初始化话机
 
             //初始化解除静音
-            await _deviceManager.UnMuteAsync(tel.No, cancellationToken);
+            await _deviceManager.UnMuteAsync(_options.Value.NewRock, tel.No, cancellationToken);
 
             foreach (var group in tel.Groups)
             {
-                await _deviceManager.ModifyGroupExtAsync(group.No, group.Distribution, group.Voice, "", false, cancellationToken);
+                await _deviceManager.ModifyGroupExtAsync(_options.Value.NewRock, group.No, group.Distribution, group.Voice, "", false, cancellationToken);
             }
 
             #endregion

+ 1 - 1
src/NewRock.Sdk/Security/AuthorizeGenerator.cs

@@ -22,7 +22,7 @@ namespace NewRock.Sdk.Security
         public NewRockAuthorize GetAuthorize(string key, int expired)
         {
             using var scope = _serviceScopeFactory.CreateScope();
-            //var options = scope.ServiceProvider.GetService<IOptionsSnapshot<DeviceConfigs>>();
+            //var options = scope.ServiceProvider.GetService<IOptionsSnapshot<NewRockConfiguration>>();
             var mapper = scope.ServiceProvider.GetService<IMapper>();
             //var key = options.Value.ReceiveKey;
 

+ 1 - 0
src/XF.Domain.Repository/Entity.cs

@@ -22,6 +22,7 @@ public abstract class Entity : IEntity<string>, IDomainEvents, IDataPermission,
 
     public string? CreatorOrgName { get; set; }
 
+    [SugarColumn(DefaultValue = "0")]
     public int CreatorOrgLevel { get; set; } = 0;
 
     /// <summary>

+ 4 - 2
src/XF.Domain/Dependency/DependencyInjectionExtensions.cs

@@ -19,7 +19,8 @@ public static class DependencyInjectionExtensions
     private static void InjectBackgroundServices(IServiceCollection services, List<Assembly> assemblies)
     {
         var types = assemblies.SelectMany(t => t.GetTypes())
-            .Where(t => typeof(BackgroundService).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract).ToList();
+            .Where(t => typeof(BackgroundService).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract
+            && t.GetInterfaces().All(d => d != typeof(IIgnoreDependency))).ToList();
 
         foreach (var type in types)
         {
@@ -32,7 +33,8 @@ public static class DependencyInjectionExtensions
             .Where(d => d.GetInterfaces().Any(x =>
                 x == typeof(IScopeDependency)
                 || x == typeof(ISingletonDependency)
-                || x == typeof(ITransientDependency)))
+                || x == typeof(ITransientDependency))
+                        && d.GetInterfaces().All(x => x != typeof(IIgnoreDependency)))
             .ToList()
             .ForEach(d => ServiceRegister.Register(services, d));
     }

+ 6 - 0
src/XF.Domain/Dependency/IIgnoreDependency.cs

@@ -0,0 +1,6 @@
+namespace XF.Domain.Dependency;
+
+public interface IIgnoreDependency
+{
+
+}

+ 13 - 0
src/XingTang.Sdk/XingTang.Sdk.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net7.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="SqlSugarCore" Version="5.1.4.153" />
+  </ItemGroup>
+
+</Project>

+ 163 - 0
src/XingTang.Sdk/XingtangCall.cs

@@ -0,0 +1,163 @@
+using SqlSugar;
+
+namespace XingTang.Sdk;
+
+[SugarTable("call_cti_trafficlist")]
+public class XingtangCall
+{
+    [SugarColumn(ColumnName = "ID")]
+    public int Id { get; set; }
+
+    /// <summary>
+    /// 客户id
+    /// </summary>
+    [SugarColumn(ColumnName = "CustomerID")]
+    public string CustomerId { get; set; }
+
+    public string CallGuid { get; set; }
+
+    /// <summary>
+    /// 主叫
+    /// </summary>
+    public string Caller { get; set; }
+
+    /// <summary>
+    /// 被叫
+    /// </summary>
+    public string Called { get; set; }
+
+    /// <summary>
+    /// 工号
+    /// </summary>
+    public string UserCode { get; set; }
+
+    /// <summary>
+    /// 分机号
+    /// </summary>
+    public string Ext { get; set; }
+
+    /// <summary>
+    /// 0:呼入,1:呼出
+    /// </summary>
+    public int CallType { get; set; }
+
+    /// <summary>
+    /// 呼叫开始时间
+    /// </summary>
+    public DateTime CallStartTime { get; set; }
+
+    /// <summary>
+    /// 振铃时间
+    /// </summary>
+    public DateTime? ReceiveStartTime { get; set; }
+
+    /// <summary>
+    /// 接听时间
+    /// </summary>
+    public DateTime? ReceiveEndTime { get; set; }
+
+    /// <summary>
+    /// 挂机时间
+    /// </summary>
+    public DateTime CallEndTime { get; set; }
+    
+    /// <summary>
+    /// 时长
+    /// </summary>
+    public int Duration { get; set; }
+    
+    /// <summary>
+    /// 录音文件
+    /// </summary>
+    public string AudioFile { get; set; }
+    
+    /// <summary>
+    /// 等待时长
+    /// </summary>
+    public int WaitTime { get; set; }
+    
+    /// <summary>
+    /// 振铃时长
+    /// </summary>
+    public int RingTime { get; set; }
+
+    /// <summary>
+    /// 呼叫状态 0 留言 1 队列等待超时 2 坐席振铃超时 3 未接 4 满意度 5 通话 6 IVR 7 振铃挂机 8 分机互打挂机 9 ASR交互
+    /// </summary>
+    public int CallState { get; set; }
+
+    /// <summary>
+    /// 呼出通道号
+    /// </summary>
+    [SugarColumn(ColumnName = "CallOut_Channel")]
+    public int CallOutChannel { get; set; }
+    
+    /// <summary>
+    /// 呼入通道号
+    /// </summary>
+    [SugarColumn(ColumnName = "CallIn_Channel")]
+    public int CallInChannel { get; set; }
+    
+    /// <summary>
+    /// 进队列时间
+    /// </summary>
+    public DateTime? EnqueueTime { get; set; }
+    
+    /// <summary>
+    /// 出队列时间
+    /// </summary>
+    public DateTime? DequeueTime { get; set; }
+    
+    public string? CompanyId { get; set; }
+    
+    public int? SkillId { get; set; }
+    public int? MeetingId { get; set; }
+
+    /// <summary>
+    /// 挂机原因
+    /// </summary>
+    public string? Cause { get; set; }
+
+    /// <summary>
+    /// 挂机方
+    /// </summary>
+    public string? Disposition { get; set; }
+
+    /// <summary>
+    /// 原主叫
+    /// </summary>
+    public string? OrgCaller { get; set; }
+
+    #region 未启用
+
+    public int MutiCall { get; set; }
+    public int CallForword { get; set; }
+    public DateTime RingStartTime { get; set; }
+
+    [SugarColumn(ColumnName = "Trans_Called")]
+    public string TransCalled { get; set; }
+
+    [SugarColumn(ColumnName = "UserListID")]
+    public int UserListId { get; set; }
+
+    public int Score { get; set; }
+    public string MarkRemark { get; set; }
+    public string MarkUserId { get; set; }
+    public DateTime MarkDate { get; set; }
+    public int MarkState { get; set; }
+    public int IsAssign { get; set; }
+    public int ResultKey { get; set; }
+    public int Direction { get; set; }
+    #endregion
+
+    #region 自建
+
+    public bool IsSync { get; set; }
+
+    public int Tries { get; set; }
+
+    [SugarColumn(IsEnableUpdateVersionValidation = true)]
+    public string Ver { get; set; }
+
+    #endregion
+}