Ver código fonte

合并 release

qinchaoyue 7 meses atrás
pai
commit
0631f7c384
87 arquivos alterados com 2114 adições e 774 exclusões
  1. 8 4
      src/Hotline.Api/Controllers/AiController.cs
  2. 25 4
      src/Hotline.Api/Controllers/ArticleController.cs
  3. 47 20
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  4. 4 4
      src/Hotline.Api/Controllers/Bi/BiKnowledgeController.cs
  5. 3 38
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  6. 7 1
      src/Hotline.Api/Controllers/Bigscreen/SeatController.cs
  7. 13 0
      src/Hotline.Api/Controllers/CommonPController.cs
  8. 191 6
      src/Hotline.Api/Controllers/DataSharingController.cs
  9. 0 18
      src/Hotline.Api/Controllers/EnforcementOrderController.cs
  10. 3 2
      src/Hotline.Api/Controllers/HotSpotController.cs
  11. 0 6
      src/Hotline.Api/Controllers/IPPbxController.cs
  12. 155 89
      src/Hotline.Api/Controllers/OrderController.cs
  13. 3 2
      src/Hotline.Api/Controllers/OrderProvinceZmhdController.cs
  14. 10 4
      src/Hotline.Api/Controllers/SettingController.cs
  15. 21 10
      src/Hotline.Api/Controllers/TestController.cs
  16. 19 20
      src/Hotline.Api/Controllers/WebPortalController.cs
  17. 6 0
      src/Hotline.Api/Program.cs
  18. 1 0
      src/Hotline.Api/Realtimes/HotlineHub.cs
  19. 4 3
      src/Hotline.Api/StartupExtensions.cs
  20. 10 0
      src/Hotline.Api/StartupHelper.cs
  21. 35 3
      src/Hotline.Api/config/appsettings.Development.json
  22. 6 0
      src/Hotline.Application.Tests/Application/OrderApplicationTest.cs
  23. 43 0
      src/Hotline.Application.Tests/Domain/LuZhouExpireTimeTest.cs
  24. 14 0
      src/Hotline.Application.Tests/Domain/ZiGongExpireTimeTest.cs
  25. 2 1
      src/Hotline.Application.Tests/ReadME.md
  26. 10 4
      src/Hotline.Application.Tests/Repository/OrderVisitRepositoryTest.cs
  27. 4 2
      src/Hotline.Application.Tests/Startup.cs
  28. 5 7
      src/Hotline.Application/Bigscreen/SeatStateDataService.cs
  29. 67 0
      src/Hotline.Application/Bulletin/BulletinApplication.cs
  30. 18 0
      src/Hotline.Application/Bulletin/IBulletinApplication.cs
  31. 32 6
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  32. 22 8
      src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs
  33. 90 0
      src/Hotline.Application/Jobs/XingTangCallSatisfactionSyncJob.cs
  34. 3 1
      src/Hotline.Application/Jobs/XingTangTelOperationSyncJob.cs
  35. 0 2
      src/Hotline.Application/JudicialManagement/EnforcementApplication.cs
  36. 5 0
      src/Hotline.Application/Mappers/CallMapperConfigs.cs
  37. 2 2
      src/Hotline.Application/Mappers/WebPortalMapperConfigs.cs
  38. 121 140
      src/Hotline.Application/Orders/OrderApplication.cs
  39. 1 1
      src/Hotline.Application/Orders/OrderScreenHandler/OrderScreenEndWorkflowHandler.cs
  40. 0 8
      src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs
  41. 0 1
      src/Hotline.Application/StatisticalReport/CallReportApplication.cs
  42. 0 14
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  43. 145 26
      src/Hotline.Application/Subscribers/DatasharingSubscriber.cs
  44. 1 12
      src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs
  45. 1 18
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  46. 17 7
      src/Hotline.Repository.SqlSugar/Orders/OrderVisitRepository.cs
  47. 9 0
      src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs
  48. 28 0
      src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/TianQuePushOrderReceiverDto.cs
  49. 107 0
      src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/TianQueReceiverOpinionDto.cs
  50. 18 0
      src/Hotline.Share/Dtos/DataSharingSearch/AcceptTypeList.cs
  51. 5 0
      src/Hotline.Share/Dtos/DataSharingSearch/GetOrderDetailDto.cs
  52. 39 0
      src/Hotline.Share/Dtos/DataSharingSearch/GridOperatorSendSmsDto.cs
  53. 6 1
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  54. 1 1
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  55. 1 1
      src/Hotline.Share/Dtos/Order/OrderWaitedDto.cs
  56. 6 0
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  57. 2 1
      src/Hotline.Share/Dtos/Order/SendBackDto.cs
  58. 7 1
      src/Hotline.Share/Dtos/Settings/TimeConfig.cs
  59. 5 0
      src/Hotline.Share/Enums/Order/ESource.cs
  60. 2 2
      src/Hotline.Share/Hotline.Share.csproj
  61. 10 0
      src/Hotline.Share/Mq/EventNames.Share.cs
  62. 1 1
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  63. 7 6
      src/Hotline/Authentications/Police110SessionContext.cs
  64. 7 6
      src/Hotline/Authentications/ProvinceSessionContext.cs
  65. 6 5
      src/Hotline/Authentications/SessionContextCreator.cs
  66. 7 6
      src/Hotline/Authentications/YbEnterpriseSessionContext.cs
  67. 7 6
      src/Hotline/Authentications/ZzptSessionContext.cs
  68. 30 1
      src/Hotline/CallCenter/Calls/CallNative.cs
  69. 25 0
      src/Hotline/CallCenter/Calls/CallSatisfaction.cs
  70. 1 0
      src/Hotline/Configurations/AppConfiguration.cs
  71. 42 0
      src/Hotline/Configurations/CityBaseConfiguration.cs
  72. 31 26
      src/Hotline/FlowEngine/Workflows/Workflow.cs
  73. 45 25
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  74. 188 64
      src/Hotline/Orders/Order.cs
  75. 1 0
      src/Hotline/Orders/OrderSendBackAudit.cs
  76. 25 1
      src/Hotline/Permissions/EPermission.cs
  77. 10 2
      src/Hotline/Push/FWMessage/PushDomainService.cs
  78. 5 0
      src/Hotline/Settings/SettingConstants.cs
  79. 16 4
      src/Hotline/Settings/SystemOrganize.cs
  80. 21 14
      src/Hotline/Settings/TimeLimitDomain/ExpireTimeLimitBase.cs
  81. 3 11
      src/Hotline/Settings/TimeLimitDomain/ExpireTimeSupplier/ExpireTimeFactory.cs
  82. 13 0
      src/Hotline/Settings/TimeLimitDomain/ExpireTimeSupplier/WorkDaySupplier.cs
  83. 22 0
      src/Hotline/Settings/TimeLimitDomain/LuZhouExpireTimeLimit.cs
  84. 9 3
      src/Hotline/Settings/TimeLimitDomain/ZiGongExpireTimeLimit.cs
  85. 109 91
      src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs
  86. 26 1
      src/Hotline/dataview.md
  87. 37 0
      src/XingTang.Sdk/XingtangSatisfaction.cs

+ 8 - 4
src/Hotline.Api/Controllers/AiController.cs

@@ -567,7 +567,7 @@ namespace Hotline.Api.Controllers
                                 //处理部门
                                 var orgDetail = visitDetail.Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Org).ToList();
                                 //过滤结果
-                                var orgProcessingResults = new Kv();
+                                Kv? orgProcessingResults = null;
                                 //var orgHandledAttitude = new Kv();
                                 ESeatEvaluate? seatEvaluate = null;
                                 var visitContent = "";
@@ -667,11 +667,14 @@ namespace Hotline.Api.Controllers
                                 orgDetail.ForEach(x =>
                                 {
                                     //x.OrgHandledAttitude = orgHandledAttitude;
-                                    x.OrgProcessingResults = orgProcessingResults;
+                                    if (orgProcessingResults!=null)
+                                    {
+                                        x.OrgProcessingResults = orgProcessingResults;
+                                    }
                                     x.VisitContent = visitContent;
                                     x.Volved = isSolve;
                                     x.IsContact = isContact;
-                                    if (string.IsNullOrEmpty(orgProcessingResults.Key) || seatEvaluate == null || isSolve == null || isContact == null ||  orgProcessingResults.Value == "不满意" || seatEvaluate== ESeatEvaluate.NoSatisfied)
+                                    if (string.IsNullOrEmpty(orgProcessingResults?.Key) || seatEvaluate == null || isSolve == null || isContact == null ||  orgProcessingResults?.Value == "不满意" || seatEvaluate== ESeatEvaluate.NoSatisfied)
                                     {
                                         //x.OrgNoSatisfiedReason = new List<Kv>() { new Kv() { Key = "7", Value = "未回复" } };
                                         //TODO 记录不满意原因到内容中供人工回访甄别选择不满意原因
@@ -1005,7 +1008,7 @@ namespace Hotline.Api.Controllers
         }
 
         /// <summary>
-        /// 可进行智能回访记录
+        /// 可进行智能回访记录 
         /// </summary>
         /// <returns></returns>
         [HttpGet("aivisit/canaivisit-list")]
@@ -1018,6 +1021,7 @@ namespace Hotline.Api.Controllers
                 .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.Order.AcceptTypeCode == dto.AcceptType)//受理类型
                 .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No.Contains(dto.No)) //工单编码
                 .WhereIF(!string.IsNullOrEmpty(dto.Title),x=> x.Order.Title.Contains(dto.Title))
+                .Where(x=> SqlFunc.Length(x.Order.Contact.Length)>6)
                 .ToListAsync();
             return _mapper.Map<IReadOnlyList<OrderVisitDto>>(items);
         }

+ 25 - 4
src/Hotline.Api/Controllers/ArticleController.cs

@@ -1,4 +1,5 @@
 using DotNetCore.CAP;
+using Hotline.Application.Bulletin;
 using Hotline.Application.FlowEngine;
 using Hotline.Article;
 using Hotline.Caching.Interfaces;
@@ -36,8 +37,23 @@ namespace Hotline.Api.Controllers
         private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
         private readonly IMediator _mediator;
         private readonly ICapPublisher _capPublisher;
-
-        public ArticleController(IRepository<Bulletin> bulletinRepository, IMapper mapper, ISystemDomainService systemDomainService, ISystemOrganizeRepository organizeRepository, IWorkflowApplication workflowApplication, IRepository<Circular> circularRepository, ISessionContext sessionContext, IRepository<CircularRecord> circularRecordRepository, IRepository<CircularReadGroup> circularReadGroupRepository, IRepository<User> userRepository, ICircularRecordDomainService circularRecordDomainService, ISystemDicDataCacheManager systemDicDataCacheManager, IMediator mediator, ICapPublisher capPublisher)
+        private readonly IBulletinApplication _bulletinApplication;
+
+        public ArticleController(IRepository<Bulletin> bulletinRepository,
+            IMapper mapper,
+            ISystemDomainService systemDomainService,
+            ISystemOrganizeRepository organizeRepository,
+            IWorkflowApplication workflowApplication,
+            IRepository<Circular> circularRepository,
+            ISessionContext sessionContext,
+            IRepository<CircularRecord> circularRecordRepository,
+            IRepository<CircularReadGroup> circularReadGroupRepository,
+            IRepository<User> userRepository,
+            ICircularRecordDomainService circularRecordDomainService,
+            ISystemDicDataCacheManager systemDicDataCacheManager,
+            IMediator mediator,
+            ICapPublisher capPublisher,
+            IBulletinApplication bulletinApplication)
         {
             _bulletinRepository = bulletinRepository;
             _mapper = mapper;
@@ -52,6 +68,7 @@ namespace Hotline.Api.Controllers
             _systemDicDataCacheManager = systemDicDataCacheManager;
             _mediator = mediator;
             _capPublisher = capPublisher;
+            _bulletinApplication = bulletinApplication;
         }
         #region 通知
 
@@ -446,6 +463,10 @@ namespace Hotline.Api.Controllers
             var model = await _bulletinRepository.Queryable()
                 .Includes(x => x.ExaminMan)
                 .FirstAsync(x => x.Id == id, HttpContext.RequestAborted);
+
+            if (model != null && !string.IsNullOrEmpty(model.Content))
+                model.Content = _bulletinApplication.GetSiteUrls(model.Content);
+
             return _mapper.Map<BulletinDto>(model);
         }
 
@@ -476,7 +497,7 @@ namespace Hotline.Api.Controllers
                 var publishBulletin = _mapper.Map<PublishBulletinDto>(bulletin);
 
                 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlinePushBulletin, publishBulletin, cancellationToken: HttpContext.RequestAborted);
-                
+
                 //todo await _bulletinService.PushBulletin(publishBulletin, HttpContext.RequestAborted);
             }
             else
@@ -589,7 +610,7 @@ namespace Hotline.Api.Controllers
                 throw UserFriendlyException.SameMessage("当前状态不能操作上架或下架");
 
             bulletin.IsArrive = dto.IsArrive;
-            if (bulletin.IsArrive==false)
+            if (bulletin.IsArrive == false)
             {
                 bulletin.ExaminTime = null;
                 bulletin.ExaminManId = null;

+ 47 - 20
src/Hotline.Api/Controllers/Bi/BiCallController.cs

@@ -118,7 +118,6 @@ public class BiCallController : BaseController
         //    items = items.OrderBy(d => d.Hour).ToList();
         //}
         #endregion
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
         return await _trCallRecordRepositoryEx.GetQueryCalls(dto.StartTime.Value, dto.EndTime.Value, dto.Keyword);
 
@@ -135,8 +134,6 @@ public class BiCallController : BaseController
     {
         if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-        dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
         var list = await _trCallRecordRepositoryEx.GetQueryCalls(dto.QueryDto.StartTime.Value, dto.QueryDto.EndTime.Value, dto.QueryDto.Keyword);
 
         if (list != null && list.Count > 0)
@@ -174,7 +171,6 @@ public class BiCallController : BaseController
     {
         if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
             throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
         var items = await _callReportApplication.QueryCallsDetailAsync(dto);
 
@@ -210,7 +206,6 @@ public class BiCallController : BaseController
     {
         if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue)
             throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
         var items = await _callReportApplication.QueryCallsDetailAsync(dto.QueryDto);
 
@@ -307,7 +302,7 @@ public class BiCallController : BaseController
     {
         if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
             throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
         //超时接通量
         int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
         //坐席超时挂断时间
@@ -355,7 +350,7 @@ public class BiCallController : BaseController
     {
         if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue)
             throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
         //超时接通量
         int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
         //坐席超时挂断时间
@@ -412,8 +407,8 @@ public class BiCallController : BaseController
     [HttpPost("seats/export")]
     public async Task<FileStreamResult> ExportSeatss([FromBody] ExportExcelDto<ReportPagedRequest> dto)
     {
-        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue) 
+            throw UserFriendlyException.SameMessage("请选择时间!");
 
         var list =  await _callReportApplication.QuerySeatCallAsync(dto.QueryDto);
         if (list != null && list.Count > 0)
@@ -457,8 +452,8 @@ public class BiCallController : BaseController
     [AllowAnonymous]
     public async Task<IReadOnlyList<BiSeatCallsDto>> QuerySeatCallsAsync([FromQuery] ReportPagedRequest dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) 
+            throw UserFriendlyException.SameMessage("请选择时间!");
 
         //获取配置
         int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
@@ -514,8 +509,8 @@ public class BiCallController : BaseController
     [AllowAnonymous]
     public async Task<IReadOnlyList<BiSeatRestDto>> QuerySeatRest([FromQuery] QuerySeatRestRequest dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) 
+            throw UserFriendlyException.SameMessage("请选择时间!");
 
         return await _telRestRepository.Queryable()
             .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
@@ -546,9 +541,8 @@ public class BiCallController : BaseController
     [AllowAnonymous]
     public async Task<PagedDto<BiSeatSwitchDto>> QuerySeatSwitch([FromQuery] QuerySeatSwitchRequest dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) 
+            throw UserFriendlyException.SameMessage("请选择时间!");
 
         var (total, items) = await _trCallRecordRepository.Queryable()
             .Where(x => !string.IsNullOrEmpty(x.AgentTransferNumber))
@@ -577,13 +571,15 @@ public class BiCallController : BaseController
     /// <returns></returns>
     [HttpGet("hourcall")]
     [AllowAnonymous]
-    public async Task<List<TrCallHourDto>> QueryHourCall([FromQuery] DateTime StartTime, DateTime? EndTime, string source)
+    public async Task<List<TrCallHourDto>> QueryHourCall([FromQuery] BiQueryHourCallDto dto)
     {
+        if (!dto.EndTime.HasValue)
+            throw UserFriendlyException.SameMessage("请选择时间!");
         //获取配置
         int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
         int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
         int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
-        var list = await _trCallRecordRepositoryEx.GetCallHourList(StartTime, EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, source);
+        var list = await _trCallRecordRepositoryEx.GetCallHourList(dto.StartTime, dto.EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, dto.Source);
         return list;
     }
 
@@ -595,6 +591,8 @@ public class BiCallController : BaseController
     [AllowAnonymous]
     public async Task<FileStreamResult> ExportQueryHourCall([FromBody] ExportExcelDto<BiQueryHourCallDto> dto)
     {
+         if (!dto.QueryDto.EndTime.HasValue)
+            throw UserFriendlyException.SameMessage("请选择时间!");
         //获取配置
         int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
         int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
@@ -634,6 +632,8 @@ public class BiCallController : BaseController
     [HttpGet("hourcall_list")]
     public async Task<object> QueryCallList([FromQuery] DateTime StartTime, DateTime? EndTime, string type, string source, TimeSpan? startHourTo, int pageIndex, int pageSize)
     {
+        if(!EndTime.HasValue)
+            throw UserFriendlyException.SameMessage("请选择时间!");
         //获取配置
         int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
         int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
@@ -666,14 +666,41 @@ public class BiCallController : BaseController
     /// <returns></returns>
     [AllowAnonymous]
     [HttpGet("gateway-query")]
-    public async Task<List<CallHotLineDto>> QueryGateWay(DateTime StartTime, DateTime EndTime, string gateway)
+    public async Task<List<CallHotLineDto>> QueryGateWay([FromQuery] BiQueryGateWayDto dto)
     {
         //获取配置
         int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
         int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
         int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
         int ringTims = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.RingTims)?.SettingValue[0]);
-        var list = await _trCallRecordRepositoryEx.GetCallHotLineList(StartTime, EndTime, gateway, noConnectByeTimes, effectiveTimes, connectByeTimes, ringTims);
+        var list = await _trCallRecordRepositoryEx.GetCallHotLineList(dto.StartTime, dto.EndTime, dto.gateway, noConnectByeTimes, effectiveTimes, connectByeTimes, ringTims);
         return list;
     }
+
+    /// <summary>
+    /// 热线号码统计导出
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("gateway-query/export")]
+    public async Task<FileStreamResult> ExportQueryGatetWay(ExportExcelDto<BiQueryGateWayDto> dto)
+    {
+        //获取配置
+        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
+        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
+        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+        int ringTims = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.RingTims)?.SettingValue[0]);
+        var list = await _trCallRecordRepositoryEx.GetCallHotLineList(dto.QueryDto.StartTime, dto.QueryDto.EndTime, dto.QueryDto.gateway, noConnectByeTimes, effectiveTimes, connectByeTimes, ringTims);
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+        var dtos = list
+            .Select(stu => _mapper.Map(stu, typeof(CallHotLineDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+
+        return ExcelStreamResult(stream, "热线号码统计");
+    }
 }

+ 4 - 4
src/Hotline.Api/Controllers/Bi/BiKnowledgeController.cs

@@ -34,8 +34,8 @@ namespace Hotline.Api.Controllers.Bi
 		[HttpGet("data_list")]
 		public async Task<PagedDto<KnowledgeBiDataListVo>> DataList([FromQuery] KnowledgeBiDataListDto dto)
 		{
-            if (!dto.CreationTimeStart.HasValue || !dto.CreationTimeEnd.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.CreationTimeEnd = dto.CreationTimeEnd.Value.AddDays(1).AddSeconds(-1);
+            if (!dto.CreationTimeStart.HasValue || !dto.CreationTimeEnd.HasValue) 
+				throw UserFriendlyException.SameMessage("请选择时间!");
 
 			var query = _knowledgeRepository.DataList(dto, HttpContext.RequestAborted);
 			switch (dto.SortField)
@@ -81,8 +81,8 @@ namespace Hotline.Api.Controllers.Bi
 		[HttpPost("data_list/_export")]
 		public async Task<FileStreamResult> DataList([FromBody] ExportExcelDto<KnowledgeBiDataListDto> dto)
 		{
-			if (!dto.QueryDto.CreationTimeStart.HasValue || !dto.QueryDto.CreationTimeEnd.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-			dto.QueryDto.CreationTimeEnd = dto.QueryDto.CreationTimeEnd.Value.AddDays(1).AddSeconds(-1);
+			if (!dto.QueryDto.CreationTimeStart.HasValue || !dto.QueryDto.CreationTimeEnd.HasValue) 
+				throw UserFriendlyException.SameMessage("请选择时间!");
 			var query = _knowledgeRepository.DataList(dto.QueryDto, HttpContext.RequestAborted);
 			List<KnowledgeBiDataListVo> data;
 			if (dto.IsExportAll)

+ 3 - 38
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -231,8 +231,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("published/statistics")]
         public async Task<PublishedOrderStatisticsDto> QueryPublishedOrderAsync([FromQuery] QueryOrderPublishStatisticsAllDto dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             var waitCount = await _orderRepository.Queryable()
              .Where(order => order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime)
              .Where(order => order.Status == EOrderStatus.Filed)
@@ -511,8 +509,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             var query = _hotspotTypeRepository.Queryable(false, true)
                 .LeftJoin<Order>((x, o) => o.HotspotSpliceName != null && (x.HotSpotFullName == o.HotspotSpliceName || o.HotspotSpliceName.Contains(x.HotSpotFullName)) && o.IsDeleted == false)
                 .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= dto.StartTime)
@@ -532,7 +528,7 @@ namespace Hotline.Api.Controllers.Bi
         }
 
         /// <summary>
-        /// 热点数据统计
+        /// 热点数据统计 TODO和前端沟通
         /// </summary>
         /// <param name="dto"></param>
         /// <returns></returns>
@@ -640,7 +636,6 @@ namespace Hotline.Api.Controllers.Bi
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
             if (dto.AddColumnName is null || dto.AddColumnName.Count == 0) throw UserFriendlyException.SameMessage("导出字段不能为空");
             if (dto.AddColumnName.FirstOrDefault() != "部门名称") throw UserFriendlyException.SameMessage("导出字段第一个必须是'部门名称'");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
             var (dissatisfiedReason, list) = await _orderReportApplication.QueryVisitNoSatisfiedAsync(dto, _sessionContext.OrgIsCenter);
             var dataTable = await _orderReportApplication.ExportQueryVisitNoSatisfiedAsync(dissatisfiedReason, list, dto.AddColumnName);
@@ -659,8 +654,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             var (dissatisfiedReason, list) = await _orderReportApplication
                 .QueryVisitNoSatisfiedAsync(_mapper.Map<QueryVisitNoSatisfiedDto>(dto), _sessionContext.OrgIsCenter);
             return new { DicReason = dissatisfiedReason, Data = list };
@@ -676,8 +669,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             var IsCenter = _sessionContext.OrgIsCenter;
 
             var (total, items) = await _orderVisitDetailRepository.Queryable()
@@ -809,11 +800,9 @@ namespace Hotline.Api.Controllers.Bi
         public async Task<PagedDto<OrderBiSpecialListVo>> SpecialDataList([FromQuery] ReportPagedRequest dto)
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
             var IsCenter = _sessionContext.OrgIsCenter;
 
-
             var query = _orderSpecialRepository.Queryable()
                 .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                 .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
@@ -851,7 +840,6 @@ namespace Hotline.Api.Controllers.Bi
         public async Task<PagedDto<OrderSpecialDto>> List([FromQuery] OrderSpecialListDto dto)
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
             var IsCenter = _sessionContext.OrgIsCenter;
             var (total, items) = await _orderSpecialRepository.Queryable()
@@ -878,7 +866,7 @@ namespace Hotline.Api.Controllers.Bi
         public async Task<PagedDto<AcceptTypeTop10Vo>> AcceptTypeTop10List([FromQuery] ReportPagedRequest dto)
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
             dto.PageIndex = 1;
             dto.PageSize = 10;
             var IsCenter = _sessionContext.OrgIsCenter;
@@ -955,7 +943,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("hotport-org-statistics")]
         public async Task<object> HotPortJoinOrgStatistics([FromQuery] HotPortJoinOrgStatisticsRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             var IsCenter = _sessionContext.OrgIsCenter;
             return await _orderRepository.HotPortJoinOrgStatistics(dto.StartTime, dto.EndTime, IsCenter, _sessionContext.OrgId);
         }
@@ -970,8 +957,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("visit-measure-statistics")]
         public async Task<VisitMeasureStatisticsDto> VisitMeasureStatistics(DateTime StartTime, DateTime EndTime, string? VisitName)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             var list = await _orderVisitRepository.Queryable()
                 .Includes(x => x.Employee)
                  .Where(x => x.VisitTime >= StartTime && x.VisitTime <= EndTime && x.VisitState == EVisitState.Visited)
@@ -1017,8 +1002,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("hotspot-statistics")]
         public async Task<object> HotspotStatistics(DateTime StartTime, DateTime EndTime, int TypeId, string? HotspotCode)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             var IsCenter = _sessionContext.OrgIsCenter;
 
             if (string.IsNullOrEmpty(HotspotCode))
@@ -1357,8 +1340,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("center_report_forms_statistics")]
         public async Task<CenterReportStatisticsDto> CenterReportFormsStatistics(DateTime StartTime, DateTime EndTime)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             CenterReportStatisticsDto centerReportStatisticsDto = new();
 
             //信件总量
@@ -2150,7 +2131,6 @@ namespace Hotline.Api.Controllers.Bi
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
                 throw UserFriendlyException.SameMessage("请选择时间!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             int CallCount = 2;
             var HighFrequencyCallStatistics = _systemSettingCacheManager.GetSetting(SettingConstants.HighFrequencyCallStatistics)?.SettingValue[0];
             if (HighFrequencyCallStatistics != null)
@@ -2196,7 +2176,6 @@ namespace Hotline.Api.Controllers.Bi
             if (string.IsNullOrEmpty(dto.FromPhone))
                 throw UserFriendlyException.SameMessage("号码不能为空!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             var data = await _trCallRecordRepository.Queryable()
                     .LeftJoin<Order>((p, o) => p.ExternalId == o.Id)
                    .Where((p, o) => p.OverTime >= dto.StartTime && p.OverTime <= dto.EndTime)
@@ -2268,9 +2247,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("highmatter-warning")]
         public async Task<PagedDto<HighMatterWarningDto>> HighMatterWarning([FromQuery] HighMatterWarningRequest dto)
         {
-
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             List<string> filterTitle = new List<string>();
             filterTitle.Add("无声");
             filterTitle.Add("骚扰");
@@ -2333,7 +2309,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("highmatter-warning-detail")]
         public async Task<PagedDto<OrderDto>> HighMatterWarningDetail([FromQuery] HighMatterWarningDetailRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             List<string> filterTitle = new List<string>();
             filterTitle.Add("无声");
             filterTitle.Add("骚扰");
@@ -2363,7 +2338,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
                 throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             var query = _orderApplication.OrderReTransact(dto);
             var (total, items) = await query
                 .ToPagedListAsync(dto, HttpContext.RequestAborted);
@@ -2473,7 +2447,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
                 throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             return await _orderApplication.SendOrderReportAsync(dto);
         }
 
@@ -2487,7 +2460,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue)
                 throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
             var list = await _orderApplication.SendOrderReportAsync(dto.QueryDto);
 
             if (list != null && list.Count > 0)
@@ -2525,9 +2497,8 @@ namespace Hotline.Api.Controllers.Bi
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
                 throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
-            var (total, items) = await _workflowStepRepository.Queryable()
+            var (total, items) = await _workflowTraceRepository.Queryable()
                 //.LeftJoin<Workflow>((x, w) => x.WorkflowId == w.Id)
                 .InnerJoin<SchedulingUser>((x, su) => x.HandlerId == su.UserId)
                 .Where((x, su) => x.ModuleCode == "OrderHandle" && x.BusinessType == EBusinessType.Send)
@@ -2892,8 +2863,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("order_source_report")]
         public async Task<IReadOnlyList<OrderSourceVo>> QueryOrderSourceReport([FromQuery] QueryOrderSourceRequest dto)
         {
-            if (dto.EndTime.HasValue)
-                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             //var count = await _orderApplication.QueryOrderSource(dto).CountAsync();
             var query = _orderApplication.QueryOrderSource(dto);
             var items = await query.GroupBy(d => d.SourceChannel).Select(d => new OrderSourceVo { Source = d.SourceChannel, Num = SqlFunc.AggregateCount(d.Id) }).ToListAsync(HttpContext.RequestAborted);
@@ -2910,8 +2879,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpPost("order_source/_export")]
         public async Task<FileStreamResult> QueryOrderSourceReport([FromBody] ExportExcelDto<QueryOrderSourceRequest> dto)
         {
-            if (dto.QueryDto.EndTime.HasValue)
-                dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
             //var count = await _orderApplication.QueryOrderSource(dto.QueryDto).CountAsync();
             var query = _orderApplication.QueryOrderSource(dto.QueryDto).GroupBy(d => d.SourceChannel).Select(d => new OrderSourceVo { Source = d.SourceChannel, Num = SqlFunc.AggregateCount(d.Id) });
             List<OrderSourceVo> orderSources;
@@ -3421,8 +3388,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("area_subordinate")]
         public async Task<object> AreaSubordinate(DateTime StartTime, DateTime EndTime, int? TypeId, string? AreaCode, string? Line)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             string count = "6";
             if (!string.IsNullOrEmpty(AreaCode) && AreaCode != "511500")
                 count = (AreaCode.Length + 2).ToString();

+ 7 - 1
src/Hotline.Api/Controllers/Bigscreen/SeatController.cs

@@ -50,10 +50,16 @@ namespace Hotline.Api.Controllers.Bigscreen
         public async Task<List<TelOutDto>> GetListenTels()
         {
             var listenTels = _systemSettingCacheManager.GetSetting(SettingConstants.ListenTels)?.SettingValue;
-            return (await _trClient.QueryTelsAsync(new QueryTelRequest(), HttpContext.RequestAborted))
+            var callOuttQueueId = _systemSettingCacheManager.GetSetting(SettingConstants.CallOutQueueId)?.SettingValue;
+            var list = (await _trClient.QueryTelsAsync(new QueryTelRequest(), HttpContext.RequestAborted))
                 .Where(m => listenTels.Contains(m.TelNo))
                 .ToList()
                 .Adapt<List<TelOutDto>>();
+            list.ForEach(x =>
+            {
+                x.Queue = callOuttQueueId[0];
+            });
+            return list;
         }
     }
 }

+ 13 - 0
src/Hotline.Api/Controllers/CommonPController.cs

@@ -25,6 +25,7 @@ using Hotline.Share.Dtos.Order;
 using System.Runtime.InteropServices;
 using Lucene.Net.Util;
 using NPOI.Util;
+using XF.Domain.Entities;
 
 namespace Hotline.Api.Controllers
 {
@@ -228,6 +229,12 @@ namespace Hotline.Api.Controllers
 				//待办
 				var waitedDataList = await _orderRepository
 					.Queryable(hasHandled: false, isAdmin: isAdmin)
+					.Where(d => SqlFunc.Subqueryable<WorkflowStep>()
+						.Where(step => step.ExternalId == d.Id &&
+						               ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
+						                (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
+						                (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
+						.Any())
 					.Includes(d => d.OrderSpecials)
 					.Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status != EOrderStatus.HandOverToUnAccept)
 					.Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC)
@@ -395,6 +402,12 @@ namespace Hotline.Api.Controllers
 				//待办
 				var waitedDataList = await _orderRepository
 					.Queryable(hasHandled: false, isAdmin: isAdmin)
+					.Where(d => SqlFunc.Subqueryable<WorkflowStep>()
+						.Where(step => step.ExternalId == d.Id &&
+						               ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
+						                (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
+						                (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
+						.Any())
 					.Includes(d => d.OrderSpecials)
 					.Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status != EOrderStatus.HandOverToUnAccept)
 					.Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC)

+ 191 - 6
src/Hotline.Api/Controllers/DataSharingController.cs

@@ -1,16 +1,28 @@
-using Hotline.Article;
+using Hotline.Application.Bulletin;
+using Hotline.Article;
+using Hotline.Caching.Interfaces;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
+using Hotline.Push.Notifies;
 using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Settings;
+using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Article;
 using Hotline.Share.Dtos.DataSharingSearch;
+using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.Article;
+using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
+using Hotline.Share.Enums.Push;
 using MapsterMapper;
+using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
+using System.Threading;
+using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 
 namespace Hotline.Api.Controllers
@@ -23,14 +35,65 @@ namespace Hotline.Api.Controllers
         private readonly IMapper _mapper;
         private readonly IOrderRepository _orderRepository;
         private readonly IRepository<Bulletin> _bulletinRepository;
+        private readonly IBulletinApplication _bulletinApplication;
+        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
+        private readonly IRepository<WorkflowTrace> _workflowTraceRepository;
+        private readonly IRepository<Hotspot> _hotspotTypeRepository;
+        private readonly IMediator _mediator;
 
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="mapper"></param>
+        /// <param name="orderRepository"></param>
+        /// <param name="bulletinRepository"></param>
+        /// <param name="bulletinApplication"></param>
+        /// <param name="sysDicDataCacheManager"></param>
+        /// <param name="workflowTraceRepository"></param>
+        /// <param name="hotspotTypeRepository"></param>
+        /// <param name="mediator"></param>
         public DataSharingController(IMapper mapper,
             IOrderRepository orderRepository,
-            IRepository<Bulletin> bulletinRepository)
+            IRepository<Bulletin> bulletinRepository,
+            IBulletinApplication bulletinApplication,
+            ISystemDicDataCacheManager sysDicDataCacheManager,
+            IRepository<WorkflowTrace> workflowTraceRepository,
+            IRepository<Hotspot> hotspotTypeRepository,
+            IMediator mediator)
         {
             _mapper = mapper;
             _orderRepository = orderRepository;
             _bulletinRepository = bulletinRepository;
+            _bulletinApplication = bulletinApplication;
+            _sysDicDataCacheManager = sysDicDataCacheManager;
+            _workflowTraceRepository = workflowTraceRepository;
+            _hotspotTypeRepository = hotspotTypeRepository;
+            _mediator = mediator;
+        }
+
+        /// <summary>
+        /// 查询受理类型
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("get_accept_type_list")]
+        [AllowAnonymous]
+        public async Task<List<AcceptTypeList>> GetAcceptTypeList()
+        {
+            //查询数据
+            var data = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType);
+            List<AcceptTypeList> acceptTypeList = new List<AcceptTypeList>();
+            if (data != null && data.Count > 0)
+            {
+                foreach (var item in data)
+                {
+                    acceptTypeList.Add(new AcceptTypeList()
+                    {
+                        Name = item.DicDataName,
+                        Value = item.DicDataValue
+                    });
+                }
+            }
+            return acceptTypeList;
         }
 
         /// <summary>
@@ -50,6 +113,21 @@ namespace Hotline.Api.Controllers
             return _mapper.Map<OrderDto>(order);
         }
 
+        /// <summary>
+        /// 根据工单编号查询信件详情
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("get_order_detail_by_no")]
+        public async Task<OrderDto> GetOrderDetailByNo([FromBody] GetOrderDetailDto dto)
+        {
+            var order = await _orderRepository.Queryable()
+                 .Where(p => p.No == dto.No)
+                 .FirstAsync();
+            return _mapper.Map<OrderDto>(order);
+        }
+
         /// <summary>
         /// 根据工单Id查询信件详情
         /// </summary>
@@ -83,6 +161,8 @@ namespace Hotline.Api.Controllers
                 .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), p => p.AcceptTypeCode == dto.AcceptTypeCode)
                 .WhereIF(dto.StartTime.HasValue, p => p.CreationTime >= dto.StartTime)
                 .WhereIF(dto.EndTime.HasValue, p => p.CreationTime < dto.EndTime)
+                .WhereIF(dto.HandleStateCode == "1", p => p.Status < EOrderStatus.Filed)
+                .WhereIF(dto.HandleStateCode == "2", p => p.Status >= EOrderStatus.Filed)
                 .OrderByDescending(p => p.CreationTime)
                 .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
@@ -96,7 +176,7 @@ namespace Hotline.Api.Controllers
         /// <returns></returns>
         [HttpPost("get_order_list_publish")]
         [AllowAnonymous]
-        public async Task<PagedDto<OrderDto>> GetOrderByListOpen([FromBody] GetOrderList dto)
+        public async Task<PagedDto<PublishDto>> GetOrderByListOpen([FromBody] GetOrderList dto)
         {
             var (total, items) = await _orderRepository.Queryable()
                 .Includes(d => d.OrderPublish)
@@ -111,7 +191,32 @@ namespace Hotline.Api.Controllers
                 .OrderByDescending(p => p.CreationTime)
                 .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
-            return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+            return new PagedDto<PublishDto>(total, _mapper.Map<IReadOnlyList<PublishDto>>(items));
+        }
+
+        /// <summary>
+        /// 根据工单编号和密码查询流程
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("get_workflow_by_no_pwd")]
+        [AllowAnonymous]
+        public async Task<List<WorkflowTraceDto>> GetWorkflowByNoPwd([FromBody] GetOrderNoPwdDto dto)
+        {
+            var order = await _orderRepository.Queryable()
+                  .Where(p => p.No == dto.No && p.Password == dto.Password)
+                  .WhereIF(!string.IsNullOrEmpty(dto.SourceChannelCode), p => p.SourceChannelCode == dto.SourceChannelCode)
+                  .FirstAsync();
+            List<WorkflowTraceDto> workflow = new();
+            if (order == null)
+                return workflow;
+
+            var data = await _workflowTraceRepository.Queryable()
+                    .Where(p => p.ExternalId == order.Id && p.ModuleCode == "OrderHandle" && p.Status == EWorkflowStepStatus.Handled && p.TraceState == EWorkflowTraceState.Normal)
+                   .OrderBy(p => p.CreationTime)
+                    .ToListAsync();
+            workflow = _mapper.Map<List<WorkflowTraceDto>>(data);
+            return workflow;
         }
 
         /// <summary>
@@ -121,7 +226,7 @@ namespace Hotline.Api.Controllers
         /// <returns></returns>
         [HttpPost("query_bulletin_list")]
         [AllowAnonymous]
-        public async Task<PagedDto<BulletinDto>> QueryBulletinList([FromQuery] GetBulletinListDto dto)
+        public async Task<PagedDto<BulletinDto>> QueryBulletinList([FromBody] GetBulletinListDto dto)
         {
             var (total, items) = await _bulletinRepository.Queryable()
                 .Where(p => p.LoseEfficacyTime >= DateTime.Now)
@@ -152,6 +257,10 @@ namespace Hotline.Api.Controllers
                 model.ReadedNum = model.ReadedNum++;
                 await _bulletinRepository.UpdateAsync(model, HttpContext.RequestAborted);
             }
+
+            if (model != null && !string.IsNullOrEmpty(model.Content))
+                model.Content = _bulletinApplication.GetSiteUrls(model.Content);
+
             return _mapper.Map<BulletinDto>(model);
         }
 
@@ -166,6 +275,7 @@ namespace Hotline.Api.Controllers
             var list = await _orderRepository.Queryable()
                  .Where(p => p.CreationTime >= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00")))
                 .Where(p => p.CreationTime <= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59")))
+                .Where(p => p.AcceptTypeCode != null && p.AcceptType != null)
                 .Select(it => new
                 {
                     it.AcceptType,
@@ -198,8 +308,83 @@ namespace Hotline.Api.Controllers
             var dayCount = await _orderRepository.Queryable().Where(p => p.CreationTime >= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00")) &&
             p.CreationTime <= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59"))).CountAsync();
 
-            return new { DayTrandCount = dayTrandCount, DayCount = dayCount };
+            //总共已办结
+            var allTrandCount = await _orderRepository.Queryable().Where(p => p.Status >= EOrderStatus.Filed).CountAsync();
+
+            //总共总量
+            var allCount = await _orderRepository.Queryable().Where(p => p.Status >= EOrderStatus.WaitForAccept).CountAsync();
+
+            return new { DayTrandCount = dayTrandCount, DayCount = dayCount, AllTrandCount = allTrandCount, AllCount = allCount };
+
+        }
+
+        /// <summary>
+        /// 查询热点分类
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("get_hotspot_statistics_list")]
+        [AllowAnonymous]
+        public async Task<object> GetHotspotStatistics()
+        {
+            var list = await _hotspotTypeRepository.Queryable()
+                .LeftJoin<Order>((it, o) => it.Id == o.HotspotId)
+                .Where((it, o) => o.CreationTime >= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00")))
+                .Where((it, o) => o.CreationTime <= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59")))
+                .Where((it, o) => o.Id != null && o.HotspotId != null)
+                .GroupBy((it, o) => new { Id = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")) })
+                .Select((it, o) => new
+                {
+                    HotspotCode = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
+                    SumCount = SqlFunc.AggregateCount(it.HotSpotName)
+                })
+                .MergeTable()
+                .LeftJoin<Hotspot>((x, q) => x.HotspotCode == q.Id)
+                .Select((x, q) => new
+                {
+                    Name = q.HotSpotName,
+                    Value = x.SumCount
+                })
+                .ToListAsync();
+
+            return list;
+        }
+
+        /// <summary>
+        ///  随手拍网格员-短信接口
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("grid_operator_send_sms")]
+        [AllowAnonymous]
+        public async Task<string> GridOperatorSendSms([FromBody] GridOperatorSendSmsDto dto)
+        {
+            if (dto == null)
+                return "数据获取失败";
+            var order = await _orderRepository.GetAsync(p => p.No == dto.ReplyCode, HttpContext.RequestAborted);
+            if (order == null)
+                return "工单查询失败";
+
+            var messageDto = new Share.Dtos.Push.MessageDto
+            {
+                PushBusiness = EPushBusiness.OrderSend,
+                ExternalId = order.Id,
+                OrderId = order.Id,
+                PushPlatform = EPushPlatform.Sms,
+                Remark = order.Title,
+                Name = dto.MemberName,
+                TemplateCode = "1010",
+                Params = new List<string>() { dto.AppealNumber },
+                TelNumber = dto.MemberMobile,
+
+            };
+            if (dto.SendType == "2")
+            {
+                messageDto.TemplateCode = "1011";
+                messageDto.PushBusiness= EPushBusiness.OrderExpire;
+            }
 
+            await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+            return "提交成功";
         }
     }
 }

+ 0 - 18
src/Hotline.Api/Controllers/EnforcementOrderController.cs

@@ -272,9 +272,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("event_classification_statistics")]
         public async Task<object> GetEventClassificationStatisticsAsync(DateTime StartTime, DateTime EndTime, string Id, string AreaCode)
         {
-
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             var items = await _judicialComplaintsEventTypeRepository.Queryable()
              .LeftJoin<EnforcementOrders>((x, o) => o.EventTypeSpliceName != null && (x.EventTypeName == o.EventTypeSpliceName || o.EventTypeSpliceName.Contains(x.EventTypeName)))
             .LeftJoin<Order>((x, o, p) => p.Id == o.Id)
@@ -325,8 +322,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("event_classification_statistics_order_list")]
         public async Task<PagedDto<EnforcementOrderListDto>> GetEventClassificationStatisticsOrderListAsync([FromQuery] QueryEventClassificationStatisticsDto dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             var (total, items) = await _enforcementOrdersRepository.Queryable()
             .Includes(x => x.Order)
             .Where(d => d.Order.Id != null)
@@ -348,8 +343,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("enforcement_departmental_processing_statistics")]
         public async Task<object> GetDepartmentalProcessingStatisticsAsync(DateTime StartTime, DateTime EndTime)
         {
-
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
             var data = await _enforcementOrdersRepository.Queryable()
                    .Includes(x => x.Order)
                    .Where(d => d.Order.Id != null)
@@ -383,8 +376,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("enforcement_departmental_processing_statistics_child")]
         public async Task<object> GetDepartmentalProcessingStatisticsChildAsync(DateTime StartTime, DateTime EndTime, string OrgCode)
         {
-
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
             if (string.IsNullOrEmpty(OrgCode))
                 throw UserFriendlyException.SameMessage("部门code不能为空!");
 
@@ -422,8 +413,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("enforcement_departmental_processing_statistics_order_list")]
         public async Task<PagedDto<EnforcementOrderListDto>> GetDepartmentalProcessingStatisticsOrderListAsync([FromQuery] QueryDepartmentalProcessingStatisticsDto dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             var (total, items) = await _enforcementOrdersRepository.Queryable()
             .Includes(x => x.Order)
             .Where(d => d.Order.Id != null)
@@ -446,7 +435,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("regional_classification_statistics")]
         public async Task<object> GetRegionalClassificationStatisticsAsync(DateTime StartTime, DateTime EndTime)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
             var areaCode = _sessionContext.OrgAreaCode ?? "511500";
             var list = await _enforcementOrdersRepository.Queryable()
                .Includes(x => x.Order)
@@ -483,8 +471,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("regional_classification_statistics_order_list")]
         public async Task<PagedDto<EnforcementOrderListDto>> GetRegionalClassificationStatisticsOrderListAsync([FromQuery] QueryRegionalClassificationStatisticsDto dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             var (total, items) = await _enforcementOrdersRepository.Queryable()
             .Includes(x => x.Order)
             .Where(d => d.Order.Id != null)
@@ -509,8 +495,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("enforcement_visit_org_satisfaction_statistics")]
         public async Task<object> GetVisitAndOrgSatisfactionStatisticsAsync(DateTime StartTime, DateTime EndTime, int TypeId)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             var list = await _enforcementOrdersRepository.Queryable()
                  .LeftJoin<OrderVisit>((x, o) => x.Id == o.OrderId)
                  .LeftJoin<OrderVisitDetail>((x, o, p) => o.Id == p.VisitId)
@@ -578,8 +562,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("enforcement_visit_org_satisfaction_statistics_child")]
         public async Task<object> GetVisitAndOrgSatisfactionStatisticsChildAsync(DateTime StartTime, DateTime EndTime, int TypeId, string OrgCode)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             var list = await _enforcementOrdersRepository.Queryable()
                  .LeftJoin<OrderVisit>((x, o) => x.Id == o.OrderId)
                  .LeftJoin<OrderVisitDetail>((x, o, p) => o.Id == p.VisitId)

+ 3 - 2
src/Hotline.Api/Controllers/HotSpotController.cs

@@ -62,6 +62,7 @@ namespace Hotline.Api.Controllers
                     HotSpotFullName = x.HotSpotFullName,
                     ProvinceCode = x.ProvinceCode,
                     HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d=>d.ParentId == x.Id).NotAny(),
+                    TrunkNum = x.TrunkNum,
                 }).ToListAsync();
 
             return list;
@@ -86,8 +87,8 @@ namespace Hotline.Api.Controllers
                 HotSpotFullName = x.HotSpotFullName,
                 ProvinceCode = x.ProvinceCode,
                 HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d => d.ParentId == x.Id).NotAny(),
-
-            }).ToTreeAsync(x => x.Children, it => it.ParentId,"", arr);
+                TrunkNum = x.TrunkNum,
+			}).ToTreeAsync(x => x.Children, it => it.ParentId,"", arr);
         }
 
 

+ 0 - 6
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -828,12 +828,6 @@ namespace Hotline.Api.Controllers
         [HttpGet("telaction-list")]
         public async Task<PagedDto<TelActionListRep>> TelActionList([FromQuery] TelActionListDto dto)
         {
-            if (!dto.EndTime.HasValue)
-            {
-                dto.EndTime = DateTime.Now.Date;
-            }
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             var (total,items) = await _telActionRecordRepository.Queryable()
                 .WhereIF(string.IsNullOrEmpty(dto.TelNo) == false, x => x.TelNo.Contains(dto.TelNo))
                 .WhereIF(dto.ActionTtype != null, x => x.ActionType == dto.ActionTtype)

+ 155 - 89
src/Hotline.Api/Controllers/OrderController.cs

@@ -64,6 +64,7 @@ using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
+using static NPOI.SS.Format.CellNumberFormatter;
 
 namespace Hotline.Api.Controllers;
 
@@ -132,8 +133,9 @@ public class OrderController : BaseController
     private readonly IOrderAnalysisApplication _orderAnalysisApplication;
     private readonly ICalcExpireTime _expireTime;
     private readonly IRepository<OrderPushType> _orderPushTypeRepository;
+    private readonly IOptions<CityBaseConfiguration> _cityBaseConfiguration;
 
-    public OrderController(
+	public OrderController(
         IOrderDomainService orderDomainService,
         IOrderRepository orderRepository,
         IWorkflowApplication workflowApplication,
@@ -192,7 +194,8 @@ public class OrderController : BaseController
         Publisher publisher,
         IOrderAnalysisApplication orderAnalysisApplication,
         ICalcExpireTime expireTime,
-        IRepository<OrderPushType> orderPushTypeRepository)
+        IRepository<OrderPushType> orderPushTypeRepository,
+        IOptions<CityBaseConfiguration> cityBaseConfiguration)
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
@@ -253,8 +256,8 @@ public class OrderController : BaseController
         _orderAnalysisApplication = orderAnalysisApplication;
         _expireTime = expireTime;
         _orderPushTypeRepository = orderPushTypeRepository;
-
-    }
+        _cityBaseConfiguration = cityBaseConfiguration;
+	}
     #endregion 
 
     #region 工单发布
@@ -350,7 +353,7 @@ public class OrderController : BaseController
                     orderVisit.PublishTime = DateTime.Now;
                     orderVisit.IsCanHandle = true;
                     orderVisit.EmployeeId = _sessionContext.RequiredUserId;
-                    if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null })
+                    if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null } && !order.IsProvince)
                     {
                         orderVisit.VisitState = EVisitState.Visited;
                         orderVisit.VisitTime = DateTime.Now;
@@ -383,7 +386,7 @@ public class OrderController : BaseController
                     orgDetail.VisitOrgCode = order.ActualHandleOrgCode;
                     orgDetail.VisitOrgName = order.ActualHandleOrgName;
                     orgDetail.VisitTarget = EVisitTarget.Org;
-                    if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null })
+                    if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null , IsProvince: false })
                     {
                         var satisfy = new Kv() { Key = "4", Value = "满意" };
                         orgDetail.OrgProcessingResults = satisfy;
@@ -545,7 +548,7 @@ public class OrderController : BaseController
             visitedDetail.Add(orgDetail);
         }
 
-        if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null })
+        if (order is { ProcessType: EProcessType.Zhiban, CounterSignType: null,IsProvince:false })
         {
             seatDetail.VoiceEvaluate = EVoiceEvaluate.Satisfied;
             seatDetail.SeatEvaluate = ESeatEvaluate.Satisfied;
@@ -915,7 +918,8 @@ public class OrderController : BaseController
         var histories = await _orderVisitRepository.Queryable()
             .Includes(m => m.OrderVisitDetails)
             .Where(m => m.OrderId == orderVisit.OrderId)
-            .Select(m => new OrderVisitDetailHistiryDto
+            .Where(m => m.VisitState == EVisitState.None && m.NowEvaluate != null)
+            .Select(m => new OrderVisitDetailHistoryDto
             {
                 VoiceEvaluate = m.OrderVisitDetails.Where(n => n.VisitTarget == EVisitTarget.Seat).Select(s => s.VoiceEvaluate).First(),
                 SeatEvaluate = m.OrderVisitDetails.Where(n => n.VisitTarget == EVisitTarget.Seat).Select(s => s.SeatEvaluate).First(),
@@ -1004,9 +1008,9 @@ public class OrderController : BaseController
             try
             {
                 var details = await _orderVisitedDetailRepository
-		    .Queryable()
-		    .Where(m => m.VisitId == visit.VisitId)
-		    .ToListAsync();
+            .Queryable()
+            .Where(m => m.VisitId == visit.VisitId)
+            .ToListAsync();
                 var seatDetail = details.First(m => m.VisitTarget == EVisitTarget.Seat);
                 var visitDto = new VisitDto
                 {
@@ -1015,14 +1019,14 @@ public class OrderController : BaseController
                     IsAgain = false,
                     VisitDetails = new List<VisitDetailDto>
                     {
-			    new()
-			    {
-				Id = seatDetail.Id,
-				VisitId = visit.VisitId,
-				VisitContent = dto.SeatVisitContent,
-				SeatEvaluate = dto.SeatEvaluate,
+                new()
+                {
+                Id = seatDetail.Id,
+                VisitId = visit.VisitId,
+                VisitContent = dto.SeatVisitContent,
+                SeatEvaluate = dto.SeatEvaluate,
                                 VisitTarget = EVisitTarget.Seat
-			    }
+                }
                     }
                 };
 
@@ -1030,16 +1034,16 @@ public class OrderController : BaseController
                 foreach (var orgDetail in orgDetails)
                 {
                     visitDto.VisitDetails.Add(
-			new()
-			{
-			    Id = orgDetail.Id,
-			    VisitId = visit.VisitId,
-			    VisitContent = dto.OrgVisitContent,
-			    VisitTarget = EVisitTarget.Org,
-			    OrgNoSatisfiedReason = dto.OrgNoSatisfiedReason,
-			    OrgProcessingResults = dto.OrgProcessingResults,
-			    OrgHandledAttitude = dto.OrgHandledAttitude
-			});
+            new()
+            {
+                Id = orgDetail.Id,
+                VisitId = visit.VisitId,
+                VisitContent = dto.OrgVisitContent,
+                VisitTarget = EVisitTarget.Org,
+                OrgNoSatisfiedReason = dto.OrgNoSatisfiedReason,
+                OrgProcessingResults = dto.OrgProcessingResults,
+                OrgHandledAttitude = dto.OrgHandledAttitude
+            });
                 }
                 await _orderApplication.SaveOrderVisit(visitDto, HttpContext.RequestAborted);
                 outDto.CompleteCount += 1;
@@ -1073,7 +1077,7 @@ public class OrderController : BaseController
             // 话务员评价
             SeatEvaluate = EnumExts.GetDescriptions<ESeatEvaluate>(),
             // 不满意原因
-            DissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason).Select(m => new { m.Id, m.DicDataName, m.DicDataValue}),
+            DissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason).Select(m => new { m.Id, m.DicDataName, m.DicDataValue }),
             // 回访满意度
             VisitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction).Where(x => x.DicDataValue != "-1").Select(m => new { m.Id, m.DicDataName, m.DicDataValue }),
             // 回访态度
@@ -1185,6 +1189,30 @@ public class OrderController : BaseController
         await _orderVisitRepository.UpdateRangeAsync(visits, HttpContext.RequestAborted);
     }
 
+
+    /// <summary>
+    /// 查询回访平移待办理人
+    /// </summary>
+    [HttpGet("ordervisit/migration")]
+    public async Task<IReadOnlyList<OrderMigrationHandler>> VisitMigration()
+    {
+        var setting = _systemSettingCacheManager.GetSetting(SettingConstants.OrderVisitRole);
+        var roles = setting?.SettingValue.ToList();
+        var users = await _userRepository.Queryable()
+            .Includes(d => d.Organization)
+            .Includes(d => d.Roles)
+            .Where(d => d.Roles.Any(x => roles.Contains(x.Name)))
+            .ToListAsync(HttpContext.RequestAborted);
+        return users.Select(d => new OrderMigrationHandler
+        {
+            UserId = d.Id,
+            Username = d.Name,
+            OrgId = d.OrgId,
+            OrgName = d.Organization.Name,
+            RoleNames = string.Join(',', d.Roles.Select(x => x.DisplayName).ToList())
+        }).ToList();
+    }
+
     #endregion
 
     #region 二次回访申请
@@ -1825,7 +1853,9 @@ public class OrderController : BaseController
             .Includes(x => x.OrderVisit, y => y.Employee)
             //.LeftJoin<OrderScreen>((x, s) => x.Id == s.VisitDetailId && s.IsDeleted == false)
             .Includes(x => x.OrderScreens)
-            .Where(x => x.OrderScreens.Any(s => s.Status == EScreenStatus.SendBack && s.SendBackApply == true) || x.OrderScreens.Any(s => (s.Status != EScreenStatus.SendBack && s.SendBackApply != true)) == false)
+            .Where(x => x.OrderScreens.Any(s => s.Status == EScreenStatus.SendBack && s.SendBackApply == true) || x.OrderScreens.Any() == false
+            //|| x.OrderScreens.Any(s => (s.Status != EScreenStatus.SendBack && s.SendBackApply != true)) == false
+            )
             .WhereIF(dto.ScreenSendBack is 1, x => x.OrderScreens.Any(s => s.Status == EScreenStatus.SendBack && s.SendBackApply == true))
             .WhereIF(dto.ScreenSendBack is 2, x => x.OrderScreens.Any(s => (s.Status != EScreenStatus.SendBack && s.SendBackApply != true)) == false)
             .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order!.No!.Contains(dto.No!))
@@ -2279,7 +2309,7 @@ public class OrderController : BaseController
             }
 
             //推省上
-            if (!string.IsNullOrEmpty(model.Id) && ("001171".Equals(model.OrgId) || "001178".Equals(model.OrgId)))
+            if (!string.IsNullOrEmpty(model.Id) && (_cityBaseConfiguration.Value.CityProvince.OrgId.Equals(model.OrgId) || _cityBaseConfiguration.Value.CityProvinceAssign.OrgId.Equals(model.OrgId)))
             {
                 var orderDto = _mapper.Map<OrderDto>(order);
                 var supervise = await _orderSuperviseRepository.GetAsync(x => x.Id == model.Id);
@@ -2524,7 +2554,7 @@ public class OrderController : BaseController
             }
 
             //推省上
-            if (!string.IsNullOrEmpty(model.Id) && ("001171".Equals(model.OrgId) || "001178".Equals(model.OrgId)))
+            if (!string.IsNullOrEmpty(model.Id) && (_cityBaseConfiguration.Value.CityProvince.OrgId.Equals(model.OrgId) || _cityBaseConfiguration.Value.CityProvinceAssign.OrgId.Equals(model.OrgId)))
             {
                 var orderDto = _mapper.Map<OrderDto>(order);
                 var urge = await _orderUrgeRepository.GetAsync(x => x.Id == model.Id);
@@ -2849,7 +2879,7 @@ public class OrderController : BaseController
 
         dto.IsCanCancelDelay = order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining && x.ApplyOrgCode == _sessionContext.RequiredOrgId);
 
-        var delayModel = order.OrderDelays.MaxBy(x => x.AfterDelay);
+        var delayModel = order.OrderDelays.MaxBy(x => x.CreationTime);
         if (delayModel != null)
         {
             var workFlow = await _workflowRepository.GetAsync(delayModel.WorkflowId);
@@ -3220,7 +3250,7 @@ public class OrderController : BaseController
             throw new UserFriendlyException($"该工单已开启办理流程, No:{order.No}", "该工单已开启办理流程");
 
         ExpiredTimeWithConfig expiredTimeConfig;
-        if (dto.Workflow.NextHandlers.Any(d => d.Key == "001171" || d.Key == "001178"))
+        if (dto.Workflow.NextHandlers.Any(d => d.Key == _cityBaseConfiguration.Value.CityProvince.OrgId || d.Key == _cityBaseConfiguration.Value.CityProvinceAssign.OrgId))
         {
             var timeResult = await _expireTime.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80, 50);
             expiredTimeConfig = new ExpiredTimeWithConfig
@@ -3235,8 +3265,17 @@ public class OrderController : BaseController
         }
         else
         {
-            //期满时间
-            expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.Adapt<OrderTimeClacInfo>());
+            if (_appOptions.Value.IsZiGong)
+            {
+                expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, order.Adapt<OrderTimeClacInfo>());
+            }
+            else
+            {
+                //期满时间
+                //expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.AcceptTypeCode);
+                expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.Adapt<OrderTimeClacInfo>());
+            }
+
         }
 
         _mapper.Map(expiredTimeConfig, order);
@@ -3298,7 +3337,7 @@ public class OrderController : BaseController
         }
 
         ExpiredTimeWithConfig? expiredTimeConfig = null;
-        if (dto.NextHandlers.Any(d => d.Key == "001171" || d.Key == "001178"))
+        if (dto.NextHandlers.Any(d => d.Key == _cityBaseConfiguration.Value.CityProvince.OrgId || d.Key == _cityBaseConfiguration.Value.CityProvinceAssign.OrgId))
         {
             // var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80, 50);
             var timeResult = await _expireTime.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 45, 80, 50);
@@ -3338,16 +3377,22 @@ public class OrderController : BaseController
         }
         else if (dto.FlowDirection is EFlowDirection.CenterToCenter)
         {
-            // expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, order.AcceptTypeCode);
-            expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, order.Adapt<OrderTimeClacInfo>());
-            order.CenterToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
-                expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime, expiredTimeConfig.NearlyExpiredTimeOne);
-            //TODO发送短信即将超期
-            //_capPublisher.PublishDelay(expiredTimeConfig.NearlyExpiredTime - DateTime.Now, EventNames.HotlineOrderNearlyExpiredTimeSms, new PublishNearlyExpiredTimeSmsDto() { OrderId = order.Id });
+            if (_appOptions.Value.IsZiGong == false)
+            {
+                // expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, order.AcceptTypeCode);
+                expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, order.Adapt<OrderTimeClacInfo>());
+                order.CenterToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
+                    expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime, expiredTimeConfig.NearlyExpiredTimeOne);
+                //TODO发送短信即将超期
+                //_capPublisher.PublishDelay(expiredTimeConfig.NearlyExpiredTime - DateTime.Now, EventNames.HotlineOrderNearlyExpiredTimeSms, new PublishNearlyExpiredTimeSmsDto() { OrderId = order.Id });
+            }
         }
 
-        _mapper.Map(expiredTimeConfig, order);
-        await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+        if (expiredTimeConfig is not null)
+        {
+            _mapper.Map(expiredTimeConfig, order);
+            await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+        }
         //1.是否是判断节点  2.是否存在历史派单节点  3.存在获取上个派单节点  4.不存在走平均派单
         if (dto.BusinessType == EBusinessType.Send)
         {
@@ -3613,8 +3658,7 @@ public class OrderController : BaseController
     public async Task<PagedDto<OrderDto>> QueryWaited([FromQuery] QueryOrderWaitedDto dto)
     {
         var isHandled = dto.IsHandled.HasValue && dto.IsHandled.Value;
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+       
         var isAdmin = _orderDomainService.IsCheckAdmin();
 
         var (total, items) = await _orderRepository
@@ -3709,8 +3753,6 @@ public class OrderController : BaseController
                     ? d is not EOrderStatus.WaitForAccept and not EOrderStatus.BackToUnAccept and not EOrderStatus.SpecialToUnAccept and not EOrderStatus.HandOverToUnAccept
                     : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept or EOrderStatus.SpecialToUnAccept or EOrderStatus.HandOverToUnAccept)
             .ToArray();
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
         var query = _orderRepository.Queryable();
         if (dto.IsHandled.HasValue)
@@ -3790,15 +3832,15 @@ public class OrderController : BaseController
     }
 
     /// <summary>
-    /// 查询中心待办
+    /// 查询中心待办 //TODO
     /// </summary>
     [HttpGet("waited/center")]
     public async Task<PagedDto<OrderDto>> QueryWaitedForCenter([FromQuery] QueryOrderWaitedCenterDto dto)
     {
-        if (dto.EndCreationTime.HasValue)
-            dto.EndCreationTime = dto.EndCreationTime.Value.AddDays(1).AddSeconds(-1);
-        if (dto.StartTimeEnd.HasValue)
-            dto.StartTimeEnd = dto.StartTimeEnd.Value.AddDays(1).AddSeconds(-1);
+        //if (dto.EndCreationTime.HasValue)
+        //    dto.EndCreationTime = dto.EndCreationTime.Value.AddDays(1).AddSeconds(-1);
+        //if (dto.StartTimeEnd.HasValue)
+        //    dto.StartTimeEnd = dto.StartTimeEnd.Value.AddDays(1).AddSeconds(-1);
 
         //var (total, items) = await _orderRepository.Queryable()
         //    //.LeftJoin<WorkflowStep>((d, step) => d.Id == step.ExternalId)
@@ -3846,7 +3888,7 @@ public class OrderController : BaseController
                 d => d.CreationTime >= dto.StCreationTime && d.CreationTime <= dto.EndCreationTime)
             .WhereIF(dto is { StartTimeSt: not null, StartTimeEnd: not null }, d => d.StartTime >= dto.StartTimeSt && d.StartTime <= dto.StartTimeEnd)
             .WhereIF(!string.IsNullOrEmpty(dto.StepName), d => d.ActualHandleStepName == dto.StepName)
-            .WhereIF(!string.IsNullOrEmpty(dto.CurrentHandleOrgName), d => d.CurrentHandleOrgName == dto.CurrentHandleOrgName!)
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
             .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)
             .WhereIF(!string.IsNullOrEmpty(dto.AcceptorName), d => d.AcceptorName!.Contains(dto.AcceptorName!))
             .WhereIF(dto.ExpiredStatus is EExpiredStatus.Normal, d => DateTime.Now < d.NearlyExpiredTime)
@@ -3886,8 +3928,8 @@ public class OrderController : BaseController
     public async Task<Object> QueryWaitedHome([FromQuery] QueryOrderWaitedDto dto)
     {
         var isHandled = dto.IsHandled.HasValue && dto.IsHandled.Value;
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        //if (dto.EndTime.HasValue)
+        //    dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         var (total, items) = await _orderRepository
             .Queryable(hasHandled: isHandled)
             .Includes(d => d.OrderSpecials)
@@ -3990,7 +4032,7 @@ public class OrderController : BaseController
             SendBackOrgName = prevStep.HandlerOrgName, //prevStep!.AcceptorOrgName,
             SendBackStepName = prevStep.Name,
             WorkflowStepSendBackCrTime = currentStep.CreationTime,
-			WorkflowOrgId = _sessionContext.RequiredOrgId,
+            WorkflowOrgId = _sessionContext.RequiredOrgId,
             WorkflowUserId = _sessionContext.RequiredUserId,
             WorkflowRoleIds = _sessionContext.Roles.ToList(),
             Status = order.Status,
@@ -3998,16 +4040,16 @@ public class OrderController : BaseController
         };
         if (_appOptions.Value.IsZiGong && prevStep.BusinessType == EBusinessType.Send)
         {
-	        // 平均派单
-	        var averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]);
-	        if (averageSendOrder)
-	        {
-		        var handler = await _orderDomainService.AverageOrder(HttpContext.RequestAborted);
+            // 平均派单
+            var averageSendOrder = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.AverageSendOrder).SettingValue[0]);
+            if (averageSendOrder)
+            {
+                var handler = await _orderDomainService.AverageOrder(HttpContext.RequestAborted);
                 dto.NextHandlers = new List<FlowStepHandler> { handler };
-			}
+            }
         }
 
-		if (oneSendBack || twoSendBack)
+        if (oneSendBack || twoSendBack)
         {
             var sendBack = await _orderSendBackAuditRepository.Queryable()
                 .Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync();
@@ -4018,15 +4060,15 @@ public class OrderController : BaseController
                 .AnyAsync();
             if (specialAny) throw UserFriendlyException.SameMessage("工单已存在待审批特提信息!");
             if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!");
-            if (oneSendBack && isOrgToCenter &&  _appOptions.Value.IsZiGong)
+            if (oneSendBack && isOrgToCenter && _appOptions.Value.IsZiGong)
             {
-	            if (order.SendBackAuditEndTime.HasValue && order.SendBackAuditEndTime.Value < DateTime.Now )
-		            throw UserFriendlyException.SameMessage("工单截至退回时间【" + order.SendBackAuditEndTime.Value.ToString("yyyy-MM-dd HH:mm:ss") + "】,无法进行退回!");
-				var sendBackAgain = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.IsReturnAgain == true).AnyAsync();
-	            if (sendBackAgain)
-		            throw UserFriendlyException.SameMessage("工单已不允许退回!");
-			}                
-			if ((oneSendBack && isOrgToCenter) || (twoSendBack && isSecondToFirstOrgLevel))
+                if (order.SendBackAuditEndTime.HasValue && order.SendBackAuditEndTime.Value < DateTime.Now)
+                    throw UserFriendlyException.SameMessage("工单截至退回时间【" + order.SendBackAuditEndTime.Value.ToString("yyyy-MM-dd HH:mm:ss") + "】,无法进行退回!");
+                var sendBackAgain = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.IsReturnAgain == false).AnyAsync();
+                if (sendBackAgain)
+                    throw UserFriendlyException.SameMessage("工单已不允许退回!");
+            }
+            if ((oneSendBack && isOrgToCenter) || (twoSendBack && isSecondToFirstOrgLevel))
             {
 
                 await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { Status = EOrderStatus.SendBackAudit })
@@ -4038,7 +4080,7 @@ public class OrderController : BaseController
                 audit.AuditUser = "默认通过";
                 audit.AuditTime = DateTime.Now;
                 dto.ExpiredTime = order.ExpiredTime;
-				var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+                var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
                 var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter
                     ? EProcessType.Zhiban
                     : EProcessType.Jiaoban;
@@ -4520,7 +4562,24 @@ public class OrderController : BaseController
             //if (dto.AlterTime)
             //{
             // var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
-            var expiredTime = await _expireTime.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
+
+            ExpiredTimeWithConfig? expiredTime = null;
+            if (_appOptions.Value.IsZiGong)
+            {
+                if (dto.FlowDirection != null)
+                {
+                    expiredTime = await _expireTime.CalcExpiredTime(DateTime.Now, dto.FlowDirection.Value, order.Adapt<OrderTimeClacInfo>());
+                }
+                else
+                {
+                    expiredTime = await _expireTime.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
+                }
+            }
+            else
+            {
+                expiredTime = await _expireTime.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
+            }
+
             var processType = dto.FlowDirection is EFlowDirection.OrgToCenter or EFlowDirection.CenterToCenter or EFlowDirection.FiledToCenter
                 ? EProcessType.Zhiban
                 : EProcessType.Jiaoban;
@@ -4566,9 +4625,9 @@ public class OrderController : BaseController
                 }
             }
 
-            if (order != null && ("001171".Equals(model.OrgId) ||
-                                  "001178".Equals(model.OrgId) ||
-                                  "001180".Equals(model.OrgId)))
+            if (order != null && (_cityBaseConfiguration.Value.CityProvince.OrgId.Equals(model.OrgId) ||
+                                  _cityBaseConfiguration.Value.CityProvinceAssign.OrgId.Equals(model.OrgId) || _cityBaseConfiguration.Value.CityEnterprise.OrgId.Equals(model.OrgId) ||
+                                  _cityBaseConfiguration.Value.PublicSecurity.OrgId.Equals(model.OrgId)))
             {
                 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
                     new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(model) },
@@ -4599,7 +4658,6 @@ public class OrderController : BaseController
     /// </summary>
     /// <param name="dtos"></param>
     /// <returns></returns>
-    [Permission(EPermission.ApplySpecial)]
     [HttpPost("re_transact")]
     [LogFilter("工单重办")]
     public async Task Add([FromBody] OrderReTransactDto dto)
@@ -4715,7 +4773,15 @@ public class OrderController : BaseController
             //}
 
             var reTransactNum = order.ReTransactNum.HasValue ? order.ReTransactNum.Value + 1 : 1;
-            var Status = model.StepType == EStepType.Start ? EOrderStatus.BackToUnAccept : EOrderStatus.SendBack;
+            var orderStatus = EOrderStatus.SendBack;
+            var orderStartStatus = EOrderStatus.BackToUnAccept;
+
+			if (_appOptions.Value.IsZiGong)
+            {
+	            orderStatus = model.SpecialType == ESpecialType.SendBack ? EOrderStatus.SendBack : EOrderStatus.Special;
+	            orderStartStatus = model.SpecialType == ESpecialType.SendBack ? EOrderStatus.BackToUnAccept : EOrderStatus.SpecialToUnAccept;
+			}
+			var Status = model.StepType == EStepType.Start ? orderStartStatus : orderStatus;
             await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType, ReTransactNum = reTransactNum, Status = Status }).Where(o => o.Id == order.Id)
                 .ExecuteCommandAsync(HttpContext.RequestAborted);
 
@@ -4812,9 +4878,9 @@ public class OrderController : BaseController
                 }
             }
 
-            if (order != null && ("001171".Equals(special.OrgId) ||
-                                  "001178".Equals(special.OrgId) ||
-                                  "001180".Equals(special.OrgId)))
+            if (order != null && (_cityBaseConfiguration.Value.CityProvince.OrgId.Equals(special.OrgId) ||
+                                  _cityBaseConfiguration.Value.CityProvinceAssign.OrgId.Equals(special.OrgId) || _cityBaseConfiguration.Value.CityEnterprise.OrgId.Equals(special.OrgId) ||
+                                  _cityBaseConfiguration.Value.PublicSecurity.OrgId.Equals(special.OrgId)))
             {
                 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
                     new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(special) },
@@ -4925,9 +4991,9 @@ public class OrderController : BaseController
                     }
                 }
 
-                if (order != null && ("001171".Equals(special.OrgId) ||
-                                      "001178".Equals(special.OrgId) ||
-                                      "001180".Equals(special.OrgId)))
+                if (order != null && (_cityBaseConfiguration.Value.CityProvince.OrgId.Equals(special.OrgId) ||
+                                      _cityBaseConfiguration.Value.CityProvinceAssign.OrgId.Equals(special.OrgId) || _cityBaseConfiguration.Value.CityEnterprise.OrgId.Equals(special.OrgId) ||
+                                      _cityBaseConfiguration.Value.PublicSecurity.OrgId.Equals(special.OrgId)))
                 {
                     await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowRecalled,
                         new PublishSpecialDto { Order = _mapper.Map<OrderDto>(order), Special = _mapper.Map<OrderSpecialDto>(special) },
@@ -5129,7 +5195,7 @@ public class OrderController : BaseController
             SpecialTimeType = EnumExts.GetDescriptions<ETimeType>(),
             SpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason),
             InstaShotSpecialReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.InstaShotSpecialReason),
-			Step = step,
+            Step = step,
             BaseTypeId = baseTypeId
         };
         return rsp;
@@ -5144,7 +5210,7 @@ public class OrderController : BaseController
     {
         var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
         var isInstaShot = order.SourceChannel.Contains("随手拍");
-		List<Kv> orgs = new();
+        List<Kv> orgs = new();
         if (order == null) throw UserFriendlyException.SameMessage("无效工单信息!");
         //中心会签调取方法
         var org = await _workflowDomainService.GetLevelOneOrgsAsync(order.WorkflowId, HttpContext.RequestAborted);
@@ -5155,7 +5221,7 @@ public class OrderController : BaseController
         {
             SpecialTimeType = EnumExts.GetDescriptions<ETimeType>(),
             SpecialReason = isInstaShot ? _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.InstaShotSpecialReason) : _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SpecialReason),
-            ReTransactErrorType =  _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ReTransactErrorType),
+            ReTransactErrorType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ReTransactErrorType),
             Step = step,
             Orgs = orgs,
         };

+ 3 - 2
src/Hotline.Api/Controllers/OrderProvinceZmhdController.cs

@@ -50,7 +50,7 @@ namespace Hotline.Api.Controllers
             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.ProvinceNo), p => p.ReceiveProvinceNo == 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)
@@ -102,7 +102,7 @@ namespace Hotline.Api.Controllers
             OrderProvinceZmhd orderProvinceZmhd = new()
             {
                 No = order.No,
-                ProvinceNo = order.ProvinceNo,
+                ProvinceNo = order.ReceiveProvinceNo,
                 OrderId = order.Id,
                 Title = order.Title,
                 AnswerTime = order.ActualHandleTime,
@@ -133,6 +133,7 @@ namespace Hotline.Api.Controllers
 
             //推送数据
             var publishPublishOrder = _mapper.Map<PublicOrderProvinceZmhdDto>(orderProvinceZmhd);
+            publishPublishOrder.ProvinceNo = order.ReceiveProvinceNo;
             await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderProvinceZmhd, publishPublishOrder);
         }
 

+ 10 - 4
src/Hotline.Api/Controllers/SettingController.cs

@@ -180,13 +180,19 @@ namespace Hotline.Api.Controllers
         [HttpPost("setdaysettings")]
         public async Task SetDaySettings([FromBody]SetDaySettingsRequest request)
         {
-            List<DaySetting> daysettings = new List<DaySetting>();
             foreach (var item in request.list)
             {
-                daysettings.Add(new DaySetting() { Day = item, IsWorkDay = request.isWorkDay });
+                var day = await _daysettingRepository.GetAsync(x => x.Day.Date == item.Date, HttpContext.RequestAborted);
+                if (day != null)
+                {
+                    day.IsWorkDay = request.isWorkDay;
+                    await _daysettingRepository.UpdateAsync(day, HttpContext.RequestAborted);
+                }
+                else
+                {
+                    await _daysettingRepository.AddAsync(new DaySetting() { Day = item, IsWorkDay = request.isWorkDay },HttpContext.RequestAborted);
+                }
             }
-
-            await _daysettingRepository.AddRangeAsync(daysettings);
         }
 
         #endregion

+ 21 - 10
src/Hotline.Api/Controllers/TestController.cs

@@ -125,9 +125,10 @@ public class TestController : BaseController
     //private readonly ITypedCache<List<User>> _cache;
     //private readonly ICacheManager<User> _cache;
     private readonly ICalcExpireTime _expireTime;
+    private readonly IOptions<CityBaseConfiguration> _cityBaseConfiguration;
 
 
-    public TestController(
+	public TestController(
         //INewRockClient client,
         ILogger<TestController> logger,
         //IAuthorizeGenerator authorizeGenerator,
@@ -146,7 +147,7 @@ public class TestController : BaseController
         IDistributedLock distributedLock,
         IRepository<OrderUrge> orderUrgeRepository,
         IRepositoryTextSearch<OrderTs> repositoryts,
-        //ITimeLimitDomainService timeLimitDomainService,
+        ITimeLimitDomainService timeLimitDomainService,
         IWfModuleDomainService wfModuleDomainService,
         IDaySettingRepository daySettingRepository,
         //ITrClient trClient,
@@ -175,8 +176,10 @@ IRepository<Hotspot> hotspotRepository,
 IOrderDomainService orderDomainService,
 ICallApplication callApplication,
         IOptionsSnapshot<AppConfiguration> appOptions,
-        ISystemSettingCacheManager systemSettingCacheManager
-        )
+        ISystemSettingCacheManager systemSettingCacheManager,
+        ICalcExpireTime expireTime,
+        IOptions<CityBaseConfiguration> cityBaseConfiguration
+		)
     {
         _logger = logger;
         //_authorizeGenerator = authorizeGenerator;
@@ -193,7 +196,7 @@ ICallApplication callApplication,
         _distributedLock = distributedLock;
         _orderUrgeRepository = orderUrgeRepository;
         _repositoryts = repositoryts;
-        //_timeLimitDomainService = timeLimitDomainService;
+        _timeLimitDomainService = timeLimitDomainService;
         _wfModuleDomainService = wfModuleDomainService;
         _daySettingRepository = daySettingRepository;
         //_trClient = trClient;
@@ -224,7 +227,9 @@ ICallApplication callApplication,
         _callApplication = callApplication;
         _appOptions = appOptions;
         _systemSettingCacheManager = systemSettingCacheManager;
-    }
+        _expireTime = expireTime;
+        _cityBaseConfiguration = cityBaseConfiguration;
+	}
 
 
     [HttpGet("time")]
@@ -278,6 +283,8 @@ ICallApplication callApplication,
         //var r = await _aiVisitService.QueryAiVisitTaskResult(batchId, DateTime.Parse("2024-07-28"), DateTime.Parse("2024-08-01"), HttpContext.RequestAborted);
 
         //var r = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, batchId);
+        var r = _timeLimitDomainService.CalcEndTime(DateTime.Parse("2024-09-12 14:45:47"), Share.Enums.Settings.ETimeType.WorkDay, 2, 80, 50);
+
 
         return OpenResponse.Ok(DateTime.Now.ToString("F"));
     }
@@ -685,10 +692,14 @@ ICallApplication callApplication,
     [HttpGet("t5")]
     public async Task<string> GetUserAllowAnonymous()
     {
-        var users = await _userRepository.Queryable()
-            .FirstAsync(d => d.Name == "xf", HttpContext.RequestAborted);
-        return users.Id;
-    }
+        //var users = await _userRepository.Queryable()
+        //    .FirstAsync(d => d.Name == "xf", HttpContext.RequestAborted);
+        //return users.Id;
+        var b = _cityBaseConfiguration.Value;
+
+		var a = await _expireTime.WorkDay_ZG(DateTime.Now);
+        return string.Empty;
+	}
 
     [HttpGet("t6")]
     public async Task<string> GetUserWithAuth()

+ 19 - 20
src/Hotline.Api/Controllers/WebPortalController.cs

@@ -1,32 +1,26 @@
-using DotNetCore.CAP;
+using Hotline.Application.Bulletin;
+using Hotline.Application.Orders;
 using Hotline.Article;
+using Hotline.Caching.Interfaces;
 using Hotline.Orders;
+using Hotline.Push.Notifies;
+using Hotline.Settings;
 using Hotline.Settings.Hotspots;
-using Hotline.Share.Dtos.Push.FWMessage;
-using Hotline.Share.Dtos.Push;
+using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
+using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.WebPortal;
 using Hotline.Share.Enums.Order;
+using Hotline.Share.Enums.Push;
 using Hotline.WebPortal;
 using MapsterMapper;
+using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
+using XF.Domain.Authentications;
+using XF.Domain.Cache;
 using XF.Domain.Filters;
 using XF.Domain.Repository;
-using XF.Domain.Cache;
-using Hotline.Push.Notifies;
-using Hotline.Share.Enums.Push;
-using StackExchange.Redis;
-using MediatR;
-using XF.Domain.Constants;
-using Hotline.Caching.Interfaces;
-using Hotline.Application.Orders;
-using XF.Domain.Authentications;
-using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
-using Hotline.Share.Dtos.Order;
-using Org.BouncyCastle.Ocsp;
-using System.Threading;
-using Hotline.Settings;
 
 namespace Hotline.Api.Controllers
 {
@@ -47,7 +41,7 @@ namespace Hotline.Api.Controllers
         private readonly IOrderApplication _orderApplication;
         private readonly ISessionContext _sessionContext;
         private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
-
+        private readonly IBulletinApplication _bulletinApplication;
 
         public WebPortalController(IMapper mapper,
             IMediator mediator,
@@ -63,7 +57,8 @@ namespace Hotline.Api.Controllers
            IRepository<OrderVisit> orderVisitRepository,
            IOrderApplication orderApplication,
            ISessionContext sessionContext,
-            IRepository<OrderVisitDetail> orderVisitDetailRepository
+            IRepository<OrderVisitDetail> orderVisitDetailRepository,
+            IBulletinApplication bulletinApplication
             )
         {
             _mapper = mapper;
@@ -81,6 +76,7 @@ namespace Hotline.Api.Controllers
             _orderApplication = orderApplication;
             _sessionContext = sessionContext;
             _orderVisitDetailRepository = orderVisitDetailRepository;
+            _bulletinApplication = bulletinApplication;
         }
 
         #region 通知
@@ -183,6 +179,9 @@ namespace Hotline.Api.Controllers
                     WNED_VideoUrl = "",
                     NoticeContent = data.Content
                 };
+
+                if (data != null && !string.IsNullOrEmpty(data.Content))
+                    data.Content = _bulletinApplication.GetSiteUrls(data.Content);
             }
             else
                 detailsDto = new();
@@ -654,7 +653,7 @@ namespace Hotline.Api.Controllers
         [HttpPost("getorderid")]
         public async Task<OpenResponse> GetOrderId([FromBody] GetOrderCodePwd dto)
         {
-            var data = await _orderRepository.GetAsync(p => p.No == dto.OrderNo && p.Password == dto.Pwd, HttpContext.RequestAborted);
+            var data = await _orderRepository.GetAsync(p => p.No == dto.OrderNo && p.Password == dto.Pwd && p.Status > EOrderStatus.Published, HttpContext.RequestAborted);
             return OpenResponse.Ok(WebPortalDeResponse<string>.Success(data?.Id));
         }
 

+ 6 - 0
src/Hotline.Api/Program.cs

@@ -11,6 +11,12 @@ try
 
     var builder = WebApplication.CreateBuilder(args);
 
+    builder.WebHost.ConfigureKestrel(serverOptions =>
+    {
+        serverOptions.Limits.MaxConcurrentConnections = 5000;
+        serverOptions.Limits.MaxConcurrentUpgradedConnections = 5000;
+    });
+
     builder.Host
         .ConfigureAppConfiguration((hostBuilderContext, configBuilder) =>
         {

+ 1 - 0
src/Hotline.Api/Realtimes/HotlineHub.cs

@@ -108,6 +108,7 @@ namespace Hotline.Api.Realtimes
         public async Task JoinGroupUnauthAsync(JoinGroupDto dto)
         {
             CheckIfConnected();
+            await Groups.RemoveFromGroupAsync(Context.ConnectionId, dto.GroupName);
             await Groups.AddToGroupAsync(Context.ConnectionId, dto.GroupName);
             await Clients.Group(dto.GroupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {dto.GroupName}.");
         }

+ 4 - 3
src/Hotline.Api/StartupExtensions.cs

@@ -57,10 +57,11 @@ internal static class StartupExtensions
         var callCenterConfiguration = callCenterConfigurationSection.Get<CallCenterConfiguration>();
         services.Configure<CallCenterConfiguration>(d => callCenterConfigurationSection.Bind(d));
 
-        //services.Configure<SendSmsConfiguration>(d => configuration.GetSection("SendSms").Bind(d));
+        services.Configure<CityBaseConfiguration>(d => configuration.GetSection(nameof(CityBaseConfiguration)).Bind(d));
+		//services.Configure<SendSmsConfiguration>(d => configuration.GetSection("SendSms").Bind(d));
 
-        // Add services to the container.
-        services
+		// Add services to the container.
+		services
             .BatchInjectServices(d =>
             {
                 var attr = d.GetCustomAttribute(typeof(InjectionAttribute)) as InjectionAttribute;

+ 10 - 0
src/Hotline.Api/StartupHelper.cs

@@ -312,6 +312,16 @@ namespace Hotline.Api
                             .StartNow()
                             .WithCronSchedule("0/10 * * * * ?")
                         );
+
+                        var getCallSatisfactionJobKey = new JobKey(nameof(XingTangCallSatisfactionSyncJob));
+                        d.AddJob<XingTangCallSatisfactionSyncJob>(getCallSatisfactionJobKey);
+                        d.AddTrigger(t => t
+                            .WithIdentity("get-callsatisfaction-trigger")
+                            .ForJob(getCallSatisfactionJobKey)
+                            .StartNow()
+                            .WithCronSchedule("0/30 * * * * ?")
+                        );
+
                         break;
                 }
             });

+ 35 - 3
src/Hotline.Api/config/appsettings.Development.json

@@ -1,4 +1,36 @@
 {
+  "CityBaseConfiguration": {
+    "CityProvince": {
+      "UserId": "03aba148-e7b1-cd03-bf00-3a1177930508",
+      "UserName": "省12345平台",
+      "OrgId": "001171",
+      "OrgName": "省12345平台"
+    },
+    "CityProvinceAssign": {
+      "UserId": "",
+      "UserName": "",
+      "OrgId": "001178",
+      "OrgName": "省12345交办"
+    },
+    "PublicSecurity": {
+      "UserId": "e90501d7-c453-e18a-f1fa-3a1177930699",
+      "UserName": "市公安局110",
+      "OrgId": "001180",
+      "OrgName": "市公安局110"
+    },
+    "CityEnterprise": {
+      "UserId": "ce42562c-afc1-764b-1dc8-3a1177930346",
+      "UserName": "联系服务企业",
+      "OrgId": "001181",
+      "OrgName": "联系服务企业"
+    },
+    "ComprehensiveTreatment": {
+      "UserId": "d4cb7151-41fa-a810-6c1e-3a117792fc0c",
+      "UserName": "综治平台",
+      "OrgId": "001143",
+      "OrgName": "综治平台"
+    }
+  },
   "AllowedHosts": "*",
   "AppConfiguration": {
     "AppScope": "ZiGong",
@@ -59,13 +91,13 @@
     }
   },
   "ConnectionStrings": {
-    "Hotline": "PORT=5432;DATABASE=hotline_dev;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;"
   },
   "Cache": {
     "Host": "110.188.24.182",
     "Port": 50179,
     "Password": "fengwo123!$!$",
-    "Database": 5 //release:3, dev:5
+    "Database": 3 //release:3, dev:5
   },
   "Swagger": true,
   "Cors": {
@@ -123,7 +155,7 @@
   "FwClient": {
     "ClientId": "hotline",
     "ClientSecret": "08db29cc-0da0-4adf-850c-1b2689bd535d"
-  },
+  }
   //"ConfigCenter": {
   //  "ServerAddresses": [ "http://110.188.24.28:8848" ],
   //  "Namespace": "17503980-9b0d-4d3e-8e35-c842c41fb888", //debug

+ 6 - 0
src/Hotline.Application.Tests/Application/OrderApplicationTest.cs

@@ -25,12 +25,18 @@ public class OrderApplicationTest
     [Theory]
     [InlineData(1)]
     [InlineData(2)]
+    [InlineData(3)]
+    [InlineData(4)]
+    [InlineData(5)]
+    [InlineData(6)]
+    [InlineData(7)]
     public async Task VisitPushSMS_Test(int count)
     {
         var orderVisit = await _orderVisitRepository.Queryable()
             .Where(m => m.VisitState == EVisitState.WaitForVisit)
             .OrderByDescending(m => m.CreationTime)
             .FirstAsync();
+        orderVisit.ShouldNotBeNull("缺少 回访单 (order_visit) VisitState = 10 的数据.");
         var dto = new VisitSmsInDto
         {
             Ids = new List<string> { orderVisit.Id }

+ 43 - 0
src/Hotline.Application.Tests/Domain/LuZhouExpireTimeTest.cs

@@ -0,0 +1,43 @@
+using Hotline.Settings.TimeLimitDomain;
+using Hotline.Settings;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+using Hotline.Orders;
+using Hotline.Share.Dtos.Settings;
+using Hotline.Share.Enums.Settings;
+using Shouldly;
+
+namespace Hotline.Application.Tests.Domain;
+public class LuZhouExpireTimeTest
+{
+    private readonly LuZhouExpireTimeLimit _calcExpireTime;
+    private readonly IRepository<Order> _orderRepository;
+    private readonly IRepository<TimeLimitSetting> _timeLimitSettingRepository;
+
+    public LuZhouExpireTimeTest(IRepository<TimeLimitSetting> timeLimitSettingRepository, IRepository<Order> orderRepository, LuZhouExpireTimeLimit calcExpireTime)
+    {
+        _timeLimitSettingRepository = timeLimitSettingRepository;
+        _orderRepository = orderRepository;
+        _calcExpireTime = calcExpireTime;
+    }
+
+    [Theory]
+    [InlineData("2024-09-04 14:00:00", 2, "10", "2024-09-06 14:00:00", "2024/9/6 10:24:00", "2024/9/5 14:00:00", "2个工作日")]
+    [InlineData("2024-09-04 14:01:01", 3, "10", "2024-09-09 14:01:01", "2024/9/6 17:37:01", "2024/9/6 9:31:01", "3个工作日")]
+    public async Task CalcEndTime_Test(string begin, int count, string busCode, string expiredTime, string nearlyExpiredTime, string nearlyExpiredTimeOne, string timeText)
+    {
+        var beginTime = DateTime.Parse(begin);
+        var result = await _calcExpireTime.CalcEndTime(beginTime, new TimeConfig(count, ETimeType.WorkDay), busCode);
+        result.ShouldNotBeNull();
+        result.ExpiredTime.ShouldBe(DateTime.Parse(expiredTime));
+        result.NearlyExpiredTime.ShouldBe(DateTime.Parse(nearlyExpiredTime));
+        result.NearlyExpiredTimeOne.ShouldBe(DateTime.Parse(nearlyExpiredTimeOne));
+        result.Count.ShouldBe(count);
+        result.TimeText.ShouldBe(timeText);
+    }
+}
+

+ 14 - 0
src/Hotline.Application.Tests/Domain/ZiGongExpireTimeTest.cs

@@ -51,6 +51,7 @@ public class ZiGongExpireTimeTest
     [InlineData("企业投诉件单元测试", "2024-09-05 14:00:00", "CenterToOrg", "2024-09-09 14:00:00")]
     [InlineData("四川省12345咨询件单元测试", "2024-09-05 14:00:00", "CenterToOrg", "2024-09-06 14:00:00")]
     [InlineData("四川省12345建议件单元测试", "2024-09-05 14:00:00", "CenterToOrg", "2024-09-10 14:00:00")]
+    [InlineData("中心到中心24小时", "2024-09-12 14:00:00", "CenterToCenter", "2024-09-13 14:00:00")]
     public async Task CalcExpiredTime_Test(string title, string beginTxt, string flowTxt, string expected)
     {
         var beginTime = DateTime.Parse(beginTxt);
@@ -63,6 +64,19 @@ public class ZiGongExpireTimeTest
         time.TimeText.ShouldBe(order.Content, $"{title} 内容结果比对失败 AcceptTypeCode:{order.AcceptTypeCode}");
     }
 
+    [Theory]
+    [InlineData("求助三个工作日", "2024-09-12 22:01:28", "CenterToOrg", "2024-09-20 08:30:00")]
+    public async Task CalcExpiredTime_Release_Test(string title, string beginTxt, string flowTxt, string expected)
+    {
+        var beginTime = DateTime.Parse(beginTxt);
+        var order = await _orderRepository.Queryable().Where(m => m.Title == title).FirstAsync();
+        order.ShouldNotBeNull($"{title} 测试数据不存在");
+        Enum.TryParse(flowTxt, out EFlowDirection flow);
+        var time = await _ziGongExpireTimeLimit.CalcExpiredTime(beginTime, flow, order.Adapt<OrderTimeClacInfo>());
+        time.ShouldNotBeNull();
+        time.ExpiredTime.ShouldBe(DateTime.Parse(expected), $"{title} 期满时间错误 AcceptTypeCode:{order.AcceptTypeCode}");
+    }
+
     public async Task InitOrderData(string orderId)
     {
         var order = await _orderRepository.Queryable().Where(m => m.Id == orderId).FirstAsync();

+ 2 - 1
src/Hotline.Application.Tests/ReadME.md

@@ -1,2 +1,3 @@
 ## 运行测试
-dotnet test --filter CalcEndTime_Test
+dotnet test --filter CalcEndTime_Test
+dotnet test --filter ZiGongExpireTimeTest.CalcExpiredTime_Test

+ 10 - 4
src/Hotline.Application.Tests/Repository/OrderVisitRepositoryTest.cs

@@ -27,22 +27,28 @@ public class OrderVisitRepositoryTest
     [Theory]
     [InlineData("4", "SMSUnsatisfied", "2" , "不满意")]
     [InlineData("1", "Visited", "5", "非常满意")]
+    [InlineData("非常满意", "Visited", "5", "非常满意")]
+    [InlineData("满意", "Visited", "4", "满意")]
+    [InlineData("一般", "Visited", "4", "满意")]
+    [InlineData("不满意", "SMSUnsatisfied", "2", "不满意")]
+    [InlineData("非常不满意", "SMSUnsatisfied", "2", "不满意")]
     public async Task UpdateSmsReply_Test(string content, string visitState, string orgResuktKey,  string orgResuktValue)
     {
         var visit = await _orderVisitRepository.Queryable()
             .Where(m => m.VisitState == EVisitState.SMSVisiting)
             .OrderByDescending(m => m.CreationTime)
             .FirstAsync();
+        visit.ShouldNotBeNull("缺少测试数据");
 
-        var dto = new PushReceiveMessageDto { ExternalId = visit.Id, IsSmsReply = true, SmsReplyContent = content };
-        var message = new Message();
+        var message = new Message { ExternalId = visit.Id, IsSmsReply = true, SmsReplyContent = content };
+        var dto = new PushReceiveMessageDto();
         await _orderVisitRepository.UpdateSmsReplyAsync(dto, message);
         visit = _orderVisitRepository.Get(visit.Id);
         visit.VisitState.ShouldBe(visitState.ToEnum<EVisitState>());
-        visit.NowEvaluate.Key.ShouldBe(content);
+        visit.NowEvaluate.Key.ShouldBe(orgResuktKey);
         visit.NowEvaluate.Value.ShouldBe(orgResuktValue);
 
-        if (content == "4" || content == "5")
+        if (content == "4" || content == "5" || content == "不满意" || content == "非常不满意")
             visit.VisitType.ShouldBeNull();
 
         await _orderVisitDetailRepository.Queryable()

+ 4 - 2
src/Hotline.Application.Tests/Startup.cs

@@ -88,10 +88,11 @@ public class Startup
             var callCenterConfigurationSection = configuration.GetRequiredSection(nameof(CallCenterConfiguration));
             var callCenterConfiguration = callCenterConfigurationSection.Get<CallCenterConfiguration>();
 
-            services.Configure<AppConfiguration>(d => appConfigurationSection.Bind(d));
+			services.Configure<AppConfiguration>(d => appConfigurationSection.Bind(d));
             services.Configure<IdentityConfiguration>(d => configuration.GetSection(nameof(IdentityConfiguration)).Bind(d));
+            services.Configure<CityBaseConfiguration>(d => configuration.GetSection(nameof(CityBaseConfiguration)).Bind(d));
 
-            services.RegisterMapper();
+			services.RegisterMapper();
 
             //sqlsugar
             services.AddSqlSugar(configuration);
@@ -143,6 +144,7 @@ public class Startup
             services.AddScoped<ExpireTimeFactory>();
             services.AddScoped<YiBinExpireTimeLimit>();
             services.AddScoped<ZiGongExpireTimeLimit>();
+            services.AddScoped<LuZhouExpireTimeLimit>();
             services.AddScoped<IMediator, MediatorMock>();
 
             ServiceLocator.Instance = services.BuildServiceProvider();

+ 5 - 7
src/Hotline.Application/Bigscreen/SeatStateDataService.cs

@@ -12,8 +12,6 @@ namespace Hotline.Application.Bigscreen
 {
 	public  class SeatStateDataService: ISeatStateDataService , IScopeDependency
 	{
-
-		public static DateTime now = DateTime.Now.Date;
 		private readonly IRepository<TrCallRecord> _callRepository;
 		public SeatStateDataService(IRepository<TrCallRecord> callRepository) {
 			_callRepository= callRepository;
@@ -27,7 +25,7 @@ namespace Hotline.Application.Bigscreen
 				timeList.Add(time);
 			}
 			var call24 = await _callRepository.Queryable()
-				.Where(x => x.CreatedTime.Date == now
+				.Where(x => x.CreatedTime.Date == DateTime.Now.Date
 					&& x.CallOrderType == Share.Enums.CallCenter.ECallOrderType.Order
 				)
 				.Select(x => new { time = x.CreatedTime.ToString("hh"), x.CallDirection }).MergeTable()
@@ -69,8 +67,8 @@ namespace Hotline.Application.Bigscreen
 		public async Task<object> GetCallList(CancellationToken stoppingToken)
 		{
 			var callList = await _callRepository.Queryable()
-				.Where(x => x.CreatedTime.Date == now
-					&& x.CallOrderType == Share.Enums.CallCenter.ECallOrderType.Order
+				.Where(x => x.CreatedTime.Date == DateTime.Now.Date
+                    && x.CallOrderType == Share.Enums.CallCenter.ECallOrderType.Order
 				)
 				.Select(x => new
 				{
@@ -92,8 +90,8 @@ namespace Hotline.Application.Bigscreen
 				timeList.Add(time);
 			}
 			var callAverage = await _callRepository.Queryable()
-				.Where(x => x.CreatedTime.Date == now
-					&& x.CallOrderType == Share.Enums.CallCenter.ECallOrderType.Order
+				.Where(x => x.CreatedTime.Date == DateTime.Now.Date
+                    && x.CallOrderType == Share.Enums.CallCenter.ECallOrderType.Order
 				)
 				.Select(x => new { time = x.CreatedTime.ToString("hh"), x.CallDirection }).MergeTable()
 				.GroupBy(x => x.time)

+ 67 - 0
src/Hotline.Application/Bulletin/BulletinApplication.cs

@@ -0,0 +1,67 @@
+using Hotline.Configurations;
+using Microsoft.Extensions.Options;
+using System.Text;
+using System.Text.RegularExpressions;
+using XF.Domain.Dependency;
+
+namespace Hotline.Application.Bulletin
+{
+    public class BulletinApplication : IBulletinApplication, IScopeDependency
+    {
+        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
+
+        public BulletinApplication(IOptionsSnapshot<AppConfiguration> appOptions)
+        {
+            _appOptions = appOptions;
+        }
+
+        /// <summary>
+        /// 处理通知公告图片附件路径
+        /// </summary>
+        /// <param name="sHtmlText"></param>
+        /// <returns></returns>
+        public string GetSiteUrls(string sHtmlText)
+        {
+            sHtmlText = sHtmlText.Replace("&lt;", "<").Replace("&gt;", ">");
+
+            //临时内容
+            System.Text.StringBuilder sb = new StringBuilder();
+            sb.Append(sHtmlText);
+            // 定义正则表达式用来匹配 img 标签
+            Regex regImg = new Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);
+            // 搜索匹配的字符串
+            MatchCollection matches = regImg.Matches(sHtmlText);
+
+            // 定义正则表达式用来匹配 video 标签
+            Regex regvideo = new Regex(@"<video\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);
+            // 搜索匹配的字符串
+            MatchCollection matchesvideo = regvideo.Matches(sHtmlText);
+
+
+            // 获取服务器地址配置 
+            string strSiteUrl = _appOptions.Value.OldFilesUrls;
+         
+            // 取得匹配项列表 视频
+            foreach (Match match in matchesvideo)
+            {
+                if (-1 == match.Groups["imgUrl"].Value.IndexOf("http"))
+                {
+                    sb.Replace(match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
+                    sb.Replace(strSiteUrl + strSiteUrl + match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
+                }
+            }
+
+            // 取得匹配项列表
+            foreach (Match match in matches)
+            {
+                if (-1 == match.Groups["imgUrl"].Value.IndexOf("http"))
+                {
+                    sb.Replace(match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
+                    sb.Replace(strSiteUrl + strSiteUrl + match.Groups["imgUrl"].Value, strSiteUrl + match.Groups["imgUrl"].Value);
+                }
+            }
+
+            return sb.ToString();
+        }
+    }
+}

+ 18 - 0
src/Hotline.Application/Bulletin/IBulletinApplication.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Bulletin
+{
+    public interface IBulletinApplication
+    {
+        /// <summary>
+        /// 处理通知公告图片附件路径
+        /// </summary>
+        /// <param name="sHtmlText"></param>
+        /// <returns></returns>
+        string GetSiteUrls(string sHtmlText);
+    }
+}

+ 32 - 6
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -30,6 +30,8 @@ using Hotline.Share.Dtos.File;
 using Microsoft.Extensions.Logging;
 using System.Text;
 using System.Diagnostics;
+using Hotline.Configurations;
+using Microsoft.Extensions.Options;
 using NPOI.SS.Formula.Functions;
 
 namespace Hotline.Application.FlowEngine;
@@ -57,6 +59,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     private readonly IFileRepository _fileRepository;
     private readonly ILogger<WorkflowApplication> _logger;
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+    private readonly IOptions<CityBaseConfiguration> _cityBaseConfiguration;
 
 	public WorkflowApplication(
         IDefinitionDomainService definitionDomainService,
@@ -76,7 +79,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         ISessionContext sessionContext,
         IMapper mapper,
         IFileRepository fileRepository,
-        ILogger<WorkflowApplication> logger)
+        ISystemSettingCacheManager systemSettingCacheManager,
+		ILogger<WorkflowApplication> logger,
+        IOptions<CityBaseConfiguration> cityBaseConfiguration)
     {
         _definitionDomainService = definitionDomainService;
         _workflowDomainService = workflowDomainService;
@@ -96,7 +101,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         _mapper = mapper;
         _fileRepository = fileRepository;
         _logger = logger;
-    }
+        _systemSettingCacheManager = systemSettingCacheManager;
+        _cityBaseConfiguration = cityBaseConfiguration;
+	}
 
     public async Task<string> StartWorkflowAsync(StartWorkflowDto dto, ISessionContext current, string externalId,
         DateTime? expiredTime, CancellationToken cancellationToken = default)
@@ -325,8 +332,27 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
         if (targetStepDefine.StepType is EStepType.End)
             throw UserFriendlyException.SameMessage("结束节点不支持撤回");
-        //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
-        var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
+		//var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
+		var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
+		if (targetStep is null)
+			throw UserFriendlyException.SameMessage("该流程尚未流转至该节点");
+
+		///退回到派单组 没有下一步办理人 获取之前节点办理人
+		if (!dto.NextHandlers.Any())
+		{
+			dto.NextHandlers.Add(new FlowStepHandler()
+			{
+				UserId = targetStep.HandlerId,
+				Username = targetStep.HandlerName,
+				OrgId = targetStep.HandlerOrgId,
+				OrgName = targetStep.HandlerOrgName,
+				Key = targetStep.HandlerId,
+				Value = targetStep.HandlerName,
+				RoleId = targetStep.RoleId,
+				RoleName = targetStep.RoleName
+			});
+		}
+		var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
             dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
 
         //var stepHandlers = await GetNextStepHandlersAsync(workflow, targetStepDefine, dto, cancellationToken);
@@ -1672,8 +1698,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true, withTraces: true,
             cancellationToken: cancellationToken);
         var step = workflow.Steps.FirstOrDefault(d =>
-            //d.StepHandlers.Any(d => d.OrgId == "001171" || d.OrgId == "001178"));
-            d.HandlerOrgId == "001171" || d.HandlerOrgId == "001178");
+			//d.StepHandlers.Any(d => d.OrgId == _cityBaseConfiguration.Value.CityProvince.OrgId || d.OrgId == _cityBaseConfiguration.Value.CityProvinceAssign.OrgId));
+			d.HandlerOrgId == _cityBaseConfiguration.Value.CityProvince.OrgId || d.HandlerOrgId == _cityBaseConfiguration.Value.CityProvinceAssign.OrgId);
         if (step is not null)
         {
             step.FileJson = await _fileRepository.AddFileAsync(files, workflow.ExternalId, step.Id, cancellationToken);

+ 22 - 8
src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs

@@ -2,6 +2,7 @@
 using Hotline.Application.JudicialManagement;
 using Hotline.Application.Quality;
 using Hotline.Caching.Interfaces;
+using Hotline.Configurations;
 using Hotline.EventBus;
 using Hotline.FlowEngine.Notifications;
 using Hotline.FlowEngine.WorkflowModules;
@@ -15,16 +16,19 @@ using Hotline.Settings.TimeLimitDomain;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.Settings;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Push;
 using Hotline.Share.Enums.Quality;
 using Hotline.Share.Mq;
 using Hotline.Users;
+using Mapster;
 using MapsterMapper;
 using MediatR;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Entities;
 using XF.Domain.Repository;
@@ -34,6 +38,8 @@ namespace Hotline.Application.Handlers.FlowEngine;
 public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
 {
     private readonly IOrderDomainService _orderDomainService;
+    private readonly ICalcExpireTime _expireTime;
+    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
     private readonly IOrderRepository _orderRepository;
     private readonly ICapPublisher _capPublisher;
     private readonly IMapper _mapper;
@@ -46,7 +52,6 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
     private readonly IMediator _mediator;
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly Publisher _publisher;
-    private readonly ICalcExpireTime _expireTime;
 
 	public WorkflowNextHandler(
         IOrderDomainService orderDomainService,
@@ -61,8 +66,9 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
         IRepository<User> userRepository,
         IMediator mediator,
         ISystemSettingCacheManager systemSettingCacheManager,
-        ICalcExpireTime expireTime,
-		Publisher publisher)
+        Publisher publisher,
+        IOptionsSnapshot<AppConfiguration> appOptions,
+        ICalcExpireTime expireTime)
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
@@ -77,9 +83,9 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
         _mediator = mediator;
         _systemSettingCacheManager = systemSettingCacheManager;
         _publisher = publisher;
+        _appOptions = appOptions;
         _expireTime = expireTime;
-
-	}
+    }
 
     /// <summary>Handles a notification</summary>
     /// <param name="notification">The notification</param>
@@ -110,6 +116,14 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                     order.UpdateHandlingStatus(workflow.IsInCountersign);
                     _mapper.Map(workflow, order);
 
+                    if (_appOptions.Value.IsZiGong && data.FlowDirection is EFlowDirection.CenterToOrg)
+                    {
+                        var expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg , order.Adapt<OrderTimeClacInfo>());
+                        order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
+                            expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime
+                            , expiredTimeConfig.NearlyExpiredTimeOne, notification.Dto.Opinion,notification.Trace.HandlerId, notification.Trace.HandlerName,true);
+                    }
+
                     //var expiredTimeChanged = false;
                     //if (data.FlowDirection.HasValue
                     //    && data.External.TimeLimit.HasValue                   
@@ -189,7 +203,7 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                                     }
                                     break;
                                 case EFlowAssignType.User:
-                                    var userCodes = notification.Trace.NextHandlers.Select(x=>x.UserId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                    var userCodes = notification.Trace.NextHandlers.Select(x => x.UserId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
                                     var userList = await _userRepository.Queryable()
                                         .Where(x => userCodes.Contains(x.Id) && !string.IsNullOrEmpty(x.PhoneNo))
                                         .ToListAsync(cancellationToken);
@@ -226,9 +240,9 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                         HandlerOrgLevel = notification.HandlerOrgId.CalcOrgLevel()
                     }, cancellationToken: cancellationToken);
                     if (data.FlowDirection is EFlowDirection.CenterToOrg)
-	                    await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken);
+                        await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken);
 
-					break;
+                    break;
                 case WorkflowModuleConsts.KnowledgeAdd:
                 case WorkflowModuleConsts.KnowledgeUpdate:
                 case WorkflowModuleConsts.KnowledgeDelete:

+ 90 - 0
src/Hotline.Application/Jobs/XingTangCallSatisfactionSyncJob.cs

@@ -0,0 +1,90 @@
+using Hotline.CallCenter.Calls;
+using MapsterMapper;
+using Microsoft.Extensions.Logging;
+using Quartz;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+using XingTang.Sdk;
+
+namespace Hotline.Application.Jobs
+{
+    /// <summary>
+    /// 兴唐评价结果
+    /// </summary>
+    public class XingTangCallSatisfactionSyncJob : IJob, IDisposable
+    {
+        private readonly IRepository<CallNative> _callRepository;
+        private readonly ISqlSugarClient _db;
+        private readonly IRepository<CallSatisfaction> _callSatisfactionRepository;
+        private readonly IMapper _mapper;
+        private readonly ILogger<XingTangCallSatisfactionSyncJob> _logger;
+
+        public XingTangCallSatisfactionSyncJob(IRepository<CallNative> callRepository, ISqlSugarClient db, IRepository<CallSatisfaction> callSatisfactionRepository, IMapper mapper, ILogger<XingTangCallSatisfactionSyncJob> logger)
+        {
+            _callRepository = callRepository;
+            _db = db;
+            _callSatisfactionRepository = callSatisfactionRepository;
+            _mapper = mapper;
+            _logger = logger;
+        }
+
+        public void Dispose()
+        {
+        }
+
+        public async Task Execute(IJobExecutionContext context)
+        {
+            var callSatisfactions = await _db.Queryable<XingtangSatisfaction>()
+                .Where(d => (d.IsSync == null || !d.IsSync) && (d.Tries == null || d.Tries <= 50))
+                .OrderBy(d => d.Id)
+                .Take(10)
+                .ToListAsync(context.CancellationToken);
+
+            var occupyCallSatisfactions = new List<XingtangSatisfaction>();
+            foreach (var callSatisfaction in callSatisfactions)
+            {
+                callSatisfaction.IsSync = true;
+                callSatisfaction.Tries += 1;
+
+                var rows = await _db.Updateable(callSatisfaction)
+                    .ExecuteCommandWithOptLockAsync();
+                if (rows > 0)
+                    occupyCallSatisfactions.Add(callSatisfaction);
+            }
+
+            try
+            {
+                var callStatisfactions = _mapper.Map<List<CallSatisfaction>>(occupyCallSatisfactions);
+                foreach (var item in callSatisfactions)
+                {
+                    var call = _callRepository.Queryable().Where(x => x.CallNo == item.CallNo).FirstAsync();
+                    if(call != null)
+                    {
+                        item.Id = call.Id;
+                    }
+                }
+                await _callSatisfactionRepository.AddRangeAsync(callStatisfactions, context.CancellationToken);
+
+            }
+            catch (Exception e)
+            {
+                _logger.LogError($"获取通话记录评价:{e.Message} \n {e.StackTrace}");
+                foreach (var callSatisfaction in occupyCallSatisfactions)
+                {
+                    callSatisfaction.IsSync = false;
+                }
+
+                await _db.Updateable(occupyCallSatisfactions)
+                    .UpdateColumns(d => new { d.IsSync })
+                    .ExecuteCommandAsync(context.CancellationToken);
+            }
+
+
+        }
+    }
+}

+ 3 - 1
src/Hotline.Application/Jobs/XingTangTelOperationSyncJob.cs

@@ -65,7 +65,9 @@ namespace Hotline.Application.Jobs
             {
                 var operations = _mapper.Map<List<TelOperation>>(occupyOperations);
                 //填充user信息
-                var staffNos = operations.Select(d => d.StaffNo).ToList();
+                var staffNos = operations
+                    .Where(d=>!string.IsNullOrEmpty(d.StaffNo) && d.StaffNo != "0")
+                    .Select(d => d.StaffNo).ToList();
                 var users = await _userRepository.Queryable()
                     .Where(d => staffNos.Contains(d.StaffNo))
                     .ToListAsync(context.CancellationToken);

+ 0 - 2
src/Hotline.Application/JudicialManagement/EnforcementApplication.cs

@@ -266,8 +266,6 @@ namespace Hotline.Application.JudicialManagement
         /// <returns></returns>
         public ISugarQueryable<VisitAndOrgSatisfactionStatisticsDto> GetVisitAndOrgSatisfactionStatisticsAsync(DateTime StartTime, DateTime EndTime, int TypeId)
         {
-            EndTime = EndTime.AddDays(1).AddSeconds(-1);
-
             return _judicialManagementOrdersRepository.Queryable()
                  .LeftJoin<OrderVisit>((x, o) => x.Id == o.OrderId)
                  .LeftJoin<OrderVisitDetail>((x, o, p) => o.Id == p.VisitId)

+ 5 - 0
src/Hotline.Application/Mappers/CallMapperConfigs.cs

@@ -90,6 +90,11 @@ namespace Hotline.Application.Mappers
                         : EEndBy.To;
                 });
 
+            config.ForType<XingtangSatisfaction, CallSatisfaction>()
+                .Map(d => d.CallNo, s => s.CallNo)
+                .Map(d => d.Result, s => s.Result)
+                ;
+
             config.ForType<XingtangSeatOperation, TelOperation>()
                 .Map(d => d.StaffNo, s => s.UserCode)
                 .Map(d => d.TelNo, s => s.Ext)

+ 2 - 2
src/Hotline.Application/Mappers/WebPortalMapperConfigs.cs

@@ -25,7 +25,7 @@ namespace Hotline.Application.Mappers
                .Map(d => d.ConTypeName, x => x.Order.HotspotName)
                .Map(d => d.FlowAddDate, x => x.Order.StartTime)
                .Map(d => d.PubDate, x => x.CreationTime)
-               .Map(d => d.RSFlagName, x => x.Order.Status < EOrderStatus.Filed ? "办理中" : "办理完成")
+               .Map(d => d.RSFlagName, x => x.Order.Status <= EOrderStatus.Filed ? "办理中" : "办理完成")
           ;
 
             //办件摘编详情
@@ -45,7 +45,7 @@ namespace Hotline.Application.Mappers
             .Map(d => d.FlowBMID, x => x.ActualHandleOrgCode)
             .Map(d => d.FlowBMName, x => x.ActualHandleOrgName)
             .Map(d => d.FlowLKName, x => x.FromName)
-            .Map(d => d.FlowRSFlagName, x => x.Status < EOrderStatus.Filed ? "办理中" : "办理完成")
+            .Map(d => d.FlowRSFlagName, x => x.Status <= EOrderStatus.Filed ? "办理中" : "办理完成")
        ;
 
             //注册用户数据

+ 121 - 140
src/Hotline.Application/Orders/OrderApplication.cs

@@ -93,9 +93,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     private readonly IRepository<OrderScreen> _orderScreenRepository;
     private readonly IRepository<OrderSendBackAudit> _orderSendBackAuditRepository;
     private readonly ICalcExpireTime _expireTime;
+    private readonly IOptions<CityBaseConfiguration> _cityBaseConfiguration;
 
 
-    public OrderApplication(
+	public OrderApplication(
         IOrderDomainService orderDomainService,
         IOrderRepository orderRepository,
         IWorkflowDomainService workflowDomainService,
@@ -124,7 +125,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         ICalcExpireTime expireTime,
         IMediator mediator,
         IRepository<OrderVisitDetail> orderVisitedDetailRepository,
-        IOptionsSnapshot<AppConfiguration> appOptions)
+        IOptionsSnapshot<AppConfiguration> appOptions,
+        IOptions<CityBaseConfiguration> cityBaseConfiguration)
     {
         _orderDomainService = orderDomainService;
         _workflowDomainService = workflowDomainService;
@@ -155,7 +157,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         _mediator = mediator;
         _orderVisitedDetailRepository = orderVisitedDetailRepository;
         _appOptions = appOptions;
-    }
+        _cityBaseConfiguration = cityBaseConfiguration;
+	}
 
     /// <summary>
     /// 更新工单办理期满时间(延期调用,其他不调用)
@@ -246,14 +249,14 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 order.ProcessType is EProcessType.Zhiban)
             : 0;
         var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
-                    ? 
+                    ?
                     // _timeLimitDomainService.CalcWorkTime(
                     await _expireTime.CalcWorkTime(
                         order.CreationTime, now,
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
         var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
-            ? 
+            ?
             // _timeLimitDomainService.CalcWorkTime(
             await _expireTime.CalcWorkTime(
                 order.CenterToOrgTime.Value, now,
@@ -282,7 +285,13 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         var IsCenter = _sessionContext.OrgIsCenter;
 
         return _orderRepository.Queryable(canView: !IsCenter).Includes(d => d.OrderDelays)
-            .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
+	        .Where(d => SqlFunc.Subqueryable<WorkflowStep>()
+		        .Where(step => step.ExternalId == d.Id &&
+		                       ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
+		                        (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
+		                        (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId))))
+		        .Any())
+			.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!))
             .WhereIF(dto.Delay.HasValue && dto.Delay == 1, d => d.OrderDelays.Any() == true)
@@ -384,7 +393,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         var seg = new Segment();
         ICollection<WordInfo> splitWords = seg.DoSegment(inputStr);
         var words = new List<string>();
-        for (int i = 0;i < splitWords.Count;i++)
+        for (int i = 0; i < splitWords.Count; i++)
         {
             var word = splitWords.ElementAt(i);
             if (word is { WordType: WordType.SimplifiedChinese, Word.Length: > 1 })
@@ -458,6 +467,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             case ESource.ZHYB:
             case ESource.ZZPT:
             case ESource.WLLZ:
+            case ESource.YBS:
                 return ReceiveOrderFromOtherPlatformAsync(dto, dto.Files, current, cancellationToken);
             case ESource.Hotline:
             case ESource.HotlineImport:
@@ -491,8 +501,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <exception cref="UserFriendlyException"></exception>
     public async Task<(int, IList<PublishedOrderStatisticsDto>)> QueryPublishedOrderAsync(QueryOrderPublishStatisticsDto dto, bool isFull)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
         var query = _orderRepository.Queryable()
             .Includes(order => order.OrderPublish)
             .LeftJoin<User>((order, user) => order.WaitForPublisherId == user.Id)
@@ -504,8 +512,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 Id = order.WaitForPublisherId,
                 Name = user.Name,
                 //TotalCount = SqlFunc.AggregateCount(order.Id),
-                WaitCount =    SqlFunc.AggregateSum(SqlFunc.IIF(order.Status == EOrderStatus.Filed, 1, 0)),
-                PublicCount =  SqlFunc.AggregateSum(SqlFunc.IIF(order.OrderPublish.PublishState == true , 1, 0)),
+                WaitCount = SqlFunc.AggregateSum(SqlFunc.IIF(order.Status == EOrderStatus.Filed, 1, 0)),
+                PublicCount = SqlFunc.AggregateSum(SqlFunc.IIF(order.OrderPublish.PublishState == true, 1, 0)),
                 PrivateCount = SqlFunc.AggregateSum(SqlFunc.IIF(order.OrderPublish.PublishState == false, 1, 0))
             });
 
@@ -531,7 +539,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <exception cref="UserFriendlyException"></exception>
     public async Task<(int, IList<PublishedOrderStatisticsDto>)> QueryPublishedOrderDepartmentAsync(QueryOrderPublishStatisticsAllDto dto, bool isFull)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
 
         var total = 0;
         var items = new List<PublishedOrderStatisticsDto>();
@@ -569,7 +576,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <exception cref="NotImplementedException"></exception>
     public async Task<IList<OrderVisitSourceChannelDto>> QueryOrderVisitSourceChannelAsync(QueryOrderVisitSourceChannelDto dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         var result = await _orderVisitRepository.Queryable()
             .LeftJoin<Order>((visit, order) => order.Id == visit.OrderId)
             .Where((visit, order) => visit.VisitTime >= dto.StartTime && visit.VisitTime <= dto.EndTime)
@@ -609,7 +615,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             visit.VisitTime = dto.VisitTime;
             visit.VisitType = dto.VisitType;
 
-            for (int i = 0;i < visit.OrderVisitDetails.Count;i++)
+            for (int i = 0; i < visit.OrderVisitDetails.Count; i++)
             {
                 var detail = visit.OrderVisitDetails[i];
                 var detaildto = dto.OrderVisitDetailDto.FirstOrDefault(x => x.Id == detail.Id);
@@ -817,32 +823,34 @@ public class OrderApplication : IOrderApplication, IScopeDependency
 
         return query
             .Includes(x => x.OrderScreens)
-            .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!)) //标题
+            .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!)) //标题
             .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo == dto.ProvinceNo) //省本地编号
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) //工单编码
             .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType)//受理类型
-                                                                                                    //.WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
+            //.WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
             .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
             //.WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
             //.WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
             .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
             .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone == dto.TransferPhone!) //转接号码
-                                                                                                           //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
-                                                                                                           //.WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
+            //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
+            //.WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
+            //.WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName),d=>d.OrgLevelOneName.Contains(dto.OrgLevelOneName)) //一级部门
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName),d=>d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName == dto.NameOrNo! || d.AcceptorStaffNo == dto.NameOrNo!) //受理人/坐席
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-                                                                                               //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
+            //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
             .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone == dto.FromPhone) //来电号码
             .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact == dto.PhoneNo!) //联系电话
-			//.WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
+            //.WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
             .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), x => x.OrderPushTypes.Any(opt => opt.PushTypeCode == dto.PushTypeCode))//推送分类
-			.WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
+            .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
-                                                                                            //.WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
+            //.WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
             .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)//工单状态
-                                                                      //.WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
+            //.WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName == dto.ActualHandlerName) //接办人
             .WhereIF(dto.IsScreen == true, d => d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //有甄别
             .WhereIF(dto.IsScreen == false, d => !d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //无甄别
@@ -853,8 +861,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(dto.IsOverTime == false, d => (d.ExpiredTime > DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime > d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //否 超期
             .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
             .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName == dto.FromName) //来电人姓名
-                                                                                           //.WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
-            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)//区域
+            //.WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
+            //.WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)//区域
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode) && dto.AreaCode.LastIndexOf("00")>0,d=>d.AreaCode.StartsWith(SqlFunc.Substring(dto.AreaCode,0,4)))
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode) && dto.AreaCode.LastIndexOf("00")<=0,d=>d.AreaCode.StartsWith(dto.AreaCode))
             .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, d => d.Source == ESource.ProvinceStraight)
             .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, d => d.Source != ESource.ProvinceStraight)
             .WhereIF(!string.IsNullOrEmpty(dto.SensitiveWord), d => SqlFunc.JsonArrayAny(d.Sensitive, dto.SensitiveWord))
@@ -876,8 +886,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<Order, WorkflowStep> QueryUnsignedOrders(QueryUnsignedOrdersRequest dto)
     {
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         var IsCenter = _sessionContext.OrgIsCenter;
         return _orderRepository.Queryable()
             .LeftJoin<WorkflowStep>((x, ws) => x.Id == ws.ExternalId)
@@ -1009,8 +1017,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
 	public ISugarQueryable<Order> QueryOrgDataListDetail(OrgDataListDetailRequest dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
         var quer = _orderRepository.Queryable()
             .InnerJoin<SystemOrganize>((x, so) => x.ActualHandleOrgCode == so.Id && so.Level == 1)
             .Where((x, so) => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
@@ -1050,7 +1056,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<Order> QueryOrgDataListDetail(OrgDataListAllDetailRequest dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         bool IsCenter = _sessionContext.OrgIsCenter;
 
         var quer = _orderRepository.Queryable()
@@ -1089,7 +1094,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<OrderReTransactVo> OrderReTransact(QueryOrderReTransactRequest dto)
     {
-
         return _orderSpecialDetailRepository.Queryable()
             .Includes(x => x.OrderSpecial)
             .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.OrgName.Contains(dto.OrgName!))
@@ -1116,7 +1120,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     {
         if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
             throw UserFriendlyException.SameMessage("请选择时间!");
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         return _orderSpecialDetailRepository.Queryable()
             .Includes(x => x.OrderSpecial, s => s.Order)
             .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.OrgName.Contains(dto.OrgName!))
@@ -1132,8 +1135,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<List<VisitAndOrgSatisfactionStatisticsDto>> VisitAndOrgSatisfactionStatistics(PagedKeywordSonRequest dto)
     {
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
         bool IsCenter = _sessionContext.OrgIsCenter;
 
         var list = _orderVisitDetailRepository.Queryable()
@@ -1227,8 +1228,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<List<VisitAndOrgSatisfactionStatisticsDto>> VisitAndOrgStatisfactionOrgDetail(PagedKeywordSonRequest dto)
     {
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
         bool IsCenter = _sessionContext.OrgIsCenter;
 
         var list = await _systemOrganizeRepository.Queryable().Where(x => x.Id.StartsWith(dto.OrgCode))
@@ -1276,7 +1275,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return list;
     }
 
-    
+
 
     /// <summary>
     /// 热点区域统计
@@ -1285,7 +1284,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<(List<SystemArea> area, object items)> HotspotAndAreaStatistics(HotspotAndAreaStatisticsReq dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         var areaList = _systemAreaRepository.Queryable().Where(x => SqlFunc.Length(x.Id) == 6 && x.Id != "510000").OrderBy(x => x.Id).MergeTable();
 
         var endIndex = (2 * dto.HotspotLevel).ToString();
@@ -1354,7 +1352,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<DataTable> HotspotAndAreaStatisticsExport(HotspotAndAreaStatisticsReq dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         var areaList = _systemAreaRepository.Queryable().Where(x => SqlFunc.Length(x.Id) == 6 && x.Id != "510000").OrderBy(x => x.Id).MergeTable();
 
         var endIndex = (2 * dto.HotspotLevel).ToString();
@@ -1429,10 +1426,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             dt.Columns.Remove("Column1");
 
         //计算小计
-        for (int i = 0;i < dt.Rows.Count;i++)
+        for (int i = 0; i < dt.Rows.Count; i++)
         {
             int sumcount = 0;
-            for (int j = 1;j < dt.Columns.Count - 1;j++)
+            for (int j = 1; j < dt.Columns.Count - 1; j++)
             {
                 sumcount += Convert.ToInt32(dt.Rows[i][j].ToString());
             }
@@ -1443,10 +1440,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         DataRow totalRow = dt.NewRow();
         if (dt.Columns[0].ColumnName == "HotspotName") totalRow["HotspotName"] = "合计";
         else totalRow["一级热点"] = "合计";
-        for (int i = 1;i < dt.Columns.Count;i++)
+        for (int i = 1; i < dt.Columns.Count; i++)
         {
             int sumcount = 0;
-            for (int j = 0;j < dt.Rows.Count;j++)
+            for (int j = 0; j < dt.Rows.Count; j++)
             {
                 sumcount += Convert.ToInt32(dt.Rows[j][i].ToString());
             }
@@ -1575,8 +1572,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<List<VisitAndHotspotSatisfactionStatisticsDto>> VisitAndHotspotSatisfactionStatistics(VisitAndHotspotPagedKeywordRequest dto)
     {
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
         bool IsCenter = _sessionContext.OrgIsCenter;
 
         var list = _orderVisitDetailRepository.Queryable()
@@ -1644,7 +1639,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<OrderVisitDetail> VisitAndHotspotSatisfactionDetail(VisitAndHotspotPagedKeywordRequest dto)
     {
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         bool IsCenter = _sessionContext.OrgIsCenter;
         var key = string.Empty;
         if (!string.IsNullOrEmpty(dto.TitleCode))
@@ -1692,8 +1686,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     {
         if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
         var query = _orderRepository.Queryable(false, false, false)
             .WhereIF(dto.StartTime.HasValue, it => it.CreationTime >= dto.StartTime)
             .WhereIF(dto.EndTime.HasValue, it => it.CreationTime <= dto.EndTime)
@@ -1750,7 +1742,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<(List<SystemDicData> acceptTypes, object items)> HotspotAndAcceptTypeStatistics(HotspotAndAcceptTypeStatisticsReq dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         var dicList = _systemDicDataRepository.Queryable().Where(x => x.DicTypeCode == "AcceptType").OrderBy(x => x.Sort).MergeTable();
         var endIndex = (2 * dto.HotspotLevel).ToString();
         var hotspotList = _hotspotRepository.Queryable().Where(x => SqlFunc.Length(x.Id) == int.Parse(endIndex))
@@ -1812,7 +1803,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public async Task<DataTable> HotspotAndAcceptTypeStatisticsExport(HotspotAndAcceptTypeStatisticsReq dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         var dicList = _systemDicDataRepository.Queryable().Where(x => x.DicTypeCode == "AcceptType").OrderBy(x => x.Sort).MergeTable();
         var endIndex = (2 * dto.HotspotLevel).ToString();
         var hotspotList = _hotspotRepository.Queryable().Where(x => SqlFunc.Length(x.Id) == int.Parse(endIndex))
@@ -1874,7 +1864,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<Order> HotspotAndAcceptTypeStatisticsDetail(HotspotAndAcceptTypeStatisticsDetailReq dto)
     {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
         var query = _orderRepository.Queryable()
             .Where(x => x.HotspotId.StartsWith(dto.HotspotId) && x.CreationTime >= dto.StartTime && x.CreationTime < dto.EndTime)
             .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), x => x.AcceptTypeCode.StartsWith(dto.AcceptTypeCode))
@@ -1888,8 +1877,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
 	public ISugarQueryable<OrderScreenApplyVo> OrderScreenApply(OrderScreenApplyPagedRequest dto)
     {
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         var query = _orderScreenRepository.Queryable()
             .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, x => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
             .WhereIF(!string.IsNullOrEmpty(dto.ApplyUserName), x => x.CreatorName == dto.ApplyUserName)
@@ -1911,22 +1898,20 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<OrderScreenAuditVo> OrderScreenAudit(OrderScreenAuditPagedRequest dto)
     {
-	    if (dto.EndTime.HasValue)
-		    dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-	    var query = _workflowTraceRepository.Queryable()
-		    .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, x => x.HandleTime >= dto.StartTime && x.HandleTime <= dto.EndTime)
-		    .WhereIF(!string.IsNullOrEmpty(dto.AuditUserName), x => x.HandlerName == dto.AuditUserName)
-            .Where(x=> x.HandlerName != null && x.HandlerName != "" )
-            .WhereIF(dto.AuditType is 1,x=>x.Name == "班长审批")
-		    .WhereIF(dto.AuditType is 2, x => x.Name == "中心领导")
-			.GroupBy(x => new { x.HandlerName })
-		    .Select(x => new OrderScreenAuditVo
-			{
-			  AuditName = x.HandlerName,
-              AuditNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.TraceType  ==  EWorkflowTraceType.Normal, 1, 0)),
-              AuditBackNum = SqlFunc.AggregateSum(SqlFunc.IIF( x.TraceType == EWorkflowTraceType.Previous , 1, 0)),
-			});
-	    return query;
+        var query = _workflowTraceRepository.Queryable()
+            .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, x => x.HandleTime >= dto.StartTime && x.HandleTime <= dto.EndTime)
+            .WhereIF(!string.IsNullOrEmpty(dto.AuditUserName), x => x.HandlerName == dto.AuditUserName)
+            .Where(x => x.HandlerName != null && x.HandlerName != "")
+            .WhereIF(dto.AuditType is 1, x => x.Name == "班长审批")
+            .WhereIF(dto.AuditType is 2, x => x.Name == "中心领导")
+            .GroupBy(x => new { x.HandlerName })
+            .Select(x => new OrderScreenAuditVo
+            {
+                AuditName = x.HandlerName,
+                AuditNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.TraceType == EWorkflowTraceType.Normal, 1, 0)),
+                AuditBackNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.TraceType == EWorkflowTraceType.Previous, 1, 0)),
+            });
+        return query;
     }
 
     /// <summary>
@@ -1936,8 +1921,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<OrderCenterAcceptVo> OrderCenterAccept(OrderCenterAcceptPagedRequest dto)
     {
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         var sendBack = _orderSendBackAuditRepository.Queryable()
             .Where(x => x.State == ESendBackAuditState.End)
             .GroupBy(x => x.OrderId).Select(x => new { OrderId = x.OrderId });
@@ -1957,7 +1940,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 InvalidNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.AcceptType == "无效", 1, 0)),
                 HandleNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.Status >= EOrderStatus.Filed, 1, 0)),
                 NoHandleNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.Status < EOrderStatus.Filed, 1, 0)),
-                BackNum = SqlFunc.AggregateSum(SqlFunc.IIF(s.OrderId != null &&  s.OrderId != "", 1, 0)),
+                BackNum = SqlFunc.AggregateSum(SqlFunc.IIF(s.OrderId != null && s.OrderId != "", 1, 0)),
                 DutyDeskNum = SqlFunc.AggregateDistinctCount(d.AcceptorId)
             });
         return query;
@@ -1969,30 +1952,28 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<OrderCenterAcceptUserVo> OrderCenterAcceptUser(OrderCenterAcceptPagedRequest dto)
     {
-        if (dto.EndTime.HasValue)
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         var sendBack = _orderSendBackAuditRepository.Queryable()
             .Where(x => x.State == ESendBackAuditState.End)
             .GroupBy(x => x.OrderId).Select(x => new { OrderId = x.OrderId });
 
-	    var query = _orderRepository.Queryable()
-		    .LeftJoin(sendBack, (d, s) => d.Id == s.OrderId)
-		    .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, d => d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime)
-		    .WhereIF(dto.TypeCode != null && dto.TypeCode == 1, d => d.IdentityType == EIdentityType.Citizen)
-		    .WhereIF(dto.TypeCode != null && dto.TypeCode == 2, d => d.IdentityType == EIdentityType.Enterprise)
-		    .GroupBy(d => d.AcceptorName)
-		    .Select((d, s) => new OrderCenterAcceptUserVo
-			{
-			    AcceptUserName = d.AcceptorName,
-			    AcceptNum = SqlFunc.AggregateCount(1),
-			    ValidNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.AcceptType != "无效", 1, 0)),
-			    RepetitionNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.DuplicateIds == null || SqlFunc.JsonArrayLength(d.DuplicateIds) > 0, 1, 0)),
-			    InvalidNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.AcceptType == "无效", 1, 0)),
-			    HandleNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.Status >= EOrderStatus.Filed, 1, 0)),
-			    NoHandleNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.Status < EOrderStatus.Filed, 1, 0)),
-			    BackNum = SqlFunc.AggregateSum(SqlFunc.IIF(s.OrderId != null && s.OrderId != "", 1, 0))
-		    });
-	    return query;
+        var query = _orderRepository.Queryable()
+            .LeftJoin(sendBack, (d, s) => d.Id == s.OrderId)
+            .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue, d => d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime)
+            .WhereIF(dto.TypeCode != null && dto.TypeCode == 1, d => d.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeCode != null && dto.TypeCode == 2, d => d.IdentityType == EIdentityType.Enterprise)
+            .GroupBy(d => d.AcceptorName)
+            .Select((d, s) => new OrderCenterAcceptUserVo
+            {
+                AcceptUserName = d.AcceptorName,
+                AcceptNum = SqlFunc.AggregateCount(1),
+                ValidNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.AcceptType != "无效", 1, 0)),
+                RepetitionNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.DuplicateIds == null || SqlFunc.JsonArrayLength(d.DuplicateIds) > 0, 1, 0)),
+                InvalidNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.AcceptType == "无效", 1, 0)),
+                HandleNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.Status >= EOrderStatus.Filed, 1, 0)),
+                NoHandleNum = SqlFunc.AggregateSum(SqlFunc.IIF(d.Status < EOrderStatus.Filed, 1, 0)),
+                BackNum = SqlFunc.AggregateSum(SqlFunc.IIF(s.OrderId != null && s.OrderId != "", 1, 0))
+            });
+        return query;
     }
 
 
@@ -2041,12 +2022,12 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     private async Task<AddOrderResponse> ReceiveOrderFromProvinceAsync(AddOrderDto dto, List<FileDto> files,
         ISessionContext current, CancellationToken cancellationToken)
     {
-        if (string.IsNullOrEmpty(dto.ProvinceNo))
+        if (string.IsNullOrEmpty(dto.ReceiveProvinceNo))
             throw new UserFriendlyException("无效省工单编号");
 
-        var orderExtension = await _orderDomainService.GetOrderExtensionsAsync(dto.ProvinceNo, cancellationToken);
+        var orderExtension = await _orderDomainService.GetOrderExtensionsAsync(dto.ReceiveProvinceNo, cancellationToken);
 
-        var order = await _orderRepository.GetAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
+        var order = await _orderRepository.GetAsync(d => d.ReceiveProvinceNo == dto.ReceiveProvinceNo, cancellationToken);
         if (order is null)
         {
             order = _mapper.Map<Order>(dto);
@@ -2084,7 +2065,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             //特提(撤回至发起)
             if (!string.IsNullOrEmpty(order.WorkflowId))
             {
-                current = SessionContextCreator.CreateSessionContext("province");
+                current = SessionContextCreator.CreateSessionContext("province",_cityBaseConfiguration.Value);
                 await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, cancellationToken);
             }
         }
@@ -2116,32 +2097,32 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 NoSendOrderNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.HandlerId == null || x.HandlerId == "", 1, 0)),
             }).ToListAsync();
 
-            var items2 = await _workflowTraceRepository.Queryable()
-                .LeftJoin<Workflow>((x, w) => x.WorkflowId == w.Id)
-                //.LeftJoin<WorkflowStepHandler>((x, w, wfsh) => x.StepId == wfsh.WorkflowStepId && wfsh.IsActualHandler == true)
-                .InnerJoin<SchedulingUser>((x, w, su) => x.HandlerId == su.UserId)
-                .Where((x, w, su) => w.ModuleCode == WorkflowModuleConsts.OrderHandle && x.BusinessType == EBusinessType.Send && x.Status == EWorkflowStepStatus.Handled 
-                && !string.IsNullOrEmpty(x.NextMainHandler) && x.NextMainHandler != OrgSeedData.CenterId)
-                .Where((x, w, su) => x.CreationTime >= dto.StartTime.Value)
-                .Where((x, w, su) => x.CreationTime <= dto.EndTime.Value)
-                .GroupBy((x, w, su) => x.WorkflowId)
-                .Having((x, w, su) => SqlFunc.AggregateCount(x.WorkflowId) > 1)
-                .Select((x, w, su) => new { Id = x.WorkflowId, CreationTime = SqlFunc.AggregateMin(x.CreationTime) })
-                .MergeTable()
-                .LeftJoin<WorkflowTrace>((a, wt) => a.Id == wt.WorkflowId)
-                .LeftJoin<Workflow>((a, wt, wf) => wt.WorkflowId == wf.Id)
-                //.LeftJoin<WorkflowStepHandler>((a, wt, wf, wsh) => wt.StepId == wsh.WorkflowStepId && wsh.CreationTime == a.CreationTime)
-                .InnerJoin<SchedulingUser>((a, wt, wf, su) => wt.HandlerId == su.UserId)
-                .WhereIF(!string.IsNullOrEmpty(dto.UserName), ((a, wt, wf, su) => su.UserName == dto.UserName))
-                .GroupBy((a, wt, wf, su) => new { su.UserId, su.UserName })
-                .Select((a, wt, wf, su) => new BiOrderSendVo
-                {
-                    UserId = su.UserId,
-                    UserName = su.UserName,
-                    SendOrderNum = 0,
-                    NoSendOrderNum = 0,
-                    ReSendOrderNum = SqlFunc.AggregateDistinctCount(wf.ExternalId),
-                }).ToListAsync();
+        var items2 = await _workflowTraceRepository.Queryable()
+            .LeftJoin<Workflow>((x, w) => x.WorkflowId == w.Id)
+            //.LeftJoin<WorkflowStepHandler>((x, w, wfsh) => x.StepId == wfsh.WorkflowStepId && wfsh.IsActualHandler == true)
+            .InnerJoin<SchedulingUser>((x, w, su) => x.HandlerId == su.UserId)
+            .Where((x, w, su) => w.ModuleCode == WorkflowModuleConsts.OrderHandle && x.BusinessType == EBusinessType.Send && x.Status == EWorkflowStepStatus.Handled
+            && !string.IsNullOrEmpty(x.NextMainHandler) && x.NextMainHandler != OrgSeedData.CenterId)
+            .Where((x, w, su) => x.CreationTime >= dto.StartTime.Value)
+            .Where((x, w, su) => x.CreationTime <= dto.EndTime.Value)
+            .GroupBy((x, w, su) => x.WorkflowId)
+            .Having((x, w, su) => SqlFunc.AggregateCount(x.WorkflowId) > 1)
+            .Select((x, w, su) => new { Id = x.WorkflowId, CreationTime = SqlFunc.AggregateMin(x.CreationTime) })
+            .MergeTable()
+            .LeftJoin<WorkflowTrace>((a, wt) => a.Id == wt.WorkflowId)
+            .LeftJoin<Workflow>((a, wt, wf) => wt.WorkflowId == wf.Id)
+            //.LeftJoin<WorkflowStepHandler>((a, wt, wf, wsh) => wt.StepId == wsh.WorkflowStepId && wsh.CreationTime == a.CreationTime)
+            .InnerJoin<SchedulingUser>((a, wt, wf, su) => wt.HandlerId == su.UserId)
+            .WhereIF(!string.IsNullOrEmpty(dto.UserName), ((a, wt, wf, su) => su.UserName == dto.UserName))
+            .GroupBy((a, wt, wf, su) => new { su.UserId, su.UserName })
+            .Select((a, wt, wf, su) => new BiOrderSendVo
+            {
+                UserId = su.UserId,
+                UserName = su.UserName,
+                SendOrderNum = 0,
+                NoSendOrderNum = 0,
+                ReSendOrderNum = SqlFunc.AggregateDistinctCount(wf.ExternalId),
+            }).ToListAsync();
 
         var res = (from t1 in items
                    join t2 in items2 on t1.UserId equals t2.UserId into t1_t2
@@ -2175,23 +2156,23 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         {
             dto.EndTime = dto.EndTime?.AddDays(1).AddSeconds(-1);
         }
-       return _orderVisitRepository.Queryable()
-            .WhereIF(dto.StartTime.HasValue, x => x.VisitTime >= dto.StartTime)
-            .WhereIF(dto.EndTime.HasValue, x => x.VisitTime <= dto.EndTime)
-            .GroupBy(x => new { EmployeeId = x.EmployeeId, Name = x.Employee.Name })
-            .Select(x => new OrderVisitJudeStatisticsRep()
-            {
-                EmpId = x.EmployeeId,
-                EmpName = x.Employee.Name,
-                OrgJudeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState !=null, 1, 0)), //部门扭转总件
-                OrgJudeApprovalingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState == EJudgeState.Judging, 1, 0)),
-                OrgJudeSuccessCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge== true && x.JudgeState == EJudgeState.Agreed, 1, 0)),
-                OrgJudeFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState == EJudgeState.UnAgreed, 1, 0)),
-                SeatJudeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState!=null, 1, 0)),
-                SeatJudeApprovalingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState == EJudgeState.Judging, 1, 0)),
-                SeatJudeSuccessCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState == EJudgeState.Agreed, 1, 0)),
-                SeatJudeFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState == EJudgeState.UnAgreed, 1, 0))
-            });
+        return _orderVisitRepository.Queryable()
+             .WhereIF(dto.StartTime.HasValue, x => x.VisitTime >= dto.StartTime)
+             .WhereIF(dto.EndTime.HasValue, x => x.VisitTime <= dto.EndTime)
+             .GroupBy(x => new { EmployeeId = x.EmployeeId, Name = x.Employee.Name })
+             .Select(x => new OrderVisitJudeStatisticsRep()
+             {
+                 EmpId = x.EmployeeId,
+                 EmpName = x.Employee.Name,
+                 OrgJudeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState != null, 1, 0)), //部门扭转总件
+                 OrgJudeApprovalingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState == EJudgeState.Judging, 1, 0)),
+                 OrgJudeSuccessCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState == EJudgeState.Agreed, 1, 0)),
+                 OrgJudeFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.OrgJudge == true && x.JudgeState == EJudgeState.UnAgreed, 1, 0)),
+                 SeatJudeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState != null, 1, 0)),
+                 SeatJudeApprovalingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState == EJudgeState.Judging, 1, 0)),
+                 SeatJudeSuccessCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState == EJudgeState.Agreed, 1, 0)),
+                 SeatJudeFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.SeatJudge == true && x.JudgeState == EJudgeState.UnAgreed, 1, 0))
+             });
     }
 
     #endregion

+ 1 - 1
src/Hotline.Application/Orders/OrderScreenHandler/OrderScreenEndWorkflowHandler.cs

@@ -113,10 +113,10 @@ public class OrderScreenEndWorkflowHandler : INotificationHandler<EndWorkflowNot
 				}
 				else
 				{
-					await _orderRepository.OrderScreenRevisionVisit(screen.VisitId, true, cancellationToken);
 					screen.Status = EScreenStatus.Refuse;
 					screen.ReplyContent = workflow.ActualOpinion;
 				}
+				await _orderRepository.OrderScreenRevisionVisit(screen.VisitId, true, cancellationToken);
 				screen.NewestAuditTime = DateTime.Now;
 				await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
 				OrderScreenDetail detail = new OrderScreenDetail

+ 0 - 8
src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs

@@ -322,8 +322,6 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         public ISugarQueryable<SecondaryHandlingVo> SecondaryHandlingReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
         {
-            if (dto.EndTime.HasValue)
-                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             return _orderSecondaryHandlingRepository.Queryable()
                 .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                 .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
@@ -347,8 +345,6 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
         {
-            if (dto.EndTime.HasValue)
-                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             return _orderSecondaryHandlingRepository.Queryable()
                 .Includes(x => x.Order)
                 .Includes(x => x.Visit)
@@ -368,8 +364,6 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         public ISugarQueryable<SecondaryHandlingSatisfactionVo> SecondaryHandlingSatisfactionReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
         {
-            if (dto.EndTime.HasValue)
-                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             return _orderSecondaryHandlingRepository.Queryable()
                 .Includes(x => x.Order)
                 .Includes(x => x.Visit)
@@ -405,8 +399,6 @@ namespace Hotline.Application.Orders
         public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingSatisfactionDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
         {
             var key = string.Empty;
-            if (dto.EndTime.HasValue)
-                dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
             if (!string.IsNullOrEmpty(dto.Header))
             {
                 switch (dto.Header)

+ 0 - 1
src/Hotline.Application/StatisticalReport/CallReportApplication.cs

@@ -92,7 +92,6 @@ namespace Hotline.Application.StatisticalReport
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
                 throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
             return _trCallRecordRepository.Queryable()
                      .Includes(p => p.Order)

+ 0 - 14
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -106,7 +106,6 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         public async Task<List<DepartmentalProcessingStatisticsDataDto>> DepartmentalProcessingStatisticsNew(DepartmentalProcessingStatisticsRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             var IsCenter = _sessionContext.OrgIsCenter;
 
             //信件总量:信件总量=已办件数+在办件数+会签已办+会签待办
@@ -140,8 +139,6 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         public async Task<List<DepartmentalProcessingStatisticsDataDto>> DepartmentalProcessingChildStatisticsNew(DepartmentalProcessingStatisticsRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             //信件总量:信件总量=已办件数+在办件数,工单需去重
             //已办件数:该部门已办理完成的工单总数(含参与会签的工单),若工单被部门多次办理,只统计一次
             //在办件数:该部门还未办理的工单数(若是一级部门,需包含中心向该部门发起回签的工单)。(特殊说明:部门或者中心发起了会签,会签中还未汇总,应算发起会签部门的在办里面)
@@ -177,8 +174,6 @@ namespace Hotline.Application.StatisticalReport
         /// <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)
@@ -549,7 +544,6 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         public ISugarQueryable<DepartmentalProcessingStatisticsDataDto> DepartmentalProcessingStatistics(DepartmentalProcessingStatisticsRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             var IsCenter = _sessionContext.OrgIsCenter;
 
             //工单   已办=归完档的工单数+会签已办数量
@@ -1439,8 +1433,6 @@ namespace Hotline.Application.StatisticalReport
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             var IsCenter = _sessionContext.OrgIsCenter;
 
             return _orderDelayRepository.Queryable()
@@ -1476,8 +1468,6 @@ namespace Hotline.Application.StatisticalReport
         {
             if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
 
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             return _orderDelayRepository.Queryable()
                  .Includes(x => x.Order)
                  .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
@@ -1500,8 +1490,6 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         public ISugarQueryable<DepartmentAcceptanceTypeStatisticsDto> DepartmentAcceptanceTypeStatistics(DepartmentKeyWordRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             var IsCenter = _sessionContext.OrgIsCenter;
 
             var orderData = _orderRepository.Queryable()
@@ -1576,7 +1564,6 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         public ISugarQueryable<Order> DepartmentAcceptanceTypeOrderList(DepartmentKeyWordRequest dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             return _orderRepository.Queryable()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime && p.Status >= EOrderStatus.Filed)
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode == "001", p => p.ActualHandleOrgCode == dto.OrgCode)
@@ -1600,7 +1587,6 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         public ISugarQueryable<AcceptTypeStatisticsDto> AcceptTypeStatistics(AcceptTypeStatisticsReq dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             var query = _orderRepository.Queryable()
                 .Where(x => x.CreationTime >= dto.StartTime && x.CreationTime < dto.EndTime)
                 .WhereIF(dto.TypeId != null && dto.TypeId == 1, x => x.IdentityType == EIdentityType.Citizen)

+ 145 - 26
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -4,6 +4,7 @@ using Hotline.Application.FlowEngine;
 using Hotline.Application.Orders;
 using Hotline.Authentications;
 using Hotline.Caching.Interfaces;
+using Hotline.Caching.Services;
 using Hotline.Configurations;
 using Hotline.ContingencyManagement;
 using Hotline.File;
@@ -24,7 +25,9 @@ using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Mq;
 using MapsterMapper;
+using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Options;
+using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
@@ -63,8 +66,11 @@ namespace Hotline.Application.Subscribers
         private readonly IRepository<ContingencyManagementOrders> _contingencyManagementOrdersRepository;
         private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
         private readonly ICallApplication _callApplication;
+        private readonly IRepository<OrderPublish> _orderPublishRepository;
+        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
+        private readonly IOptions<CityBaseConfiguration> _cityBaseConfiguration;
 
-        public DataSharingSubscriber(
+		public DataSharingSubscriber(
             IRepository<OrderVisit> orderVisitRepository,
             IMapper mapper,
             IOrderRepository orderRepository,
@@ -91,7 +97,10 @@ namespace Hotline.Application.Subscribers
              IRepository<OrderRevoke> orderRevokeRepository,
              IRepository<ContingencyManagementOrders> contingencyManagementOrdersRepository,
             IOptionsSnapshot<AppConfiguration> appOptions,
-            ICallApplication callApplication)
+            ICallApplication callApplication,
+            IRepository<OrderPublish> orderPublishRepository,
+            ISystemDicDataCacheManager sysDicDataCacheManager,
+            IOptions<CityBaseConfiguration> cityBaseConfiguration)
         {
             _orderSendBackRepository = orderSendBackRepository;
             _workflowApplication = workflowApplication;
@@ -120,7 +129,10 @@ namespace Hotline.Application.Subscribers
             _contingencyManagementOrdersRepository = contingencyManagementOrdersRepository;
             _appOptions = appOptions;
             _callApplication = callApplication;
-        }
+            _orderPublishRepository = orderPublishRepository;
+            _sysDicDataCacheManager = sysDicDataCacheManager;
+            _cityBaseConfiguration = cityBaseConfiguration;
+		}
 
         /// <summary>
         /// 接收工单退回结果
@@ -168,7 +180,7 @@ namespace Hotline.Application.Subscribers
                     //order.File(now, handleDuration, fileDuration, allDuration);
                     //await _orderRepository.UpdateAsync(order, cancellationToken);
 
-                    var current = SessionContextCreator.CreateSessionContext(dto.Source);
+                    var current = SessionContextCreator.CreateSessionContext(dto.Source, _cityBaseConfiguration.Value);
                     if (string.IsNullOrEmpty(order.WorkflowId))
                     {
                         var startDto = new StartWorkflowDto
@@ -204,7 +216,7 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderRevoke)]
         public async Task RecCancelOrderAsync(CancelOrderDto dto, CancellationToken cancellationToken)
         {
-            var order = await _orderRepository.GetAsync(p => p.ProvinceNo == dto.ProvinceNo, cancellationToken);
+            var order = await _orderRepository.GetAsync(p => p.ReceiveProvinceNo == dto.ProvinceNo, cancellationToken);
             if (order is null)
                 throw new UserFriendlyException("未查询到工单");
 
@@ -228,7 +240,7 @@ namespace Hotline.Application.Subscribers
             };
             await _orderRevokeRepository.AddAsync(orderRevoke, cancellationToken);
 
-            var current = SessionContextCreator.CreateSessionContext(dto.Source);
+            var current = SessionContextCreator.CreateSessionContext(dto.Source,_cityBaseConfiguration.Value);
             if (string.IsNullOrEmpty(order?.WorkflowId))
             {
                 var startDto = new StartWorkflowDto
@@ -260,7 +272,7 @@ namespace Hotline.Application.Subscribers
             if (exists)
                 throw new UserFriendlyException($"收到重复催办编号: {dto.DsBisId}");
 
-            var order = await _orderRepository.Queryable().Where(x => x.ProvinceNo == dto.CaseSerial).FirstAsync(cancellationToken);
+            var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.CaseSerial).FirstAsync(cancellationToken);
             var model = new OrderUrge();
             model.InitId();
             model.State = 0;
@@ -282,8 +294,11 @@ namespace Hotline.Application.Subscribers
             //        model.OrgName = org.Value;
             //    }
             //}
-            model.OrgId = order.CurrentHandleOrgId;
-            model.OrgName = order.CurrentHandleOrgName;
+            if (!string.IsNullOrEmpty(order.CurrentHandleOrgId) && !string.IsNullOrEmpty(order.CurrentHandleOrgName))
+            {
+                model.OrgId = order.CurrentHandleOrgId;
+                model.OrgName = order.CurrentHandleOrgName;
+            }
 
 
             if (dto.Files.Any())
@@ -301,7 +316,7 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderWarning)]
         public async Task RecWarnInfoAsync(WarningDto dto, CancellationToken cancellationToken)
         {
-            var order = await _orderRepository.Queryable().Where(x => x.ProvinceNo == dto.CaseSerial).FirstAsync(cancellationToken);
+            var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.CaseSerial).FirstAsync(cancellationToken);
             if (order != null)
             {
                 var model = new OrderUrge();
@@ -324,8 +339,13 @@ namespace Hotline.Application.Subscribers
                 //        model.OrgName = org.Value;
                 //    }
                 //}
-                model.OrgId = order.CurrentHandleOrgId;
-                model.OrgName = order.CurrentHandleOrgName;
+                //model.OrgId = order.CurrentHandleOrgId;
+                //model.OrgName = order.CurrentHandleOrgName;
+                if (!string.IsNullOrEmpty(order.CurrentHandleOrgId) && !string.IsNullOrEmpty(order.CurrentHandleOrgName))
+                {
+                    model.OrgId = order.CurrentHandleOrgId;
+                    model.OrgName = order.CurrentHandleOrgName;
+                }
 
                 await _orderUrgeRepository.AddAsync(model, cancellationToken);
 
@@ -356,7 +376,7 @@ namespace Hotline.Application.Subscribers
             if (exists)
                 throw new UserFriendlyException($"收到重复督办编号: {dto.ProvinceOrderSuperviseDto.SuperviseSerial}");
 
-            var order = await _orderRepository.Queryable().Where(x => x.ProvinceNo == dto.ProvinceOrderSuperviseDto!.CaseSerial).FirstAsync(cancellationToken);
+            var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.ProvinceOrderSuperviseDto!.CaseSerial).FirstAsync(cancellationToken);
             var org = await _systemOrganizeRepository.GetAsync(x => x.Id == order.ActualHandleOrgCode, cancellationToken);
             var model = new OrderSupervise();
             model.InitId();
@@ -393,11 +413,11 @@ namespace Hotline.Application.Subscribers
             //    .FirstAsync(cancellationToken);
 
             var orderScreen = await _orderScreenRepository.Queryable()
-                .Where(x => x.Order.ProvinceNo == dto.ProvinceScreenResult.CaseSerial &&
+                .Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceScreenResult.CaseSerial &&
                             x.Status == EScreenStatus.Approval)
                 .FirstAsync(cancellationToken);
 
-            var current = SessionContextCreator.CreateSessionContext(dto.Source);
+            var current = SessionContextCreator.CreateSessionContext(dto.Source,_cityBaseConfiguration.Value);
             await _workflowApplication.HandleToEndAsync(current,
                 orderScreen.WorkflowId, "省上推送甄别结果", null,
                 dto.ProvinceScreenResult.AuditResult
@@ -451,7 +471,7 @@ namespace Hotline.Application.Subscribers
             var orderVisit = await _orderVisitRepository.Queryable()
                 .Includes(x => x.Order)
                 .Includes(x => x.OrderVisitDetails)
-                .Where(x => x.Order.ProvinceNo == dto.ProvinceNo &&
+                .Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo &&
              x.VisitState != Share.Enums.Order.EVisitState.None).FirstAsync(cancellationToken);
 
             if (orderVisit != null)
@@ -526,6 +546,83 @@ namespace Hotline.Application.Subscribers
                     }
                 }
             }
+            else
+            {
+                //处理省下行回访
+                var order = await _orderRepository.Queryable().Where(x => x.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync();
+                if (order !=null)
+                {
+                    //判断是否有发布数据
+                    var orderPublish = await _orderPublishRepository.Queryable()
+                        .Includes(x => x.Order).
+                        Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo).FirstAsync(cancellationToken);
+                    if (orderPublish == null)
+                    {
+                        orderPublish = new OrderPublish();
+                        orderPublish.OrderId = order.Id;
+                        orderPublish.No = order.No;
+                        orderPublish.PublishState = false;
+                        orderPublish.ArrangeTitle = order.Title;
+                        orderPublish.ArrangeContent = order.Content;
+                        orderPublish.ArrangeOpinion = order.FileOpinion;
+                        orderPublish.ProPublishState = false;
+                        orderPublish.FeedBackPhone = order.Contact;
+                        orderPublish.CreatorName = order.CenterToOrgHandlerId;
+                        await _orderPublishRepository.AddAsync(orderPublish);
+                        order.Publish(orderPublish.PublishState);
+                    }
+
+                    orderVisit = new OrderVisit();
+                    orderVisit.No = order.No;
+                    orderVisit.OrderId = order.Id;
+                    orderVisit.VisitState = EVisitState.WaitForVisit;
+                    orderVisit.PublishTime = DateTime.Now;
+                    orderVisit.IsCanHandle = true;
+                    orderVisit.EmployeeId = order.CenterToOrgHandlerId;
+                    orderVisit.VisitState = EVisitState.Visited;
+                    orderVisit.VisitTime = dto.VisitTime;
+                    orderVisit.VisitType = dto.VisitType;
+                    orderVisit.IsCanAiVisit = false;
+                    orderVisit.IsCanHandle = false;
+                    var VisitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction).Where(x => x.DicDataValue == dto.OrgProcessingResults).Select(m => new Kv { Key = m.DicDataValue, Value = m.DicDataName }).FirstOrDefault();
+                    var satisfy = VisitSatisfaction;
+                    orderVisit.NowEvaluate = satisfy;
+                    string visitId = await _orderVisitRepository.AddAsync(orderVisit);
+
+                    //新增回访信息
+                    var visitedDetail = new List<OrderVisitDetail>();
+
+                    //新增坐席回访
+                    var seatDetail = new OrderVisitDetail();
+                    seatDetail.VisitId = visitId;
+                    seatDetail.VisitTarget = EVisitTarget.Seat;
+                    seatDetail.VoiceEvaluate = EVoiceEvaluate.Satisfied;
+                    seatDetail.SeatEvaluate = ESeatEvaluate.Satisfied;
+                    visitedDetail.Add(seatDetail);
+
+                    //新增部门回访
+                    var orgDetail = new OrderVisitDetail();
+                    orgDetail.VisitId = visitId;
+                    orgDetail.VisitOrgCode = order.ActualHandleOrgCode;
+                    orgDetail.VisitOrgName = order.ActualHandleOrgName;
+                    orgDetail.VisitTarget = EVisitTarget.Org;
+                    
+                    
+                    orgDetail.OrgProcessingResults = satisfy;
+
+                    visitedDetail.Add(orgDetail);
+                    //TODO 自贡办件态度
+
+
+                    await _orderVisitedDetailRepository.AddRangeAsync(visitedDetail,cancellationToken);
+                    order.Visited(satisfy.Key,satisfy.Value);
+                    order.Status = EOrderStatus.Visited;
+                    await _orderRepository.UpdateAsync(order, cancellationToken);
+
+                }
+                
+                
+            }
         }
 
         /// <summary>
@@ -549,7 +646,7 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderDelayResult)]
         public async Task OrderDelayWeb(ProvinceSendDelayResultDto dto, CancellationToken cancellationToken)
         {
-            var order = await _orderRepository.GetAsync(x => x.ProvinceNo == dto.No, cancellationToken);
+            var order = await _orderRepository.GetAsync(x => x.ReceiveProvinceNo == dto.No, cancellationToken);
             if (order != null)
             {
                 //查询延期
@@ -566,7 +663,7 @@ namespace Hotline.Application.Subscribers
                         orderDelay.FileJson = await _fileRepository.AddFileAsync(dto.Files, orderDelay.Id, orderDelay.WorkflowId, cancellationToken);
                     await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken);
 
-                    var current = SessionContextCreator.CreateSessionContext(dto.Source);
+                    var current = SessionContextCreator.CreateSessionContext(dto.Source, _cityBaseConfiguration.Value);
                     await _workflowApplication.HandleToEndAsync(current, orderDelay.WorkflowId, dto.Opinion, dto.Files,
                         dto.IsPass ? EReviewResult.Approval : EReviewResult.Failed, cancellationToken);
                 }
@@ -592,7 +689,7 @@ namespace Hotline.Application.Subscribers
             //    await _orderRepository.FileAsync(order, cancellationToken);
             //}
 
-            var current = SessionContextCreator.CreateSessionContext(dto.Source);
+            var current = SessionContextCreator.CreateSessionContext(dto.Source, _cityBaseConfiguration.Value);
             switch (dto.FinishType)
             {
                 case "0":
@@ -630,7 +727,7 @@ namespace Hotline.Application.Subscribers
         public async Task RecOrderExtensionAsync(OrderExtensionDto dto, CancellationToken cancellationToken)
         {
             var order = await _orderRepository.Queryable()
-                .FirstAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
+                .FirstAsync(d => d.ReceiveProvinceNo == dto.ProvinceNo, cancellationToken);
 
             var orderExtension = await _orderDomainService.GetOrderExtensionsAsync(dto.ProvinceNo, cancellationToken);
             if (orderExtension is null)
@@ -677,7 +774,7 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(EventNames.SharingOrderSupplements)]
         public async Task RecOrderSupplementsAsync(AddOrderComplementDto dto, CancellationToken cancellationToken)
         {
-            var order = await _orderRepository.GetAsync(d => d.ProvinceNo == dto.CaseSerial, cancellationToken);
+            var order = await _orderRepository.GetAsync(d => d.ReceiveProvinceNo == dto.CaseSerial, cancellationToken);
             if (order is null)
                 throw new UserFriendlyException("无效省工单编号");
             dto.OrderId = order.Id;
@@ -701,16 +798,16 @@ namespace Hotline.Application.Subscribers
             switch (dto.DsBisType)
             {
                 case EDsBisType.AcceptOrder:
-                    var order = await _orderRepository.GetAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
+                    var order = await _orderRepository.GetAsync(d => d.ReceiveProvinceNo == dto.ProvinceNo, cancellationToken);
                     if (order is null)
                         throw new UserFriendlyException("无效省工单编号");
 
-                    order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, order.WorkflowId ?? string.Empty, cancellationToken);
+                    order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", cancellationToken);
                     await _orderRepository.UpdateAsync(order, cancellationToken);
                     break;
                 case EDsBisType.OrderPreviousResult:
                     var sendBack = await _orderSendBackRepository.Queryable()
-                        .Where(d => d.Order.ProvinceNo == dto.ProvinceNo)
+                        .Where(d => d.Order.ReceiveProvinceNo == dto.ProvinceNo)
                         .FirstAsync(cancellationToken);
                     if (sendBack is null)
                         throw new UserFriendlyException("无效省工单退回编号");
@@ -738,7 +835,7 @@ namespace Hotline.Application.Subscribers
                     break;
                 case EDsBisType.OrderScreenResult:
                     var orderScreen = await _orderScreenRepository.Queryable()
-                        .Where(x => x.Order.ProvinceNo == dto.ProvinceNo && x.Status == Share.Enums.Order.EScreenStatus.Approval)
+                        .Where(x => x.Order.ReceiveProvinceNo == dto.ProvinceNo && x.Status == Share.Enums.Order.EScreenStatus.Approval)
                         .FirstAsync(cancellationToken);
                     if (orderScreen is null)
                         throw new UserFriendlyException("未查询到对应省工单甄别数据");
@@ -748,7 +845,7 @@ namespace Hotline.Application.Subscribers
                     break;
                 case EDsBisType.OrderDelayResult:
                     var orderDelay = await _orderDelayRepository.Queryable()
-                        .Where(d => d.Order.ProvinceNo == dto.ProvinceNo && d.DelayState == EDelayState.Examining)
+                        .Where(d => d.Order.ReceiveProvinceNo == dto.ProvinceNo && d.DelayState == EDelayState.Examining)
                         .FirstAsync(cancellationToken);
                     if (orderDelay is null)
                         throw new UserFriendlyException($"未查询到延期数据, ProvinceNo: {dto.ProvinceNo}");
@@ -897,6 +994,28 @@ namespace Hotline.Application.Subscribers
 
             }
         }
+
+        /// <summary>
+        ///  随手拍网格员、回复办理结果
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        [CapSubscribe(EventNames.TianQueReceiverOpinion)]
+        public async Task TianQueReceiverOpinion(TianQueReceiverOpinionDto dto, CancellationToken cancellationToken)
+        {
+            //todo
+        }
+
+        /// <summary>
+        ///  天阙推送工单,返回信息
+        /// </summary>
+        /// <returns></returns>
+        [CapSubscribe(EventNames.TianQuePushOrderReceiver)]
+        public async Task TianQuePushOrderReceiver(TianQuePushOrderReceiverDto dto, CancellationToken cancellationToken)
+        {
+            //todo
+        }
     }
 
 }

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

@@ -125,15 +125,6 @@ namespace Hotline.Repository.SqlSugar.CallCenter
 
         public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string source)
         {
-            //计算小时差
-            if (!endDate.HasValue)
-            {
-                endDate = beginDate.Date.AddDays(1).AddSeconds(-1);
-            }
-            else
-            {
-                endDate = endDate.Value.Date.AddDays(1).AddSeconds(-1);
-            }
             TimeSpan timeDifference = endDate.Value.Subtract(beginDate).Duration();
 
             int hourDiff = (int)(timeDifference.TotalHours);
@@ -194,7 +185,6 @@ namespace Hotline.Repository.SqlSugar.CallCenter
             {
                 endHourTo = startHourTo.Value.Add(new TimeSpan(1, 0, 0));
             }
-            endDate = endDate.Value.Date.AddDays(1).AddSeconds(-1);
             RefAsync<int> total = 0;
             var res = await Db.Queryable<TrCallRecord>()
                 .Where(x => x.CreatedTime >= beginDate && x.CreatedTime <= endDate)
@@ -225,9 +215,8 @@ namespace Hotline.Repository.SqlSugar.CallCenter
 
         public async Task<List<CallHotLineDto>> GetCallHotLineList(DateTime beginDate, DateTime endDate, string lineNum, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int ringTims)
         {
-            endDate = endDate.AddDays(1).AddSeconds(-1);
             var list = await Db.Queryable<TrCallRecord>()
-                .Where(x => x.CreatedTime >= beginDate && x.CreatedTime <= endDate)
+                .Where(x => x.CreatedTime >= beginDate && x.CreatedTime <= endDate && SqlFunc.Length(x.Gateway)>4)
                 .WhereIF(!string.IsNullOrEmpty(lineNum), x => x.Gateway == lineNum)
                 .GroupBy(x => x.Gateway)
                 .Select(x => new CallHotLineDto()

+ 1 - 18
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -203,7 +203,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -257,7 +256,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -311,7 +309,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -365,7 +362,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -419,7 +415,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -473,8 +468,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -528,7 +521,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -586,7 +578,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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++)
             {
@@ -639,7 +630,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
@@ -676,7 +666,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <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.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
@@ -782,7 +771,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public ISugarQueryable<HotspotAndAreaStatisticsDetailDto> HotspotAndAreaStatisticsDetail(HotspotAndAreaStatisticsDetailReq dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             var query = Db.Queryable<Order>()
                 //.Includes(x => x.OrderScreens.OrderByDescending(x => x.CreationTime).FirstOrDefault())
                 .Where(x => x.HotspotId.StartsWith(dto.HotspotId) && x.CreationTime >= dto.StartTime && x.CreationTime < dto.EndTime)
@@ -825,7 +813,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                .Where(x => x.AcceptTypeCode == dto.AcceptTypeCode && x.CreationTime.ToString("yyyy-MM-dd") == Date)
                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title))
-               .WhereIF(!string.IsNullOrEmpty(dto.CurrentHandleOrgName), x => x.ActualHandleOrgName.Contains(dto.CurrentHandleOrgName))
+               .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
                .Select(x => new HotspotAndAreaStatisticsDetailDto
                {
                    Id = x.Id,
@@ -858,8 +846,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<(List<SystemDicData> acceptType, object items)> AcceptTypeStatisticsByDate(AcceptTypeStatisticsByDateReq dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             //处理时间
             var diffDays = (dto.EndTime - dto.StartTime).Days;
             List<string> dateList = new List<string>();
@@ -929,8 +915,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<DataTable> AcceptTypeStatisticsByDateExport(AcceptTypeStatisticsByDateReq dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-
             //处理时间
             var diffDays = (dto.EndTime - dto.StartTime).Days;
             List<string> dateList = new List<string>();
@@ -1311,7 +1295,6 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public ISugarQueryable<OrgVisitDetailListResp> VisitAndOrgSatisfactionDetail(VisitAndOrgSatisfactionDetailDto dto)
         {
-            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
             bool IsCenter = _sessionContext.OrgIsCenter;
             return _orderVisitDetailRepository.Queryable()
                 .Includes(x => x.OrderVisit, o => o.Order, d => d.CallRecord)

+ 17 - 7
src/Hotline.Repository.SqlSugar/Orders/OrderVisitRepository.cs

@@ -38,23 +38,33 @@ public class OrderVisitRepository : BaseRepository<OrderVisit>, IOrderVisitRepos
     /// <returns></returns>
     public async Task UpdateSmsReplyAsync(PushReceiveMessageDto dto, Message data)
     {
-        if (dto.IsSmsReply == false || dto.SmsReplyContent.IsNullOrEmpty() || dto.ExternalId.IsNullOrEmpty()) return;
+        _logger.LogInformation($"UpdateSmsReplyAsync 收到通知: {dto.ToJson()}");
+        if (data.IsSmsReply == false || data.SmsReplyContent.IsNullOrEmpty() || data.ExternalId.IsNullOrEmpty()) return;
 
-        var orderVisit = await GetAsync(dto.ExternalId)
-             ?? throw new UserFriendlyException($"回访单不存在, visitId: {dto.ExternalId} message: {data.ToJson()}");
+        var orderVisit = await GetAsync(data.ExternalId)
+             ?? throw new UserFriendlyException($"回访单不存在, visitId: {data.ExternalId} message: {data.ToJson()}");
+
+        if (orderVisit.VisitState == EVisitState.Visited) 
+            throw new UserFriendlyException($"回访单已回访. visitId: {data.ExternalId}");
 
         Dictionary<string, string> dics = new()
         {
             { "1", $"非常满意|{EVisitState.Visited}|{ESeatEvaluate.VerySatisfied}|{EVoiceEvaluate.VerySatisfied}|5" },
             { "2", $"满意|{EVisitState.Visited}|{ESeatEvaluate.Satisfied}|{EVoiceEvaluate.Satisfied}|4"},
-            { "3", $"一般|{EVisitState.Visited}|{ESeatEvaluate.Satisfied}|{EVoiceEvaluate.Normal}|4"},
+            { "3", $"一般|{EVisitState.Visited}|{ESeatEvaluate.Normal}|{EVoiceEvaluate.Normal}|4"},
             { "4", $"不满意|{EVisitState.SMSUnsatisfied}|{ESeatEvaluate.NoSatisfied}|{EVoiceEvaluate.NoSatisfied}|2"},
             { "5", $"非常不满意|{EVisitState.SMSUnsatisfied}|{ESeatEvaluate.NoSatisfied}|{EVoiceEvaluate.VeryNoSatisfied}|2"},
         };
+        var replyTxt = data.SmsReplyContent.Trim();
+        var result = string.Empty;
+        if (dics.TryGetValue(replyTxt, out result) == false)
+        {
+            var m = dics.FirstOrDefault(item => item.Value.StartsWith(replyTxt));
+            replyTxt = m.Key;
+            result = m.Value;
+        }
 
-        var replyTxt = dto.SmsReplyContent.Trim();
-        var result = dics[replyTxt];
-        if (result.IsNullOrEmpty()) throw new UserFriendlyException($"用户回复短信内容异常; reply: {replyTxt}");
+        if (result.IsNullOrEmpty()) throw new UserFriendlyException($"用户回复短信内容异常; reply: {data.SmsReplyContent}");
         var replySplit = result.Split("|");
         if (new string[] { "4", "5" }.Contains(replyTxt))
         {

+ 9 - 0
src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs

@@ -20,4 +20,13 @@ public class BiQueryHourCallDto
     public DateTime StartTime { get; set; }
     public DateTime? EndTime { get; set; }
     public string Source {get; set; }
+}
+
+public class BiQueryGateWayDto
+{
+    public DateTime StartTime { get; set; }
+    
+    public DateTime EndTime { get; set; }
+    
+    public string gateway { get; set; }
 }

+ 28 - 0
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/TianQuePushOrderReceiverDto.cs

@@ -0,0 +1,28 @@
+namespace Hotline.Share.Dtos.DataSharing.PusherHotlineDto
+{
+    /// <summary>
+    /// 天阙推送工单返回
+    /// </summary>
+    public class TianQuePushOrderReceiverDto
+    {
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string OrderNo { get; set; }
+
+        /// <summary>
+        /// 随手拍工单编号
+        /// </summary>
+        public string? AppealNumber { get; set; }
+
+        /// <summary>
+        /// 区域id
+        /// </summary>
+        public string? OrgId { get; set; }
+
+        /// <summary>
+        /// 自动退回时间
+        /// </summary>
+        public DateTime? AutoBackTime { get; set; }
+    }
+}

+ 107 - 0
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/TianQueReceiverOpinionDto.cs

@@ -0,0 +1,107 @@
+using Hotline.Share.Dtos.File;
+
+namespace Hotline.Share.Dtos.DataSharing.PusherHotlineDto
+{
+    public class TianQueReceiverOpinionDto
+    {
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string No { get; set; }
+
+        /// <summary>
+        /// 办理时间
+        /// </summary>
+        public DateTime? HandleTime { get; set; }
+
+        /// <summary>
+        /// 办理人
+        /// </summary>
+        public string? HandleUser { get; set; }
+
+        /// <summary>
+        /// 办理部门
+        /// </summary>
+        public string? HandleOrgName { get; set; }
+
+        /// <summary>
+        /// 办理状态 1,7:流转 2:办结 3:退回 4:网格员签收 5:消息推送 6: 超时自动退单
+        /// </summary>
+        public string? HandleType { get; set; }
+
+        /// <summary>
+        /// 是否属实
+        /// </summary>
+        public bool ISTrue { get; set; }
+
+        /// <summary>
+        /// 是否重复 
+        /// </summary>
+        public bool IsRepeat { get; set; }
+
+        /// <summary>
+        /// 重复工单号
+        /// </summary>
+        public string? RepeatNo { get; set; }
+
+        /// <summary>
+        /// 是否隐患
+        /// </summary>
+        public bool IsHiddenDanger { get; set; }
+
+        /// <summary>
+        /// 是否重大隐患 
+        /// </summary>
+        public bool IsMajorHidden { get; set; }
+
+        /// <summary>
+        /// 网格员姓名
+        /// </summary>
+        public string? MemberName { get; set; }
+
+        /// <summary>
+        /// 网格员电话
+        /// </summary>
+        public string? MemberMobile { get; set; }
+
+        /// <summary>
+        /// 网格化诉求编号
+        /// </summary>
+        public string? AppealNumber { get; set; }
+
+        /// <summary>
+        /// 办理内容
+        /// </summary>
+        public string? ReplyContent { get; set; }
+
+        /// <summary>
+        /// 区域id
+        /// </summary>
+        public string? AreaId { get; set; }
+
+        /// <summary>
+        /// 区域名称
+        /// </summary>
+        public string? AreaName { get; set; }
+
+        /// <summary>
+        /// 区域全称
+        /// </summary>
+        public string? AreaFullName { get; set; }
+
+        /// <summary>
+        /// 区域编码
+        /// </summary>
+        public string? DepartmentNo { get; set; }
+
+        /// <summary>
+        /// 区域上级Id
+        /// </summary>
+        public string? ParentAreaId { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<FileDto> FileDtos { get; set; }
+    }
+}

+ 18 - 0
src/Hotline.Share/Dtos/DataSharingSearch/AcceptTypeList.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.DataSharingSearch
+{
+    /// <summary>
+    /// 受理类型
+    /// </summary>
+    public class AcceptTypeList
+    {
+        public string? Name { get; set; }
+
+        public string? Value { get; set; }
+    }
+}

+ 5 - 0
src/Hotline.Share/Dtos/DataSharingSearch/GetOrderDetailDto.cs

@@ -52,5 +52,10 @@ namespace Hotline.Share.Dtos.DataSharingSearch
         /// 区域ID
         /// </summary>
         public string? AreaCode { get; set; }
+
+        /// <summary>
+        /// 工单办理状态Code  1:办理中,2:办理完成 ,其他查询全部
+        /// </summary>
+        public string? HandleStateCode { get; set; }
     }
 }

+ 39 - 0
src/Hotline.Share/Dtos/DataSharingSearch/GridOperatorSendSmsDto.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.DataSharingSearch
+{
+    public class GridOperatorSendSmsDto
+    {
+        /// <summary>
+        /// 唯一标识/工单编号
+        /// </summary>
+        public string ReplyCode { get; set; }
+
+        /// <summary>
+        /// 网格员姓名
+        /// </summary>
+        public string? MemberName { get; set; }
+
+        /// <summary>
+        /// 网格员电话
+        /// </summary>
+        public string? MemberMobile { get; set; }
+
+        /// <summary>
+        /// 网格化诉求编号
+        /// </summary>
+        public string? AppealNumber { get; set; }
+
+        /// <summary>
+        /// 短信类型 1: 短信  2:超时提醒  
+        /// </summary>
+        public string SendType { get; set; }
+    }
+}

+ 6 - 1
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -908,10 +908,15 @@ namespace Hotline.Share.Dtos.Order
         public bool IsProvince { get; set; }
 
         /// <summary>
-        /// 同步省工单编号和省上传下来的工单都用这个字段
+        /// 省本地编号
         /// </summary>
         public string? ProvinceNo { get; set; }
 
+        /// <summary>
+        /// 省交办编号
+        /// </summary>
+        public string? ReceiveProvinceNo { get; set; }
+
         /// <summary>
         /// 省过期时间(省工单才有)
         /// </summary>

+ 1 - 1
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -858,7 +858,7 @@ namespace Hotline.Share.Dtos.Order
     /// <summary>
     /// 回访详情的历史记录
     /// </summary>
-    public class OrderVisitDetailHistiryDto
+    public class OrderVisitDetailHistoryDto
     {
         public EVoiceEvaluate? VoiceEvaluate { get; set; }
         public string? VoiceEvaluateTxt => this.VoiceEvaluate?.GetDescription();

+ 1 - 1
src/Hotline.Share/Dtos/Order/OrderWaitedDto.cs

@@ -86,7 +86,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 接办部门
         /// </summary>
-        public string? CurrentHandleOrgName { get; set; }
+        public string? ActualHandleOrgName { get; set; }
 
         /// <summary>
         /// 状态

+ 6 - 0
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -58,6 +58,12 @@ namespace Hotline.Share.Dtos.Order
         public string? OrgId { get; set; }
         //public List<string> OrgCodes { get; set; } = new();
 
+        public string? OrgLevelOneName { get; set; }
+        /// <summary>
+        /// 接办名称(综合查询使用)
+        /// </summary>
+        public string? ActualHandleOrgName { get; set; }
+
         /// <summary>
         /// 受理坐席名字或工号(×)
         /// </summary>

+ 2 - 1
src/Hotline.Share/Dtos/Order/SendBackDto.cs

@@ -26,7 +26,7 @@ namespace Hotline.Share.Dtos.Order
 		public string? AuditContent { get; set; }
 
 
-		/// <summary>
+			/// <summary>
 		/// 是否允许再次退回
 		/// </summary>
 		public bool? IsReturnAgain { get; set; }
@@ -121,6 +121,7 @@ namespace Hotline.Share.Dtos.Order
 			return 0;
 		}
 
+		public bool IsReturnAgainShow => ApplyOrgId != "001" && SendBackOrgId == "001";
 
 	}
 	public class SendBackBaseDto

+ 7 - 1
src/Hotline.Share/Dtos/Settings/TimeConfig.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Settings;
 using Hotline.Share.Tools;
@@ -26,6 +27,11 @@ namespace Hotline.Share.Dtos.Settings
         /// </summary>
         public string? AcceptTypeCode { get; set; }
 
+        /// <summary>
+        /// 流程方向
+        /// </summary>
+        public EFlowDirection FlowDirection { get; set; }
+
         /// <summary>
         /// 24小时办结
         /// </summary>
@@ -75,7 +81,7 @@ namespace Hotline.Share.Dtos.Settings
                 if (timeText.IsNullOrEmpty()) return $"{Count}个{TimeType.GetDescription()}";
                 return timeText;
             }
-            set 
+            set
             {
                 timeText = value;
             }

+ 5 - 0
src/Hotline.Share/Enums/Order/ESource.cs

@@ -74,6 +74,11 @@ public enum ESource
     /// </summary>
     WLLZ = 404,
 
+    /// <summary>
+    /// 宜办事
+    /// </summary>
+    YBS = 405,
+
     #region 导入类型(>=500  <530为导入来源)
     /// <summary>
     /// 麻辣社区导入

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

@@ -7,7 +7,7 @@
     <GenerateDocumentationFile>True</GenerateDocumentationFile>
     <NoWarn>$(NoWarn);1591;8618;</NoWarn>
     <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-    <Version>1.0.96</Version>
+    <Version>1.0.105</Version>
   </PropertyGroup>
 
   <ItemGroup>
@@ -15,7 +15,7 @@
     <PackageReference Include="Mapster" Version="7.3.0" />
     <PackageReference Include="MediatR.Contracts" Version="1.0.1" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
-    <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
     <PackageReference Include="XF.Utility.EnumExtensions" Version="1.0.4" />
   </ItemGroup>
 

+ 10 - 0
src/Hotline.Share/Mq/EventNames.Share.cs

@@ -104,5 +104,15 @@
         /// 接受省上上传附件
         /// </summary>
         public const string SharingFileInfo = "sharing.file.info";
+
+        /// <summary>
+        /// 接收天阙办理结果
+        /// </summary>
+        public const string TianQueReceiverOpinion = "tian.que.receiver.opinion";
+
+        /// <summary>
+        /// 天阙推送工单,返回信息
+        /// </summary>
+        public const string TianQuePushOrderReceiver = "tian.que.push.order.receiver";
     }
 }

+ 1 - 1
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -466,7 +466,7 @@ public record AcceptTypeStatisticsByDateDetailReq:PagedRequest
     /// <summary>
     /// 接办部门名称
     /// </summary>
-    public string? CurrentHandleOrgName { get; set; }
+    public string? ActualHandleOrgName { get; set; }
 
     /// <summary>
     /// 受理类型Code

+ 7 - 6
src/Hotline/Authentications/Police110SessionContext.cs

@@ -1,15 +1,16 @@
-using XF.Domain.Authentications;
+using Hotline.Configurations;
+using XF.Domain.Authentications;
 
 namespace Hotline.Authentications
 {
     public class Police110SessionContext : ISessionContext
     {
-        public Police110SessionContext()
+        public Police110SessionContext(PublicSecurityConfiguration config)
         {
-            UserId = "e90501d7-c453-e18a-f1fa-3a1177930699";
-            UserName = "市公安局110";
-            OrgId = "001180";
-            OrgName = "市公安局110";
+            UserId = config.UserId;
+            UserName = config.UserName;
+            OrgId = config.OrgId;
+            OrgName = config.OrgName;
             OrgLevel = 1;
         }
 

+ 7 - 6
src/Hotline/Authentications/ProvinceSessionContext.cs

@@ -1,15 +1,16 @@
-using XF.Domain.Authentications;
+using Hotline.Configurations;
+using XF.Domain.Authentications;
 
 namespace Hotline.Authentications
 {
     public class ProvinceSessionContext : ISessionContext
     {
-        public ProvinceSessionContext()
+        public ProvinceSessionContext(CityProvinceConfiguration config)
         {
-            UserId = "03aba148-e7b1-cd03-bf00-3a1177930508";
-            UserName = "省12345平台";
-            OrgId = "001171";
-            OrgName = "省12345平台";
+            UserId = config.UserId;
+            UserName = config.UserName;
+            OrgId = config.OrgId;
+            OrgName = config.OrgName;
             OrgLevel = 1;
         }
 

+ 6 - 5
src/Hotline/Authentications/SessionContextCreator.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Configurations;
 using Hotline.Share.Enums.Order;
 using XF.Domain.Authentications;
 
@@ -10,18 +11,18 @@ namespace Hotline.Authentications
 {
     public class SessionContextCreator
     {
-        public static ISessionContext CreateSessionContext(string source)
+        public static ISessionContext CreateSessionContext(string source, CityBaseConfiguration cityBase)
         {
             switch (source)
             {
                 case "province":
-                    return new ProvinceSessionContext();
+                    return new ProvinceSessionContext(cityBase.CityProvince);
                 case "110":
-                    return new Police110SessionContext();
+                    return new Police110SessionContext(cityBase.PublicSecurity);
                 case "yb-enterprise":
-                    return new YbEnterpriseSessionContext();
+                    return new YbEnterpriseSessionContext(cityBase.CityEnterprise);
                 case "zzpt":
-                    return new ZzptSessionContext();
+                    return new ZzptSessionContext(cityBase.ComprehensiveTreatment);
                 default:
                     throw new ArgumentOutOfRangeException(nameof(source), source, null);
             }

+ 7 - 6
src/Hotline/Authentications/YbEnterpriseSessionContext.cs

@@ -1,15 +1,16 @@
-using XF.Domain.Authentications;
+using Hotline.Configurations;
+using XF.Domain.Authentications;
 
 namespace Hotline.Authentications
 {
     public class YbEnterpriseSessionContext : ISessionContext
     {
-        public YbEnterpriseSessionContext()
+        public YbEnterpriseSessionContext(CityEnterpriseConfiguration config)
         {
-            UserId = "ce42562c-afc1-764b-1dc8-3a1177930346";
-            UserName = "联系服务企业";
-            OrgId = "001181";
-            OrgName = "联系服务企业";
+            UserId = config.UserId;
+            UserName = config.UserName;
+            OrgId = config.OrgId;
+            OrgName = config.OrgName;
             OrgLevel = 1;
         }
 

+ 7 - 6
src/Hotline/Authentications/ZzptSessionContext.cs

@@ -1,15 +1,16 @@
-using XF.Domain.Authentications;
+using Hotline.Configurations;
+using XF.Domain.Authentications;
 
 namespace Hotline.Authentications
 {
     public class ZzptSessionContext : ISessionContext
     {
-        public ZzptSessionContext()
+        public ZzptSessionContext(ComprehensiveTreatmentConfiguration config)
         {
-            UserId = "d4cb7151-41fa-a810-6c1e-3a117792fc0c";
-            UserName = "综治平台";
-            OrgId = "001143";
-            OrgName = "综治平台";
+            UserId = config.UserId;
+            UserName = config.UserName;
+            OrgId = config.OrgId;
+            OrgName = config.OrgName;
             OrgLevel = 1;
         }
 

+ 30 - 1
src/Hotline/CallCenter/Calls/CallNative.cs

@@ -19,106 +19,136 @@ namespace Hotline.CallCenter.Calls
         /// <summary>
         /// 通话记录编号
         /// </summary>
+        [SugarColumn(ColumnDescription = "通话记录编号")]
         public string CallNo { get; set; }
 
+        [SugarColumn(ColumnDescription = "通话方向")]
         public ECallDirection Direction { get; set; }
 
         /// <summary>
         /// 主叫
         /// </summary>
+        [SugarColumn(ColumnDescription = "主叫号码")]
         public string FromNo { get; set; }
 
         /// <summary>
         /// 被叫
         /// </summary>
+        [SugarColumn(ColumnDescription = "被叫号码")]
         public string ToNo { get; set; }
 
         /// <summary>
         /// 响应分机号
         /// </summary>
+        [SugarColumn(ColumnDescription = "响应分机号")]
         public string TelNo { get; set; }
 
         /// <summary>
         /// 挂断方
         /// </summary>
+        [SugarColumn(ColumnDescription = "挂断方")]
         public EEndBy? EndBy { get; set; }
 
         /// <summary>
         /// IVR开始时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "IVR开始时间")]
         public DateTime? BeginIvrTime { get; set; }
+
         /// <summary>
         /// IVR结束时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "IVR结束时间")]
         public DateTime? EndIvrTime { get; set; }
+
         /// <summary>
         /// 开始等待时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "开始等待时间")]
         public DateTime? BeginQueueTime { get; set; }
+
         /// <summary>
         /// 结束等待时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "结束等待时间")]
         public DateTime? EndQueueTime { get; set; }
+
         /// <summary>
         /// 开始振铃时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "开始振铃时间")]
         public DateTime? BeginRingTime { get; set; }
+
         /// <summary>
         /// 结束振铃时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "结束振铃时间")]
         public DateTime? EndRingTime { get; set; }
+
         /// <summary>
         /// 接听时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "接听时间")]
         public DateTime? AnsweredTime { get; set; }
+
         /// <summary>
         /// 挂机时间
         /// </summary>
+        [SugarColumn(ColumnDescription = "挂机时间")]
         public DateTime EndTime { get; set; }
 
         /// <summary>
         /// 分机组id(技能组Id)
         /// </summary>
+        [SugarColumn(ColumnDescription = "分机组ID")]
         public string? GroupId { get; set; }
 
         /// <summary>
         /// 工号
         /// </summary>
+        [SugarColumn(ColumnDescription = "工号")]
         public string? StaffNo { get; set; }
 
         /// <summary>
         /// 话务员id
         /// </summary>
+        [SugarColumn(ColumnDescription = "话务员ID")]
         public string? UserId { get; set; }
 
         /// <summary>
         /// 话务员姓名
         /// </summary>
+        [SugarColumn(ColumnDescription = "话务员姓名")]
         public string? UserName { get; set; }
 
         /// <summary>
         /// 评分
         /// </summary>
+        [SugarColumn(ColumnDescription = "评分")]
         public int Score { get; set; }
 
         /// <summary>
         /// 通话时长(秒)
         /// </summary>
+        [SugarColumn(ColumnDescription = "通话时长(秒)")]
         public int Duration { get; set; }
 
         /// <summary>
         /// 响铃时长(秒)
         /// </summary>
+        [SugarColumn(ColumnDescription = "响铃时长(秒)")]
         public int RingDuration { get; set; }
 
         /// <summary>
         /// 等待时长
         /// </summary>
+        [SugarColumn(ColumnDescription = "等待时长")]
         public int WaitDuration { get; set; }
 
         /// <summary>
         /// 通话录音
         /// </summary>
+        [SugarColumn(ColumnDescription = "通话录音")]
         public string AudioFile { get; set; }
 
         //public string? ExternalId { get; set; }
@@ -126,6 +156,5 @@ namespace Hotline.CallCenter.Calls
         //public string? OrderNo { get; set; }
 
         //public string? Title { get; set; }
-
     }
 }

+ 25 - 0
src/Hotline/CallCenter/Calls/CallSatisfaction.cs

@@ -0,0 +1,25 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.CallCenter.Calls
+{
+    public class CallSatisfaction:CreationEntity
+    {
+        ///Id 和CallNative.Id一致   和Order.CallId 一致
+
+        /// <summary>
+        /// 兴唐通话记录编号(业务不用)
+        /// </summary>
+        public string CallNo { get; set; }
+
+        /// <summary>
+        /// 按键结果
+        /// </summary>
+        public string Result { get; set; }
+    }
+}

+ 1 - 0
src/Hotline/Configurations/AppConfiguration.cs

@@ -8,6 +8,7 @@ namespace Hotline.Configurations
 {
     public class AppConfiguration
     {
+        public string OldFilesUrls {  get; set; }
         public string AppScope { get; set; }
         public YiBinConfiguration YiBin { get; set; }
         public ZiGongConfiguration ZiGong { get; set; }

+ 42 - 0
src/Hotline/Configurations/CityBaseConfiguration.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Configurations
+{
+	public class CityBaseConfiguration
+	{
+		public CityProvinceConfiguration CityProvince { get; set; }
+
+		public CityProvinceAssignConfiguration CityProvinceAssign { get; set; }
+		public PublicSecurityConfiguration PublicSecurity { get; set; }
+		public CityEnterpriseConfiguration CityEnterprise { get; set; }
+		public ComprehensiveTreatmentConfiguration ComprehensiveTreatment { get; set; }
+	}
+
+	public class CityProvinceConfiguration : DefaultCityBaseConfiguration
+	{
+	}
+	public class CityProvinceAssignConfiguration : DefaultCityBaseConfiguration
+	{
+	}
+	public class PublicSecurityConfiguration : DefaultCityBaseConfiguration
+	{
+	}
+	public class CityEnterpriseConfiguration : DefaultCityBaseConfiguration
+	{
+	}
+	public class ComprehensiveTreatmentConfiguration : DefaultCityBaseConfiguration
+	{
+	}
+
+	public abstract class DefaultCityBaseConfiguration
+	{
+		public string UserId { get; set; }
+		public string UserName { get; set; }
+		public string OrgId { get; set; }
+		public string OrgName { get; set; }
+	}
+}

+ 31 - 26
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -106,6 +106,11 @@ public partial class Workflow : CreationEntity
     /// </summary>
     public string? ActualHandleOrgCode { get; set; }
 
+    /// <summary>
+    /// 实际办理部门等级
+    /// </summary>
+    public int? ActualHandleOrgLevel { get; set; }
+    
     /// <summary>
     /// 实际办理部门行政区划编码
     /// </summary>
@@ -484,19 +489,23 @@ public partial class Workflow
     /// <summary>
     /// 指派、未办理时调用
     /// </summary>
-    public void UpdateActualStepWhenAssign(
-        WorkflowStep nextStep,
-        string? actualHandleOrgCode = null,
-        string? actualHandleOrgName = null
-        )
+    public void UpdateActualStepWhenAssign(WorkflowStep nextStep, FlowStepHandler nextStepHandler)
     {
         ResetActualStep();
         ActualHandleStepId = nextStep.Id;
         ActualHandleStepCode = nextStep.Code;
         ActualHandleStepName = nextStep.Name;
         ActualHandleStepCreateTime = nextStep.CreationTime;
-        ActualHandleOrgCode = actualHandleOrgCode;
-        ActualHandleOrgName = actualHandleOrgName;
+        ActualHandlerId = nextStepHandler.UserId;
+        ActualHandlerName = nextStepHandler.Username;
+        ActualHandleOrgCode = nextStepHandler.OrgId;
+        ActualHandleOrgName = nextStepHandler.OrgName;
+        if (!string.IsNullOrEmpty(ActualHandleOrgCode))
+            ActualHandleOrgLevel = ActualHandleOrgCode.CalcOrgLevel();
+
+        //实际办理部门为一级部门时记录
+        if (ActualHandleOrgLevel.HasValue && ActualHandleOrgLevel == 1)
+            UpdateLevelOneOrg(ActualHandleOrgCode, ActualHandleOrgName);
     }
 
     /// <summary>
@@ -504,30 +513,25 @@ public partial class Workflow
     /// </summary>
     public void UpdateActualStepWhenHandle(
         WorkflowStep step,
-        string handlerId,
-        string? handlerName,
-        string handleOrgId,
-        string? handleOrgName,
         string? handleOrgAreaCode,
         string? handleOrgAreaName,
         int handlerOrgLevel)
     {
-        ActualHandleStepCode = step.Code;
-        ActualHandleStepName = step.Name;
-        ActualHandleStepId = step.Id;
-        ActualHandleStepCreateTime = step.CreationTime;
         ActualHandleStepAcceptTime = step.AcceptTime;
         ActualHandleTime = step.HandleTime;
-        ActualHandlerId = handlerId;
-        ActualHandlerName = handlerName;
-        ActualHandleOrgCode = handleOrgId;
-        ActualHandleOrgName = handleOrgName;
         ActualHandleOrgAreaCode = handleOrgAreaCode;
         ActualHandleOrgAreaName = handleOrgAreaName;
-
-        ////实际办理部门为一级部门时记录
-        //if (handlerOrgLevel == 1)
-        //    UpdateLevelOneOrg(handleOrgId, handleOrgName);
+        ActualHandleOrgLevel = handlerOrgLevel;
+        
+        //坐席->派单存在不选办理对象的场景,所以要补赋值
+        ActualHandleStepId = step.Id;
+        ActualHandleStepCode = step.Code;
+        ActualHandleStepName = step.Name;
+        ActualHandleStepCreateTime = step.CreationTime;
+        ActualHandlerId = step.HandlerId;
+        ActualHandlerName = step.HandlerName;
+        ActualHandleOrgCode = step.HandlerOrgId;
+        ActualHandleOrgName = step.HandlerOrgName;
     }
 
     /// <summary>
@@ -547,12 +551,13 @@ public partial class Workflow
         if (!string.IsNullOrEmpty(CurrentHandleOrgId))
             CurrentHandleOrgLevel = CurrentHandleOrgId.CalcOrgLevel();
 
-        //实际办理部门为一级部门时记录
-        if (CurrentHandleOrgLevel.HasValue && CurrentHandleOrgLevel == 1)
-            UpdateLevelOneOrg(CurrentHandleOrgId, CurrentHandleOrgName);
+        // //实际办理部门为一级部门时记录
+        // if (CurrentHandleOrgLevel.HasValue && CurrentHandleOrgLevel == 1)
+        //     UpdateLevelOneOrg(CurrentHandleOrgId, CurrentHandleOrgName);
     }
 
     public void UpdateCurrentStepAcceptTime(DateTime acceptTime) => CurrentStepAcceptTime = acceptTime;
+    public void UpdateActualStepAcceptTime(DateTime acceptTime) => ActualHandleStepAcceptTime = acceptTime;
 
     /// <summary>
     /// 办理时调用

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

@@ -110,14 +110,9 @@ namespace Hotline.FlowEngine.Workflows
                     PublishStrategy.ParallelWhenAll, cancellationToken);
 
                 //firstStep是否为end,t: 实际办理节点为startStep, 并且handlerId赋值 f: 实际办理节点为firstStep, handlerId未赋值
-                workflow.UpdateActualStepWhenHandle(startStep,
-                    current.RequiredUserId, current.UserName,
-                    current.RequiredOrgId, current.OrgName,
-                    current.OrgAreaCode, current.OrgAreaName,
-                    current.OrgLevel);
-
-                workflow.UpdateCurrentStepWhenHandle(startStep,
-                    current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
+                workflow.UpdateActualStepWhenHandle(startStep, current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
+                
+                workflow.UpdateCurrentStepWhenHandle(startStep, current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
 
                 var endTrace = await EndAsync(workflow, dto, firstStepDefine, startStep, current, expiredTime, cancellationToken);
                 return;
@@ -480,17 +475,12 @@ namespace Hotline.FlowEngine.Workflows
             if (workflow.ActualHandleStepId == currentStep.Id)
             {
                 //更新实际办理节点信息
-                workflow.UpdateActualStepWhenHandle(currentStep,
-                    current.RequiredUserId, current.UserName,
-                    current.RequiredOrgId, current.OrgName,
-                    current.OrgAreaCode, current.OrgAreaName,
-                    current.OrgLevel);
+                workflow.UpdateActualStepWhenHandle(currentStep, current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
             }
 
             if (workflow.CurrentStepId == currentStep.Id)
             {
-                workflow.UpdateCurrentStepWhenHandle(currentStep,
-                    current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
+                workflow.UpdateCurrentStepWhenHandle(currentStep, current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
             }
 
             //检查是否流转到流程终点
@@ -661,7 +651,13 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.SetStatusRunnable();
 
             //更新实际办理节点信息
-            workflow.UpdateActualStepWhenAssign(newPrevStep, prevStep.HandlerOrgId, prevStep.HandlerOrgName);
+            workflow.UpdateActualStepWhenAssign(newPrevStep,new FlowStepHandler
+            {
+                UserId = prevStep.HandlerId,
+                Username = prevStep.HandlerName,
+                OrgId = prevStep.HandlerOrgId,
+                OrgName = prevStep.HandlerOrgName,
+            });
 
             workflow.UpdateCurrentStepWhenAssign(newPrevStep, new FlowStepHandler
             {
@@ -1134,7 +1130,13 @@ namespace Hotline.FlowEngine.Workflows
             var newStartStep =
                 await DuplicateStepWithTraceAsync(workflow, targetStep, EWorkflowTraceType.Recall, cancellationToken);
 
-            workflow.UpdateActualStepWhenAssign(targetStep, targetStep.HandlerOrgId, targetStep.HandlerOrgName);
+            workflow.UpdateActualStepWhenAssign(targetStep,new FlowStepHandler
+            {
+                UserId = targetStep.HandlerId,
+                Username = targetStep.HandlerName,
+                OrgId = targetStep.HandlerOrgId,
+                OrgName = targetStep.HandlerOrgName,
+            });
 
             workflow.UpdateCurrentStepWhenAssign(targetStep, new FlowStepHandler
             {
@@ -1498,6 +1500,12 @@ namespace Hotline.FlowEngine.Workflows
             workflow.UpdateCurrentStepWhenHandle(endStep,
                 current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
             workflow.UpdateCurrentStepAcceptTime(endStep.AcceptTime.Value);
+            
+            //workflow.UpdateActualStepWhenHandle(endStep, current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
+            //workflow.UpdateActualStepAcceptTime(endStep.AcceptTime.Value);
+
+            if(string.IsNullOrEmpty(workflow.OrgLevelOneCode))
+                workflow.UpdateLevelOneOrg(workflow.ActualHandleOrgCode, workflow.ActualHandleOrgName);
 
             await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
@@ -1595,15 +1603,16 @@ namespace Hotline.FlowEngine.Workflows
             {
                 //坐席->派单不选办理对象时
                 workflow.UpdateActualStepWhenAssign(nextSteps.First(),
-                    actualHandleOrgCode: OrgSeedData.CenterId,
-                    actualHandleOrgName: OrgSeedData.CenterName);
+                    new FlowStepHandler
+                    {
+                        OrgId = OrgSeedData.CenterId,
+                        OrgName = OrgSeedData.CenterName
+                    });
             }
             else
             {
                 var nextHandler = dto.NextHandlers.First();
-                workflow.UpdateActualStepWhenAssign(nextSteps.First(),
-                    actualHandleOrgCode: nextHandler.OrgId,
-                    actualHandleOrgName: nextHandler.OrgName);
+                workflow.UpdateActualStepWhenAssign(nextSteps.First(),nextHandler);
             }
 
             //if ( /*workflow.FlowType is EFlowType.Handle &&*/
@@ -2300,7 +2309,13 @@ namespace Hotline.FlowEngine.Workflows
                     null, expiredTime, cancellationToken: cancellationToken)).First();
 
             //更新实际办理节点信息
-            workflow.UpdateActualStepWhenAssign(targetStepNew, targetStep.HandlerOrgId, targetStep.HandlerOrgName);
+            workflow.UpdateActualStepWhenAssign(targetStepNew,new FlowStepHandler
+            {
+                UserId = targetStep.HandlerId,
+                Username = targetStep.HandlerName,
+                OrgId = targetStep.HandlerOrgId,
+                OrgName = targetStep.HandlerOrgName
+            });
 
             workflow.UpdateCurrentStepWhenAssign(targetStepNew, new FlowStepHandler
             {
@@ -2587,8 +2602,13 @@ namespace Hotline.FlowEngine.Workflows
                 if (startCountersignStep.Id == workflow.TopCountersignStepId)
                 {
                     workflow.UpdateActualStepWhenAssign(newStep,
-                        startCountersignStep.HandlerOrgId,
-                        startCountersignStep.HandlerOrgName);
+                        new FlowStepHandler
+                        {
+                            UserId = startCountersignStep.HandlerId,
+                            Username = startCountersignStep.HandlerName,
+                            OrgId = startCountersignStep.HandlerOrgId,
+                            OrgName = startCountersignStep.HandlerOrgName
+                        });
 
                     workflow.UpdateCurrentStepWhenAssign(newStep,
                         new FlowStepHandler

Diferenças do arquivo suprimidas por serem muito extensas
+ 188 - 64
src/Hotline/Orders/Order.cs


+ 1 - 0
src/Hotline/Orders/OrderSendBackAudit.cs

@@ -27,6 +27,7 @@ namespace Hotline.Orders
 		/// 部门等级/分类为:depCodes, 角色为:userIds
 		/// </example>
 		/// </summary>
+		[SugarColumn(ColumnDataType = "json", IsJson = true)]
 		public List<FlowStepHandler>? NextHandlers { get; set; } = new();
 
 		/// <summary>

+ 25 - 1
src/Hotline/Permissions/EPermission.cs

@@ -539,6 +539,11 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName ="发布待办",Name ="数据范围",Description ="数据范围")]
         PublishDataRange = 200808,
+        /// <summary>
+        /// 工单退回
+        /// </summary>
+        [Display(GroupName ="发布待办",Name ="工单退回",Description ="工单退回")]
+        PublishOrderReturn = 200809,
         #endregion
 
         #region 发布列表
@@ -597,6 +602,21 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName ="回访待办",Name ="工单类型",Description ="工单类型")]
         OrderTypeForVisit = 200915,
+        /// <summary>
+        /// 短信回访
+        /// </summary>
+        [Display(GroupName = "回访待办", Name ="短信回访",Description ="短信回访")]
+        SmsOrderVisit = 200916,
+        /// <summary>
+        /// 批量回访
+        /// </summary>
+        [Display(GroupName ="回访待办",Name ="批量回访",Description ="批量回访")]
+        BatchOrderVisit = 200917,
+        /// <summary>
+        /// 重办
+        /// </summary>
+        [Display(GroupName ="回访待办",Name ="重办",Description ="重办")]
+        OrderVisitRedo = 200919,
         #endregion
 
         #region 回访列表
@@ -605,7 +625,11 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName = "业务管理", Name = "回访列表", Description = "回访列表")]
         OrderVisited = 200904,
-
+        /// <summary>
+        /// 修改回访结果
+        /// </summary>
+        [Display(GroupName ="业务管理",Name ="修改回访结果",Description ="修改回访结果")]
+        ModifyOrderVisit = 200918,
         #endregion
 
         #region 智能回访任务

+ 10 - 2
src/Hotline/Push/FWMessage/PushDomainService.cs

@@ -123,6 +123,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// <returns></returns>
     public async Task PushMsgUpdateStateAsync(PushReceiveMessageDto dto, CancellationToken cancellation)
     {
+        _logger.LogInformation("收到短信通知 PushMsgUpdateStateAsync");
         var data = await _messageRepository.GetAsync(p => p.Id == dto.ExternalId, cancellation);
         if (data != null)
         {
@@ -150,8 +151,15 @@ public class PushDomainService : IPushDomainService, IScopeDependency
                 data.SmsReplyTime = Convert.ToDateTime(dto.SmsReplyTime);
                 data.SmsReplyContent = dto.SmsReplyContent;
 
-                if (data.PushBusiness == EPushBusiness.VisitSms)
-                    await _orderVisitRepository.UpdateSmsReplyAsync(dto, data);
+                try
+                {
+                    if (data.PushBusiness == EPushBusiness.VisitSms)
+                        await _orderVisitRepository.UpdateSmsReplyAsync(dto, data);
+                }
+                catch (Exception e)
+                {
+                    _logger.LogError("_orderVisitRepository.UpdateSmsReplyAsync: " + e.Message);
+                }           
             }
             data.Reason = dto.Reason;
             await _messageRepository.UpdateAsync(data, cancellation);

+ 5 - 0
src/Hotline/Settings/SettingConstants.cs

@@ -494,5 +494,10 @@ namespace Hotline.Settings
         /// 是否发送超期短信
         /// </summary>
         public const string IsSendOverTimeSms = "IsSendOverTimeSms";
+
+        /// <summary>
+        /// 可分配回访角色
+        /// </summary>
+        public const string OrderVisitRole = "OrderVisitRole";
     }
 }

+ 16 - 4
src/Hotline/Settings/SystemOrganize.cs

@@ -18,62 +18,73 @@ public class SystemOrganize : CreationSoftDeleteEntity
     // /// 部门编码结构中,中心为顶级
     // /// </remarks>
     // /// </summary>
+    // [SugarColumn(ColumnDescription = "编码")]
     // public string Code { get; set; }
 
     /// <summary>
     /// 组织架构名称
     /// </summary>
+    [SugarColumn(ColumnDescription = "组织架构名称")]
     public string Name { get; set; }
 
     /// <summary>
     /// 组织架构简称
     /// </summary>
+    [SugarColumn(ColumnDescription = "组织架构简称")]
     public string ShortName { get; set; }
 
     /// <summary>
     /// 区域Code(行政区域代码)
     /// </summary>
+    [SugarColumn(ColumnDescription = "区域Code(行政区域代码)")]
     public string? AreaCode { get; set; }
 
     /// <summary>
     /// 区域名称(行政区域名称)
     /// </summary>
+    [SugarColumn(ColumnDescription = "区域名称(行政区域名称)")]
     public string? AreaName { get; set; }
 
     /// <summary>
     /// 部门级别
     /// </summary>
+    [SugarColumn(ColumnDescription = "部门级别")]
     public int Level { get; set; }
 
     /// <summary>
     /// 部门类型
     /// </summary>
+    [SugarColumn(ColumnDescription = "部门类型")]
     public EOrgType OrgType { get; set; }
 
     /// <summary>
     /// 上级ID
     /// </summary>
+    [SugarColumn(ColumnDescription = "上级ID")]
     public string? ParentId { get; set; }
 
     /// <summary>
     /// 上级名称
     /// </summary>
+    [SugarColumn(ColumnDescription = "上级名称")]
     public string? ParentName { get; set; }
 
     /// <summary>
     /// 是否启用
     /// </summary>
+    [SugarColumn(ColumnDescription = "是否启用")]
     public bool IsEnable { get; set; }
 
     /// <summary>
     /// 是否为中心
     /// </summary>
+    [SugarColumn(ColumnDescription = "是否为中心")]
     public bool IsCenter { get; set; }
 
-    [SugarColumn(IsIgnore = true)] 
+    [SugarColumn(IsIgnore = true)]
     public List<SystemOrganize> Children { get; set; }
 
-    [SugarColumn(IsIgnore = true)]
+    [SugarColumn(IsIgnore = true , ColumnDescription = "部门类型描述")]
     public string OrgTypeText => OrgType.GetDescription();
 
     public void InitOrgLevel() => Level = Id.CalcOrgLevel();
@@ -81,10 +92,11 @@ public class SystemOrganize : CreationSoftDeleteEntity
     /// <summary>
     /// 旧系统id
     /// </summary>
+    [SugarColumn(ColumnDescription = "旧系统id")]
     public int? oldBmid { get; set; }
-
 }
 
+// ... (Rest of the OrgExtensions class unchanged)
 public static class OrgExtensions
 {
     public static int CalcOrgLevel(this string orgCode)
@@ -132,4 +144,4 @@ public static class OrgExtensions
             throw UserFriendlyException.SameMessage("无效部门编码");
         return orgId == OrgSeedData.CenterId;
     }
-}
+}

+ 21 - 14
src/Hotline/Settings/TimeLimitDomain/ExpireTimeLimitBase.cs

@@ -78,15 +78,26 @@ public abstract class ExpireTimeLimitBase
 
     public virtual async Task<DateTime> WorkDay_ZG(DateTime date)
     {
-	    //一级部门退回中心的可退回时间为1个工作日(从派单组交办给部门就开始倒计时);节假日派单组派给部门的工单,一级部门退回截止时间该为第2个工作日18: 00
-		var workTime = GetWorkTimes(SettingConstants.WorkTime);
-	    var (WorkBeginTime, WorkEndTime) = GetWorkTime(DateTime.Now, workTime);
-	    if (await IsWorkDay(date))
-	    {
-		    if (date < WorkBeginTime || date > WorkEndTime)
-		    {
-			    date = date.AddDays(1);
-		    }
+	 
+		if (await IsWorkDay(date))
+		{
+			var workTime = GetWorkTimes(SettingConstants.WorkTime);
+			var (WorkBeginTime, WorkEndTime) = GetWorkTime(date, workTime);
+            if (date > WorkBeginTime && date < WorkEndTime)
+            {
+                date = date.AddDays(1);
+				while (await NotWorkDay(date))
+				{
+					date = date.AddDays(1);
+				}
+			}
+            else {
+				date = WorkBeginTime.AddDays(2);
+				while (await NotWorkDay(date))
+				{
+					date = date.AddDays(1);
+				}
+			}
 	    }
 	    else
 	    {
@@ -94,11 +105,7 @@ public abstract class ExpireTimeLimitBase
 		    {
 			    date = date.AddDays(1);
 		    }
-		    while (await NotWorkDay(date))
-		    {
-			    date = date.AddDays(1);
-		    }
-		    date = DateTime.Parse(date.ToShortDateString() + "18:00");
+			date = DateTime.Parse(date.ToShortDateString() + "18:00");
 		}
 	    return date;
     }

+ 3 - 11
src/Hotline/Settings/TimeLimitDomain/ExpireTimeSupplier/ExpireTimeFactory.cs

@@ -12,15 +12,7 @@ public class ExpireTimeFactory : IScopeDependency
     }
 
     public IExpireTimeSupplier GetSupplier(ETimeType timeType)
-    {
-        foreach (var supplier in _expireTimeSuppliers)
-        {
-            if (supplier.GetType().Name == timeType.ToString() + "Supplier")
-            {
-                return supplier;
-            }
-        }
-
-        return _expireTimeSuppliers.First();
-    }
+        => _expireTimeSuppliers
+        .FirstOrDefault(supplier => supplier.GetType().Name == timeType.ToString() + "Supplier")
+        ?? _expireTimeSuppliers.First();
 }

+ 13 - 0
src/Hotline/Settings/TimeLimitDomain/ExpireTimeSupplier/WorkDaySupplier.cs

@@ -41,6 +41,19 @@ public class WorkDaySupplier : IExpireTimeSupplier, IScopeDependency
             {
                 beginTime = WorkBeginTime.AddDays(1);
             }
+            if (await NotWorkDay(beginTime))
+            {
+                beginTime = WorkBeginTime.AddDays(1);
+            }
+        }
+
+        while (true)
+        {
+            if (await IsWorkDay(beginTime))
+            {
+                break;
+            }
+            beginTime = beginTime.AddDays(1);
         }
 
         int day = 1;

+ 22 - 0
src/Hotline/Settings/TimeLimitDomain/LuZhouExpireTimeLimit.cs

@@ -0,0 +1,22 @@
+using Hotline.Caching.Interfaces;
+using Hotline.DI;
+using Hotline.Settings.TimeLimits;
+using MapsterMapper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+using XF.Domain.Repository;
+
+namespace Hotline.Settings.TimeLimitDomain;
+
+[Injection(AppScopes = EAppScope.LuZhou)]
+public class LuZhouExpireTimeLimit : ExpireTimeLimitBase, ICalcExpireTime, IScopeDependency
+{
+    public LuZhouExpireTimeLimit(ISystemSettingCacheManager systemSettingCacheManager, IRepository<TimeLimitSetting> timeLimitSettingRepository, IExpireTimeHandler expireTimeHandler, IMapper mapper, IDaySettingRepository daySettingRepository) : base(systemSettingCacheManager, timeLimitSettingRepository, expireTimeHandler, mapper, daySettingRepository)
+    {
+    }
+}
+

+ 9 - 3
src/Hotline/Settings/TimeLimitDomain/ZiGongExpireTimeLimit.cs

@@ -7,6 +7,7 @@ using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Tools;
 using Mapster;
 using MapsterMapper;
+using Microsoft.Extensions.Logging;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
@@ -27,8 +28,9 @@ public class ZiGongExpireTimeLimit : ExpireTimeLimitBase, ICalcExpireTime, IScop
     private readonly IMapper _mapper;
     private readonly IRepository<SystemSetting> _systemSettingRepository;
     private readonly IDaySettingRepository _daySettingRepository;
+    private readonly ILogger<ZiGongExpireTimeLimit> _logger;
 
-    public ZiGongExpireTimeLimit(ISystemSettingCacheManager systemSettingCacheManager, ITimeLimitSettingRepository timeLimitSettingRepository, IExpireTimeHandler expireTimeHandler, IMapper mapper, IRepository<SystemSetting> systemSettingRepository, IDaySettingRepository daySettingRepository, ITimeLimitSettingAttributeRepository timeLimitSettingAttributeRepository, ITimeLimitSettingInventoryRepository timeLimitSettingInventoryRepository) : base(systemSettingCacheManager, timeLimitSettingRepository, expireTimeHandler, mapper, daySettingRepository)
+    public ZiGongExpireTimeLimit(ISystemSettingCacheManager systemSettingCacheManager, ITimeLimitSettingRepository timeLimitSettingRepository, IExpireTimeHandler expireTimeHandler, IMapper mapper, IRepository<SystemSetting> systemSettingRepository, IDaySettingRepository daySettingRepository, ITimeLimitSettingAttributeRepository timeLimitSettingAttributeRepository, ITimeLimitSettingInventoryRepository timeLimitSettingInventoryRepository, ILogger<ZiGongExpireTimeLimit> logger) : base(systemSettingCacheManager, timeLimitSettingRepository, expireTimeHandler, mapper, daySettingRepository)
     {
         _systemSettingCacheManager = systemSettingCacheManager;
         _timeLimitSettingRepository = timeLimitSettingRepository;
@@ -38,13 +40,17 @@ public class ZiGongExpireTimeLimit : ExpireTimeLimitBase, ICalcExpireTime, IScop
         _daySettingRepository = daySettingRepository;
         _timeLimitSettingAttributeRepository = timeLimitSettingAttributeRepository;
         _timeLimitSettingInventoryRepository = timeLimitSettingInventoryRepository;
+        _logger = logger;
     }
 
     public override async Task<ExpiredTimeWithConfig> CalcExpiredTime(DateTime beginTime, EFlowDirection flowDirection, OrderTimeClacInfo order)
     {
-        if (EFlowDirection.CenterToOrg == flowDirection)
+        order.FlowDirection = flowDirection;
+        if (EFlowDirection.CenterToOrg == flowDirection || EFlowDirection.CenterToCenter == flowDirection)
         {
             var timeConfig = await GetTimeConfigByOrderAsync(order);
+            if (order.FlowDirection == EFlowDirection.CenterToCenter)
+                _logger.LogInformation($"中心到中心的订单:{timeConfig.ToJson()}");
             timeConfig.WorkTime = GetWorkTimes(SettingConstants.WorkTime);
             var result = await _expireTimeHandler.CalcEndTimeAsync(beginTime, timeConfig);
 
@@ -99,7 +105,7 @@ public class ZiGongExpireTimeLimit : ExpireTimeLimitBase, ICalcExpireTime, IScop
             timeLimitAttribute ??= noBusCodeAttribute;
             if (timeLimitAttribute is null) return true;
             code += timeLimitAttribute.Code;
-            if (timeLimitAttribute is not null && false == timeLimitAttribute.IsCommon)
+            if (timeLimitAttribute.IsCommon == false)
                 return false;
             return true;
         });

+ 109 - 91
src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs

@@ -744,98 +744,100 @@ namespace Hotline.Settings.TimeLimits
             //如果是部门,采用部门计算方式
             switch (timeType)
             {
+                #region 小时计算
                 //新增对应小时
                 //case ETimeType.Hour:
-                    //if (isCenter)
-                    //{
-                    //    //中心计算自然时间
-                    //    return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
-                    //}
-                    //else
-                    //{
-                    //    //部门计算工作时间
-                    //    //查询统一部门工作时间
-                    //    var workTime = _systemSettingRepository.Get(x => x.Code == "WorkTime");
-                    //    if (workTime != null)
-                    //    {
-                    //        //计算一天工作时间(分钟)
-                    //        DateTime WorkBeginTime = DateTime.Parse(DateTime.Now.ToShortDateString() + " " + workTime.SettingValue[0] + ":00");
-                    //        DateTime WorkEndTime = DateTime.Parse(DateTime.Now.ToShortDateString() + " " + workTime.SettingValue[1] + ":00");
-                    //        TimeSpan minuteSpan = new TimeSpan(WorkEndTime.Ticks - WorkBeginTime.Ticks);
-                    //        //一天工作时间(分钟)
-                    //        int minutes = (int)minuteSpan.TotalMinutes;
-                    //        //延期总时间(分钟)
-                    //        int timeValueMinutes = timeValue * 60;
-
-                    //        //判断开始时间不在工时间段修正时间复位至当天或者第二天的开始时间(如果大于结束时间则复位至第二天的开始时间)
-                    //        if (beginTime < WorkBeginTime)
-                    //        {
-                    //            beginTime = WorkBeginTime;
-                    //        }
-                    //        else
-                    //        {
-                    //            if (beginTime > WorkEndTime)
-                    //            {
-                    //                beginTime = WorkBeginTime.AddDays(1);
-                    //            }
-                    //        }
-
-                    //        //判断第一天时间是否足够
-                    //        TimeSpan firstMinuteSpan = new TimeSpan(WorkEndTime.Ticks - beginTime.Ticks);
-                    //        //计算开始时间的第一天时间
-                    //        int firstMinute = (int)firstMinuteSpan.TotalMinutes;
-                    //        //判断第一天时间是否足够
-                    //        if (firstMinute > timeValueMinutes)
-                    //        {
-                    //            //足够
-                    //            bool canWhile = true;
-                    //            while (canWhile)
-                    //            {
-                    //                //判断开始时间是否在工作日
-                    //                if (IsWorkDay(beginTime))
-                    //                {
-                    //                    return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
-                    //                }
-                    //                else
-                    //                {
-                    //                    //如果不是工作日就加一天
-                    //                    beginTime = beginTime.AddDays(1);
-                    //                }
-                    //            }
-                    //            return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
-                    //        }
-                    //        else
-                    //        {
-                    //            //不够
-                    //            bool canWhile = true;
-                    //            while (canWhile)
-                    //            {
-                    //                //判断开始时间是否在工作日
-                    //                if (IsWorkDay(beginTime))
-                    //                {
-                    //                    //在工作日
-                    //                    timeValueMinutes = timeValueMinutes - minutes;
-                    //                    if (timeValueMinutes > 0)
-                    //                    {
-                    //                        beginTime = beginTime.AddDays(1);
-                    //                    }
-                    //                    else
-                    //                    {
-                    //                        return new TimeResult { EndTime = beginTime.AddMinutes(timeValueMinutes), RuleStr = timeValue + "小时" };
-                    //                    }
-                    //                }
-                    //                else
-                    //                {
-                    //                    //如果不是工作日
-                    //                    beginTime = beginTime.AddDays(1);
-                    //                }
-                    //            }
-                    //        }
-
-                    //    }
-                    //    return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
-                    //}
-                 //   return null;
+                //if (isCenter)
+                //{
+                //    //中心计算自然时间
+                //    return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
+                //}
+                //else
+                //{
+                //    //部门计算工作时间
+                //    //查询统一部门工作时间
+                //    var workTime = _systemSettingRepository.Get(x => x.Code == "WorkTime");
+                //    if (workTime != null)
+                //    {
+                //        //计算一天工作时间(分钟)
+                //        DateTime WorkBeginTime = DateTime.Parse(DateTime.Now.ToShortDateString() + " " + workTime.SettingValue[0] + ":00");
+                //        DateTime WorkEndTime = DateTime.Parse(DateTime.Now.ToShortDateString() + " " + workTime.SettingValue[1] + ":00");
+                //        TimeSpan minuteSpan = new TimeSpan(WorkEndTime.Ticks - WorkBeginTime.Ticks);
+                //        //一天工作时间(分钟)
+                //        int minutes = (int)minuteSpan.TotalMinutes;
+                //        //延期总时间(分钟)
+                //        int timeValueMinutes = timeValue * 60;
+
+                //        //判断开始时间不在工时间段修正时间复位至当天或者第二天的开始时间(如果大于结束时间则复位至第二天的开始时间)
+                //        if (beginTime < WorkBeginTime)
+                //        {
+                //            beginTime = WorkBeginTime;
+                //        }
+                //        else
+                //        {
+                //            if (beginTime > WorkEndTime)
+                //            {
+                //                beginTime = WorkBeginTime.AddDays(1);
+                //            }
+                //        }
+
+                //        //判断第一天时间是否足够
+                //        TimeSpan firstMinuteSpan = new TimeSpan(WorkEndTime.Ticks - beginTime.Ticks);
+                //        //计算开始时间的第一天时间
+                //        int firstMinute = (int)firstMinuteSpan.TotalMinutes;
+                //        //判断第一天时间是否足够
+                //        if (firstMinute > timeValueMinutes)
+                //        {
+                //            //足够
+                //            bool canWhile = true;
+                //            while (canWhile)
+                //            {
+                //                //判断开始时间是否在工作日
+                //                if (IsWorkDay(beginTime))
+                //                {
+                //                    return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
+                //                }
+                //                else
+                //                {
+                //                    //如果不是工作日就加一天
+                //                    beginTime = beginTime.AddDays(1);
+                //                }
+                //            }
+                //            return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
+                //        }
+                //        else
+                //        {
+                //            //不够
+                //            bool canWhile = true;
+                //            while (canWhile)
+                //            {
+                //                //判断开始时间是否在工作日
+                //                if (IsWorkDay(beginTime))
+                //                {
+                //                    //在工作日
+                //                    timeValueMinutes = timeValueMinutes - minutes;
+                //                    if (timeValueMinutes > 0)
+                //                    {
+                //                        beginTime = beginTime.AddDays(1);
+                //                    }
+                //                    else
+                //                    {
+                //                        return new TimeResult { EndTime = beginTime.AddMinutes(timeValueMinutes), RuleStr = timeValue + "小时" };
+                //                    }
+                //                }
+                //                else
+                //                {
+                //                    //如果不是工作日
+                //                    beginTime = beginTime.AddDays(1);
+                //                }
+                //            }
+                //        }
+
+                //    }
+                //    return new TimeResult { EndTime = beginTime.AddHours(timeValue), RuleStr = timeValue + "小时" };
+                //}
+                //   return null;
+                #endregion
                 //新增工作日
                 case ETimeType.WorkDay:
 
@@ -852,8 +854,9 @@ namespace Hotline.Settings.TimeLimits
                         double workMinutes = duration.TotalMinutes;
                         double totalWorkMinutes = (workMinutes * timeValue) * (Percentage/100.00);
                         double totalWorkMinutesOne = (workMinutes * timeValue) * (PercentageOne / 100.00);
-                        
+
                         //判断开始时间不在工时间段修正时间复位至当天或者第二天的开始时间(如果大于结束时间则复位至第二天的开始时间)
+                        
                         if (beginTime < WorkBeginTime)
                         {
                             beginTime = WorkBeginTime;
@@ -864,6 +867,21 @@ namespace Hotline.Settings.TimeLimits
                             {
                                 beginTime = WorkBeginTime.AddDays(1);
                             }
+                            if (!IsWorkDay(beginTime))
+                            {
+                                beginTime = WorkBeginTime.AddDays(1);
+                            }
+                        }
+
+                        while (true)
+                        {
+                            if (IsWorkDay(beginTime))
+                            {
+                                break;
+                            }
+                            beginTime = beginTime.AddDays(1);
+                            WorkBeginTime = WorkBeginTime.AddDays(1);
+                            WorkEndTime = WorkEndTime.AddDays(1);
                         }
 
                         int day = 1;

+ 26 - 1
src/Hotline/dataview.md

@@ -54,7 +54,7 @@ CASE
 	ELSE
 		'-'
 END AS "OrgLevelTwoName" , 
-"CurrentHandleOrgName" AS "CurrentHandleOrgName" , 
+"ActualHandleOrgName" AS "ActualHandleOrgName" , 
 to_char("FiledTime", 'YYYY-MM-DD HH24:MI:SS') AS "FiledTime" , 
 "AcceptType" AS "AcceptType" , 
 "HotspotName" AS "HotspotName",
@@ -314,3 +314,28 @@ ordertemp."Content",
 left join order_visit ordervisittemp on ordervisitdetailtemp."VisitId"=ordervisittemp."Id"
 left join "order" ordertemp on ordervisittemp."OrderId" = ordertemp."Id"
 WHERE ordervisitdetailtemp."VisitTarget" = 20 and ordervisittemp."VisitTime">='2024-07-01' and ordervisittemp."VisitTime"<'2024-08-01' and (ordervisitdetailtemp."OrgProcessingResults"->>'Key')::INT=2 and ordervisittemp."VisitState"=30
+
+## 舆情数据
+ select aaa."GateWay" as 热线号码,
+ aaa."CallInCount" as 呼入,
+ aaa."ConnectCount" as 接通,
+ aaa."NoConnectByeCount" as 未接通秒挂,
+ round(round(aaa."ConnectCount",2)/aaa."CallInCount"*100,2) as 接通率,
+ aaa."EffectiveCount" as 有效接通,
+ aaa."DurationSum"/(aaa."EffectiveCount" + aaa."ConnectByeCount") as 平均时长,
+ aaa."DurationSum" as 通话总时长,
+ aaa."ConnectByeCount" as 接通秒挂,
+ aaa."TimelyAnswerCount" as 及时应答数,
+ round(round(aaa."TimelyAnswerCount",2)/aaa."ConnectCount"*100,2) as 有效率 
+	from (
+ SELECT  
+ "Gateway" AS "GateWay" , 
+ SUM(( CASE  WHEN ( "CallDirection" = 0 ) THEN 1  ELSE 0 END )) AS "CallInCount" , 
+ SUM(( CASE  WHEN (( "CallDirection" = 0 ) AND ( "OnState" = 1 )) THEN 1  ELSE 0 END )) AS "ConnectCount" , 
+ SUM(( CASE  WHEN (((( "CallDirection" = 0 ) AND ( "Duration" = 0 )) AND ( "RingTimes" <= 5 )) AND ( "RingTimes" > 0 )) THEN 1  ELSE 0 END )) AS "NoConnectByeCount" , 
+ SUM(( CASE  WHEN (( "CallDirection" = 0 ) AND ( "Duration" >= 15 )) THEN 1  ELSE 0 END )) AS "EffectiveCount" , 
+ SUM(( CASE  WHEN (( "CallDirection" = 0 ) AND ( "OnState" = 1 )) THEN "Duration"  ELSE 0 END )) AS "DurationSum" , 
+ SUM(( CASE  WHEN ((( "CallDirection" = 0 ) AND ( "Duration" > 0 )) AND ( "Duration" <= 5 )) THEN 1  ELSE 0 END )) AS "ConnectByeCount" , 
+ SUM(( CASE  WHEN ((( "CallDirection" = 0 ) AND ( "OnState" = 1 )) AND ( "RingTimes" <= 15 )) THEN 1  ELSE 0 END )) AS "TimelyAnswerCount"  
+ FROM "tr_call_record"  WHERE (( "CreatedTime" >= '2024-09-12 17:00:00' ) AND ( "CreatedTime" <= '2024-09-13 17:00:00' ))  AND ( "Gateway" = '12333' )GROUP BY "Gateway") aaa
+ 

+ 37 - 0
src/XingTang.Sdk/XingtangSatisfaction.cs

@@ -0,0 +1,37 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XingTang.Sdk
+{
+    [SugarTable("call_cti_satisfaction")]
+    public class XingtangSatisfaction
+    {
+        [SugarColumn(IsPrimaryKey = true)]
+        public int Id { get; set; }
+        /// <summary>
+        /// 通话ID
+        /// </summary>
+        [SugarColumn(ColumnName = "callguid")]
+        public string CallNo { get; set; }
+        /// <summary>
+        /// 评价结果
+        /// </summary>
+        public string Result { get; set; }
+
+
+        #region 自建
+
+        public bool IsSync { get; set; }
+
+        public int Tries { get; set; }
+
+        [SugarColumn(IsEnableUpdateVersionValidation = true)]
+        public string Ver { get; set; }
+
+        #endregion
+    }
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff