소스 검색

merge dev -> release

xf 9 달 전
부모
커밋
acb9f6e5b2
70개의 변경된 파일3088개의 추가작업 그리고 453개의 파일을 삭제
  1. 28 12
      src/Hotline.Ai.Jths/AiVisitService.cs
  2. 16 3
      src/Hotline.Api/Controllers/AiController.cs
  3. 254 5
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  4. 17 16
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  5. 95 0
      src/Hotline.Api/Controllers/ContingencyManagementController.cs
  6. 5 0
      src/Hotline.Api/Controllers/IPPbxController.cs
  7. 290 163
      src/Hotline.Api/Controllers/OrderController.cs
  8. 89 11
      src/Hotline.Api/Controllers/TestController.cs
  9. 4 4
      src/Hotline.Api/Controllers/WorkflowController.cs
  10. 1 0
      src/Hotline.Api/StartupExtensions.cs
  11. 2 2
      src/Hotline.Api/config/appsettings.Development.json
  12. 2 2
      src/Hotline.Application.Contracts/Validators/Bi/BiQueryVisitNoSatisfiedDetailDtoValidator.cs
  13. 2 2
      src/Hotline.Application.Contracts/Validators/Bi/QueryOrderDelayDataListRequestValidator.cs
  14. 2 2
      src/Hotline.Application.Contracts/Validators/Bi/QuerySeatRestRequestValidator.cs
  15. 2 2
      src/Hotline.Application.Contracts/Validators/Bi/QuerySeatSwitchRequestValidator.cs
  16. 2 2
      src/Hotline.Application.Contracts/Validators/Bi/QueryVisitNoSatiisfiedRequestValidator.cs
  17. 18 0
      src/Hotline.Application.Contracts/Validators/Order/OrderStartFlowDtoValidator.cs
  18. 8 5
      src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs
  19. 14 4
      src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs
  20. 19 5
      src/Hotline.Application/Handlers/FlowEngine/WorkflowPreviousHandler.cs
  21. 5 0
      src/Hotline.Application/Mappers/CallMapperConfigs.cs
  22. 10 5
      src/Hotline.Application/Mappers/OrderMapperConfigs.cs
  23. 5 1
      src/Hotline.Application/Orders/AiOrderVisitApplication.cs
  24. 12 2
      src/Hotline.Application/Orders/OrderApplication.cs
  25. 10 10
      src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs
  26. 97 0
      src/Hotline.Application/StatisticalReport/CallReportApplication.cs
  27. 24 0
      src/Hotline.Application/StatisticalReport/ICallReportApplication.cs
  28. 80 16
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  29. 24 3
      src/Hotline.Application/Subscribers/DatasharingSubscriber.cs
  30. 69 9
      src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs
  31. 34 2
      src/Hotline.Share/Dtos/Ai/AiDto.cs
  32. 8 3
      src/Hotline.Share/Dtos/Bi/BiOrderDto.cs
  33. 5 0
      src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs
  34. 128 0
      src/Hotline.Share/Dtos/CallCenter/QueryCallsDetailDto.cs
  35. 246 0
      src/Hotline.Share/Dtos/ContingencyManagement/ContingencyManagementOrdersDto.cs
  36. 42 0
      src/Hotline.Share/Dtos/ContingencyManagement/ContingencyManagementPagedKeywordRequest.cs
  37. 15 0
      src/Hotline.Share/Dtos/ContingencyManagement/RecOrderStateDto.cs
  38. 4 4
      src/Hotline.Share/Dtos/FlowEngine/Workflow/QueryWorkflowCountersignDto.cs
  39. 1 1
      src/Hotline.Share/Dtos/JudicialManagement/JudicialManagementAddOrderDto.cs
  40. 4 1
      src/Hotline.Share/Dtos/Knowledge/KnowledgeBiDto.cs
  41. 1 1
      src/Hotline.Share/Dtos/Order/DepartmentAcceptanceTypeStatisticsDto.cs
  42. 16 0
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  43. 58 0
      src/Hotline.Share/Dtos/Order/OrderScreenDetailDto.cs
  44. 64 0
      src/Hotline.Share/Dtos/Order/OrderScreenDto.cs
  45. 1 1
      src/Hotline.Share/Dtos/Order/OrderStartFlowDto.cs
  46. 39 15
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  47. 5 0
      src/Hotline.Share/Dtos/Order/OrderWaitedDto.cs
  48. 216 96
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  49. 197 0
      src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs
  50. 9 3
      src/Hotline.Share/Enums/Order/EScreenStatus.cs
  51. 1 1
      src/Hotline.Share/Hotline.Share.csproj
  52. 10 0
      src/Hotline.Share/Mq/EventNames.Order.cs
  53. 5 0
      src/Hotline.Share/Requests/DepartmentKeyWordRequest.cs
  54. 5 0
      src/Hotline.Share/Requests/DepartmentalProcessingStatisticsDto.cs
  55. 27 14
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  56. 2 0
      src/Hotline/Ai/Visit/IAiVisitService.cs
  57. 13 0
      src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs
  58. 13 0
      src/Hotline/ContingencyManagement/ContingencyManagementHotspot.cs
  59. 204 0
      src/Hotline/ContingencyManagement/ContingencyManagementOrders.cs
  60. 48 2
      src/Hotline/Orders/AiOrderVisitDetail.cs
  61. 22 11
      src/Hotline/Orders/Order.cs
  62. 41 6
      src/Hotline/Orders/OrderScreen.cs
  63. 65 0
      src/Hotline/Orders/OrderScreenDetail.cs
  64. 5 0
      src/Hotline/Orders/OrderVisit.cs
  65. 6 0
      src/Hotline/Orders/OrderVisitDetail.cs
  66. 9 0
      src/Hotline/Settings/SettingConstants.cs
  67. 10 0
      src/Hotline/Settings/SysDicTypeConsts.cs
  68. 11 1
      src/Hotline/Settings/TimeLimits/ITimeLimitDomainService.cs
  69. 231 1
      src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs
  70. 61 4
      src/Hotline/dataview.md

+ 28 - 12
src/Hotline.Ai.Jths/AiVisitService.cs

@@ -114,20 +114,25 @@ namespace Hotline.Ai.Jths
                 taskData.CalledNumber = item.OuterNo;
                 taskData.VariableList = new List<Variable>();
                
-                if (item.Order.FromGender!= EGender.Unknown)
+               
+                if (!string.IsNullOrEmpty(item.Order.FromName))
                 {
-                    if (!string.IsNullOrEmpty(item.Order.FromName))
-                    {
-                        //来电名称
-                        //开发环境 :OC_SCENE_VAR_FIELD11
-                        //生产环境:OC_SCENE_VAR_FIELD12
-                        taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = item.Order.FromName });
-                    }
-                    //来电性别
-                    //开发环境: OC_SCENE_VAR_FIELD14
-                    //生产环境:OC_SCENE_VAR_FIELD14
-                    taskData.VariableList.Add(new Variable() { Code = visitFromGenderKey, Value = item.Order.FromGender == EGender.Female ? "女士" : "先生" });
+                    //来电名称
+                    //开发环境 :OC_SCENE_VAR_FIELD11
+                    //生产环境:OC_SCENE_VAR_FIELD12
+                    taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = item.Order.FromName });
                 }
+                else
+                {
+                    //来电名称
+                    //开发环境 :OC_SCENE_VAR_FIELD11
+                    //生产环境:OC_SCENE_VAR_FIELD12
+                    taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = "市民" });
+                }
+                //来电性别
+                //开发环境: OC_SCENE_VAR_FIELD14
+                //生产环境:OC_SCENE_VAR_FIELD14
+                taskData.VariableList.Add(new Variable() { Code = visitFromGenderKey, Value = item.Order.FromGender == EGender.Female ? "女士" : "先生" });
                 //来电时间
                 //开发环境:OC_SCENE_VAR_FIELD17
                 //生产环境:OC_SCENE_VAR_FIELD19
@@ -178,6 +183,17 @@ namespace Hotline.Ai.Jths
             return null;
         }
 
+        public async Task<AiVisitQueryData> QueryAiVisitTaskEx(string batchId, string taskId, CancellationToken cancellationToken)
+        {
+            var dto = new AiVisitServiceQueryRequest() { BatchUid = batchId, TaskUid = taskId, PageNo = 1, PageSize = 100 };
+            var response = await ExecuteAsync<AiVisitServiceQueryRequest, AiVisitServiceQueryResponse>(_baseUrl + "/edas/task/status/history", Method.Get, dto, cancellationToken);
+            if (response != null && response.Result != null && response.Result.Result.Count > 0)
+            {
+                return new AiVisitQueryData() { Uid = response.Result.Result[0].Uid, Status = response.Result.Result[0].Status };
+            }
+            return null;
+        }
+
 
         public async Task<TResponse> ExecuteAsync<TRequest,TResponse>(string path, Method httpMethod, TRequest request,
             CancellationToken cancellationToken)

+ 16 - 3
src/Hotline.Api/Controllers/AiController.cs

@@ -27,6 +27,7 @@ using Newtonsoft.Json;
 using Novacode.NETCorePort;
 using Org.BouncyCastle.Utilities;
 using SqlSugar;
+using System.Runtime.CompilerServices;
 using System.Threading;
 using XF.Domain.Authentications;
 using XF.Domain.Constants;
@@ -558,6 +559,7 @@ namespace Hotline.Api.Controllers
                             {
                                 aiOrderVisitDetail.AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.Ended; //更新AI子表
                                 aiOrderVisitDetail.AiVisitTime = DateTime.Now;
+                                aiOrderVisitDetail.CallTime = callRecord.CallTime;
                                 aiOrderVisit.VisitedCount++;
                                 //处理结果
                                 var visitDetail = _orderVisitDetailRepository.Queryable().Where(x => x.VisitId == aiOrderVisitDetail.OrderVisit.Id).ToList();
@@ -670,15 +672,17 @@ namespace Hotline.Api.Controllers
                                     x.VisitContent = visitContent;
                                     x.Volved = isSolve;
                                     x.IsContact = isContact;
-                                    if (string.IsNullOrEmpty(orgProcessingResults.Key) || seatEvaluate == null || isSolve == null || isContact == null ||  orgProcessingResults.Value == "不满意")
+                                    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 记录不满意原因到内容中供人工回访甄别选择不满意原因
                                         aiOrderVisitDetail.OrderVisit.VisitState = Share.Enums.Order.EVisitState.WaitForVisit;
+                                        aiOrderVisitDetail.OrderVisit.IsEffectiveAiVisit = false;
                                     }
                                     else
                                     {
                                         aiOrderVisitDetail.OrderVisit.VisitState = Share.Enums.Order.EVisitState.Visited;
+                                        aiOrderVisitDetail.OrderVisit.IsEffectiveAiVisit = true;
                                     }
                                 });
                                 await _orderVisitDetailRepository.UpdateRangeAsync(orgDetail, HttpContext.RequestAborted);
@@ -693,6 +697,15 @@ namespace Hotline.Api.Controllers
                                 aiOrderVisitDetail.OrderVisit.VisitType = Share.Enums.Order.EVisitType.ChipVoiceVisit;
                                 aiOrderVisitDetail.OrderVisit.AiVisitTime();
                                 aiOrderVisitDetail.IsSuccess = true;
+                                aiOrderVisitDetail.AiVolved = isSolve;
+                                aiOrderVisitDetail.AiIsContact = isContact;
+                                aiOrderVisitDetail.AiVolveConent = visitContent;
+                                aiOrderVisitDetail.AiSeatEvaluate = seatEvaluate;
+                                aiOrderVisitDetail.AiOrgProcessingResults = orgProcessingResults;
+                                aiOrderVisitDetail.AiOrgNoSatisfiedReason = visitContent;
+                                aiOrderVisitDetail.AiSeatNoSatisfiedReason = seatVisitContent;
+                                aiOrderVisitDetail.CallTimes = dto.CallTimes;
+
                                 if (orgProcessingResults != null)
                                 {
                                     aiOrderVisitDetail.OrderVisit.NowEvaluate = orgProcessingResults;
@@ -1002,8 +1015,8 @@ namespace Hotline.Api.Controllers
             var items= await _orderVisitRepository.Queryable()
                 .Includes(x=>x.Order)
                 .Where(x => x.VisitState == Share.Enums.Order.EVisitState.WaitForVisit && x.IsCanAiVisit == true && x.EmployeeId == _sessionContext.RequiredUserId)
-                .WhereIF(dto.HotspotIds.Any(), x => dto.HotspotIds.Contains(x.Order.HotspotId)) //热点类型
-                .WhereIF(dto.AcceptTypes.Any(), x => dto.AcceptTypes.Contains(x.Order.AcceptTypeCode)) //受理类型
+                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.Order.HotspotSpliceName != null && d.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+                .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))
                 .ToListAsync();

+ 254 - 5
src/Hotline.Api/Controllers/Bi/BiCallController.cs

@@ -1,13 +1,13 @@
-using Hotline.Caching.Interfaces;
-using Hotline.Caching.Services;
+using Hotline.Application.StatisticalReport;
+using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Tels;
-using Hotline.Orders;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.User;
 using Hotline.Share.Requests;
@@ -18,7 +18,6 @@ using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
 using System.Data;
-using XF.Domain.Constants;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 
@@ -37,6 +36,7 @@ public class BiCallController : BaseController
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly IRepository<Work> _workRepository;
     private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
+    private readonly ICallReportApplication _callReportApplication;
 
 
 
@@ -48,7 +48,8 @@ public class BiCallController : BaseController
         ITrCallRecordRepository trCallRecordRepositoryEx,
         ISystemSettingCacheManager systemSettingCacheManager,
         ISystemDicDataCacheManager sysDicDataCacheManager,
-        IRepository<Work> workRepository)
+        IRepository<Work> workRepository,
+        ICallReportApplication callReportApplication)
     {
         _trCallRecordRepository = trCallRecordRepository;
         _userRepository = userRepository;
@@ -58,6 +59,7 @@ public class BiCallController : BaseController
         _systemSettingCacheManager = systemSettingCacheManager;
         _workRepository = workRepository;
         _sysDicDataCacheManager = sysDicDataCacheManager;
+        _callReportApplication = callReportApplication;
 
     }
 
@@ -161,6 +163,253 @@ public class BiCallController : BaseController
         return ExcelStreamResult(stream, "话务统计分析");
     }
 
+    /// <summary>
+    /// 话务日期明细
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("query_calls_detail")]
+    public async Task<object> QueryCallsDetailAsync([FromQuery] BiQueryCallsDto dto)
+    {
+        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);
+
+        var total = new QueryCallsDetailDto
+        {
+            Date = "合计",
+            Hour = "",
+            InTotal = items.Sum(p => p.InTotal),
+            InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
+            NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
+            TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
+            InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
+            InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
+            TimeoutConnection = items.Sum(p => p.TimeoutConnection),
+            TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
+            QueueByeCount = items.Sum(p => p.QueueByeCount),
+            IvrByeCount = items.Sum(p => p.IvrByeCount),
+            OutTotal = items.Sum(p => p.OutTotal),
+            OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
+        };
+
+        return new { List = items, Total = total };
+
+    }
+
+    /// <summary>
+    /// 话务日期明细--导出
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("query_calls_detail_export")]
+    public async Task<FileStreamResult> QueryCallsDetailExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
+    {
+        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);
+
+        var total = new QueryCallsDetailDto
+        {
+            Date = "合计",
+            Hour = "",
+            InTotal = items.Sum(p => p.InTotal),
+            InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
+            NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
+            TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
+            InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
+            InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
+            TimeoutConnection = items.Sum(p => p.TimeoutConnection),
+            TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
+            QueueByeCount = items.Sum(p => p.QueueByeCount),
+            IvrByeCount = items.Sum(p => p.IvrByeCount),
+            OutTotal = items.Sum(p => p.OutTotal),
+            OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
+        };
+        items.Add(total);
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+        var dtos = items
+            .Select(stu => _mapper.Map(stu, typeof(QueryCallsDetailDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+
+        return ExcelStreamResult(stream, "话务日期明细数据");
+
+    }
+
+    /// <summary>
+    /// 话务日期明细--呼入明细
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("query_incall_calls_list")]
+    public async Task<PagedDto<TrCallDtoNew>> GetInCallCallListAsync([FromQuery] BiQueryCallsDto dto)
+    {
+        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
+            throw UserFriendlyException.SameMessage("请选择时间!");
+        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
+        var (total, items) = await _callReportApplication.QueryCallsDetailInTotalAsync(dto)
+            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+
+        return new PagedDto<TrCallDtoNew>(total, _mapper.Map<IReadOnlyList<TrCallDtoNew>>(items));
+    }
+
+    /// <summary>
+    /// 话务日期明细----导出
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("query_incall_calls_list_export")]
+    public async Task<FileStreamResult> GetInCallCallListExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
+    {
+        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue)
+            throw UserFriendlyException.SameMessage("请选择时间!");
+        dto.QueryDto.EndTime = dto.QueryDto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
+        var query = _callReportApplication.QueryCallsDetailInTotalAsync(dto.QueryDto);
+        List<TrCallRecord> data;
+        if (dto.IsExportAll)
+        {
+            data = await query.ToListAsync(HttpContext.RequestAborted);
+        }
+        else
+        {
+            var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+            data = items;
+        }
+
+        var dataDtos = _mapper.Map<ICollection<TrCallDtoNew>>(data);
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+        var dtos = dataDtos
+            .Select(stu => _mapper.Map(stu, typeof(TrCallDtoNew), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+
+        string name = dto.QueryDto.TypeCode == "2" ? "话务日期-接通明细数据" : "话务日期-总量明细数据";
+
+        return ExcelStreamResult(stream, name);
+
+    }
+
+    /// <summary>
+    /// 话务日期明细--时间段
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("query_calls_hour_detail_list")]
+    public async Task<object> QueryCallsHourDetailListAsync([FromQuery] BiQueryCallsDto dto)
+    {
+        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]);
+        //坐席超时挂断时间
+        int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
+
+        //未接秒挂时间
+        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 items = await _trCallRecordRepositoryEx.QueryCallsHourDetail(dto.StartTime.Value, dto.EndTime.Value, noConnectByeTimes, effectiveTimes
+              , connectByeTimes, CallInOverConnRingTime, SeatChaoTime, dto.Keyword);
+
+        var total = new QueryCallsDetailDto
+        {
+            Date = "",
+            Hour = "合计",
+            InTotal = items.Sum(p => p.InTotal),
+            InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
+            NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
+            TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
+            InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
+            InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
+            TimeoutConnection = items.Sum(p => p.TimeoutConnection),
+            TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
+            QueueByeCount = items.Sum(p => p.QueueByeCount),
+            IvrByeCount = items.Sum(p => p.IvrByeCount),
+            OutTotal = items.Sum(p => p.OutTotal),
+            OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
+        };
+
+        return new { List = items, Total = total };
+
+    }
+
+    /// <summary>
+    /// 话务日期明细--时间段--导出
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("query_calls_hour_detail_list_export")]
+    public async Task<FileStreamResult> QueryCallsHourDetailListExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
+    {
+        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]);
+        //坐席超时挂断时间
+        int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
+
+        //未接秒挂时间
+        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 items = await _trCallRecordRepositoryEx.QueryCallsHourDetail(dto.QueryDto.StartTime.Value, dto.QueryDto.EndTime.Value, noConnectByeTimes, effectiveTimes
+              , connectByeTimes, CallInOverConnRingTime, SeatChaoTime, dto.QueryDto.Keyword);
+
+        var total = new QueryCallsDetailDto
+        {
+            Date = "",
+            Hour = "合计",
+            InTotal = items.Sum(p => p.InTotal),
+            InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
+            NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
+            TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
+            InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
+            InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
+            TimeoutConnection = items.Sum(p => p.TimeoutConnection),
+            TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
+            QueueByeCount = items.Sum(p => p.QueueByeCount),
+            IvrByeCount = items.Sum(p => p.IvrByeCount),
+            OutTotal = items.Sum(p => p.OutTotal),
+            OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
+        };
+
+        items.Add(total);
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+        var dtos = items
+            .Select(stu => _mapper.Map(stu, typeof(QueryCallsDetailDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+
+        return ExcelStreamResult(stream, "话务日期明细-时间段");
+
+    }
 
     /// <summary>
     /// 坐席话务统计分析

+ 17 - 16
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -839,12 +839,12 @@ namespace Hotline.Api.Controllers.Bi
                 .Where(x => x.AiVisitTime >= StartTime && x.AiVisitTime <= EndTime && x.IsSuccess != null).CountAsync();
 
             returnModel.AiVisitSatisfiedCount = await _aiOrderVisitDetailRepository.Queryable()
-                .Includes(x => x.OrderVisit)
-                .Where(x => x.AiVisitTime >= StartTime && x.AiVisitTime <= EndTime && x.IsSuccess == true && SqlFunc.JsonField(x.OrderVisit.NowEvaluate, "Key") != "1" && SqlFunc.JsonField(x.OrderVisit.NowEvaluate, "Key") != "2").CountAsync();
+                //.Includes(x => x.OrderVisit)
+                .Where(x => x.AiVisitTime >= StartTime && x.AiVisitTime <= EndTime && x.IsSuccess == true && SqlFunc.JsonField(x.AiOrgProcessingResults, "Key") == "4").CountAsync();
 
             returnModel.AiVisitNoSatisfiedCount = await _aiOrderVisitDetailRepository.Queryable()
-                .Includes(x => x.OrderVisit)
-                .Where(x => x.AiVisitTime >= StartTime && x.AiVisitTime <= EndTime && x.IsSuccess == true && SqlFunc.JsonField(x.OrderVisit.NowEvaluate, "Key") == "1" && SqlFunc.JsonField(x.OrderVisit.NowEvaluate, "Key") == "2").CountAsync();
+                //.Includes(x => x.OrderVisit)
+                .Where(x => x.AiVisitTime >= StartTime && x.AiVisitTime <= EndTime && x.IsSuccess == true && SqlFunc.JsonField(x.AiOrgProcessingResults, "Key") == "2").CountAsync();
 
             returnModel.AIVisitFailCount = await _aiOrderVisitDetailRepository.Queryable()
                 .Where(x => x.AiVisitTime >= StartTime && x.AiVisitTime <= EndTime && x.IsSuccess == false).CountAsync();
@@ -1443,35 +1443,35 @@ namespace Hotline.Api.Controllers.Bi
                 OrgCode = "",
                 OrgType = "",
                 ZxAllCount = items.Sum(p => p.ZxAllCount),
-                ZxAllTimes = items.Sum(p => p.ZxAllTimes),
+                ZxAllTimes = Math.Round(items.Sum(p => p.ZxAllTimes).Value,2),
                 ZxAcceptanceTypeCode = "10",
 
                 JyAllCount = items.Sum(p => p.JyAllCount),
-                JyAllTimes = items.Sum(p => p.JyAllTimes),
+                JyAllTimes = Math.Round(items.Sum(p => p.JyAllTimes).Value,2),
                 JyAcceptanceTypeCode = "15",
 
                 QzAllCount = items.Sum(p => p.QzAllCount),
-                QzAllTimes = items.Sum(p => p.QzAllTimes),
+                QzAllTimes = Math.Round(items.Sum(p => p.QzAllTimes).Value,2),
                 QzAcceptanceTypeCode = "20",
 
                 ByAllCount = items.Sum(p => p.ByAllCount),
-                ByAllTimes = items.Sum(p => p.ByAllTimes),
+                ByAllTimes = Math.Round(items.Sum(p => p.ByAllTimes).Value,2),
                 ByAcceptanceTypeCode = "25",
 
                 JbAllCount = items.Sum(p => p.JbAllCount),
-                JbAllTimes = items.Sum(p => p.JbAllTimes),
+                JbAllTimes = Math.Round(items.Sum(p => p.JbAllTimes).Value,2),
                 JbAcceptanceTypeCode = "30",
 
                 TsAllCount = items.Sum(p => p.TsAllCount),
-                TsAllTimes = items.Sum(p => p.TsAllTimes),
+                TsAllTimes = Math.Round(items.Sum(p => p.TsAllTimes).Value,2),
                 TsAcceptanceTypeCode = "35",
 
                 QtAllCount = items.Sum(p => p.QtAllCount),
-                QtAllTimes = items.Sum(p => p.QtAllTimes),
+                QtAllTimes = Math.Round(items.Sum(p => p.QtAllTimes).Value,2),
                 QtAcceptanceTypeCode = "40",
 
                 YjAllCount = items.Sum(p => p.YjAllCount),
-                YjAllTimes = items.Sum(p => p.YjAllTimes),
+                YjAllTimes = Math.Round(items.Sum(p => p.YjAllTimes).Value,2),
                 YjAcceptanceTypeCode = "1"
             };
 
@@ -2026,7 +2026,8 @@ namespace Hotline.Api.Controllers.Bi
             .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.OrgName), d => d.CurrentHandleOrgName == dto.OrgName)//接办部门
+                                                                                                           //.WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
+             .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
             .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) //受理时间结束
@@ -2081,9 +2082,9 @@ namespace Hotline.Api.Controllers.Bi
                 .Where(x => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
                 .Where(x => filterTitle.Any(s => x.Title.Contains(s)) == false)
                 .LeftJoin<SystemArea>((it, o) => it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == o.Id)
-                .WhereIF(dto.AreaCodes.Any(), (it, o) => dto.AreaCodes.Contains(it.AreaCode)) //区域
-                .WhereIF(dto.HotspotIds.Any(), (it, o) => dto.HotspotIds.Contains(it.HotspotId)) //热点类型
-                .WhereIF(dto.AcceptTypeCodes.Any(), (it, o) => dto.AcceptTypeCodes.Contains(it.AcceptTypeCode)) //受理类型
+                .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.AcceptTypeCode == dto.AcceptType)//受理类型
+                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), x => x.HotspotSpliceName != null && x.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+                .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), x => x.AreaCode == dto.AreaCode)//区域
                 .GroupBy((it, o) => new
                 {
                     it.AcceptTypeCode,

+ 95 - 0
src/Hotline.Api/Controllers/ContingencyManagementController.cs

@@ -0,0 +1,95 @@
+using Hotline.ContingencyManagement;
+using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.ContingencyManagement;
+using Hotline.Share.Dtos.Order;
+using Hotline.Tools;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using XF.Domain.Authentications;
+using XF.Domain.Repository;
+
+namespace Hotline.Api.Controllers
+{
+    public class ContingencyManagementController : BaseController
+    {
+        private readonly IMapper _mapper;
+        private readonly ISessionContext _sessionContext;
+        private readonly IRepository<ContingencyManagementOrders> _contingencyManagementOrdersRepository;
+
+        public ContingencyManagementController(IMapper mapper,
+            ISessionContext sessionContext,
+            IRepository<ContingencyManagementOrders> contingencyManagementOrdersRepository)
+        {
+            _mapper = mapper;
+            _sessionContext = sessionContext;
+            _contingencyManagementOrdersRepository = contingencyManagementOrdersRepository;
+        }
+
+        /// <summary>
+        /// 应急数据查询
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("getlist")]
+        public async Task<PagedDto<ContingencyManagementOrdersDto>> GetList([FromQuery] ContingencyManagementPagedKeywordRequest dto)
+        {
+            var (total, items) = await _contingencyManagementOrdersRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), p => p.Title.Contains(dto.Title))
+                .WhereIF(!string.IsNullOrEmpty(dto.No), p => p.No.Contains(dto.No))
+                .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), p => p.HotspotSpliceName.Contains(dto.HotspotSpliceName))
+                .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), p => p.AcceptType.Contains(dto.AcceptType))
+                .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), p => p.SourceChannel.Contains(dto.SourceChannel))
+                .WhereIF(dto.FiledStartTime.HasValue, p => p.FiledTime >= dto.FiledStartTime)
+                .WhereIF(dto.FiledEndTime.HasValue, p => p.FiledTime <= dto.FiledEndTime)
+                .WhereIF(dto.StartTime.HasValue, p => p.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, p => p.CreationTime <= dto.EndTime)
+                .OrderByDescending(d => d.FiledTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+
+            return new PagedDto<ContingencyManagementOrdersDto>(total, _mapper.Map<IReadOnlyList<ContingencyManagementOrdersDto>>(items));
+        }
+
+        /// <summary>
+        /// 应急数据查询--导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("getlist_export")]
+        public async Task<FileStreamResult> GetListExport([FromBody] ExportExcelDto<ContingencyManagementPagedKeywordRequest> dto)
+        {
+            var query = _contingencyManagementOrdersRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.Title), p => p.Title.Contains(dto.QueryDto.Title))
+                .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.No), p => p.No.Contains(dto.QueryDto.No))
+                .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.HotspotSpliceName), p => p.HotspotSpliceName.Contains(dto.QueryDto.HotspotSpliceName))
+                .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.AcceptType), p => p.AcceptType.Contains(dto.QueryDto.AcceptType))
+                .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.SourceChannel), p => p.SourceChannel.Contains(dto.QueryDto.SourceChannel))
+                .WhereIF(dto.QueryDto.FiledStartTime.HasValue, p => p.FiledTime >= dto.QueryDto.FiledStartTime)
+                .WhereIF(dto.QueryDto.FiledEndTime.HasValue, p => p.FiledTime <= dto.QueryDto.FiledEndTime)
+                .WhereIF(dto.QueryDto.StartTime.HasValue, p => p.CreationTime >= dto.QueryDto.StartTime)
+                .WhereIF(dto.QueryDto.EndTime.HasValue, p => p.CreationTime <= dto.QueryDto.EndTime)
+                .OrderByDescending(d => d.FiledTime);
+
+            List<ContingencyManagementOrders> data;
+            if (dto.IsExportAll)
+            {
+                data = await query.ToListAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                data = items;
+            }
+            var dataDtos = _mapper.Map<ICollection<ContingencyManagementOrdersDto>>(data);
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+            var dtos = dataDtos
+                .Select(stu => _mapper.Map(stu, typeof(ContingencyManagementOrdersDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+            return ExcelStreamResult(stream, "应急清单数据");
+        }
+    }
+}

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

@@ -404,6 +404,11 @@ namespace Hotline.Api.Controllers
         public async Task<OpenResponse> ReceiveCallRecord([FromBody] ReceiveCallRecordDto dto)
         {
             _logger.LogInformation($"收到通话记录结果回传:{JsonConvert.SerializeObject(dto)}");
+            //bool isHas = await _trCallRecordRepository.AnyAsync(x => x.OtherAccept == dto.other_accept, HttpContext.RequestAborted);
+            //if (isHas)
+            //{
+            //    return OpenResponse.Ok("success");
+            //}
 
             var model = _mapper.Map<TrCallRecord>(dto);
             model.Duration = 0;

+ 290 - 163
src/Hotline.Api/Controllers/OrderController.cs

@@ -1,12 +1,13 @@
-using Consul;
-using DotNetCore.CAP;
+using DotNetCore.CAP;
 using Hotline.Api.Filter;
+using Hotline.Application.CallCenter;
 using Hotline.Application.ExportExcel;
 using Hotline.Application.FlowEngine;
 using Hotline.Application.Orders;
 using Hotline.Application.Quality;
 using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
+using Hotline.ContingencyManagement;
 using Hotline.Enterprise;
 using Hotline.File;
 using Hotline.FlowEngine.Definitions;
@@ -26,6 +27,7 @@ using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.ContingencyManagement;
 using Hotline.Share.Dtos.Enterprise;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
@@ -47,26 +49,16 @@ using MapsterMapper;
 using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.OpenApi.Writers;
+using Microsoft.Extensions.Options;
 using MiniExcelLibs;
 using MongoDB.Driver;
-using NPOI.SS.Formula.Functions;
-using NPOI.SS.Util;
-using Org.BouncyCastle.Utilities;
 using SqlSugar;
-using StackExchange.Redis;
-using System.Diagnostics.Tracing;
-using Hotline.Application.CallCenter;
-using Hotline.CallCenter.Configs;
-using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Cache;
-using XF.Domain.Constants;
 using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
-using Hotline.Repository.SqlSugar.CallCenter;
 
 namespace Hotline.Api.Controllers;
 
@@ -75,6 +67,7 @@ namespace Hotline.Api.Controllers;
 /// </summary>
 public class OrderController : BaseController
 {
+    #region 注入
     private readonly IOrderDomainService _orderDomainService;
     private readonly IOrderRepository _orderRepository;
     private readonly IWorkflowApplication _workflowApplication;
@@ -113,10 +106,7 @@ public class OrderController : BaseController
     private readonly IRepository<OrderFinality> _orderFinalityRepository;
     private readonly IRepository<OrderSendBack> _orderSendBackRepository;
     private readonly IRepository<OrderSpecial> _orderSpecialRepository;
-
     private readonly IRepository<WorkflowTrace> _workflowTraceRepository;
-
-    //private readonly IRepository<TrCallRecord> _trCallRecordRepository;
     private readonly IOrderApplication _orderApplication;
     private readonly IEnterpriseService _enterpriseService;
     private readonly IPushDomainService _pushDomainService;
@@ -134,6 +124,8 @@ public class OrderController : BaseController
     private readonly ICallApplication _callApplication;
     private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
     private readonly IOrderSendBackAuditApplication _orderSendBackAuditApplication;
+    private readonly IRepository<ContingencyManagementOrders> _contingencyManagementOrdersRepository;
+    private readonly IRepository<ContingencyManagementHotspot> _contingencyManagementHotspotRepository;
 
     public OrderController(
         IOrderDomainService orderDomainService,
@@ -175,7 +167,6 @@ public class OrderController : BaseController
         IRepository<OrderSendBack> orderSendBackRepository,
         IRepository<OrderSpecial> orderSpecialRepository,
         IRepository<WorkflowTrace> workflowTraceRepository,
-        //IRepository<TrCallRecord> trCallRecordRepository,
         IOrderApplication orderApplication,
         IEnterpriseService enterpriseService,
         IPushDomainService pushDomainService,
@@ -192,7 +183,9 @@ public class OrderController : BaseController
         ICallApplication callApplication,
         IOptionsSnapshot<CallCenterConfiguration> callcenterOptions,
         IRepository<OrderModifyingRecords> orderModifyingRecordsRepository,
-        IOrderSendBackAuditApplication orderSendBackAuditApplication
+        IOrderSendBackAuditApplication orderSendBackAuditApplication,
+        IRepository<ContingencyManagementOrders> contingencyManagementOrdersRepository,
+        IRepository<ContingencyManagementHotspot> contingencyManagementHotspotRepository
         )
     {
         _orderDomainService = orderDomainService;
@@ -234,7 +227,6 @@ public class OrderController : BaseController
         _orderSendBackRepository = orderSendBackRepository;
         _orderSpecialRepository = orderSpecialRepository;
         _workflowTraceRepository = workflowTraceRepository;
-        //_trCallRecordRepository = trCallRecordRepository;
         _logger = logger;
         _orderApplication = orderApplication;
         _enterpriseService = enterpriseService;
@@ -252,8 +244,10 @@ public class OrderController : BaseController
         _callApplication = callApplication;
         _callcenterOptions = callcenterOptions;
         _orderSendBackAuditApplication = orderSendBackAuditApplication;
-
+        _contingencyManagementOrdersRepository = contingencyManagementOrdersRepository;
+        _contingencyManagementHotspotRepository = contingencyManagementHotspotRepository;
     }
+    #endregion 
 
     #region 工单发布
 
@@ -327,6 +321,47 @@ public class OrderController : BaseController
                     publishPublishOrder.Order = _mapper.Map<OrderDto>(order);
                     await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderPublishOrder, publishPublishOrder);
 
+                    try
+                    {
+                        //应急管理局业务处理
+                        //是否是指定热点
+                        if (await _contingencyManagementHotspotRepository.AnyAsync(p => p.Id == order.HotspotId, HttpContext.RequestAborted))
+                        {
+                            var orderData = await _contingencyManagementOrdersRepository.GetAsync(p => p.Id == order.Id, HttpContext.RequestAborted);
+                            //不存在新增
+                            if (orderData == null)
+                            {
+                                orderData = new ContingencyManagementOrders();
+                                orderData = _mapper.Map<ContingencyManagementOrders>(order);
+                                orderData.Id = order.Id;
+                                orderData.ArrangementOpinion = order.ActualOpinion;
+                                orderData.ArrangeTitle = order.Title;
+                                orderData.ArrangeContent = order.Content;
+                                orderData.PushState = "0";
+                                await _contingencyManagementOrdersRepository.AddAsync(orderData, HttpContext.RequestAborted);
+                            }
+                            else
+                            {
+                                //存在修改
+                                _mapper.Map(order, orderData);
+                                orderData.ArrangementOpinion = order.ActualOpinion;
+                                orderData.ArrangeTitle = order.Title;
+                                orderData.ArrangeContent = order.Content;
+                                orderData.PushState = "0";
+                                await _contingencyManagementOrdersRepository.UpdateAsync(orderData, HttpContext.RequestAborted);
+                            }
+                            //推送消息
+                            var pushaData = _mapper.Map<ContingencyManagementOrdersDto>(orderData);
+                            pushaData.Id = orderData.Id;
+                            //推送消息
+                            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderContingencyManagement,
+                             pushaData, Hotline.Share.Mq.EventNames.HotlineOrderContingencyManagementState);
+                        }
+                    }
+                    catch (Exception)
+                    {
+                    }
+
                     var orderVisit = new OrderVisit();
                     orderVisit.No = order.No;
                     orderVisit.OrderId = order.Id;
@@ -461,6 +496,48 @@ public class OrderController : BaseController
         }
         await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderPublishOrder, publishPublishOrder);
 
+        try
+        {
+            //应急管理局业务处理
+            //是否是指定热点
+            if (await _contingencyManagementHotspotRepository.AnyAsync(p => p.Id == order.HotspotId, HttpContext.RequestAborted))
+            {
+                var orderData = await _contingencyManagementOrdersRepository.GetAsync(p => p.Id == order.Id, HttpContext.RequestAborted);
+                //不存在新增
+                if (orderData == null)
+                {
+                    orderData = new ContingencyManagementOrders();
+                    orderData = _mapper.Map<ContingencyManagementOrders>(order);
+                    orderData.Id = order.Id;
+                    orderData.ArrangementOpinion = dto.ArrangeOpinion;
+                    orderData.ArrangeTitle = dto.ArrangeTitle;
+                    orderData.ArrangeContent = dto.ArrangeContent;
+                    orderData.PushState = "0";
+                    await _contingencyManagementOrdersRepository.AddAsync(orderData, HttpContext.RequestAborted);
+                }
+                else
+                {
+                    //存在修改
+                    _mapper.Map(order, orderData);
+                    orderData.ArrangementOpinion = dto.ArrangeOpinion;
+                    orderData.ArrangeTitle = dto.ArrangeTitle;
+                    orderData.ArrangeContent = dto.ArrangeContent;
+                    orderData.PushState = "0";
+                    await _contingencyManagementOrdersRepository.UpdateAsync(orderData, HttpContext.RequestAborted);
+                }
+                var pushaData = _mapper.Map<ContingencyManagementOrdersDto>(orderData);
+                pushaData.Id = order.Id;
+                pushaData.CreationTime = order.CreationTime;
+                //推送消息
+                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderContingencyManagement,
+                 pushaData, Hotline.Share.Mq.EventNames.HotlineOrderContingencyManagementState, HttpContext.RequestAborted);
+
+            }
+        }
+        catch (Exception)
+        {
+        }
+
         var orderVisit = new OrderVisit();
         orderVisit.No = order.No;
         orderVisit.OrderId = order.Id;
@@ -770,6 +847,7 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.EmployeeName), d => !string.IsNullOrEmpty(d.EmployeeId) && d.Employee.Name == dto.EmployeeName)
             .WhereIF(dto.IsProvince != null && dto.IsProvince == true, d => d.Order.IsProvince == true)
             .WhereIF(dto.IsProvince != null && dto.IsProvince == false, d => d.Order.IsProvince == false)
+            .WhereIF(dto.IsEffectiveAiVisit != null, d => d.IsEffectiveAiVisit == dto.IsEffectiveAiVisit)
             .OrderByDescending(x => x.PublishTime)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
@@ -822,6 +900,7 @@ public class OrderController : BaseController
         var recordingFileUrl = "";
         var recordingBaseAddress = "";
         var recordingAbsolutePath = "";
+        var aiVisitVoiceBaseUrl = "";
         if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
         {
             var callRecord = await _callApplication.GetTianrunCallAsync(orderVisit.CallId, HttpContext.RequestAborted);
@@ -842,6 +921,8 @@ public class OrderController : BaseController
                 recordingAbsolutePath = call.AudioFile;
             }
         }
+        //获取系统配置智能回访语音URL头
+        aiVisitVoiceBaseUrl = _systemSettingCacheManager.GetSetting(SettingConstants.AiVisitVoiceBaseUrl)?.SettingValue[0];
 
         return new
         {
@@ -856,6 +937,7 @@ public class OrderController : BaseController
             RecordingFileUrl = recordingFileUrl,
             RecordingBaseAddress = recordingBaseAddress,
             RecordingAbsolutePath = recordingAbsolutePath,
+            AiVisitVoiceBaseUrl = aiVisitVoiceBaseUrl,
         };
     }
 
@@ -1020,9 +1102,9 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
             .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title))
             .WhereIF(!string.IsNullOrEmpty(dto.VisitUserName), x => x.Employee.Name.Contains(dto.VisitUserName))
-            .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.Order.AcceptTypeCode)) //受理类型
-            .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.Order.HotspotId)) //热点类型
-            .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Order.ActualHandleOrgCode)) //接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.Order.AcceptTypeCode == dto.AcceptType)//受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.Order.HotspotSpliceName != null && d.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.Order.CurrentHandleOrgId == dto.OrgId)//接办部门
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo),
                 d => d.Order.AcceptorName.Contains(dto.NameOrNo!) || d.Order.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
@@ -1492,8 +1574,8 @@ public class OrderController : BaseController
         if (dto.Data.Files.Any())
             delay.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, delay.Id, "", HttpContext.RequestAborted);
         else
-	        delay.FileJson = new List<Share.Dtos.File.FileJson>();
-		await _orderDelayRepository.UpdateAsync(delay, HttpContext.RequestAborted);
+            delay.FileJson = new List<Share.Dtos.File.FileJson>();
+        await _orderDelayRepository.UpdateAsync(delay, HttpContext.RequestAborted);
         try
         {
             dto.NextWorkflow.WorkflowId = delay.WorkflowId;
@@ -1709,41 +1791,44 @@ public class OrderController : BaseController
             .Includes(x => x.OrderVisit)
             .Includes(x => x.OrderVisit, y => y.Order)
             .Includes(x => x.OrderVisit, y => y.Employee)
-            .LeftJoin<OrderScreen>((x, s) => x.Id == s.VisitDetailId && s.IsDeleted == false)
-            //&& s.Status < EScreenStatus.End
-            .Where((x, s) => s.Id == null)
-            .WhereIF(dto.IsHomePage.HasValue && dto.IsHomePage == true,
-                x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart)
+            //.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)
+            .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!))
-            .WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order!.Title!.Contains(dto.Title!))
-            .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.OrderVisit.Order!.SourceChannelCode! == dto.SourceChannel!)
+            .WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.OrderVisit.Order!.AcceptTypeCode! == dto.AcceptType!)
-            .WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType)
+            .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), x => x.OrderVisit.Order!.Hotspot.HotSpotFullName!.StartsWith(dto.HotspotSpliceName!))
+            .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.OrderVisit.Order!.SourceChannelCode! == dto.SourceChannel!)
             .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.OrderVisit.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!))
             .WhereIF(!string.IsNullOrEmpty(dto.CurrentHandleOrgName), x => x.OrderVisit.Order!.CurrentHandleOrgName!.Contains(dto.CurrentHandleOrgName!))
-            .WhereIF(dto.ActualHandleTime.HasValue && dto.EndActualHandleTime.HasValue,
-                x => x.OrderVisit.Order!.ActualHandleTime >= dto.ActualHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndActualHandleTime)
-            .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue,
-                x => x.OrderVisit.Order!.FiledTime == dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime)
+            .WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitOrgName!.Contains(dto.VisitOrgName!))
             .WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue,
-                x => x.OrderVisit.Order!.CreationTime == dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime)
+                x => x.OrderVisit.Order!.CreationTime >= dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.CurrentHandleTime.HasValue && dto.EndCurrentHandleTime.HasValue,
+                x => x.OrderVisit.Order!.CurrentHandleTime >= dto.CurrentHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndCurrentHandleTime)
+            .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue,
+                x => x.OrderVisit.Order!.FiledTime >= dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime)
             .WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue,
-                x => x.OrderVisit.VisitTime == dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime)
-            .WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitOrgName!.Contains(dto.VisitOrgName!))
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults),
-                x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude),
-                x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude))
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason),
-                x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
-            .Where((x, s) => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle);
+                x => x.OrderVisit.VisitTime >= dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime)
+            .WhereIF(dto.IsHomePage.HasValue && dto.IsHomePage == true,
+                x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart)
+            //.WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType)
+            //.WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults),
+            //    x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
+            //.WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude),
+            //    x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude))
+            //.WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason),
+            //    x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
+            .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle);
         if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
         {
             query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-                    (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
+                    x => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
                               x.OrderVisit.Order.No.Contains(dto.Keyword!))
-                .Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode == _sessionContext.OrgId && (
+                .Where(x => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode == _sessionContext.OrgId && (
                     SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
                     SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" ||
                     SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
@@ -1753,9 +1838,9 @@ public class OrderController : BaseController
         else
         {
             query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-                    (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
+                    x => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
                               x.OrderVisit.Order.No.Contains(dto.Keyword!))
-                .Where((x, s) => x.VisitTarget == EVisitTarget.Org && (
+                .Where(x => x.VisitTarget == EVisitTarget.Org && (
                     SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
                     SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" ||
                     SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
@@ -1764,7 +1849,15 @@ public class OrderController : BaseController
         }
 
         var (total, items) = await query
-            .OrderByDescending((x, s) => x.CreationTime)
+            .OrderByIF(dto is { SortRule: 0, SortField: "order.startTime" }, x => x.OrderVisit.Order.StartTime, OrderByType.Asc)
+            .OrderByIF(dto is { SortRule: 1, SortField: "order.startTime" }, x => x.OrderVisit.Order.StartTime, OrderByType.Desc)
+            .OrderByIF(dto is { SortRule: 0, SortField: "order.actualHandleTime" }, x => x.OrderVisit.Order.ActualHandleTime, OrderByType.Asc)
+            .OrderByIF(dto is { SortRule: 1, SortField: "order.actualHandleTime" }, x => x.OrderVisit.Order.ActualHandleTime, OrderByType.Desc)
+            .OrderByIF(dto is { SortRule: 0, SortField: "order.filedTime" }, x => x.OrderVisit.Order.FiledTime, OrderByType.Asc)
+            .OrderByIF(dto is { SortRule: 1, SortField: "order.filedTime" }, x => x.OrderVisit.Order.FiledTime, OrderByType.Desc)
+            .OrderByIF(dto is { SortRule: 0, SortField: "orderVisit.visitTime" }, x => x.OrderVisit.VisitTime, OrderByType.Asc)
+            .OrderByIF(dto is { SortRule: 1, SortField: "orderVisit.visitTime" }, x => x.OrderVisit.VisitTime, OrderByType.Desc)
+            .OrderByIF(dto.SortRule is null, x => x.CreationTime, OrderByType.Desc)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
     }
@@ -1786,26 +1879,49 @@ public class OrderController : BaseController
             .Includes(d => d.VisitDetail)
             .Includes(d => d.Visit, v => v.Order)
             .Includes(d => d.Workflow)
+            .Includes(d => d.ScreenDetails.Where(sd => sd.AuditUserId == _sessionContext.UserId).OrderByDescending(sd => sd.AuditTime).Take(1).ToList())
             .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Visit.Order.Title.Contains(dto.Title!))
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.Visit.Order.No.Contains(dto.No!));
-        if (dto.Status is EScreenStatus.Apply)
+        if (dto.TabStatus is EScreenStatus.Apply)
         {
-            query.Where(d => (d.Status == EScreenStatus.Apply || d.Status == EScreenStatus.Approval));
+            query.Where(d => (d.Status == EScreenStatus.Apply || d.Status == EScreenStatus.Approval || (d.Status == EScreenStatus.SendBack || d.SendBackApply == false)));
         }
 
-        if (dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle)
+        if (dto.TabStatus.HasValue && dto.Status == EScreenStatus.MyHandle)
         {
             query.Where(d => (d.Status != EScreenStatus.Apply));
         }
 
         var (total, items) = await query
-            //.WhereIF(dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle,
-            //    x => x.Status != EScreenStatus.Apply && x.CreatorId == _sessionContext.UserId)
+            .WhereIF(dto.DataScope is 1, x => x.CreatorId == _sessionContext.RequiredUserId)
+            .WhereIF(dto.Status.HasValue, x => x.Status == dto.Status)
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.Order!.AcceptTypeCode! == dto.AcceptType!)
+            .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), x => x.Order!.Hotspot.HotSpotFullName!.StartsWith(dto.HotspotSpliceName!))
+            .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.Order!.SourceChannelCode! == dto.SourceChannel!)
+            .WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitDetail.VisitOrgName!.Contains(dto.VisitOrgName!))
+            .WhereIF(!string.IsNullOrEmpty(dto.CreatorOrgName), d => d.CreatorOrgName == dto.CreatorOrgName)
+            .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), d => d.CreatorName == dto.CreatorName)
+            .WhereIF(dto.IsProvince.HasValue, x => x.Order!.IsProvince == dto.IsProvince)
+            .WhereIF(dto.IsSendBackApplyNum is true, x => x.SendBackApplyNum > 0)
+            .WhereIF(dto.IsSendBackApplyNum is false, x => x.SendBackApplyNum == 0)
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
             .WhereIF(!string.IsNullOrEmpty(dto.OrderId), d => d.OrderId == dto.OrderId)
-            .WhereIF(!string.IsNullOrEmpty(dto.CreatorOrgName), d => d.CreatorOrgName == dto.CreatorOrgName)
-            .OrderByDescending(d => d.CreationTime)
+            //甄别列表
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!))
+            .WhereIF(!string.IsNullOrEmpty(dto.CurrentHandleOrgName), x => x.Order!.CurrentHandleOrgName!.Contains(dto.CurrentHandleOrgName!))
+            .WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue,
+                x => x.Order!.CreationTime >= dto.CreationTime && x.Order!.CreationTime <= dto.EndCreationTime)
+            .WhereIF(dto.CurrentHandleTime.HasValue && dto.EndCurrentHandleTime.HasValue,
+                x => x.Order!.CurrentHandleTime >= dto.CurrentHandleTime && x.Order!.ActualHandleTime <= dto.EndCurrentHandleTime)
+            .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue,
+                x => x.Order!.FiledTime >= dto.FiledTime && x.Order!.FiledTime <= dto.EndFiledTime)
+            .WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue,
+                x => x.Visit.VisitTime >= dto.VisitTime && x.Visit.VisitTime <= dto.EndVisitTime)
+            .WhereIF(!string.IsNullOrEmpty(dto.Contact), x => x.Order!.Contact! == dto.Contact!)
+            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), x => x.Order!.FromPhone! == dto.FromPhone!)
+            .OrderByIF(dto is { SortRule: 0, SortField: "creationTime" }, x => x.CreationTime, OrderByType.Asc)
+            .OrderByIF(dto is { SortRule: 1, SortField: "creationTime" } || dto.SortRule is null, x => x.CreationTime, OrderByType.Desc)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         return new PagedDto<OrderScreenListDto>(total, _mapper.Map<IReadOnlyList<OrderScreenListDto>>(items));
     }
@@ -1854,8 +1970,8 @@ public class OrderController : BaseController
         if (dto.Data.Files.Any())
             model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted);
         else
-	        model.FileJson = new List<Share.Dtos.File.FileJson>();
-		await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted);
+            model.FileJson = new List<Share.Dtos.File.FileJson>();
+        await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted);
 
         var workflowId = string.Empty;
         try
@@ -1896,8 +2012,10 @@ public class OrderController : BaseController
         if (dto.Data.Files.Any())
             screen.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, screen.Id, "", HttpContext.RequestAborted);
         else
-	        screen.FileJson = new List<Share.Dtos.File.FileJson>();
-		await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
+            screen.FileJson = new List<Share.Dtos.File.FileJson>();
+
+        screen.SendBackApplyNum++;
+        await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
         try
         {
             dto.NextWorkflow.WorkflowId = screen.WorkflowId;
@@ -1918,19 +2036,14 @@ public class OrderController : BaseController
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
             cancellationToken: HttpContext.RequestAborted);
-        if (workflow.Steps.Count > 2)
-        {
-            await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
-        }
-        else
-        {
-            TerminateDto terDto = new TerminateDto
-            {
-                WorkflowId = dto.WorkflowId,
-                Opinion = "退回申请人"
-            };
-            await _workflowDomainService.TerminateAsync(terDto, HttpContext.RequestAborted);
-        }
+        var screen = await _orderScreenRepository.Queryable().Where(x => x.WorkflowId == dto.WorkflowId).FirstAsync();
+        if (screen == null)
+            throw UserFriendlyException.SameMessage("甄别信息错误!");
+        screen.SendBackApply = workflow.Steps.Count <= 2;
+        await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+        screen.Status = EScreenStatus.SendBack;
+        screen.SendBackNum++;
+        await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
     }
     /// <summary>
     /// 查询工单甄别流程开启参数
@@ -2418,8 +2531,8 @@ public class OrderController : BaseController
         if (dto.Files.Any())
             urge.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, urge.Id, "", HttpContext.RequestAborted);
         else
-	        urge.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
-		await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted);
+            urge.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
+        await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted);
     }
 
     /// <summary>
@@ -2759,8 +2872,8 @@ public class OrderController : BaseController
         dto.RepeatableEventDetails = repeatables;
         if (!string.IsNullOrEmpty(dto.WorkflowId))
         {
-            var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, withTraces:true,
-				cancellationToken: HttpContext.RequestAborted);
+            var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, withTraces: true,
+                cancellationToken: HttpContext.RequestAborted);
             var centerOpinion = workflow.Steps.Where(x => x.HandlerOrgId == OrgSeedData.CenterId && x.StepType != EStepType.End).MaxBy(d => d.CreationTime)?.Opinion ?? string.Empty;
             dto.CenterOpinion = centerOpinion;
             List<OrderRemarksDto> remarks = workflow.Steps.Where(x => !string.IsNullOrEmpty(x.Remark)).Select(x => new OrderRemarksDto { Remark = x.Remark, RemarkTime = x.CreationTime, RemarkUser = x.CreatorName }).ToList();
@@ -2768,10 +2881,15 @@ public class OrderController : BaseController
             if (order.Status == EOrderStatus.SendBack || order.Status == EOrderStatus.SendBackAudit || order.Status == EOrderStatus.BackToUnAccept)
             {
                 var backTrace = workflow.Traces.Where(x => x.Status == EWorkflowStepStatus.Handled).OrderByDescending(x => x.CreationTime).First();
-                dto.SendBackOpinion = string.IsNullOrEmpty(backTrace.Opinion) ? string.Empty : backTrace.Opinion.Replace("流程归档","");
-				//var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == dto.Id).OrderByDescending(x => x.CreationTime).FirstAsync();
-				//dto.SendBackOpinion = sendBack is { Id: not null } && !string.IsNullOrEmpty(sendBack.Content) ? sendBack.Content : string.Empty;
-			}
+                dto.SendBackOpinion = string.IsNullOrEmpty(backTrace.Opinion) ? string.Empty : backTrace.Opinion.Replace("流程归档", "");
+                //var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == dto.Id).OrderByDescending(x => x.CreationTime).FirstAsync();
+                //dto.SendBackOpinion = sendBack is { Id: not null } && !string.IsNullOrEmpty(sendBack.Content) ? sendBack.Content : string.Empty;
+            }
+        }
+        //工单是否在退回审批中
+        if (await _orderSendBackAuditRepository.AnyAsync(x => x.OrderId == order.Id && x.State == ESendBackAuditState.Apply, HttpContext.RequestAborted))
+        {
+            dto.IsReturnUnderApproval = true;
         }
 
         return dto;
@@ -2981,8 +3099,8 @@ public class OrderController : BaseController
         if (dto.Files.Any())
             order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", HttpContext.RequestAborted);
         else
-	        order.FileJson = new List<Share.Dtos.File.FileJson>();
-		await _orderRepository.UpdateNav(order).Include(d => d.OrderExtension).ExecuteCommandAsync();
+            order.FileJson = new List<Share.Dtos.File.FileJson>();
+        await _orderRepository.UpdateNav(order).Include(d => d.OrderExtension).ExecuteCommandAsync();
         //敏感分词
         await _orderApplication.OrderSensitiveParticiple(dto.Content, order.Id, HttpContext.RequestAborted);
         // 副本工单
@@ -3002,6 +3120,8 @@ public class OrderController : BaseController
     [HttpPost("startflow")]
     public async Task StartFlow([FromBody] OrderStartFlowDto dto)
     {
+        var order = await _orderDomainService.GetOrderAsync(dto.Data, cancellationToken: HttpContext.RequestAborted);
+
         ExpiredTimeWithConfig expiredTimeConfig;
         if (dto.Workflow.NextHandlers.Any(d => d.Key == "001171" || d.Key == "001178"))
         {
@@ -3031,21 +3151,10 @@ public class OrderController : BaseController
         else
         {
             //期满时间
-            expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, dto.Data.AcceptTypeCode);
+            expiredTimeConfig = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToOrg, order.AcceptTypeCode);
         }
 
-        _mapper.Map(expiredTimeConfig, dto.Data);
-
-        var id = dto.Data.Id;
-        var isAdd = string.IsNullOrEmpty(dto.Data.Id);
-        if (isAdd)
-        {
-            id = await Add(dto.Data);
-        }
-        else
-        {
-            await Update(dto.Data);
-        }
+        _mapper.Map(expiredTimeConfig, order);
 
         try
         {
@@ -3059,34 +3168,32 @@ public class OrderController : BaseController
 
             var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
             startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle;
-            startDto.Title = dto.Data.Title;
-            await _workflowApplication.StartWorkflowAsync(startDto, _sessionContext, id, dto.Data.ExpiredTime, HttpContext.RequestAborted);
+            startDto.Title = order.Title;
+            await _workflowApplication.StartWorkflowAsync(startDto, _sessionContext, order.Id, order.ExpiredTime, HttpContext.RequestAborted);
         }
         catch (Exception e)
         {
             _logger.LogError($"工单开启流程失败!, {e.Message}, {e.StackTrace}");
-            if (isAdd)
-                await Remove(id);
             throw new UserFriendlyException($"工单开启流程失败!, {e.Message}, {e.StackTrace}", "工单开启流程失败");
         }
 
-        //是否市州互转
-        if (dto.Data.Transpond.HasValue && dto.Data.Transpond.Value)
-        {
-            var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
-            var orderDto = _mapper.Map<OrderDto>(order);
-            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderTranspondCity, orderDto);
-            //保存本地数据
-            TranspondCityRawData cityRawData = new TranspondCityRawData
-            {
-                OrderCode = order.No,
-                TransferOutTime = DateTime.Now,
-                CityName = order.TranspondCityName,
-                Direction = ETranspondDirection.Out
-            };
-
-            await _transpondCityRawDataRepository.AddAsync(cityRawData, HttpContext.RequestAborted);
-        }
+        ////是否市州互转
+        //if (dto.Data.Transpond.HasValue && dto.Data.Transpond.Value)
+        //{
+        //    var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
+        //    var orderDto = _mapper.Map<OrderDto>(order);
+        //    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderTranspondCity, orderDto);
+        //    //保存本地数据
+        //    TranspondCityRawData cityRawData = new TranspondCityRawData
+        //    {
+        //        OrderCode = order.No,
+        //        TransferOutTime = DateTime.Now,
+        //        CityName = order.TranspondCityName,
+        //        Direction = ETranspondDirection.Out
+        //    };
+
+        //    await _transpondCityRawDataRepository.AddAsync(cityRawData, HttpContext.RequestAborted);
+        //}
     }
 
     /// <summary>
@@ -3140,6 +3247,8 @@ public class OrderController : BaseController
                 expiredTimeConfig.NearlyExpiredTime, expiredTimeConfig.NearlyExpiredTimeOne, dto.Opinion,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
                 canUpdateOrderSender);
+            //TODO 发送短信超期和即将超期
+
         }
         else if (dto.FlowDirection is EFlowDirection.CenterToOrg)
         {
@@ -3151,6 +3260,8 @@ public class OrderController : BaseController
                 expiredTimeConfig.NearlyExpiredTime, expiredTimeConfig.NearlyExpiredTimeOne, dto.Opinion,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
                 canUpdateOrderSender);
+            //TODO 发送短信超期和即将超期
+
             //写入质检
             await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, HttpContext.RequestAborted);
         }
@@ -3296,27 +3407,40 @@ public class OrderController : BaseController
         //是否行政执法类工单
         var IsOpenJudicialManagement = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.IsOpenJudicialManagement).SettingValue[0]);
         //重点关注事件
-        List<Kv> FocusOnEvents = new()
+        var FocusOnEvents = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.FocusOnEvent).ToList();
+        if (!IsOpenJudicialManagement)
         {
-            new Kv { Key = "0", Value = "紧急工单" },
-            new Kv { Key = "1", Value = "形式主义工单" },
-            new Kv { Key = "3", Value = "敏感类工单" }
-        };
-        if (IsOpenJudicialManagement)
-            FocusOnEvents.Add(new Kv { Key = "2", Value = "行政执法类工单" });
+            var xingzhengzhifa = FocusOnEvents.FirstOrDefault(d => d.DicDataValue == "2");
+            if (xingzhengzhifa is not null)
+                FocusOnEvents.Remove(xingzhengzhifa);
+        }
+
+        //List<Kv> FocusOnEvents = new()
+        //{
+        //    new Kv { Key = "0", Value = "紧急工单" },
+        //    new Kv { Key = "1", Value = "形式主义工单" },
+        //    new Kv { Key = "3", Value = "敏感类工单" }
+        //};
+        //if (IsOpenJudicialManagement)
+        //    FocusOnEvents.Add(new Kv { Key = "2", Value = "行政执法类工单" });
+
+        ////todo 宜宾add 1,3
+        ////todo 自贡add 4
+        //FocusOnEvents.Add(new Kv { Key = "4", Value = "24小时办结" });
 
         var rsp = new
         {
             TranspondCity = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.TranspondCity),
             ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
             AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
-            EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
+            //EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
             PushTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType),
             GenderOptions = EnumExts.GetDescriptions<EGender>(),
             IdentityTypeOptions = EnumExts.GetDescriptions<EIdentityType>(),
             LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType),
             AgeRangeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AgeRange),
             OrderTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderType),
+            OrderTags = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderTag),
             FocusOnEvents
         };
         return rsp;
@@ -3404,6 +3528,7 @@ public class OrderController : BaseController
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword))
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
             .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true,
@@ -3516,6 +3641,7 @@ public class OrderController : BaseController
             .WhereIF(dto.IsHandled.HasValue, d => handleStatuses.Contains(d.Status))
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!))
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
             .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true,
@@ -3755,23 +3881,23 @@ public class OrderController : BaseController
             .Includes(d => d.Workflow)
             .FirstAsync(d => d.Id == workflow.ExternalId);
         var (currentStep, prevStep, isOrgToCenter, isSecondToFirstOrgLevel) = await _workflowApplication.GetPreviousInformationAsync(
-	        dto.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles, HttpContext.RequestAborted);
-		var audit = new OrderSendBackAudit
-        {
-	        OrderId = workflow.ExternalId,
-	        State = ESendBackAuditState.Apply,
-	        Content = dto.Opinion,
-	        SendBackData = dto,
-	        ApplyOrgId = currentStep.AcceptorOrgId,
-	        ApplyOrgName = currentStep!.AcceptorOrgName,
-	        SendBackOrgId = prevStep.HandlerOrgId, //prevStep.AcceptorOrgId,
-	        SendBackOrgName = prevStep.HandlerOrgName, //prevStep!.AcceptorOrgName,
-	        WorkflowOrgId = _sessionContext.RequiredOrgId,
-	        WorkflowUserId = _sessionContext.RequiredUserId,
-	        WorkflowRoleIds = _sessionContext.Roles.ToList(),
-	        TraceId = currentStep.Id
+            dto.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles, HttpContext.RequestAborted);
+        var audit = new OrderSendBackAudit
+        {
+            OrderId = workflow.ExternalId,
+            State = ESendBackAuditState.Apply,
+            Content = dto.Opinion,
+            SendBackData = dto,
+            ApplyOrgId = currentStep.AcceptorOrgId,
+            ApplyOrgName = currentStep!.AcceptorOrgName,
+            SendBackOrgId = prevStep.HandlerOrgId, //prevStep.AcceptorOrgId,
+            SendBackOrgName = prevStep.HandlerOrgName, //prevStep!.AcceptorOrgName,
+            WorkflowOrgId = _sessionContext.RequiredOrgId,
+            WorkflowUserId = _sessionContext.RequiredUserId,
+            WorkflowRoleIds = _sessionContext.Roles.ToList(),
+            TraceId = currentStep.Id
         };
-		if (oneSendBack || twoSendBack)
+        if (oneSendBack || twoSendBack)
         {
             var sendBack = await _orderSendBackAuditRepository.Queryable()
                 .Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync();
@@ -3784,16 +3910,16 @@ public class OrderController : BaseController
             if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!");
             if ((oneSendBack && isOrgToCenter) || (twoSendBack && isSecondToFirstOrgLevel))
             {
-               
+
                 await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { Status = EOrderStatus.SendBackAudit })
                     .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
             }
             else
             {
                 audit.State = ESendBackAuditState.End;
-                audit.AuditUser ="默认通过";
+                audit.AuditUser = "默认通过";
                 audit.AuditTime = DateTime.Now;
-				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;
@@ -3804,10 +3930,10 @@ public class OrderController : BaseController
         }
         else
         {
-	        audit.State = ESendBackAuditState.End;
-	        audit.AuditUser = "默认通过";
-	        audit.AuditTime = DateTime.Now;
-			var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+            audit.State = ESendBackAuditState.End;
+            audit.AuditUser = "默认通过";
+            audit.AuditTime = DateTime.Now;
+            var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
             var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter
                 ? EProcessType.Zhiban
                 : EProcessType.Jiaoban;
@@ -3815,8 +3941,8 @@ public class OrderController : BaseController
                 .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
             //发送短信TODO
         }
-		await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
-	}
+        await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
+    }
 
     /// <summary>
     /// 工单业务退回审批
@@ -3859,7 +3985,7 @@ public class OrderController : BaseController
             //发送短信TODO
         }
         await _orderSendBackAuditRepository.UpdateAsync(sendBack, HttpContext.RequestAborted);
-	}
+    }
 
     /// <summary>
     /// 工单业务批量退回审批
@@ -4248,7 +4374,7 @@ public class OrderController : BaseController
                 cancellationToken: HttpContext.RequestAborted);
             //}
             await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, order.Status >= EOrderStatus.Filed, HttpContext.RequestAborted);
-           
+
 
             if (order != null && ("001171".Equals(model.OrgId) ||
                                   "001178".Equals(model.OrgId) ||
@@ -4388,7 +4514,7 @@ public class OrderController : BaseController
 
             var reTransactNum = order.ReTransactNum.HasValue ? order.ReTransactNum.Value + 1 : 1;
             var Status = model.StepType == EStepType.Start ? EOrderStatus.BackToUnAccept : EOrderStatus.SendBack;
-			await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType, ReTransactNum = reTransactNum, Status = Status }).Where(o => o.Id == order.Id)
+            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType, ReTransactNum = reTransactNum, Status = Status }).Where(o => o.Id == order.Id)
                 .ExecuteCommandAsync(HttpContext.RequestAborted);
 
             //var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId && x.VisitState != EVisitState.None);
@@ -4421,8 +4547,8 @@ public class OrderController : BaseController
         if (dto.Files.Any())
             special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted);
         else
-	        special.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
-		await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted);
+            special.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
+        await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted);
         var order = await _orderRepository.GetAsync(x => x.Id == special.OrderId);
         if (special.State == 1)
         {
@@ -4525,8 +4651,8 @@ public class OrderController : BaseController
             if (dto.Files.Any())
                 special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted);
             else
-	            special.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
-			await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted);
+                special.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
+            await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted);
             var order = await _orderRepository.GetAsync(x => x.Id == special.OrderId);
             if (special.State == 1)
             {
@@ -4695,11 +4821,12 @@ public class OrderController : BaseController
                 d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
             //.WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!))
             .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(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
             .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!))
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgName), d => d.CurrentHandleOrgName == dto.OrgName)//接办部门
+              //.WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
+              .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo),
                 d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!))
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)

+ 89 - 11
src/Hotline.Api/Controllers/TestController.cs

@@ -18,6 +18,7 @@ using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
+using Hotline.ContingencyManagement;
 using Hotline.FlowEngine;
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Notifications;
@@ -34,6 +35,7 @@ using Hotline.Repository.SqlSugar.CallCenter;
 using Hotline.Repository.SqlSugar.System;
 using Hotline.Repository.SqlSugar.Ts;
 using Hotline.Settings;
+using Hotline.Settings.Hotspots;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.FlowEngine;
@@ -135,6 +137,8 @@ public class TestController : BaseController
     private readonly IRepository<EnforcementOrdersHandler> _enforcementOrdersHandlerRepository;
     private readonly IWorkflowApplication _workflowApplication;
 
+    private readonly IRepository<ContingencyManagementHotspot> _contingencyManagementHotspotRepository;
+    private readonly IRepository<Hotspot> _hotspotRepository;
     //private readonly ITypedCache<List<User>> _cache;
     //private readonly ICacheManager<User> _cache;
 
@@ -184,7 +188,8 @@ public class TestController : BaseController
 IRepository<EnforcementOrders> enforcementOrdersRepository,
 IRepository<JudicialManagementOrders> judicialManagementOrdersRepository,
 IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository,
-        IWorkflowApplication workflowApplication
+IRepository<ContingencyManagementHotspot> contingencyManagementHotspotRepository,
+IRepository<Hotspot> hotspotRepository
         )
     {
         _logger = logger;
@@ -227,9 +232,78 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository,
         _enforcementOrdersRepository = enforcementOrdersRepository;
         _judicialManagementOrdersRepository = judicialManagementOrdersRepository;
         _enforcementOrdersHandlerRepository = enforcementOrdersHandlerRepository;
-        _workflowApplication = workflowApplication;
+        _contingencyManagementHotspotRepository = contingencyManagementHotspotRepository;
+        _hotspotRepository = hotspotRepository;
+    }
+
+
+    /// <summary>
+    /// 推送回访到省上
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("publishVisitToProvince")]
+    [AllowAnonymous]
+    public async Task PublsihVisitToProvince([FromBody]DateTime date)
+    {
+        //查询需要推送的数据
+       var  list = await  _orderRepository.Queryable()
+            .Includes(x=>x.OrderVisits.Where(q=>q.VisitState== EVisitState.Visited).ToList())
+            .Where(x => x.CreationTime.Date == date.Date && x.Status == EOrderStatus.Visited && x.ProcessType == EProcessType.Zhiban && x.CounterSignType == null).ToListAsync();
+
+
+        foreach (var item in list)
+        {
+            var visit = item.OrderVisits.FirstOrDefault();
+            if (visit!=null)
+            {
+                //推省上
+                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
+                new PublishVisitDto()
+                {
+                    Order = _mapper.Map<OrderDto>(item),
+                    No = visit.No,
+                    VisitType = visit.VisitType,
+                    VisitName = visit.CreatorName,
+                    VisitTime = visit.VisitTime,
+                    VisitRemark = "满意",
+                    AreaCode = item.AreaCode!,
+                    SubjectResultSatifyCode = "4",
+                    FirstSatisfactionCode = "4",
+                    ClientGuid = ""
+                }, cancellationToken: HttpContext.RequestAborted);
+            }
+        }
+    }
 
+    [HttpGet("addcontingencymanagementhotspot")]
+    [AllowAnonymous]
+    public async Task AddContingencyManagementHotspot([FromQuery] string? Id,string? ParentId)
+    {
+        if (!string.IsNullOrWhiteSpace(Id))
+        {
+            var data = await _hotspotRepository.GetAsync(Id, HttpContext.RequestAborted);
+            if(data != null)
+            {
+                var newdata = _mapper.Map<ContingencyManagementHotspot>(data);
+                newdata.Id = data.Id;
+                await _contingencyManagementHotspotRepository.AddAsync(newdata, HttpContext.RequestAborted);
+            }
+        }
+        if (!string.IsNullOrEmpty(ParentId))
+        {
+            var data = await _hotspotRepository.Queryable().Where(p=>p.ParentId==ParentId).ToListAsync();
+            if (data != null&&data.Count>0)
+            {
+                foreach (var item in data)
+                {
+                    var newdata = _mapper.Map<ContingencyManagementHotspot>(item);
+                    newdata.Id = item.Id;
+                    await _contingencyManagementHotspotRepository.AddAsync(newdata, HttpContext.RequestAborted);
+                }
+            }
+        }
     }
+
     /// <summary>
     /// 处理司法工单数据
     /// </summary>
@@ -324,29 +398,29 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository,
         {
             foreach (var item in list)
             {
-                var creationTimeHandleDurationWorkday = item.ActualHandleTime.HasValue
-                  ? _timeLimitDomainService.CalcWorkTime(item.CreationTime, item.ActualHandleTime.Value,
+                var creationTimeHandleDurationWorkday = item.FiledTime.HasValue
+                  ? _timeLimitDomainService.CalcWorkTimeEx(item.CreationTime, item.FiledTime.Value,
                   item.ProcessType is EProcessType.Zhiban)
                   : 0;
-                var centerToOrgHandleDurationWorkday = item.ActualHandleTime.HasValue && item.CenterToOrgTime.HasValue
-                    ? _timeLimitDomainService.CalcWorkTime(item.CenterToOrgTime.Value, item.ActualHandleTime.Value,
+                var centerToOrgHandleDurationWorkday = item.FiledTime.HasValue && item.CenterToOrgTime.HasValue
+                    ? _timeLimitDomainService.CalcWorkTimeEx(item.CenterToOrgTime.Value, item.FiledTime.Value,
                     item.ProcessType is EProcessType.Zhiban)
                     : 0;
 
                 item.CreationTimeHandleDurationWorkday = creationTimeHandleDurationWorkday;
                 item.CenterToOrgHandleDurationWorkday = centerToOrgHandleDurationWorkday;
 
-                if (item.ActualHandleTime.HasValue)
+                if (item.FiledTime.HasValue)
                 {
-                    var count = Math.Round((item.ActualHandleTime - item.CreationTime).Value.TotalSeconds);
+                    var count = Math.Round((item.FiledTime - item.CreationTime).Value.TotalSeconds);
                     item.CreationTimeHandleDuration = count <= 0 ? 1 : count;
                 }
                 else
                     item.CreationTimeHandleDuration = 0;
 
-                if (item.ActualHandleTime.HasValue && item.CenterToOrgTime.HasValue)
+                if (item.FiledTime.HasValue && item.CenterToOrgTime.HasValue)
                 {
-                    var count = Math.Round((item.ActualHandleTime - item.CenterToOrgTime).Value.TotalSeconds);
+                    var count = Math.Round((item.FiledTime - item.CenterToOrgTime).Value.TotalSeconds);
                     item.CenterToOrgHandleDuration = count <= 0 ? 1 : count;
                 }
                 else
@@ -515,7 +589,11 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository,
         //var r = _timeLimitDomainService.CalcWorkTimeToDecimal(DateTime.Parse("2024-07-09 14:57:51"), DateTime.Parse("2024-07-10 14:20:42"), false);
         //var endTime = _timeLimitDomainService
         //.CalcEndTime(DateTime.Parse("2024-07-09 14:57:51"), ETimeType.WorkDay, -3, 0, 0);///.EndTime;
-        var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 3, 80, 50);
+        //var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 3, 80, 50);
+        //var t = _timeLimitDomainService.CalcWorkTimeEx(DateTime.Parse("2024-07-22 11:30:00"), DateTime.Parse("2024-07-23 14:00:00"), false);
+        var r = await _aiVisitService.QueryAiVisitTaskEx("MTAwMDAx173ASS0kSUAqK2rl2sFGME", "", HttpContext.RequestAborted);
+
+
         return OpenResponse.Ok(DateTime.Now.ToString("F"));
     }
 

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

@@ -562,10 +562,10 @@ public class WorkflowController : BaseController
             .InnerJoin<Order>((c, w, o) => w.ExternalId == o.Id)
             .WhereIF(!string.IsNullOrEmpty(dto.Title), (c, w, o) => o.Title.Contains(dto.Title))
             .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), (c, w, o) => o.No == dto.OrderNo)
-            .WhereIF(dto.AcceptTypes.Any(), (c, w, o) => dto.AcceptTypes.Contains(o.AcceptTypeCode)) //受理类型
-            .WhereIF(dto.Channels.Any(), (c, w, o) => dto.Channels.Contains(o.SourceChannelCode)) //来源渠道
-            .WhereIF(dto.HotspotIds.Any(), (c, w, o) => dto.HotspotIds.Contains(o.HotspotId)) //热点类型
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgName), (c, w, o) => c.FinisherOrgName.Contains(dto.OrgName)) //接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), (c, w, o) => o.AcceptTypeCode == dto.AcceptType)//受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Channel), (c, w, o) => o.SourceChannelCode == dto.Channel)//受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), (c, w, o) => o.HotspotSpliceName != null && o.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgId), (c, w, o) => c.FinisherOrgId == dto.OrgId) //接办部门
             .WhereIF(dto.CounterSignType != null, (c, w, o) => c.CounterSignType == dto.CounterSignType) //会签类型
         ;
 

+ 1 - 0
src/Hotline.Api/StartupExtensions.cs

@@ -188,6 +188,7 @@ internal static class StartupExtensions
             app.UseSwagger();
             app.UseSwaggerUI(c =>
             {
+                c.DocExpansion(DocExpansion.None);
                 //c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
             });
         }

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

@@ -29,7 +29,7 @@
     }
   },
   "ConnectionStrings": {
-    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
+    "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
     //"Redis": "110.188.24.182:50179",
     //"MongoDB": "mongodb://192.168.100.121:27017",
     //"Wex": "server=222.212.82.225;Port=4509;Database=fs_kft;Uid=root;Pwd=Wex@12345;"
@@ -38,7 +38,7 @@
     "Host": "110.188.24.182",
     "Port": 50179,
     "Password": "fengwo123!$!$",
-    "Database": 3 //release:3, dev:5
+    "Database": 5 //release:3, dev:5
   },
   "Swagger": true,
   "Cors": {

+ 2 - 2
src/Hotline.Application.Contracts/Bi/BiQueryVisitNoSatisfiedDetailDtoValidator.cs → src/Hotline.Application.Contracts/Validators/Bi/BiQueryVisitNoSatisfiedDetailDtoValidator.cs

@@ -1,9 +1,9 @@
 using FluentValidation;
 using Hotline.Share.Requests;
 
-namespace Hotline.Application.Contracts.Bi
+namespace Hotline.Application.Contracts.Validators.Bi
 {
-    public class BiQueryVisitNoSatisfiedDetailDtoValidator: AbstractValidator<BiQueryVisitNoSatisfiedDetailDto>
+    public class BiQueryVisitNoSatisfiedDetailDtoValidator : AbstractValidator<BiQueryVisitNoSatisfiedDetailDto>
     {
         public BiQueryVisitNoSatisfiedDetailDtoValidator()
         {

+ 2 - 2
src/Hotline.Application.Contracts/Bi/QueryOrderDelayDataListRequestValidator.cs → src/Hotline.Application.Contracts/Validators/Bi/QueryOrderDelayDataListRequestValidator.cs

@@ -6,9 +6,9 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
-namespace Hotline.Application.Contracts.Bi
+namespace Hotline.Application.Contracts.Validators.Bi
 {
-    public class QueryOrderDelayDataListRequestValidator: AbstractValidator<QueryOrderDelayDataListRequest>
+    public class QueryOrderDelayDataListRequestValidator : AbstractValidator<QueryOrderDelayDataListRequest>
     {
         public QueryOrderDelayDataListRequestValidator()
         {

+ 2 - 2
src/Hotline.Application.Contracts/Bi/QuerySeatRestRequestValidator.cs → src/Hotline.Application.Contracts/Validators/Bi/QuerySeatRestRequestValidator.cs

@@ -6,9 +6,9 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
-namespace Hotline.Application.Contracts.Bi
+namespace Hotline.Application.Contracts.Validators.Bi
 {
-    public class QuerySeatRestRequestValidator: AbstractValidator<QuerySeatRestRequest>
+    public class QuerySeatRestRequestValidator : AbstractValidator<QuerySeatRestRequest>
     {
         public QuerySeatRestRequestValidator()
         {

+ 2 - 2
src/Hotline.Application.Contracts/Bi/QuerySeatSwitchRequestValidator.cs → src/Hotline.Application.Contracts/Validators/Bi/QuerySeatSwitchRequestValidator.cs

@@ -1,9 +1,9 @@
 using FluentValidation;
 using Hotline.Share.Requests;
 
-namespace Hotline.Application.Contracts.Bi
+namespace Hotline.Application.Contracts.Validators.Bi
 {
-    public class QuerySeatSwitchRequestValidator: AbstractValidator<QuerySeatSwitchRequest>
+    public class QuerySeatSwitchRequestValidator : AbstractValidator<QuerySeatSwitchRequest>
     {
         public QuerySeatSwitchRequestValidator()
         {

+ 2 - 2
src/Hotline.Application.Contracts/Bi/QueryVisitNoSatiisfiedRequestValidator.cs → src/Hotline.Application.Contracts/Validators/Bi/QueryVisitNoSatiisfiedRequestValidator.cs

@@ -1,9 +1,9 @@
 using FluentValidation;
 using Hotline.Share.Requests;
 
-namespace Hotline.Application.Contracts.Bi
+namespace Hotline.Application.Contracts.Validators.Bi
 {
-    public class QueryVisitNoSatiisfiedRequestValidator: AbstractValidator<QueryVisitNoSatiisfiedRequest>
+    public class QueryVisitNoSatiisfiedRequestValidator : AbstractValidator<QueryVisitNoSatiisfiedRequest>
     {
         public QueryVisitNoSatiisfiedRequestValidator()
         {

+ 18 - 0
src/Hotline.Application.Contracts/Validators/Order/OrderStartFlowDtoValidator.cs

@@ -0,0 +1,18 @@
+using FluentValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Hotline.Share.Dtos.Order;
+
+namespace Hotline.Application.Contracts.Validators.Order
+{
+    public class OrderStartFlowDtoValidator : AbstractValidator<OrderStartFlowDto>
+    {
+        public OrderStartFlowDtoValidator()
+        {
+            RuleFor(d => d.Data).NotEmpty();
+        }
+    }
+}

+ 8 - 5
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -58,8 +58,9 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
     private readonly ICallApplication _callApplication;
     private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
     private readonly ISessionContext _sessionContext;
+    private readonly IRepository<OrderScreenDetail> _orderScreenDetailRepository;
 
-    public WorkflowEndHandler(
+	public WorkflowEndHandler(
         IKnowledgeDomainService knowledgeDomainService,
         IOrderDomainService orderDomainService,
         IOrderApplication orderApplication,
@@ -87,7 +88,8 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
         IEnforcementApplication enforcementApplication,
         ICallApplication callApplication,
         IOptionsSnapshot<CallCenterConfiguration> callcenterOptions,
-        ISessionContext sessionContext)
+        ISessionContext sessionContext,
+        IRepository<OrderScreenDetail> orderScreenDetailRepository)
     {
         _knowledgeDomainService = knowledgeDomainService;
         _orderDomainService = orderDomainService;
@@ -116,7 +118,8 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
         _callApplication = callApplication;
         _callcenterOptions = callcenterOptions;
         _sessionContext = sessionContext;
-    }
+        _orderScreenDetailRepository = orderScreenDetailRepository;
+	}
 
     /// <summary>Handles a notification</summary>
     /// <param name="notification">The notification</param>
@@ -168,11 +171,11 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
                 var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
-                    ? _timeLimitDomainService.CalcWorkTime(order.CreationTime, now,
+                    ? _timeLimitDomainService.CalcWorkTimeEx(order.CreationTime, now,
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
                 var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
-                    ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value, now,
+                    ? _timeLimitDomainService.CalcWorkTimeEx(order.CenterToOrgTime.Value, now,
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
 

+ 14 - 4
src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs

@@ -45,8 +45,9 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
     private readonly IRepository<User> _userRepository;
     private readonly IMediator _mediator;
     private readonly IEnforcementApplication _enforcementApplication;
+    private readonly IRepository<OrderScreenDetail> _orderScreenDetailRepository;
 
-    public WorkflowNextHandler(
+	public WorkflowNextHandler(
         IOrderDomainService orderDomainService,
         IKnowledgeDomainService knowledgeDomainService,
         IOrderRepository orderRepository,
@@ -63,7 +64,8 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
         IOrderDelayRepository orderDelayRepository,
         IRepository<User> userRepository,
         IMediator mediator,
-        IEnforcementApplication enforcementApplication)
+        IEnforcementApplication enforcementApplication,
+        IRepository<OrderScreenDetail> orderScreenDetailRepository)
     {
         _orderDomainService = orderDomainService;
         _knowledgeDomainService = knowledgeDomainService;
@@ -82,7 +84,9 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
         _userRepository = userRepository;
         _mediator = mediator;
         _enforcementApplication = enforcementApplication;
-    }
+        _orderScreenDetailRepository = orderScreenDetailRepository;
+
+	}
 
     /// <summary>Handles a notification</summary>
     /// <param name="notification">The notification</param>
@@ -283,7 +287,13 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
             //        }
             //    }
 
-            //    break;
+                OrderScreenDetail detail = new OrderScreenDetail
+                {
+	                ScreenId = screen.Id
+                };
+                detail.Audit(_sessionContext.UserId, _sessionContext.UserName, _sessionContext.OrgId, _sessionContext.OrgName,1);
+                await _orderScreenDetailRepository.AddAsync(detail,cancellationToken);
+                break;
             case WorkflowModuleConsts.OrderDelay:
                 var orderDelay = await _orderDelayRepository.Queryable().Includes(x => x.Order)
                     .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);

+ 19 - 5
src/Hotline.Application/Handlers/FlowEngine/WorkflowPreviousHandler.cs

@@ -15,6 +15,7 @@ using MapsterMapper;
 using MediatR;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
+using XF.Domain.Authentications;
 using XF.Domain.Repository;
 
 namespace Hotline.Application.Handlers.FlowEngine
@@ -32,8 +33,10 @@ namespace Hotline.Application.Handlers.FlowEngine
         private readonly ILogger<WorkflowPreviousHandler> _logger;
         private readonly IRepository<User> _userRepository;
         private readonly IMediator _mediator;
+        private readonly ISessionContext _sessionContext;
+        private readonly IRepository<OrderScreenDetail> _orderScreenDetailRepository;
 
-        public WorkflowPreviousHandler(
+		public WorkflowPreviousHandler(
             IOrderDomainService orderDomainService,
             IOrderRepository orderRepository,
             IOrderScreenRepository orderScreenRepository,
@@ -44,8 +47,10 @@ namespace Hotline.Application.Handlers.FlowEngine
             IMapper mapper,
             ILogger<WorkflowPreviousHandler> logger,
             IRepository<User> userRepository,
-            IMediator mediator
-            )
+            IMediator mediator,
+            ISessionContext sessionContext,
+            IRepository<OrderScreenDetail> orderScreenDetailRepository
+			)
         {
             _orderDomainService = orderDomainService;
             _orderRepository = orderRepository;
@@ -58,7 +63,9 @@ namespace Hotline.Application.Handlers.FlowEngine
             _mediator = mediator;
             _orderScreenRepository = orderScreenRepository;
             _orderDelayRepository = orderDelayRepository;
-        }
+            _sessionContext = sessionContext;
+            _orderScreenDetailRepository = orderScreenDetailRepository;
+		}
 
         /// <summary>Handles a notification</summary>
         /// <param name="notification">The notification</param>
@@ -162,9 +169,16 @@ namespace Hotline.Application.Handlers.FlowEngine
                     if (screen != null)
                     {
                         screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
+                        screen.SendBackTime = DateTime.Now;
                         await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
                     }
-                    break;
+					OrderScreenDetail detail = new OrderScreenDetail
+					{
+						ScreenId = screen.Id
+					};
+					detail.Audit(_sessionContext.UserId, _sessionContext.UserName, _sessionContext.OrgId, _sessionContext.OrgName, 2);
+                    await _orderScreenDetailRepository.AddAsync(detail, cancellationToken);
+					break;
                 case WorkflowModuleConsts.KnowledgeAdd:
                 case WorkflowModuleConsts.KnowledgeUpdate:
                 case WorkflowModuleConsts.KnowledgeDelete:

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

@@ -111,6 +111,11 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.TelNo, s => s.TelNo)
                 .Map(d => d.RecordingFileUrl, s => s.AudioFile)
                 ;
+
+            config.ForType<TrCallRecord, TrCallDtoNew>()
+                .Map(d => d.Cpn, s => s.CPN)
+                .Map(d => d.Cdpn, s => s.CDPN)
+                ;
         }
 
         private DateTime? FormatDateTime(string? time)

+ 10 - 5
src/Hotline.Application/Mappers/OrderMapperConfigs.cs

@@ -31,13 +31,18 @@ public class OrderMapperConfigs : IRegister
             .Map(d => d.StartTime, s => s.Order.StartTime)
             .Map(d => d.FiledTime, s => s.Order.FiledTime)
             .Map(d => d.RecordUrl, s => s.OrderVisit.RecordUrl)
+            .Map(d=>d.SeatEvaluate,s=>s.AiSeatEvaluate)
             .AfterMapping((s, d) =>
             {
-                d.SeatEvaluate = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Seat)?.SeatEvaluate;
-                d.OrgProcessingResults = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.OrgProcessingResults?.Value;
-                d.IsContact = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.IsContact == true ? "是" : "否";
-                d.Volved = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.Volved == true ? "是" : "否";
-                d.IsSuccessText = s.IsSuccess == true ? "是" : "否";
+                //d.SeatEvaluate = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Seat)?.SeatEvaluate;
+                //d.OrgProcessingResults = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.OrgProcessingResults?.Value;
+                //d.IsContact = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.IsContact == true ? "是" : s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.IsContact == false ? "否" : "";
+                //d.Volved = s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.Volved == true ? "是" : s.OrderVisit.OrderVisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org)?.Volved == false ? "否" :"";
+                //d.IsSuccessText = s.IsSuccess == true ? "是" : s.IsSuccess == false ? "否" : "";
+                d.OrgProcessingResults = s.AiOrgProcessingResults?.Value;
+                d.IsContact = s.AiIsContact == true ? "是" : s.AiIsContact == false ? "否" : "";
+                d.Volved = s.AiVolved == true ? "是" : s.AiVolved == false ? "否" : "";
+                d.IsSuccessText = s.IsSuccess == true ? "是" : s.IsSuccess == false ? "否" : "";
             });
 
         config.ForType<OrderVisitDetail, OrgVisitDetailListResp>()

+ 5 - 1
src/Hotline.Application/Orders/AiOrderVisitApplication.cs

@@ -31,13 +31,17 @@ namespace Hotline.Application.Orders
                 .WhereIF(dto.AiOrderVisitTaskState != null, x => x.TaskState == dto.AiOrderVisitTaskState)
                 .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                 .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                .WhereIF(dto.AiVisitTimeBeginStart.HasValue,x=>x.BeginTime>= dto.AiVisitTimeBeginStart)
+                .WhereIF(dto.AiVisitTimeBeginEnd.HasValue,x=>x.BeginTime< dto.AiVisitTimeBeginEnd)
+                .WhereIF(dto.AiVisitTimeEndStart.HasValue,x=>x.EndTime>= dto.AiVisitTimeEndStart)
+                .WhereIF(dto.AiVisitTimeEndEnd.HasValue,x=>x.EndTime< dto.AiVisitTimeEndEnd)
                 .OrderByDescending(x => x.CreationTime);
         }
 
         public ISugarQueryable<AiOrderVisitDetail> QueryAiOrderVisitDetail(AiVisitDetailListDto dto)
         {
             return _aiOrderVisitDetailRepository.Queryable()
-                .Includes(x => x.OrderVisit, x => x.OrderVisitDetails)
+                //.Includes(x => x.OrderVisit, x => x.OrderVisitDetails)
                 .Includes(x => x.Order)
                 .Where(x => x.AiOrderVisitId == dto.Id)
                 .WhereIF(dto.AiOrderVisitState.HasValue, x => x.AiOrderVisitState == dto.AiOrderVisitState)

+ 12 - 2
src/Hotline.Application/Orders/OrderApplication.cs

@@ -505,7 +505,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .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.OrgName), d => d.CurrentHandleOrgName == dto.OrgName)//接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
             .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) //受理时间结束
@@ -618,6 +618,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .LeftJoin<Order>((x, o) => x.Id == o.ActualHandleOrgCode)
             .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= dto.StartTime)
             .WhereIF(dto.EndTime.HasValue, (x, o) => o.CreationTime <= dto.EndTime)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 1, (x, o) => o.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 2, (x, o) => o.IdentityType == EIdentityType.Enterprise)
             .WhereIF(IsCenter == false, (x, o) => o.ActualHandleOrgCode == _sessionContext.RequiredOrgId)
             .GroupBy((x, o) => new { x.Id, x.Name })
             .Select((x, o) => new OrderBiOrgDataListVo
@@ -692,6 +694,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             //.WhereIF(dto.Statuses.Any(), x => dto.Statuses.Contains(x.Status))  //工单状态
             .WhereIF(dto.QueryType == 1, (x, so) => x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime) //业务已办超期
             .WhereIF(dto.QueryType == 3, (x, so) => x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate()) //业务待办超期
+            .WhereIF(dto.TypeId != null && dto.TypeId == 1, (x, so) => x.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 2, (x, so) => x.IdentityType == EIdentityType.Enterprise)
             .WhereIF(dto.QueryType == 5, (x, so) =>
                 (x.Status >= EOrderStatus.Filed && x.ExpiredTime < x.FiledTime) || (x.Status < EOrderStatus.Filed && x.ExpiredTime < SqlFunc.GetDate()))
             .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), (x, so) => x.ActualHandleOrgCode == dto.OrgCode)
@@ -813,6 +817,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .Where(x => x.OrderVisit.VisitTime >= dto.StartTime.Value && x.OrderVisit.VisitTime <= dto.EndTime.Value && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited && !string.IsNullOrEmpty(x.VisitOrgCode))
             .WhereIF(string.IsNullOrEmpty(dto.OrgName) == false, x => x.VisitOrgName.Contains(dto.OrgName))
             .WhereIF(string.IsNullOrEmpty(dto.LineNum) == false, x => x.OrderVisit.Order.CallRecord.Gateway.Contains(dto.LineNum))
+            .WhereIF(dto.TypeId != null && dto.TypeId == 1, x => x.OrderVisit.Order.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 2, x => x.OrderVisit.Order.IdentityType == EIdentityType.Enterprise)
             .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId));
 
         var data = new List<VisitAndOrgSatisfactionStatisticsDto>();
@@ -908,6 +914,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(dto.OrgCode == "001", (x, it) => it.VisitOrgCode == dto.OrgCode)
             .WhereIF(dto.OrgCode != "001", (x, it) => it.VisitOrgCode.StartsWith(dto.OrgCode))
             .WhereIF(!string.IsNullOrEmpty(dto.LineNum), (x, it) => it.OrderVisit.Order.CallRecord.Gateway.Contains(dto.LineNum))
+            .WhereIF(dto.TypeId != null && dto.TypeId == 1, (x, it) => it.OrderVisit.Order.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 2, (x, it) => it.OrderVisit.Order.IdentityType == EIdentityType.Enterprise)
             .WhereIF(IsCenter == false, (x, it) => it.VisitOrgCode.StartsWith(_sessionContext.OrgId))
              .GroupBy((x, it) => new
              {
@@ -958,6 +966,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .Includes(x => x.OrderVisit, o => o.Order, d => d.CallRecord)
             .Where(x => x.OrderVisit.VisitTime >= dto.StartTime && x.OrderVisit.VisitTime <= dto.EndTime && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited)
             .WhereIF(dto.OrgCode == "001", x => x.VisitOrgCode == dto.OrgCode)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 1, x=> x.OrderVisit.Order.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 2, x => x.OrderVisit.Order.IdentityType == EIdentityType.Enterprise)
             //.WhereIF(dto.OrgCode != "001", x => x.VisitOrgCode == dto.OrgCode).
             .WhereIF(dto.IsOnlyMy == true, x => x.VisitOrgCode == dto.OrgCode)
             .WhereIF(IsCenter == true && dto.IsOnlyMy == true, x => x.VisitOrgCode == dto.OrgCode)
@@ -1172,7 +1182,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             else
             {
                 //if (dt.Columns.Contains(item))
-                    dt2.Columns.Add(item);
+                dt2.Columns.Add(item);
             }
         }
 

+ 10 - 10
src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs

@@ -223,7 +223,7 @@ namespace Hotline.Application.Orders
                 .WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType)
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.OrderVisit.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!))
                 .WhereIF(!string.IsNullOrEmpty(dto.CurrentHandleOrgName), x => x.OrderVisit.Order!.CurrentHandleOrgName!.Contains(dto.CurrentHandleOrgName!))
-                .WhereIF(dto.ActualHandleTime.HasValue && dto.EndActualHandleTime.HasValue, x => x.OrderVisit.Order!.ActualHandleTime >= dto.ActualHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndActualHandleTime)
+                .WhereIF(dto.CurrentHandleTime.HasValue && dto.EndCurrentHandleTime.HasValue, x => x.OrderVisit.Order!.ActualHandleTime >= dto.CurrentHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndCurrentHandleTime)
                 .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue, x => x.OrderVisit.Order!.FiledTime == dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime)
                 .WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue, x => x.OrderVisit.Order!.CreationTime == dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime)
                 .WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue, x => x.OrderVisit.VisitTime == dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime)
@@ -369,13 +369,13 @@ namespace Hotline.Application.Orders
                     OrgName = x.ApplyOrgName,
                     OrgType = o.OrgType,
                     TotalSumCount = SqlFunc.AggregateCount(x.Id),
-                    VerySatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
-                    SatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
-                    RegardedAsSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
-                    DefaultSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
-                    NoSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
-                    NoEvaluateCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
-                    NoPutThroughCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
+                    VerySatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
+                    SatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
+                    RegardedAsSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
+                    DefaultSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
+                    NoSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
+                    NoEvaluateCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
+                    NoPutThroughCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
                 });
         }
 
@@ -426,8 +426,8 @@ namespace Hotline.Application.Orders
                 .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
                 .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
-                .WhereIF(dto.TypeId is 1 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == key)
-                .WhereIF(dto.TypeId is 2 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == key)
+                .WhereIF(dto.VisitTypeId is 1 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == key)
+                .WhereIF(dto.VisitTypeId is 2 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == key)
                 .Where(x => x.ApplyOrgId == dto.OrgId)
                 .Where(x => x.State == ESecondaryHandlingState.End);
         }

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

@@ -0,0 +1,97 @@
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Calls;
+using Hotline.Settings;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Enums.CallCenter;
+using SqlSugar;
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+using XF.Domain.Repository;
+
+namespace Hotline.Application.StatisticalReport
+{
+    public class CallReportApplication : ICallReportApplication, IScopeDependency
+    {
+        private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+
+        public CallReportApplication(
+            IRepository<TrCallRecord> trCallRecordRepository,
+            ISystemSettingCacheManager systemSettingCacheManager)
+        {
+            _trCallRecordRepository = trCallRecordRepository;
+            _systemSettingCacheManager = systemSettingCacheManager;
+
+        }
+
+        /// <summary>
+        /// 话务日期明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<List<QueryCallsDetailDto>> QueryCallsDetailAsync(BiQueryCallsDto dto)
+        {
+            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]);
+            //坐席超时挂断时间
+            int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
+
+            //未接秒挂时间
+            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 callData = await _trCallRecordRepository.Queryable()
+                    .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime)
+                    .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
+                     .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
+                     .GroupBy(p => p.CreatedTime.ToString("yyyy-MM-dd"))
+                    .Select(p => new QueryCallsDetailDto
+                    {
+                        Date = p.CreatedTime.ToString("yyyy-MM-dd"),
+                        InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
+                        InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
+                        NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingTimes <= noConnectByeTimes && p.RingTimes > 0, 1, 0)), //未接通秒挂
+                        TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.OnState == EOnState.On, p.Duration, 0)), //呼入总时长
+                        InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
+                        InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
+                        TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.RingTimes >= CallInOverConnRingTime, 1, 0)),//超时接通量
+                        TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
+                        QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.QueueTims > 0 && p.RingTimes == 0 && p.OnState == EOnState.NoOn, 1, 0)), //队列挂断
+                        IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
+                        OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
+                        OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
+                    })
+                    .ToListAsync();
+
+            return callData;
+        }
+
+        /// <summary>
+        /// 话务日期明细-呼入总量/接通总量
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto)
+        {
+            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)
+                    .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime && p.CallDirection == ECallDirection.In)
+                    .WhereIF(dto.TypeCode == "2", p => p.OnState == EOnState.On && p.AnsweredTime != null)
+                    .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
+                     .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
+                     .OrderByDescending(p => p.CreatedTime)
+                    .MergeTable();
+        }
+
+    }
+}

+ 24 - 0
src/Hotline.Application/StatisticalReport/ICallReportApplication.cs

@@ -0,0 +1,24 @@
+using Hotline.CallCenter.Calls;
+using Hotline.Share.Dtos.CallCenter;
+using SqlSugar;
+
+namespace Hotline.Application.StatisticalReport
+{
+    public interface ICallReportApplication
+    {
+        /// <summary>
+        /// 话务日期明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        Task<List<QueryCallsDetailDto>> QueryCallsDetailAsync(BiQueryCallsDto dto);
+
+        /// <summary>
+        /// 话务日期明细-呼入总量/接通总量
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto);
+
+    }
+}

+ 80 - 16
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -1,11 +1,8 @@
 using Hotline.Application.Orders;
-using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.Calls;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Settings;
-using Hotline.Settings.Hotspots;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.FlowEngine;
@@ -265,10 +262,18 @@ where 1=1 {5}
 order by ""su"".""OrgCode""";
             var orgLength = IsCenter == true ? 6 : _sessionContext.RequiredOrgId.Length + 3;
             var isOrg = IsCenter == false ? " and \"HandlerOrgId\" like concat('" + _sessionContext.RequiredOrgId + "','%') " : " ";
-            var IsProvince = dto.IsProvince.HasValue && dto.IsProvince == true ? "  and \"o\".\"Source\"=100 " : " ";
+            string strWhere = " ";
+            if (dto.IsProvince.HasValue && dto.IsProvince == true)
+                strWhere += "  and \"o\".\"Source\"=100 ";
+
+            if (dto.TypeId.HasValue && dto.TypeId == 1)
+                strWhere += " and \"o\".\"IdentityType\"=1 ";
+            else if (dto.TypeId.HasValue && dto.TypeId == 2)
+                strWhere += " and \"o\".\"IdentityType\"=2 ";
+
             var orgName = string.IsNullOrEmpty(dto.OrgName) == false ? "   and   \"OrgName\" like concat('%'," + dto.OrgName + ",'%')" : "";
 
-            strSql = string.Format(strSql, dto.StartTime, dto.EndTime, IsProvince, orgLength, isOrg, orgName);
+            strSql = string.Format(strSql, dto.StartTime, dto.EndTime, strWhere, orgLength, isOrg, orgName);
 
             return _orderRepository.DepartmentalProcessingStatisticsNew(strSql);
         }
@@ -462,14 +467,23 @@ left join ""system_organize"" ""so"" on ""so"".""Id""=""su"".""OrgCode""
 where 1=1 {5}
 order by ""su"".""OrgCode""";
 
-            var IsProvince = dto.IsProvince.HasValue && dto.IsProvince == true ? "  and \"o\".\"Source\"=100 " : " ";
+            string strWhere = " ";
+            if (dto.IsProvince.HasValue && dto.IsProvince == true)
+                strWhere += "  and \"o\".\"Source\"=100 ";
+
+            if (dto.TypeId.HasValue && dto.TypeId == 1)
+                strWhere += " and \"o\".\"IdentityType\"=1 ";
+            else if (dto.TypeId.HasValue && dto.TypeId == 2)
+                strWhere += " and \"o\".\"IdentityType\"=2 ";
+
+            // var IsProvince = dto.IsProvince.HasValue && dto.IsProvince == true ? "  and \"o\".\"Source\"=100 " : " ";
             var orgLength = dto.OrgCode.Length + 3;
 
             var isOrg = dto.OrgCode == "001" ? "  and \"HandlerOrgId\" ='001'" : " and \"HandlerOrgId\" like concat('" + dto.OrgCode + "','%') ";
 
             var orgName = string.IsNullOrEmpty(dto.OrgName) == false ? "   and   \"OrgName\" like concat('%'," + dto.OrgName + ",'%')" : "";
 
-            strSql = string.Format(strSql, dto.StartTime, dto.EndTime, IsProvince, orgLength, isOrg, orgName);
+            strSql = string.Format(strSql, dto.StartTime, dto.EndTime, strWhere, orgLength, isOrg, orgName);
 
             return _orderRepository.DepartmentalProcessingStatisticsNew(strSql);
         }
@@ -493,6 +507,8 @@ order by ""su"".""OrgCode""";
                          .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
                          && t.Status >= EWorkflowStepStatus.Handled && t.TraceState != EWorkflowTraceState.StepRemoveByPrevious)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -506,6 +522,8 @@ order by ""su"".""OrgCode""";
                        .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
                        && t.Status < EWorkflowStepStatus.Handled)
                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                        .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -518,6 +536,8 @@ order by ""su"".""OrgCode""";
                           .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
                         .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && d.DelayState == EDelayState.Pass)
                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                          .WhereIF(dto.TypeId != null && dto.TypeId == 1, (d, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (d, o) => o.IdentityType == EIdentityType.Enterprise)
                         .WhereIF(dto.OrgCode == "001", (d, o) => d.ApplyOrgCode == dto.OrgCode)
                         .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.ApplyOrgCode.StartsWith(dto.OrgCode))
                         .WhereIF(dto.OrgCode == "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.ApplyOrgCode == dto.OrgCode)
@@ -532,6 +552,8 @@ order by ""su"".""OrgCode""";
                          && t.Status >= EWorkflowStepStatus.Handled && t.HandleTime > t.StepExpiredTime && t.CountersignPosition == ECountersignPosition.None
                          && t.TraceState != EWorkflowTraceState.StepRemoveByPrevious)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                           .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -545,6 +567,8 @@ order by ""su"".""OrgCode""";
                          .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
                          && t.Status < EWorkflowStepStatus.Handled && DateTime.Now > t.StepExpiredTime && t.CountersignPosition == ECountersignPosition.None)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                           .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -559,6 +583,8 @@ order by ""su"".""OrgCode""";
                          && t.Status >= EWorkflowStepStatus.Handled && t.HandleTime > t.StepExpiredTime && t.CountersignPosition > ECountersignPosition.None
                          && t.TraceState != EWorkflowTraceState.StepRemoveByPrevious)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                           .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -572,6 +598,8 @@ order by ""su"".""OrgCode""";
                          .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
                          && t.Status < EWorkflowStepStatus.Handled && DateTime.Now > t.StepExpiredTime && t.CountersignPosition > ECountersignPosition.None)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                           .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -586,6 +614,8 @@ order by ""su"".""OrgCode""";
                             && t.Status >= EWorkflowStepStatus.Handled && t.HandleTime > t.StepExpiredTime && t.CountersignPosition >= ECountersignPosition.None
                             && t.TraceState != EWorkflowTraceState.StepRemoveByPrevious)
                             .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                              .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                             .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -597,6 +627,8 @@ order by ""su"".""OrgCode""";
                              .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
                              && t.Status < EWorkflowStepStatus.Handled && DateTime.Now > t.StepExpiredTime && t.CountersignPosition >= ECountersignPosition.None)
                              .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                               .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                              .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -612,6 +644,8 @@ order by ""su"".""OrgCode""";
                             && t.Status >= EWorkflowStepStatus.Handled && t.CountersignPosition > ECountersignPosition.None
                             && t.TraceState != EWorkflowTraceState.StepRemoveByPrevious)
                             .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                              .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                             .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -625,6 +659,8 @@ order by ""su"".""OrgCode""";
                              .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime
                              && t.Status < EWorkflowStepStatus.Handled && t.CountersignPosition > ECountersignPosition.None)
                              .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                               .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                              .WhereIF(dto.OrgCode == "001", (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (t, o) => t.HandlerOrgId == dto.OrgCode)
@@ -636,6 +672,8 @@ order by ""su"".""OrgCode""";
                     query = _orderRepository.Queryable()
                             .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status < EOrderStatus.WaitForAccept)
                            .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, o => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, o => o.IdentityType == EIdentityType.Enterprise)
                             .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
@@ -646,6 +684,8 @@ order by ""su"".""OrgCode""";
                     query = _orderRepository.Queryable()
                           .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status >= EOrderStatus.Filed)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, o => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, o => o.IdentityType == EIdentityType.Enterprise)
                           .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
@@ -656,6 +696,8 @@ order by ""su"".""OrgCode""";
                     query = _orderRepository.Queryable()
                          .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status == EOrderStatus.Filed)
                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, o => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, o => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
@@ -666,6 +708,8 @@ order by ""su"".""OrgCode""";
                     query = _orderRepository.Queryable()
                          .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status >= EOrderStatus.Published && o.IsPublicity == true)
                         .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, o => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, o => o.IdentityType == EIdentityType.Enterprise)
                          .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
@@ -676,6 +720,8 @@ order by ""su"".""OrgCode""";
                     query = _orderRepository.Queryable()
                         .Where(o => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Status >= EOrderStatus.Published && o.IsPublicity == false)
                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, o => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, o => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, o => o.IdentityType == EIdentityType.Enterprise)
                         .WhereIF(dto.OrgCode == "001", o => o.ActualHandleOrgCode == dto.OrgCode)
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, o => o.ActualHandleOrgCode.StartsWith(dto.OrgCode))
                             .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, o => o.ActualHandleOrgCode == dto.OrgCode)
@@ -687,6 +733,8 @@ order by ""su"".""OrgCode""";
                         .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
                        .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null)
                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, (d, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (d, o) => o.IdentityType == EIdentityType.Enterprise)
                        .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
@@ -699,6 +747,8 @@ order by ""su"".""OrgCode""";
                        .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null
                        && (d.Status == EScreenStatus.Approval || d.Status == EScreenStatus.Apply))
                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, (d, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (d, o) => o.IdentityType == EIdentityType.Enterprise)
                        .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
@@ -710,6 +760,8 @@ order by ""su"".""OrgCode""";
                        .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
                        .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null && d.Status == EScreenStatus.End)
                        .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, (d, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (d, o) => o.IdentityType == EIdentityType.Enterprise)
                        .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
@@ -721,6 +773,8 @@ order by ""su"".""OrgCode""";
                       .LeftJoin<Order>((d, o) => d.OrderId == o.Id)
                       .Where((d, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null && d.Status == EScreenStatus.Refuse)
                       .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (d, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, (d, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (d, o) => o.IdentityType == EIdentityType.Enterprise)
                       .WhereIF(dto.OrgCode == "001", (d, o) => d.CreatorOrgId == dto.OrgCode)
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode != dto.ParentOrgCode, (d, o) => d.CreatorOrgId.StartsWith(dto.OrgCode))
                        .WhereIF(dto.OrgCode != "001" && dto.OrgCode == dto.ParentOrgCode, (d, o) => d.CreatorOrgId == dto.OrgCode)
@@ -744,6 +798,8 @@ order by ""su"".""OrgCode""";
                         .LeftJoin<Order>((t, o) => t.ExternalId == o.Id)
                          .Where((t, o) => t.ModuleCode == WorkflowModuleConsts.OrderHandle && o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime)
                          .WhereIF(dto.IsProvince.HasValue && dto.IsProvince == true, (t, o) => o.Source == ESource.ProvinceStraight)
+                             .WhereIF(dto.TypeId != null && dto.TypeId == 1, (t, o) => o.IdentityType == EIdentityType.Citizen)
+                         .WhereIF(dto.TypeId != null && dto.TypeId == 2, (t, o) => o.IdentityType == EIdentityType.Enterprise)
                          // .WhereIF(IsCenter, (t, o) => t.HandlerOrgId == dto.OrgCode)
                          .WhereIF(!_sessionContext.OrgIsCenter, (t, o) => t.HandlerOrgId.StartsWith(dto.OrgCode))
                          .GroupBy((t, o) => o.Id)
@@ -1656,8 +1712,11 @@ order by ""su"".""OrgCode""";
 
             return _orderDelayRepository.Queryable()
                 .LeftJoin<SystemOrganize>((x, o) => x.ApplyOrgCode == o.Id)
-                .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
-                .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
+                .LeftJoin<Order>((x, o, s) => x.OrderId == s.Id)
+                .WhereIF(dto.StartTime.HasValue, (x, o, s) => x.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime.HasValue, (x, o, s) => x.CreationTime <= dto.EndTime)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 1, (x, o, s) => s.IdentityType == EIdentityType.Citizen)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 2, (x, o, s) => s.IdentityType == EIdentityType.Enterprise)
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Contains(dto.OrgName))
                 .WhereIF(IsCenter == false, x => x.ApplyOrgCode.StartsWith(_sessionContext.RequiredOrgId))
                 .GroupBy(x => new { x.ApplyOrgCode, x.ApplyOrgName })
@@ -1690,6 +1749,8 @@ order by ""su"".""OrgCode""";
                  .Includes(x => x.Order)
                  .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                  .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 1, x => x.Order.IdentityType == EIdentityType.Citizen)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 2, x => x.Order.IdentityType == EIdentityType.Enterprise)
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), x => x.ApplyOrgCode == dto.OrgCode)
                  .WhereIF(dto.Type is 1, x => x.DelayState == EDelayState.Pass)
                  .WhereIF(dto.Type is 2, x => x.DelayState == EDelayState.NoPass)
@@ -1712,6 +1773,8 @@ order by ""su"".""OrgCode""";
 
             var orderData = _orderRepository.Queryable()
               .Where(it => it.CreationTime >= dto.StartTime && it.CreationTime <= dto.EndTime && it.Status >= EOrderStatus.Filed)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 1, it => it.IdentityType == EIdentityType.Citizen)
+            .WhereIF(dto.TypeId != null && dto.TypeId == 2, it => it.IdentityType == EIdentityType.Enterprise)
               .Select(it => new
               {
                   OrgCode = IsCenter == true ? it.ActualHandleOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) : it.ActualHandleOrgCode.Substring(0, _sessionContext.RequiredOrgId.Length + 3),
@@ -1784,7 +1847,8 @@ order by ""su"".""OrgCode""";
             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)
-
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode != "001" && _sessionContext.RequiredOrgId != dto.OrgCode, p => p.ActualHandleOrgCode.StartsWith(dto.OrgCode))
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode != "001" && _sessionContext.RequiredOrgId == dto.OrgCode, p => p.ActualHandleOrgCode == dto.OrgCode)
                  .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), p => p.AcceptTypeCode == dto.AcceptTypeCode)
@@ -1814,9 +1878,9 @@ order by ""su"".""OrgCode""";
                 .WhereIF(!string.IsNullOrEmpty(dto.VisitUser), x => x.OrderVisit.Employee.Name.Contains(dto.VisitUser))
                 .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order.No == dto.No)
                 .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order.Title.Contains(dto.Title))
-                .WhereIF(dto.OrgCodes.Any(), x => dto.OrgCodes.Contains(x.VisitOrgCode))
-                .WhereIF(dto.HotspotIds.Any(), x => dto.HotspotIds.Contains(x.OrderVisit.Order.HotspotId))
-                .WhereIF(dto.Channels.Any(), x => dto.Channels.Contains(x.OrderVisit.Order.SourceChannelCode))
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgId), x => x.VisitOrgCode == dto.OrgId)//接办部门
+                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), x => x.OrderVisit.Order.HotspotSpliceName != null && x.OrderVisit.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+                .WhereIF(!string.IsNullOrEmpty(dto.Channel), x => x.OrderVisit.Order.SourceChannelCode == dto.Channel)//受理类型
                 .WhereIF(dto.CreationTimeStart.HasValue, x => x.OrderVisit.Order.CreationTime >= dto.CreationTimeStart) //受理时间开始
                 .WhereIF(dto.CreationTimeEnd.HasValue, x => x.OrderVisit.Order.CreationTime <= dto.CreationTimeEnd) //受理时间结束
                 .WhereIF(dto.ActualHandleTimeStart.HasValue, x => x.OrderVisit.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
@@ -1836,9 +1900,9 @@ order by ""su"".""OrgCode""";
             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)
-                .WhereIF(dto.TypeId != null && dto.TypeId == 2,x=>x.IdentityType == EIdentityType.Enterprise)
-                .WhereIF(!string.IsNullOrEmpty(dto.Gateway),x=>x.TransferPhone == dto.Gateway)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 1, x => x.IdentityType == EIdentityType.Citizen)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 2, x => x.IdentityType == EIdentityType.Enterprise)
+                .WhereIF(!string.IsNullOrEmpty(dto.Gateway), x => x.TransferPhone == dto.Gateway)
                 .GroupBy(x => x.AcceptType)
                 .Select(x => new AcceptTypeStatisticsDto
                 {

+ 24 - 3
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -4,6 +4,7 @@ using Hotline.Application.Orders;
 using Hotline.Application.Quality;
 using Hotline.Authentications;
 using Hotline.Caching.Interfaces;
+using Hotline.ContingencyManagement;
 using Hotline.File;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
@@ -11,6 +12,8 @@ using Hotline.Orders;
 using Hotline.OrderTranspond;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.ContingencyManagement;
 using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
@@ -55,6 +58,7 @@ namespace Hotline.Application.Subscribers
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
         private readonly IRepository<OrderWarning> _orderWarningRepository;
         private readonly IRepository<OrderRevoke> _orderRevokeRepository;
+        private readonly IRepository<ContingencyManagementOrders> _contingencyManagementOrdersRepository;
 
         public DataSharingSubscriber(
             IRepository<OrderVisit> orderVisitRepository,
@@ -79,7 +83,8 @@ namespace Hotline.Application.Subscribers
             IOrderApplication orderApplication,
             ISystemSettingCacheManager systemSettingCacheManager,
             IRepository<OrderWarning> orderWarningRepository,
-             IRepository<OrderRevoke> orderRevokeRepository
+             IRepository<OrderRevoke> orderRevokeRepository,
+             IRepository<ContingencyManagementOrders> contingencyManagementOrdersRepository
             )
         {
             _orderSendBackRepository = orderSendBackRepository;
@@ -105,6 +110,7 @@ namespace Hotline.Application.Subscribers
             _systemSettingCacheManager = systemSettingCacheManager;
             _orderWarningRepository = orderWarningRepository;
             _orderRevokeRepository = orderRevokeRepository;
+            _contingencyManagementOrdersRepository = contingencyManagementOrdersRepository;
         }
 
         /// <summary>
@@ -113,7 +119,7 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderReturnFeedback)]
         public async Task RecOrderReturnAsync(OrderSendBackResultDto dto, CancellationToken cancellationToken)
         {
-            var sendBack = await _orderSendBackRepository.GetAsync(p=>p.Id==dto.Id&&p.State==0, cancellationToken);
+            var sendBack = await _orderSendBackRepository.GetAsync(p => p.Id == dto.Id && p.State == 0, cancellationToken);
             if (sendBack != null)
             {
                 sendBack.Result = dto.Result;
@@ -256,7 +262,7 @@ namespace Hotline.Application.Subscribers
             model.OrgId = "001";
             model.OrgName = "市民热线服务中心";
             model.RemindTime = dto.RemindTime;
-            model.DsBisId= dto.DsBisId;
+            model.DsBisId = dto.DsBisId;
 
             //if (!string.IsNullOrEmpty(order.WorkflowId))
             //{
@@ -816,5 +822,20 @@ namespace Hotline.Application.Subscribers
                 await _transpondCityRawDataRepository.UpdateAsync(data, cancellationToken);
             }
         }
+
+        /// <summary>
+        /// 应急管理局推送回调
+        /// </summary>
+        /// <returns></returns>
+        [CapSubscribe(EventNames.HotlineOrderContingencyManagementState)]
+        public async Task RecHotlineOrderContingencyManagementState(RecOrderStateDto dto, CancellationToken cancellationToken)
+        {
+            var data = await _contingencyManagementOrdersRepository.GetAsync(p => p.Id == dto.Id, cancellationToken);
+            if (data != null && dto.State != data.PushState)
+            {
+                data.PushState = dto.State;
+                await _contingencyManagementOrdersRepository.UpdateAsync(data, cancellationToken);
+            }
+        }
     }
 }

+ 69 - 9
src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs

@@ -1,16 +1,8 @@
-using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.Calls;
-using Hotline.Orders;
+using Hotline.CallCenter.Calls;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using SqlSugar;
-using System;
-using System.Collections.Generic;
-using System.Drawing.Printing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using XF.Domain.Dependency;
 
 namespace Hotline.Repository.SqlSugar.CallCenter
@@ -63,6 +55,74 @@ namespace Hotline.Repository.SqlSugar.CallCenter
             return listCall;
         }
 
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="beginDate"></param>
+        /// <param name="endDate"></param>
+        /// <param name="noConnectByeTimes"></param>
+        /// <param name="effectiveTimes"></param>
+        /// <param name="connectByeTimes"></param>
+        /// <param name="CallInOverConnRingTime"></param>
+        /// <param name="SeatChaoTime"></param>
+        /// <param name="Line"></param>
+        /// <returns></returns>
+        public async Task<List<QueryCallsDetailDto>> QueryCallsHourDetail(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int CallInOverConnRingTime, int SeatChaoTime, string? Line)
+        {
+            List<int> dts = new List<int>();
+            for (int i = 0; i < 24; i++)
+            {
+                dts.Add(i);
+            }
+
+            var listHour = Db.Reportable(dts).ToQueryable<int>();
+
+            var list = Db.Queryable<TrCallRecord>()
+                  .Where(p => p.CreatedTime >= beginDate && p.CreatedTime <= endDate)
+                  .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
+                  .WhereIF(!string.IsNullOrEmpty(Line), p => p.Gateway == Line)
+                   .GroupBy(p => p.CreatedTime.Hour)
+                   .Select(p => new
+                   {
+                       Hour = p.CreatedTime.Hour, //小时段
+                       InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
+                       InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
+                       NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingTimes <= noConnectByeTimes && p.RingTimes > 0, 1, 0)), //未接通秒挂
+                       TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.OnState == EOnState.On, p.Duration, 0)), //呼入总时长
+                       InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
+                       InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
+                       TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.RingTimes >= CallInOverConnRingTime, 1, 0)),//超时接通量
+                       TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
+                       QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.QueueTims > 0 && p.RingTimes == 0 && p.OnState == EOnState.NoOn, 1, 0)), //队列挂断
+                       IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
+                       OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
+                       OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
+                   })
+                   .MergeTable();
+
+            var listCall = await listHour.LeftJoin(list, (x, p) => x.ColumnName == p.Hour)
+                .OrderBy(x => x.ColumnName)
+               .Select((x, p) => new QueryCallsDetailDto()
+               {
+                   Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+                   InTotal = p.InTotal,
+                   InConnectionQuantity = p.InConnectionQuantity,
+                   NotAcceptedHang = p.NotAcceptedHang,
+                   TotalDurationIncomingCalls = p.TotalDurationIncomingCalls,
+                   InAvailableAnswer = p.InAvailableAnswer,
+                   InHangupImmediateWhenAnswered = p.InHangupImmediateWhenAnswered,
+                   TimeoutConnection = p.TimeoutConnection,
+                   TimeoutSuspension = p.TimeoutSuspension,
+                   QueueByeCount = p.QueueByeCount,
+                   IvrByeCount = p.IvrByeCount,
+                   OutTotal = p.OutTotal,
+                   OutConnectionQuantity = p.OutConnectionQuantity
+               })
+               .ToListAsync();
+
+            return listCall;
+        }
+
         public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string source)
         {
             //计算小时差

+ 34 - 2
src/Hotline.Share/Dtos/Ai/AiDto.cs

@@ -204,6 +204,8 @@ namespace Hotline.Share.Dtos.Ai
     {
         public int CallNo { get; set; }
 
+        public DateTime? CallTime { get; set; }
+
         /// <summary>
         /// 呼叫状态(1:呼叫中、2:完成、3:呼叫失败)
         /// </summary>
@@ -237,6 +239,26 @@ namespace Hotline.Share.Dtos.Ai
     public record AiVisitListDto : PagedKeywordRequest
     {
         public EAiOrderVisitTaskState? AiOrderVisitTaskState { get; set; }
+
+        /// <summary>
+        /// 智能回访开始时间开始
+        /// </summary>
+        public DateTime? AiVisitTimeBeginStart { get; set; }
+
+        /// <summary>
+        /// 智能回访开始时间结束
+        /// </summary>
+        public DateTime? AiVisitTimeBeginEnd { get; set; }
+
+        /// <summary>
+        /// 智能回访结束时间开始
+        /// </summary>
+        public DateTime? AiVisitTimeEndStart { get; set; }
+
+        /// <summary>
+        /// 智能回访结束时间结束
+        /// </summary>
+        public DateTime? AiVisitTimeEndEnd { get; set; }
     }
 
     public record AiVisitDetailListDto : PagedKeywordRequest
@@ -407,6 +429,16 @@ namespace Hotline.Share.Dtos.Ai
         /// 是否成功
         /// </summary>
         public string? IsSuccessText { get; set; }
+
+        /// <summary>
+        /// 重呼次数
+        /// </summary>
+        public int CallTimes { get; set; }
+
+        /// <summary>
+        /// 最新外呼时间
+        /// </summary>
+        public DateTime? CallTime { get; set; }
     }
 
     public class CanAiVisitListDto
@@ -424,12 +456,12 @@ namespace Hotline.Share.Dtos.Ai
         /// <summary>
         /// 热点分类
         /// </summary>
-        public List<string> HotspotIds { get; set; } = new();
+        public string Hotspot { get; set; }
 
         /// <summary>
         /// 受理类型
         /// </summary>
-        public List<string> AcceptTypes { get; set; } = new();
+        public string AcceptType { get; set; }
     }
 
 

+ 8 - 3
src/Hotline.Share/Dtos/Bi/BiOrderDto.cs

@@ -16,6 +16,11 @@ namespace Hotline.Share.Dtos.Bi
         /// 是否只看自己(优先级最高)
         /// </summary>
         public bool? IsOnlyMy { get; set; }
+
+        /// <summary>
+        /// 来电/信人身份0:全部 ,1:市民,2:企业
+        /// </summary>
+        public int? TypeCode { get; set; }
     }
 
     public record HighFrequencyCallStatisticsRequest : PagedRequest
@@ -31,11 +36,11 @@ namespace Hotline.Share.Dtos.Bi
         public DateTime StartTime { get; set; }
         public DateTime EndTime { get; set; }
 
-        public List<string> HotspotIds { get; set; } = new();
+        public string Hotspot { get; set; }
 
-        public List<string> AreaCodes { get; set; } = new();
+        public string AreaCode { get; set; }
 
-        public List<string> AcceptTypeCodes { get; set; } = new();
+        public string AcceptType { get; set; }
     }
 
     public record HighMatterWarningDetailRequest : PagedRequest

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

@@ -8,4 +8,9 @@ public record BiQueryCallsDto: ReportPagedRequest
     /// 线路
     /// </summary>
     public string? Line { get; set; }
+
+    /// <summary>
+    /// 查询类型 1:呼入总量明细;2:接通总量明细
+    /// </summary>
+    public string? TypeCode { get; set; } = "1";
 }

+ 128 - 0
src/Hotline.Share/Dtos/CallCenter/QueryCallsDetailDto.cs

@@ -0,0 +1,128 @@
+namespace Hotline.Share.Dtos.CallCenter
+{
+    public class QueryCallsDetailDto
+    {
+        /// <summary>
+        /// 日期
+        /// </summary>
+        public string Date { get; set; }
+
+        /// <summary>
+        /// 时间
+        /// </summary>
+        public string Hour { get; set; }
+
+        /// <summary>
+        /// 呼入总量
+        /// </summary>
+        public int InTotal { get; set; }
+
+        /// <summary>
+        /// 呼入接通量
+        /// </summary>
+        public int InConnectionQuantity { get; set; }
+
+        /// <summary>
+        /// 未接秒挂
+        /// </summary>
+        public int NotAcceptedHang { get; set; }
+
+        /// <summary>
+        /// 呼入接通率
+        /// </summary>
+        public string InConnectionRate => CalcSatisfiedRate(InTotal - NotAcceptedHang, InConnectionQuantity);
+
+        /// <summary>
+        /// 呼入总时长
+        /// </summary>
+        public double TotalDurationIncomingCalls { get; set; }
+
+        /// <summary>
+        /// 平均时长
+        /// </summary>
+        public double AverageDuration => CalcAvg(TotalDurationIncomingCalls, InConnectionQuantity);
+
+        /// <summary>
+        /// 有效接通量
+        /// </summary>
+        public int InAvailableAnswer { get; set; }
+
+        /// <summary>
+        /// 呼入接通秒挂
+        /// </summary>
+        public int InHangupImmediateWhenAnswered { get; set; }
+
+        /// <summary>
+        /// 有效接通率
+        /// </summary>
+        public string EffectiveConnectionRate => CalcSatisfiedRate(InConnectionQuantity, InAvailableAnswer - InHangupImmediateWhenAnswered);
+
+        /// <summary>
+        /// 超时接通
+        /// </summary>
+        public int TimeoutConnection { get; set; }
+
+        /// <summary>
+        /// 超时挂断
+        /// </summary>
+        public int TimeoutSuspension { get; set; }
+
+        /// <summary>
+        /// 按时接通率
+        /// </summary>
+        public string OnTimeConnectionRate => CalcSatisfiedRate(InConnectionQuantity, InConnectionQuantity - TimeoutConnection - TimeoutSuspension);
+
+        /// <summary>
+        /// 队列挂断
+        /// </summary>
+        public int QueueByeCount { get; set; }
+
+        /// <summary>
+        /// IVR挂断
+        /// </summary>
+        public int IvrByeCount { get; set; }
+
+        /// <summary>
+        /// 呼出总量
+        /// </summary>
+        public int OutTotal { get; set; }
+
+        /// <summary>
+        /// 呼出接通量
+        /// </summary>
+        public int OutConnectionQuantity { get; set; }
+
+        /// <summary>
+        /// 呼出接通率
+        /// </summary>
+        public string OutConnectionRate => CalcSatisfiedRate(OutTotal, OutConnectionQuantity);
+
+        /// <summary>
+        /// 计算平均
+        /// </summary>
+        /// <param name="Count">总数</param>
+        /// <param name="Quantity"></param>
+        /// <returns></returns>
+        public double CalcAvg(double Count, int Quantity)
+        {
+            if (Count <= 0 || Quantity <= 0)
+                return 0;
+
+            return Math.Round((Quantity / (double)Count) * 100, 3);
+        }
+
+        /// <summary>
+        /// 计算满意度
+        /// </summary>
+        /// <param name="Count">总数</param>
+        /// <param name="Quantity"></param>
+        /// <returns></returns>
+        public string CalcSatisfiedRate(int Count, int Quantity)
+        {
+            if (Count <= 0 || Quantity <= 0)
+                return 0 + "%";
+
+            return Math.Round((Quantity / (double)Count) * 100, 3) + "%";
+        }
+    }
+}

+ 246 - 0
src/Hotline.Share/Dtos/ContingencyManagement/ContingencyManagementOrdersDto.cs

@@ -0,0 +1,246 @@
+using Hotline.Share.Dtos.File;
+using Hotline.Share.Enums.JudicialManagement;
+using Hotline.Share.Enums.Order;
+
+namespace Hotline.Share.Dtos.ContingencyManagement
+{
+    public class ContingencyManagementOrdersDto
+    {
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 来源渠道(电话、网站、APP等)
+        /// </summary>
+        public string? SourceChannel { get; set; }
+
+        public string? SourceChannelCode { get; set; }
+
+        /// <summary>
+        /// 来电号码
+        /// </summary>
+        public string? FromPhone { get; set; }
+
+        /// <summary>
+        /// 转接号码(转接来源)
+        /// </summary>
+        public string? TransferPhone { get; set; }
+
+        /// <summary>
+        /// 来电/信人姓名
+        /// </summary>
+        public string? FromName { get; set; }
+
+        /// <summary>
+        /// 来电/信人性别
+        /// </summary>
+        public EGender FromGender { get; set; }
+
+        /// <summary>
+        /// 来电/信人身份
+        /// </summary>
+        public EIdentityType? IdentityType { get; set; }
+
+        /// <summary>
+        /// 联系电话
+        /// </summary>
+        public string? Contact { get; set; }
+
+        public string? ContactMask { get; set; }
+
+        /// <summary>
+        /// 受理类型
+        /// </summary>
+        public string? AcceptType { get; set; }
+
+        public string? AcceptTypeCode { get; set; }
+
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string? HotspotId { get; set; }
+
+        public string? HotspotName { get; set; }
+
+        public string? HotspotSpliceName { get; set; }
+
+        /// <summary>
+        /// 外部数据(为前端提供级联功能)
+        /// </summary>
+        public string? HotspotExternal { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<FileDto>? Additions { get; set; } = new();
+
+        /// <summary>
+        /// 诉求内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 工单编码(20220101000001)
+        /// </summary>
+        public string? No { get; set; }
+
+        /// <summary>
+        /// 市民查询密码
+        /// </summary>
+        public string? Password { get; set; }
+
+        /// <summary>
+        /// 受理人id
+        /// </summary>
+        public string? AcceptorId { get; set; }
+
+        /// <summary>
+        /// 受理人名称
+        /// </summary>
+        public string? AcceptorName { get; set; }
+
+        /// <summary>
+        /// 受理人工号
+        /// </summary>
+        public string? AcceptorStaffNo { get; set; }
+
+        /// <summary>
+        /// 受理人部门编码
+        /// </summary>
+        public string? AcceptorOrgCode { get; set; }
+
+        /// <summary>
+        /// 受理人部门名称
+        /// </summary>
+        public string? AcceptorOrgName { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<FileJson>? FileJson { get; set; }
+
+        /// <summary>
+        /// 工单来源
+        /// </summary>
+        public EOrderSoure? OrderSoure { get; set; }
+
+        /// <summary>
+        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
+        /// </summary>
+        public DateTime? FiledTime { get; set; }
+
+        /// <summary>
+        /// 归档意见
+        /// </summary>
+        public string? FileOpinion { get; set; }
+
+        /// <summary>
+        /// 实际办理时间
+        /// </summary>
+        public DateTime? ActualHandleTime { get; set; }
+
+        /// <summary>
+        /// 实际办理人id
+        /// </summary>
+        public string? ActualHandlerId { get; set; }
+
+        /// <summary>
+        /// 实际办理人名称
+        /// </summary>
+        public string? ActualHandlerName { get; set; }
+
+        /// <summary>
+        /// 实际办理部门名称
+        /// </summary>
+        public string? ActualHandleOrgName { get; set; }
+
+        /// <summary>
+        /// 实际办理部门编码
+        /// </summary>
+        public string? ActualHandleOrgCode { get; set; }
+
+        /// <summary>
+        /// 实际办理意见(办理中...or 最终办理意见)
+        /// </summary>
+        public string ActualOpinion { get; set; } = "办理中...";
+
+        /// <summary>
+        /// 整理标题
+        /// </summary>
+        public string ArrangeTitle { get; set; }
+
+        /// <summary>
+        /// 整理内容
+        /// </summary>
+        public string ArrangeContent { get; set; }
+
+        /// <summary>
+        /// 整理后办理意见
+        /// </summary>
+        public string? ArrangementOpinion { get; set; }
+
+        /// <summary>
+        /// 经度
+        /// </summary>
+        public double? Longitude { get; set; }
+
+        /// <summary>
+        /// 维度
+        /// </summary>
+        public double? Latitude { get; set; }
+
+        /// <summary>
+        /// 行政区划编码
+        /// </summary>
+        public string? AreaCode { get; set; }
+
+        /// <summary>
+        /// 省
+        /// </summary>
+        public string? Province { get; set; }
+
+        /// <summary>
+        /// 市
+        /// </summary>
+        public string? City { get; set; }
+
+        /// <summary>
+        /// 区/县
+        /// </summary>
+        public string? County { get; set; }
+
+        /// <summary>
+        /// 乡镇(4级行政区划)
+        /// </summary>
+        public string? Town { get; set; }
+
+        /// <summary>
+        /// 详细街道
+        /// </summary>
+        public string? Street { get; set; }
+
+        /// <summary>
+        /// 行政区划地址
+        /// </summary>
+        public string? Address { get; set; }
+
+        /// <summary>
+        /// 完整地址
+        /// </summary>
+        public string? FullAddress { get; set; }
+
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public DateTime CreationTime { get; set; }
+
+        /// <summary>
+        ///  推送状态 0:推送中,1:成功,2:失败
+        /// </summary>
+        public string? PushState { get; set; }
+    }
+}

+ 42 - 0
src/Hotline.Share/Dtos/ContingencyManagement/ContingencyManagementPagedKeywordRequest.cs

@@ -0,0 +1,42 @@
+using Hotline.Share.Requests;
+
+namespace Hotline.Share.Dtos.ContingencyManagement
+{
+    public record ContingencyManagementPagedKeywordRequest : PagedKeywordRequest
+    {
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 工单编码(20220101000001)
+        /// </summary>
+        public string? No { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string? HotspotSpliceName { get; set; }
+
+        /// <summary>
+        /// 受理类型
+        /// </summary>
+        public string? AcceptType { get; set; }
+
+        /// <summary>
+        /// 来源渠道(电话、网站、APP等)
+        /// </summary>
+        public string? SourceChannel { get; set; }
+
+        /// <summary>
+        /// 办结时间开始
+        /// </summary>
+        public DateTime? FiledStartTime { get; set; }
+
+        /// <summary>
+        /// 办结时间结束
+        /// </summary>
+        public DateTime? FiledEndTime { get; set; }
+    }
+}

+ 15 - 0
src/Hotline.Share/Dtos/ContingencyManagement/RecOrderStateDto.cs

@@ -0,0 +1,15 @@
+namespace Hotline.Share.Dtos.ContingencyManagement
+{
+    public class RecOrderStateDto
+    {
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 状态
+        /// </summary>
+        public string State { get; set; }
+    }
+}

+ 4 - 4
src/Hotline.Share/Dtos/FlowEngine/Workflow/QueryWorkflowCountersignDto.cs

@@ -40,12 +40,12 @@ namespace Hotline.Share.Dtos.FlowEngine.Workflow
         /// <summary>
         /// 受理类型(√)
         /// </summary>
-        public List<string> AcceptTypes { get; set; } = new();
+        public string AcceptType { get; set; }
 
         /// <summary>
         /// 来源渠道(√)
         /// </summary>
-        public List<string> Channels { get; set; } = new();
+        public string Channel { get; set; }
 
         /// <summary>
         /// 会签类型
@@ -55,11 +55,11 @@ namespace Hotline.Share.Dtos.FlowEngine.Workflow
         /// <summary>
         /// 接办部门
         /// </summary>
-        public string? OrgName { get; set; }
+        public string? OrgId { get; set; }
 
         /// <summary>
         /// 热点分类(√)
         /// </summary>
-        public List<string> HotspotIds { get; set; } = new();
+        public string Hotspot { get; set; }
     }
 }

+ 1 - 1
src/Hotline.Share/Dtos/JudicialManagement/JudicialManagementAddOrderDto.cs

@@ -7,7 +7,7 @@ namespace Hotline.Share.Dtos.JudicialManagement
     /// <summary>
     /// 修改
     /// </summary>
-    public class JudicialManagementAddOrderDto: Position
+    public class JudicialManagementAddOrderDto : Position
     {
         /// <summary>
         /// 来源渠道(电话、网站、APP等)

+ 4 - 1
src/Hotline.Share/Dtos/Knowledge/KnowledgeBiDto.cs

@@ -33,8 +33,11 @@ namespace Hotline.Share.Dtos.Knowledge
 	}
 
 
-	public record KnowledgeBiDataListDto : PagedKeywordRequest
+	public record KnowledgeBiDataListDto : PagedRequest
 	{
+
+		public string? Keyword { get; set; }
+
 		/// <summary>
 		/// 开始时间
 		/// </summary>

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

@@ -18,7 +18,7 @@
         /// 总量
         /// </summary>
         public int AllCount => ZxAllCount + JyAllCount + QzAllCount + ByAllCount + JbAllCount + TsAllCount + QtAllCount;
-        public double? AllTimes => ZxAllTimes + JyAllTimes + QzAllTimes + ByAllTimes + JbAllTimes + TsAllTimes + QtAllTimes;
+        public double? AllTimes => Math.Round(ZxAllTimes.Value + JyAllTimes.Value + QzAllTimes.Value + ByAllTimes.Value + JbAllTimes.Value + TsAllTimes.Value + QtAllTimes.Value, 2);
         public double? AverageTime => GetCalculateAverage(AllCount, AllTimes);
        public string? AcceptanceTypeCode { get; set; }
 

+ 16 - 0
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -670,6 +670,11 @@ namespace Hotline.Share.Dtos.Order
         /// 交办人(派单员)
         /// </summary>
         public string? CenterToOrgHandlerName { get; set; }
+
+        /// <summary>
+        /// 是否退回审批中
+        /// </summary>
+        public bool IsReturnUnderApproval {  get; set; }
     }
 
     public class UpdateOrderDto : AddOrderDto
@@ -778,6 +783,12 @@ namespace Hotline.Share.Dtos.Order
 
         public string Title { get; set; }
 
+        /// <summary>
+        /// 工单标签(自贡)
+        /// </summary>
+        public string? OrderTag { get; set; }
+        public string? OrderTagCode { get; set; }
+
         #region 热点
 
         /// <summary>
@@ -961,6 +972,11 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public bool IsSensitiveWorkOrders { get; set; }
 
+        /// <summary>
+        /// 24小时办结
+        /// </summary>
+        public bool Is24HoursComplete { get; set; }
+
         /// <summary>
         /// 重点关注事件,保存前端选择,用于返回前端数据
         /// </summary>

+ 58 - 0
src/Hotline.Share/Dtos/Order/OrderScreenDetailDto.cs

@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Order
+{
+	public class OrderScreenDetailDto
+	{
+		/// <summary>
+		/// 甄别Id
+		/// </summary>
+		public string ScreenId { get; set; }
+
+		/// <summary>
+		/// 审批人
+		/// </summary>
+		public string? AuditUserName { get; set; }
+
+		/// <summary>
+		/// 审批人
+		/// </summary>
+		public string? AuditUserId { get; set; }
+
+		/// <summary>
+		/// 审批人
+		/// </summary>
+		public string? AuditOrgId { get; set; }
+
+		/// <summary>
+		/// 审批机构
+		/// </summary>
+		public string? AuditOrgName { get; set; }
+
+		/// <summary>
+		/// 审批时间
+		/// </summary>
+		public DateTime? AuditTime { get; set; }
+
+		/// <summary>
+		/// 审批类型   1 审批  2 退回
+		/// </summary>
+		public int AuditType { get; set; }
+
+
+		/// <summary>
+		/// 当前最新审批时间
+		/// </summary>
+		public DateTime? NewestAuditTime => AuditType == 1 ? AuditTime : null;
+
+
+		/// <summary>
+		/// 当前最新退回时间
+		/// </summary>
+		public DateTime? NewestBackTime => AuditType == 2 ? AuditTime : null;
+	}
+}

+ 64 - 0
src/Hotline.Share/Dtos/Order/OrderScreenDto.cs

@@ -69,12 +69,32 @@ namespace Hotline.Share.Dtos.Order
 		/// </summary>
 		public DateTime? ApplyEndTime { get; set; }
 
+		/// <summary>
+		/// 业务流程ID
+		/// </summary>
+		public string? WorkflowId { get; set; }
+
 		/// <summary>
 		/// 附件列表
 		/// </summary>
 		public List<FileDto> Files { get; set; } = new();
 
 		public List<FileJson>? FileJson { get; set; }
+
+		/// <summary>
+		/// 甄别退回次数
+		/// </summary>
+		public int SendBackNum { get; set; }
+
+		/// <summary>
+		/// 甄别退回到申请人
+		/// </summary>
+		public bool SendBackApply { get; set; }
+
+		/// <summary>
+		/// 甄别重提申请次数
+		/// </summary>
+		public int SendBackApplyNum { get; set; }
 	}
 
 	public class OrderScreenListDto
@@ -118,6 +138,16 @@ namespace Hotline.Share.Dtos.Order
 
 		public WorkflowDto Workflow { get; set; }
 
+		/// <summary>
+		/// 甄别明细
+		/// </summary>
+		public OrderScreenDetailDto ScreenDetail => ScreenDetails != null && ScreenDetails.Any() ? ScreenDetails.First() : null;
+
+		/// <summary>
+		/// 甄别明细
+		/// </summary>
+		public List<OrderScreenDetailDto> ScreenDetails { get; set; }
+
 		/// <summary>
 		/// 回访明细id
 		/// </summary>
@@ -212,6 +242,40 @@ namespace Hotline.Share.Dtos.Order
 		public decimal? TimeConsuming { get; set; }
 
 		public string TimeConsuminText => TimeConsuming.HasValue ? TimeConsuming.ToString() + "天" : "-";
+		/// <summary>
+		/// 甄别退回次数
+		/// </summary>
+		public int SendBackNum { get; set; }
+
+		/// <summary>
+		/// 甄别退回到申请人
+		/// </summary>
+		public bool SendBackApply { get; set; }
+
+		/// <summary>
+		/// 甄别退回
+		/// </summary>
+		public string ScreenSendBack => Status  == EScreenStatus.SendBack && SendBackApply ? "是" : "否";
+
+		/// <summary>
+		/// 甄别重提申请次数
+		/// </summary>
+		public int SendBackApplyNum { get; set; }
+
+		/// <summary>
+		/// 重提甄别
+		/// </summary>
+		public string ScreenSendBackApply => SendBackApplyNum > 0 ? "是" : "否";
+
+		/// <summary>
+		/// 甄别退回时间
+		/// </summary>
+		public DateTime? SendBackTime { get; set; }
+
+		/// <summary>
+		/// 甄别审批时间
+		/// </summary>
+		public DateTime? NewestAuditTime { get; set; }
 	}
 
 	public class PublishScreenDto {

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

@@ -9,7 +9,7 @@ using Hotline.Share.Enums.FlowEngine;
 
 namespace Hotline.Share.Dtos.Order
 {
-    public class OrderStartFlowDto : StartWorkflowDto<UpdateOrderDto>
+    public class OrderStartFlowDto : StartWorkflowDto<string>
     {
         
     }

+ 39 - 15
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -11,7 +11,7 @@ using XF.Utility.EnumExtensions;
 
 namespace Hotline.Share.Dtos.Order
 {
-    public record CanLinkCallRecordOrderVisitDto:PagedKeywordRequest
+    public record CanLinkCallRecordOrderVisitDto : PagedKeywordRequest
     {
 
     }
@@ -53,9 +53,14 @@ namespace Hotline.Share.Dtos.Order
         /// 是否省工单
         /// </summary>
         public bool? IsProvince { get; set; }
-	}
 
-    public record VisitJudgeQueryReq:PagedKeywordRequest
+        /// <summary>
+        /// 是否有效智能回访
+        /// </summary>
+        public bool? IsEffectiveAiVisit { get; set; }
+    }
+
+    public record VisitJudgeQueryReq : PagedKeywordRequest
     {
         /// <summary>
         /// 工单编号
@@ -77,17 +82,17 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 受理类型
         /// </summary>
-        public List<string> AcceptTypes { get; set; } = new();
+        public string AcceptType { get; set; }
 
         /// <summary>
         /// 热点分类
         /// </summary>
-        public List<string> HotspotIds { get; set; } = new();
+        public string Hotspot { get; set; }
 
         /// <summary>
         /// 接办部门
         /// </summary>
-        public List<string> OrgCodes { get; set; } = new();
+        public string OrgId { get; set; }
 
         /// <summary>
         /// 受理坐席名字或工号
@@ -505,7 +510,7 @@ namespace Hotline.Share.Dtos.Order
         public EJudgeState? JudgeState { get; set; }
 
         public string? JudgeStateText => JudgeState?.GetDescription() ?? string.Empty;
-        
+
         /// <summary>
         /// 评判意见
         /// </summary>
@@ -530,7 +535,12 @@ namespace Hotline.Share.Dtos.Order
 
         public OrderSecondaryHandlingDto SecondaryHandling { get; set; }
 
-        public OrderDto Order => OrderVisit != null ? OrderVisit.Order : null;
+        /// <summary>
+        /// 甄别记录
+        /// </summary>
+        public List<OrderScreenDto> OrderScreens { get; set; }
+
+		public OrderDto Order => OrderVisit != null ? OrderVisit.Order : null;
 
         /// <summary>
         /// 语音评价(话务评价)
@@ -564,15 +574,15 @@ namespace Hotline.Share.Dtos.Order
 
         public string OrgProcessingResultsText => !(OrgProcessingResults is null) ? OrgProcessingResults.Value : "";
 
-		/// <summary>
-		/// 不满意原因
-		/// </summary>
-		public List<Kv>? OrgNoSatisfiedReason { get; set; }
+        /// <summary>
+        /// 不满意原因
+        /// </summary>
+        public List<Kv>? OrgNoSatisfiedReason { get; set; }
 
         /// <summary>
         /// 不满意原因字符串
         /// </summary>
-        public string OrgNoSatisfiedReasonText =>  OrgNoSatisfiedReason != null ?  string.Join(',', OrgNoSatisfiedReason.Select(d=>d.Value)) : "";
+        public string OrgNoSatisfiedReasonText => OrgNoSatisfiedReason != null ? string.Join(',', OrgNoSatisfiedReason.Select(d => d.Value)) : "";
 
         /// <summary>
         /// 部门办件态度
@@ -603,7 +613,21 @@ namespace Hotline.Share.Dtos.Order
         /// 未解决备注
         /// </summary>
         public string? VolveConent { get; set; }
-    }
+
+        public string ScreenSendBackText => GetScreenSendBack();
+
+        public string GetScreenSendBack() {
+            if (OrderScreens != null && OrderScreens.Any())
+            {
+                if (OrderScreens.First().Status == EScreenStatus.SendBack && OrderScreens.First().SendBackApply)
+                {
+                    return "是";
+                }
+            }
+            return "否";
+        }
+
+	}
 
     public class DistributionVisitRspDto
     {
@@ -740,7 +764,7 @@ namespace Hotline.Share.Dtos.Order
         /// 回访内容
         /// </summary>
         public string? VisitContent { get; set; }
-      
+
     }
 
 

+ 5 - 0
src/Hotline.Share/Dtos/Order/OrderWaitedDto.cs

@@ -36,6 +36,11 @@ namespace Hotline.Share.Dtos.Order
         /// 是否紧急
         /// </summary>
         public bool? IsUrgent { get; set; }
+
+        /// <summary>
+        /// 区域
+        /// </summary>
+        public string? AreaCode { get; set; }
 	}
 
     /// <summary>

+ 216 - 96
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -55,7 +55,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 接办部门(√)
         /// </summary>
-        public string? OrgName { get; set; }
+        public string? OrgId { get; set; }
         //public List<string> OrgCodes { get; set; } = new();
 
         /// <summary>
@@ -69,12 +69,6 @@ namespace Hotline.Share.Dtos.Order
         public DateTime? CreationTimeStart { get; set; }
         public DateTime? CreationTimeEnd { get; set; }
 
-        /// <summary>
-        /// 紧急程度(√)
-        /// </summary>
-        public EEmergencyLevel? EmergencyLevel { get; set; }
-        //public List<EEmergencyLevel> EmergencyLevels { get; set; } = new();
-
         /// <summary>
         /// 来电号码(×)
         /// </summary>
@@ -460,128 +454,252 @@ namespace Hotline.Share.Dtos.Order
 
     public record ScreenListDto : PagedKeywordRequest
     {
-        /// <summary>
-        /// 甄别申请状态
-        /// </summary>
-        public EScreenStatus? Status { get; set; }
 
-        public DateTime? CreationTimeStart { get; set; }
-        public DateTime? CreationTimeEnd { get; set; }
-
-        public string? OrderId { get; set; }
+		/// <summary>
+		/// 0 全部  1 我的
+		/// </summary>
+		public int? DataScope { get; set; }
+
+		/// <summary>
+		/// 甄别申请状态选项卡
+		/// </summary>
+		public EScreenStatus? TabStatus { get; set; }
+
+		/// <summary>
+		/// 甄别申请状态
+		/// </summary>
+		public EScreenStatus? Status { get; set; }
+
+		/// <summary>
+		/// 编码
+		/// </summary>
+		public string? No { get; set; }
+
+		/// <summary>
+		/// 标题
+		/// </summary>
+		public string? Title { get; set; }
+
+		/// <summary>
+		/// 受理类型
+		/// </summary>
+		public string? AcceptType { get; set; }
+
+		/// <summary>
+		/// 热点类型
+		/// </summary>
+		public string? HotspotSpliceName { get; set; }
+
+		/// <summary>
+		/// 来源渠道(电话、网站、APP等)
+		/// </summary>
+		public string? SourceChannel { get; set; }
+
+		/// <summary>
+		/// 回访部门名称
+		/// </summary>
+		public string? VisitOrgName { get; set; }
+
+		/// <summary>
+		/// 甄别申请部门
+		/// </summary>
+		public string? CreatorOrgName { get; set; }
+
+		/// <summary>
+		/// 是否省工单
+		/// </summary>
+		public bool? IsProvince { get; set; }
 
         /// <summary>
-        /// 甄别查询来源  1 甄别待办  2 甄别列表
+        /// 申请人
         /// </summary>
-        public int source { get; set; }
+        public string? CreatorName { get; set; }
 
         /// <summary>
-        /// 标题
+        /// 甄别申请时间
         /// </summary>
-        public string? Title { get; set; }
+		public DateTime? CreationTimeStart { get; set; }
 
         /// <summary>
-        /// 编码
+        /// 甄别申请时间
         /// </summary>
-        public string? No { get; set; }
+		public DateTime? CreationTimeEnd { get; set; }
+
+        public string? OrderId { get; set; }
 
         /// <summary>
-        /// 甄别申请部门
+        /// 甄别查询来源  1 甄别待办  2 甄别列表
         /// </summary>
-        public string? CreatorOrgName { get; set; }
+        public int source { get; set; }
 
+        /// <summary>
+        /// 重提甄别
+        /// </summary>
+        public bool? IsSendBackApplyNum { get; set; }
+
+		//甄别列表
+		/// <summary>
+		/// 一级部门名称
+		/// </summary>
+		public string? OrgLevelOneName { get; set; }
+
+		/// <summary>
+		/// 接办部门
+		/// </summary>
+		public string? CurrentHandleOrgName { get; set; }
+
+		/// <summary>
+		/// 受理时间
+		/// </summary>
+		public DateTime? CreationTime { get; set; }
+
+		/// <summary>
+		/// 受理时间
+		/// </summary>
+		public DateTime? EndCreationTime { get; set; }
+
+		/// <summary>
+		/// 接办时间
+		/// </summary>
+		public DateTime? CurrentHandleTime { get; set; }
+
+		/// <summary>
+		/// 接办时间
+		/// </summary>
+		public DateTime? EndCurrentHandleTime { get; set; }
+
+		/// <summary>
+		/// 归档时间(暂为流程结束时间,因流程结束自动归档)
+		/// </summary>
+		public DateTime? FiledTime { get; set; }
+
+		/// <summary>
+		/// 归档时间(暂为流程结束时间,因流程结束自动归档)
+		/// </summary>
+		public DateTime? EndFiledTime { get; set; }
+
+		/// <summary>
+		/// 回访时间
+		/// </summary>
+		public DateTime? VisitTime { get; set; }
+
+		/// <summary>
+		/// 回访时间
+		/// </summary>
+		public DateTime? EndVisitTime { get; set; }
+
+		/// <summary>
+		/// 联系电话
+		/// </summary>
+		public string? Contact { get; set; }
+
+		/// <summary>
+		/// 来电电话
+		/// </summary>
+		public string? FromPhone { get; set; }
 	}
 
     public record MayScreenListDto : PagedKeywordRequest
     {
-        public DateTime? CreationTimeStart { get; set; }
-        public DateTime? CreationTimeEnd { get; set; }
-        public bool? IsHomePage { get; set; }
-
-        /// <summary>
-        /// 工单编号
-        /// </summary>
-        public string? No { get; set; }
-
-        /// <summary>
-        /// 是否省工单
-        /// </summary>
-        public bool? IsProvince { get; set; }
-
-        /// <summary>
-        /// 标题
-        /// </summary>
-        public string? Title { get; set; }
-
-        /// <summary>
-        /// 来源渠道(电话、网站、APP等)
-        /// </summary>
-        public string? SourceChannel { get; set; }
-
-        /// <summary>
-        /// 受理类型
-        /// </summary>
-        public string? AcceptType { get; set; }
+	    /// <summary>
+	    /// 甄别退回  0  全部  1 是  2 否
+	    /// </summary>
+	    public int? ScreenSendBack { get; set; }
+
+	    /// <summary>
+	    /// 工单编号
+	    /// </summary>
+	    public string? No { get; set; }
+
+	    /// <summary>
+	    /// 标题
+	    /// </summary>
+	    public string? Title { get; set; }
+
+	    /// <summary>
+	    /// 是否省工单
+	    /// </summary>
+	    public bool? IsProvince { get; set; }
+
+	    /// <summary>
+	    /// 受理类型
+	    /// </summary>
+	    public string? AcceptType { get; set; }
+
+	    /// <summary>
+	    /// 热点类型
+	    /// </summary>
+	    public string? HotspotSpliceName { get; set; }
+
+	    /// <summary>
+	    /// 来源渠道(电话、网站、APP等)
+	    /// </summary>
+	    public string? SourceChannel { get; set; }
+
+	    /// <summary>
+	    /// 一级部门名称
+	    /// </summary>
+	    public string? OrgLevelOneName { get; set; }
+
+	    /// <summary>
+	    /// 接办部门
+	    /// </summary>
+	    public string? CurrentHandleOrgName { get; set; }
+
+	    /// <summary>
+	    /// 回访部门名称
+	    /// </summary>
+	    public string? VisitOrgName { get; set; }
 
         /// <summary>
-        /// 会签类型
+        /// 受理时间
         /// </summary>
-        public ECounterSignType? CounterSignType { get; set; }
+        public DateTime? CreationTime { get; set; }
 
         /// <summary>
-        /// 一级部门名称
+        /// 受理时间
         /// </summary>
-        public string? OrgLevelOneName { get; set; }
+        public DateTime? EndCreationTime { get; set; }
 
-        /// <summary>
-        /// 实际办理节点名称(会签状态此字段保存最外层会签发起节点名称)
-        /// </summary>
-        public string? CurrentHandleOrgName { get; set; }
+		/// <summary>
+		/// 接办时间
+		/// </summary>
+		public DateTime? CurrentHandleTime { get; set; }
 
-        /// <summary>
-        /// 实际办理时间
-        /// </summary>
-        public DateTime? ActualHandleTime { get; set; }
+		/// <summary>
+		/// 接办时间
+		/// </summary>
+		public DateTime? EndCurrentHandleTime { get; set; }
 
-        /// <summary>
-        /// 实际办理时间
-        /// </summary>
-        public DateTime? EndActualHandleTime { get; set; }
+		/// <summary>
+		/// 归档时间(暂为流程结束时间,因流程结束自动归档)
+		/// </summary>
+		public DateTime? FiledTime { get; set; }
 
-        /// <summary>
-        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
-        /// </summary>
-        public DateTime? FiledTime { get; set; }
+		/// <summary>
+		/// 归档时间(暂为流程结束时间,因流程结束自动归档)
+		/// </summary>
+		public DateTime? EndFiledTime { get; set; }
 
-        /// <summary>
-        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
-        /// </summary>
-        public DateTime? EndFiledTime { get; set; }
+		/// <summary>
+		/// 回访时间
+		/// </summary>
+		public DateTime? VisitTime { get; set; }
 
-        /// <summary>
-        /// 受理时间
-        /// </summary>
-        public DateTime? CreationTime { get; set; }
-
-        /// <summary>
-        /// 受理时间
-        /// </summary>
-        public DateTime? EndCreationTime { get; set; }
-
-        /// <summary>
-        /// 回访时间
-        /// </summary>
-        public DateTime? VisitTime { get; set; }
+		/// <summary>
+		/// 回访时间
+		/// </summary>
+		public DateTime? EndVisitTime { get; set; }
 
-        /// <summary>
-        /// 回访时间
-        /// </summary>
-        public DateTime? EndVisitTime { get; set; }
 
+		public DateTime? CreationTimeStart { get; set; }
+        public DateTime? CreationTimeEnd { get; set; }
+        public bool? IsHomePage { get; set; }
+        
         /// <summary>
-        /// 回访部门名称
+        /// 会签类型
         /// </summary>
-        public string? VisitOrgName { get; set; }
+        public ECounterSignType? CounterSignType { get; set; }
 
         /// <summary>
         /// 部门办件结果
@@ -597,7 +715,9 @@ namespace Hotline.Share.Dtos.Order
         /// 不满意原因
         /// </summary>
         public string? OrgNoSatisfiedReason { get; set; }
-    }
+
+       
+	}
 
     public record UrgeListDto : PagedKeywordRequest
     {

+ 197 - 0
src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs

@@ -746,6 +746,203 @@ namespace Hotline.Share.Dtos.TrCallCenter
         #endregion
     }
 
+    public class TrCallDtoNew
+    {
+        /// <summary>
+        /// 可直接访问的通话录音地址
+        /// </summary>
+        public string? RecordingFileUrl { get; set; }
+        public string? RecordingBaseAddress { get; set; }
+        public string? RecordingAbsolutePath { get; set; }
+
+        /// <summary>
+        /// 呼叫方向
+        /// </summary>
+        public ECallDirection CallDirection { get; set; }
+
+        /// <summary>
+        /// 呼叫方向
+        /// </summary>
+        public string CallDirectionText => CallDirection.GetDescription();
+
+        /// <summary>
+        /// 挂断方
+        /// </summary>
+        public EEndBy? EndBy { get; set; }
+
+        /// <summary>
+        /// 挂断方
+        /// </summary>
+        public string EndByText => EndBy.GetDescription();
+
+
+        /// <summary>
+        /// 坐席侧通话流水,无坐席参与则为手机侧通话流水
+        /// </summary>
+        public string CallAccept { get; set; }
+        /// <summary>
+        /// 主叫
+        /// </summary>
+        public string Cpn { get; set; }
+        /// <summary>
+        /// 主叫名称
+        /// </summary>
+        public string CPNName { get; set; }
+        /// <summary>
+        /// 被叫
+        /// </summary>
+        public string Cdpn { get; set; }
+        /// <summary>
+        /// 分机号
+        /// </summary>
+        public string TelNo { get; set; }
+        /// <summary>
+        /// 用户ID
+        /// </summary>
+        public string UserId { get; set; }
+        /// <summary>
+        /// 用户名
+        /// </summary>
+        public string UserName { get; set; }
+        /// <summary>
+        /// 通话录音绝对路径
+        /// </summary>
+        public string? RecordingFileName { get; set; }
+        /// <summary>
+        /// 通话创建时间
+        /// </summary>
+        public DateTime CreatedTime { get; set; }
+        /// <summary>
+        /// 接通时间
+        /// </summary>
+        public DateTime? AnsweredTime { get; set; }
+        /// <summary>
+        /// 挂机时间
+        /// </summary>
+        public DateTime OverTime { get; set; }
+        /// <summary>
+        /// 线路号
+        /// </summary>
+        public string Gateway { get; set; }
+        /// <summary>
+        /// 呼出时自定义的内容
+        /// </summary>
+        public string? OtherStr { get; set; }
+        /// <summary>
+        /// 手机侧通话流水,无坐席参与则为空
+        /// </summary>
+        public string? OtherAccept { get; set; }
+        /// <summary>
+        /// 状态码,语音信箱:999/其他:16
+        /// </summary>
+        public string Status { get; set; }
+        /// <summary>
+        /// IVR开始时间
+        /// </summary>
+        public DateTime? BeginIvrTime { get; set; }
+        /// <summary>
+        /// IVR结束时间
+        /// </summary>
+        public DateTime? EndIvrTime { get; set; }
+        /// <summary>
+        /// 开始等待时间
+        /// </summary>
+        public DateTime? BeginQueueTime { get; set; }
+        /// <summary>
+        /// 结束等待时间
+        /// </summary>
+        public DateTime? EndQueueTime { get; set; }
+        /// <summary>
+        /// 开始振铃时间
+        /// </summary>
+        public DateTime? BeginRingTime { get; set; }
+        /// <summary>
+        /// 结束振铃时间
+        /// </summary>
+        public DateTime? EndRingTimg { get; set; }
+        /// <summary>
+        /// 队列ID
+        /// </summary>
+        public string? OlaQueue { get; set; }
+        /// <summary>
+        /// 批量外呼流水
+        /// </summary>
+        public string? BatchAccept { get; set; }
+        /// <summary>
+        /// IVR按键信息
+        /// </summary>
+        public string? IvrDtmf { get; set; }
+        /// <summary>
+        /// IVR按键对应动作,需解码
+        /// </summary>
+        public string? DtmfType { get; set; }
+
+        #region 自定义字段
+        /// <summary>
+        /// 通话时长(挂机时间-接通时间)
+        /// </summary>
+        public int Duration { get; set; }
+
+        /// <summary>
+        /// 振铃时长(振铃结束时间-振铃开始时间)
+        /// </summary>
+        public int RingTimes { get; set; }
+
+        /// <summary>
+        /// 排队时长(排队结束时间-排队开始时间)
+        /// </summary>
+        public int QueueTims { get; set; }
+
+        /// <summary>
+        /// 通话状态
+        /// </summary>
+        public EOnState OnState { get; set; }
+
+        /// <summary>
+        /// 通话状态
+        /// </summary>
+        public string OnStateText => OnState.GetDescription();
+
+
+        public ECallOrderType? CallOrderType { get; set; }
+
+        /// <summary>
+        /// 外部ID
+        /// </summary>
+        public string? ExternalId { get; set; }
+
+        /// <summary>
+        /// 归属地
+        /// </summary>
+        public string? MobileAreaName { get; set; }
+
+        /// <summary>
+        /// 运营商
+        /// </summary>
+        public string? OFlag { get; set; }
+
+        /// <summary>
+        /// 卡类型
+        /// </summary>
+        public string? OperatorName { get; set; }
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string  OrderId { get; set; }
+
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string OrderNo { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        public string OrderTitle { get; set; }
+        #endregion
+    }
+
 
     #endregion
 

+ 9 - 3
src/Hotline.Share/Enums/Order/EScreenStatus.cs

@@ -18,19 +18,19 @@ namespace Hotline.Share.Enums.Order
 		/// <summary>
 		/// 审批中
 		/// </summary>
-		[Description("审批中")]
+		[Description("甄别中")]
 		Approval = 1,
 
 		/// <summary>
 		/// 审批完成
 		/// </summary>
-		[Description("审批完成")]
+		[Description("甄别同意")]
 		End = 2,
 
 		/// <summary>
 		/// 审批拒绝
 		/// </summary>
-		[Description("审批拒绝")]
+		[Description("甄别不同意")]
 		Refuse = 3,
 
 		/// <summary>
@@ -38,5 +38,11 @@ namespace Hotline.Share.Enums.Order
 		/// </summary>
 		[Description("已办")]
 		MyHandle = 4,
+
+		/// <summary>
+		/// 退回
+		/// </summary>
+		[Description("甄别退回")]
+		SendBack = 5,
 	}
 }

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

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

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

@@ -100,6 +100,16 @@ namespace Hotline.Share.Mq
         /// </summary>
         public const string HotlineOrderProvinceZmhd = "hotline.order.province.zmhd";
 
+        /// <summary>
+        /// 应急管理局
+        /// </summary>
+        public const string HotlineOrderContingencyManagement = "hotline.order.contingency.management";
+
+        /// <summary>
+        /// 应急管理局推送回调
+        /// </summary>
+        public const string HotlineOrderContingencyManagementState = "hotline.order.contingency.management.state";
+
         #endregion
     }
 }

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

@@ -26,5 +26,10 @@
         /// 0:全部,1:中心,2:部门
         /// </summary>
         public int TypeCode { get; set; }
+
+        /// <summary>
+        /// 来电/信人身份0:全部 ,1:市民,2:企业
+        /// </summary>
+        public int? TypeId { get; set; }
     }
 }

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

@@ -250,6 +250,11 @@ namespace Hotline.Share.Requests
         /// 是否省来源
         /// </summary>
         public bool? IsProvince { get; set; }
+
+        /// <summary>
+        /// 来电/信人身份0:全部 ,1:市民,2:企业
+        /// </summary>
+        public int? TypeId { get; set; }
     }
 
     public class SelectOrderId

+ 27 - 14
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -16,6 +16,16 @@ public record PagedKeywordRequest : PagedRequest
     public DateTime? EndTime { get; set; }
 
     public string? Keyword { get; set; }
+
+    /// <summary>
+    /// 排序字段 
+    /// </summary>
+    public string? SortField { get; set; }
+
+    /// <summary>
+    /// 排序规则  0 升序  1 降序
+    /// </summary>
+    public int? SortRule { get; set; }
 }
 public record PagedKeywordSonRequest : PagedRequest
 {
@@ -37,6 +47,11 @@ public record PagedKeywordSonRequest : PagedRequest
     public int? TypeId { get; set; }
 
     public string? LineNum { get; set; }
+
+    /// <summary>
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
+    /// </summary>
+    public int? TypeCode { get; set; }
 }
 public record VisitAndHotspotPagedKeywordRequest : PagedKeywordRequest
 {
@@ -53,7 +68,7 @@ public record VisitAndHotspotPagedKeywordRequest : PagedKeywordRequest
 	/// <summary>
 	/// 1:办件结果 2:办件态度
 	/// </summary>
-	public int? TypeId { get; set; }
+	public int TypeId { get; set; }
 
 	/// <summary>
 	/// 标题名称
@@ -63,17 +78,10 @@ public record VisitAndHotspotPagedKeywordRequest : PagedKeywordRequest
 }
 public record ReportPagedRequest : PagedKeywordRequest
 {
-
     /// <summary>
-    /// 排序字段 
-    /// </summary>
-    public string SortField { get; set; }
-
-    /// <summary>
-    /// 排序规则  0 升序  1 降序
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
     /// </summary>
-    public int? SortRule { get; set; }
-
+    public int? TypeId { get; set; }
 }
 
 public record OrgDataListDetailRequest : PagedRequest
@@ -105,6 +113,11 @@ public record OrgDataListDetailRequest : PagedRequest
     /// 超期类型 1:系统中超期  2:申请延期超期
     /// </summary>
     public int ExpiredType { get; set; }
+
+    /// <summary>
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
+    /// </summary>
+    public int? TypeId { get; set; }
 }
 /// <summary>
 /// 部门超期全部数据
@@ -248,7 +261,7 @@ public record QuerySecondaryHandlingRequest : ReportPagedRequest
     /// <summary>
     ///  1  办件结果
     /// </summary>
-    public int TypeId { get; set; }
+    public int VisitTypeId { get; set; }
 
     public string? CDPN { get; set; }
 
@@ -381,17 +394,17 @@ public record OrgVisitDetailListReq: PagedKeywordRequest
     /// <summary>
     /// 回访部门
     /// </summary>
-    public List<string> OrgCodes { get; set; } = new();
+    public string OrgId { get; set; }
 
     /// <summary>
     /// 热点分类
     /// </summary>
-    public List<string> HotspotIds { get; set; } = new();
+    public string Hotspot { get; set; }
 
     /// <summary>
     /// 来源渠道(√)
     /// </summary>
-    public List<string> Channels { get; set; } = new();
+    public string Channel { get; set; }
 
     /// <summary>
     /// 受理时间(工单创建时间)(√)

+ 2 - 0
src/Hotline/Ai/Visit/IAiVisitService.cs

@@ -15,6 +15,8 @@ namespace Hotline.Ai.Visit
 
         Task<AiVisitQueryData> QueryAiVisitTask(string batchId,string taskId, CancellationToken cancellationToken);
 
+        Task<AiVisitQueryData> QueryAiVisitTaskEx(string batchId, string taskId, CancellationToken cancellationToken);
+
         Task<bool> ChangeStatusAsync(string batchUid, string status, CancellationToken cancellationToken);
     }
 }

+ 13 - 0
src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs

@@ -5,6 +5,19 @@ namespace Hotline.CallCenter.Calls
 {
     public interface ITrCallRecordRepository
     {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="beginDate"></param>
+        /// <param name="endDate"></param>
+        /// <param name="noConnectByeTimes"></param>
+        /// <param name="effectiveTimes"></param>
+        /// <param name="connectByeTimes"></param>
+        /// <param name="CallInOverConnRingTime"></param>
+        /// <param name="SeatChaoTime"></param>
+        /// <param name="Line"></param>
+        /// <returns></returns>
+        Task<List<QueryCallsDetailDto>> QueryCallsHourDetail(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int CallInOverConnRingTime, int SeatChaoTime, string? Line);
 
         Task<List<BiCallDto>?> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line);
         Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes,int connectByeTimes, string source);

+ 13 - 0
src/Hotline/ContingencyManagement/ContingencyManagementHotspot.cs

@@ -0,0 +1,13 @@
+using Hotline.Settings.Hotspots;
+using System.ComponentModel;
+
+namespace Hotline.ContingencyManagement
+{
+    /// <summary>
+    /// 宜宾应急管理局指定热点
+    /// </summary>
+    [Description("宜宾应急管理局指定热点")]
+    public class ContingencyManagementHotspot : Hotspot
+    {
+    }
+}

+ 204 - 0
src/Hotline/ContingencyManagement/ContingencyManagementOrders.cs

@@ -0,0 +1,204 @@
+
+using Hotline.Share.Dtos.File;
+using Hotline.Share.Enums.JudicialManagement;
+using Hotline.Share.Enums.Order;
+using SqlSugar;
+using System.ComponentModel;
+using XF.Domain.Repository;
+
+namespace Hotline.ContingencyManagement
+{
+    /// <summary>
+    /// 宜宾应急管理局工单数据
+    /// </summary>
+    [Description("宜宾应急管理局工单数据")]
+    public class ContingencyManagementOrders : PositionEntity
+    {
+        /// <summary>
+        /// 来源渠道(电话、网站、APP等)
+        /// </summary>
+        public string? SourceChannel { get; set; }
+
+        public string? SourceChannelCode { get; set; }
+
+        /// <summary>
+        /// 来电号码
+        /// </summary>
+        public string? FromPhone { get; set; }
+
+        /// <summary>
+        /// 转接号码(转接来源)
+        /// </summary>
+        public string? TransferPhone { get; set; }
+
+        /// <summary>
+        /// 来电/信人姓名
+        /// </summary>
+        public string? FromName { get; set; }
+
+        /// <summary>
+        /// 来电/信人性别
+        /// </summary>
+        public EGender FromGender { get; set; }
+
+        /// <summary>
+        /// 来电/信人身份
+        /// </summary>
+        public EIdentityType? IdentityType { get; set; }
+
+        /// <summary>
+        /// 联系电话
+        /// </summary>
+        [SugarColumn(ColumnDescription = "联系电话", IsNullable = true)]
+        public string? Contact { get; set; }
+
+        [SugarColumn(ColumnDescription = "联系电话脱敏", IsNullable = true)]
+        public string? ContactMask { get; set; }
+
+        /// <summary>
+        /// 受理类型
+        /// </summary>
+        public string? AcceptType { get; set; }
+
+        public string? AcceptTypeCode { get; set; }
+
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string? HotspotId { get; set; }
+
+        public string? HotspotName { get; set; }
+
+        public string? HotspotSpliceName { get; set; }
+
+        /// <summary>
+        /// 外部数据(为前端提供级联功能)
+        /// </summary>
+        public string? HotspotExternal { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        [SugarColumn(ColumnDataType = "json", IsJson = true)]
+        public List<FileDto>? Additions { get; set; } = new();
+
+        /// <summary>
+        /// 诉求内容
+        /// </summary>
+        [SugarColumn(ColumnDataType = "varchar(8000)")]
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 工单编码(20220101000001)
+        /// </summary>
+        public string? No { get; set; }
+
+        /// <summary>
+        /// 市民查询密码
+        /// </summary>
+        public string? Password { get; set; }
+
+        /// <summary>
+        /// 受理人id
+        /// </summary>
+        public string? AcceptorId { get; set; }
+
+        /// <summary>
+        /// 受理人名称
+        /// </summary>
+        public string? AcceptorName { get; set; }
+
+        /// <summary>
+        /// 受理人工号
+        /// </summary>
+        public string? AcceptorStaffNo { get; set; }
+
+        /// <summary>
+        /// 受理人部门编码
+        /// </summary>
+        public string? AcceptorOrgCode { get; set; }
+
+        /// <summary>
+        /// 受理人部门名称
+        /// </summary>
+        public string? AcceptorOrgName { get; set; }
+
+        [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
+        public List<FileJson>? FileJson { get; set; }
+
+        /// <summary>
+        /// 工单来源
+        /// </summary>
+        public EOrderSoure? OrderSoure { get; set; }
+
+        /// <summary>
+        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
+        /// </summary>
+        public DateTime? FiledTime { get; set; }
+
+        /// <summary>
+        /// 归档意见
+        /// </summary>
+        [SugarColumn(ColumnDataType = "varchar(8000)")]
+        public string? FileOpinion { get; set; }
+
+        /// <summary>
+        /// 实际办理时间
+        /// </summary>
+        public DateTime? ActualHandleTime { get; set; }
+
+        /// <summary>
+        /// 实际办理人id
+        /// </summary>
+        public string? ActualHandlerId { get; set; }
+
+        /// <summary>
+        /// 实际办理人名称
+        /// </summary>
+        public string? ActualHandlerName { get; set; }
+
+        /// <summary>
+        /// 实际办理部门名称
+        /// </summary>
+        public string? ActualHandleOrgName { get; set; }
+
+        /// <summary>
+        /// 实际办理部门编码
+        /// </summary>
+        public string? ActualHandleOrgCode { get; set; }
+
+        /// <summary>
+        /// 实际办理意见(办理中...or 最终办理意见)
+        /// </summary>
+        [SugarColumn(Length = 8000)]
+        public string ActualOpinion { get; set; } = "办理中...";
+
+        /// <summary>
+        /// 整理标题
+        /// </summary>
+        public string ArrangeTitle { get; set; }
+
+        /// <summary>
+        /// 整理内容
+        /// </summary>
+        [SugarColumn(ColumnDataType = "varchar(8000)")]
+        public string ArrangeContent { get; set; }
+
+        /// <summary>
+        /// 整理后办理意见
+        /// </summary>
+        [SugarColumn(Length = 8000)]
+        public string? ArrangementOpinion { get; set; }
+
+        /// <summary>
+        /// 推送状态 0:推送中,1:成功,2:失败
+        /// </summary>        
+        [SugarColumn(DefaultValue = "0")]
+        public string? PushState { get; set; }
+    }
+}

+ 48 - 2
src/Hotline/Orders/AiOrderVisitDetail.cs

@@ -1,4 +1,7 @@
-using Hotline.Share.Enums.Ai;
+using Hotline.Share.Dtos;
+using Hotline.Share.Enums.Ai;
+using Hotline.Share.Enums.Order;
+using Oracle.ManagedDataAccess.Types;
 using SqlSugar;
 using System;
 using System.Collections.Generic;
@@ -46,6 +49,10 @@ namespace Hotline.Orders
         /// </summary>
         public DateTime? AiVisitTime { get; set; }
 
+        /// <summary>
+        /// 最新外呼时间
+        /// </summary>
+        public DateTime? CallTime { get; set; }
 
         /// <summary>
         /// 是否成功
@@ -57,8 +64,47 @@ namespace Hotline.Orders
         /// 批此上传成功后任务ID
         /// </summary>
         public string? TaskUid { get; set; }
-       
 
+        /// <summary>
+        /// 话务员评价(话务评价)
+        /// </summary>
+        public ESeatEvaluate? AiSeatEvaluate { get; set; }
+
+        /// <summary>
+        /// 话务员不满意原因
+        /// </summary>
+        public string? AiSeatNoSatisfiedReason { get; set; }
+
+        /// <summary>
+        /// 是否联系
+        /// </summary>
+        public bool? AiIsContact { get; set; }
+
+        /// <summary>
+        /// 处理结果
+        /// </summary>
+        public bool? AiVolved { get; set; }
+
+        /// <summary>
+        /// 未处理内容
+        /// </summary>
+        public string? AiVolveConent { get; set; }
+
+        /// <summary>
+        /// 部门办件结果
+        /// </summary>
+        [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
+        public Kv? AiOrgProcessingResults { get; set; }
+
+        /// <summary>
+        /// 不满意原因
+        /// </summary>
+        public string? AiOrgNoSatisfiedReason { get; set; }
 
+        /// <summary>
+        /// 重呼次数
+        /// </summary>
+        [SugarColumn(DefaultValue = "0")]
+        public int CallTimes { get; set; }
     }
 }

+ 22 - 11
src/Hotline/Orders/Order.cs

@@ -142,6 +142,12 @@ namespace Hotline.Orders
 
         public string Title { get; set; }
 
+        /// <summary>
+        /// 工单标签(自贡)
+        /// </summary>
+        public string? OrderTag { get; set; }
+        public string? OrderTagCode { get; set; }
+
         #region 热点
 
         /// <summary>
@@ -283,7 +289,6 @@ namespace Hotline.Orders
         /// </summary>
         public string? ZhuanBanCode { get; set; }
 
-
         #endregion
 
         #region 流程信息
@@ -343,22 +348,22 @@ namespace Hotline.Orders
         public double? HandleDurationWorkday { get; set; }
 
         /// <summary>
-        /// 办结时长(秒) 办结时间-受理时间(工单创建时间)
+        /// 办结时长(秒)归档时间-受理时间(工单创建时间)
         /// </summary>
         public double? CreationTimeHandleDuration { get; set; }
 
         /// <summary>
-        /// 办结工作日时长(秒)办结时间-受理时间(工单创建时间)
+        /// 办结工作日时长(秒)归档时间-受理时间(工单创建时间)
         /// </summary>
         public double? CreationTimeHandleDurationWorkday { get; set; }
 
         /// <summary>
-        /// 办结时长(秒) 办结时间-派单时间(中心到部门时间)
+        /// 办结时长(秒) 归档时间-派单时间(中心到部门时间)
         /// </summary>
         public double? CenterToOrgHandleDuration { get; set; }
 
         /// <summary>
-        /// 办结工作日时长(秒)办结时间-派单时间(中心到部门时间)
+        /// 办结工作日时长(秒)归档时间-派单时间(中心到部门时间)
         /// </summary>
         public double? CenterToOrgHandleDurationWorkday { get; set; }
 
@@ -790,6 +795,12 @@ namespace Hotline.Orders
         [SugarColumn(DefaultValue = "f")]
         public bool IsSensitiveWorkOrders { get; set; }
 
+        /// <summary>
+        /// 24小时办结
+        /// </summary>
+        [SugarColumn(DefaultValue = "f")]
+        public bool Is24HoursComplete { get; set; }
+
         /// <summary>
         /// 部门是否解决
         /// </summary>
@@ -1096,28 +1107,28 @@ namespace Hotline.Orders
         }
 
         /// <summary>
-        ///  办结时长(秒) 办结时间-受理时间(工单创建时间)
+        ///  办结时长(秒) 归档时间-受理时间(工单创建时间)
         /// </summary>
         public void SetCreationTimeHandleDurationWorkday()
         {
-            if (!ActualHandleTime.HasValue)
+            if (!FiledTime.HasValue)
                 CreationTimeHandleDuration = 0;
             else
             {
-                var count = Math.Round((ActualHandleTime - CreationTime).Value.TotalSeconds);
+                var count = Math.Round((FiledTime - CreationTime).Value.TotalSeconds);
                 CreationTimeHandleDuration = count <= 0 ? 1 : count;
             }
 
         }
 
         /// <summary>
-        ///  办结时长(秒) 办结时间-派单时间(工单创建时间)
+        ///  办结时长(秒) 归档时间-派单时间(工单创建时间)
         /// </summary>
         public void SetCenterToOrgHandleDurationWorkday()
         {
-            if (ActualHandleTime.HasValue && CenterToOrgTime.HasValue)
+            if (FiledTime.HasValue && CenterToOrgTime.HasValue)
             {
-                var count = Math.Round((ActualHandleTime - CenterToOrgTime).Value.TotalSeconds);
+                var count = Math.Round((FiledTime - CenterToOrgTime).Value.TotalSeconds);
                 CenterToOrgHandleDuration = count <= 0 ? 1 : count;
             }
             else

+ 41 - 6
src/Hotline/Orders/OrderScreen.cs

@@ -54,9 +54,15 @@ namespace Hotline.Orders
         public Order Order { get; set; }
 
         /// <summary>
-        /// 甄别申请类型id
+        /// 回访
         /// </summary>
-        [SugarColumn(ColumnDescription = "甄别申请类型id")]
+        [Navigate(NavigateType.OneToMany, nameof(OrderScreenDetail.ScreenId), nameof(Id))]
+        public List<OrderScreenDetail> ScreenDetails { get; set; }
+
+		/// <summary>
+		/// 甄别申请类型id
+		/// </summary>
+		[SugarColumn(ColumnDescription = "甄别申请类型id")]
         public string? TypeDicId { get; set; }
 
         /// <summary>
@@ -115,10 +121,10 @@ namespace Hotline.Orders
         [SugarColumn(ColumnDescription = "甄别申请状态")]
         public EScreenStatus? Status { get; set; }
 
-        /// <summary>
-        /// 业务流程ID
-        /// </summary>
-        [SugarColumn(ColumnDescription = "业务流程ID")]
+		/// <summary>
+		/// 业务流程ID
+		/// </summary>
+		[SugarColumn(ColumnDescription = "业务流程ID")]
         public string? WorkflowId { get; set; }
 
         [Navigate(NavigateType.OneToOne, nameof(WorkflowId))]
@@ -134,5 +140,34 @@ namespace Hotline.Orders
 		[SugarColumn(ColumnDescription = "甄别耗时")]
 		public decimal? TimeConsuming { get; set; }
 
+        /// <summary>
+        /// 甄别退回次数
+        /// </summary>
+		[SugarColumn(DefaultValue = "0")]
+		public int SendBackNum { get; set; }
+
+        /// <summary>
+        /// 甄别退回到申请人
+        /// </summary>
+		[SugarColumn(DefaultValue = "f")]
+		public bool SendBackApply { get; set; }
+
+        /// <summary>
+        /// 甄别重提申请次数
+        /// </summary>
+		[SugarColumn(DefaultValue = "0")]
+		public int SendBackApplyNum { get; set; }
+
+        /// <summary>
+        /// 甄别退回时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "甄别退回时间")]
+        public DateTime? SendBackTime { get; set; }
+
+        /// <summary>
+        /// 甄别审批时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "甄别审批时间")]
+        public DateTime? NewestAuditTime { get; set; }
 	}
 }

+ 65 - 0
src/Hotline/Orders/OrderScreenDetail.cs

@@ -0,0 +1,65 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+	public class OrderScreenDetail : FullStateEntity
+	{
+		/// <summary>
+		/// 甄别Id
+		/// </summary>
+		[SugarColumn(ColumnDescription = "甄别Id")]
+		public string ScreenId { get; set; }
+
+		/// <summary>
+		/// 审批人
+		/// </summary>
+		[SugarColumn(ColumnDescription = "审批人")]
+		public string? AuditUserName { get; set; }
+
+		/// <summary>
+		/// 审批人
+		/// </summary>
+		[SugarColumn(ColumnDescription = "审批人id")]
+		public string? AuditUserId { get; set; }
+
+		/// <summary>
+		/// 审批机构ID
+		/// </summary>
+		[SugarColumn(ColumnDescription = "审批机构ID")]
+		public string? AuditOrgId { get; set; }
+
+		/// <summary>
+		/// 审批机构
+		/// </summary>
+		[SugarColumn(ColumnDescription = "审批机构")]
+		public string? AuditOrgName { get; set; }
+
+		/// <summary>
+		/// 审批时间
+		/// </summary>
+		[SugarColumn(ColumnDescription = "审批时间")]
+		public DateTime? AuditTime { get; set; }
+
+		/// <summary>
+		/// 审批类型   1 审批  2 退回
+		/// </summary>
+		[SugarColumn(ColumnDescription = "审批类型   1 审批  2 退回")]
+		public int AuditType { get; set; }
+
+		public void Audit(string userId, string userName, string userOrgId, string userOrgName,int auditType) {
+			AuditUserId = userId;
+			AuditUserName = userName;
+			AuditOrgId = userOrgId;
+			AuditOrgName = userOrgName;
+			AuditTime = DateTime.Now;
+			AuditType = auditType;
+		}
+	}
+
+}

+ 5 - 0
src/Hotline/Orders/OrderVisit.cs

@@ -158,6 +158,11 @@ public class OrderVisit : CreationEntity
     /// </summary>
     public DateTime? JudgeTime { get; set; }
 
+    /// <summary>
+    /// 是否有效智能回访
+    /// </summary>
+    public bool? IsEffectiveAiVisit { get; set; }
+
     public void AiVisitTime()
     {
         LastVisitTime = DateTime.Now;

+ 6 - 0
src/Hotline/Orders/OrderVisitDetail.cs

@@ -24,6 +24,12 @@ namespace Hotline.Orders
         /// </summary>
         [Navigate(NavigateType.OneToOne, nameof(Id),nameof(OrderSecondaryHandling.VisitDetailId))]
         public OrderSecondaryHandling SecondaryHandling { get; set; }
+
+        /// <summary>
+        /// 甄别记录
+        /// </summary>
+        [Navigate(NavigateType.OneToMany,  nameof(OrderScreen.VisitDetailId), nameof(Id))]
+        public List<OrderScreen> OrderScreens { get; set; }
 		/// <summary>
 		/// 语音评价(话务评价)
 		/// </summary>

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

@@ -42,6 +42,11 @@ namespace Hotline.Settings
         /// </summary>
         public const string WorkTime = "WorkTime";
 
+        /// <summary>
+        /// 部门工作日工作时间(报表用)
+        /// </summary>
+        public const string WorkTimeOrg = "WorkTimeOrg";
+
         /// <summary>
         /// 工单延期申请次数
         /// </summary>
@@ -365,5 +370,9 @@ namespace Hotline.Settings
         /// </summary>
         public const string SeatChaoTime = "SeatChaoTime";
 
+        /// <summary>
+        /// 智能语音URL头
+        /// </summary>
+        public const string AiVisitVoiceBaseUrl = "AiVisitVoiceBaseUrl";
     }
 }

+ 10 - 0
src/Hotline/Settings/SysDicTypeConsts.cs

@@ -229,4 +229,14 @@ public class SysDicTypeConsts
 	/// 通话转接分类
 	/// </summary>
 	public const string CallForwardingType = "CallForwardingType";
+
+    /// <summary>
+    /// 工单标签
+    /// </summary>
+	public const string OrderTag = "OrderTag";
+
+    /// <summary>
+    /// 重点关注事件
+    /// </summary>
+	public const string FocusOnEvent = "FocusOnEvent";
 }

+ 11 - 1
src/Hotline/Settings/TimeLimits/ITimeLimitDomainService.cs

@@ -69,13 +69,23 @@ namespace Hotline.Settings.TimeLimits
 
 
         /// <summary>
-        /// 
+        /// 计算工作时间分钟数(已改返回秒)
         /// </summary>
         /// <param name="beginTime"></param>
         /// <param name="endTime"></param>
         /// <returns></returns>
         int CalcWorkTime(DateTime beginTime, DateTime endTime, bool isCenter);
 
+        /// <summary>
+        /// 计算工作时间分钟数(已改返回秒)
+        /// </summary>
+        /// <param name="beginTime"></param>
+        /// <param name="endTime"></param>
+        /// <param name="isCenter"></param>
+        /// <returns></returns>
+        int CalcWorkTimeEx(DateTime beginTime, DateTime endTime, bool isCenter);
+
+
         /// <summary>
         /// 计算时间间隔
         /// </summary>

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

@@ -223,7 +223,7 @@ namespace Hotline.Settings.TimeLimits
 
 
 		/// <summary>
-		/// 计算工作时间分钟数
+		/// 计算工作时间分钟数(已改返回秒)
 		/// </summary>
 		/// <param name="beginTime"></param>
 		/// <param name="endTime"></param>
@@ -411,6 +411,236 @@ namespace Hotline.Settings.TimeLimits
         }
 
 
+        /// <summary>
+		/// 计算工作时间分钟数(已改返回秒)
+		/// </summary>
+		/// <param name="beginTime"></param>
+		/// <param name="endTime"></param>
+		/// <param name="isCenter"></param>
+		/// <returns></returns>
+		public int CalcWorkTimeEx(DateTime beginTime, DateTime endTime, bool isCenter)
+        {
+            if (isCenter)
+            {
+                //如果是中心,采用中心计算方式
+                //计算时间差
+                TimeSpan minuteSpan = new TimeSpan(endTime.Ticks - beginTime.Ticks);
+                //总时差分钟数
+                int minutes = (int)minuteSpan.TotalMinutes;
+
+
+                //计算开始时间是否计算在工作时间内
+                if (!IsWorkDay(beginTime))
+                {
+                    var newBeginTime = beginTime.AddDays(1).Date;
+                    TimeSpan beginTimeMinuteSpan = new TimeSpan(newBeginTime.Ticks - beginTime.Ticks);
+                    int beginTimeMinute = (int)beginTimeMinuteSpan.TotalMinutes;
+                    minutes = minutes - beginTimeMinute;
+                }
+
+
+                //计算结束时间是否计算在工作时间内
+                if (!IsWorkDay(endTime))
+                {
+                    var newEndTime = endTime.Date;
+                    TimeSpan endTimeMinuteSpan = new TimeSpan(endTime.Ticks - newEndTime.Ticks);
+                    int endTimeMinute = (int)endTimeMinuteSpan.TotalMinutes;
+                    minutes = minutes - endTimeMinute;
+                }
+
+                //计算整天时间是否在工作时间内
+                int days = minuteSpan.Days;
+                for (int i = 0; i < days; i++)
+                {
+                    var newDay = beginTime.AddDays(i + 1);
+                    if (newDay.Date == endTime.Date)
+                    {
+                        continue;
+                    }
+
+                    if (!IsWorkDay(beginTime.AddDays(i + 1)))
+                    {
+                        minutes = minutes - 1440;
+                    }
+                }
+                return minutes == 0 ? 1 : minutes * 60;
+            }
+            else
+            {
+                //如果不是中心(则是部门计算方式)
+                //
+                var workTime = _systemSettingRepository.Get(x => x.Code == SettingConstants.WorkTimeOrg);
+                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");
+                    DateTime MornWorkBeginTime = DateTime.Parse(beginTime.ToShortDateString() + " " + workTime.SettingValue[0] + ":00");
+                    DateTime MornWorkEndTime = DateTime.Parse(beginTime.ToShortDateString() + " " + workTime.SettingValue[1] + ":00");
+                    DateTime AfterWorkBeginTime = DateTime.Parse(beginTime.ToShortDateString() + " " + workTime.SettingValue[2] + ":00");
+                    DateTime AfterWorkEndTime = DateTime.Parse(beginTime.ToShortDateString() + " " + workTime.SettingValue[3] + ":00");
+
+                    //处理开始时间
+                    if (beginTime.Date == MornWorkBeginTime.Date && beginTime < MornWorkBeginTime)
+                    {
+                        beginTime = MornWorkBeginTime;
+                    }
+                    else if(beginTime.Date == MornWorkBeginTime.Date && beginTime > MornWorkEndTime && beginTime< AfterWorkBeginTime)
+                    {
+                        beginTime = AfterWorkBeginTime;
+                    }
+                    else
+                    {
+                        if (beginTime > AfterWorkEndTime)
+                        {
+                            beginTime = MornWorkBeginTime.AddDays(1);
+                        }
+                    }
+                    if (beginTime >= endTime)
+                    {
+                        return 1;
+                    }
+
+                    if (endTime.Date == AfterWorkEndTime.Date && endTime < MornWorkBeginTime)
+                    {
+                        endTime = MornWorkBeginTime;
+                    }
+                    else if(endTime.Date == AfterWorkEndTime.Date && endTime> MornWorkEndTime && endTime< AfterWorkBeginTime)
+                    {
+                        endTime = MornWorkEndTime;
+                    }
+                    else
+                    {
+                        if (endTime > AfterWorkEndTime && endTime < MornWorkBeginTime.AddDays(1))
+                        {
+                            endTime = AfterWorkEndTime;//MornWorkBeginTime.AddDays(1);
+                        }
+                    }
+
+                    while (true)
+                    {
+                        if (!IsWorkDay(endTime))
+                        {
+                            endTime = DateTime.Parse(endTime.AddDays(1).ToShortDateString() + " " + workTime.SettingValue[0] + ":00");
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+
+                    //计算午休时差
+                    var restMinutes = 0;
+                    TimeSpan restSp = new TimeSpan(AfterWorkBeginTime.Ticks - MornWorkEndTime.Ticks);
+                    restMinutes = (int)restSp.TotalMinutes;
+
+
+                    int minutes = 0;
+                    int i = 0;
+                    while (true)
+                    {
+                        i++;
+                        //如果是工作日
+                        if (IsWorkDay(beginTime))
+                        {
+                            //最后一天
+                            if (beginTime.Date == endTime.Date)
+                            {
+                                if (endTime > AfterWorkEndTime)
+                                {
+                                    if (i != 1)
+                                    {
+                                        TimeSpan sp = new TimeSpan(AfterWorkEndTime.Ticks - MornWorkBeginTime.Ticks);
+                                        minutes += (int)sp.TotalMinutes- restMinutes;
+                                    }
+                                    //最后一天就是当天
+                                    else
+                                    {
+                                        TimeSpan sp = new TimeSpan(AfterWorkEndTime.Ticks - beginTime.Ticks);
+                                        minutes += (int)sp.TotalMinutes;
+                                        if (beginTime>MornWorkEndTime)
+                                        {
+                                            minutes = minutes - restMinutes;
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    if (i != 1)
+                                    {
+                                        TimeSpan sp = new TimeSpan(endTime.Ticks - MornWorkBeginTime.Ticks);
+                                        minutes += (int)sp.TotalMinutes;
+                                        if (endTime>AfterWorkBeginTime)
+                                        {
+                                            minutes = minutes - restMinutes;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        TimeSpan sp = new TimeSpan(endTime.Ticks - beginTime.Ticks);
+                                        minutes += (int)sp.TotalMinutes;
+                                        if (endTime> AfterWorkBeginTime && beginTime< MornWorkEndTime )
+                                        {
+                                            minutes = minutes - restMinutes;
+                                        }
+                                    }
+                                }
+                                return minutes == 0 ? 1 : minutes * 60;
+                            }
+                            //如果不是当天完成
+                            else
+                            {
+                                if (i == 1)
+                                {
+                                    TimeSpan sp = new TimeSpan(AfterWorkEndTime.Ticks - beginTime.Ticks);
+                                    minutes += (int)sp.TotalMinutes;
+                                    if (beginTime>MornWorkEndTime)
+                                    {
+                                        minutes = minutes - restMinutes;
+                                    }
+                                }
+                                else
+                                {
+                                    if (endTime.Date == AfterWorkEndTime.Date)
+                                    {
+                                        if (endTime > AfterWorkEndTime)
+                                        {
+                                            TimeSpan sp = new TimeSpan(AfterWorkEndTime.Ticks - MornWorkBeginTime.Ticks);
+                                            minutes += (int)sp.TotalMinutes - restMinutes;
+                                        }
+                                        else
+                                        {
+                                            TimeSpan sp = new TimeSpan(endTime.Ticks - MornWorkBeginTime.Ticks);
+                                            minutes += (int)sp.TotalMinutes;
+                                            if (endTime> AfterWorkBeginTime)
+                                            {
+                                                minutes = minutes - restMinutes;
+                                            }
+                                        }
+                                        return minutes == 0 ? 1 : minutes * 60;
+                                    }
+                                    else
+                                    {
+                                        TimeSpan sp = new TimeSpan(AfterWorkEndTime.Ticks - MornWorkBeginTime.Ticks);
+                                        minutes += (int)sp.TotalMinutes-restMinutes;
+                                    }
+                                }
+                            }
+                        }
+
+                        beginTime = beginTime.AddDays(1);
+                        AfterWorkEndTime = AfterWorkEndTime.AddDays(1);
+                        MornWorkBeginTime = MornWorkBeginTime.AddDays(1);
+                        MornWorkEndTime = MornWorkEndTime.AddDays(1);
+                        AfterWorkBeginTime = AfterWorkBeginTime.AddDays(1);
+                    }
+                }
+                return 0;
+            }
+        }
+
+
+
+
         /// <summary>
         /// 计算工作日
         /// </summary>

+ 61 - 4
src/Hotline/dataview.md

@@ -6,6 +6,11 @@ CASE "ordertemp"."Status"
 	WHEN 400 THEN '已发布'
 	WHEN 300 THEN '已归档'
 	WHEN 200 THEN '会签中'
+	WHEN 105 THEN '退回审批中'
+	WHEN 104 THEN '特提审批中'
+	WHEN 103 THEN '移交信件'
+	WHEN 102 THEN '退回信件'
+	WHEN 101 THEN '特提信件'
 	WHEN 100 THEN '办理中'
 	WHEN 9 THEN '退回省平台'
 	WHEN 2 THEN '特提待受理'
@@ -17,6 +22,7 @@ CASE 	WHEN "Status">=300 and "ExpiredTime">"FiledTime" THEN '正常'
 		  WHEN "Status">=300 AND "ExpiredTime"<"FiledTime" THEN '超期'
 			WHEN "Status"<300 AND "ExpiredTime"> now() AND now()> "NearlyExpiredTime" THEN '即将超期'
 			WHEN "Status"<300 AND "ExpiredTime">now() AND now()< "NearlyExpiredTime" THEN '正常'
+		  WHEN "Status"<300 AND "ExpiredTime"<now() THEN '超期'
 	ELSE '未知'
 END AS "IsOverExpiredTime",
 "SourceChannel" AS "Source" , 
@@ -82,7 +88,7 @@ END AS "FromGender" ,
 "Content" AS "Content" , 
 "ActualOpinion" AS "ActualOpinion" ,
 "FileOpinion" AS "FileOpinion" ,
-"Id" AS "SugarNav_Id" FROM "order" ordertemp  WHERE (( "CreationTime" >= '2024-03-29' ) AND ( "CreationTime" < '2024-07-3' ))  AND ( "IsDeleted" = FALSE )ORDER BY "CreationTime" ASC) aaa
+"Id" AS "SugarNav_Id" FROM "order" ordertemp  WHERE (( "CreationTime" >= '2024-07-17' ) AND ( "CreationTime" < '2024-07-24' ))  AND ( "IsDeleted" = FALSE )ORDER BY "CreationTime" ASC) aaa
 left join 
 (select DISTINCT CASE visitdetailtemp."SeatEvaluate"
 	WHEN 0 THEN '默认满意'
@@ -96,8 +102,7 @@ left join
 END AS "SeatVisitResult",visittemp."OrderId" as "OrderId"
  from order_visit visittemp
 left join order_visit_detail visitdetailtemp on visittemp."Id"= visitdetailtemp."VisitId"  
-where visittemp."CreationTime">='2024-03-29' and visitdetailtemp."VisitTarget"=10 AND visittemp."VisitState"=30 ) bbb on aaa."SugarNav_Id"=bbb."OrderId";
-
+where visittemp."CreationTime">='2024-07-17' and visitdetailtemp."VisitTarget"=10 AND visittemp."VisitState"=30 ) bbb on aaa."SugarNav_Id"=bbb."OrderId";
 
 
 ### 超期件查询
@@ -186,4 +191,56 @@ CASE "DelayState"
 END AS DelayState 
  from order_delay delaytemp
 left join "order" ordertemp on delaytemp."OrderId"= ordertemp."Id"
-where ordertemp."CreationTime">='2024-06-01' and ordertemp."CreationTime"<'2024-07-01' and delaytemp."DelayState"<>3
+where ordertemp."CreationTime">='2024-06-01' and ordertemp."CreationTime"<'2024-07-01' and delaytemp."DelayState"<>3
+
+
+### 智能回访任务统计
+select 
+cc."No" as "No",
+cc."Title" as "Title",
+CASE aa."AiOrderVisitState"
+	WHEN 1 THEN '待执行'
+	WHEN 2 THEN '暂停中'
+	WHEN 3 THEN '执行中'
+	WHEN 4 THEN '失效'
+	WHEN 5 THEN '呼叫失败'
+	WHEN 6 THEN '已结束'
+	ELSE
+		'未知'
+END AS "AiOrderVisitState",
+CASE aa."IsSuccess"
+	WHEN true THEN
+		'成功'
+	ELSE
+		'失败'
+END AS "IsSuccess",
+aa."OuterNo" as "OuterNo",
+cc."FromName" as "FromName",
+CASE cc."FromGender"
+		WHEN 0 THEN '女士'
+	WHEN 1 THEN '先生'
+	ELSE '未知'
+END AS "FromGender",
+cc."StartTime" as "StartTime",
+cc."FiledTime" as "FiledTime",
+(select 
+CASE qq."SeatEvaluate"
+	WHEN 0 THEN	'默认满意'
+	WHEN 2 THEN '不满意'
+	WHEN 4 THEN '满意'
+	WHEN 5 THEN '非常满意'
+	WHEN 6 THEN '未接通'
+	WHEN 7 THEN '未做评价'
+	ELSE
+		'未知'
+END AS SeatEvaluate
+ from order_visit_detail qq where qq."VisitId"= aa."OrderVisitId" and qq."VisitTarget"=10 and qq."CreationTime">'2024-06-01' and qq."CreationTime"<'2024-07-24' LIMIT 1)  AS SeatEvaluate,
+(
+select ww."OrgProcessingResults"::JSON->>'Value'  from order_visit_detail ww  WHERE ww."VisitId" = aa."OrderVisitId" AND ww."VisitTarget"=20 and ww."CreationTime">'2024-06-01' and ww."CreationTime"<'2024-07-24' LIMIT 1) AS OrgProcessingResults,
+(select ee."IsContact"  from order_visit_detail ee  WHERE ee."VisitId" = aa."OrderVisitId" AND ee."VisitTarget"=20 and ee."CreationTime">'2024-06-01' and ee."CreationTime"<'2024-07-24' LIMIT 1) as "IsContact",
+(select rr."Volved"  from order_visit_detail rr  WHERE rr."VisitId" = aa."OrderVisitId" AND rr."VisitTarget"=20 and rr."CreationTime">'2024-06-01' and rr."CreationTime"<'2024-07-24' LIMIT 1) as "IsContact"
+ from ai_order_visit_detail aa
+left join order_visit bb on aa."OrderVisitId"=bb."Id"
+left join "order" cc on bb."OrderId"=cc."Id"
+--left join order_visit_detail dd on bb."Id"=dd."VisitId"
+where aa."CreationTime" >'2024-07-01' --and dd."VisitTarget"=20