Forráskód Böngészése

Merge branch 'release/yibin'

xf 9 hónapja
szülő
commit
f694bb1cd4
100 módosított fájl, 4203 hozzáadás és 1234 törlés
  1. 7 0
      Hotline.sln
  2. 1 0
      src/Hotline.Api/Controllers/AiController.cs
  3. 12 0
      src/Hotline.Api/Controllers/Bi/BiKnowledgeController.cs
  4. 461 87
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  5. 15 15
      src/Hotline.Api/Controllers/HomeController.cs
  6. 4 5
      src/Hotline.Api/Controllers/IPPbxController.cs
  7. 90 15
      src/Hotline.Api/Controllers/OrderController.cs
  8. 140 0
      src/Hotline.Api/Controllers/OrderProvinceZmhdController.cs
  9. 35 30
      src/Hotline.Api/Controllers/PbxController.cs
  10. 3 1
      src/Hotline.Api/Controllers/ReportController.cs
  11. 30 24
      src/Hotline.Api/Controllers/TelController.cs
  12. 14 3
      src/Hotline.Api/Controllers/TestController.cs
  13. 82 81
      src/Hotline.Api/Controllers/TestSdkController.cs
  14. 39 20
      src/Hotline.Api/Controllers/UserController.cs
  15. 2 2
      src/Hotline.Api/Controllers/WorkflowController.cs
  16. 50 23
      src/Hotline.Api/StartupExtensions.cs
  17. 16 4
      src/Hotline.Api/StartupHelper.cs
  18. 15 17
      src/Hotline.Api/config/appsettings.Development.json
  19. 15 17
      src/Hotline.Api/config/appsettings.json
  20. 4 3
      src/Hotline.Application/CallCenter/Calls/CurrentWaitNumService.cs
  21. 4 3
      src/Hotline.Application/CallCenter/Calls/TelsStatusRefreshService.cs
  22. 1 1
      src/Hotline.Application/CallCenter/Calls/TrApplication.cs
  23. 5 0
      src/Hotline.Application/FlowEngine/IWorkflowApplication.cs
  24. 62 26
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  25. 10 9
      src/Hotline.Application/Handlers/CallCenter/BaseHandler.cs
  26. 1 0
      src/Hotline.Application/Handlers/CallCenter/CallState/DtmfNotificationHandler.cs
  27. 10 2
      src/Hotline.Application/Handlers/CallCenter/ExtState/IdleNotificationHandler.cs
  28. 1 0
      src/Hotline.Application/Handlers/CallCenter/FlowControl/EndOfAnnOuterToMenuNotificationHandler.cs
  29. 1 0
      src/Hotline.Application/Handlers/CallCenter/FlowControl/EndOfAnnVisitorToMenuNotificationHandler.cs
  30. 3 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/IncomingNotificationHandler.cs
  31. 3 2
      src/Hotline.Application/Handlers/CallCenter/FlowControl/InviteNotificationHandler.cs
  32. 9 3
      src/Hotline.Application/Handlers/CallCenter/System/BootupNotificationHandler.cs
  33. 2 0
      src/Hotline.Application/Hotline.Application.csproj
  34. 112 0
      src/Hotline.Application/Jobs/GetCallsJob.cs
  35. 0 35
      src/Hotline.Application/Jobs/ReloadTotalsJob.cs
  36. 30 4
      src/Hotline.Application/Mappers/CallMapperConfigs.cs
  37. 39 9
      src/Hotline.Application/Mappers/OrderMapperConfigs.cs
  38. 8 15
      src/Hotline.Application/Orders/IOrderApplication.cs
  39. 82 160
      src/Hotline.Application/Orders/OrderApplication.cs
  40. 35 4
      src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs
  41. 709 13
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  42. 2 2
      src/Hotline.Application/Subscribers/DatasharingSubscriber.cs
  43. 139 130
      src/Hotline.NewRock/DeviceManager.cs
  44. 9 7
      src/Hotline.NewRock/Handlers/DeviceEventHandler.cs
  45. 13 0
      src/Hotline.NewRock/IDeviceEventHandler.cs
  46. 9 4
      src/Hotline.NewRock/NewRockStartupExtensions.cs
  47. 1 1
      src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs
  48. 2 2
      src/Hotline.Repository.SqlSugar/Extensions/SqlSugarStartupExtensions.cs
  49. 24 0
      src/Hotline.Repository.SqlSugar/Extensions/XingTangDbExtensions.cs
  50. 597 4
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  51. 11 2
      src/Hotline.Repository.SqlSugar/Ts/BaseRepositoryTextSearch.cs
  52. 8 0
      src/Hotline.Repository.SqlSugar/Ts/IRepositoryTextSearch.cs
  53. 8 0
      src/Hotline.Repository.SqlSugar/XingTangDbContext.cs
  54. 6 0
      src/Hotline.Share/Dtos/Ai/AiDto.cs
  55. 5 0
      src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs
  56. 5 0
      src/Hotline.Share/Dtos/FlowEngine/NextWorkflowDto.cs
  57. 101 160
      src/Hotline.Share/Dtos/Order/OrderBiDto.cs
  58. 49 3
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  59. 135 0
      src/Hotline.Share/Dtos/Order/OrderProvinceZmhdDto.cs
  60. 10 0
      src/Hotline.Share/Dtos/Users/UserDto.cs
  61. 14 0
      src/Hotline.Share/Enums/Order/EOrgVisitStatisticsType.cs
  62. 1 1
      src/Hotline.Share/Hotline.Share.csproj
  63. 7 2
      src/Hotline.Share/Mq/EventNames.Order.cs
  64. 5 0
      src/Hotline.Share/Requests/DepartmentalProcessingStatisticsDto.cs
  65. 254 131
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  66. 5 3
      src/Hotline.Wex/WexStartupExtensions.cs
  67. 1 1
      src/Hotline.Wex/WexTokenManager.cs
  68. 20 11
      src/Hotline/CallCenter/Calls/CallDomainService.cs
  69. 3 1
      src/Hotline/CallCenter/Calls/TrCallRecord.cs
  70. 14 0
      src/Hotline/CallCenter/Configs/CallCenterConfiguration.cs
  71. 2 2
      src/Hotline/CallCenter/Configs/NewRockConfiguration.cs
  72. 2 2
      src/Hotline/CallCenter/Configs/TianrunConfiguration.cs
  73. 1 1
      src/Hotline/CallCenter/Configs/WexConfiguration.cs
  74. 7 0
      src/Hotline/CallCenter/Configs/XingTangConfiguration.cs
  75. 0 10
      src/Hotline/CallCenter/Devices/CallCenterConfiguration.cs
  76. 41 40
      src/Hotline/CallCenter/Devices/IDeviceManager.cs
  77. 0 8
      src/Hotline/CallCenter/Devices/WexConfiguration.cs
  78. 0 12
      src/Hotline/CallCenter/IDeviceEventHandler.cs
  79. 7 2
      src/Hotline/CallCenter/Ivrs/IvrDomainService.cs
  80. 8 4
      src/Hotline/CallCenter/Manage/VoiceFileDomainService.cs
  81. 2 3
      src/Hotline/CallCenter/Tels/Tel.cs
  82. 9 8
      src/Hotline/CallCenter/Tels/TelDomainService.cs
  83. 7 1
      src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs
  84. 4 2
      src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs
  85. 6 5
      src/Hotline/FlowEngine/Workflows/Workflow.cs
  86. 25 10
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  87. 81 1
      src/Hotline/Orders/IOrderRepository.cs
  88. 26 0
      src/Hotline/Orders/Order.cs
  89. 5 4
      src/Hotline/Orders/OrderDomainService.cs
  90. 83 0
      src/Hotline/Orders/OrderProvinceZmhd.cs
  91. 39 0
      src/Hotline/Permissions/EPermission.cs
  92. 6 1
      src/Hotline/Settings/SettingConstants.cs
  93. 1 1
      src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs
  94. 9 6
      src/Hotline/Tools/ExcelHelper.cs
  95. 5 0
      src/Hotline/Users/User.cs
  96. 12 8
      src/Hotline/Users/UserDomainService.cs
  97. 189 0
      src/Hotline/dataview.md
  98. 1 1
      src/NewRock.Sdk/Security/AuthorizeGenerator.cs
  99. 1 0
      src/XF.Domain.Repository/Entity.cs
  100. 4 2
      src/XF.Domain/Dependency/DependencyInjectionExtensions.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

@@ -687,6 +687,7 @@ namespace Hotline.Api.Controllers
                                 //处理主表
                                 aiOrderVisitDetail.OrderVisit.AiVisitCount++;
                                 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;

+ 12 - 0
src/Hotline.Api/Controllers/Bi/BiKnowledgeController.cs

@@ -12,6 +12,7 @@ using Hotline.Share.Dtos.Order;
 using Hotline.Share.Requests;
 using Hotline.Tools;
 using MapsterMapper;
+using Org.BouncyCastle.Utilities;
 
 namespace Hotline.Api.Controllers.Bi
 {
@@ -93,6 +94,17 @@ namespace Hotline.Api.Controllers.Bi
 				var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
 				data = items;
 			}
+			data.Add(new KnowledgeBiDataListVo
+			{
+				OrgName = "合计",
+				OrgId = "0",
+				OrgType = null,
+				AddNum = data.Select(x => x.AddNum).Sum(),
+				DeleteNum = data.Select(x => x.DeleteNum).Sum(),
+				SendBackNum = data.Select(x => x.SendBackNum).Sum(),
+				PassNum = data.Select(x => x.PassNum).Sum(),
+				PublicNum = data.Select(x => x.PublicNum).Sum(),
+			});
 			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
 
 			var dtos = data

+ 461 - 87
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -2,20 +2,19 @@
 using Hotline.Application.StatisticalReport;
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
-using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
+using Hotline.Quality;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Schedulings;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Ai;
 using Hotline.Share.Dtos.Bi;
 using Hotline.Share.Dtos.Bigscreen;
 using Hotline.Share.Dtos.CallCenter;
-using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
-using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.FlowEngine;
@@ -23,18 +22,16 @@ using Hotline.Share.Enums.Order;
 using Hotline.Share.Requests;
 using Hotline.Tools;
 using MapsterMapper;
-using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Cors.Infrastructure;
 using Microsoft.AspNetCore.Mvc;
+using MiniExcelLibs;
 using NPOI.SS.Formula.Functions;
-using Org.BouncyCastle.Utilities;
 using SqlSugar;
-using System.Dynamic;
+using System.Data;
 using XF.Domain.Authentications;
-using XF.Domain.Constants;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
-using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
 
 namespace Hotline.Api.Controllers.Bi
 {
@@ -47,12 +44,11 @@ namespace Hotline.Api.Controllers.Bi
         private readonly IRepository<OrderDelay> _orderDelayRepository;
         private readonly IMapper _mapper;
         private readonly IRepository<WorkflowCountersign> _workflowCountersignRepository;
-        //private readonly IRepository<WorkflowStepHandler> _workflowStepHandleRepository;
         private readonly IRepository<OrderSpecial> _orderSpecialRepository;
         private readonly IRepository<OrderVisit> _orderVisitRepository;
         private readonly IRepository<TrCallRecord> _trCallRecordRepository;
         private readonly IRepository<OrderPublish> _orderPublishRepository;
-        private readonly IRepository<SystemOrganize> _systemOrganizeRepository;
+        private readonly ISystemOrganizeRepository _systemOrganizeRepository;
         private readonly IRepository<AiOrderVisitDetail> _aiOrderVisitDetailRepository;
         private readonly ISessionContext _sessionContext;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
@@ -63,6 +59,10 @@ namespace Hotline.Api.Controllers.Bi
         private readonly IOrderApplication _orderApplication;
         private readonly ITimeLimitDomainService _timeLimitDomainService;
         private readonly IOrderReportApplication _orderReportApplication;
+        private readonly IRepository<SystemArea> _systemAreaRepository;
+        private readonly IRepository<Hotspot> _hotspotRepository;
+        private readonly IRepository<SystemDicData> _systemDicDataRepository;
+        private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
 
         public BiOrderController(
             IOrderRepository orderRepository,
@@ -76,18 +76,21 @@ namespace Hotline.Api.Controllers.Bi
             IRepository<OrderVisit> orderVisitRepository,
             IRepository<TrCallRecord> trCallRecordRepository,
             IRepository<OrderPublish> orderPublishRepository,
-            IRepository<SystemOrganize> systemOrganizeRepository,
+            ISystemOrganizeRepository systemOrganizeRepository,
             IRepository<AiOrderVisitDetail> aiOrderVisitDetailRepository,
             ISessionContext sessionContext,
             ISystemSettingCacheManager systemSettingCacheManager,
             IRepository<OrderSpecialDetail> orderSpecialDetailRepository,
             IRepository<WorkflowTrace> workflowTraceRepository,
             IRepository<OrderScreen> orderScreenRepository,
-            //IRepository<WorkflowStepHandler> workflowStepHandleRepository,
             IOrderSecondaryHandlingApplication orderSecondaryHandlingApplication,
             IOrderApplication orderApplication,
             ITimeLimitDomainService timeLimitDomainService,
-            IOrderReportApplication orderReportApplication
+            IOrderReportApplication orderReportApplication,
+            IRepository<SystemArea> systemAreaRepository,
+            IRepository<Hotspot> hotspotRepository,
+             IRepository<SystemDicData> systemDicDataRepository,
+            ISystemDicDataCacheManager systemDicDataCacheManager
             )
         {
             _orderRepository = orderRepository;
@@ -108,11 +111,14 @@ namespace Hotline.Api.Controllers.Bi
             _orderSpecialDetailRepository = orderSpecialDetailRepository;
             _workflowTraceRepository = workflowTraceRepository;
             _orderScreenRepository = orderScreenRepository;
-            //_workflowStepHandleRepository = workflowStepHandleRepository;
             _orderSecondaryHandlingApplication = orderSecondaryHandlingApplication;
             _orderApplication = orderApplication;
             _timeLimitDomainService = timeLimitDomainService;
             _orderReportApplication = orderReportApplication;
+            _systemAreaRepository = systemAreaRepository;
+            _hotspotRepository = hotspotRepository;
+            _systemDicDataRepository = systemDicDataRepository;
+            _systemDicDataCacheManager = systemDicDataCacheManager;
         }
 
         /// <summary>
@@ -162,6 +168,67 @@ namespace Hotline.Api.Controllers.Bi
             return ExcelStreamResult(stream, "部门超期统计明细数据");
         }
 
+        /// <summary>
+        /// 全量部门超期统计明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("org_data_list_detail_all")]
+        public async Task<PagedDto<OrderDto>> OrgDataListDetail([FromQuery] OrgDataListAllDetailRequest dto)
+        {
+            var quer = _orderApplication.QueryOrgDataListDetail(dto);
+            var (total, items) = await quer.ToPagedListAsync(dto.PageIndex, dto.PageSize);
+
+            return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        }
+
+        /// <summary>
+        /// 部门超期统计明细导出
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("org_data_list_detail_all/_export")]
+        public async Task<FileStreamResult> OrgDataListDetailExport([FromBody] ExportExcelDto<OrgDataListAllDetailRequest> dto)
+        {
+            var query = _orderApplication.QueryOrgDataListDetail(dto.QueryDto);
+            List<Order> data;
+            if (dto.IsExportAll)
+            {
+                data = await query.ToListAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                data = items;
+            }
+
+            var dataDtos = _mapper.Map<ICollection<OrderDto>>(data);
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+            var dtos = dataDtos
+                .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "部门超期统计明细数据");
+        }
+
+
+        /// <summary>
+        /// 列表页面基础数据
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("org_data_list_detail_all/base-data")]
+        public async Task<object> BaseData()
+        {
+            var rsp = new
+            {
+                OrderStatusOptions = EnumExts.GetDescriptions<EOrderStatus>()
+            };
+            return rsp;
+        }
 
         /// <summary>
         /// 部门超期统计
@@ -194,6 +261,14 @@ namespace Hotline.Api.Controllers.Bi
             var query = _orderApplication.QueryOrgDataList(dto.QueryDto);
             List<OrderBiOrgDataListVo> data;
             data = await query.ToListAsync(HttpContext.RequestAborted);
+            data.Add(new OrderBiOrgDataListVo
+            {
+                OrgName = "合计",
+                HandlerExtendedNum = data.Select(s => s.HandlerExtendedNum).Sum(),
+                CounterHandlerExtendedNum = data.Select(s => s.CounterHandlerExtendedNum).Sum(),
+                NoHandlerExtendedNum = data.Select(s => s.NoHandlerExtendedNum).Sum(),
+                CounterNoHandlerExtendedNum = data.Select(s => s.CounterNoHandlerExtendedNum).Sum(),
+            });
             dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
             var dtos = data
              .Select(stu => _mapper.Map(stu, typeof(OrderBiOrgDataListVo), dynamicClass))
@@ -1315,7 +1390,7 @@ namespace Hotline.Api.Controllers.Bi
               {
                   CountNum = SqlFunc.AggregateCount(it.OrgLevelOneCode),
 
-                  OrgName = it.OrgLevelOneCode == "001" ? "热线中心" : o.Name
+                  OrgName = it.OrgLevelOneCode == "001" ? "市民热线服务中心" : o.Name
               }).ToListAsync();
 
             centerReportStatisticsDto.OrgStatisticsCityAll = new OrgStatisticsAll
@@ -1335,7 +1410,7 @@ namespace Hotline.Api.Controllers.Bi
              .Select((it, o) => new OrgStatistics
              {
                  CountNum = SqlFunc.AggregateCount(it.OrgLevelOneCode),
-                 OrgName = it.OrgLevelOneCode == "001" ? "热线中心" : o.Name
+                 OrgName = it.OrgLevelOneCode == "001" ? "市民热线服务中心" : o.Name
              }).ToListAsync();
 
             centerReportStatisticsDto.OrgStatisticsAreaAll = new OrgStatisticsAll
@@ -1357,6 +1432,19 @@ namespace Hotline.Api.Controllers.Bi
         {
             var items = await _orderReportApplication.DepartmentAcceptanceTypeStatistics(dto).ToListAsync();
 
+            foreach (var item in items)
+            {
+                item.ZxAllTimes = Math.Round(((double)item.ZxAllTimes / 3600), 2);
+                item.JyAllTimes = Math.Round(((double)item.JyAllTimes / 3600), 2);
+                item.QzAllTimes = Math.Round(((double)item.QzAllTimes / 3600), 2);
+                item.ByAllTimes = Math.Round(((double)item.ByAllTimes / 3600), 2);
+                item.JbAllTimes = Math.Round(((double)item.JbAllTimes / 3600), 2);
+                item.TsAllTimes = Math.Round(((double)item.TsAllTimes / 3600), 2);
+                item.QtAllTimes = Math.Round(((double)item.QtAllTimes / 3600), 2);
+                item.YjAllTimes = Math.Round(((double)item.YjAllTimes / 3600), 2);
+            }
+
+
             var total = new DepartmentAcceptanceTypeStatisticsDto
             {
                 OrgName = "合计",
@@ -1417,7 +1505,17 @@ namespace Hotline.Api.Controllers.Bi
                 var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
                 list = items;
             }
-
+            foreach (var item in list)
+            {
+                item.ZxAllTimes = Math.Round(((double)item.ZxAllTimes / 3600), 2);
+                item.JyAllTimes = Math.Round(((double)item.JyAllTimes / 3600), 2);
+                item.QzAllTimes = Math.Round(((double)item.QzAllTimes / 3600), 2);
+                item.ByAllTimes = Math.Round(((double)item.ByAllTimes / 3600), 2);
+                item.JbAllTimes = Math.Round(((double)item.JbAllTimes / 3600), 2);
+                item.TsAllTimes = Math.Round(((double)item.TsAllTimes / 3600), 2);
+                item.QtAllTimes = Math.Round(((double)item.QtAllTimes / 3600), 2);
+                item.YjAllTimes = Math.Round(((double)item.YjAllTimes / 3600), 2);
+            }
             //增加合计
             list.Add(new DepartmentAcceptanceTypeStatisticsDto
             {
@@ -1528,8 +1626,10 @@ namespace Hotline.Api.Controllers.Bi
         public async Task<object> DepartmentalProcessingStatistics([FromQuery] DepartmentalProcessingStatisticsRequest dto)
         {
             //联合查询
-            var items = await _orderReportApplication.DepartmentalProcessingStatistics(dto)
-                .ToListAsync();
+            //var items = await _orderReportApplication.DepartmentalProcessingStatistics(dto)
+            //    .ToListAsync();
+
+            var items = await _orderReportApplication.DepartmentalProcessingStatisticsNew(dto);
 
             var total = new DepartmentalProcessingStatisticsDataDto
             {
@@ -1570,17 +1670,8 @@ namespace Hotline.Api.Controllers.Bi
         [HttpPost("departmental_processing_statistics_export")]
         public async Task<FileStreamResult> ExportDepartmentalProcessingStatistics([FromBody] ExportExcelDto<DepartmentalProcessingStatisticsRequest> dto)
         {
-            var query = _orderReportApplication.DepartmentalProcessingStatistics(dto.QueryDto);
-            List<DepartmentalProcessingStatisticsDataDto> list;
-            if (dto.IsExportAll)
-            {
-                list = await query.ToListAsync(HttpContext.RequestAborted);
-            }
-            else
-            {
-                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
-                list = items;
-            }
+            var list = await _orderReportApplication.DepartmentalProcessingStatisticsNew(dto.QueryDto);
+
 
             //增加合计
             list.Add(new DepartmentalProcessingStatisticsDataDto
@@ -1634,8 +1725,7 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("departmental_processing_child_statistics")]
         public async Task<object> DepartmentalProcessingChildStatistics([FromQuery] DepartmentalProcessingStatisticsRequest dto)
         {
-            var items = await _orderReportApplication.DepartmentalProcessingChildStatistics(dto)
-               .ToListAsync();
+            var items = await _orderReportApplication.DepartmentalProcessingChildStatisticsNew(dto);
 
             //计算合计
             var total = new DepartmentalProcessingStatisticsDataDto
@@ -1677,18 +1767,7 @@ namespace Hotline.Api.Controllers.Bi
         [HttpPost("departmental_processing_child_statistics_export")]
         public async Task<FileStreamResult> ExportDepartmentalProcessingChildStatistics([FromBody] ExportExcelDto<DepartmentalProcessingStatisticsRequest> dto)
         {
-            var query = _orderReportApplication.DepartmentalProcessingChildStatistics(dto.QueryDto);
-            List<DepartmentalProcessingStatisticsDataDto> list;
-            if (dto.IsExportAll)
-            {
-                list = await query.ToListAsync(HttpContext.RequestAborted);
-            }
-            else
-            {
-                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
-                list = items;
-            }
-
+            var list = await _orderReportApplication.DepartmentalProcessingChildStatisticsNew(dto.QueryDto);
             //增加合计
             list.Add(new DepartmentalProcessingStatisticsDataDto
             {
@@ -1744,8 +1823,9 @@ namespace Hotline.Api.Controllers.Bi
         {
             RefAsync<int> total = 0;
 
-            var queryData = await _orderReportApplication.GetDepartmentalProcessingStatisticsList(dto, HttpContext.RequestAborted)
+            var queryData = await _orderReportApplication.GetDepartmentalProcessingStatisticsListNew(dto, HttpContext.RequestAborted)
                         .LeftJoin<Order>((x, o) => x.Id == o.Id)
+                        .OrderByDescending((x, o) => o.CreationTime)
                          .Select((x, o) => new { o })
                         .ToPageListAsync(dto.PageIndex, dto.PageSize, total, HttpContext.RequestAborted);
 
@@ -1758,7 +1838,7 @@ namespace Hotline.Api.Controllers.Bi
         }
 
         /// <summary>
-        /// 部门办件统计表--明细
+        /// 部门办件统计表--明细--导出
         /// </summary>
         /// <param name="dto"></param>
         /// <returns></returns>
@@ -1766,8 +1846,9 @@ namespace Hotline.Api.Controllers.Bi
         [HttpPost("departmental_processing_statistics_list_export")]
         public async Task<FileStreamResult> ExportGetDepartmentalProcessingStatisticsList([FromBody] ExportExcelDto<DepartmentalProcessingStatisticsRequest> dto)
         {
-            var query = _orderReportApplication.GetDepartmentalProcessingStatisticsList(dto.QueryDto, HttpContext.RequestAborted)
+            var query = _orderReportApplication.GetDepartmentalProcessingStatisticsListNew(dto.QueryDto, HttpContext.RequestAborted)
                  .LeftJoin<Order>((x, o) => x.Id == o.Id)
+                 .OrderByDescending((x, o) => o.CreationTime)
                  .Select((x, o) => new { o });
             List<OrderDto> list = new List<OrderDto>();
             if (dto.IsExportAll)
@@ -1790,8 +1871,6 @@ namespace Hotline.Api.Controllers.Bi
                 }).ToList();
             }
 
-            //   var orderDtos = _mapper.Map<ICollection<OrderDto>>(list);
-
             dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
 
             var dtos = list
@@ -1804,6 +1883,74 @@ namespace Hotline.Api.Controllers.Bi
             return ExcelStreamResult(stream, "部门办件统计明细数据");
         }
 
+        /// <summary>
+        /// 部门办件统计明细表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("departmental_processing_statistics_details_list")]
+        public async Task<PagedDto<OrderDto>> DepartmentalProcessingStatisticsDetailsList([FromQuery] DepartmentalProcessingStatisticsRequest dto)
+        {
+            RefAsync<int> total = 0;
+
+            var queryData = await _orderReportApplication.DepartmentalProcessingStatisticsDetailsList(dto)
+                        .LeftJoin<Order>((x, o) => x.Id == o.Id)
+                        .OrderByDescending((x, o) => o.CreationTime)
+                         .Select((x, o) => new { o })
+                        .ToPageListAsync(dto.PageIndex, dto.PageSize, total, HttpContext.RequestAborted);
+
+            var dtos = queryData.Select(d =>
+            {
+                var dto = _mapper.Map<OrderDto>(d.o);
+                return dto;
+            }).ToList();
+            return new PagedDto<OrderDto>(total, dtos);
+        }
+
+        /// <summary>
+        /// 部门办件统计明细表--导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("departmental_processing_statistics_details_list_export")]
+        public async Task<FileStreamResult> ExportDepartmentalProcessingStatisticsDetailsList([FromBody] ExportExcelDto<DepartmentalProcessingStatisticsRequest> dto)
+        {
+            var query = _orderReportApplication.DepartmentalProcessingStatisticsDetailsList(dto.QueryDto)
+                  .LeftJoin<Order>((x, o) => x.Id == o.Id)
+                  .OrderByDescending((x, o) => o.CreationTime)
+                  .Select((x, o) => new { o });
+            var list = new List<OrderDto>();
+            if (dto.IsExportAll)
+            {
+                var listData = await query.ToListAsync(HttpContext.RequestAborted);
+                list = listData.Select(d =>
+                {
+                    var dto = _mapper.Map<OrderDto>(d.o);
+                    return dto;
+                }).ToList();
+            }
+            else
+            {
+                RefAsync<int> total = 0;
+                var listData = await query.ToPageListAsync(dto.QueryDto.PageIndex, dto.QueryDto.PageSize, total, HttpContext.RequestAborted);
+                list = listData.Select(d =>
+                {
+                    var dto = _mapper.Map<OrderDto>(d.o);
+                    return dto;
+                }).ToList();
+            }
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+            var dtos = list
+                .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "部门办件统计明细表数据");
+        }
 
         /// <summary>
         /// 高频来电统计
@@ -2043,6 +2190,11 @@ namespace Hotline.Api.Controllers.Bi
             var query = _orderApplication.OrderReTransact(dto.QueryDto);
             List<OrderReTransactVo> data;
             data = await query.ToListAsync(HttpContext.RequestAborted);
+            data.Add(new OrderReTransactVo
+            {
+                OrgName = "合计",
+                Num = data.Select(s => s.Num).Sum(),
+            });
             dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
             var dtos = data
              .Select(stu => _mapper.Map(stu, typeof(OrderReTransactVo), dynamicClass))
@@ -2611,27 +2763,30 @@ namespace Hotline.Api.Controllers.Bi
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpGet("order_source_report_list")]
-        public async Task<List<OrderSourceHeaderVo>> QueryOrderSourceReportList([FromQuery] QueryOrderSourceRequest dto)
+        public async Task<Object> QueryOrderSourceReportList([FromQuery] QueryOrderSourceRequest dto)
         {
-            var data = await _orderApplication.QueryOrderSourceList(dto);
-            return data;
-            ;
+            var item = await _orderRepository.OrderSource(dto);
+
+            var titleData = await _systemDicDataRepository.Queryable()
+                .Where(p => p.DicTypeCode == "SourceChannel")
+                .Select(p => new
+                {
+                    Key = p.DicDataValue,
+                    Value = p.DicDataName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
         }
         /// <summary>
         /// 信件来源统计导出
         /// </summary>
         /// <returns></returns>
         [HttpPost("order_source_list/_export")]
-        public async Task<FileStreamResult> QueryOrderSourceReportList([FromBody] ExportExcelDto<QueryOrderSourceRequest> dto)
+        public async Task<FileStreamResult> QueryOrderSourceListExport([FromBody] QueryOrderSourceRequest dto)
         {
-            var data = await _orderApplication.QueryOrderSourceList(dto.QueryDto);
-            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-            var dtos = data
-                .Select(stu => _mapper.Map(stu, typeof(OrderSourceHeaderVo), dynamicClass))
-                .Cast<object>()
-                .ToList();
-            var stream = ExcelHelper.CreateStream(dtos);
-            return ExcelStreamResult(stream, "信件来源统计列表数据");
+            var dataTable = await _orderRepository.OrderSourceExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "信件来源统计数据");
         }
 
         /// <summary>
@@ -2674,32 +2829,251 @@ namespace Hotline.Api.Controllers.Bi
         }
 
         /// <summary>
-        /// 信件来源时分统计列表
+        /// 区域分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("order_area_time")]
+        public async Task<object> OrderAreaTime([FromQuery] TimeSharingPagedKeywordRequest dto)
+        {
+            var item = await _orderRepository.OrderAreaTime(dto);
+
+            var titleData = await _systemAreaRepository.Queryable()
+                .Where(p => p.Id.Length == 6 && p.Id != "510000")
+                .Select(p => new
+                {
+                    Key = p.Id,
+                    Value = p.AreaName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
+        }
+
+        /// <summary>
+        /// 区域分时统计-导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("order_area_time_export")]
+        public async Task<FileStreamResult> OrderAreaTimeExport([FromBody] TimeSharingPagedKeywordRequest dto)
+        {
+            var dataTable = await _orderRepository.OrderAreaTimeExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "区域分时统计数据");
+        }
+
+        /// <summary>
+        /// 热点类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("order_hotspot_time")]
+        public async Task<object> OrderHotspotTime([FromQuery] TimeSharingPagedKeywordRequest dto)
+        {
+            var item = await _orderRepository.OrderHotspotTime(dto);
+
+            var titleData = await _hotspotRepository.Queryable()
+                .Where(p => p.Id.Length == 2 && (p.ParentId == null || p.ParentId == ""))
+                .Select(p => new
+                {
+                    Key = p.Id,
+                    Value = p.HotSpotName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
+        }
+
+        /// <summary>
+        /// 热点类型分时统计-导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("order_hotspot_time_export")]
+        public async Task<FileStreamResult> OrderHotspotTimeExport([FromBody] TimeSharingPagedKeywordRequest dto)
+        {
+            var dataTable = await _orderRepository.OrderHotspotTimeExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "热点类型分时统计数据");
+        }
+
+        /// <summary>
+        /// 受理类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("order_acceptance_time")]
+        public async Task<object> OrderAcceptanceTime([FromQuery] TimeSharingPagedKeywordRequest dto)
+        {
+            var item = await _orderRepository.OrderAcceptanceTime(dto);
+
+            var titleData = await _systemDicDataRepository.Queryable()
+                .Where(p => p.DicTypeCode == "AcceptType")
+                .Select(p => new
+                {
+                    Key = p.DicDataValue,
+                    Value = p.DicDataName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
+        }
+
+        /// <summary>
+        /// 受理类型分时统计-导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("order_acceptance_time_export")]
+        public async Task<FileStreamResult> OrderAcceptanceTimeExport([FromBody] TimeSharingPagedKeywordRequest dto)
+        {
+            var dataTable = await _orderRepository.OrderAcceptanceTimeExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "受理类型分时统计数据");
+        }
+
+        /// <summary>
+        /// 信件来源分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("order_source_time")]
+        public async Task<object> OrderSourceTime([FromQuery] TimeSharingPagedKeywordRequest dto)
+        {
+            var item = await _orderRepository.OrderSourceTime(dto);
+
+            var titleData = await _systemDicDataRepository.Queryable()
+                .Where(p => p.DicTypeCode == "SourceChannel")
+                .Select(p => new
+                {
+                    Key = p.DicDataValue,
+                    Value = p.DicDataName
+                }).ToListAsync();
+
+            return new { Item = item, TitleData = titleData };
+        }
+
+        /// <summary>
+        /// 信件来源分时统计-导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("order_source_time_export")]
+        public async Task<FileStreamResult> OrderSourceTimeExport([FromBody] TimeSharingPagedKeywordRequest dto)
+        {
+            var dataTable = await _orderRepository.OrderSourceTimeExport(dto);
+            var stream = ExcelHelper.CreateStream(dataTable);
+            return ExcelStreamResult(stream, "信件来源分时统计数据");
+        }
+
+        /// <summary>
+        /// 部门满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("org-visitdetail-list")]
+        public async Task<PagedDto<OrgVisitDetailListResp>> OrgVisitDetailList([FromQuery] OrgVisitDetailListReq dto)
+        {
+            var query = _orderReportApplication.OrgVisitDetailList(dto);
+            var (total, items) = await query.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+
+            return new PagedDto<OrgVisitDetailListResp>(total, _mapper.Map<IReadOnlyList<OrgVisitDetailListResp>>(items));
+        }
+
+        /// <summary>
+        /// 部门满意度明细页面基础数据
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("org-visitdetail-list-basedata")]
+        public async Task<object> OrgVisitDetailListBaseData()
+        {
+            var VisitSatisfaction =  _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction);
+            
+            if (_sessionContext.OrgIsCenter)
+            {
+                return new { OrgsOptions = await _systemOrganizeRepository.GetOrgJson() , VisitSatisfaction= VisitSatisfaction };
+            }
+            else
+            {
+                return new { OrgsOptions = await _systemOrganizeRepository.GetOrgJsonForUser(_sessionContext.RequiredOrgId), VisitSatisfaction = VisitSatisfaction };
+            }
+        }
+
+        /// <summary>
+        /// 部门满意度明细导出
         /// </summary>
         /// <param name="dto"></param>
         /// <returns></returns>
-        [HttpGet("order_source_hours_report_list")]
-        public async Task<List<OrderSourceHeaderVo>> QueryOrderSourceHoursReportList([FromQuery] QueryOrderSourceRequest dto)
-        {
-	        var data = await _orderApplication.QueryOrderSourceHoursList(dto);
-	        return data;
-	        ;
-        }
-		/// <summary>
-		/// 信件来源时分统计导出
-		/// </summary>
-		/// <returns></returns>
-		[HttpPost("order_source_hours_list/_export")]
-        public async Task<FileStreamResult> QueryOrderSourceHoursReportList([FromBody] ExportExcelDto<QueryOrderSourceRequest> dto)
-        {
-	        var data = await _orderApplication.QueryOrderSourceHoursList(dto.QueryDto);
-	        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-	        var dtos = data
-		        .Select(stu => _mapper.Map(stu, typeof(OrderSourceHeaderVo), dynamicClass))
-		        .Cast<object>()
-		        .ToList();
-	        var stream = ExcelHelper.CreateStream(dtos);
-	        return ExcelStreamResult(stream, "信件来源统计列表数据");
-        }
-	}
+        [HttpPost("org-visitdetail-list-export")]
+        public async Task<FileStreamResult> OrgVisitDetailListExport([FromBody] ExportExcelDto<OrgVisitDetailListReq> dto)
+        {
+            var query = _orderReportApplication.OrgVisitDetailList(dto.QueryDto);
+
+            List<OrderVisitDetail> orders;
+            if (dto.IsExportAll)
+            {
+                orders = await query.ToListAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                orders = items;
+            }
+            var ordersDtos = _mapper.Map<ICollection<OrgVisitDetailListResp>>(orders);
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+            var dtos = ordersDtos
+                .Select(stu => _mapper.Map(stu, typeof(OrgVisitDetailListResp), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+            return ExcelStreamResult(stream, "部门满意度明细");
+        }
+
+        /// <summary>
+        /// 热点区域统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("hotspot-area-statistics")]
+        public async Task<object> HotspotAndAreaStatistics([FromQuery] HotspotAndAreaStatisticsReq dto)
+        {
+            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
+            var areaList = await _systemOrganizeRepository.Queryable().Where(x => SqlFunc.Length(x.Id) == 6).ToListAsync();
+            List<dynamic> list = new List<dynamic>();
+            foreach (var item in areaList)
+            {
+                var table = await _orderRepository.Queryable()
+                   .Where(x => x.CreationTime >= dto.StartTime && x.CreationTime < dto.EndTime && x.AreaCode.StartsWith(item.Id))
+                   .GroupByIF(dto.HotspotLevel == 1, x => new
+                   {
+                       HotspotId = x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2"))
+                   })
+                   .GroupByIF(dto.HotspotLevel == 2, x => new
+                   {
+                       HotspotId = x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("4"))
+                   })
+                   .GroupByIF(dto.HotspotLevel == 3, x => new
+                   {
+                       HotspotId = x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))
+                   })
+                   .GroupByIF(dto.HotspotLevel == 4, x => new
+                   {
+                       HotspotId = x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("8"))
+                   })
+                   .Select(x => new
+                   {
+                       HotspotId = SqlFunc.IIF(dto.HotspotLevel == 1, x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
+                                   SqlFunc.IIF(dto.HotspotLevel == 2, x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("4")),
+                                   SqlFunc.IIF(dto.HotspotLevel == 3, x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                                   SqlFunc.IIF(dto.HotspotLevel == 4, x.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("8")), "")))),
+                       Key = item.Id,
+                       AreaName = item.AreaName,
+                       Count = 1//SqlFunc.AggregateSum(SqlFunc.IIF(x.Hotspot.))
+                   }).ToPivotListAsync(x => x.Key, x => new { x.HotspotId, x.AreaName }, x => x.Sum(x => x.Count));
+                list.AddRange(table);
+            }
+
+            return new { AreaList = areaList, Data = list };
+        }
+    }
+
 }

+ 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>
     /// 获取可选快捷入口

+ 4 - 5
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -1,18 +1,20 @@
 using DotNetCore.CAP;
+using ExtendedNumerics.Exceptions;
 using Hotline.Ai.Quality;
 using Hotline.Application.CallCenter.Calls;
 using Hotline.Application.Systems;
 using Hotline.Application.Tels;
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Tels;
 using Hotline.Orders;
 using Hotline.Permissions;
 using Hotline.Quality;
-using Hotline.Repository.SqlSugar.CallCenter;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
@@ -21,19 +23,16 @@ using Hotline.Users;
 using MapsterMapper;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.IdentityModel.Tokens;
+using Microsoft.Extensions.Options;
 using Newtonsoft.Json;
-using SqlSugar;
 using Tr.Sdk;
 using Tr.Sdk.Blacklist;
 using Tr.Sdk.Tels;
 using XF.Domain.Authentications;
-using XF.Domain.Constants;
 using XF.Domain.Exceptions;
 using XF.Domain.Filters;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
-using static Grpc.Core.ChannelOption;
 
 namespace Hotline.Api.Controllers
 {

+ 90 - 15
src/Hotline.Api/Controllers/OrderController.cs

@@ -2419,6 +2419,41 @@ public class OrderController : BaseController
         //}
         if (!string.IsNullOrEmpty(order.WorkflowId))
         {
+            bool canInsteadHandle = false;
+			//班长代办
+			var settingEnable = _systemSettingCacheManager.GetSetting(SettingConstants.ChargeDAffaires);
+            var isEnable = settingEnable != null && settingEnable.SettingValue.Any() ? int.Parse(settingEnable?.SettingValue[0]) : 0;
+			if (isEnable > 0)
+			{
+				var setting = _systemSettingCacheManager.GetSetting(SettingConstants.SeatsMonitor);
+				var settingStr = setting?.SettingValue;
+				var roles = _sessionContext.Roles;
+				foreach (var item in settingStr)
+				{
+                    if (roles != null && roles.Contains(item))
+                    { 
+                        canInsteadHandle = true; 
+                    }else {
+                        canInsteadHandle = false;
+                    };
+				}
+				if (canInsteadHandle)
+				{
+					var unhandleSteps =
+						await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+					// 会签多节点 不允许班长代办
+					if (unhandleSteps.Count > 1)
+						canInsteadHandle = false;
+					if (isEnable < 3 && unhandleSteps.Count == 1)
+                    {
+                        var type = isEnable - 1;
+						var step = unhandleSteps.FirstOrDefault(d => d.BusinessType == (EBusinessType)type);
+						canInsteadHandle = step != null && !string.IsNullOrEmpty(step.Id);
+						if (canInsteadHandle && step.IsInCountersign())
+							canInsteadHandle = false;
+					}
+				}
+			}
             var result = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
                 order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles,
                 cancellationToken: HttpContext.RequestAborted);
@@ -2426,13 +2461,15 @@ public class OrderController : BaseController
             dto.CountersignId = result.CountersignId;
             dto.CanHandle = result.CanHandle;
             dto.CanPrevious = result.CanPrevious;
+            dto.CanInsteadHandle = !dto.CanHandle && canInsteadHandle;
             dto.PreviousOpinion = result.previousOpinion;
 
-            await _mediator.Publish(new GetOrderDetailNotify(result.Workflow,
+			await _mediator.Publish(new GetOrderDetailNotify(result.Workflow,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
                 _sessionContext.RequiredOrgId, _sessionContext.OrgName,
                 _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName));
         }
+       
 
         //var dto = _mapper.Map<OrderDto>(order!);
         //dto.CountersignId = countersignId;
@@ -2565,7 +2602,7 @@ public class OrderController : BaseController
         }
 
         //内容分词
-        await _orderApplication.OrderParticiple(dto.Content, order.Id, HttpContext.RequestAborted);
+        await _orderApplication.OrderParticiple(dto.Content, order.Id,order.CreationTime, HttpContext.RequestAborted);
         //敏感分词
         await _orderApplication.OrderSensitiveParticiple(dto.Content, order.Id, HttpContext.RequestAborted);
         //sms
@@ -2671,7 +2708,6 @@ public class OrderController : BaseController
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    [Permission(EPermission.OrderUpdate)]
     [HttpPut]
     [LogFilter("更新工单")]
     public async Task Update([FromBody] UpdateOrderDto dto)
@@ -2690,7 +2726,7 @@ public class OrderController : BaseController
             throw UserFriendlyException.SameMessage("工单已发起流程,不可编辑");
 
         if (order.Content != dto.Content)
-            await _orderApplication.OrderParticiple(dto.Content, dto.Id, HttpContext.RequestAborted);
+            await _orderApplication.OrderParticiple(dto.Content, dto.Id, order.CreationTime, HttpContext.RequestAborted);
         if (dto.RepeatableEventDetails?.Any() ?? false)
         {
             var reAdds = dto.RepeatableEventDetails.Where(x => string.IsNullOrEmpty(x.OrderId) && !x.IsDeleted)
@@ -2832,7 +2868,7 @@ public class OrderController : BaseController
         var order = await _orderRepository.Queryable()
             .FirstAsync(d => d.WorkflowId == dto.WorkflowId, HttpContext.RequestAborted);
         if (order is null)
-            throw new UserFriendlyException("无效工单编号");
+            throw UserFriendlyException.SameMessage("无效工单编号");
         //if (await _orderDelayRepository.AnyAsync(x => x.OrderId == order.Id && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted))
         //{
         //    throw UserFriendlyException.SameMessage("该工单存在正在审核中的延期,不能办理");
@@ -2921,9 +2957,43 @@ public class OrderController : BaseController
     }
 
     /// <summary>
-    /// 结束会签
+    /// 查询工单办理下一步可选节点(带推荐部门)
     /// </summary>
-    [HttpPost("endcs")]
+    [HttpGet("nextsteps_commission/{orderId}")]
+    public async Task<NextStepsWithOpinionDto<RecommendStepOption>> GetNextStepsWithRecommendCommission(string orderId)
+    {
+	    var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: HttpContext.RequestAborted);
+	    if (string.IsNullOrEmpty(order.WorkflowId))
+		    throw UserFriendlyException.SameMessage("该工单未开启流程");
+	    var unhandleSteps =
+		    await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+	    if (unhandleSteps.Count > 1)
+		    throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
+	    if (unhandleSteps.Count < 1)
+		    throw UserFriendlyException.SameMessage("未查询到流程信息");
+        var stepOne = unhandleSteps.First();
+        if (stepOne.IsInCountersign())
+	        throw UserFriendlyException.SameMessage("会签工单不允许班长代办");
+		var dto = await _workflowApplication.GetNextStepsAsync(order.WorkflowId, stepOne.Id, HttpContext.RequestAborted);
+	    dto.ExpiredTime = order.ExpiredTime;
+	    var rsp = _mapper.Map<NextStepsWithOpinionDto<RecommendStepOption>>(dto);
+	    foreach (var step in rsp.Steps)
+	    {
+		    if (dto.CurrentStepBusinessType is not EBusinessType.Send ||
+		        step.BusinessType is not EBusinessType.Department) continue;
+		    var org = await _organizeRepository.GetAsync(d => d.AreaCode == order.AreaCode, HttpContext.RequestAborted);
+		    if (org is null) continue;
+		    step.RecommendOrgId = org.Id;
+		    step.RecommendOrgName = org.Name;
+	    }
+
+	    return rsp;
+    }
+
+	/// <summary>
+	/// 结束会签
+	/// </summary>
+	[HttpPost("endcs")]
     public async Task EndCountersign([FromBody] EndCountersignDto dto)
     {
         var workflow = await _workflowDomainService.TerminalCountersignAsync(dto.CountersignId, HttpContext.RequestAborted);
@@ -3954,7 +4024,7 @@ public class OrderController : BaseController
                 NextStepCode = dto.NextStepCode,
                 NextStepName = dto.NextStepName,
                 NextHandlers = dto.NextHandlers,
-                Opinion = dto.Cause,
+                Opinion = dto.Reason,
                 FlowDirection = dto.FlowDirection,
                 HandlerType = dto.HandlerType,
                 BusinessType = dto.BusinessType
@@ -5089,7 +5159,7 @@ public class OrderController : BaseController
         if (order == null)
             throw new UserFriendlyException($"无效工单编号, orderId: {orderId}", "无效工单编号");
         if (order.IsSigned())
-            throw new UserFriendlyException("该工单已被签收");
+            throw UserFriendlyException.SameMessage("该工单已被签收");
         order.Sign(_sessionContext.RequiredUserId, _sessionContext.UserName);
         order.AutoAccept(_sessionContext.RequiredUserId, _sessionContext.UserName, _sessionContext.StaffNo);
 
@@ -5725,13 +5795,15 @@ public class OrderController : BaseController
         var order = await _orderRepository.GetAsync(orderId, HttpContext.RequestAborted);
         var step = new WorkflowStep();
         var setting = _systemSettingCacheManager.GetSetting(SettingConstants.RoleZuoXi);
-        if (!string.IsNullOrEmpty(order.WorkflowId))
+        if (string.IsNullOrEmpty(order.SignerId))
+	        throw UserFriendlyException.SameMessage("工单尚未签收,暂不支持平移");
+		if (!string.IsNullOrEmpty(order.WorkflowId))
         {
             var steps = await _workflowStepRepository.Queryable()
                 .Where(d => d.ExternalId == orderId && d.Status != EWorkflowStepStatus.Handled)
                 .ToListAsync(HttpContext.RequestAborted);
             if (steps.Count > 1)
-                throw new UserFriendlyException("多个待办理节点暂不支持平移");
+                throw UserFriendlyException.SameMessage("多个待办理节点暂不支持平移");
             step = steps.First();
             if (step.BusinessType is not EBusinessType.Center and not EBusinessType.Send)
                 throw UserFriendlyException.SameMessage("当前办理节点非中心暂不支持平移");
@@ -5767,7 +5839,10 @@ public class OrderController : BaseController
     [HttpPost("change-handler")]
     public async Task ChangeHandler([FromBody] ChangeHandlerDto dto)
     {
-        if (string.IsNullOrEmpty(dto.StepId))
+        var special = await _orderSpecialRepository.Queryable().Where(x => x.OrderId == dto.OrderId && x.State == 0).AnyAsync();
+        if (special)
+	        throw  UserFriendlyException.SameMessage("当前工单特提审批中,请审批后再操作!");
+		if (string.IsNullOrEmpty(dto.StepId))
         {
             await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { SignerId = dto.Handler.UserId, SignerName = dto.Handler.Username })
                 .Where(o => o.Id == dto.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted);
@@ -5778,10 +5853,10 @@ public class OrderController : BaseController
                 .Includes(d => d.WorkflowTrace)
                 .FirstAsync(d => d.Id == dto.StepId, HttpContext.RequestAborted);
             if (step is null)
-                throw new UserFriendlyException("无效节点编号");
-            await _workflowDomainService.ChangeHandlerBatchAsync(new List<(string userId, string username, string orgId, string orgName, ICollection<WorkflowStep> steps)>
+                throw UserFriendlyException.SameMessage("无效节点编号");
+            await _workflowDomainService.ChangeHandlerBatchAsync(new List<(string userId, string username, string orgId, string orgName, string? roleId, string? roleName, ICollection<WorkflowStep> steps)>
             {
-                new(dto.Handler.UserId,dto.Handler.Username,dto.Handler.OrgId,dto.Handler.OrgName, new List<WorkflowStep>{step})
+                new(dto.Handler.UserId,dto.Handler.Username,dto.Handler.OrgId,dto.Handler.OrgName,step.RoleId,step.RoleName, new List<WorkflowStep>{step})
             }, HttpContext.RequestAborted);
         }
     }

+ 140 - 0
src/Hotline.Api/Controllers/OrderProvinceZmhdController.cs

@@ -0,0 +1,140 @@
+using DotNetCore.CAP;
+using Hotline.Orders;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Enums.Order;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using StackExchange.Redis;
+using System.Reflection;
+using XF.Domain.Authentications;
+using XF.Domain.Exceptions;
+using XF.Domain.Repository;
+
+namespace Hotline.Api.Controllers
+{
+    public class OrderProvinceZmhdController : BaseController
+    {
+        private readonly ILogger<OrderProvinceZmhdController> _logger;
+        private readonly ISessionContext _sessionContext;
+        private readonly IMapper _mapper;
+        private readonly ICapPublisher _capPublisher;
+        private readonly IOrderRepository _orderRepository;
+        private readonly IRepository<OrderProvinceZmhd> _orderProvinceZmhdRepository;
+
+        public OrderProvinceZmhdController(ILogger<OrderProvinceZmhdController> logger,
+            ISessionContext sessionContext,
+            IMapper mapper,
+            ICapPublisher capPublisher,
+            IOrderRepository orderRepository,
+            IRepository<OrderProvinceZmhd> orderProvinceZmhdRepository)
+        {
+            _logger = logger;
+            _sessionContext = sessionContext;
+            _mapper = mapper;
+            _capPublisher = capPublisher;
+            _orderRepository = orderRepository;
+            _orderProvinceZmhdRepository = orderProvinceZmhdRepository;
+        }
+
+        /// <summary>
+        /// 查询列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("getorderlist")]
+        public async Task<PagedDto<OrderDto>> GetOrderList([FromQuery] OrderProvinceZmhdDto dto)
+        {
+            RefAsync<int> total = 0;
+            var items = await _orderRepository.Queryable()
+                .Where(p => p.SourceChannelCode == "SZMHD" && p.IsProvince == false && p.Status >= EOrderStatus.Filed && p.Source == ESource.ProvinceStraight)
+                .WhereIF(!string.IsNullOrEmpty(dto.No), p => p.No == dto.No)
+                .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), p => p.ProvinceNo == dto.ProvinceNo)
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), p => p.Title.StartsWith(dto.Title!))
+                .WhereIF(!string.IsNullOrEmpty(dto.AnswerOu), p => p.ActualHandleOrgName == dto.AnswerOu)
+                .WhereIF(!string.IsNullOrEmpty(dto.AuditFirstName), p => p.AuditFirstName == dto.AuditFirstName)
+                .WhereIF(dto.IsProvinceZmhd.HasValue, p => p.IsProvinceZmhd == dto.IsProvinceZmhd)
+                .WhereIF(dto.StartTime.HasValue, d => d.AuditFirstTime >= dto.StartTime) //初审时间开始
+                .WhereIF(dto.EndTime.HasValue, d => d.AuditFirstTime <= dto.EndTime) //初审时间结束
+                .OrderByDescending(d => d.CreationTime)
+                .ToPageListAsync(dto.PageIndex, dto.PageSize, total, HttpContext.RequestAborted);
+
+            return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        }
+
+        /// <summary>
+        /// 查询政民互动发布详情
+        /// </summary>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpGet("getorderprovincezmhdinfo")]
+        public async Task<PublicOrderProvinceZmhdDto> GetOrderProvinceZmhdInfo(string Id)
+        {
+            var info = await _orderProvinceZmhdRepository.GetAsync(p => p.Id == Id, HttpContext.RequestAborted);
+            if (info == null)
+                throw UserFriendlyException.SameMessage("查询失败");
+
+            return _mapper.Map<PublicOrderProvinceZmhdDto>(info);
+        }
+
+        /// <summary>
+        /// 政民互动发布
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("add")]
+        public async Task AddOrderProvinceZmhd([FromBody] AddOrderProvinceZmhdDto dto)
+        {
+            if (string.IsNullOrEmpty(dto.AnswerContent))
+                throw UserFriendlyException.SameMessage("整理结果不能为空!");
+
+            if (string.IsNullOrEmpty(dto.PublicOpinion))
+                throw UserFriendlyException.SameMessage("公开意见不能为空!");
+
+            if (dto.PublicOpinion.Length > 300)
+                throw UserFriendlyException.SameMessage("公开意见不能超过300字符!");
+
+            var order = await _orderRepository.GetAsync(p => p.Id == dto.OrderId, HttpContext.RequestAborted);
+            if (order == null)
+                throw UserFriendlyException.SameMessage("工单查询失败!");
+
+            OrderProvinceZmhd orderProvinceZmhd = new()
+            {
+                No = order.No,
+                ProvinceNo = order.ProvinceNo,
+                OrderId = order.Id,
+                Title = order.Title,
+                AnswerTime = order.ActualHandleTime,
+                AnswerOu = order.ActualHandleOrgName,
+                AnswerContent = dto.AnswerContent,
+                AuditFirstName = _sessionContext.UserName,
+                AuditFirstTime = DateTime.Now,
+                AuditSecondName = _sessionContext.UserName,
+                PublishDate = DateTime.Now,
+                PublicOpinion = dto.PublicOpinion
+            };
+            //查询是否已经发布过
+            var info = await _orderProvinceZmhdRepository.GetAsync(p => p.OrderId == order.Id, HttpContext.RequestAborted);
+            if (info != null)
+                throw UserFriendlyException.SameMessage("此工单已公开!");
+
+            //发布
+            var id = await _orderProvinceZmhdRepository.AddAsync(orderProvinceZmhd, HttpContext.RequestAborted);
+            if (string.IsNullOrEmpty(id))
+                throw UserFriendlyException.SameMessage("公开失败!");
+
+            //修改工单发布数据
+            order.IsProvinceZmhd = true;
+            order.AuditFirstName = _sessionContext.UserName;
+            order.AuditFirstTime = orderProvinceZmhd.AuditFirstTime;
+            order.OrderProvinceZmhdId = orderProvinceZmhd.Id;
+            await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+
+            //推送数据
+            var publishPublishOrder = _mapper.Map<PublicOrderProvinceZmhdDto>(orderProvinceZmhd);
+            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderProvinceZmhd, publishPublishOrder);
+        }
+
+    }
+}

+ 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); 
+        }
     }
 }

+ 14 - 3
src/Hotline.Api/Controllers/TestController.cs

@@ -10,8 +10,10 @@ using Hotline.Ai.Visit;
 using Hotline.Application.ExportExcel;
 using Hotline.Application.JudicialManagement;
 using Hotline.Application.Quality;
+using Hotline.Application.StatisticalReport;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.FlowEngine;
@@ -43,6 +45,7 @@ using Hotline.Share.Enums.Push;
 using Hotline.Share.Enums.Quality;
 using Hotline.Share.Enums.Settings;
 using Hotline.Share.Mq;
+using Hotline.Share.Requests;
 using Hotline.Tools;
 using Hotline.Users;
 using MapsterMapper;
@@ -77,7 +80,7 @@ namespace Hotline.Api.Controllers;
 /// <summary>
 /// 
 /// </summary>
-[AllowAnonymous]
+//[AllowAnonymous]
 public class TestController : BaseController
 {
     private readonly ILogger<TestController> _logger;
@@ -121,7 +124,7 @@ public class TestController : BaseController
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IMapper _mapper;
     private readonly IOptionsSnapshot<SendSmsConfiguration> _sendSmsConfiguration;
-
+    private readonly IOrderReportApplication _orderReportApplication;
 
     //private readonly ITypedCache<List<User>> _cache;
     //private readonly ICacheManager<User> _cache;
@@ -167,7 +170,8 @@ public class TestController : BaseController
         IMapper mapper,
 
 
-   IOptionsSnapshot<SendSmsConfiguration> sendSmsConfiguration
+   IOptionsSnapshot<SendSmsConfiguration> sendSmsConfiguration,
+   IOrderReportApplication orderReportApplication
         )
     {
         _logger = logger;
@@ -206,7 +210,14 @@ public class TestController : BaseController
         _orderRepository = orderRepository;
         _mapper = mapper;
         _sendSmsConfiguration = sendSmsConfiguration;
+        _orderReportApplication = orderReportApplication;
+    }
+    [HttpGet("test222")]
+    public async Task test222([FromQuery] DepartmentalProcessingStatisticsRequest dto)
+    {
+      await   _orderReportApplication.DepartmentalProcessingStatisticsNew(dto);
     }
+
     [HttpGet("testo111")]
     [AllowAnonymous]
     public async Task Test111(DateTime StartTime, DateTime? EndTime)

+ 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);
     }

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

@@ -666,9 +666,9 @@ public class WorkflowController : BaseController
         //.GetAsync(dto.StepId, HttpContext.RequestAborted);
         if (step is null)
             throw new UserFriendlyException("无效节点编号");
-        await _workflowDomainService.ChangeHandlerBatchAsync(new List<(string userId, string username, string orgId, string orgName, ICollection<WorkflowStep> steps)>
+        await _workflowDomainService.ChangeHandlerBatchAsync(new List<(string userId, string username, string orgId, string orgName, string? roleId, string? roleName, ICollection<WorkflowStep> steps)>
             {
-                new(dto.Handler.UserId,dto.Handler.Username,dto.Handler.OrgId,dto.Handler.OrgName, new List<WorkflowStep>{step})
+                new(dto.Handler.UserId,dto.Handler.Username,dto.Handler.OrgId,dto.Handler.OrgName,step.RoleId,step.RoleName, new List<WorkflowStep>{step})
             }, 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 =>

+ 15 - 17
src/Hotline.Api/config/appsettings.Development.json

@@ -1,8 +1,8 @@
 {
   "AllowedHosts": "*",
   "CallCenterConfiguration": {
-    "CallCenterType": "WeiErXin", //XunShi、WeiErXin、TianRun
-    "DeviceConfigs": {
+    "CallCenterType": "TianRun", //XunShi、WeiErXin、TianRun、XingTang
+    "NewRock": {
       "Address": "http://192.168.100.100/xml",
       "Authorize": true,
       "ReceiveKey": "E1BBD1BB-A269-44",
@@ -13,10 +13,22 @@
       "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": {
-    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
     //"Redis": "110.188.24.182:50179",
     //"MongoDB": "mongodb://192.168.100.121:27017",
     //"Wex": "server=222.212.82.225;Port=4509;Database=fs_kft;Uid=root;Pwd=Wex@12345;"
@@ -103,20 +115,6 @@
     "Url": "http://118.122.73.80:19061",
     "Appkey": "MTAwMDAx",
     "ServiceVersion": "V1.0.0" //接口版本号
-    //"SceneUid": "MTAwMDAxVW7cUNRwRegsLGqb0pvXCU", //场景ID
-    //"RuleUid": "MTAwMDAxUbQsuOcmS5ApRyHGyWQr7g", //现有规则ID
-    //"VisitFromNameKey": "OC_SCENE_VAR_FIELD14", //来电名称       //开发环境 :OC_SCENE_VAR_FIELD14  //生产环境:OC_SCENE_VAR_FIELD12
-    //"VisitFromGenderKey": "OC_SCENE_VAR_FIELD13", //来电性别     //开发环境: OC_SCENE_VAR_FIELD13   //生产环境:OC_SCENE_VAR_FIELD14
-    //"VisitCreationTimeKey": "OC_SCENE_VAR_FIELD15", //来电时间   //开发环境:OC_SCENE_VAR_FIELD15    //生产环境:OC_SCENE_VAR_FIELD19
-    //"VisitOrderTitleKey": "OC_SCENE_VAR_FIELD16", //工单标题      //开发环境:OC_SCENE_VAR_FIELD16    //生产环境:OC_SCENE_VAR_FIELD20
-    //"VisitIsCallOrder": "OC_SCENE_VAR_FIELD17", //是否来电工单 //开发环境:OC_SCENE_VAR_FIELD17          //生产环境:
-    ////"QuestionIdOne": "MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM", //服务过程满意度 //开发环境:MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM  //生产环境:MTAwMDAxvgT-2PoYRR8pxyL4p8AJsM
-    //"QuestionIdZone": "MTAwMDAxvpXEOVcRQR0meGKouw6oXU", //是否联系  //开发环境:MTAwMDAxvpXEOVcRQR0meGKouw6oXU    //测试环境:
-    //"QuestionIdOne": "MTAwMDAxP2AJqUCvTU4jsgzvRkADVo", //是否解决 , //开发环境:MTAwMDAxP2AJqUCvTU4jsgzvRkADVo   //生产环境:
-    //"QuestionIdTwo": "MTAwMDAx_mLpLD0hSyosIwvgW-byjg", //办件结果满意度 //开发环境:MTAwMDAx_mLpLD0hSyosIwvgW-byjg  //生产环境:MTAwMDAxhIyRJzpwTskpsiXPD-uwl0
-    //"QuestionIdThree": "MTAwMDAxos3PXU5TTzEnXMSU8GeApc", //坐席是否满意  //开发环境:  //生产环境:
-    //"VisitContentIdOne": "reason1", //办件结果不满意原因 // 开发环境:NotSat2   //生产环境:NotSat2
-    //"VisitContentIdTwo": "reason2", //坐席不满意原因  // 开发环境:    //生产环境:
   },
   //智能质检
   "AiQuality": {

+ 15 - 17
src/Hotline.Api/config/appsettings.json

@@ -1,8 +1,8 @@
 {
   "AllowedHosts": "*",
   "CallCenterConfiguration": {
-    "CallCenterType": "WeiErXin", //XunShi、WeiErXin
-    "DeviceConfigs": {
+    "CallCenterType": "TianRun", //XunShi、WeiErXin、TianRun、XingTang
+    "NewRock": {
       "Address": "http://192.168.100.100/xml",
       "Authorize": true,
       "ReceiveKey": "E1BBD1BB-A269-44",
@@ -13,10 +13,22 @@
       "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": {
-    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
     //"Redis": "110.188.24.182:50179,password=fengwo22@@",
     //"MongoDB": "mongodb://192.168.100.121:27017",
     //"Wex": "server=222.212.82.225;Port=4509;Database=fs_kft;Uid=root;Pwd=Wex@12345;"
@@ -107,20 +119,6 @@
     "Url": "http://118.122.73.80:19061",
     "Appkey": "MTAwMDAx",
     "ServiceVersion": "V1.0.0" //接口版本号
-    //"SceneUid": "MTAwMDAxVW7cUNRwRegsLGqb0pvXCU", //场景ID
-    //"RuleUid": "MTAwMDAxUbQsuOcmS5ApRyHGyWQr7g", //现有规则ID
-    //"VisitFromNameKey": "OC_SCENE_VAR_FIELD14", //来电名称       //开发环境 :OC_SCENE_VAR_FIELD14  //生产环境:OC_SCENE_VAR_FIELD12
-    //"VisitFromGenderKey": "OC_SCENE_VAR_FIELD13", //来电性别     //开发环境: OC_SCENE_VAR_FIELD13   //生产环境:OC_SCENE_VAR_FIELD14
-    //"VisitCreationTimeKey": "OC_SCENE_VAR_FIELD15", //来电时间   //开发环境:OC_SCENE_VAR_FIELD15    //生产环境:OC_SCENE_VAR_FIELD19
-    //"VisitOrderTitleKey": "OC_SCENE_VAR_FIELD16", //工单标题      //开发环境:OC_SCENE_VAR_FIELD16    //生产环境:OC_SCENE_VAR_FIELD20
-    //"VisitIsCallOrder": "OC_SCENE_VAR_FIELD17", //是否来电工单 //开发环境:OC_SCENE_VAR_FIELD17          //生产环境:
-    ////"QuestionIdOne": "MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM", //服务过程满意度 //开发环境:MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM  //生产环境:MTAwMDAxvgT-2PoYRR8pxyL4p8AJsM
-    //"QuestionIdZone": "MTAwMDAxvpXEOVcRQR0meGKouw6oXU", //是否联系  //开发环境:MTAwMDAxvpXEOVcRQR0meGKouw6oXU    //测试环境:
-    //"QuestionIdOne": "MTAwMDAxP2AJqUCvTU4jsgzvRkADVo", //是否解决 , //开发环境:MTAwMDAxP2AJqUCvTU4jsgzvRkADVo   //生产环境:
-    //"QuestionIdTwo": "MTAwMDAx_mLpLD0hSyosIwvgW-byjg", //办件结果满意度 //开发环境:MTAwMDAx_mLpLD0hSyosIwvgW-byjg  //生产环境:MTAwMDAxhIyRJzpwTskpsiXPD-uwl0
-    //"QuestionIdThree": "MTAwMDAxos3PXU5TTzEnXMSU8GeApc", //坐席是否满意  //开发环境:  //生产环境:
-    //"VisitContentIdOne": "reason1", //办件结果不满意原因 // 开发环境:NotSat2   //生产环境:NotSat2
-    //"VisitContentIdTwo": "reason2" //坐席不满意原因  // 开发环境:    //生产环境:
   },
   //企业服务
   "Enterprise": {

+ 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);
             }
 

+ 4 - 3
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)
@@ -45,7 +46,7 @@ namespace Hotline.Application.CallCenter.Calls
                         {
                             if (telmodel.State == "logout")
                             {
-                                var telRest = await _telRestRepository.GetAsync(x => x.TelNo == item.TelNo && x.EndTime != null, stoppingToken);
+                                var telRest = await _telRestRepository.GetAsync(x => x.TelNo == item.TelNo && !x.EndTime.HasValue, stoppingToken);
                                 if (telRest is not null)
                                 {
                                     telRest.EndRest();

+ 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;

+ 5 - 0
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -67,6 +67,11 @@ namespace Hotline.Application.FlowEngine
         /// </summary>
         Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(string workflowId, CancellationToken cancellationToken);
 
+        /// <summary>
+        /// 查询指定节点的下一步待选节点
+        /// </summary>
+        Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(string workflowId, string stepId, CancellationToken cancellationToken);
+
         /// <summary>
         /// 查询撤回可选节点
         /// </summary>

+ 62 - 26
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -30,6 +30,7 @@ using Hotline.Share.Dtos.File;
 using Microsoft.Extensions.Logging;
 using System.Text;
 using System.Diagnostics;
+using NPOI.SS.Formula.Functions;
 
 namespace Hotline.Application.FlowEngine;
 
@@ -146,22 +147,25 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             current.RequiredUserId, current.RequiredOrgId,
             externalId, cancellationToken);
 
-        //var startStepHandles = new List<WorkflowStepHandler>{WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
-        //    EFlowAssignType.User, current.RequiredUserId, current.UserName,
-        //    current.RequiredOrgId, current.OrgName)};
-
-        var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
-            new FlowStepHandler
-            {
-                Key = current.RequiredUserId,
-                Value = current.UserName,
-                UserId = current.UserId,
-                Username = current.UserName,
-                OrgId = current.RequiredOrgId,
-                OrgName = current.OrgName
-            }, expiredTime);
-
-        var flowAssignInfo =
+		//var startStepHandles = new List<WorkflowStepHandler>{WorkflowStepHandler.Create(workflow.Id, workflow.ExternalId,
+		//    EFlowAssignType.User, current.RequiredUserId, current.UserName,
+		//    current.RequiredOrgId, current.OrgName)};
+
+		var defineHandler = startStepDefine.HandlerTypeItems.First();
+		var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
+			new FlowStepHandler
+			{
+				Key = current.RequiredUserId,
+				Value = current.UserName,
+				UserId = current.UserId,
+				Username = current.UserName,
+				OrgId = current.RequiredOrgId,
+				OrgName = current.OrgName,
+				RoleId = defineHandler.Key,
+				RoleName = defineHandler.Value,
+			}, expiredTime);
+
+		var flowAssignInfo =
             await GetNextStepFlowAssignInfoAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, cancellationToken);
 
         //var firstStepHandlers = await GetNextStepHandlersAsync(workflow, firstStepDefine, dto, cancellationToken);
@@ -218,8 +222,12 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
             withTraces: true, withCountersigns: true, cancellationToken: cancellationToken);
 
-        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow,
-            current.RequiredUserId, current.RequiredOrgId, current.Roles);
+        //var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow,
+        //    current.RequiredUserId, current.RequiredOrgId, current.Roles);
+        var currentStep = workflow.Steps.FirstOrDefault(d => d.Id == dto.StepId);
+        if (currentStep == null)
+            throw new UserFriendlyException(
+                $"未找到对应节点, workflowId: {dto.WorkflowId}, stepId: {dto.StepId}", "未找到对应节点");
         if (currentStep.Status is EWorkflowStepStatus.Handled)
             throw new UserFriendlyException("该状态不支持继续办理");
 
@@ -457,6 +465,24 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (currentStep.StepType is EStepType.End)
             throw new UserFriendlyException("结束节点无需办理");
 
+        return await GetNextStepsAsync(workflow, currentStep, cancellationToken);
+    }
+
+    public async Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(string workflowId, string stepId, CancellationToken cancellationToken)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
+            cancellationToken: cancellationToken);
+        var currentStep = workflow.Steps.FirstOrDefault(d => d.Id == stepId);
+        if (currentStep == null)
+            throw new UserFriendlyException($"未查询到选择节点, workflowId: {workflowId}, stepId: {stepId}");
+        if (currentStep.StepType is EStepType.End)
+            throw new UserFriendlyException("结束节点无需办理");
+
+        return await GetNextStepsAsync(workflow, currentStep, cancellationToken);
+    }
+
+    private async Task<NextStepsWithOpinionDto<NextStepOption>> GetNextStepsAsync(Workflow workflow, WorkflowStep currentStep, CancellationToken cancellationToken)
+    {
         var dto = new NextStepsWithOpinionDto<NextStepOption>
         {
             CanReject = workflow.IsReviewType() && currentStep.CanReject,
@@ -465,6 +491,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             CurrentStepBusinessType = currentStep.BusinessType,
             TimeTypeOptions = EnumExts.GetDescriptions<ETimeType>().ToList(),
             IsMainHandlerShow = workflow.WorkflowDefinition.IsMainHandlerShow,
+            StepId = currentStep.Id
         };
 
         var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
@@ -485,14 +512,15 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             {
                 // 宜宾需求:会签汇总节点展示会签办理节点办理意见
                 var countersignHandleSteps = workflow.Steps.Where(d =>
-                        d.CountersignId == currentStep.CountersignId &&
-                        d.CountersignPosition is ECountersignPosition.Multi or ECountersignPosition.Single).ToList();
+                    d.CountersignId == currentStep.CountersignId &&
+                    d.CountersignPosition is ECountersignPosition.Multi or ECountersignPosition.Single).ToList();
                 var sb = new StringBuilder();
                 foreach (var countersignHandleStep in countersignHandleSteps)
                 {
                     //sb.AppendLine($"{countersignHandleStep.GetActualHandler()?.GetHandler().Value} : {countersignHandleStep.Opinion}");
                     sb.AppendLine($"{countersignHandleStep.GetHandler().Value} : {countersignHandleStep.Opinion}");
                 }
+
                 dto.Opinion = sb.ToString();
 
                 //当前待办节点为会签汇总节点时:检查是否为顶级会签汇总节点,t:按配置往下走,f:继续往上汇总,不需要重复往下指派
@@ -713,6 +741,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                 var summaryTargetStep = workflow.Steps.FirstOrDefault(d =>
                     d.StepType == EStepType.Normal &&
                     d.Code == stepDefine.SummaryTargetCode &&
+                    d.Status == EWorkflowStepStatus.Handled &&
                     d.IsOrigin);
                 if (summaryTargetStep is null)
                     throw UserFriendlyException.SameMessage("未查询到汇总对象节点");
@@ -725,7 +754,11 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                     Key = summaryTargetStep.HandlerId,
                     Value = summaryTargetStep.HandlerName,
                     UserId = summaryTargetStep.HandlerId,
-                    Username = summaryTargetStep.HandlerName
+                    Username = summaryTargetStep.HandlerName,
+                    OrgId = summaryTargetStep.HandlerOrgId,
+                    OrgName = summaryTargetStep.HandlerOrgName,
+                    RoleId = summaryTargetStep.RoleId,
+                    RoleName = summaryTargetStep.RoleName
                 };
 
                 nextStepOption = new NextStepOption
@@ -820,8 +853,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                 if (flowType is EFlowType.Handle
                     && (stepDefine.StepType != EStepType.Summary && stepDefine.BusinessType != EBusinessType.Center))
                     users1 = users1.Where(d => d.OrgId.StartsWith(levelOneOrgId));
+                var defineTypeItem = stepDefine.HandlerTypeItems.First();
 
-                handlers = users1.Where(d => d != null && !string.IsNullOrEmpty(d.Id))
+				handlers = users1.Where(d => d != null && !string.IsNullOrEmpty(d.Id))
                     .Select(d => new FlowStepHandler
                     {
                         Key = d.Id,
@@ -829,8 +863,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                         UserId = d.Id,
                         Username = d.Name,
                         OrgId = d.OrgId,
-                        OrgName = d.Organization.Name
-                    })
+                        OrgName = d.Organization.Name,
+                        RoleId = defineTypeItem.Key,
+                        RoleName = defineTypeItem.Value
+					})
                     .ToList();
                 break;
             case EHandlerType.OrgLevel:
@@ -967,7 +1003,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         return new NextStepOption
         {
             Key = orgLevel.ToString(),
-            Value = orgLevel == 0 ? "热线中心" : $"{orgLevel.ToChinese()}级部门",
+            Value = orgLevel == 0 ? "市民热线服务中心" : $"{orgLevel.ToChinese()}级部门",
         };
     }
 
@@ -1097,7 +1133,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         return new NextStepOption
         {
             Key = orgLevel.ToString(),
-            Value = orgLevel == 0 ? "热线中心" : $"{orgLevel.ToChinese()}级部门",
+            Value = orgLevel == 0 ? "市民热线服务中心" : $"{orgLevel.ToChinese()}级部门",
             FlowDirection = flowDirection,
             StepType = stepType,
             BusinessType = businessType,

+ 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
 

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

@@ -7,6 +7,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="JV.PanGu.Core" Version="1.0.1" />
     <PackageReference Include="NPOI" Version="2.7.0" />
     <PackageReference Include="XC.RSAUtil" Version="1.3.6" />
     <PackageReference Include="Quartz.Jobs" Version="3.8.0" />
@@ -22,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 == null || !d.IsSync) && (d.Tries == null || d.Tries <= 50))
+                .Take(100)
+                .ToListAsync(context.CancellationToken);
+
+            var occupyCalls = new List<XingtangCall>();
+            foreach (var call in calls)
+            {
+                var rows = await _db.Updateable(new XingtangCall
+                {
+                    Id = call.Id,
+                    IsSync = true,
+                    Tries = call.Tries + 1
+                }).ExecuteCommandWithOptLockAsync();
+                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 => s.ReceiveEndTime.HasValue ? s.ReceiveEndTime : s.CallEndTime)
+                .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;
             }
         }
-
     }
-}
+}

+ 39 - 9
src/Hotline.Application/Mappers/OrderMapperConfigs.cs

@@ -16,7 +16,7 @@ public class OrderMapperConfigs : IRegister
             .IgnoreIf((s, d) => s.OrderExtension == null, d => d.OrderExtension)
             .IgnoreIf((s, d) => s.Hotspot == null, d => d.Hotspot)
             ;
-        //TODO 等待测试
+
         config.ForType<AiOrderVisitDetail, AiOrderVisitDetailDto>()
             .IgnoreIf((s, d) => s.Order == null, d => d.No)
             .IgnoreIf((s, d) => s.Order == null, d => d.Title)
@@ -30,12 +30,7 @@ public class OrderMapperConfigs : IRegister
             .Map(d => d.FromGender, s => s.Order.FromGender)
             .Map(d => d.StartTime, s => s.Order.StartTime)
             .Map(d => d.FiledTime, s => s.Order.FiledTime)
-            //.IgnoreIf((s, d) => s.OrderVisit.OrderVisitDetails == null || !s.OrderVisit.OrderVisitDetails.Any() || s.OrderVisit.OrderVisitDetails.All(x=>x.VisitTarget != Share.Enums.Order.EVisitTarget.Seat), d => d.SeatEvaluate)
-            // .IgnoreIf((s, d) => s.OrderVisit.OrderVisitDetails == null && s.OrderVisit.OrderVisitDetails.Count > 0, d => d.OrgProcessingResults)
-            //.IgnoreIf((s, d) => s.OrderVisit.OrderVisitDetails == null && s.OrderVisit.OrderVisitDetails.Count > 0, d => d.IsContact)
-            //.IgnoreIf((s, d) => s.OrderVisit.OrderVisitDetails == null && s.OrderVisit.OrderVisitDetails.Count > 0, d => d.Volved)
-            //.Ignore(d=>d.SeatEvaluate)
-            //.Map(d=>d.SeatEvaluate, s=>s.OrderVisit.OrderVisitDetails.First(x=> x.VisitTarget == EVisitTarget.Seat))
+            .Map(d => d.RecordUrl, s => s.OrderVisit.RecordUrl)
             .AfterMapping((s, d) =>
             {
                 d.SeatEvaluate = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Seat)?.SeatEvaluate;
@@ -43,8 +38,43 @@ public class OrderMapperConfigs : IRegister
                 d.IsContact = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.IsContact == true ? "是" : "否";
                 d.Volved = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.Volved == true ? "是" : "否";
                 d.IsSuccessText = s.IsSuccess == true ? "是" : "否";
-            })
-            ;
+            });
+
+        config.ForType<OrderVisitDetail, OrgVisitDetailListResp>()
+            //.IgnoreIf((s, d) => s.OrderVisit == null, d => d.VisitId)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.Id)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.No)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.ReTransactNum)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.HotspotSpliceName)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.OrgLevelOneName)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.ActualHandleOrgName)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.Title)
+            .IgnoreIf((s, d) => s.OrderVisit.Employee == null, d => d.VisitUser)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.Content)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.FileOpinion)
+            .IgnoreIf((s, d) => s.OrderVisit.Order == null, d => d.FiledTime)
+            .Map(d => d.VisitId, s => s.OrderVisit.Id)
+            .Map(d => d.Id, s => s.OrderVisit.Order.Id)
+            .Map(d => d.No, s => s.OrderVisit.Order.No)
+            .Map(d => d.ReTransactNum, s => s.OrderVisit.Order.ReTransactNum)
+            .Map(d => d.HotspotSpliceName, s => s.OrderVisit.Order.HotspotSpliceName)
+            .Map(d => d.OrgLevelOneName, s => s.OrderVisit.Order.OrgLevelOneName)
+            .Map(d => d.ActualHandleOrgName, s => s.OrderVisit.Order.ActualHandleOrgName)
+            .Map(d => d.Title, s => s.OrderVisit.Order.Title)
+            .Map(d => d.VisitUser, s => s.OrderVisit.Employee.Name)
+            .Map(d => d.VisitType, s => s.OrderVisit.VisitType)
+            .Map(d => d.VisitTime, s => s.OrderVisit.VisitTime)
+            .Map(d => d.Content, s => s.OrderVisit.Order.Content)
+            .Map(d => d.FileOpinion, s => s.OrderVisit.Order.FileOpinion)
+            .Map(d => d.FiledTime, s => s.OrderVisit.Order.FiledTime)
+            .AfterMapping((s, d) =>
+            {
+                d.OrderScreenStatus = s.OrderVisit.Order.OrderScreens.OrderByDescending(q=>q.CreationTime).FirstOrDefault()?.Status;
+                d.OrgProcessingResults = s.OrgProcessingResults.Value;
+            });
+
+            
+
 
 
 

+ 8 - 15
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -44,7 +44,7 @@ namespace Hotline.Application.Orders
 		//Task<PagedDto<WorkflowOrderDto>> GetToExpireNodeAsync(AboutToExpireListDto dto, CancellationToken cancellationToken);
 		ISugarQueryable<Order> GetAboutToExpireAsync(AboutToExpireListDto dto);
         //Task<PagedDto<WorkflowOrderDto>> GetAboutToExpireNodeAsync(AboutToExpireListDto dto, CancellationToken cancellationToken);
-        Task OrderParticiple(string inputStr, string orderId, CancellationToken cancellationToken);
+        Task OrderParticiple(string inputStr, string orderId,DateTime time , CancellationToken cancellationToken);
         Task OrderSensitiveParticiple(string inputStr, string orderId, CancellationToken cancellationToken);
         /// <summary>
         /// 接收外部平台工单
@@ -84,13 +84,6 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         ISugarQueryable<Order> QueryOrderSource(QueryOrderSourceRequest dto);
 
-		/// <summary>
-		/// 信件来源统计列表
-        /// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		Task<List<OrderSourceHeaderVo>> QueryOrderSourceList(QueryOrderSourceRequest dto);
-
         /// <summary>
         /// 信件来源统计
         /// </summary>
@@ -98,13 +91,6 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         ISugarQueryable<Order> QueryOrderSourceDetail(QueryOrderSourceDetailRequest dto);
 
-		/// <summary>
-		/// 信件来源时分统计列表
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		Task<List<OrderSourceHeaderVo>> QueryOrderSourceHoursList(QueryOrderSourceRequest dto);
-
 		/// <summary>
 		/// 部门超期统计
 		/// </summary>
@@ -119,6 +105,13 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
 		ISugarQueryable<Order> QueryOrgDataListDetail(OrgDataListDetailRequest dto);
 
+		/// <summary>
+		/// 部门全量超期统计明细
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		ISugarQueryable<Order> QueryOrgDataListDetail(OrgDataListAllDetailRequest dto);
+
 		/// <summary>
 		/// 回退错件统计
 		/// </summary>

+ 82 - 160
src/Hotline.Application/Orders/OrderApplication.cs

@@ -36,6 +36,9 @@ using Hotline.Repository.SqlSugar.System;
 using Microsoft.AspNetCore.Mvc;
 using Hotline.Share.Dtos.Bi;
 using System.Net;
+using PanGu;
+using Hotline.Users;
+using PanGu.Match;
 
 namespace Hotline.Application.Orders;
 
@@ -201,7 +204,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
 		//stTime = _timeLimitDomainService.WorkDay(stTime);
 		//DateTime stTime2 = _timeLimitDomainService.WorkDay(DateTime.Now);
 		DateTime? dateTime = DateTime.Now;
-		return _orderRepository.Queryable(canView: true).Includes(d => d.OrderDelays)
+		var IsCenter = _sessionContext.OrgIsCenter;
+
+		return _orderRepository.Queryable(canView: !IsCenter).Includes(d => d.OrderDelays)
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No!))
             .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title!))
@@ -250,8 +255,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     public ISugarQueryable<Order> GetToExpireAsync(AboutToExpireListDto dto)
     {
         DateTime stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
+        var IsCenter = _sessionContext.OrgIsCenter;
 
-        return _orderRepository.Queryable(canView: true).Includes(d => d.OrderDelays)
+		return _orderRepository.Queryable(canView: !IsCenter).Includes(d => d.OrderDelays)
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             //.WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
             .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No.Contains(dto.No))
@@ -291,29 +297,44 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// </summary>
     /// <param name="inputStr"></param>
     /// <returns></returns>
-    public async Task OrderParticiple(string inputStr, string orderId, CancellationToken cancellationToken)
+    public async Task OrderParticiple(string inputStr, string orderId,DateTime time, CancellationToken cancellationToken)
     {
-        var words = await _orderWrodRepository.Queryable().Where(x => x.IsEnable == 1 && x.Classify.Contains("普通标签")).Select(x => x.Tag).ToListAsync(cancellationToken);
-        var res = new List<string>();
-        if (words.Any()) res = ParticipleTool.SegMMDouble(inputStr, ref words);
-        var participles = await _orderWrodRepository.Queryable().In(x => x.Tag, res).ToListAsync(cancellationToken);
-        if (participles.Any())
+        var seg = new Segment();
+		ICollection<WordInfo> splitWords = seg.DoSegment(inputStr);
+        var words = new List<string>();
+        for (int i = 0; i < splitWords.Count; i++)
         {
-            //关键词
-            var tags = participles.Select(x => x.Tag).ToList();
-            var tagsStr = string.Join(",", tags);
-            await _orderRepository.Updateable().SetColumns(x => x.TagNames == tagsStr).Where(x => x.Id == orderId).ExecuteCommandAsync(cancellationToken);
-            List<string> synonyms = participles.Select(x => x.Synonym).ToList();
-            if (synonyms.Any())
-            {
-                var synonymsStr = string.Join(",", synonyms);
-                synonyms = synonymsStr.Split(",").Distinct().ToList();
-                tags.AddRange(synonyms);
-            }
-            var vector = await _orderRepository.Queryable().Where(x => x.Id == orderId).ToListAsync(cancellationToken);
-            if (vector.Any()) await _repositoryts.UpdateVectorAsync(orderId, tags, cancellationToken);
-            else await _repositoryts.AddVectorAsync(orderId, DateTime.Now, tags, cancellationToken);
-        }
+            var word = splitWords.ElementAt(i);
+            if (word is { WordType: WordType.SimplifiedChinese, Word.Length: > 1 } )
+	            words.Add(splitWords.ElementAt(i).Word);
+		}
+        if (words.Any())
+        {
+			var vector = await _repositoryts.SearchAsync(orderId, cancellationToken);
+			if (vector != null && vector.Any()) await _repositoryts.UpdateVectorAsync(orderId, words, cancellationToken);
+			else await _repositoryts.AddVectorAsync(orderId, time, words, cancellationToken);
+		}
+        //var words = await _orderWrodRepository.Queryable().Where(x => x.IsEnable == 1 && x.Classify.Contains("普通标签")).Select(x => x.Tag).ToListAsync(cancellationToken);
+        //var res = new List<string>();
+        //if (words.Any()) res = ParticipleTool.SegMMDouble(inputStr, ref words);
+        //var participles = await _orderWrodRepository.Queryable().In(x => x.Tag, res).ToListAsync(cancellationToken);
+        //if (participles.Any())
+        //{
+        //    //关键词
+        //    var tags = participles.Select(x => x.Tag).ToList();
+        //    var tagsStr = string.Join(",", tags);
+        //    await _orderRepository.Updateable().SetColumns(x => x.TagNames == tagsStr).Where(x => x.Id == orderId).ExecuteCommandAsync(cancellationToken);
+        //    List<string> synonyms = participles.Select(x => x.Synonym).ToList();
+        //    if (synonyms.Any())
+        //    {
+        //        var synonymsStr = string.Join(",", synonyms);
+        //        synonyms = synonymsStr.Split(",").Distinct().ToList();
+        //        tags.AddRange(synonyms);
+        //    }
+        //    var vector = await _orderRepository.Queryable().Where(x => x.Id == orderId).ToListAsync(cancellationToken);
+        //    if (vector.Any()) await _repositoryts.UpdateVectorAsync(orderId, tags, cancellationToken);
+        //    else await _repositoryts.AddVectorAsync(orderId, DateTime.Now, tags, cancellationToken);
+        //}
     }
 
     public async Task OrderSensitiveParticiple(string inputStr, string orderId, CancellationToken cancellationToken)
@@ -521,70 +542,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .Where(d => d.SourceChannel != null && d.SourceChannel != "");
     }
 
-    /// <summary>
-    /// 信件来源统计列表
-    /// </summary>
-    /// <param name="dto"></param>
-    /// <returns></returns>
-    public async Task<List<OrderSourceHeaderVo>> QueryOrderSourceList(QueryOrderSourceRequest dto)
-    {
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-        var data = await _orderRepository.Queryable()
-            .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
-            .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
-            .WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
-            .Where(d => d.SourceChannel != null && d.SourceChannel != "")
-            .GroupBy(d => new { Time = d.CreationTime.ToString("yyyy-MM-dd"), d.SourceChannel })
-            .Select(d => new OrderSourceHeaderVo
-            {
-                Time = d.CreationTime.ToString("yyyy-MM-dd"),
-                Phone = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "RGDH", 1, 0)),
-                Web = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YTW", 1, 0)),
-                Rests = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "QT", 1, 0)),
-                Created = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "ZJ", 1, 0)),
-                WeChat = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "WX", 1, 0)),
-                App = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "AP", 1, 0)),
-                WisdomYB = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "ZHYB", 1, 0)),
-                Platform = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "ZZPT", 1, 0)),
-                Platform12328 = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "S12328", 1, 0)),
-                MayorAndNetizens = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SZYSM", 1, 0)),
-                MediaYB = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YBRMT", 1, 0)),
-                Platform12345 = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "S12345", 1, 0)),
-                Interaction = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SZMHD", 1, 0)),
-                ServiceYB = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YBS", 1, 0)),
-                CityTransfer = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SZHZ", 1, 0)),
-                Platform110 = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YB110", 1, 0)),
-                NoService = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SMZXBNCS", 1, 0)),
-                Iyb = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "IYB", 1, 0))
-            }).ToListAsync();
-        var totalVo = new OrderSourceHeaderVo()
-        {
-            Time = "合计",
-            Phone = data.Sum(x => x.Phone),
-            Web = data.Sum(x => x.Web),
-            Rests = data.Sum(x => x.Rests),
-            Created = data.Sum(x => x.Created),
-            WeChat = data.Sum(x => x.WeChat),
-            App = data.Sum(x => x.App),
-            WisdomYB = data.Sum(x => x.WisdomYB),
-            Platform = data.Sum(x => x.Platform),
-            Platform12328 = data.Sum(x => x.Platform12328),
-            MayorAndNetizens = data.Sum(x => x.MayorAndNetizens),
-            MediaYB = data.Sum(x => x.MediaYB),
-            Platform12345 = data.Sum(x => x.Platform12345),
-            Interaction = data.Sum(x => x.Interaction),
-            ServiceYB = data.Sum(x => x.ServiceYB),
-            CityTransfer = data.Sum(x => x.CityTransfer),
-            Platform110 = data.Sum(x => x.Platform110),
-            NoService = data.Sum(x => x.NoService),
-            Iyb = data.Sum(x => x.Iyb)
-        };
-        data.Add(totalVo);
-        return data;
-    }
-
-
 	/// <summary>
 	/// 信件来源统计明细
 	/// </summary>
@@ -594,78 +551,12 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     {
 
         return _orderRepository.Queryable()
-            .WhereIF(string.IsNullOrEmpty(dto.SourceChannel), d => d.SourceChannel == dto.SourceChannel)
+            .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), d => d.SourceChannel == dto.SourceChannel)
             .WhereIF(dto.Time.HasValue, d => d.CreationTime.ToString("yyyy-MM-dd") == dto.Time.Value.ToString("yyyy-MM-dd"))
             .WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
             .Where(d => d.SourceChannel != null && d.SourceChannel != "");
     }
 
-	/// <summary>
-	/// 信件来源时分统计列表
-	/// </summary>
-	/// <param name="dto"></param>
-	/// <returns></returns>
-	public async Task<List<OrderSourceHeaderVo>> QueryOrderSourceHoursList(QueryOrderSourceRequest dto)
-	{
-		if (dto.EndTime.HasValue)
-			dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
-        var data =await _orderRepository.Queryable()
-			.WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
-			.WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
-			.WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
-			.Where(d => d.SourceChannel != null && d.SourceChannel != "")
-			.GroupBy(d => new { Time = d.CreationTime.ToString("HH"), d.SourceChannel })
-			.Select(d => new OrderSourceHeaderVo
-			{
-				Time = d.CreationTime.ToString("HH")+":00 - " + d.CreationTime.ToString("HH")+":59",
-                TimeSort = d.CreationTime.ToString("HH"),
-				Phone = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "RGDH", 1, 0)),
-				Web = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YTW", 1, 0)),
-				Rests = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "QT", 1, 0)),
-				Created = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "ZJ", 1, 0)),
-				WeChat = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "WX", 1, 0)),
-				App = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "AP", 1, 0)),
-				WisdomYB = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "ZHYB", 1, 0)),
-				Platform = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "ZZPT", 1, 0)),
-				Platform12328 = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "S12328", 1, 0)),
-				MayorAndNetizens = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SZYSM", 1, 0)),
-				MediaYB = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YBRMT", 1, 0)),
-				Platform12345 = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "S12345", 1, 0)),
-				Interaction = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SZMHD", 1, 0)),
-				ServiceYB = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YBS", 1, 0)),
-				CityTransfer = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SZHZ", 1, 0)),
-				Platform110 = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "YB110", 1, 0)),
-				NoService = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "SMZXBNCS", 1, 0)),
-				Iyb = SqlFunc.AggregateSum(SqlFunc.IIF(d.SourceChannelCode == "IYB", 1, 0))
-			}).OrderBy(d=> d.TimeSort).ToListAsync();
-
-		var totalVo = new OrderSourceHeaderVo()
-		{
-			Time = "合计",
-			Phone = data.Sum(x => x.Phone),
-			Web = data.Sum(x => x.Web),
-			Rests = data.Sum(x => x.Rests),
-			Created = data.Sum(x => x.Created),
-			WeChat = data.Sum(x => x.WeChat),
-			App = data.Sum(x => x.App),
-			WisdomYB = data.Sum(x => x.WisdomYB),
-			Platform = data.Sum(x => x.Platform),
-			Platform12328 = data.Sum(x => x.Platform12328),
-			MayorAndNetizens = data.Sum(x => x.MayorAndNetizens),
-			MediaYB = data.Sum(x => x.MediaYB),
-			Platform12345 = data.Sum(x => x.Platform12345),
-			Interaction = data.Sum(x => x.Interaction),
-			ServiceYB = data.Sum(x => x.ServiceYB),
-			CityTransfer = data.Sum(x => x.CityTransfer),
-			Platform110 = data.Sum(x => x.Platform110),
-			NoService = data.Sum(x => x.NoService),
-			Iyb = data.Sum(x => x.Iyb)
-		};
-		data.Add(totalVo);
-		return data;
-	}
-
 	/// <summary>
 	/// 部门超期统计
 	/// </summary>
@@ -750,6 +641,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
 		var quer = _orderRepository.Queryable()
 			.InnerJoin<SystemOrganize>((x, so) => x.ActualHandleOrgCode == so.Id)
 			.Where(x => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
+			//.WhereIF(dto.Statuses.Any(), x => dto.Statuses.Contains(x.Status))  //工单状态
 			.WhereIF(dto.QueryType == 1, x => x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime) //业务已办超期
 			.WhereIF(dto.QueryType == 3, x => x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate()) //业务待办超期
 			.WhereIF(dto.QueryType == 5, x =>
@@ -776,12 +668,42 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return quer;
 	}
 
-    /// <summary>
-    /// 回退错件统计
-    /// </summary>
-    /// <param name="dto"></param>
-    /// <returns></returns>
-    public ISugarQueryable<OrderReTransactVo> OrderReTransact(QueryOrderReTransactRequest dto)
+	/// <summary>
+	/// 部门超期统计明细
+	/// </summary>
+	/// <param name="dto"></param>
+	/// <returns></returns>
+	public ISugarQueryable<Order> QueryOrgDataListDetail(OrgDataListAllDetailRequest dto)
+	{
+		dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
+		bool IsCenter = _sessionContext.OrgIsCenter;
+
+		var quer = _orderRepository.Queryable()
+			.InnerJoin<SystemOrganize>((x, so) => x.ActualHandleOrgCode == so.Id)
+			.Where(x => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
+            .WhereIF(dto.Statuses.Any(), x => dto.Statuses.Contains(x.Status))  //工单状态
+            .Where(x =>
+				(x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime) || (x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate()))
+			.WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && IsCenter == false, x => x.ActualHandleOrgCode.StartsWith(dto.OrgCode))
+			.MergeTable();
+
+        var queryCountersign = _workflowCountersignRepository.Queryable()
+            .LeftJoin<WorkflowCountersignMember>((x, o) => x.Id == o.WorkflowCountersignId)
+            .Where((x, o) => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime && x.IsExpired.HasValue && x.IsExpired.Value == true)
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && IsCenter == false, (x, o) => o.Key.StartsWith(dto.OrgCode))
+            .Select((x, o) => new { Id = x.WorkflowId })
+            .MergeTable();
+
+         quer = quer.InnerJoin(queryCountersign, (x, c) => x.WorkflowId == c.Id);
+        return quer;
+	}
+
+	/// <summary>
+	/// 回退错件统计
+	/// </summary>
+	/// <param name="dto"></param>
+	/// <returns></returns>
+	public ISugarQueryable<OrderReTransactVo> OrderReTransact(QueryOrderReTransactRequest dto)
     {
 
 		return _orderSpecialDetailRepository.Queryable()

+ 35 - 4
src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs

@@ -1,16 +1,40 @@
 using Hotline.Orders;
-using Hotline.Repository.SqlSugar.Orders;
-using Hotline.Settings;
 using Hotline.Share.Dtos.Order;
-using Hotline.Share.Enums.Order;
 using Hotline.Share.Requests;
 using SqlSugar;
-using XF.Domain.Authentications;
 
 namespace Hotline.Application.StatisticalReport
 {
     public interface IOrderReportApplication
     {
+        /// <summary>
+        /// 部门办件统计表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<List<DepartmentalProcessingStatisticsDataDto>> DepartmentalProcessingStatisticsNew(DepartmentalProcessingStatisticsRequest dto);
+
+        /// <summary>
+        /// 部门办件统计表--子级---新
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<List<DepartmentalProcessingStatisticsDataDto>> DepartmentalProcessingChildStatisticsNew(DepartmentalProcessingStatisticsRequest dto);
+
+        /// <summary>
+        /// 部门办件统计表--明细---新
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<SelectOrderId> GetDepartmentalProcessingStatisticsListNew(DepartmentalProcessingStatisticsRequest dto, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 部门办件统计明细表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<SelectOrderId> DepartmentalProcessingStatisticsDetailsList(DepartmentalProcessingStatisticsRequest dto);
+
         /// <summary>
         /// 部门办件统计表
         /// </summary>
@@ -59,5 +83,12 @@ namespace Hotline.Application.StatisticalReport
         /// <param name="dto"></param>
         /// <returns></returns>
         ISugarQueryable<Order> DepartmentAcceptanceTypeOrderList(DepartmentKeyWordRequest dto);
+
+        /// <summary>
+        /// 满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrderVisitDetail> OrgVisitDetailList(OrgVisitDetailListReq dto);
     }
 }

+ 709 - 13
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -8,23 +8,15 @@ using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos.Order;
-using Hotline.Share.Dtos;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Requests;
 using MapsterMapper;
-using Microsoft.AspNetCore.Http;
 using SqlSugar;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
-using XF.Domain.Repository;
-using Microsoft.AspNetCore.Mvc;
 using XF.Domain.Exceptions;
+using XF.Domain.Repository;
 
 namespace Hotline.Application.StatisticalReport
 {
@@ -37,7 +29,6 @@ namespace Hotline.Application.StatisticalReport
         private readonly IRepository<OrderDelay> _orderDelayRepository;
         private readonly IMapper _mapper;
         private readonly IRepository<WorkflowCountersign> _workflowCountersignRepository;
-        //private readonly IRepository<WorkflowStepHandler> _workflowStepHandleRepository;
         private readonly IRepository<OrderSpecial> _orderSpecialRepository;
         private readonly IRepository<OrderVisit> _orderVisitRepository;
         private readonly IRepository<TrCallRecord> _trCallRecordRepository;
@@ -51,6 +42,7 @@ namespace Hotline.Application.StatisticalReport
         private readonly IRepository<OrderScreen> _orderScreenRepository;
         private readonly IOrderSecondaryHandlingApplication _orderSecondaryHandlingApplication;
         private readonly ITimeLimitDomainService _timeLimitDomainService;
+        
 
         public OrderReportApplication(
             IOrderRepository orderRepository,
@@ -71,7 +63,6 @@ namespace Hotline.Application.StatisticalReport
             IRepository<OrderSpecialDetail> orderSpecialDetailRepository,
             IRepository<WorkflowTrace> workflowTraceRepository,
             IRepository<OrderScreen> orderScreenRepository,
-            //IRepository<WorkflowStepHandler> workflowStepHandleRepository,
             IOrderSecondaryHandlingApplication orderSecondaryHandlingApplication,
             ITimeLimitDomainService timeLimitDomainService
             )
@@ -94,9 +85,683 @@ namespace Hotline.Application.StatisticalReport
             _orderSpecialDetailRepository = orderSpecialDetailRepository;
             _workflowTraceRepository = workflowTraceRepository;
             _orderScreenRepository = orderScreenRepository;
-            //_workflowStepHandleRepository = workflowStepHandleRepository;
             _orderSecondaryHandlingApplication = orderSecondaryHandlingApplication;
             _timeLimitDomainService = timeLimitDomainService;
+            
+        }
+        /// <summary>
+        /// 部门办件统计表---新
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<List<DepartmentalProcessingStatisticsDataDto>> DepartmentalProcessingStatisticsNew(DepartmentalProcessingStatisticsRequest dto)
+        {
+            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
+            var IsCenter = _sessionContext.OrgIsCenter;
+
+            //信件总量:信件总量=已办件数+在办件数,工单需去重
+            //已办件数:该部门已办理完成的工单总数(含参与会签的工单),若工单被部门多次办理,只统计一次
+            //在办件数:该部门还未办理的工单数(若是一级部门,需包含中心向该部门发起回签的工单)。(特殊说明:部门或者中心发起了会签,会签中还未汇总,应算发起会签部门的在办里面)
+
+            string strSql = @"select 
+""OrgCode""
+,""Name"" ""OrgName""
+,""OrgType""
+, ""YbOrderCountNum""
+, ""ZbOrderCountNum""
+,""Archived""
+, ""ToBeArchived""
+, ""WaitPublished""
+,""PublishedOpen""
+, ""PublishedNoOpen""
+,""YbOverdue""
+, ""ZbOverdue""
+, ""HqzbOverdue""
+, ""HqybOverdue""
+, ""DelayEnd""
+, ""DelayWait""
+, ""OrderDelayCount""
+, ""ScreenCount""
+, ""ScreenApproval""
+, ""ScreenPass""
+,""ScreenNotPass""
+,""SatisfactionCount""
+,""NotSatisfactionCount""
+, (""YbOrderCountNum""-""YbOverdue""  -""HqybOverdue"" ) ""CompleteOnTime""
+
+from (
+
+SELECT ""HandlerOrgId"" ""OrgCode""
+,SUM(""YbOrderCountNum"") ""YbOrderCountNum""
+,SUM(""ZbOrderCountNum"") ""ZbOrderCountNum""
+,SUM(""Archived"") ""Archived""
+,SUM(""ToBeArchived"") ""ToBeArchived""
+,SUM(""WaitPublished"") ""WaitPublished""
+,SUM(""PublishedOpen"") ""PublishedOpen""
+,SUM(""PublishedNoOpen"") ""PublishedNoOpen""
+,SUM(""YbOverdue"") ""YbOverdue""
+,SUM(""ZbOverdue"") ""ZbOverdue""
+,SUM(""HqzbOverdue"") ""HqzbOverdue""
+,SUM(""HqybOverdue"") ""HqybOverdue""
+,SUM(""DelayEnd"") ""DelayEnd""
+,SUM(""DelayWait"") ""DelayWait""
+,SUM(""OrderDelayCount"") ""OrderDelayCount""
+,SUM(""ScreenCount"") ""ScreenCount""
+,SUM(""ScreenApproval"") ""ScreenApproval""
+,SUM(""ScreenPass"") ""ScreenPass""
+,SUM(""ScreenNotPass"") ""ScreenNotPass""
+,SUM(""SatisfactionCount"") ""SatisfactionCount""
+,SUM(""NotSatisfactionCount"") ""NotSatisfactionCount""
+FROM (
+
+		/*查询已办*/
+		select  ""HandlerOrgId"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"",0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"" ,0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"" ,0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10  and ""t"".""Status"">=2   {2} --and ""t"".""CountersignPosition""<=1 
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询待办*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""ZbOrderCountNum"",0 ""YbOverdue"",0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2  {2} --and ""t"".""CountersignPosition""<=1 
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询已办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2 and ""HandleTime"">""StepExpiredTime"" and ""t"".""CountersignPosition""=0   {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询待办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2 and (SELECT NOW())>""StepExpiredTime"" and ""t"".""CountersignPosition""=0   {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签已办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2 and ""HandleTime"">""StepExpiredTime"" and ""CountersignPosition"">0  {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签待办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS  ""HqzbOverdue"" ,0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2 and (SELECT NOW())>""StepExpiredTime"" 
+			and   ""CountersignPosition"">0  {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签已办*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2 and ""CountersignPosition"">0 {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签待办*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS  ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2 and ""CountersignPosition"">0 {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		UNION ALL
+		/*已归档、 待发布、已发布公开、已发布不公开*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait""
+		,SUM(( CASE  WHEN ( ""Status"">=300 ) THEN 1  ELSE 0 END )) AS ""Archived""
+		,0 ""ToBeArchived""
+		,SUM(( CASE  WHEN ( ""Status""=300 ) THEN 1  ELSE 0 END )) AS ""WaitPublished""
+		,SUM(( CASE  WHEN ( ""Status"">=400 and ""IsPublicity""=TRUE  ) THEN 1  ELSE 0 END )) AS ""PublishedOpen""
+		,SUM(( CASE  WHEN ( ""Status"">=400 and ""IsPublicity""=FALSE  ) THEN 1  ELSE 0 END )) AS ""PublishedNoOpen""
+		,0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+			select  SUBSTRING(""o"".""ActualHandleOrgCode"",1,{3}) ""HandlerOrgId"", ""o"".""Status"", ""o"".""IsPublicity"" from ""order"" ""o""
+			where  ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and  ""o"".""Status"">=300  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询延期通过数量*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS  ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+			select  SUBSTRING(""ApplyOrgCode"",1,{3}) ""HandlerOrgId"" from ""order_delay"" ""d""
+			left join ""order"" ""o"" on ""d"".""OrderId""=""o"".""Id""
+			where  ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}' and ""d"".""DelayState""=1  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		union all 
+		/*查询甄别*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"" 
+		,SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""ScreenCount""
+		,SUM(( CASE  WHEN ( ""Status""<=1 ) THEN 1  ELSE 0 END )) AS ""ScreenApproval""
+		,SUM(( CASE  WHEN ( ""Status""=2 ) THEN 1  ELSE 0 END )) AS ""ScreenPass""
+		,SUM(( CASE  WHEN ( ""Status""=3 ) THEN 1  ELSE 0 END )) AS ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount""
+		from(
+			select  SUBSTRING(""d"".""CreatorOrgId"",1,{3}) ""HandlerOrgId"",""d"".""Status"" from ""order_screen"" ""d""
+			left join ""order"" ""o"" on ""d"".""OrderId""=""o"".""Id""
+			where  ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询满意度*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" 
+		,SUM(( CASE  WHEN ( (""OrgProcessingResults""->>'Key')::VARCHAR != '2' ) THEN 1  ELSE 0 END )) AS ""SatisfactionCount""
+		,SUM(( CASE  WHEN ( (""OrgProcessingResults""->>'Key')::VARCHAR = '2'  ) THEN 1  ELSE 0 END )) AS ""NotSatisfactionCount""
+		FROM(
+			SELECT SUBSTRING(""VisitOrgCode"",1,{3}) ""HandlerOrgId"" ,""OrgProcessingResults"" from ""order_visit_detail"" ""d""
+			left join ""order_visit"" ""v"" on ""v"".""Id""=""d"".""VisitId""
+			left join ""order"" ""o"" on ""o"".""Id""=""v"".""OrderId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}' and ""d"".""VisitTarget""=20 and ""v"".""VisitState""=30 and ""d"".""VisitOrgCode"" is not NULL  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+)""te""
+GROUP BY ""HandlerOrgId""
+) ""su""
+left join ""system_organize"" ""so"" on ""so"".""Id""=""su"".""OrgCode""
+where 1=1 {5}
+order by ""su"".""OrgCode""";
+            var orgLength = IsCenter == true ? 6 : _sessionContext.RequiredOrgId.Length + 3;
+            var isOrg = IsCenter == false ? " and \"HandlerOrgId\" like concat('" + _sessionContext.RequiredOrgId + "','%') " : " ";
+            var IsProvince = dto.IsProvince.HasValue && dto.IsProvince == true ? "  and \"o\".\"Source\"=100 " : " ";
+            var orgName = string.IsNullOrEmpty(dto.OrgName) == false ? "   and   \"OrgName\" like concat('%'," + dto.OrgName + ",'%')" : "";
+
+            strSql = string.Format(strSql, dto.StartTime, dto.EndTime, IsProvince, orgLength, isOrg, orgName);
+
+            return _orderRepository.DepartmentalProcessingStatisticsNew(strSql);
+        }
+
+        /// <summary>
+        /// 部门办件统计表--子级---新
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<List<DepartmentalProcessingStatisticsDataDto>> DepartmentalProcessingChildStatisticsNew(DepartmentalProcessingStatisticsRequest dto)
+        {
+            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
+
+            //信件总量:信件总量=已办件数+在办件数,工单需去重
+            //已办件数:该部门已办理完成的工单总数(含参与会签的工单),若工单被部门多次办理,只统计一次
+            //在办件数:该部门还未办理的工单数(若是一级部门,需包含中心向该部门发起回签的工单)。(特殊说明:部门或者中心发起了会签,会签中还未汇总,应算发起会签部门的在办里面)
+
+            string strSql = @"select 
+""OrgCode""
+,""Name"" ""OrgName""
+,""OrgType""
+, ""YbOrderCountNum""
+, ""ZbOrderCountNum""
+,""Archived""
+, ""ToBeArchived""
+, ""WaitPublished""
+,""PublishedOpen""
+, ""PublishedNoOpen""
+,""YbOverdue""
+, ""ZbOverdue""
+, ""HqzbOverdue""
+, ""HqybOverdue""
+, ""DelayEnd""
+, ""DelayWait""
+, ""OrderDelayCount""
+, ""ScreenCount""
+, ""ScreenApproval""
+, ""ScreenPass""
+,""ScreenNotPass""
+,""SatisfactionCount""
+,""NotSatisfactionCount""
+, (""YbOrderCountNum""-""YbOverdue""  -""HqybOverdue"" ) ""CompleteOnTime""
+
+from (
+
+SELECT ""HandlerOrgId"" ""OrgCode""
+,SUM(""YbOrderCountNum"") ""YbOrderCountNum""
+,SUM(""ZbOrderCountNum"") ""ZbOrderCountNum""
+,SUM(""Archived"") ""Archived""
+,SUM(""ToBeArchived"") ""ToBeArchived""
+,SUM(""WaitPublished"") ""WaitPublished""
+,SUM(""PublishedOpen"") ""PublishedOpen""
+,SUM(""PublishedNoOpen"") ""PublishedNoOpen""
+,SUM(""YbOverdue"") ""YbOverdue""
+,SUM(""ZbOverdue"") ""ZbOverdue""
+,SUM(""HqzbOverdue"") ""HqzbOverdue""
+,SUM(""HqybOverdue"") ""HqybOverdue""
+,SUM(""DelayEnd"") ""DelayEnd""
+,SUM(""DelayWait"") ""DelayWait""
+,SUM(""OrderDelayCount"") ""OrderDelayCount""
+,SUM(""ScreenCount"") ""ScreenCount""
+,SUM(""ScreenApproval"") ""ScreenApproval""
+,SUM(""ScreenPass"") ""ScreenPass""
+,SUM(""ScreenNotPass"") ""ScreenNotPass""
+,SUM(""SatisfactionCount"") ""SatisfactionCount""
+,SUM(""NotSatisfactionCount"") ""NotSatisfactionCount""
+FROM (
+
+		/*查询已办*/
+		select  ""HandlerOrgId"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"",0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"" ,0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"" ,0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2   {2} --and ""t"".""CountersignPosition""<=1 
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询待办*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""ZbOrderCountNum"",0 ""YbOverdue"",0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2  {2} --and ""t"".""CountersignPosition""<=1 
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询已办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2 and ""HandleTime"">""StepExpiredTime"" and ""t"".""CountersignPosition""=0   {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询待办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2 and (SELECT NOW())>""StepExpiredTime"" and ""t"".""CountersignPosition""=0   {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签已办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"",0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2 and ""HandleTime"">""StepExpiredTime"" and ""CountersignPosition"">0  {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签待办超期*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS  ""HqzbOverdue"" ,0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2 and (SELECT NOW())>""StepExpiredTime"" 
+			and   ""CountersignPosition"">0  {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签已办*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""TraceState"" !=10 and ""t"".""Status"">=2 and ""CountersignPosition"">0 {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询会签待办*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS  ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+		 select ""o"".""Id"",SUBSTRING(""t"".""HandlerOrgId"",1,{3}) ""HandlerOrgId"" from ""workflow_trace"" ""t""
+			left join ""order"" ""o"" on ""o"".""Id""=""t"".""ExternalId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and ""t"".""ModuleCode""='OrderHandle' and ""t"".""Status""<2 and ""CountersignPosition"">0 {2}
+			GROUP BY SUBSTRING(""t"".""HandlerOrgId"",1,{3}),""o"".""Id""
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		UNION ALL
+		/*已归档、 待发布、已发布公开、已发布不公开*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait""
+		,SUM(( CASE  WHEN ( ""Status"">=300 ) THEN 1  ELSE 0 END )) AS ""Archived""
+		,0 ""ToBeArchived""
+		,SUM(( CASE  WHEN ( ""Status""=300 ) THEN 1  ELSE 0 END )) AS ""WaitPublished""
+		,SUM(( CASE  WHEN ( ""Status"">=400 and ""IsPublicity""=TRUE  ) THEN 1  ELSE 0 END )) AS ""PublishedOpen""
+		,SUM(( CASE  WHEN ( ""Status"">=400 and ""IsPublicity""=FALSE  ) THEN 1  ELSE 0 END )) AS ""PublishedNoOpen""
+		,0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+			select  SUBSTRING(""o"".""ActualHandleOrgCode"",1,{3}) ""HandlerOrgId"", ""o"".""Status"", ""o"".""IsPublicity"" from ""order"" ""o""
+			where  ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  and  ""o"".""Status"">=300  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询延期通过数量*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS  ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" ,0 ""SatisfactionCount"", 0 ""NotSatisfactionCount"" from(
+			select  SUBSTRING(""ApplyOrgCode"",1,{3}) ""HandlerOrgId"" from ""order_delay"" ""d""
+			left join ""order"" ""o"" on ""d"".""OrderId""=""o"".""Id""
+			where  ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}' and ""d"".""DelayState""=1  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		union all 
+		/*查询甄别*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"" 
+		,SUM(( CASE  WHEN ( ""HandlerOrgId"" IS NOT NULL ) THEN 1  ELSE 0 END )) AS ""ScreenCount""
+		,SUM(( CASE  WHEN ( ""Status""<=1 ) THEN 1  ELSE 0 END )) AS ""ScreenApproval""
+		,SUM(( CASE  WHEN ( ""Status""=2 ) THEN 1  ELSE 0 END )) AS ""ScreenPass""
+		,SUM(( CASE  WHEN ( ""Status""=3 ) THEN 1  ELSE 0 END )) AS ""ScreenNotPass"",0 ""SatisfactionCount"", 0 ""NotSatisfactionCount""
+		from(
+			select  SUBSTRING(""d"".""CreatorOrgId"",1,{3}) ""HandlerOrgId"",""d"".""Status"" from ""order_screen"" ""d""
+			left join ""order"" ""o"" on ""d"".""OrderId""=""o"".""Id""
+			where  ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}'  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL  {4}
+		GROUP BY ""HandlerOrgId""
+		union ALL
+		/*查询满意度*/
+		select  ""HandlerOrgId"",0 ""YbOrderCountNum"",0 ""ZbOrderCountNum"",0 ""YbOverdue"" ,0 ""ZbOverdue"",0 ""HqybOverdue"",0 ""HqzbOverdue"",0 ""DelayEnd"",0 ""DelayWait"" ,0""Archived"",0 ""ToBeArchived"",0 ""WaitPublished"",0 ""PublishedOpen"",0 ""PublishedNoOpen"",0 ""OrderDelayCount"",0 ""ScreenCount"",0 ""ScreenApproval"", 0 ""ScreenPass"" , 0 ""ScreenNotPass"" 
+		,SUM(( CASE  WHEN ( (""OrgProcessingResults""->>'Key')::VARCHAR != '2' ) THEN 1  ELSE 0 END )) AS ""SatisfactionCount""
+		,SUM(( CASE  WHEN ( (""OrgProcessingResults""->>'Key')::VARCHAR = '2'  ) THEN 1  ELSE 0 END )) AS ""NotSatisfactionCount""
+		FROM(
+			SELECT SUBSTRING(""VisitOrgCode"",1,{3}) ""HandlerOrgId"" ,""OrgProcessingResults"" from ""order_visit_detail"" ""d""
+			left join ""order_visit"" ""v"" on ""v"".""Id""=""d"".""VisitId""
+			left join ""order"" ""o"" on ""o"".""Id""=""v"".""OrderId""
+			where ""o"".""CreationTime"">='{0}' and ""o"".""CreationTime""<='{1}' and ""d"".""VisitTarget""=20 and ""v"".""VisitState""=30 and ""d"".""VisitOrgCode"" is not NULL  {2}
+		)""s"" where ""HandlerOrgId"" IS not NULL {4}
+		GROUP BY ""HandlerOrgId""
+)""te""
+GROUP BY ""HandlerOrgId""
+) ""su""
+left join ""system_organize"" ""so"" on ""so"".""Id""=""su"".""OrgCode""
+where 1=1 {5}
+order by ""su"".""OrgCode""";
+
+            var IsProvince = dto.IsProvince.HasValue && dto.IsProvince == true ? "  and \"o\".\"Source\"=100 " : " ";
+            var orgLength = dto.OrgCode.Length + 3;
+
+            var isOrg = dto.OrgCode == "001" ? "  and \"HandlerOrgId\" ='001'" : " and \"HandlerOrgId\" like concat('" + dto.OrgCode + "','%') ";
+
+            var orgName = string.IsNullOrEmpty(dto.OrgName) == false ? "   and   \"OrgName\" like concat('%'," + dto.OrgName + ",'%')" : "";
+
+            strSql = string.Format(strSql, dto.StartTime, dto.EndTime, IsProvince, orgLength, isOrg, orgName);
+
+            return _orderRepository.DepartmentalProcessingStatisticsNew(strSql);
+        }
+
+        /// <summary>
+        /// 部门办件统计表--明细---新
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<SelectOrderId> GetDepartmentalProcessingStatisticsListNew(DepartmentalProcessingStatisticsRequest dto, CancellationToken cancellationToken)
+        {
+            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
+
+            RefAsync<int> total = 0;
+            ISugarQueryable<SelectOrderId> query = null;
+            switch (dto.StatisticsType)
+            {
+                case EStatisticsType.YBOrderCountNum://工单已办
+                    query = _workflowTraceRepository.Queryable()
+                        .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                         .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                         && t.Status >= EWorkflowStepStatus.Handled)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .GroupBy((t, o) => o.Id)
+                         .Select((t, o) => new SelectOrderId { Id = o.Id })
+                         .MergeTable();
+                    break;
+                case EStatisticsType.ZBOrderCountNum://工单在办
+                    query = _workflowTraceRepository.Queryable()
+                      .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                       .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                       && t.Status < EWorkflowStepStatus.Handled)
+                       .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                       .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                       .GroupBy((t, o) => o.Id)
+                       .Select((t, o) => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.OrderDelayCount://延期次数
+                    query = _orderDelayRepository.Queryable()
+                          .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
+                        .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && d.DelayState == EDelayState.Pass)
+                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                        .WhereIF(dto.OrgCode == "001", (d, o) => d.ApplyOrgCode == dto.OrgCode)
+                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.ApplyOrgCode.StartsWith(dto.OrgCode))
+                        .WhereIF(dto.OrgCode == "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.ApplyOrgCode == dto.OrgCode)
+                        .OrderByDescending((d, o) => o.CreationTime)
+                        .Select((d, o) => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.YBOverdue://已办超期
+                    query = _workflowTraceRepository.Queryable()
+                        .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                         .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                         && t.Status >= EWorkflowStepStatus.Handled && t.HandleTime > t.StepExpiredTime && t.CountersignPosition == ECountersignPosition.None)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .GroupBy((t, o) => o.Id)
+                         .Select((t, o) => new SelectOrderId { Id = o.Id })
+                         .MergeTable();
+                    break;
+                case EStatisticsType.ZBOverdue://待办超期
+                    query = _workflowTraceRepository.Queryable()
+                        .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                         .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                         && t.Status < EWorkflowStepStatus.Handled && DateTime.Now > t.StepExpiredTime && t.CountersignPosition == ECountersignPosition.None)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .GroupBy((t, o) => o.Id)
+                         .Select((t, o) => new SelectOrderId { Id = o.Id })
+                         .MergeTable();
+                    break;
+                case EStatisticsType.HQYBOverdue://会签已办超期
+                    query = _workflowTraceRepository.Queryable()
+                        .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                         .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                         && t.Status >= EWorkflowStepStatus.Handled && t.HandleTime > t.StepExpiredTime && t.CountersignPosition > ECountersignPosition.None)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .GroupBy((t, o) => o.Id)
+                         .Select((t, o) => new SelectOrderId { Id = o.Id })
+                         .MergeTable();
+                    break;
+                case EStatisticsType.HQZBOverdue://会签待办超期
+                    query = _workflowTraceRepository.Queryable()
+                        .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                         .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                         && t.Status < EWorkflowStepStatus.Handled && DateTime.Now > t.StepExpiredTime && t.CountersignPosition > ECountersignPosition.None)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .GroupBy((t, o) => o.Id)
+                         .Select((t, o) => new SelectOrderId { Id = o.Id })
+                         .MergeTable();
+                    break;
+                case EStatisticsType.SubtotalOverdue://超期件数
+                    var cqybquery = _workflowTraceRepository.Queryable()
+                           .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                            .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                            && t.Status >= EWorkflowStepStatus.Handled && t.HandleTime > t.StepExpiredTime && t.CountersignPosition >= ECountersignPosition.None)
+                            .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                            .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                            .GroupBy((t, o) => o.Id)
+                            .Select((t, o) => new SelectOrderId { Id = o.Id })
+                            .MergeTable();
+                    var cqdbquery = _workflowTraceRepository.Queryable()
+                            .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                             .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                             && t.Status < EWorkflowStepStatus.Handled && DateTime.Now > t.StepExpiredTime && t.CountersignPosition >= ECountersignPosition.None)
+                             .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                             .GroupBy((t, o) => o.Id)
+                             .Select((t, o) => new SelectOrderId { Id = o.Id })
+                             .MergeTable();
+                    query = _orderRepository.UnionAll(cqybquery, cqdbquery).GroupBy(p => p.Id).MergeTable();
+                    break;
+                case EStatisticsType.DelayEnd://会签已办
+                    query = _workflowTraceRepository.Queryable()
+                           .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                            .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                            && t.Status >= EWorkflowStepStatus.Handled && t.CountersignPosition > ECountersignPosition.None)
+                            .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                            .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                            .GroupBy((t, o) => o.Id)
+                            .Select((t, o) => new SelectOrderId { Id = o.Id })
+                            .MergeTable();
+                    break;
+                case EStatisticsType.DelayWait://会签待办
+                    query = _workflowTraceRepository.Queryable()
+                            .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                             .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
+                             && t.Status < EWorkflowStepStatus.Handled && t.CountersignPosition > ECountersignPosition.None)
+                             .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                             .GroupBy((t, o) => o.Id)
+                             .Select((t, o) => new SelectOrderId { Id = o.Id })
+                             .MergeTable();
+                    break;
+                case EStatisticsType.ToBeArchived://待归档没得数据
+                    query = _orderRepository.Queryable()
+                            .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status < EOrderStatus.WaitForAccept)
+                           .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                            .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
+                             .Select(o => new SelectOrderId { Id = o.Id })
+                          .MergeTable();
+                    break;
+                case EStatisticsType.Archived://已归档
+                    query = _orderRepository.Queryable()
+                          .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status >= EOrderStatus.Filed)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                          .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
+                           .Select(o => new SelectOrderId { Id = o.Id })
+                        .MergeTable();
+                    break;
+                case EStatisticsType.WaitPublished://待发布
+                    query = _orderRepository.Queryable()
+                         .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status == EOrderStatus.Filed)
+                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
+                          .Select(o => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.PublishedOpen://发布公开
+                    query = _orderRepository.Queryable()
+                         .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status >= EOrderStatus.Published && o.IsPublicity == true)
+                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
+                          .Select(o => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.PublishedNoOpen://发布不公开
+                    query = _orderRepository.Queryable()
+                        .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status >= EOrderStatus.Published && o.IsPublicity == false)
+                       .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                        .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
+                            .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
+                         .Select(o => new SelectOrderId { Id = o.Id })
+                      .MergeTable();
+                    break;
+                case EStatisticsType.ScreenCount://甄别总量
+                    query = _orderScreenRepository.Queryable()
+                        .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
+                       .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null)
+                       .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                       .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
+                        .Select((d, o) => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.ScreenApproval://带甄别
+                    query = _orderScreenRepository.Queryable()
+                       .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
+                       .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null
+                       && (d.Status == EScreenStatus.Approval || d.Status == EScreenStatus.Apply))
+                       .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                       .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
+                        .Select((d, o) => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.ScreenPass://甄别通过
+                    query = _orderScreenRepository.Queryable()
+                       .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
+                       .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null && d.Status == EScreenStatus.End)
+                       .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                       .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
+                        .Select((d, o) => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                case EStatisticsType.ScreenNotPass://甄别不通过
+                    query = _orderScreenRepository.Queryable()
+                      .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
+                      .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null && d.Status == EScreenStatus.Refuse)
+                      .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                      .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
+                       .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
+                        .Select((d, o) => new SelectOrderId { Id = o.Id })
+                       .MergeTable();
+                    break;
+                default:
+                    break;
+            }
+            return query;
+        }
+
+        /// <summary>
+        /// 部门办件统计明细表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<SelectOrderId> DepartmentalProcessingStatisticsDetailsList(DepartmentalProcessingStatisticsRequest dto)
+        {
+            var query = _workflowTraceRepository.Queryable()
+                        .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
+                         .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime)
+                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         // .WhereIF(IsCenter, (t, o) => t.HandlerOrgId == dto.OrgCode)
+                         .WhereIF(!_sessionContext.OrgIsCenter, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
+                         .GroupBy((t, o) => o.Id)
+                         .Select((t, o) => new SelectOrderId { Id = o.Id })
+                         .MergeTable();
+
+            return query;
         }
 
         /// <summary>
@@ -1081,7 +1746,7 @@ namespace Hotline.Application.StatisticalReport
                })
                 .Select((it, o) => new DepartmentAcceptanceTypeStatisticsDto
                 {
-                    OrgName = it.OrgCode == "001" ? "热线中心" : o.Name,
+                    OrgName = it.OrgCode == "001" ? "市民热线服务中心" : o.Name,
                     OrgCode = it.OrgCode,
                     OrgType = o.OrgType == EOrgType.County ? "区县部门" : "市直部门",
                     ZxAllCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.AcceptTypeCode == "10", 1, 0)),
@@ -1139,5 +1804,36 @@ namespace Hotline.Application.StatisticalReport
                  .OrderByDescending(d => d.CreationTime)
                  .MergeTable();
         }
+
+
+        /// <summary>
+        /// 满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<OrderVisitDetail> OrgVisitDetailList(OrgVisitDetailListReq dto)
+        {
+            var IsCenter = _sessionContext.OrgIsCenter;
+
+            return _orderVisitDetailRepository.Queryable()
+                .Includes(x => x.OrderVisit, x => x.Order, x => x.OrderScreens)
+                .Includes(x => x.OrderVisit, x => x.Employee)
+                .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.VisitTarget == EVisitTarget.Org)
+                .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.RequiredOrgId))
+                .WhereIF(dto.OrgVisitStatisticsType.HasValue, x => x.OrderVisit.Order.ProcessType == (EProcessType)((int)dto.OrgVisitStatisticsType))
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
+                .WhereIF(!string.IsNullOrEmpty(dto.VisitUser), x => x.OrderVisit.Employee.Name.Contains(dto.VisitUser))
+                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order.No == dto.No)
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order.Title.Contains(dto.Title))
+                .WhereIF(dto.OrgCodes.Any(), x => dto.OrgCodes.Contains(x.VisitOrgCode))
+                .WhereIF(dto.HotspotIds.Any(), x => dto.HotspotIds.Contains(x.OrderVisit.Order.HotspotId))
+                .WhereIF(dto.Channels.Any(), x => dto.Channels.Contains(x.OrderVisit.Order.SourceChannelCode))
+                .WhereIF(dto.CreationTimeStart.HasValue, x => x.OrderVisit.Order.CreationTime >= dto.CreationTimeStart) //受理时间开始
+                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.OrderVisit.Order.CreationTime <= dto.CreationTimeEnd) //受理时间结束
+                .WhereIF(dto.ActualHandleTimeStart.HasValue, x => x.OrderVisit.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
+                .WhereIF(dto.ActualHandleTimeEnd.HasValue, x => x.OrderVisit.Order.ActualHandleTime <= dto.ActualHandleTimeEnd)
+                .OrderBy(x => x.OrderVisit.VisitTime); //办结时间结束
+
+        }
     }
 }

+ 2 - 2
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -232,7 +232,7 @@ namespace Hotline.Application.Subscribers
             model.ApplyContent = dto.RemindReasion;
             model.OrderId = order.Id;
             model.OrgId = "001";
-            model.OrgName = "热线中心";
+            model.OrgName = "市民热线服务中心";
             model.ApplyContent = dto.RemindReasion;
 
             if (!string.IsNullOrEmpty(order.WorkflowId))
@@ -271,7 +271,7 @@ namespace Hotline.Application.Subscribers
             model.OrderId = order.Id;
             model.ReplyLimitTime = dto.WarnTimebf;
             model.OrgId = "001";
-            model.OrgName = "热线中心";
+            model.OrgName = "市民热线服务中心";
 
             if (!string.IsNullOrEmpty(order.WorkflowId))
             {

+ 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;
         }
     }

+ 1 - 1
src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs

@@ -99,7 +99,7 @@ namespace Hotline.Repository.SqlSugar.CallCenter
                     EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration >= effectiveTimes, 1, 0)),//有效接通
                     ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration > 0 && o.Duration <= connectByeTimes, 1, 0)), //接通秒挂
                     NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration == 0 && o.RingTimes <= noConnectByeTimes && o.RingTimes>0, 1, 0)), //未接通秒挂
-                    QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.QueueTims > 0 && o.RingTimes == 0, 1, 0)), //队列挂断
+                    QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.QueueTims > 0 && o.RingTimes == 0 && o.OnState == EOnState.NoOn, 1, 0)), //队列挂断
                     IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.BeginIvrTime.HasValue && !o.BeginQueueTime.HasValue && !o.BeginRingTime.HasValue && o.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
                 })
                 .MergeTable()

+ 2 - 2
src/Hotline.Repository.SqlSugar/Extensions/SqlSugarStartupExtensions.cs

@@ -207,8 +207,8 @@ namespace Hotline.Repository.SqlSugar.Extensions
             /***写AOP等方法***/
             db.Aop.OnLogExecuting = (sql, pars) =>
             {
-                //Log.Information("Sql: {0}", sql);
-                //Log.Information("SqlParameters: {0}", string.Join(',', pars.Select(d => d.Value)));
+                // Log.Information("Sql: {0}", sql);
+                // Log.Information("SqlParameters: {0}", string.Join(',', pars.Select(d => d.Value)));
             };
             db.Aop.OnError = (exp) =>//SQL报错
             {

+ 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);
+    }
+}

+ 597 - 4
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -1,11 +1,20 @@
-using Hotline.Orders;
+using Hotline.CallCenter.Calls;
+using Hotline.Orders;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Enums.CallCenter;
+using Hotline.Share.Enums.Order;
 using Hotline.Share.Requests;
 using SqlSugar;
+using System.Data;
+using System.Linq;
+using System.Linq.Dynamic.Core;
 using System.Reflection;
+using System.Reflection.Emit;
+using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 
 namespace Hotline.Repository.SqlSugar.Orders
@@ -125,7 +134,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                        .Select(p => new DepartmentalProcessingStatisticsDataDto
                        {
                            OrgCode = p.OrgCode,
-                         //  OrderCountNum = SqlFunc.AggregateSum(p.OrderCountNum),
+                           //  OrderCountNum = SqlFunc.AggregateSum(p.OrderCountNum),
                            YbOrderCountNum = SqlFunc.AggregateSum(p.YbOrderCountNum),
                            ZbOrderCountNum = SqlFunc.AggregateSum(p.ZbOrderCountNum),
                            Archived = SqlFunc.AggregateSum(p.Archived),
@@ -135,7 +144,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                            PublishedNoOpen = SqlFunc.AggregateSum(p.PublishedNoOpen),
                            YbOverdue = SqlFunc.AggregateSum(p.YbOverdue),
                            ZbOverdue = SqlFunc.AggregateSum(p.ZbOverdue),
-                           CompleteOnTime= SqlFunc.AggregateSum(p.CompleteOnTime),
+                           CompleteOnTime = SqlFunc.AggregateSum(p.CompleteOnTime),
                            HqybOverdue = SqlFunc.AggregateSum(p.HqybOverdue),
                            HqzbOverdue = SqlFunc.AggregateSum(p.HqzbOverdue),
                            DelayEnd = SqlFunc.AggregateSum(p.DelayEnd),
@@ -150,9 +159,593 @@ namespace Hotline.Repository.SqlSugar.Orders
                        })
                        .MergeTable();
 
-                      
+
+        }
+
+        public  ISugarQueryable<T> UnionAll<T>(params ISugarQueryable<T>[] queryables) where T : class
+        {
+            return Db.UnionAll(queryables);
+        }
+
+        /// <summary>
+        /// 部门办件统计
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <returns></returns>
+        public List<DepartmentalProcessingStatisticsDataDto> DepartmentalProcessingStatisticsNew(string sql)
+        {
+            return Db.Ado.SqlQuery<DepartmentalProcessingStatisticsDataDto>(sql);
+
+        }
+
+        /// <summary>
+        /// 区域分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderAreaTime(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemArea>()
+              .LeftJoin(listOrder, (s, p) => s.Id == p.AreaCode)
+              .Where((s, p) => s.Id.Length == 6 && s.Id != "510000")
+              .GroupBy((s, p) => s.Id).GroupBy((s, p) => s.AreaName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.Id)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.AreaCode != null && p.AreaCode != "", 1, 0)),
+                  AreaCode = s.Id,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  AreaName = s.AreaName
+              })
+              .MergeTable();
+
+            var list = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   p.AreaCode,
+                   p.count
+               })
+                .ToPivotListAsync(p => p.AreaCode, p => p.Hour, p => p.Sum(x => x.count));
+            return list;
+
+        }
+
+        /// <summary>
+        /// 区域分时统计--导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderAreaTimeExport(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemArea>()
+              .LeftJoin(listOrder, (s, p) => s.Id == p.AreaCode)
+              .Where((s, p) => s.Id.Length == 6 && s.Id != "510000")
+              .GroupBy((s, p) => s.Id).GroupBy((s, p) => s.AreaName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.Id)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.AreaCode != null && p.AreaCode != "", 1, 0)),
+                  AreaCode = s.Id,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  AreaName = s.AreaName
+              })
+              .MergeTable();
+
+            var dt = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+               .OrderBy(x => x.ColumnName)
+              .Select((x, p) => new
+              {
+                  Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                  p.AreaName,
+                  p.count
+              })
+               .ToPivotTableAsync(p => p.AreaName, p => p.Hour, p => p.Sum(x => x.count));
+
+            return InitDatatTable(dt, dto.AddColumnName);
         }
 
+        /// <summary>
+        /// 热点类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderHotspotTime(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     HotspotCode = p.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<Hotspot>()
+              .LeftJoin(listOrder, (s, p) => s.Id == p.HotspotCode)
+              .Where((s, p) => s.Id.Length == 2 && (s.ParentId == null || s.ParentId == ""))
+              .GroupBy((s, p) => s.Id).GroupBy((s, p) => s.HotSpotName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.Id)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.HotspotCode != null && p.HotspotCode != "", 1, 0)),
+                  HotspotCode = s.Id,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  HotSpotName = s.HotSpotName
+              })
+              .MergeTable();
+
+            var list = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   p.HotspotCode,
+                   p.count
+               })
+                .ToPivotListAsync(p => p.HotspotCode, p => p.Hour, p => p.Sum(x => x.count));
+            return list;
+
+        }
+
+        /// <summary>
+        /// 热点类型分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderHotspotTimeExport(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     HotspotCode = p.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<Hotspot>()
+              .LeftJoin(listOrder, (s, p) => s.Id == p.HotspotCode)
+              .Where((s, p) => s.Id.Length == 2 && (s.ParentId == null || s.ParentId == ""))
+              .GroupBy((s, p) => s.Id).GroupBy((s, p) => s.HotSpotName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.Id)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.HotspotCode != null && p.HotspotCode != "", 1, 0)),
+                  HotspotCode = s.Id,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  HotSpotName = s.HotSpotName
+              })
+              .MergeTable();
+
+            var dt = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+               .OrderBy(x => x.ColumnName)
+              .Select((x, p) => new
+              {
+                  Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                  p.HotSpotName,
+                  p.count
+              })
+               .ToPivotTableAsync(p => p.HotSpotName, p => p.Hour, p => p.Sum(x => x.count));
+
+            return InitDatatTable(dt, dto.AddColumnName);
+        }
+
+        /// <summary>
+        /// 受理类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderAcceptanceTime(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     AcceptTypeCode = p.AcceptTypeCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.AcceptTypeCode)
+              .Where((s, p) => s.DicTypeCode == "AcceptType")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.AcceptTypeCode != null && p.AcceptTypeCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var list = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   p.DicDataValue,
+                   p.count
+               })
+                .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
+            return list;
+
+        }
+
+        /// <summary>
+        /// 受理类型分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderAcceptanceTimeExport(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
+			List<int> dts = new();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     AcceptTypeCode = p.AcceptTypeCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.AcceptTypeCode)
+              .Where((s, p) => s.DicTypeCode == "AcceptType")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.AcceptTypeCode != null && p.AcceptTypeCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var dt = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+               .OrderBy(x => x.ColumnName)
+              .Select((x, p) => new
+              {
+                  Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                  p.DicDataName,
+                  p.count
+              })
+               .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
+
+            return InitDatatTable(dt, dto.AddColumnName);
+        }
+
+        /// <summary>
+        /// 信件来源分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderSourceTime(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     SourceChannelCode = p.SourceChannelCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+              .Where((s, p) => s.DicTypeCode == "SourceChannel")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var list = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   p.DicDataValue,
+                   p.count
+               })
+                .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
+            return list;
+
+        }
+
+        /// <summary>
+        /// 信件来源分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderSourceTimeExport(TimeSharingPagedKeywordRequest dto)
+        {
+	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			List<int> dts = new();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .Select(p => new
+                 {
+                     SourceChannelCode = p.SourceChannelCode,
+                     Hour = p.CreationTime.Hour.ToString()
+                 })
+               .MergeTable();
+
+            var listOrg = Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+              .Where((s, p) => s.DicTypeCode == "SourceChannel")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => s.DicDataValue)
+              .Select((s, p) => new
+              {
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  DicDataName = s.DicDataName
+              })
+              .MergeTable();
+
+            var dt = await listHour.LeftJoin(listOrg, (x, p) => x.ColumnName.ToString() == p.Hour)
+               .OrderBy(x => x.ColumnName)
+              .Select((x, p) => new
+              {
+                  Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                  p.DicDataName,
+                  p.count
+              })
+               .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
+            return InitDatatTable(dt, dto.AddColumnName);
+        }
+
+		/// <summary>
+		/// 信件来源统计
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		public async Task<object> OrderSource(QueryOrderSourceRequest dto)
+		{
+			dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			var listOrder = Db.Queryable<Order>()
+				 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+				 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+				 .Select(p => new
+				 {
+					 SourceChannelCode = p.SourceChannelCode,
+					 Hour = p.CreationTime.ToString("yyyy-MM-dd")
+				 })
+			   .MergeTable();
+
+			var listOrg = await Db.Queryable<SystemDicData>()
+			  .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+			  .Where((s, p) => s.DicTypeCode == "SourceChannel")
+			  .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+			  .GroupBy((s, p) => p.Hour)
+			  .OrderBy((s, p) => p.Hour)
+			  .Select((s, p) => new
+			  {
+				  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+				  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+				  DicDataValue = s.DicDataValue,
+				  DicDataName = s.DicDataName
+			  })
+			  .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
+			return listOrg;
+
+		}
+
+		/// <summary>
+		/// 信件来源统计---导出
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		public async Task<DataTable> OrderSourceExport(QueryOrderSourceRequest dto)
+		{
+			dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+			var listOrder = Db.Queryable<Order>()
+				 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+				 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+				 .Select(p => new
+				 {
+					 SourceChannelCode = p.SourceChannelCode,
+					 Hour = p.CreationTime.ToString("yyyy-MM-dd")
+				 })
+			   .MergeTable();
+
+			var listOrg = await Db.Queryable<SystemDicData>()
+			  .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+			  .Where((s, p) => s.DicTypeCode == "SourceChannel")
+			  .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+			  .GroupBy((s, p) => p.Hour)
+			  .OrderBy((s, p) => p.Hour)
+			  .Select((s, p) => new
+			  {
+				  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+				  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+				  DicDataValue = s.DicDataValue,
+				  DicDataName = s.DicDataName
+			  })
+			  .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
+				listOrg.Columns["Hour"].ColumnName = "日期";
+				if (listOrg.Rows[0][listOrg.Rows.Count - 1] == "0")
+				    listOrg.Rows[listOrg.Rows.Count - 1].Delete();
+			return InitDatatTable(listOrg, dto.AddColumnName);
+		}
+
+		/// <summary>
+		/// 处理导出数据
+		/// </summary>
+		/// <param name="dt"></param>
+		/// <param name="AddColumnName"></param>
+		/// <returns></returns>
+		public DataTable InitDatatTable(DataTable dt, List<string> AddColumnName)
+        {
+            //修改列名
+            if (dt.Columns.Contains("Hour"))
+                dt.Columns["Hour"].ColumnName = "时间段";
+
+            //增加小计
+            DataColumn totalColumn = new DataColumn("小计", typeof(decimal));
+            dt.Columns.Add(totalColumn);
+            if (dt.Columns.Contains("Column1"))
+                dt.Columns.Remove("Column1");
+            //计算小计
+            for (int i = 0; i < dt.Rows.Count; i++)
+            {
+                int sumcount = 0;
+                for (int j = 1; j < dt.Columns.Count - 1; j++)
+                {
+                    sumcount += Convert.ToInt32(dt.Rows[i][j].ToString());
+                }
+                dt.Rows[i][dt.Columns.Count - 1] = sumcount;
+            }
+
+            //增加合计
+            DataRow totalRow = dt.NewRow();
+            if (dt.Columns[0].ColumnName == "日期") totalRow["日期"] = "合计";
+            else totalRow["时间段"] = "合计";
+            for (int i = 1; i < dt.Columns.Count; i++)
+            {
+                int sumcount = 0;
+                for (int j = 0; j < dt.Rows.Count; j++)
+                {
+                    sumcount += Convert.ToInt32(dt.Rows[j][i].ToString());
+                }
+                totalRow[i] = sumcount;
+            }
+            dt.Rows.Add(totalRow);
+
+            //创建新表
+            DataTable dt2 = new DataTable();
+
+            //添加表头
+            foreach (var item in AddColumnName)
+            {
+                if (dt.Columns.Contains(item))
+                    dt2.Columns.Add(item);
+            }
+
+            //处理数据
+            foreach (DataRow sourceRow in dt.Rows)
+            {
+                DataRow targetRow = dt2.NewRow();
+                foreach (var item in AddColumnName)
+                {
+                    targetRow[item] = sourceRow[item];
+                }
+                dt2.Rows.Add(targetRow);
+            }
+            return dt2;
+        }
+
+        
+
+
+
         public ISugarQueryable<SelectOrderId> OrderListUnionAll(ISugarQueryable<SelectOrderId> t1, ISugarQueryable<SelectOrderId> t2)
         {
             return Db.UnionAll(t1, t2).Select(it => new SelectOrderId { Id = it.Id }).MergeTable();

+ 11 - 2
src/Hotline.Repository.SqlSugar/Ts/BaseRepositoryTextSearch.cs

@@ -84,9 +84,18 @@ FROM order_ts, to_tsquery('simple', 'bb') query WHERE "Vector" @@ query ORDER BY
          */
     }
 
-    #region private method
+    public async Task<List<TEntity>> SearchAsync(string id, CancellationToken cancellationToken)
+    {
+	    var tableName = typeof(TEntity).Name.ToSnakeCase();
+	    var sql =
+		    $"SELECT * FROM {tableName} WHERE \"Id\" ='{id}' ";
+	    return await _db.Ado.SqlQueryAsync<TEntity>(sql, null, cancellationToken);
+
+    }
+
+	#region private method
 
-    private static string CreateVectorSql(ICollection<NpgsqlWeight> weights)
+	private static string CreateVectorSql(ICollection<NpgsqlWeight> weights)
     {
         var setweghtStrings = weights.Select(d => $"setweight(to_tsvector('simple', '{d.Text}'), '{d.Weight}')");
         var vectorString = string.Join(" || ", setweghtStrings);

+ 8 - 0
src/Hotline.Repository.SqlSugar/Ts/IRepositoryTextSearch.cs

@@ -28,4 +28,12 @@ public interface IRepositoryTextSearch<TEntity>
     /// <param name="cancellationToken"></param>
     /// <returns></returns>
     Task<List<TEntity>> SearchAsync(IReadOnlyList<string> texts, CancellationToken cancellationToken);
+
+    /// <summary>
+    /// 根据id获取
+    /// </summary>
+    /// <param name="id"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    Task<List<TEntity>> SearchAsync(string id, CancellationToken cancellationToken);
 }

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

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

+ 6 - 0
src/Hotline.Share/Dtos/Ai/AiDto.cs

@@ -379,6 +379,12 @@ namespace Hotline.Share.Dtos.Ai
         /// 工单
         /// </summary>
         public OrderVisitDto OrderVisit { get; set; }
+
+        /// <summary>
+        /// 智能回访录音地址
+        /// </summary>
+        public string? RecordUrl { get; set; }
+
         /// <summary>
         /// 外呼电话
         /// </summary>

+ 5 - 0
src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs

@@ -4,6 +4,11 @@ namespace Hotline.Share.Dtos.FlowEngine;
 
 public class NextStepsDto
 {
+    /// <summary>
+    /// 当前办理节点
+    /// </summary>
+    public string StepId { get; set; }
+
     // public IReadOnlyList<NextStepOption> Steps { get; set; }
     public DateTime? ExpiredTime { get; set; }
 

+ 5 - 0
src/Hotline.Share/Dtos/FlowEngine/NextWorkflowDto.cs

@@ -9,6 +9,11 @@ public class NextWorkflowDto : BasicWorkflowDto
 {
     public string WorkflowId { get; set; }
 
+    /// <summary>
+    /// 当前办理节点id
+    /// </summary>
+    public string StepId { get; set; }
+
     ///// <summary>
     ///// 下一节点到期时间(节点期满时间)
     ///// 需求调整

+ 101 - 160
src/Hotline.Share/Dtos/Order/OrderBiDto.cs

@@ -271,6 +271,106 @@ namespace Hotline.Share.Dtos.Order
     }
 
 
+	public class OrgVisitDetailListResp
+	{
+		/// <summary>
+		/// 工单ID
+		/// </summary>
+		public string Id { get; set; }
+
+		/// <summary>
+		/// 回访ID
+		/// </summary>
+		public string VisitId { get; set; }
+		/// <summary>
+		/// 工单编号
+		/// </summary>
+		public string No { get; set; }
+
+		/// <summary>
+		/// 重办次数
+		/// </summary>
+		public string ReTransactNum { get; set; }
+
+		/// <summary>
+		/// 甄别状态
+		/// </summary>
+		public EScreenStatus? OrderScreenStatus { get; set; }
+		public string? OrderScreenStatusText => OrderScreenStatus?.GetDescription();
+
+        /// <summary>
+        /// 回访内容
+        /// </summary>
+        public string VisitContent { get; set; }
+
+		/// <summary>
+		/// 热点全称
+		/// </summary>
+		public string HotspotSpliceName { get; set; }
+
+		/// <summary>
+		/// 一级部门
+		/// </summary>
+		public string OrgLevelOneName { get; set; }
+
+		/// <summary>
+		/// 办结部门
+		/// </summary>
+		public string ActualHandleOrgName { get; set; }
+
+		/// <summary>
+		/// 受理时间
+		/// </summary>
+		public DateTime CreationTime { get; set; }
+
+		/// <summary>
+		/// 工单标题
+		/// </summary>
+		public string Title { get; set; }
+
+		/// <summary>
+		/// 回访人
+		/// </summary>
+		public string VisitUser { get; set; }
+
+		/// <summary>
+		/// 回访部门
+		/// </summary>
+		public string VisitOrgName { get; set; }
+
+		/// <summary>
+		/// 回访方式
+		/// </summary>
+		public EVisitType? VisitType { get; set; }
+
+		public string? VisitTypeText => VisitType?.GetDescription();
+
+		/// <summary>
+		/// 回访时间
+		/// </summary>
+		public DateTime VisitTime { get; set; }
+
+		/// <summary>
+		/// 满意度
+		/// </summary>
+		public string OrgProcessingResults { get; set; }
+
+		/// <summary>
+		/// 受理内容
+		/// </summary>
+		public string Content { get; set; }
+
+		/// <summary>
+		/// 承办意见
+		/// </summary>
+		public string FileOpinion { get; set;}
+
+		/// <summary>
+		/// 办结时间
+		/// </summary>
+		public DateTime? FiledTime { get; set; }
+    }
+
 
 
     public class VisitAndOrgSatisfactionStatisticsDto
@@ -868,164 +968,5 @@ namespace Hotline.Share.Dtos.Order
 	}
 
 
-    public class QueryTempDto
-    {
-        /// <summary>
-        /// 信件状态
-        /// </summary>
-        public EOrderStatus Status { get; set; }
-
-        /// <summary>
-        /// 是否超期
-        /// </summary>
-        public string IsOverTime { get; set; }
-
-        /// <summary>
-        /// 来源
-        /// </summary>
-        public string Source { get; set; }
-
-        /// <summary>
-        /// 转接来源
-        /// </summary>
-        public string TransferPhone { get; set; }
-
-        /// <summary>
-        /// 当前节点
-        /// </summary>
-        public string ActualHandleStepName { get; set; }
-
-        /// <summary>
-        /// 重办次数
-        /// </summary>
-        public int? ReTransactNum { get; set; }
-
-        /// <summary>
-        /// 甄别状态
-        /// </summary>
-        public string? OrderScreenStatus { get; set; }
-
-        /// <summary>
-        /// 受理编号
-        /// </summary>
-        public string? No { get; set; }
-
-        /// <summary>
-        /// 省编号
-        /// </summary>
-        public string? ProvinceNo { get; set; }
-
-        /// <summary>
-        /// 受理时间
-        /// </summary>
-        public DateTime? StartTime { get; set; }
-
-        /// <summary>
-        /// 标题
-        /// </summary>
-        public string Title { get; set; }
-
-        /// <summary>
-        /// 超期时间(期满时间)
-        /// </summary>
-        public DateTime? ExpiredTime { get; set; }
-
-        /// <summary>
-        /// 一级部门
-        /// </summary>
-        public string? OrgLevelOneName { get; set; }
-
-        /// <summary>
-        /// 二级部门
-        /// </summary>
-        public string? OrgLevelTwoName { get; set; }
-
-        /// <summary>
-        /// 受理人部门名称
-        /// </summary>
-        public string? AcceptorOrgName { get; set; }
-
-        /// <summary>
-        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
-        /// </summary>
-        public DateTime? FiledTime { get; set; }
-
-        /// <summary>
-        /// 受理类型
-        /// </summary>
-        public string? AcceptType { get; set; }
-
-        /// <summary>
-        /// 热点全称
-        /// </summary>
-        public string? HotspotSpliceName { get; set; }
-
-        /// <summary>
-        /// 区域全称
-        /// </summary>
-        public string? FullAddress { get; set; }
-
-        /// <summary>
-        /// 受理人名称
-        /// </summary>
-        public string? AcceptorName { get; set; }
-
-        /// <summary>
-        /// 来电/信人姓名
-        /// </summary>
-        public string? FromName { get; set; }
-
-        /// <summary>
-        /// 联系电话
-        /// </summary>
-        public string? Contact { get; set; }
-
-        /// <summary>
-        /// 来电号码
-        /// </summary>
-        public string? FromPhone { get; set; }
-
-        /// <summary>
-        /// 来电/信人身份
-        /// </summary>
-        public EIdentityType? IdentityType { get; set; }
-
-        /// <summary>
-        /// 来电/信人性别
-        /// </summary>
-        public EGender FromGender { get; set; }
-
-        /// <summary>
-        /// 第一次评价结果
-        /// </summary>
-        public string? FirstVisitResult { get; set; }
-
-        /// <summary>
-        /// 推送分类
-        /// </summary>
-        public string? PushType { get; set; }
-
-
-        /// <summary>
-        /// 诉求内容
-        /// </summary>
-        public string Content { get; set; }
-
-        /// <summary>
-        /// 实际办理意见
-        /// </summary>
-        public string ActualOpinion { get; set; }
-
-        /// <summary>
-        /// 归档意见
-        /// </summary>
-        public string? FileOpinion { get; set; }
-
-        /// <summary>
-        /// 创建时间
-        /// </summary>
-        public DateTime CreationTime { get; set; }
-
-
-    }
+    
 }

+ 49 - 3
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -360,9 +360,14 @@ namespace Hotline.Share.Dtos.Order
         public string? PreviousOpinion { get; set; }
 
         /// <summary>
-        /// 延期申请数量
+        /// 是否可代办
         /// </summary>
-        public int DelayingCount => OrderDelays?.Count ?? 0;
+        public bool CanInsteadHandle { get; set; }
+
+		/// <summary>
+		/// 延期申请数量
+		/// </summary>
+		public int DelayingCount => OrderDelays?.Count ?? 0;
 
         /// <summary>
         /// 是否紧急
@@ -399,7 +404,28 @@ namespace Hotline.Share.Dtos.Order
             }
         }
 
-        public EExpiredStatus? CalculateExpiredState()
+        /// <summary>
+        /// 超期天数
+        /// </summary>
+        public string DaysOverdue => DaysOverdueText();
+
+        private string DaysOverdueText()
+        {
+            DateTime? dateTime = DateTime.Now;
+            if (Status >= EOrderStatus.Filed && ExpiredTime.HasValue && FiledTime.HasValue)
+            {
+                var days = (FiledTime.Value - ExpiredTime.Value).TotalDays;
+                return $"超期{days:N1}天";
+            }
+            if (ExpiredTime.HasValue)
+            {
+                var days = (dateTime.Value - ExpiredTime.Value).TotalDays;
+                return $"超期{days:N1}天";
+            }
+            return string.Empty;
+        }
+
+		public EExpiredStatus? CalculateExpiredState()
         {
             DateTime? dateTime = DateTime.Now;
             if (Status >= EOrderStatus.Filed)
@@ -817,6 +843,26 @@ namespace Hotline.Share.Dtos.Order
         /// 是否紧急
         /// </summary>
         public bool IsUrgent { get; set; }
+
+        /// <summary>
+        /// 是否政民互动公开
+        /// </summary>
+        public bool IsProvinceZmhd { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 政民互动公开ID
+        /// </summary>
+        public string? OrderProvinceZmhdId { get; set; }
     }
 
     public record CanLinkCallRecordOrderDto : PagedKeywordRequest

+ 135 - 0
src/Hotline.Share/Dtos/Order/OrderProvinceZmhdDto.cs

@@ -0,0 +1,135 @@
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.Order
+{
+    /// <summary>
+    /// 政民互动查询
+    /// </summary>
+    public record OrderProvinceZmhdDto : PagedRequest
+    {
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string? No { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        public string? ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        public string? Title { get; set; }
+
+        /// <summary>
+        /// 答复部门名称
+        /// </summary>
+        public string? AnswerOu { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 审核开始时间
+        /// </summary>
+        public DateTime? StartTime { get; set; }
+        /// <summary>
+        /// 审核结束时间
+        /// </summary>
+        public DateTime? EndTime { get; set; }
+
+        /// <summary>
+        /// 是否政民互动公开
+        /// </summary>
+        public bool? IsProvinceZmhd { get; set; }
+    }
+
+    public class AddOrderProvinceZmhdDto
+    {
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 整理结果
+        /// </summary>
+        public string AnswerContent { get; set; }
+
+        /// <summary>
+        /// 公开意见(长度300)
+        /// </summary>
+        public string? PublicOpinion { get; set; }
+    }
+
+    public class PublicOrderProvinceZmhdDto
+    {
+        /// <summary>
+        /// Id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string No { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        public string ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 部门答复时间
+        /// </summary>
+        public DateTime? AnswerTime { get; set; }
+
+        /// <summary>
+        /// 答复部门名称
+        /// </summary>
+        public string AnswerOu { get; set; }
+
+        /// <summary>
+        /// 答复内容
+        /// </summary>
+        public string AnswerContent { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 二审人姓名
+        /// </summary>
+        public string? AuditSecondName { get; set; }
+
+        /// <summary>
+        /// 公开时间
+        /// </summary>
+        public DateTime? PublishDate { get; set; }
+
+        /// <summary>
+        /// 公开意见
+        /// </summary>
+        public string? PublicOpinion { get; set; }
+    }
+}

+ 10 - 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>
@@ -125,6 +130,11 @@ public record UpdateUserDto
     /// 默认分机号
     /// </summary>
     public string? DefaultTelNo { get; set; }
+    
+    /// <summary>
+    /// 默认分机组(技能组)
+    /// </summary>
+    public string? DefaultTelGroup { get; set; }
 
     public string Email { get; set; }
 

+ 14 - 0
src/Hotline.Share/Enums/Order/EOrgVisitStatisticsType.cs

@@ -0,0 +1,14 @@
+
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Order
+{
+    public enum EOrgVisitStatisticsType
+    {
+        [Description("中心统计")]
+        CallCenter = 10,
+
+        [Description("部门统计")]
+        Org = 20,
+    }
+}

+ 1 - 1
src/Hotline.Share/Hotline.Share.csproj

@@ -7,7 +7,7 @@
     <GenerateDocumentationFile>True</GenerateDocumentationFile>
     <NoWarn>$(NoWarn);1591;8618;</NoWarn>
     <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-    <Version>1.0.79</Version>
+    <Version>1.0.80</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 7 - 2
src/Hotline.Share/Mq/EventNames.Order.cs

@@ -95,6 +95,11 @@ namespace Hotline.Share.Mq
         /// </summary>
         public const string HotlineOrderTranspondCity = "hotline.order.transpond.city";
 
-		#endregion
-	}
+        /// <summary>
+        /// 政民互动公开
+        /// </summary>
+        public const string HotlineOrderProvinceZmhd = "hotline.order.province.zmhd";
+
+        #endregion
+    }
 }

+ 5 - 0
src/Hotline.Share/Requests/DepartmentalProcessingStatisticsDto.cs

@@ -231,6 +231,11 @@ namespace Hotline.Share.Requests
         /// </summary>
         public string OrgCode { get; set; }
 
+        /// <summary>
+        /// 父级ID
+        /// </summary>
+        public string ParentOrgCode { get; set; }
+
         /// <summary>
         /// 部门名称
         /// </summary>

+ 254 - 131
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -4,56 +4,89 @@ namespace Hotline.Share.Requests;
 
 public record PagedKeywordRequest : PagedRequest
 {
-	/// <summary>
-	/// 开始时间
-	/// </summary>
-	public DateTime? StartTime { get; set; }
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    public DateTime? StartTime { get; set; }
 
-	/// <summary>
-	/// 结束时间
-	/// </summary>
-	public DateTime? EndTime { get; set; }
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    public DateTime? EndTime { get; set; }
 
-	public string? Keyword { get; set; }
+    public string? Keyword { get; set; }
 }
 public record PagedKeywordSonRequest : PagedRequest
 {
-	/// <summary>
-	/// 开始时间
-	/// </summary>
-	public DateTime? StartTime { get; set; }
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    public DateTime? StartTime { get; set; }
 
-	/// <summary>
-	/// 结束时间
-	/// </summary>
-	public DateTime? EndTime { get; set; }
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    public DateTime? EndTime { get; set; }
 
-	public string? OrgName { get; set; }
-	public string? OrgCode { get; set; }
-	/// <summary>
-	/// 1:办件结果 2:办件态度
-	/// </summary>
-	public int? TypeId { get; set; }
+    public string? OrgName { get; set; }
+    public string? OrgCode { get; set; }
+    /// <summary>
+    /// 1:办件结果 2:办件态度
+    /// </summary>
+    public int? TypeId { get; set; }
 
-	public string? LineNum { get; set; }
+    public string? LineNum { get; set; }
 }
 
-public record ReportPagedRequest : PagedKeywordRequest 
+public record ReportPagedRequest : PagedKeywordRequest
 {
 
-	/// <summary>
-	/// 排序字段 
-	/// </summary>
-	public string SortField { get; set; }
+    /// <summary>
+    /// 排序字段 
+    /// </summary>
+    public string SortField { get; set; }
 
-	/// <summary>
-	/// 排序规则  0 升序  1 降序
-	/// </summary>
-	public int? SortRule { get; set; }
+    /// <summary>
+    /// 排序规则  0 升序  1 降序
+    /// </summary>
+    public int? SortRule { get; set; }
 
 }
 
-public record OrgDataListDetailRequest:PagedRequest
+public record OrgDataListDetailRequest : PagedRequest
+{
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    public DateTime StartTime { get; set; }
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    public DateTime EndTime { get; set; }
+    /// <summary>
+    /// 部门Code
+    /// </summary>
+    public string OrgCode { get; set; }
+
+    /// <summary>
+    /// 工单编号
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 查询状态 1:业务已办超期  2:会签已办超期  3:业务待办超期  4:会签待办超期  5:小计
+    /// </summary>
+    public int QueryType { get; set; }
+
+    /// <summary>
+    /// 超期类型 1:系统中超期  2:申请延期超期
+    /// </summary>
+    public int ExpiredType { get; set; }
+}
+/// <summary>
+/// 部门超期全部数据
+/// </summary>
+public record OrgDataListAllDetailRequest : PagedRequest
 {
 	/// <summary>
 	/// 开始时间
@@ -66,29 +99,30 @@ public record OrgDataListDetailRequest:PagedRequest
 	/// <summary>
 	/// 部门Code
 	/// </summary>
-	public string OrgCode {  get; set; }
+	public string OrgCode { get; set; }
 
 	/// <summary>
 	/// 工单编号
 	/// </summary>
 	public string? No { get; set; }
 
-	/// <summary>
-	/// 查询状态 1:业务已办超期  2:会签已办超期  3:业务待办超期  4:会签待办超期  5:小计
-	/// </summary>
-	public int QueryType { get; set; }
-
 	/// <summary>
 	/// 超期类型 1:系统中超期  2:申请延期超期
 	/// </summary>
 	public int ExpiredType { get; set; }
-}
 
-public record PublishedPagedRequest : PagedKeywordRequest {
 	/// <summary>
-	/// 是否解决
+	/// 工单状态(√)
 	/// </summary>
-	public bool? Resolve { get; set; }
+	public List<EOrderStatus> Statuses { get; set; } = new();
+}
+
+public record PublishedPagedRequest : PagedKeywordRequest
+{
+    /// <summary>
+    /// 是否解决
+    /// </summary>
+    public bool? Resolve { get; set; }
 
     /// <summary>
     /// 工单编号
@@ -99,174 +133,263 @@ public record PublishedPagedRequest : PagedKeywordRequest {
 public record HotspotSubtotalReportPagedRequest : ReportPagedRequest
 {
 
-	public string Id { get; set; }
+    public string Id { get; set; }
 }
 
 public record HotPortJoinOrgStatisticsRequest
 {
-	public DateTime StartTime { get; set; }
+    public DateTime StartTime { get; set; }
 
-	public DateTime EndTime { get; set; }
+    public DateTime EndTime { get; set; }
 }
 
 
-public record HotspotReportPagedRequest : ReportPagedRequest { 
+public record HotspotReportPagedRequest : ReportPagedRequest
+{
 
-	public string Id { get; set; }
+    public string Id { get; set; }
 
-	/// <summary>
-	/// 查询类型  年 3 月 2 日 1 自定义 0
-	/// </summary>
-	public int Type { get; set; }
+    /// <summary>
+    /// 查询类型  年 3 月 2 日 1 自定义 0
+    /// </summary>
+    public int Type { get; set; }
 
-	public DateTime? ChainStartTime { get; set; }
+    public DateTime? ChainStartTime { get; set; }
 
-	public DateTime? ChainEndTime { get; set; }
+    public DateTime? ChainEndTime { get; set; }
 }
 
 
-public record QuerySeatRestRequest:ReportPagedRequest
+public record QuerySeatRestRequest : ReportPagedRequest
 {
-	public string? UserName { get; set; }
+    public string? UserName { get; set; }
 
-	public string? StaffNo { get; set; }
+    public string? StaffNo { get; set; }
 
 }
 
-public record QuerySeatSwitchRequest:ReportPagedRequest
+public record QuerySeatSwitchRequest : ReportPagedRequest
 {
-	public string? UserName { get; set; }
+    public string? UserName { get; set; }
 
-	public string? CDPN { get; set; }
+    public string? CDPN { get; set; }
 
 }
 
-public record QueryVisitNoSatiisfiedRequest:ReportPagedRequest
+public record QueryVisitNoSatiisfiedRequest : ReportPagedRequest
 {
-	public string? OrgName { get; set; }
+    public string? OrgName { get; set; }
 
 }
 
-public record BiQueryVisitNoSatisfiedDetailDto: ReportPagedRequest
+public record BiQueryVisitNoSatisfiedDetailDto : ReportPagedRequest
 {
-	/// <summary>
-	/// 部门Code
-	/// </summary>
-	public string OrgCode { get; set; }
-	/// <summary>
-	/// 不满意原因Key
-	/// </summary>
-	public string DissatisfiedKey { get; set; }
+    /// <summary>
+    /// 部门Code
+    /// </summary>
+    public string OrgCode { get; set; }
+    /// <summary>
+    /// 不满意原因Key
+    /// </summary>
+    public string DissatisfiedKey { get; set; }
 }
 
-public record QueryOrderDelayDataListRequest:ReportPagedRequest 
-{ 
-	public string? OrgName { get; set; }
+public record QueryOrderDelayDataListRequest : ReportPagedRequest
+{
+    public string? OrgName { get; set; }
 }
 
 public record QueryOrderDelayDataDetailRequest : ReportPagedRequest
 {
-	public string? OrgCode { get; set; }
+    public string? OrgCode { get; set; }
 
-	/// <summary>
-	/// 查询类型  1已同意次数 2 未同意次数 3  审批中次数 4 小计
-	/// </summary>
-	public int? Type { get; set; }
+    /// <summary>
+    /// 查询类型  1已同意次数 2 未同意次数 3  审批中次数 4 小计
+    /// </summary>
+    public int? Type { get; set; }
 
 }
 
 public record QueryOrderReTransactRequest : ReportPagedRequest
 {
-	public string? OrgName { get; set; }
+    public string? OrgName { get; set; }
 
 }
 
 public record QuerySecondaryHandlingRequest : ReportPagedRequest
 {
-	public string? OrgName { get; set; }
+    public string? OrgName { get; set; }
 
-	public string? OrgId { get; set; }
+    public string? OrgId { get; set; }
 
-	/// <summary>
-	///  1  办件结果
-	/// </summary>
-	public int  TypeId { get; set; }
+    /// <summary>
+    ///  1  办件结果
+    /// </summary>
+    public int TypeId { get; set; }
 
-	public string? CDPN { get; set; }
+    public string? CDPN { get; set; }
 
-	public string Header { get; set; }
+    public string Header { get; set; }
 
 }
 
 public record QueryOrderReTransactDetailRequest : ReportPagedRequest
 {
-	public string? OrgName { get; set; }
+    public string? OrgName { get; set; }
 
-	public string? ErrorName { get; set; }
+    public string? ErrorName { get; set; }
 
-	public string? No { get; set; }
+    public string? No { get; set; }
 
 }
 
 public record QuerySendOrderRequest
 {
-	public string? UserName { get; set; }
+    public string? UserName { get; set; }
 
 
-	/// <summary>
-	/// 开始时间
-	/// </summary>
-	public DateTime? StartTime { get; set; }
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    public DateTime? StartTime { get; set; }
 
-	/// <summary>
-	/// 结束时间
-	/// </summary>
-	public DateTime? EndTime { get; set; }
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    public DateTime? EndTime { get; set; }
 
 }
 
-public record QuerySendOrderDetailRequest : ReportPagedRequest 
+public record QuerySendOrderDetailRequest : ReportPagedRequest
 {
-	public string UserId { get; set; }
+    public string UserId { get; set; }
 
-	public string TitleCode { get; set; }
+    public string TitleCode { get; set; }
 }
 
-public record QueryUnsignedOrdersRequest : ReportPagedRequest 
-{ 
-	/// <summary>
-	///  0 全部  1 本级  2 下级
-	/// </summary>
-	public int Level { get; set; }
+public record QueryUnsignedOrdersRequest : ReportPagedRequest
+{
+    /// <summary>
+    ///  0 全部  1 本级  2 下级
+    /// </summary>
+    public int Level { get; set; }
 
-	/// <summary>
-	///  0 未签收  1 签收
-	/// </summary>
-	public int Signed { get; set; }
+    /// <summary>
+    ///  0 未签收  1 签收
+    /// </summary>
+    public int Signed { get; set; }
 }
 
-public record QueryOrderSourceRequest : ReportPagedRequest 
+public record QueryOrderSourceRequest : ReportPagedRequest
 {
-	/// <summary>
-	/// 来电/信人身份
-	/// </summary>
-	public EIdentityType? IdentityType { get; set; }
+    /// <summary>
+    /// 来电/信人身份
+    /// </summary>
+    public EIdentityType? IdentityType { get; set; }
+
+    /// <summary>
+    /// 导出列名
+    /// </summary>
+    public List<string> AddColumnName { get; set; }
 }
 
 public record QueryOrderSourceDetailRequest : QueryOrderSourceRequest
 {
-	/// <summary>
-	/// 来电/信人身份
-	/// </summary>
-	public EIdentityType? IdentityType { get; set; }
+    /// <summary>
+    /// 来电/信人身份
+    /// </summary>
+    public EIdentityType? IdentityType { get; set; }
 
-	/// <summary>
-	/// 点击时间
-	/// </summary>
-	public DateTime? Time { get; set; }
+    /// <summary>
+    /// 点击时间
+    /// </summary>
+    public DateTime? Time { get; set; }
+
+    /// <summary>
+    /// 来源渠道(电话、网站、APP等)
+    /// </summary>
+    public string? SourceChannel { get; set; }
+}
+
+/// <summary>
+/// 分时统计
+/// </summary>
+public record TimeSharingPagedKeywordRequest : PagedKeywordRequest
+{
+    /// <summary>
+    /// 来电/信人身份
+    /// </summary>
+    public EIdentityType? IdentityType { get; set; }
+
+    /// <summary>
+    /// 导出列名
+    /// </summary>
+    public List<string> AddColumnName { get; set; }
+}
+
+
+public record OrgVisitDetailListReq: PagedKeywordRequest
+{
+    /// <summary>
+    /// 部门分类
+    /// </summary>
+    public EOrgVisitStatisticsType? OrgVisitStatisticsType { get; set; }
+
+    /// <summary>
+    /// 办件结果
+    /// </summary>
+    public string? OrgProcessingResults { get; set; }
+
+    /// <summary>
+    /// 回访人
+    /// </summary>
+    public string? VisitUser { get; set; }
+
+    /// <summary>
+    /// 工单编号
+    /// </summary>
+    public string? No { get; set; }
+
+    /// <summary>
+    /// 工单标题
+    /// </summary>
+    public string? Title { get; set; }
+
+    /// <summary>
+    /// 回访部门
+    /// </summary>
+    public List<string> OrgCodes { get; set; } = new();
+
+    /// <summary>
+    /// 热点分类
+    /// </summary>
+    public List<string> HotspotIds { get; set; } = new();
+
+    /// <summary>
+    /// 来源渠道(√)
+    /// </summary>
+    public List<string> Channels { get; set; } = new();
+
+    /// <summary>
+    /// 受理时间(工单创建时间)(√)
+    /// </summary>
+    public DateTime? CreationTimeStart { get; set; }
+    public DateTime? CreationTimeEnd { get; set; }
+
+    /// <summary>
+    /// 办结时间(√)
+    /// </summary>
+    public DateTime? ActualHandleTimeStart { get; set; }
+    public DateTime? ActualHandleTimeEnd { get; set; }
+}
+
+
+public record HotspotAndAreaStatisticsReq
+{
+    public int HotspotLevel { get; set; }
+
+    public DateTime StartTime { get; set; }
+
+    public DateTime EndTime { get; set; }
 
-	/// <summary>
-	/// 来源渠道(电话、网站、APP等)
-	/// </summary>
-	public string? SourceChannel { get; set; }
 }

+ 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);
     }
 }

+ 7 - 1
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -234,7 +234,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 批量修改工单办理对象
         /// </summary>
         Task ChangeHandlerBatchAsync(
-            IReadOnlyList<(string userId, string username, string orgId, string orgName, ICollection<WorkflowStep> steps)> handlers,
+            IReadOnlyList<(string userId, string username, string orgId, string orgName, string? roleId, string? roleName, ICollection<WorkflowStep> steps)> handlers,
             CancellationToken cancellationToken);
 
         /// <summary>
@@ -262,5 +262,11 @@ namespace Hotline.FlowEngine.Workflows
         /// 流程被签收至某个用户(更新流转对象,办理对象,节点办理对象以及stepHandlers)
         /// </summary>
         Task<Workflow> SignToSomebodyAsync(string workflowId, string userId, string username, string orgId, string orgName, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 非节点办理人员查询待办节点
+        /// </summary>
+        /// <returns></returns>
+        Task<ICollection<WorkflowStep>> GetUnhandleStepsByOthersAsync(string workflowId, CancellationToken cancellationToken);
     }
 }

+ 4 - 2
src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs

@@ -490,8 +490,10 @@ public abstract class StepBasicEntity : CreationEntity
                     UserId = HandlerId,
                     Username = HandlerName,
                     OrgId = HandlerOrgId,
-                    OrgName = HandlerOrgName
-                };
+                    OrgName = HandlerOrgName,
+                    RoleId = RoleId,
+                    RoleName = RoleName
+				};
             case EFlowAssignType.Role:
                 return new FlowStepHandler
                 {

+ 6 - 5
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -35,12 +35,13 @@ public partial class Workflow : CreationEntity
 
     public string? ModuleCode { get; set; }
 
-    #endregion
+	#endregion
 
-    /// <summary>
-    /// 流程标题
-    /// </summary>
-    public string Title { get; set; }
+	/// <summary>
+	/// 流程标题
+	/// </summary>
+	[SugarColumn(ColumnDataType = "varchar(2000)")]
+	public string Title { get; set; }
 
     ///// <summary>
     ///// 到期时间(期满时间)

+ 25 - 10
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -329,8 +329,8 @@ namespace Hotline.FlowEngine.Workflows
             StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo,
             DateTime? expiredTime, ISessionContext current, CancellationToken cancellationToken)
         {
-            ValidatePermission(workflow, current.RequiredOrgId, current.RequiredUserId, current.Roles);
-            //CheckWhetherRunnable(workflow.Status);
+            //ValidatePermission(workflow, current.RequiredOrgId, current.RequiredUserId, current.Roles);
+            CheckWhetherRunnable(workflow.Status);
 
             #region 办理当前节点
 
@@ -788,7 +788,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 批量修改工单办理对象
         /// </summary>
         public async Task ChangeHandlerBatchAsync(
-            IReadOnlyList<(string userId, string username, string orgId, string orgName, ICollection<WorkflowStep> steps
+            IReadOnlyList<(string userId, string username, string orgId, string orgName,string? roleId,string? roleName, ICollection<WorkflowStep> steps
                 )> handlers,
             CancellationToken cancellationToken)
         {
@@ -798,7 +798,7 @@ namespace Hotline.FlowEngine.Workflows
                 {
                     step.FlowAssignType = EFlowAssignType.User;
                     step.Assign(handler.userId, handler.username,
-                        handler.orgId, handler.orgName);
+                        handler.orgId, handler.orgName,handler.roleId,handler.roleName);
                     if (step.WorkflowTrace is null)
                         throw new UserFriendlyException("未查询节点对应快照信息");
                     step.WorkflowTrace.Assign(handler.userId, handler.username,
@@ -979,6 +979,17 @@ namespace Hotline.FlowEngine.Workflows
             return workflow;
         }
 
+        /// <summary>
+        /// 非节点办理人员查询待办节点
+        /// </summary>
+        /// <returns></returns>
+        public async Task<ICollection<WorkflowStep>> GetUnhandleStepsByOthersAsync(string workflowId, CancellationToken cancellationToken)
+        {
+            return await _workflowStepRepository.Queryable()
+                .Where(d => d.WorkflowId == workflowId && d.Status != EWorkflowStepStatus.Handled)
+                .ToListAsync(cancellationToken);
+        }
+
         /// <summary>
         /// 查找当前会签内所有节点(含start,end)
         /// </summary>
@@ -1477,7 +1488,7 @@ namespace Hotline.FlowEngine.Workflows
             if (nextStepDefine.BusinessType is EBusinessType.Center or EBusinessType.Send)
             {
                 workflow.UpdateActualStepWhenAssign(nextSteps.First(), actualHandleOrgCode: OrgSeedData.CenterId,
-                    actualHandleOrgName: "热线中心");
+                    actualHandleOrgName: "市民热线服务中心");
             }
             else
             {
@@ -1494,7 +1505,7 @@ namespace Hotline.FlowEngine.Workflows
             //    if (nextStepDefine.BusinessType is EBusinessType.Center or EBusinessType.Send)
             //    {
             //        workflow.UpdateActualStepWhenAssign(firstSteps.First(), actualHandleOrgCode: OrgSeedData.CenterId,
-            //            actualHandleOrgName: "热线中心");
+            //            actualHandleOrgName: "市民热线服务中心");
             //    }
             //    else
             //    {
@@ -1871,11 +1882,15 @@ namespace Hotline.FlowEngine.Workflows
             newStep.CountersignId = step.CountersignId;
             newStep.IsStartedCountersignEnd = step.IsStartedCountersignEnd;
 
-            //退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制
-            if (traceType is EWorkflowTraceType.Previous)
+			//退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制
+			if (traceType is EWorkflowTraceType.Previous)
             {
-                newStep.FlowAssignType = EFlowAssignType.User;
-                newStep.Assign(step.HandlerId, step.HandlerName, step.HandlerOrgId, step.HandlerOrgName);
+	            //newStep.FlowAssignType = EFlowAssignType.User;
+                // 是否中心  临时紧急修改 后续在流程模版定义是否原办理人退回类型 来实现流程 禅道200
+                newStep.FlowAssignType = !step.HandlerOrgIsCenter!.Value ? EFlowAssignType.Org : EFlowAssignType.Role;
+                if (newStep is { FlowAssignType: EFlowAssignType.Role, BusinessType: EBusinessType.Send })
+                    newStep.FlowAssignType = EFlowAssignType.User;
+				newStep.Assign(step.HandlerId, step.HandlerName, step.HandlerOrgId, step.HandlerOrgName, step.RoleId, step.RoleName);
             }
 
             await _workflowStepRepository.AddAsync(newStep, cancellationToken);

+ 81 - 1
src/Hotline/Orders/IOrderRepository.cs

@@ -1,5 +1,7 @@
-using Hotline.Share.Requests;
+using Hotline.Settings;
+using Hotline.Share.Requests;
 using SqlSugar;
+using System.Data;
 using XF.Domain.Repository;
 
 namespace Hotline.Orders
@@ -24,7 +26,85 @@ namespace Hotline.Orders
 
         ISugarQueryable<SelectOrderId> OrderListUnionAll(ISugarQueryable<SelectOrderId> t1, ISugarQueryable<SelectOrderId> t2);
 
+        /// <summary>
+        /// 区域分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderAreaTime(TimeSharingPagedKeywordRequest dto);
 
+        /// <summary>
+        /// 区域分时统计--导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<DataTable> OrderAreaTimeExport(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 热点类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderHotspotTime(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 热点类型分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<DataTable> OrderHotspotTimeExport(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 受理类型分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderAcceptanceTime(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 受理类型分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<DataTable> OrderAcceptanceTimeExport(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 信件来源分时统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderSourceTime(TimeSharingPagedKeywordRequest dto);
+
+        /// <summary>
+        /// 信件来源分时统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<DataTable> OrderSourceTimeExport(TimeSharingPagedKeywordRequest dto);
+
+
+        /// <summary>
+        /// 信件来源统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<object> OrderSource(QueryOrderSourceRequest dto);
+
+        /// <summary>
+        /// 信件来源统计 -- 导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+		Task<DataTable> OrderSourceExport(QueryOrderSourceRequest dto);
+
+        ISugarQueryable<T> UnionAll<T>(params ISugarQueryable<T>[] queryables) where T : class;
+
+        /// <summary>
+        /// 部门办件统计
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <returns></returns>
+        List<DepartmentalProcessingStatisticsDataDto> DepartmentalProcessingStatisticsNew(string sql);
 
     }
 

+ 26 - 0
src/Hotline/Orders/Order.cs

@@ -401,6 +401,8 @@ namespace Hotline.Orders
 
         #region 实际办理信息(节点,部门,意见)
 
+        public string? ActualHandleStepId { get; set; }
+
         /// <summary>
         /// 实际办理节点code(会签状态此字段保存最外层会签发起节点code)
         /// </summary>
@@ -801,6 +803,30 @@ namespace Hotline.Orders
         /// 待发布人Id
         /// </summary>
         public string? WaitForPublisherId { get; set; }
+
+        /// <summary>
+        /// 是否政民互动公开
+        /// </summary>
+        [SugarColumn(DefaultValue = "f")]
+        public bool IsProvinceZmhd { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审人姓名")]
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审时间")]
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 政民互动公开ID
+        /// </summary>
+        [SugarColumn(ColumnDescription = "政民互动公开ID")]
+        public string? OrderProvinceZmhdId { get; set; }
     }
 
     public partial class Order

+ 5 - 4
src/Hotline/Orders/OrderDomainService.cs

@@ -247,14 +247,14 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
 	            .Where(s => s.Id == scheduling.Id).ExecuteCommandAsync(cancellationToken);
 			if (sendNum <= 0) return;
             var sendSteps = steps.Take(sendNum).ToList();
-            await _workflowDomainService.ChangeHandlerBatchAsync(new List<(string userId, string username, string orgId, string orgName, ICollection<WorkflowStep> steps)>
+            await _workflowDomainService.ChangeHandlerBatchAsync(new List<(string userId, string username, string orgId, string orgName, string? roleId, string? roleName, ICollection<WorkflowStep> steps)>
             {
-                new(user.Id, user.Name, user.OrgId, user.Organization.Name, sendSteps)
+                new(user.Id, user.Name, user.OrgId, user.Organization.Name,null,null, sendSteps)
             }, cancellationToken);
         }
 
     }
-
+        
     /// <summary>
     /// 触发平均派单
     /// </summary>
@@ -275,7 +275,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
                 cancellationToken);
             if (steps.Any())
             {
-                List<(string userId, string username, string orgId, string orgName, ICollection<WorkflowStep> steps)> handlers = new();
+                List<(string userId, string username, string orgId, string orgName,string? roleId,string? roleName, ICollection<WorkflowStep> steps)> handlers = new();
                 var avg = steps.Count / schedulings.Count;
                 var remaining = steps.Count % schedulings.Count;
                 for (var i = 0; i < schedulings.Count; i++)
@@ -287,6 +287,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
                         scheduling.SchedulingUser.UserName,
                         scheduling.SchedulingUser.OrgId,
                         scheduling.SchedulingUser.OrgIdName,
+                        null,null,
                         steps.Take(size).ToList()));
                     scheduling.SendOrderNum += size;
 					await _schedulingRepository.Updateable()

+ 83 - 0
src/Hotline/Orders/OrderProvinceZmhd.cs

@@ -0,0 +1,83 @@
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    /// <summary>
+    /// 政民互动公开
+    /// </summary>
+    public class OrderProvinceZmhd : CreationEntity
+    {
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        [SugarColumn( ColumnDescription = "工单编号")]
+        public string No { get; set; }
+
+        /// <summary>
+        /// 省工单编号
+        /// </summary>
+        [SugarColumn(ColumnDescription = "省工单编号")]
+        public string ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        [SugarColumn(ColumnDescription = "工单Id")]
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        [SugarColumn(ColumnDescription = "工单标题")]
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 部门答复时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "部门答复时间")]
+        public DateTime? AnswerTime { get; set; }
+
+        /// <summary>
+        /// 答复部门名称
+        /// </summary>
+        [SugarColumn(ColumnDescription = "答复部门名称")]
+        public string AnswerOu { get; set; }
+
+        /// <summary>
+        /// 答复内容
+        /// </summary>
+        [SugarColumn(ColumnDataType = "text", ColumnDescription = "答复内容")]
+        public string AnswerContent { get; set; }
+
+        /// <summary>
+        /// 初审人姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审人姓名")]
+        public string? AuditFirstName { get; set; }
+
+        /// <summary>
+        /// 初审时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "初审时间")]
+        public DateTime? AuditFirstTime { get; set; }
+
+        /// <summary>
+        /// 二审人姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "二审人姓名")]
+        public string? AuditSecondName { get; set; }
+
+        /// <summary>
+        /// 公开时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "公开时间")]
+        public DateTime? PublishDate { get; set; }
+
+        /// <summary>
+        /// 公开意见
+        /// </summary>
+        [SugarColumn(Length = 300, ColumnDescription = "公开意见")]
+        public string? PublicOpinion { get; set; }
+    }
+}

+ 39 - 0
src/Hotline/Permissions/EPermission.cs

@@ -223,6 +223,12 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName ="工单列表",Name ="交办单导出",Description ="交办单导出")]
         BusinessOrderJbdExport = 200116,
+
+        /// <summary>
+        /// 工单待办
+        /// </summary>
+        [Display(GroupName ="工单列表",Name ="工单待办",Description ="工单待办")]
+        OrderAgent = 200117,
         #endregion
 
         #region 延期管理
@@ -1969,6 +1975,19 @@ namespace Hotline.Permissions
         #endregion
         #endregion
 
+        #region 省平台对接
+        /// <summary>
+        /// 省平台对接
+        /// </summary>
+        [Display(GroupName ="省平台对接",Name ="省平台对接",Description ="省平台对接")]
+        ProvinceAbutment = 701600,
+        /// <summary>
+        /// 政民互动发布
+        /// </summary>
+        [Display(GroupName ="省平台对接",Name ="政民互动发布",Description ="政民互动发布")]
+        GovernmentpPeopleInteractPublish = 701601,
+
+        #endregion
         #endregion
 
         #region 话务管理(80,00,00)
@@ -2229,6 +2248,21 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName ="数据统计",Name ="信件来源分时统计",Description ="信件来源分时统计")]
         OrderSourceTimeStatistics = 110216,
+        /// <summary>
+        /// 受理类型时分统计
+        /// </summary>
+        [Display(GroupName ="数据统计",Name = "受理类型分时统计", Description = "受理类型分时统计")]
+        AcceptTypeTimeStatistics = 110217,
+        /// <summary>
+        /// 热点类型分时统计
+        /// </summary>
+        [Display(GroupName ="数据统计",Name ="热点类型分时统计",Description = "热点类型分时统计")]
+        HotspotTypeTimeStatistics = 110218,
+        /// <summary>
+        /// 区域分时统计
+        /// </summary>
+        [Display(GroupName ="数据统计",Name ="区域分时统计",Description ="区域分时统计")]
+        AreaTimeStatistics = 110219,
         #endregion
 
         #region 知识库统计(11,03,00)
@@ -2459,6 +2493,11 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName = "数据共享平台", Name = "及时率(新)", Description = "及时率(新)")]
         TimelinessRateNew = 131300,
+        /// <summary>
+        /// 推送失败查询
+        /// </summary>
+        [Display(GroupName ="数据共享平台",Name = "推送失败查询",Description ="推送失败查询")]
+        PublishErrorQuery = 131400,
         #endregion
 
         #region 公用(99,00,00)

+ 6 - 1
src/Hotline/Settings/SettingConstants.cs

@@ -354,5 +354,10 @@ namespace Hotline.Settings
         /// 是否开启重复工单
         /// </summary>
         public const string IsOpenRepeatedWorkOrders = "IsOpenRepeatedWorkOrders";
-    }
+
+        /// <summary>
+        /// 班长代办
+        /// </summary>
+        public const string ChargeDAffaires = "ChargeDAffaires";
+	}
 }

+ 1 - 1
src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs

@@ -310,7 +310,7 @@ namespace Hotline.Settings.TimeLimits
                     }
                     else
                     {
-                        if (endTime>WorkEndTime)
+                        if (endTime> WorkEndTime && endTime < WorkBeginTime.AddDays(1))
                         {
                             endTime = WorkBeginTime.AddDays(1);
                         }

+ 9 - 6
src/Hotline/Tools/ExcelHelper.cs

@@ -1,10 +1,5 @@
 using MiniExcelLibs;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Mapster;
+using System.Data;
 
 namespace Hotline.Tools
 {
@@ -17,5 +12,13 @@ namespace Hotline.Tools
             stream.Seek(0, SeekOrigin.Begin);
             return stream;
         }
+
+        public static MemoryStream CreateStream(DataTable dataTable)
+        {
+            var stream = new MemoryStream();
+            stream.SaveAs(dataTable);
+            stream.Seek(0, SeekOrigin.Begin);
+            return stream;
+        }
     }
 }

+ 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

+ 189 - 0
src/Hotline/dataview.md

@@ -0,0 +1,189 @@
+### 信件数据查询
+select aaa.*,bbb."SeatVisitResult" from 
+(select 
+CASE "ordertemp"."Status"
+	WHEN 500 THEN '已回访'
+	WHEN 400 THEN '已发布'
+	WHEN 300 THEN '已归档'
+	WHEN 200 THEN '会签中'
+	WHEN 100 THEN '办理中'
+	WHEN 9 THEN '退回省平台'
+	WHEN 2 THEN '特提待受理'
+	WHEN 1 THEN '退回待受理'
+	WHEN 0 THEN '待受理'
+	ELSE	'未知'
+END AS "Status",
+CASE 	WHEN "Status">=300 and "ExpiredTime">"FiledTime" THEN '正常'
+		  WHEN "Status">=300 AND "ExpiredTime"<"FiledTime" THEN '超期'
+			WHEN "Status"<300 AND "ExpiredTime"> now() AND now()> "NearlyExpiredTime" THEN '即将超期'
+			WHEN "Status"<300 AND "ExpiredTime">now() AND now()< "NearlyExpiredTime" THEN '正常'
+	ELSE '未知'
+END AS "IsOverExpiredTime",
+"SourceChannel" AS "Source" , 
+CASE 
+	WHEN "TransferPhone" is null or "TransferPhone"='undefined' THEN '12345'
+	ELSE
+		"TransferPhone"
+END AS "TransferPhone" ,
+"ActualHandleStepName" AS "ActualHandleStepName" ,
+"ReTransactNum" AS "ReTransactNum" , 
+(select CASE "screentemp"."Status"
+	WHEN 0 THEN '待办'
+	WHEN 1 THEN '审批中'
+	WHEN 2 THEN '审批完成'
+	WHEN 3 THEN '审批拒绝'
+	ELSE '-'
+END AS "OrderScreenStatus"
+ from order_screen screentemp WHERE "OrderId"="ordertemp"."Id" order by "CreationTime" DESC LIMIT 1) as "OrderScreenStatus", 
+"No" AS "No" , 
+"ProvinceNo" AS "ProvinceNo" , 
+to_char("CreationTime", 'YYYY-MM-DD HH24:MI:SS') AS "StartTime" , 
+"Title" AS "Title" , 
+to_char("ExpiredTime", 'YYYY-MM-DD HH24:MI:SS') AS "ExpiredTime" , 
+"OrgLevelOneName" AS "OrgLevelOneName" , 
+
+CASE 
+	WHEN length("ActualHandleOrgCode")>=9 THEN
+		(select "Name" from system_organize orgtemp WHERE orgtemp."Id"="substring"("ordertemp"."ActualHandleOrgCode", 1, 9))
+	ELSE
+		'-'
+END AS "OrgLevelTwoName" , 
+"ActualHandleOrgName" AS "ActualHandleOrgName" , 
+to_char("FiledTime", 'YYYY-MM-DD HH24:MI:SS') AS "FiledTime" , 
+"AcceptType" AS "AcceptType" , 
+"HotspotName" AS "HotspotName",
+"HotspotSpliceName" AS "HotspotSpliceName",
+CASE 
+	WHEN "Town" is not NULL and "Town" <>'' THEN "Town"
+  WHEN "County" is not null and "County" <>'' THEN "County"
+	ELSE "City"
+END AS "AreaName",
+"Address"  As "FullAreaName",
+"AcceptorName" AS "AcceptorName" ,
+ "FromName" AS "FromName" , 
+ "Contact" AS "Contact" , 
+ "FromPhone" AS "FromPhone" , 
+ "Street" AS "Address" ,
+ '' AS "Obj",
+ CASE "IdentityType"
+	WHEN 1 THEN '市民'
+	WHEN 2 THEN '企业'
+	ELSE
+		'市民'
+END AS "IdentityType",
+CASE "FromGender"
+	WHEN 0 THEN '女士'
+	WHEN 1 THEN '先生'
+	ELSE '未知'
+END AS "FromGender" , 
+'-' AS "SeatVisitResult",
+"FirstVisitResult" AS "FirstVisitResult" , 
+"PushType" AS "PushType" , 
+"Content" AS "Content" , 
+"ActualOpinion" AS "ActualOpinion" ,
+"FileOpinion" AS "FileOpinion" ,
+"Id" AS "SugarNav_Id" FROM "order" ordertemp  WHERE (( "CreationTime" >= '2024-03-29' ) AND ( "CreationTime" < '2024-07-3' ))  AND ( "IsDeleted" = FALSE )ORDER BY "CreationTime" ASC) aaa
+left join 
+(select DISTINCT CASE visitdetailtemp."SeatEvaluate"
+	WHEN 0 THEN '默认满意'
+	WHEN 2 THEN '不满意'
+	WHEN 4 THEN '满意'
+	WHEN 5 THEN '非常满意'
+	WHEN 6 THEN '未接通'
+	WHEN 7 THEN '未做评价'
+	ELSE
+		'-'
+END AS "SeatVisitResult",visittemp."OrderId" as "OrderId"
+ from order_visit visittemp
+left join order_visit_detail visitdetailtemp on visittemp."Id"= visitdetailtemp."VisitId"  
+where visittemp."CreationTime">='2024-03-29' and visitdetailtemp."VisitTarget"=10 AND visittemp."VisitState"=30 ) bbb on aaa."SugarNav_Id"=bbb."OrderId";
+
+
+
+### 超期件查询
+select 
+aaa."No",aaa."CreationTime",aaa."Title",aaa."SourceChannel",aaa."ActualHandleOrgName",aaa."ExpiredTime",aaa."FiledTime",
+CASE 
+	WHEN aaa."StatusInt">=300 THEN
+		to_number(date_trunc('day',aaa."FiledTime"::TIMESTAMP-aaa."ExpiredTime" ::TIMESTAMP)::text, '9999')
+	ELSE
+		to_number(date_trunc('day',now()::TIMESTAMP-aaa."ExpiredTime" ::TIMESTAMP)::text, '9999')
+END AS OverTimeDayNum,
+aaa."Status"
+from (
+select "No",to_char("CreationTime", 'YYYY-MM-DD HH24:MI:SS') as "CreationTime","Title","SourceChannel","ActualHandleOrgName",to_char("ExpiredTime", 'YYYY-MM-DD HH24:MI:SS') as "ExpiredTime",to_char("FiledTime", 'YYYY-MM-DD HH24:MI:SS') as "FiledTime",
+CASE "ordertemp"."Status"
+	WHEN 500 THEN '已回访'
+	WHEN 400 THEN '已发布'
+	WHEN 300 THEN '已归档'
+	WHEN 200 THEN '会签中'
+	WHEN 100 THEN '办理中'
+	WHEN 9 THEN '退回省平台'
+	WHEN 2 THEN '特提待受理'
+	WHEN 1 THEN '退回待受理'
+	WHEN 0 THEN '待受理'
+	ELSE	'未知'
+END AS "Status",
+CASE 	WHEN "Status">=300 and "ExpiredTime">"FiledTime" THEN '正常'
+		  WHEN "Status">=300 AND "ExpiredTime"<"FiledTime" THEN '超期'
+			WHEN "Status"<300 AND "ExpiredTime"> now() AND now()> "NearlyExpiredTime" THEN '即将超期'
+			WHEN "Status"<300 AND "ExpiredTime">now() AND now()< "NearlyExpiredTime" THEN '正常'
+	ELSE '未知'
+END AS "IsOverExpiredTime",
+ordertemp."Status" as "StatusInt"
+ from "order" ordertemp
+where "CreationTime">='2024-06-01' AND "CreationTime"<'2024-07-01') aaa where aaa."IsOverExpiredTime" ='超期' or aaa."IsOverExpiredTime"='未知'
+
+
+### 部门延期明细
+
+
+select 
+CASE "ordertemp"."Status"
+	WHEN 500 THEN '已回访'
+	WHEN 400 THEN '已发布'
+	WHEN 300 THEN '已归档'
+	WHEN 200 THEN '会签中'
+	WHEN 100 THEN '办理中'
+	WHEN 9 THEN '退回省平台'
+	WHEN 2 THEN '特提待受理'
+	WHEN 1 THEN '退回待受理'
+	WHEN 0 THEN '待受理'
+	ELSE	'未知'
+END AS "Status",
+ordertemp."SourceChannel",
+ordertemp."ActualHandleStepName",
+ordertemp."No",
+to_char(ordertemp."CreationTime", 'YYYY-MM-DD HH24:MI:SS') "CreationTime",
+ordertemp."Title",
+to_char(ordertemp."ExpiredTime", 'YYYY-MM-DD HH24:MI:SS') "ExpiredTime",
+delaytemp."ApplyOrgName",
+delaytemp."DelayNum",
+CASE "DelayUnit"
+	WHEN 2 THEN
+		'工作日'
+	ELSE
+		'自然日'
+END AS "DelayUnit",
+to_char(delaytemp."ApplyDelayTime", 'YYYY-MM-DD HH24:MI:SS') "ApplyDelayTime",
+CASE "DelayState"
+	WHEN 1 THEN
+		to_char(ordertemp."ExpiredTime", 'YYYY-MM-DD HH24:MI:SS')
+	ELSE
+		''
+END AS "AfterDelay",
+ordertemp."AcceptType",
+ordertemp."HotspotName",
+CASE "DelayState"
+	WHEN 0 THEN
+		'审批中'
+	WHEN 1 THEN
+	  '同意'
+	WHEN 2 THEN
+	  '拒绝'
+	ELSE
+		'未知'
+END AS DelayState 
+ from order_delay delaytemp
+left join "order" ordertemp on delaytemp."OrderId"= ordertemp."Id"
+where ordertemp."CreationTime">='2024-06-01' and ordertemp."CreationTime"<'2024-07-01' and delaytemp."DelayState"<>3

+ 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));
     }

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott