Quellcode durchsuchen

Merge branch 'dev' of http://110.188.24.182:10023/Fengwo/hotline into dev

田爽 vor 9 Monaten
Ursprung
Commit
9e3b9f74d1
55 geänderte Dateien mit 2483 neuen und 964 gelöschten Zeilen
  1. 2 2
      src/Hotline.Api/Controllers/AiController.cs
  2. 254 5
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  3. 203 165
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  4. 9 9
      src/Hotline.Api/Controllers/Bigscreen/JudicialManagementScreenController.cs
  5. 1 1
      src/Hotline.Api/Controllers/EnforcementOrderController.cs
  6. 4 2
      src/Hotline.Api/Controllers/JudicialManagementOrdersController.cs
  7. 5 2
      src/Hotline.Api/Controllers/KnowledgeController.cs
  8. 150 144
      src/Hotline.Api/Controllers/OrderController.cs
  9. 84 3
      src/Hotline.Api/Controllers/ProvinceStatisticsController.cs
  10. 144 103
      src/Hotline.Api/Controllers/TestController.cs
  11. 4 4
      src/Hotline.Api/Controllers/WorkflowController.cs
  12. 5 0
      src/Hotline.Application/CallCenter/TianRunCallApplication.cs
  13. 2 2
      src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs
  14. 39 4
      src/Hotline.Application/Handlers/FlowEngine/WorkflowRecallHandler.cs
  15. 8 7
      src/Hotline.Application/JudicialManagement/EnforcementApplication.cs
  16. 5 0
      src/Hotline.Application/Mappers/CallMapperConfigs.cs
  17. 179 115
      src/Hotline.Application/Orders/OrderApplication.cs
  18. 1 0
      src/Hotline.Application/Orders/OrderSendBackAuditApplication.cs
  19. 97 0
      src/Hotline.Application/StatisticalReport/CallReportApplication.cs
  20. 24 0
      src/Hotline.Application/StatisticalReport/ICallReportApplication.cs
  21. 3 3
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  22. 25 18
      src/Hotline.Application/Subscribers/DatasharingSubscriber.cs
  23. 69 9
      src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs
  24. 1 1
      src/Hotline.Repository.SqlSugar/File/FileRepository.cs
  25. 134 117
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  26. 2 2
      src/Hotline.Share/Dtos/Ai/AiDto.cs
  27. 3 3
      src/Hotline.Share/Dtos/Bi/BiOrderDto.cs
  28. 5 0
      src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs
  29. 128 0
      src/Hotline.Share/Dtos/CallCenter/QueryCallsDetailDto.cs
  30. 5 0
      src/Hotline.Share/Dtos/File/FileDto.cs
  31. 4 4
      src/Hotline.Share/Dtos/FlowEngine/Workflow/QueryWorkflowCountersignDto.cs
  32. 5 0
      src/Hotline.Share/Dtos/JudicialManagement/JudicialManagementAddOrderDto.cs
  33. 12 2
      src/Hotline.Share/Dtos/Order/OrderBiDto.cs
  34. 39 37
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  35. 5 0
      src/Hotline.Share/Dtos/Order/OrderSpecialDto.cs
  36. 13 13
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  37. 18 13
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  38. 42 1
      src/Hotline.Share/Dtos/ProvinceStatistics/ProvinceSendBackListDto.cs
  39. 56 0
      src/Hotline.Share/Dtos/ProvinceStatistics/QueryProvinceSendBackDto.cs
  40. 197 0
      src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs
  41. 1 1
      src/Hotline.Share/Enums/FlowEngine/EWorkflowTraceType.cs
  42. 1 1
      src/Hotline.Share/Enums/Order/ESendBackAuditState.cs
  43. 1 1
      src/Hotline.Share/Hotline.Share.csproj
  44. 9 9
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  45. 13 0
      src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs
  46. 5 8
      src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs
  47. 1 1
      src/Hotline/FlowEngine/Workflows/Workflow.cs
  48. 81 22
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  49. 0 4
      src/Hotline/Hotline.csproj
  50. 10 15
      src/Hotline/Orders/Order.cs
  51. 5 0
      src/Hotline/Orders/OrderSpecial.cs
  52. 123 109
      src/Hotline/Orders/OrderSupervise.cs
  53. 5 0
      src/Hotline/Settings/SettingConstants.cs
  54. 11 1
      src/Hotline/Settings/TimeLimits/ITimeLimitDomainService.cs
  55. 231 1
      src/Hotline/Settings/TimeLimits/TimeLimitDomainService.cs

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

@@ -1002,8 +1002,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>
     /// 坐席话务统计分析

+ 203 - 165
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -2014,27 +2014,32 @@ namespace Hotline.Api.Controllers.Bi
 
             var (total, items) = await _orderRepository.Queryable()
            .Includes(x => x.OrderScreens)
-           .Where(p => data.Contains(p.Id))
-           .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!)) //标题
-           .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo.Contains(dto.ProvinceNo)) //省本地编号
-           .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No)) //工单编码
-           .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
-           .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
-           .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
-           .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!)) //转接号码
-           .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
-           .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) //受理时间开始
-           .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-           .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
-                                                                                                     //  .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone.Contains(dto.FromPhone)) //来电号码
-           .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact.Contains(dto.PhoneNo!)) //联系电话
-           .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
-           .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
-           .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
-           .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
-           .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
-           .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName.Contains(dto.ActualHandlerName)) //接办人
+            .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!)) //标题
+            .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo == dto.ProvinceNo) //省本地编号
+            .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) //工单编码
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType)//受理类型
+            //.WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
+            //.WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
+            //.WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
+            .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone == dto.TransferPhone!) //转接号码
+                                                                                                           //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
+                                                                                                           //.WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
+           .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.CurrentHandleOrgId == dto.OrgId)//接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName == dto.NameOrNo! || d.AcceptorStaffNo == dto.NameOrNo!) //受理人/坐席
+            .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
+            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
+            //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
+            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone == dto.FromPhone) //来电号码
+            .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact == dto.PhoneNo!) //联系电话
+            .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
+            .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
+            .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
+            //.WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
+            .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)//工单状态
+            //.WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName == dto.ActualHandlerName) //接办人
             .WhereIF(dto.IsScreen == true, d => d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //有甄别
             .WhereIF(dto.IsScreen == false, d => !d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //无甄别
             .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepCode), d => d.ActualHandleStepCode == dto.CurrentStepCode) //当前办理节点
@@ -2043,8 +2048,9 @@ namespace Hotline.Api.Controllers.Bi
             .WhereIF(dto.IsOverTime == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //是 超期
             .WhereIF(dto.IsOverTime == false, d => (d.ExpiredTime > DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime > d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //否 超期
             .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
-            .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName.Contains(dto.FromName)) //来电人姓名
-            .WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
+            .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName == dto.FromName) //来电人姓名
+            //.WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)//区域
             .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, x => x.IsProvince == true)
             .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, x => x.IsProvince == false)
            .OrderByDescending(d => d.CreationTime)
@@ -2075,9 +2081,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,
@@ -2203,10 +2209,6 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("reTransact_detail")]
         public async Task<PagedDto<OrderSpecialDetailDto>> OrderReTransactDetail([FromQuery] QueryOrderReTransactDetailRequest dto)
         {
-            if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
-                throw UserFriendlyException.SameMessage("请选择时间!");
-            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
             var query = _orderApplication.QueryOrderSourceDetail(dto);
             var (total, items) = await
                 query.ToPagedListAsync(dto, HttpContext.RequestAborted);
@@ -3220,8 +3222,6 @@ namespace Hotline.Api.Controllers.Bi
             return ExcelStreamResult(stream, "受理类型时间统计");
         }
 
-
-
         /// <summary>
         /// 下级区域统计
         /// </summary>
@@ -3236,8 +3236,6 @@ namespace Hotline.Api.Controllers.Bi
         {
             EndTime = EndTime.AddDays(1).AddSeconds(-1);
 
-            var IsCenter = _sessionContext.OrgIsCenter;
-
             string count = "6";
             if (!string.IsNullOrEmpty(AreaCode) && AreaCode != "511500")
                 count = (AreaCode.Length + 2).ToString();
@@ -3245,139 +3243,179 @@ namespace Hotline.Api.Controllers.Bi
             if (string.IsNullOrEmpty(AreaCode))
                 AreaCode = "510000";
 
-            var query = _orderRepository.Queryable()
-                  .Where(p => p.CreationTime >= StartTime && p.CreationTime <= EndTime)
-                    .WhereIF(TypeId != null && TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
-                  .WhereIF(TypeId != null && TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
-                  .WhereIF(!string.IsNullOrEmpty(Line), p => p.TransferPhone == Line)
-                  .WhereIF(IsCenter == false, p => p.ActualHandleOrgCode.StartsWith(_sessionContext.RequiredOrgId))
-                   .GroupBy(p => new { Id = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)) })
-                  .Select(p => new
-                  {
-                      AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)),
-                      SumCount = SqlFunc.AggregateCount(p.AreaCode)
-                  })
-                  .MergeTable();
-
-            var list = await _systemAreaRepository.Queryable()
-                  .LeftJoin(query, (s, o) => s.Id == o.AreaCode)
-                  .Where((s, o) => s.ParentId == AreaCode)
-                  .Select((s, o) => new
-                  {
-                      AreaCode = s.Id,
-                      SumCount = o.SumCount,
-                      AreaName = s.AreaName,
-                      HasChild = SqlFunc.Subqueryable<SystemArea>().Where(d => d.ParentId == o.AreaCode).Any()
-                  })
-                .ToListAsync();
+            if (AreaCode == "510000")
+            {
+                var query = _orderRepository.Queryable()
+                      .Where(p => p.CreationTime >= StartTime && p.CreationTime <= EndTime)
+                        .WhereIF(TypeId != null && TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                      .WhereIF(TypeId != null && TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
+                      .WhereIF(!string.IsNullOrEmpty(Line), p => p.TransferPhone == Line)
+                      .Select(p => new
+                      {
+                          AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)),
+
+                      })
+                      .MergeTable()
+                      .Select(p => new
+                      {
+                          AreaCode = SqlFunc.IIF(p.AreaCode != "519800" && p.AreaCode != "519900", "511500", p.AreaCode)
+                      }
+                    ).MergeTable()
+                    .GroupBy(p => p.AreaCode)
+                    .Select(p => new
+                    {
+                        AreaCode = p.AreaCode,
+                        SumCount = SqlFunc.AggregateCount(p.AreaCode)
+                    }
+                    ).MergeTable();
+
+                var list = await _systemAreaRepository.Queryable()
+                      .LeftJoin(query, (s, o) => s.Id == o.AreaCode)
+                      .Where((s, o) => s.ParentId == AreaCode)
+                      .Select((s, o) => new
+                      {
+                          AreaCode = s.Id,
+                          SumCount = o.SumCount,
+                          AreaName = s.AreaName,
+                          HasChild = SqlFunc.Subqueryable<SystemArea>().Where(d => d.ParentId == o.AreaCode).Any()
+                      })
+                    .ToListAsync();
 
-            return list;
+                return list;
+            }
+            else
+            {
+                var query = _orderRepository.Queryable()
+                 .Where(p => p.CreationTime >= StartTime && p.CreationTime <= EndTime)
+                   .WhereIF(TypeId != null && TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(TypeId != null && TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
+                 .WhereIF(!string.IsNullOrEmpty(Line), p => p.TransferPhone == Line)
+                  .GroupBy(p => new { Id = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)) })
+                 .Select(p => new
+                 {
+                     AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)),
+                     SumCount = SqlFunc.AggregateCount(p.AreaCode)
+                 })
+                 .MergeTable();
+
+                var list = await _systemAreaRepository.Queryable()
+                      .LeftJoin(query, (s, o) => s.Id == o.AreaCode)
+                      .Where((s, o) => s.ParentId == AreaCode)
+                      .Select((s, o) => new
+                      {
+                          AreaCode = s.Id,
+                          SumCount = o.SumCount,
+                          AreaName = s.AreaName,
+                          HasChild = SqlFunc.Subqueryable<SystemArea>().Where(d => d.ParentId == o.AreaCode).Any()
+                      })
+                    .ToListAsync();
+                return list;
+            }
         }
 
+        /// <summary>
+        /// 热点满意度统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("visit-hotspot-satisfaction-statistics")]
+        public async Task<Object> VisitAndHotspotSatisfactionStatistics([FromQuery] VisitAndHotspotPagedKeywordRequest dto)
+        {
+            var data = await _orderApplication.VisitAndHotspotSatisfactionStatistics(dto);
+            var sumModel = new VisitAndHotspotSatisfactionStatisticsDto()
+            {
+                HotspotName = "总计",
+                TotalSumCount = data.Sum(x => x.TotalSumCount),
+                VerySatisfiedCount = data.Sum(x => x.VerySatisfiedCount),
+                SatisfiedCount = data.Sum(x => x.SatisfiedCount),
+                RegardedAsSatisfiedCount = data.Sum(x => x.RegardedAsSatisfiedCount),
+                DefaultSatisfiedCount = data.Sum(x => x.DefaultSatisfiedCount),
+                NoSatisfiedCount = data.Sum(x => x.NoSatisfiedCount),
+                NoEvaluateCount = data.Sum(x => x.NoEvaluateCount),
+                NoPutThroughCount = data.Sum(x => x.NoPutThroughCount),
+            };
+
+            return new { DataList = data, SumModel = sumModel };
+        }
 
-		/// <summary>
-		/// 热点满意度统计
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("visit-hotspot-satisfaction-statistics")]
-		public async Task<Object> VisitAndHotspotSatisfactionStatistics([FromQuery] VisitAndHotspotPagedKeywordRequest dto)
-		{
-			var data = await _orderApplication.VisitAndHotspotSatisfactionStatistics(dto);
-			var sumModel = new VisitAndHotspotSatisfactionStatisticsDto()
-			{
-				HotspotName = "总计",
-				TotalSumCount = data.Sum(x => x.TotalSumCount),
-				VerySatisfiedCount = data.Sum(x => x.VerySatisfiedCount),
-				SatisfiedCount = data.Sum(x => x.SatisfiedCount),
-				RegardedAsSatisfiedCount = data.Sum(x => x.RegardedAsSatisfiedCount),
-				DefaultSatisfiedCount = data.Sum(x => x.DefaultSatisfiedCount),
-				NoSatisfiedCount = data.Sum(x => x.NoSatisfiedCount),
-				NoEvaluateCount = data.Sum(x => x.NoEvaluateCount),
-				NoPutThroughCount = data.Sum(x => x.NoPutThroughCount),
-			};
-
-			return new { DataList = data, SumModel = sumModel };
-		}
-
-		/// <summary>
-		/// 热点满意度统计导出
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpPost("visit-hotspot-satisfaction-statistics/_export")]
-		public async Task<FileStreamResult> VisitAndHotspotSatisfactionStatisticsExport([FromBody] ExportExcelDto<VisitAndHotspotPagedKeywordRequest> dto)
-		{
-			List<VisitAndHotspotSatisfactionStatisticsDto> data = await _orderApplication.VisitAndHotspotSatisfactionStatistics(dto.QueryDto);
-			var sumModel = new VisitAndHotspotSatisfactionStatisticsDto()
-			{
-				HotspotName = "总计",
-				TotalSumCount = data.Sum(x => x.TotalSumCount),
-				VerySatisfiedCount = data.Sum(x => x.VerySatisfiedCount),
-				SatisfiedCount = data.Sum(x => x.SatisfiedCount),
-				RegardedAsSatisfiedCount = data.Sum(x => x.RegardedAsSatisfiedCount),
-				DefaultSatisfiedCount = data.Sum(x => x.DefaultSatisfiedCount),
-				NoSatisfiedCount = data.Sum(x => x.NoSatisfiedCount),
-				NoEvaluateCount = data.Sum(x => x.NoEvaluateCount),
-				NoPutThroughCount = data.Sum(x => x.NoPutThroughCount),
-			};
-			data.Add(sumModel);
-			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-			var dtos = data
-			 .Select(stu => _mapper.Map(stu, typeof(VisitAndHotspotSatisfactionStatisticsDto), dynamicClass))
-			 .Cast<object>()
-			 .ToList();
-
-			var stream = ExcelHelper.CreateStream(dtos);
-
-			return ExcelStreamResult(stream, "热点满意度统计数据");
-		}
-
-		/// <summary>
-		/// 热点满意度明细
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("visit-hotspot-satisfaction-detail")]
-		public async Task<PagedDto<OrderVisitDetailDto>> VisitAndHotspotSatisfactionDetail([FromQuery] VisitAndHotspotPagedKeywordRequest dto)
-		{
-			var (total, items) = await _orderApplication.VisitAndHotspotSatisfactionDetail(dto)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
-		}
-
-		/// <summary>
-		/// 热点满意度明细导出
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpPost("visit-hotspot-satisfaction-detail/_export")]
-		public async Task<FileStreamResult> VisitAndHotspotSatisfactionDetailExport([FromBody] ExportExcelDto<VisitAndHotspotPagedKeywordRequest> dto)
-		{
-			var query = _orderApplication.VisitAndHotspotSatisfactionDetail(dto.QueryDto);
-			List<OrderVisitDetail> 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<OrderVisitDetailDto>>(data);
-
-			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-			var dtos = dataDtos
-				.Select(stu => _mapper.Map(stu, typeof(OrderVisitDetailDto), dynamicClass))
-				.Cast<object>()
-				.ToList();
-
-			var stream = ExcelHelper.CreateStream(dtos);
-
-			return ExcelStreamResult(stream, "热点满意度明细数据");
-		}
-	}
+        /// <summary>
+        /// 热点满意度统计导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("visit-hotspot-satisfaction-statistics/_export")]
+        public async Task<FileStreamResult> VisitAndHotspotSatisfactionStatisticsExport([FromBody] ExportExcelDto<VisitAndHotspotPagedKeywordRequest> dto)
+        {
+            List<VisitAndHotspotSatisfactionStatisticsDto> data = await _orderApplication.VisitAndHotspotSatisfactionStatistics(dto.QueryDto);
+            var sumModel = new VisitAndHotspotSatisfactionStatisticsDto()
+            {
+                HotspotName = "总计",
+                TotalSumCount = data.Sum(x => x.TotalSumCount),
+                VerySatisfiedCount = data.Sum(x => x.VerySatisfiedCount),
+                SatisfiedCount = data.Sum(x => x.SatisfiedCount),
+                RegardedAsSatisfiedCount = data.Sum(x => x.RegardedAsSatisfiedCount),
+                DefaultSatisfiedCount = data.Sum(x => x.DefaultSatisfiedCount),
+                NoSatisfiedCount = data.Sum(x => x.NoSatisfiedCount),
+                NoEvaluateCount = data.Sum(x => x.NoEvaluateCount),
+                NoPutThroughCount = data.Sum(x => x.NoPutThroughCount),
+            };
+            data.Add(sumModel);
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+            var dtos = data
+             .Select(stu => _mapper.Map(stu, typeof(VisitAndHotspotSatisfactionStatisticsDto), dynamicClass))
+             .Cast<object>()
+             .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "热点满意度统计数据");
+        }
+
+        /// <summary>
+        /// 热点满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("visit-hotspot-satisfaction-detail")]
+        public async Task<PagedDto<OrderVisitDetailDto>> VisitAndHotspotSatisfactionDetail([FromQuery] VisitAndHotspotPagedKeywordRequest dto)
+        {
+            var (total, items) = await _orderApplication.VisitAndHotspotSatisfactionDetail(dto)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
+        }
+
+        /// <summary>
+        /// 热点满意度明细导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("visit-hotspot-satisfaction-detail/_export")]
+        public async Task<FileStreamResult> VisitAndHotspotSatisfactionDetailExport([FromBody] ExportExcelDto<VisitAndHotspotPagedKeywordRequest> dto)
+        {
+            var query = _orderApplication.VisitAndHotspotSatisfactionDetail(dto.QueryDto);
+            List<OrderVisitDetail> 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<OrderVisitDetailDto>>(data);
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+            var dtos = dataDtos
+                .Select(stu => _mapper.Map(stu, typeof(OrderVisitDetailDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "热点满意度明细数据");
+        }
+    }
 }

+ 9 - 9
src/Hotline.Api/Controllers/Bigscreen/JudicialManagementScreenController.cs

@@ -47,7 +47,7 @@ namespace Hotline.Api.Controllers.Bigscreen
             var dto = new OrderModuleDto();
 
             var data = await _judicialManagementOrdersRepository.Queryable()
-                .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime)
+                .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.IsItCounted == true)
                 .Select(o => new
                 {
                     o.Id,
@@ -102,7 +102,7 @@ namespace Hotline.Api.Controllers.Bigscreen
 
             var list = await _judicialManagementOrdersRepository.Queryable()
                .LeftJoin<JudicialComplaintsEventType>((o, j) => o.EventTypeOneLevelId == j.Id)
-               .Where((o, j) => o.EventTypeOneLevelId != null && j.Id != null)
+               .Where((o, j) => o.EventTypeOneLevelId != null && j.Id != null&&o.IsItCounted==true)
                .Where((o, j) => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.AreaCode.StartsWith(AreaCode))
                .Select((o, j) => new
                {
@@ -169,7 +169,7 @@ namespace Hotline.Api.Controllers.Bigscreen
                 };
 
                 var data = await _judicialManagementOrdersRepository.Queryable()
-                .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.AreaCode.StartsWith(item.Id))
+                .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.AreaCode.StartsWith(item.Id)&&o.IsItCounted==true)
                 .Select(o => new
                 {
                     o.Id,
@@ -213,7 +213,7 @@ namespace Hotline.Api.Controllers.Bigscreen
         {
             var list = await _judicialManagementOrdersRepository.Queryable()
                   .LeftJoin<SystemArea>((o, s) => o.AreaCode == s.Id)
-                  .Where((o, s) => o.CreationTime.Date >= DateTime.Now.Date)
+                  .Where((o, s) => o.CreationTime.Date >= DateTime.Now.Date&&o.IsItCounted==true)
                   .Select((o, s) => new
                   {
                       o.Id,
@@ -251,7 +251,7 @@ namespace Hotline.Api.Controllers.Bigscreen
                  .LeftJoin<OrderVisit>((x, o) => x.Id == o.OrderId)
                  .LeftJoin<OrderVisitDetail>((x, o, p) => o.Id == p.VisitId)
                 .Where((x, o, p) => o.VisitTime >= StartTime && o.VisitTime <= EndTime && p.VisitTarget == EVisitTarget.Org &&
-                o.VisitState == EVisitState.Visited && !string.IsNullOrEmpty(p.VisitOrgCode) && p.VisitOrgCode.Length >= 6)
+                o.VisitState == EVisitState.Visited && !string.IsNullOrEmpty(p.VisitOrgCode) && p.VisitOrgCode.Length >= 6&&x.IsItCounted==true)
                 .Select((x, o, p) => new
                 {
                     p.VisitOrgCode,
@@ -296,7 +296,7 @@ namespace Hotline.Api.Controllers.Bigscreen
             }
 
             var queryData = await _judicialManagementOrdersRepository.Queryable()
-                       .Where(o => o.CreationTime >= StartDate && o.CreationTime <= EndDate)
+                       .Where(o => o.CreationTime >= StartDate && o.CreationTime <= EndDate&&o.IsItCounted==true)
                        .Select(o => new
                        {
                            o.Id,
@@ -338,13 +338,13 @@ namespace Hotline.Api.Controllers.Bigscreen
             EndTime = EndTime.AddDays(1).AddSeconds(-1);
 
             var SumCount = await _judicialManagementOrdersRepository.Queryable()
-               .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime)
+               .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.IsItCounted == true)
                .CountAsync();
 
             if (IsSource)
             {
                 var list = await _judicialManagementOrdersRepository.Queryable()
-                .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime)
+                .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime&&o.IsItCounted==true)
                 .GroupBy(o => new { o.SourceChannelCode, o.SourceChannel })
                 .Select(o => new OrderProportionStatisticsDto()
                 {
@@ -358,7 +358,7 @@ namespace Hotline.Api.Controllers.Bigscreen
             else
             {
                 var list = await _judicialManagementOrdersRepository.Queryable()
-               .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime)
+               .Where(o => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.IsItCounted == true)
                 .GroupBy(o => new { o.AcceptTypeCode, o.AcceptType })
                 .Select(o => new OrderProportionStatisticsDto()
                 {

+ 1 - 1
src/Hotline.Api/Controllers/EnforcementOrderController.cs

@@ -101,7 +101,7 @@ namespace Hotline.Api.Controllers
            .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.Order.AcceptorName.Contains(dto.NameOrNo!) || d.Order.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席
            .WhereIF(dto.CreationTimeStart.HasValue, d => d.Order.CreationTime >= dto.CreationTimeStart) //受理时间开始
            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.Order.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-           .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.Order.EmergencyLevel))  //紧急程度
+           //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.Order.EmergencyLevel))  //紧急程度
            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.Order.FromPhone.Contains(dto.FromPhone)) //来电号码
            .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Order.Contact.Contains(dto.PhoneNo!)) //联系电话
            .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.Order.PushTypeCode == dto.PushTypeCode) //推送分类

+ 4 - 2
src/Hotline.Api/Controllers/JudicialManagementOrdersController.cs

@@ -133,7 +133,9 @@ namespace Hotline.Api.Controllers
             _mapper.Map(dto, order);
             if (dto.Files.Any())
                 order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", HttpContext.RequestAborted);
-            await _judicialManagementOrdersRepository.UpdateAsync(order, HttpContext.RequestAborted);
+            else
+	            order.FileJson = new List<Share.Dtos.File.FileJson>();
+			await _judicialManagementOrdersRepository.UpdateAsync(order, HttpContext.RequestAborted);
 
             //处理执法部门
             if (dto.EnforcementOrdersHandler != null && dto.EnforcementOrdersHandler.Any())
@@ -482,7 +484,7 @@ namespace Hotline.Api.Controllers
              var items = await _judicialComplaintsEventTypeRepository.Queryable()
              .LeftJoin<JudicialManagementOrders>((x, o) => o.EventTypeSpliceName != null &&
              (x.EventTypeName == o.EventTypeSpliceName || o.EventTypeSpliceName.Contains(x.EventTypeName)))
-            .Where((x, o) => o.CreationTime >= StartTime && o.CreationTime <= EndTime)
+            .Where((x, o) => o.CreationTime >= StartTime && o.CreationTime <= EndTime && o.IsItCounted == true)
             .WhereIF(!string.IsNullOrEmpty(areCodeText), (x, o) => o.AreaCode.StartsWith(areCodeText))
              .Where((x, o) => x.ParentId == Id)
              .GroupBy((x, o) => new { x.Id, x.EventTypeName })

+ 5 - 2
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -245,8 +245,11 @@ namespace Hotline.Api.Controllers
             _mapper.Map(dto.Data, knowledge);
             //if (update.Tags.Any()) await _repositoryts.UpdateVectorAsync(update.Id, update.Tags, HttpContext.RequestAborted);
 
-            if (dto.Data.Files.Any()) knowledge.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, knowledge.Id, "", HttpContext.RequestAborted);
-            if (dto.Workflow != null) knowledge.Renewaln = update.Status != EKnowledgeStatus.Drafts;
+            if (dto.Data.Files.Any()) 
+                knowledge.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, knowledge.Id, "", HttpContext.RequestAborted);
+            else
+	            knowledge.FileJson = new List<Share.Dtos.File.FileJson>();
+			if (dto.Workflow != null) knowledge.Renewaln = update.Status != EKnowledgeStatus.Drafts;
             await _knowledgeRepository.UpdateAsync(knowledge, HttpContext.RequestAborted);
             if (dto.Workflow != null)
             {

+ 150 - 144
src/Hotline.Api/Controllers/OrderController.cs

@@ -961,9 +961,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) //受理时间开始
@@ -1432,7 +1432,9 @@ public class OrderController : BaseController
         _mapper.Map(dto.Data, delay);
         if (dto.Data.Files.Any())
             delay.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, delay.Id, "", HttpContext.RequestAborted);
-        await _orderDelayRepository.UpdateAsync(delay, HttpContext.RequestAborted);
+        else
+	        delay.FileJson = new List<Share.Dtos.File.FileJson>();
+		await _orderDelayRepository.UpdateAsync(delay, HttpContext.RequestAborted);
         try
         {
             dto.NextWorkflow.WorkflowId = delay.WorkflowId;
@@ -1780,11 +1782,11 @@ public class OrderController : BaseController
         var endTime = DateTime.Now;
         if (int.Parse(setting?.SettingValue[0]) > 0)
         {
-	        endTime = _timeLimitDomainService
-		        .CalcEndTime(visit.VisitTime.Value, ETimeType.WorkDay, int.Parse(setting?.SettingValue[0]),0,0).EndTime;
-	        if (DateTime.Now > endTime)
-		        throw UserFriendlyException.SameMessage("甄别申请时限已超过系统预定设置,不能申请");
-		}
+            endTime = _timeLimitDomainService
+                .CalcEndTime(visit.VisitTime.Value, ETimeType.WorkDay, int.Parse(setting?.SettingValue[0]), 0, 0).EndTime;
+            if (DateTime.Now > endTime)
+                throw UserFriendlyException.SameMessage("甄别申请时限已超过系统预定设置,不能申请");
+        }
 
         var model = _mapper.Map<OrderScreen>(dto.Data);
         model.Status = EScreenStatus.Apply;
@@ -1793,7 +1795,9 @@ public class OrderController : BaseController
         model.InitId();
         if (dto.Data.Files.Any())
             model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted);
-        await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted);
+        else
+	        model.FileJson = new List<Share.Dtos.File.FileJson>();
+		await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted);
 
         var workflowId = string.Empty;
         try
@@ -1834,7 +1838,8 @@ public class OrderController : BaseController
         if (dto.Data.Files.Any())
             screen.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, screen.Id, "", HttpContext.RequestAborted);
         else
-            screen.FileJson = null;
+	        screen.FileJson = new List<Share.Dtos.File.FileJson>();
+		
 		screen.SendBackApplyNum++;
 		await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
         try
@@ -1853,7 +1858,7 @@ public class OrderController : BaseController
     /// 甄别流程退回
     /// </summary>
     [HttpPost("screen/previous")]
-	public async Task ScreenPrevious([FromBody] PreviousWorkflowDto dto) 
+    public async Task ScreenPrevious([FromBody] PreviousWorkflowDto dto)
     {
 	    var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
 		    cancellationToken: HttpContext.RequestAborted);
@@ -2351,7 +2356,9 @@ public class OrderController : BaseController
         urge.State = 1;
         if (dto.Files.Any())
             urge.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, urge.Id, "", HttpContext.RequestAborted);
-        await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted);
+        else
+	        urge.ReplyFileJson = new List<Share.Dtos.File.FileJson>();
+		await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted);
     }
 
     /// <summary>
@@ -2548,15 +2555,15 @@ public class OrderController : BaseController
                     {
                         canInsteadHandle = false;
                     };
-				}
-				if (canInsteadHandle)
-				{
-					var unhandleSteps =
-						await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
-					// 会签多节点 不允许班长代办  归档没有待办节点
-					if (unhandleSteps.Count != 1)
-						canInsteadHandle = false;
-					if (isEnable < 3 && unhandleSteps.Count == 1)
+                }
+                if (canInsteadHandle)
+                {
+                    var unhandleSteps =
+                        await _workflowDomainService.GetUnhandleStepsByOthersAsync(order.WorkflowId, HttpContext.RequestAborted);
+                    // 会签多节点 不允许班长代办  归档没有待办节点
+                    if (unhandleSteps.Count != 1)
+                        canInsteadHandle = false;
+                    if (isEnable < 3 && unhandleSteps.Count == 1)
                     {
                         var type = isEnable - 1;
                         var step = unhandleSteps.FirstOrDefault(d => d.BusinessType == (EBusinessType)type);
@@ -2691,16 +2698,18 @@ public class OrderController : BaseController
         dto.RepeatableEventDetails = repeatables;
         if (!string.IsNullOrEmpty(dto.WorkflowId))
         {
-            var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: 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();
             dto.OrderRemarks = remarks;
-            if (order.Status == EOrderStatus.SendBack || order.Status == EOrderStatus.SendBackAudit)
+            if (order.Status == EOrderStatus.SendBack || order.Status == EOrderStatus.SendBackAudit || order.Status == EOrderStatus.BackToUnAccept)
             {
-				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;
+                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;
 			}
         }
 
@@ -2729,7 +2738,7 @@ public class OrderController : BaseController
             dto.CallId = await _callApplication.GetOrSetCallIdAsync(dto.CallId, HttpContext.RequestAborted);
             var exists = await _orderRepository.AnyAsync(d => d.CallId == dto.CallId, HttpContext.RequestAborted);
             if (exists)
-                throw UserFriendlyException.SameMessage("来电已保存工单");
+                throw new UserFriendlyException($"来电已保存工单, phone:{dto.FromPhone}, callId: {dto.CallId}", "来电已保存工单");
         }
 
         var order = _mapper.Map<Orders.Order>(dto);
@@ -2910,7 +2919,9 @@ public class OrderController : BaseController
 
         if (dto.Files.Any())
             order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", HttpContext.RequestAborted);
-        await _orderRepository.UpdateNav(order).Include(d => d.OrderExtension).ExecuteCommandAsync();
+        else
+	        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);
         // 副本工单
@@ -3068,6 +3079,8 @@ public class OrderController : BaseController
                 expiredTimeConfig.NearlyExpiredTime, expiredTimeConfig.NearlyExpiredTimeOne, dto.Opinion,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
                 canUpdateOrderSender);
+            //TODO 发送短信超期和即将超期
+            
         }
         else if (dto.FlowDirection is EFlowDirection.CenterToOrg)
         {
@@ -3079,6 +3092,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);
         }
@@ -3172,7 +3187,7 @@ public class OrderController : BaseController
         if (order is null)
             throw new UserFriendlyException($"工单未开启流程, workflowId: {workflow.Id}");
         order.UpdateHandlingStatus(workflow.IsInCountersign);
-		_mapper.Map(workflow, order);
+        _mapper.Map(workflow, order);
         await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
     }
 
@@ -3328,7 +3343,7 @@ public class OrderController : BaseController
         var (total, items) = await _orderRepository
             .Queryable(hasHandled: isHandled)
             .Includes(d => d.OrderSpecials)
-            .Where(d=>d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept)
+            .Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept)
             .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)
@@ -3682,10 +3697,25 @@ public class OrderController : BaseController
             .Queryable()
             .Includes(d => d.Workflow)
             .FirstAsync(d => d.Id == workflow.ExternalId);
-        if (oneSendBack || twoSendBack)
+        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
+        };
+		if (oneSendBack || twoSendBack)
         {
-            var (currentStep, prevStep, isOrgToCenter, isSecondToFirstOrgLevel) = await _workflowApplication.GetPreviousInformationAsync(
-                dto.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles, HttpContext.RequestAborted);
             var sendBack = await _orderSendBackAuditRepository.Queryable()
                 .Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync();
             if (sendBack)
@@ -3694,33 +3724,19 @@ public class OrderController : BaseController
             var specialAny = await _orderSpecialRepository.Queryable().Where(x => x.OrderId == dto.OrderId && x.State == 0)
                 .AnyAsync();
             if (specialAny) throw UserFriendlyException.SameMessage("工单已存在待审批特提信息!");
-
-
             if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!");
             if ((oneSendBack && isOrgToCenter) || (twoSendBack && isSecondToFirstOrgLevel))
             {
-                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
-                };
-                await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
+               
                 await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { Status = EOrderStatus.SendBackAudit })
-	                .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
-			}
+                    .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
+            }
             else
             {
-                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;
@@ -3731,7 +3747,10 @@ public class OrderController : BaseController
         }
         else
         {
-            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;
@@ -3739,7 +3758,8 @@ public class OrderController : BaseController
                 .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
             //发送短信TODO
         }
-    }
+		await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
+	}
 
     /// <summary>
     /// 工单业务退回审批
@@ -3780,9 +3800,9 @@ public class OrderController : BaseController
             await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType })
                 .Where(o => o.Id == sendBack.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted);
             //发送短信TODO
-            await _orderSendBackAuditRepository.UpdateAsync(sendBack, HttpContext.RequestAborted);
         }
-    }
+        await _orderSendBackAuditRepository.UpdateAsync(sendBack, HttpContext.RequestAborted);
+	}
 
     /// <summary>
     /// 工单业务批量退回审批
@@ -3817,7 +3837,7 @@ public class OrderController : BaseController
                 var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter
                     ? EProcessType.Zhiban
                     : EProcessType.Jiaoban;
-                await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType})
+                await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType })
                     .Where(o => o.Id == sendBack.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted);
                 //发送短信TODO
             }
@@ -4164,34 +4184,14 @@ public class OrderController : BaseController
             //var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
             //	ETimeType.WorkDay,
             //	dto.TimeLimit.Value, order.AcceptTypeCode);
-            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType,Status = EOrderStatus.Special })
+            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType, Status = EOrderStatus.Special })
                 .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
             var orderDto = _mapper.Map<OrderDto>(order);
             await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto,
                 cancellationToken: HttpContext.RequestAborted);
             //}
             await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, order.Status >= EOrderStatus.Filed, HttpContext.RequestAborted);
-            var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == dto.OrderId);
-            if (publish != null)
-            {
-                var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-                publishHistory.OrderPublishId = publish.Id;
-                publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-                publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-                publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-                publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-                publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-                publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-                await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
-                await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
-            }
-
-            var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId && x.VisitState != EVisitState.None);
-            if (visit != null)
-            {
-                visit.VisitState = EVisitState.None;
-                await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
-            }
+           
 
             if (order != null && ("001171".Equals(model.OrgId) ||
                                   "001178".Equals(model.OrgId) ||
@@ -4214,10 +4214,11 @@ public class OrderController : BaseController
                 //}
             }
         }
-        else {
-			await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { Status = EOrderStatus.SpecialAudit })
-				.Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
-		}
+        else
+        {
+            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { Status = EOrderStatus.SpecialAudit })
+                .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
+        }
     }
 
     /// <summary>
@@ -4313,31 +4314,32 @@ public class OrderController : BaseController
                 ? EProcessType.Zhiban
                 : EProcessType.Jiaoban;
             await _workflowApplication.RecallAsync(recall, endTime, order.Status >= EOrderStatus.Filed, HttpContext.RequestAborted);
-			var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == dto.OrderId);
-            if (publish != null)
-            {
-                var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-                publishHistory.OrderPublishId = publish.Id;
-                publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-                publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-                publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-                publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-                publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-                publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-                await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
-                await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
-            }
+            //var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == dto.OrderId);
+            //if (publish != null)
+            //{
+            //    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+            //    publishHistory.OrderPublishId = publish.Id;
+            //    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+            //    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+            //    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+            //    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+            //    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+            //    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+            //    await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
+            //    await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
+            //}
 
             var reTransactNum = order.ReTransactNum.HasValue ? order.ReTransactNum.Value + 1 : 1;
-            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType,ReTransactNum = reTransactNum, Status = EOrderStatus.BackToUnAccept }).Where(o => o.Id == order.Id)
+            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)
                 .ExecuteCommandAsync(HttpContext.RequestAborted);
 
-            var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId && x.VisitState != EVisitState.None);
-            if (visit != null)
-            {
-                visit.VisitState = EVisitState.None;
-                await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
-            }
+            //var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId && x.VisitState != EVisitState.None);
+            //if (visit != null)
+            //{
+            //    visit.VisitState = EVisitState.None;
+            //    await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
+            //}
         }
     }
 
@@ -4361,7 +4363,9 @@ public class OrderController : BaseController
         special.Opinion = dto.Opinion;
         if (dto.Files.Any())
             special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted);
-        await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted);
+        else
+	        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)
         {
@@ -4387,7 +4391,7 @@ public class OrderController : BaseController
             var processType = special.FlowDirection is EFlowDirection.OrgToCenter or EFlowDirection.CenterToCenter or EFlowDirection.FiledToCenter
                 ? EProcessType.Zhiban
                 : EProcessType.Jiaoban;
-            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType,Status = EOrderStatus.Special })
+            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType, Status = EOrderStatus.Special })
                 .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
             var orderDto = _mapper.Map<OrderDto>(order);
             await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto,
@@ -4397,27 +4401,27 @@ public class OrderController : BaseController
             //todo 特提重办,按审批通过时间依据中心派至部门的规则计算期满时间,更新order
 
             await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, order.Status >= EOrderStatus.Filed, HttpContext.RequestAborted);
-            var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId);
-            if (publish != null)
-            {
-                var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-                publishHistory.OrderPublishId = publish.Id;
-                publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-                publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-                publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-                publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-                publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-                publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-                await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
-                await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
-            }
+            //var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId);
+            //if (publish != null)
+            //{
+            //    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+            //    publishHistory.OrderPublishId = publish.Id;
+            //    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+            //    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+            //    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+            //    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+            //    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+            //    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+            //    await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
+            //    await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
+            //}
 
-            var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None);
-            if (visit != null)
-            {
-                visit.VisitState = EVisitState.None;
-                await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
-            }
+            //var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None);
+            //if (visit != null)
+            //{
+            //    visit.VisitState = EVisitState.None;
+            //    await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
+            //}
 
             if (order != null && ("001171".Equals(special.OrgId) ||
                                   "001178".Equals(special.OrgId) ||
@@ -4463,7 +4467,9 @@ public class OrderController : BaseController
             special.Opinion = dto.Opinion;
             if (dto.Files.Any())
                 special.ReplyFileJson = await _fileRepository.AddFileAsync(dto.Files, special.Id, "", HttpContext.RequestAborted);
-            await _orderSpecialRepository.UpdateAsync(special, HttpContext.RequestAborted);
+            else
+	            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)
             {
@@ -4489,7 +4495,7 @@ public class OrderController : BaseController
                 var processType = special.FlowDirection is EFlowDirection.OrgToCenter or EFlowDirection.CenterToCenter or EFlowDirection.FiledToCenter
                     ? EProcessType.Zhiban
                     : EProcessType.Jiaoban;
-                await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType,Status = EOrderStatus.Special })
+                await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType, Status = EOrderStatus.Special })
                     .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
                 var orderDto = _mapper.Map<OrderDto>(order);
                 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto,
@@ -4631,24 +4637,24 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                 d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
             //.WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!))
-            .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
-            .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannel))
-            .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId))
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType)//受理类型
+                                                                                                //.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(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Workflow.ActualHandleOrgCode))
+            .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)
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
-            .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))
+            //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))
             .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo),
                 d => d.FromPhone.Contains(dto.PhoneNo!) || d.Contact.Contains(dto.PhoneNo!))
             .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode)
             .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart)
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd)
-            .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))
-            .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.BackToUnAccept),
-                d => d.Status <= EOrderStatus.SpecialToUnAccept);
+            .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)//工单状态
+            .WhereIF(dto.Status != null && dto.Status == EOrderStatus.BackToUnAccept, d => d.Status <= EOrderStatus.SpecialToUnAccept);
         if (!_sessionContext.OrgIsCenter && _sessionContext.OrgId.Length >= 6)
         {
             var oneCode = _sessionContext.OrgId.Substring(0, 6);
@@ -6198,7 +6204,7 @@ public class OrderController : BaseController
         if (string.IsNullOrEmpty(dto.StepId))
         {
             await _orderRepository.Updateable()
-                .SetColumns(o => new Orders.Order() { SignerId = dto.Handler.UserId, SignerName = dto.Handler.Username,Status = EOrderStatus.HandOver })
+                .SetColumns(o => new Orders.Order() { SignerId = dto.Handler.UserId, SignerName = dto.Handler.Username, Status = EOrderStatus.HandOver })
                 .Where(o => o.Id == dto.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted);
         }
         else
@@ -6212,10 +6218,10 @@ public class OrderController : BaseController
             {
                 new(dto.Handler.UserId,dto.Handler.Username,dto.Handler.OrgId,dto.Handler.OrgName,step.RoleId,step.RoleName, new List<WorkflowStep>{step})
             }, HttpContext.RequestAborted);
-			await _orderRepository.Updateable()
-				.SetColumns(o => new Orders.Order() { Status = EOrderStatus.HandOver })
-				.Where(o => o.Id == dto.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted);
-		}
+            await _orderRepository.Updateable()
+                .SetColumns(o => new Orders.Order() { Status = EOrderStatus.HandOver })
+                .Where(o => o.Id == dto.OrderId).ExecuteCommandAsync(HttpContext.RequestAborted);
+        }
     }
 
     #endregion

+ 84 - 3
src/Hotline.Api/Controllers/ProvinceStatisticsController.cs

@@ -4,10 +4,8 @@ using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.ProvinceStatistics;
 using Hotline.Share.Enums.Order;
-using Hotline.Share.Enums.Settings;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
-using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
@@ -26,6 +24,9 @@ namespace Hotline.Api.Controllers
         private readonly IRepository<OrderWarning> _orderWarningRepository;
         private readonly IRepository<OrderUrge> _orderUrgeRepository;
         private readonly IRepository<OrderComplement> _orderComplementRepository;
+        private readonly IRepository<OrderSupervise> _orderSuperviseRepository;
+        private readonly IOrderRepository _orderRepository;
+        private readonly IRepository<OrderExtension> _orderExtensionRepository;
 
 
         public ProvinceStatisticsController(IMapper mapper,
@@ -36,7 +37,10 @@ namespace Hotline.Api.Controllers
             IRepository<OrderRevoke> orderRevokeRepository,
             IRepository<OrderWarning> orderWarningRepository,
             IRepository<OrderUrge> orderUrgeRepository,
-            IRepository<OrderComplement> orderComplementRepository)
+            IRepository<OrderComplement> orderComplementRepository,
+            IRepository<OrderSupervise> orderSuperviseRepository,
+            IOrderRepository orderRepository,
+            IRepository<OrderExtension> orderExtensionRepository)
         {
             _mapper = mapper;
             _sessionContext = sessionContext;
@@ -47,6 +51,9 @@ namespace Hotline.Api.Controllers
             _orderWarningRepository = orderWarningRepository;
             _orderUrgeRepository = orderUrgeRepository;
             _orderComplementRepository = orderComplementRepository;
+            _orderSuperviseRepository = orderSuperviseRepository;
+            _orderRepository = orderRepository;
+            _orderExtensionRepository = orderExtensionRepository;
         }
 
         /// <summary>
@@ -371,5 +378,79 @@ namespace Hotline.Api.Controllers
             return data;
         }
 
+        /// <summary>
+        /// 省督办查询
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("get_province_order_supervise_list")]
+        public async Task<PagedDto<ProvinceOrderSuperviseListDto>> GetProvinceOrderSuperviseList([FromQuery] QueryProvinceSuperviseDto dto)
+        {
+            var (total, items) = await _orderSuperviseRepository.Queryable()
+                           .Includes(p => p.Order)
+                           .Where(p => p.Province == true)
+                          .WhereIF(!string.IsNullOrEmpty(dto.No), p => p.Order.No == dto.No)
+                           .WhereIF(!string.IsNullOrEmpty(dto.Title), p => p.Order.Title == dto.Title)
+                           .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), p => p.Order.ProvinceNo == dto.ProvinceNo)
+                           .WhereIF(dto.ApplyStartTime.HasValue, p => p.SuperviseTime >= dto.ApplyStartTime.Value)
+                           .WhereIF(dto.ApplyEndTime.HasValue, p => p.SuperviseTime <= dto.ApplyEndTime.Value)
+                           .WhereIF(!string.IsNullOrEmpty(dto.OrgName), p => p.OrgName.Contains(dto.OrgName))
+                           .WhereIF(dto.State.HasValue, p => p.State == dto.State)
+                            .WhereIF(dto.ReplyStartTime.HasValue, p => p.ReplyTime >= dto.ReplyStartTime.Value)
+                           .WhereIF(dto.ReplyEndTime.HasValue, p => p.ReplyTime <= dto.ReplyEndTime.Value)
+                           .OrderByDescending(x => x.SuperviseTime)
+                           .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+
+            return new PagedDto<ProvinceOrderSuperviseListDto>(total, _mapper.Map<IReadOnlyList<ProvinceOrderSuperviseListDto>>(items));
+        }
+
+        /// <summary>
+        /// 获督办详情
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("get_order_supervise_detail")]
+        public async Task<OrderSupervise> GetOrderSuperviseDetail(string id)
+        {
+            var data = await _orderSuperviseRepository.GetAsync(p => p.Id == id, HttpContext.RequestAborted);
+            if (data == null)
+                throw UserFriendlyException.SameMessage("督办查询失败");
+            return data;
+        }
+
+        /// <summary>
+        /// 查询省拓展信息
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("get_province_order_extension")]
+        public async Task<PagedDto<OrderDto>> GetProvinceOrderExtension([FromQuery] QueryProvinceSendBackDto dto)
+        {
+            var (total, items) = await _orderRepository.Queryable()
+               .Includes(p => p.OrderExtension)
+               .Where(p => p.OrderExtension.Id != null && p.Source != ESource.ProvinceStraight)
+               .WhereIF(!string.IsNullOrEmpty(dto.No), p => p.No == dto.No)
+               .WhereIF(!string.IsNullOrEmpty(dto.Title), p => p.Title == dto.Title)
+               .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), p => p.ProvinceNo == dto.ProvinceNo)
+               .WhereIF(dto.ApplyStartTime.HasValue, p => p.CreationTime >= dto.ApplyStartTime.Value)
+               .WhereIF(dto.ApplyEndTime.HasValue, p => p.CreationTime <= dto.ApplyEndTime.Value)
+               .OrderByDescending(p => p.CreationTime)
+               .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        }
+
+        /// <summary>
+        /// 查询拓展信息详情
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("get_order_extension_info")]
+        public async Task<OrderExtension> GetOrderExtensionInfo(string id)
+        {
+            var data = await _orderExtensionRepository.GetAsync(p => p.Id == id, HttpContext.RequestAborted);
+            if (data == null)
+                throw UserFriendlyException.SameMessage("拓展信息查询失败");
+            return data;
+        }
     }
 }

+ 144 - 103
src/Hotline.Api/Controllers/TestController.cs

@@ -1,5 +1,6 @@
 using System.Collections.Concurrent;
 using System.Data;
+using System.Diagnostics;
 using System.IO;
 using System.Threading;
 using DotNetCore.CAP;
@@ -15,6 +16,9 @@ using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Configs;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
+using Hotline.FlowEngine;
+using Hotline.FlowEngine.Definitions;
+using Hotline.FlowEngine.Notifications;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Identity.Roles;
@@ -120,6 +124,7 @@ public class TestController : BaseController
     private readonly IRepository<TrCallRecord> _trCallRecordRepository;
     private readonly IQualityApplication _qualityApplication;
     private readonly IEnforcementApplication _enforcementApplication;
+    private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IMapper _mapper;
     private readonly IOptionsSnapshot<SendSmsConfiguration> _sendSmsConfiguration;
     private readonly IOrderReportApplication _orderReportApplication;
@@ -167,6 +172,7 @@ public class TestController : BaseController
         IRepository<TrCallRecord> trCallRecordRepository,
         IQualityApplication qualityApplication,
         IEnforcementApplication enforcementApplication,
+        IWorkflowDomainService workflowDomainService,
         IMapper mapper,
 
 
@@ -209,6 +215,7 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository
         _trCallRecordRepository = trCallRecordRepository;
         _qualityApplication = qualityApplication;
         _enforcementApplication = enforcementApplication;
+        _workflowDomainService = workflowDomainService;
         _orderRepository = orderRepository;
         _mapper = mapper;
         _sendSmsConfiguration = sendSmsConfiguration;
@@ -248,6 +255,7 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository
                     orderData.IsTheClueTrue = item.IsTheClueTrue;
                     orderData.IsPassTheBuckOrder = item.IsPassTheBuckOrder;
                     orderData.OrderSoure = EOrderSoure.Hotline;
+                    orderData.CreationTime = item.CreationTime;
                     if (item.EventTypeId == "04" || item.EventTypeId == "05" || item.EventTypeId == "06" || item.EventTypeId == "07" || item.EventTypeId == "08" ||
                         item.EventTypeId == "0401" || item.EventTypeId == "0501" || item.EventTypeId == "0601" || item.EventTypeId == "0701" || item.EventTypeId == "0801")
                     {
@@ -280,7 +288,8 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository
                         OrderNo = order.No,
                         OrderSoure = EOrderSoure.Hotline,
                         OrgCode = order.OrgLevelOneCode,
-                        OrgName = order.OrgLevelOneName
+                        OrgName = order.OrgLevelOneName,
+                        CreationTime= order.CreationTime
                     };
                     await _enforcementOrdersHandlerRepository.AddAsync(enforcementOrdersHandler, HttpContext.RequestAborted);
                 }
@@ -309,29 +318,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
@@ -500,7 +509,8 @@ 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);
         return OpenResponse.Ok(DateTime.Now.ToString("F"));
     }
 
@@ -729,12 +739,30 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository
     [HttpPost("t4")]
     public async Task TestExportExcel1()
     {
-        //var orders = await _orderRepository.Queryable()
-        //    .Includes(d => d.OrderExtension)
-        //    .InnerJoin<Workflow>((o, w) => o.WorkflowId == w.Id)
-        //    .Where((o, w) => o.Status < EOrderStatus.Filed && w.Status == EWorkflowStatus.Completed)
-        //    .ToListAsync(HttpContext.RequestAborted);
-        //_logger.LogWarning($"order count: {orders.Count}");
+        var numbers = new List<string>
+        {
+            "20240623000180",
+            "20240622000097",
+            "20240621000055",
+            "20240622000185",
+            "20240623000025",
+            "20240621000099",
+            "20240621000270",
+            "20240622000060",
+            "20240621000144",
+        };
+        
+        var orders = await _orderRepository.Queryable()
+            .Includes(d => d.OrderExtension)
+            .Where(d => numbers.Contains(d.No))
+            .ToListAsync(HttpContext.RequestAborted);
+        _logger.LogWarning($"order count: {orders.Count}");
+
+        var workflowIds = orders.Select(d => d.WorkflowId).ToList();
+        var workflows = await _workflowRepository.Queryable()
+            .Includes(d => d.Steps, x => x.WorkflowTrace)
+            .Where(d => workflowIds.Contains(d.Id))
+            .ToListAsync(HttpContext.RequestAborted);
 
         //var workflowIds = orders.Select(d => d.WorkflowId).ToList();
         //var workflows = await _workflowRepository.Queryable()
@@ -743,99 +771,112 @@ IRepository<EnforcementOrdersHandler> enforcementOrdersHandlerRepository
         //    .Where(d => workflowIds.Contains(d.Id))
         //    .ToListAsync(HttpContext.RequestAborted);
 
-        //var updateOrders = new List<Order>();
-        //foreach (var order in orders)
-        //{
-        //    var workflow = workflows.First(d => d.Id == order.WorkflowId);
-
-        //    _mapper.Map(workflow, order);
-        //    var now = DateTime.Now;
-        //    var handleDuration = order.StartTime.HasValue
-        //        ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value,
-        //        now, order.ProcessType is EProcessType.Zhiban)
-        //        : 0;
-        //    var fileDuration = order.CenterToOrgTime.HasValue
-        //        ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value,
-        //            now, order.ProcessType is EProcessType.Zhiban)
-        //        : 0;
-        //    var allDuration = order.StartTime.HasValue
-        //        ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value, now,
-        //        order.ProcessType is EProcessType.Zhiban)
-        //        : 0;
-        //    var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
-        //           ? _timeLimitDomainService.CalcWorkTime(order.CreationTime, order.ActualHandleTime.Value,
-        //           order.ProcessType is EProcessType.Zhiban)
-        //           : 0;
-        //    var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
-        //        ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value, order.ActualHandleTime.Value,
-        //        order.ProcessType is EProcessType.Zhiban)
-        //        : 0;
-
-        //    order.File(now, handleDuration, fileDuration, allDuration, creationTimeHandleDurationWorkday, centerToOrgHandleDurationWorkday);
-
-        //    var endStep = workflow.Steps.FirstOrDefault(d => d.StepType == EStepType.End);
-        //    //var endTrace = workflow.Steps.FirstOrDefault(d => d.WorkflowTrace.StepType == EStepType.End)?.WorkflowTrace;
-        //    if (endStep is null)
-        //    {
-        //        _logger.LogWarning($"endStep 为空, orderNo:{order.No}");
-        //        continue;
-        //    }
+        var updateOrders = new List<Order>();
+        foreach (var order in orders)
+        {
+            var workflow = workflows.First(d => d.Id == order.WorkflowId);
 
-        //    var step = workflow.Steps.FirstOrDefault(d => d.Id == endStep.PrevStepId);
-        //    //var trace = workflow.Steps.FirstOrDefault(d => d.WorkflowTrace.Id == endTrace.PrevStepId)?.WorkflowTrace;
-        //    if (step is null)
-        //    {
-        //        _logger.LogWarning($"step 为空, orderNo:{order.No}");
-        //        continue;
-        //    }
+            _mapper.Map(workflow, order);
+            var now = order.FiledTime.Value;//DateTime.Now;
+            var handleDuration = order.StartTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value,
+                now, order.ProcessType is EProcessType.Zhiban)
+                : 0;
+            var fileDuration = order.CenterToOrgTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value,
+                    now, order.ProcessType is EProcessType.Zhiban)
+                : 0;
+            var allDuration = order.StartTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value, now,
+                order.ProcessType is EProcessType.Zhiban)
+                : 0;
+            var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
+                   ? _timeLimitDomainService.CalcWorkTime(order.CreationTime, now,
+                   order.ProcessType is EProcessType.Zhiban)
+                   : 0;
+            var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value, now,
+                order.ProcessType is EProcessType.Zhiban)
+                : 0;
 
-        //    var trace = step.WorkflowTrace;
-        //    order.FileUserId = trace.HandlerId;
-        //    order.FileUserName = trace.HandlerName;
-        //    order.FileUserOrgId = trace.HandlerOrgId;
-        //    order.FileUserOrgName = trace.HandlerOrgName;
-        //    order.FileOpinion = trace.Opinion;
+            //order.File(now, handleDuration, fileDuration, allDuration, creationTimeHandleDurationWorkday, centerToOrgHandleDurationWorkday);
 
-        //    //记录冗余归档数据
-        //    if (workflow.Steps.Any(x => x.BusinessType == Share.Enums.FlowEngine.EBusinessType.Send))
-        //    {
-        //        order.FileUserRole = EFileUserType.Dispatch;
-        //    }
-        //    else
-        //    {
-        //        order.FileUserRole = EFileUserType.Seat;
-        //    }
-        //    if (order.ProcessType == EProcessType.Jiaoban)
-        //    {
-        //        order.FileUserRole = EFileUserType.Org;
-        //    }
+            order.HandleDurationWorkday = handleDuration;
+            order.FileDurationWorkday = fileDuration;
+            order.AllDurationWorkday = allDuration;
+            order.CreationTimeHandleDurationWorkday = creationTimeHandleDurationWorkday;
+            order.CenterToOrgHandleDurationWorkday = centerToOrgHandleDurationWorkday;
 
-        //    //是否已解决
-        //    order.IsResolved = true;//notification.Dto.External == null ? false : notification.Dto.External.IsResolved;
+            //计算实际办结时长
+            order.SetHandleDuration();
+            order.SetFileDuration();
+            order.SetAllDuration();
+            order.SetCreationTimeHandleDurationWorkday();
+            order.SetCenterToOrgHandleDurationWorkday();
 
-        //    //await _orderRepository.UpdateAsync(order, cancellationToken);
-        //    updateOrders.Add(order);
+            var endStep = workflow.Steps.FirstOrDefault(d => d.StepType == EStepType.End);
+            //var endTrace = workflow.Steps.FirstOrDefault(d => d.WorkflowTrace.StepType == EStepType.End)?.WorkflowTrace;
+            if (endStep is null)
+            {
+                _logger.LogWarning($"endStep 为空, orderNo:{order.No}");
+                continue;
+            }
 
-        //    //var callRecord = await _trCallRecordRepository.GetAsync(p => p.CallAccept == order.CallId, cancellationToken); //由CallAccept改为OtherAccept
-        //    var orderFlowDto = new OrderFlowDto
-        //    {
-        //        Order = _mapper.Map<OrderDto>(order),
-        //        WorkflowTrace = _mapper.Map<WorkflowTraceDto>(trace)
-        //    };
-        //    var callRecord = await _trCallRecordRepository.GetAsync(p => p.OtherAccept == order.CallId, HttpContext.RequestAborted);
-        //    if (callRecord != null)
-        //    {
-        //        orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
-        //    }
-        //    //这里需要判断是否是警情退回
-        //    orderFlowDto.IsNonPoliceReturn = false;//notification.Dto.External == null ? false : notification.Dto.External.IsPoliceReturn;
-        //    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: HttpContext.RequestAborted);
-        //    //写入质检  针对受理之后直接结束的工单
-        //    await _qualityApplication.AddQualityAsync(EQualitySource.Accepted, order.Id, HttpContext.RequestAborted);
-
-        //    //司法行政监督管理-工单处理
-        //    await _enforcementApplication.AddEnforcementOrderAsync(order, HttpContext.RequestAborted);
-        //}
+            var step = workflow.Steps.FirstOrDefault(d => d.Id == endStep.PrevStepId);
+            //var trace = workflow.Steps.FirstOrDefault(d => d.WorkflowTrace.Id == endTrace.PrevStepId)?.WorkflowTrace;
+            if (step is null)
+            {
+                _logger.LogWarning($"step 为空, orderNo:{order.No}");
+                continue;
+            }
+
+            var trace = step.WorkflowTrace;
+            order.FileUserId = trace.HandlerId;
+            order.FileUserName = trace.HandlerName;
+            order.FileUserOrgId = trace.HandlerOrgId;
+            order.FileUserOrgName = trace.HandlerOrgName;
+            order.FileOpinion = trace.Opinion;
+
+            //记录冗余归档数据
+            if (workflow.Steps.Any(x => x.BusinessType == Share.Enums.FlowEngine.EBusinessType.Send))
+            {
+                order.FileUserRole = EFileUserType.Dispatch;
+            }
+            else
+            {
+                order.FileUserRole = EFileUserType.Seat;
+            }
+            if (order.ProcessType == EProcessType.Jiaoban)
+            {
+                order.FileUserRole = EFileUserType.Org;
+            }
+
+            ////是否已解决
+            //order.IsResolved = true;//notification.Dto.External == null ? false : notification.Dto.External.IsResolved;
+
+            //await _orderRepository.UpdateAsync(order, cancellationToken);
+            updateOrders.Add(order);
+
+            //var callRecord = await _trCallRecordRepository.GetAsync(p => p.CallAccept == order.CallId, cancellationToken); //由CallAccept改为OtherAccept
+            var orderFlowDto = new OrderFlowDto
+            {
+                Order = _mapper.Map<OrderDto>(order),
+                WorkflowTrace = _mapper.Map<WorkflowTraceDto>(trace)
+            };
+            var callRecord = await _trCallRecordRepository.GetAsync(p => p.OtherAccept == order.CallId, HttpContext.RequestAborted);
+            if (callRecord != null)
+            {
+                orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
+            }
+            //这里需要判断是否是警情退回
+            orderFlowDto.IsNonPoliceReturn = false;//notification.Dto.External == null ? false : notification.Dto.External.IsPoliceReturn;
+            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: HttpContext.RequestAborted);
+            //写入质检  针对受理之后直接结束的工单
+            await _qualityApplication.AddQualityAsync(EQualitySource.Accepted, order.Id, HttpContext.RequestAborted);
+
+            //司法行政监督管理-工单处理
+            //await _enforcementApplication.AddEnforcementOrderAsync(order, HttpContext.RequestAborted);
+        }
 
         //_logger.LogWarning($"更新orders:{updateOrders.Count}");
         //await _orderRepository.UpdateRangeAsync(updateOrders, HttpContext.RequestAborted);

+ 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) //会签类型
         ;
 

+ 5 - 0
src/Hotline.Application/CallCenter/TianRunCallApplication.cs

@@ -83,6 +83,11 @@ namespace Hotline.Application.CallCenter
         public override Task SingOutAsync(string telNo, CancellationToken cancellationToken) =>
             _telApplication.SignOutByTelNoAsync(telNo, cancellationToken);
 
+        public override async Task<string> GetOrSetCallIdAsync(string callNo, CancellationToken cancellationToken)
+        {
+            return await Task.FromResult(callNo);
+        }
+
         /// <summary>
         /// 查询当前用户的分机状态
         /// </summary>

+ 2 - 2
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -168,11 +168,11 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
                 var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
-                    ? _timeLimitDomainService.CalcWorkTime(order.CreationTime, order.ActualHandleTime.Value,
+                    ? _timeLimitDomainService.CalcWorkTimeEx(order.CreationTime, now,
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
                 var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
-                    ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value, order.ActualHandleTime.Value,
+                    ? _timeLimitDomainService.CalcWorkTimeEx(order.CenterToOrgTime.Value, now,
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
 

+ 39 - 4
src/Hotline.Application/Handlers/FlowEngine/WorkflowRecallHandler.cs

@@ -11,8 +11,10 @@ using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using MapsterMapper;
 using MediatR;
+using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using XF.Domain.Constants;
+using XF.Domain.Repository;
 
 namespace Hotline.Application.Handlers.FlowEngine;
 
@@ -26,14 +28,22 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
     private readonly ICapPublisher _capPublisher;
     private readonly IMapper _mapper;
     private readonly ILogger<WorkflowRecallHandler> _logger;
+    private readonly IRepository<OrderPublish> _orderPublishRepository;
+    private readonly IRepository<OrderVisit> _orderVisitRepository;
+    private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
+    private readonly IRepository<OrderPublishHistory> _orderPublishHistoryRepository;
 
-    public WorkflowRecallHandler(
+	public WorkflowRecallHandler(
         IOrderDomainService orderDomainService,
         IOrderRepository orderRepository,
         IWorkflowDomainService workflowDomainService,
         ITimeLimitDomainService timeLimitDomainService,
         ISystemSettingCacheManager systemSettingCacheManager,
-        ICapPublisher capPublisher,
+        IRepository<OrderPublish> orderPublishRepository,
+        IRepository<OrderVisit> orderVisitRepository,
+        IRepository<OrderVisitDetail> orderVisitedDetailRepository,
+        IRepository<OrderPublishHistory> orderPublishHistoryRepository,
+		ICapPublisher capPublisher,
         IMapper mapper,
         ILogger<WorkflowRecallHandler> logger)
     {
@@ -43,7 +53,11 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
         _timeLimitDomainService = timeLimitDomainService;
         _systemSettingCacheManager = systemSettingCacheManager;
         _capPublisher = capPublisher;
-        _mapper = mapper;
+        _orderPublishRepository = orderPublishRepository;
+        _orderVisitRepository = orderVisitRepository;
+        _orderVisitedDetailRepository = orderVisitedDetailRepository;
+        _orderPublishHistoryRepository = orderPublishHistoryRepository;
+		_mapper = mapper;
         _logger = logger;
     }
 
@@ -89,7 +103,28 @@ public class WorkflowRecallHandler : INotificationHandler<RecallNotify>
 					//}
 				}
                 await _orderRepository.UpdateAsync(order, false, cancellationToken);
-                break;
+                var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == order.Id, cancellationToken);
+                if (publish != null)
+                {
+	                var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+	                publishHistory.OrderPublishId = publish.Id;
+	                publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+	                publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+	                publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+	                publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+	                publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+	                publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+	                await _orderPublishHistoryRepository.AddAsync(publishHistory, cancellationToken);
+	                await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
+                }
+
+                var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == order.Id && x.VisitState != EVisitState.None, cancellationToken);
+                if (visit != null)
+                {
+	                visit.VisitState = EVisitState.None;
+	                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+                }
+				break;
             case WorkflowModuleConsts.KnowledgeAdd:
             case WorkflowModuleConsts.KnowledgeUpdate:
             case WorkflowModuleConsts.KnowledgeDelete:

+ 8 - 7
src/Hotline.Application/JudicialManagement/EnforcementApplication.cs

@@ -264,6 +264,7 @@ namespace Hotline.Application.JudicialManagement
             var areaCode = _sessionContext.OrgAreaCode ?? "511500";
 
             return _judicialManagementOrdersRepository.Queryable()
+                .Where(d => d.IsItCounted == true)
                     .WhereIF(areaCode != "511500", d => d.AreaCode.StartsWith(areaCode))
                     .WhereIF(dto.IsEnforcementOrder.HasValue, d => d.IsEnforcementOrder == dto.IsEnforcementOrder)//是否行政执法类
                     .WhereIF(dto.IsPassTheBuckOrder.HasValue, d => d.IsPassTheBuckOrder == dto.IsPassTheBuckOrder)//是否推诿
@@ -302,7 +303,7 @@ namespace Hotline.Application.JudicialManagement
                 areCodeText = dto.AreaCode;
 
             return _judicialManagementOrdersRepository.Queryable()
-            .Where(d => d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime && d.EventTypeId != null)
+            .Where(d =>d.IsItCounted==true&& d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime && d.EventTypeId != null)
             .WhereIF(!string.IsNullOrEmpty(dto.EventTypeId), d => d.EventTypeId.StartsWith(dto.EventTypeId))
             .WhereIF(!string.IsNullOrEmpty(areCodeText), d => d.AreaCode.StartsWith(areCodeText))
             .OrderByDescending(d => d.CreationTime)
@@ -319,7 +320,7 @@ namespace Hotline.Application.JudicialManagement
         {
             return _enforcementOrdersHandlerRepository.Queryable()
                    .LeftJoin<JudicialManagementOrders>((h, o) => h.OrderId == o.Id)
-                   .Where((h, o) => o.CreationTime >= StartTime && o.CreationTime <= EndTime)
+                   .Where((h, o) => o.CreationTime >= StartTime && o.CreationTime <= EndTime&&o.IsItCounted==true)
                     .GroupBy((h, o) => new
                     {
                         OrgCode = h.OrgCode,
@@ -346,7 +347,7 @@ namespace Hotline.Application.JudicialManagement
         {
             return _enforcementOrdersHandlerRepository.Queryable()
                  .LeftJoin<JudicialManagementOrders>((x, o) => x.OrderId == o.Id)
-                 .Where((x, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null)
+                 .Where((x, o) => o.CreationTime >= dto.StartTime && o.CreationTime <= dto.EndTime && o.Id != null&&o.IsItCounted==true)
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode == "001", (x, o) => x.OrgCode == dto.OrgCode)
                  .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode != "001", (x, o) => x.OrgCode.StartsWith(dto.OrgCode))
                  .WhereIF(dto.TheClueIsTrue == true, (x, o) => o.IsTheClueTrue == true)
@@ -397,7 +398,7 @@ namespace Hotline.Application.JudicialManagement
         {
             var areaCode = _sessionContext.OrgAreaCode ?? "511500";
             return _judicialManagementOrdersRepository.Queryable()
-                .Where(x => x.CreationTime >= StartTime && x.CreationTime <= EndTime)
+                .Where(x => x.CreationTime >= StartTime && x.CreationTime <= EndTime&&x.IsItCounted==true)
                 .LeftJoin<SystemArea>((x, o) => x.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == o.Id)
                 .WhereIF(areaCode != "511500", (x, o) => x.AreaCode.StartsWith(areaCode))
                 .GroupBy((x, o) => new
@@ -427,7 +428,7 @@ namespace Hotline.Application.JudicialManagement
         public ISugarQueryable<JudicialManagementOrders> GetRegionalClassificationStatisticsOrderListAsync(QueryRegionalClassificationStatisticsDto dto)
         {
             return _judicialManagementOrdersRepository.Queryable()
-            .Where(d => d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime)
+            .Where(d => d.CreationTime >= dto.StartTime && d.CreationTime <= dto.EndTime && d.IsItCounted == true)
             .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode.StartsWith(dto.AreaCode))
             .WhereIF(dto.TheClueIsTrue == true, d => d.IsTheClueTrue == true)
             .WhereIF(dto.TheClueIsNotTrue == true, d => d.IsTheClueTrue == false)
@@ -451,7 +452,7 @@ namespace Hotline.Application.JudicialManagement
             return _judicialManagementOrdersRepository.Queryable()
                  .LeftJoin<OrderVisit>((x, o) => x.Id == o.OrderId)
                  .LeftJoin<OrderVisitDetail>((x, o, p) => o.Id == p.VisitId)
-                .Where((x, o, p) => o.VisitTime >= StartTime && o.VisitTime <= EndTime && p.VisitTarget == EVisitTarget.Org
+                .Where((x, o, p) => o.VisitTime >= StartTime && o.VisitTime <= EndTime&&x.IsItCounted==true && p.VisitTarget == EVisitTarget.Org
                 && o.VisitState == EVisitState.Visited && !string.IsNullOrEmpty(p.VisitOrgCode) && x.OrderSoure == EOrderSoure.Hotline)
                 .GroupBy((x, o, p) => new
                 {
@@ -499,7 +500,7 @@ namespace Hotline.Application.JudicialManagement
             return _judicialManagementOrdersRepository.Queryable()
                 .LeftJoin<OrderVisit>((x, o) => x.Id == o.OrderId)
                 .LeftJoin<OrderVisitDetail>((x, o, p) => o.Id == p.VisitId)
-                .Where((x, o, p) => o.VisitTime >= dto.StartTime && o.VisitTime <= dto.EndTime && p.VisitTarget == EVisitTarget.Org && x.OrderSoure == EOrderSoure.Hotline)
+                .Where((x, o, p) => o.VisitTime >= dto.StartTime && o.VisitTime <= dto.EndTime&&x.IsItCounted==true && p.VisitTarget == EVisitTarget.Org && x.OrderSoure == EOrderSoure.Hotline)
                 .Where((x, o, p) => o.VisitState == EVisitState.Visited && !string.IsNullOrEmpty(p.VisitOrgCode))
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode == "001", (x, o, p) => p.VisitOrgCode == dto.OrgCode)
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgCode) && dto.OrgCode != "001", (x, o, p) => p.VisitOrgCode.StartsWith(dto.OrgCode))

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

+ 179 - 115
src/Hotline.Application/Orders/OrderApplication.cs

@@ -41,6 +41,7 @@ using Hotline.Users;
 using PanGu.Match;
 using Hotline.Settings.Hotspots;
 using Hotline.Share.Enums.FlowEngine;
+using Hotline.Authentications;
 
 namespace Hotline.Application.Orders;
 
@@ -193,11 +194,11 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 order.ProcessType is EProcessType.Zhiban)
             : 0;
         var creationTimeHandleDurationWorkday = order.ActualHandleTime.HasValue
-                    ? _timeLimitDomainService.CalcWorkTime(order.CreationTime, order.ActualHandleTime.Value,
+                    ? _timeLimitDomainService.CalcWorkTime(order.CreationTime, now,
                     order.ProcessType is EProcessType.Zhiban)
                     : 0;
         var centerToOrgHandleDurationWorkday = order.ActualHandleTime.HasValue && order.CenterToOrgTime.HasValue
-            ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value, order.ActualHandleTime.Value,
+            ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value, now,
             order.ProcessType is EProcessType.Zhiban)
             : 0;
 
@@ -370,6 +371,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// </summary>
     public Task<AddOrderResponse> ReceiveOrderFromExternalAsync(AddOrderDto dto, ISessionContext current, CancellationToken cancellationToken)
     {
+
         switch (dto.Source)
         {
             case ESource.ProvinceStraight:
@@ -494,24 +496,28 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!)) //标题
             .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo == dto.ProvinceNo) //省本地编号
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No) //工单编码
-                                                                         //.WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!))
-            .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
-            .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
-            .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptType == dto.AcceptType)//受理类型
+                                                                                                //.WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannel == dto.Channel)
+            //.WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
+            //.WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
             .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone == dto.TransferPhone!) //转接号码
                                                                                                            //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
-            .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
+                                                                                                           //.WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgName), d => d.CurrentHandleOrgName == dto.OrgName)//接办部门
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName == dto.NameOrNo! || d.AcceptorStaffNo == dto.NameOrNo!) //受理人/坐席
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-            .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
+                                                                                               //.WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))  //紧急程度
             .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone == dto.FromPhone) //来电号码
             .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact == dto.PhoneNo!) //联系电话
             .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
             .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
-            .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
-            .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
+                                                                                            //.WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))  //工单状态
+            .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)//工单状态
+                                                                      //.WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName == dto.ActualHandlerName) //接办人
             .WhereIF(dto.IsScreen == true, d => d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //有甄别
             .WhereIF(dto.IsScreen == false, d => !d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //无甄别
@@ -522,7 +528,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(dto.IsOverTime == false, d => (d.ExpiredTime > DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime > d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //否 超期
             .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
             .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName == dto.FromName) //来电人姓名
-            .WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
+                                                                                           //.WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)//区域
             .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, d => d.Source == ESource.ProvinceStraight)
             .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, d => d.Source != ESource.ProvinceStraight)
             .WhereIF(!string.IsNullOrEmpty(dto.SensitiveWord), d => SqlFunc.JsonArrayAny(d.Sensitive, dto.SensitiveWord))
@@ -572,7 +579,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return _orderRepository.Queryable()
             .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
             .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
-            .WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 1, x => x.IdentityType == EIdentityType.Citizen)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 2, x => x.IdentityType == EIdentityType.Enterprise)
             .Where(d => d.SourceChannel != null && d.SourceChannel != "");
     }
 
@@ -587,7 +595,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return _orderRepository.Queryable()
             .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), d => d.SourceChannel == dto.SourceChannel)
             .WhereIF(dto.Time.HasValue, d => d.CreationTime.ToString("yyyy-MM-dd") == dto.Time.Value.ToString("yyyy-MM-dd"))
-            .WhereIF(dto.IdentityType.HasValue, d => d.IdentityType == dto.IdentityType)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 1, x => x.IdentityType == EIdentityType.Citizen)
+                .WhereIF(dto.TypeId != null && dto.TypeId == 2, x => x.IdentityType == EIdentityType.Enterprise)
             .Where(d => d.SourceChannel != null && d.SourceChannel != "");
     }
 
@@ -631,11 +640,14 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 CounterNoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status != Share.Enums.FlowEngine.EWorkflowStepStatus.Handled && x.StepExpiredTime < SqlFunc.GetDate(), 1, 0)),
             }).MergeTable();
 
-        var query = queryOrder.LeftJoin(queryCountersign, (or, co) => or.OrgId == co.OrgId)
+        var query =
+            _systemOrganizeRepository.Queryable()
+            .LeftJoin(queryOrder, (x, or) => x.Id == or.OrgId)
+            .LeftJoin(queryCountersign, (x, or, co) => x.Id == co.OrgId)
             //.LeftJoin<SystemOrganize>((or, co, so) => or.OrgId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == so.Id)
-            .LeftJoin<SystemOrganize>((or, co, so) => or.OrgId == so.Id && so.Level == 1)
-            .GroupBy((or, co, so) => new { so.Id, so.Name })
-            .Select((or, co, so) => new OrderBiOrgDataListVo
+            .LeftJoin<SystemOrganize>((x, or, co, so) => or.OrgId == so.Id && so.Level == 1)
+            .GroupBy((x, or, co, so) => new { so.Id, so.Name })
+            .Select((x, or, co, so) => new OrderBiOrgDataListVo
             {
                 OrgName = so.Name,
                 OrgId = so.Id,
@@ -645,7 +657,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 CounterNoHandlerExtendedNum = SqlFunc.AggregateSum(co.CounterNoHandlerExtendedNum)
             }).MergeTable();
 
-        query = query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrgName.Contains(dto.Keyword!)).Where(x => x.HandlerExtendedNum > 0 || x.NoHandlerExtendedNum > 0 || x.CounterHandlerExtendedNum > 0 || x.CounterNoHandlerExtendedNum > 0);
+        query = query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrgName.Contains(dto.Keyword!))
+            .Where(x => x.OrgName != null).Where(x => x.HandlerExtendedNum > 0 || x.NoHandlerExtendedNum > 0 || x.CounterHandlerExtendedNum > 0 || x.CounterNoHandlerExtendedNum > 0);
         switch (dto.SortField)
         {
             case "handlerExtendedNum":
@@ -727,10 +740,12 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         var queryCountersign = _workflowStepRepository.Queryable()
             .Includes(x => x.Workflow)
             .InnerJoin<SystemOrganize>((x, so) => x.HandlerOrgId == so.Id && so.Level == 1)
+            .LeftJoin<Order>((x, so, o) => x.ExternalId == o.Id)
             .Where((x, so) => x.CountersignPosition != ECountersignPosition.None && x.Workflow.ModuleCode == "OrderHandle")
             .Where((x, so) => x.CreationTime >= dto.StartTime && x.CreationTime <= dto.EndTime)
             .Where((x, so) => (x.Status == Share.Enums.FlowEngine.EWorkflowStepStatus.Handled && x.StepExpiredTime < x.HandleTime) || (x.Status != Share.Enums.FlowEngine.EWorkflowStepStatus.Handled && x.StepExpiredTime < SqlFunc.GetDate()))
             .WhereIF(IsCenter == false, (x, so) => x.HandlerOrgId == _sessionContext.RequiredOrgId)
+            .WhereIF(dto.ExpiredType is 2, (x, so, o) => o.OrderDelays.Any(x => x.DelayState == EDelayState.Pass))
             .GroupBy(x => new { x.ExternalId, x.HandlerOrgName })
             .Select(x => new { Id = x.ExternalId, WorkflowId = x.ExternalId, HandlerOrgName = x.HandlerOrgName });
 
@@ -772,7 +787,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<OrderSpecialDetail> QueryOrderSourceDetail(QueryOrderReTransactDetailRequest dto)
     {
-
+        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
+            throw UserFriendlyException.SameMessage("请选择时间!");
+        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
         return _orderSpecialDetailRepository.Queryable()
             .Includes(x => x.OrderSpecial, s => s.Order)
             .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.OrgName.Contains(dto.OrgName!))
@@ -1011,7 +1028,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                AreaCode = pp.Id,
                AreaName = pp.AreaName,
                Count = SqlFunc.AggregateSum(dd.Count)
-           }).Where(q => q.HotspotName != "").ToPivotListAsync(q => q.AreaCode, q => new { q.HotspotName, q.HotspotId }, q => q.Sum(x => x.Count));
+           }).ToPivotListAsync(q => q.AreaCode, q => new { q.HotspotName, q.HotspotId }, q => q.Sum(x => x.Count));
 
         var areaTitleList = await _systemAreaRepository.Queryable().Where(x => SqlFunc.Length(x.Id) == 6 && x.Id != "510000").OrderBy(x => x.Id).ToListAsync();
         return (areaTitleList, returnList);
@@ -1080,7 +1097,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                AreaCode = pp.Id,
                AreaName = pp.AreaName,
                Count = SqlFunc.AggregateSum(dd.Count)
-           }).Where(q => q.HotspotName != "").ToPivotTableAsync(q => q.AreaName, q => new { q.HotspotName }, q => q.Sum(x => x.Count));
+           }).ToPivotTableAsync(q => q.AreaName, q => new { q.HotspotName }, q => q.Sum(x => x.Count));
+        //returnList.Rows.RemoveAt(returnList.Rows.Count-1);
         return returnList;
     }
 
@@ -1153,7 +1171,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             }
             else
             {
-                if (dt.Columns.Contains(item))
+                //if (dt.Columns.Contains(item))
                     dt2.Columns.Add(item);
             }
         }
@@ -1161,6 +1179,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         //处理数据
         foreach (DataRow sourceRow in dt.Rows)
         {
+            if (sourceRow["一级热点"].ToString() == "")
+            {
+                continue;
+            }
             DataRow targetRow = dt2.NewRow();
             foreach (var item in AddColumnName)
             {
@@ -1221,7 +1243,14 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 }
                 else
                 {
-                    targetRow[item] = sourceRow[item];
+                    try
+                    {
+                        targetRow[item] = sourceRow[item];
+                    }
+                    catch
+                    {
+                        targetRow[item] = 0;
+                    }
                 }
             }
             dt2.Rows.Add(targetRow);
@@ -1230,98 +1259,126 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return dt2;
     }
 
-	/// <summary>
-	/// 热点类型满意度统计
-	/// </summary>
-	/// <returns></returns>
-	public async Task<List<VisitAndHotspotSatisfactionStatisticsDto>> VisitAndHotspotSatisfactionStatistics(VisitAndHotspotPagedKeywordRequest dto)
-	{
-		dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-
-		bool IsCenter = _sessionContext.OrgIsCenter;
-
-		var data =await _orderVisitDetailRepository.Queryable()
-			.Includes(x => x.OrderVisit, v => v.Order)
-			.InnerJoin<Hotspot>((x, h) => h.Id == x.OrderVisit.Order.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")) && h.ParentId == null)
-			.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.HotspotName) == false, (x, h) => h.HotSpotName == dto.HotspotName)
-			.WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
-            .GroupBy((x,h) => new
-		    {
-			    HotspotId = h.Id,
-			    HotspotName = h.HotSpotName
-			})
-		    .Select((x, h) => new VisitAndHotspotSatisfactionStatisticsDto()
-		    {
-			    HotspotName = h.HotSpotName,
-			    HotspotId = h.Id,
-			    TotalSumCount = SqlFunc.AggregateCount(x.OrderVisit.Order.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2"))),
-			    VerySatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
-			    SatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
-			    RegardedAsSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
-			    DefaultSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
-			    NoSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
-			    NoEvaluateCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
-			    NoPutThroughCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
-		    })
-		    .ToListAsync();
-		return data;
-	}
-
-	/// <summary>
-	/// 热点满意度明细统计
-	/// </summary>
-	/// <param name="dto"></param>
-	/// <returns></returns>
-	public ISugarQueryable<OrderVisitDetail> VisitAndHotspotSatisfactionDetail(VisitAndHotspotPagedKeywordRequest dto)
-	{
-		dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-		bool IsCenter = _sessionContext.OrgIsCenter;
-		var key = string.Empty;
-		if (!string.IsNullOrEmpty(dto.TitleCode))
-		{
-			switch (dto.TitleCode)
-			{
-				case "verySatisfiedCount":
-					key = "5";
-					break;
-				case "satisfiedCount":
-					key = "4";
-					break;
-				case "regardedAsSatisfiedCount":
-					key = "-1";
-					break;
-				case "defaultSatisfiedCount":
-					key = "0";
-					break;
-				case "noSatisfiedCount":
-					key = "2";
-					break;
-				case "noEvaluateCount":
-					key = "7";
-					break;
-				case "noPutThroughCount":
-					key = "6";
-					break;
-			}
-		}
-		return _orderVisitDetailRepository.Queryable()
-			.Includes(x => x.OrderVisit, o => o.Order)
-			.Where(x => x.OrderVisit.VisitTime >= dto.StartTime && x.OrderVisit.VisitTime <= dto.EndTime && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited)
-			.WhereIF(!string.IsNullOrEmpty(dto.HotspotId), x => x.OrderVisit.Order.HotspotId.StartsWith(dto.HotspotId))
-			.WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
-			.WhereIF(dto.TypeId is 1 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == key)
-			.WhereIF(dto.TypeId is 2 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == key);
-	}
-	#region private
-
-	/// <summary>
-	/// 接受外部工单(除省平台)
-	/// </summary>
-	/// <param name="dto"></param>
-	/// <param name="cancellationToken"></param>
-	/// <returns></returns>
-	private async Task<AddOrderResponse> ReceiveOrderFromOtherPlatformAsync(AddOrderDto dto, List<FileDto> files,
+    /// <summary>
+    /// 热点类型满意度统计
+    /// </summary>
+    /// <returns></returns>
+    public async Task<List<VisitAndHotspotSatisfactionStatisticsDto>> VisitAndHotspotSatisfactionStatistics(VisitAndHotspotPagedKeywordRequest dto)
+    {
+        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+
+        bool IsCenter = _sessionContext.OrgIsCenter;
+
+        var list = _orderVisitDetailRepository.Queryable()
+            .Includes(x => x.OrderVisit, v => v.Order)
+            .InnerJoin<Hotspot>((x, h) => h.Id == x.OrderVisit.Order.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")) && h.ParentId == null)
+            .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.HotspotName) == false, (x, h) => h.HotSpotName == dto.HotspotName)
+            .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId));
+
+        var data = new List<VisitAndHotspotSatisfactionStatisticsDto>();
+
+        if (IsCenter && list != null)
+        {
+            data = await list.GroupBy((x, h) => new
+            {
+                HotspotName = h.HotSpotName,
+                HotspotId = h.Id
+            })
+            .Select((x, h) => new VisitAndHotspotSatisfactionStatisticsDto()
+            {
+                HotspotName = h.HotSpotName,
+                HotspotId = h.Id,
+                TotalSumCount = SqlFunc.AggregateCount(x.OrderVisit.Order.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2"))),
+                VerySatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
+                SatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
+                RegardedAsSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
+                DefaultSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
+                NoSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
+                NoEvaluateCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
+                NoPutThroughCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
+            })
+            .ToListAsync();
+        }
+        else
+        {
+            data = await list.GroupBy((x, h) => new
+            {
+                HotspotName = h.HotSpotName,
+                HotspotId = h.Id
+            })
+            .Select((x, h) => new VisitAndHotspotSatisfactionStatisticsDto()
+            {
+                HotspotName = h.HotSpotName,
+                HotspotId = h.Id,
+                TotalSumCount = SqlFunc.AggregateCount(x.OrderVisit.Order.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2"))),
+                VerySatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
+                SatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
+                RegardedAsSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
+                DefaultSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
+                NoSatisfiedCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
+                NoEvaluateCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "7", 1, 0))),//未做评价
+                NoPutThroughCount = SqlFunc.IIF(dto.TypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "6", 1, 0))),//未接通
+            })
+            .ToListAsync();
+        }
+        return data;
+    }
+
+    /// <summary>
+    /// 热点满意度明细统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public ISugarQueryable<OrderVisitDetail> VisitAndHotspotSatisfactionDetail(VisitAndHotspotPagedKeywordRequest dto)
+    {
+        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+        bool IsCenter = _sessionContext.OrgIsCenter;
+        var key = string.Empty;
+        if (!string.IsNullOrEmpty(dto.TitleCode))
+        {
+            switch (dto.TitleCode)
+            {
+                case "verySatisfiedCount":
+                    key = "5";
+                    break;
+                case "satisfiedCount":
+                    key = "4";
+                    break;
+                case "regardedAsSatisfiedCount":
+                    key = "-1";
+                    break;
+                case "defaultSatisfiedCount":
+                    key = "0";
+                    break;
+                case "noSatisfiedCount":
+                    key = "2";
+                    break;
+                case "noEvaluateCount":
+                    key = "7";
+                    break;
+                case "noPutThroughCount":
+                    key = "6";
+                    break;
+            }
+        }
+        return _orderVisitDetailRepository.Queryable()
+            .Includes(x => x.OrderVisit, o => o.Order)
+            .Where(x => x.OrderVisit.VisitTime >= dto.StartTime && x.OrderVisit.VisitTime <= dto.EndTime && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited)
+            .WhereIF(!string.IsNullOrEmpty(dto.HotspotName), x => x.OrderVisit.Order.Hotspot.HotSpotFullName.StartsWith(dto.HotspotName))
+            .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
+            .WhereIF(dto.TypeId is 1, x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == key)
+            .WhereIF(dto.TypeId is 2, x => SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == key);
+    }
+    #region private
+
+    /// <summary>
+    /// 接受外部工单(除省平台)
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    private async Task<AddOrderResponse> ReceiveOrderFromOtherPlatformAsync(AddOrderDto dto, List<FileDto> files,
         ISessionContext current, CancellationToken cancellationToken)
     {
         if (string.IsNullOrEmpty(dto.ExternalId))
@@ -1342,6 +1399,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             _mapper.Map(dto, order);
             if (files != null && files.Any())
                 order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
+            else
+                order.FileJson = new List<Share.Dtos.File.FileJson>();
             await _orderRepository.UpdateAsync(order, cancellationToken);
         }
 
@@ -1381,6 +1440,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             _mapper.Map(dto, order);
             if (files != null && files.Any())
                 order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
+            else
+                order.FileJson = new List<Share.Dtos.File.FileJson>();
             order.ReTransactNum++;
             await _orderRepository.UpdateAsync(order, cancellationToken);
 
@@ -1394,7 +1455,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
 
             //特提(撤回至发起)
             if (!string.IsNullOrEmpty(order.WorkflowId))
+            {
+                current = SessionContextCreator.CreateSessionContext("province");
                 await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, cancellationToken);
+            }
         }
         return _mapper.Map<AddOrderResponse>(order);
     }

+ 1 - 0
src/Hotline.Application/Orders/OrderSendBackAuditApplication.cs

@@ -30,6 +30,7 @@ namespace Hotline.Application.Orders
 				.WhereIF(!string.IsNullOrEmpty(dto.No), d => d.Order.No.Contains(dto.No!))
 				.WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), d => d.Order.AcceptTypeCode == dto.AcceptTypeCode)
 				.WhereIF(!string.IsNullOrEmpty(dto.OrgName), d => d.ApplyOrgName == dto.OrgName)
+				.WhereIF(dto.DataScope is 1 ,d=>d.CreatorId  == _sessionContext.RequiredUserId)
 				.WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime)
 				.WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime)
 				.WhereIF(dto.AuditState == 1, d => d.State == ESendBackAuditState.Apply)

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

+ 3 - 3
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -1814,9 +1814,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) //办结时间开始

+ 25 - 18
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -258,15 +258,17 @@ namespace Hotline.Application.Subscribers
             model.RemindTime = dto.RemindTime;
             model.DsBisId= dto.DsBisId;
 
-            if (!string.IsNullOrEmpty(order.WorkflowId))
-            {
-                var org = await _workflowDomainService.FindActualHandlerAsync(order.WorkflowId, cancellationToken);
-                if (org != null)
-                {
-                    model.OrgId = org.Key;
-                    model.OrgName = org.Value;
-                }
-            }
+            //if (!string.IsNullOrEmpty(order.WorkflowId))
+            //{
+            //    var org = await _workflowDomainService.FindActualHandlerAsync(order.WorkflowId, cancellationToken);
+            //    if (org != null)
+            //    {
+            //        model.OrgId = org.Key;
+            //        model.OrgName = org.Value;
+            //    }
+            //}
+            model.OrgId = order.CurrentHandleOrgId;
+            model.OrgName = order.CurrentHandleOrgName;
 
 
             if (dto.Files.Any())
@@ -298,15 +300,17 @@ namespace Hotline.Application.Subscribers
                 model.OrgId = "001";
                 model.OrgName = "市民热线服务中心";
 
-                if (!string.IsNullOrEmpty(order.WorkflowId))
-                {
-                    var org = await _workflowDomainService.FindActualHandlerAsync(order.WorkflowId, cancellationToken);
-                    if (org != null)
-                    {
-                        model.OrgId = org.Key;
-                        model.OrgName = org.Value;
-                    }
-                }
+                //if (!string.IsNullOrEmpty(order.WorkflowId))
+                //{
+                //    var org = await _workflowDomainService.FindActualHandlerAsync(order.WorkflowId, cancellationToken);
+                //    if (org != null)
+                //    {
+                //        model.OrgId = org.Key;
+                //        model.OrgName = org.Value;
+                //    }
+                //}
+                model.OrgId = order.CurrentHandleOrgId;
+                model.OrgName = order.CurrentHandleOrgName;
 
                 await _orderUrgeRepository.AddAsync(model, cancellationToken);
 
@@ -351,6 +355,9 @@ namespace Hotline.Application.Subscribers
             model.Province = true;
             model.ApplyContent = dto.ProvinceOrderSuperviseDto.SuperviseContent;
             model.SuperviseSerial = dto.ProvinceOrderSuperviseDto.SuperviseSerial;
+            model.SuperviseTitle = dto.ProvinceOrderSuperviseDto.SuperviseTitle;
+            model.SuperviseTime = dto.ProvinceOrderSuperviseDto.SuperviseTime;
+            model.SuperviseType = dto.ProvinceOrderSuperviseDto.SuperviseType;
             if (dto.Files.Any())
                 model.FileJson =
                     await _fileRepository.AddFileAsync(dto.Files, model.Id, "", 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)
         {
             //计算小时差

+ 1 - 1
src/Hotline.Repository.SqlSugar/File/FileRepository.cs

@@ -44,7 +44,7 @@ namespace Hotline.Repository.SqlSugar.File
 				newFiles.Add(model);
 			}
 			await AddRangeAsync(newFiles, cancellationToken);
-			return newFiles.Select(x=> new FileJson { Id = x.Id,FileId = x.Additions,Path = x.Path}).ToList();
+			return newFiles.Select(x=> new FileJson { Id = x.Id,FileId = x.Additions,Path = x.Path,FileName =x.Name ,FileType =x.Type}).ToList();
 		}
 
 		public async Task<List<FileDto>> GetFilesAsync(List<string> ids, CancellationToken cancellationToken) 

+ 134 - 117
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -164,7 +164,7 @@ namespace Hotline.Repository.SqlSugar.Orders
 
         }
 
-        public  ISugarQueryable<T> UnionAll<T>(params ISugarQueryable<T>[] queryables) where T : class
+        public ISugarQueryable<T> UnionAll<T>(params ISugarQueryable<T>[] queryables) where T : class
         {
             return Db.UnionAll(queryables);
         }
@@ -187,8 +187,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<object> OrderAreaTime(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new List<int>();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new List<int>();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -197,7 +197,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
@@ -240,8 +241,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<DataTable> OrderAreaTimeExport(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -250,7 +251,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                   .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      AreaCode = p.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
@@ -293,8 +295,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<object> OrderHotspotTime(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new List<int>();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new List<int>();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -303,7 +305,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                  .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      HotspotCode = p.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
@@ -346,8 +349,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<DataTable> OrderHotspotTimeExport(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -356,7 +359,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                  .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      HotspotCode = p.HotspotId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
@@ -399,8 +403,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<object> OrderAcceptanceTime(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new List<int>();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new List<int>();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -409,7 +413,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                  .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      AcceptTypeCode = p.AcceptTypeCode,
@@ -452,9 +457,9 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<DataTable> OrderAcceptanceTimeExport(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
 
-			List<int> dts = new();
+            List<int> dts = new();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -463,7 +468,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                   .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      AcceptTypeCode = p.AcceptTypeCode,
@@ -506,8 +512,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<object> OrderSourceTime(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new List<int>();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new List<int>();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -516,7 +522,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                  .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      SourceChannelCode = p.SourceChannelCode,
@@ -527,7 +534,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listOrg = Db.Queryable<SystemDicData>()
               .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
               .Where((s, p) => s.DicTypeCode == "SourceChannel")
-              .GroupBy((s, p) => new {
+              .GroupBy((s, p) => new
+              {
                   DicDataValue = s.DicDataValue,
                   DicDataName = s.DicDataName,
                   Hour = p.Hour,
@@ -562,8 +570,8 @@ namespace Hotline.Repository.SqlSugar.Orders
         /// <returns></returns>
         public async Task<DataTable> OrderSourceTimeExport(TimeSharingPagedKeywordRequest dto)
         {
-	        dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			List<int> dts = new();
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            List<int> dts = new();
             for (int i = 0; i < 24; i++)
             {
                 dts.Add(i);
@@ -572,7 +580,8 @@ namespace Hotline.Repository.SqlSugar.Orders
             var listHour = Db.Reportable(dts).ToQueryable<int>();
             var listOrder = Db.Queryable<Order>()
                  .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-                 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
+                  .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
                  .Select(p => new
                  {
                      SourceChannelCode = p.SourceChannelCode,
@@ -607,87 +616,89 @@ namespace Hotline.Repository.SqlSugar.Orders
             return InitDatatTable(dt, dto.AddColumnName);
         }
 
-		/// <summary>
-		/// 信件来源统计
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		public async Task<object> OrderSource(QueryOrderSourceRequest dto)
-		{
-			dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			var listOrder = Db.Queryable<Order>()
-				 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-				 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
-				 .Select(p => new
-				 {
-					 SourceChannelCode = p.SourceChannelCode,
-					 Hour = p.CreationTime.ToString("yyyy-MM-dd")
-				 })
-			   .MergeTable();
-
-			var listOrg = await Db.Queryable<SystemDicData>()
-			  .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
-			  .Where((s, p) => s.DicTypeCode == "SourceChannel")
-			  .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
-			  .GroupBy((s, p) => p.Hour)
-			  .OrderBy((s, p) => p.Hour)
-			  .Select((s, p) => new
-			  {
-				  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
-				  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
-				  DicDataValue = s.DicDataValue,
-				  DicDataName = s.DicDataName
-			  })
-			  .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
-			return listOrg;
-
-		}
-
-		/// <summary>
-		/// 信件来源统计---导出
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		public async Task<DataTable> OrderSourceExport(QueryOrderSourceRequest dto)
-		{
-			dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
-			var listOrder = Db.Queryable<Order>()
-				 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
-				 .WhereIF(dto.IdentityType != null, p => p.IdentityType == dto.IdentityType)
-				 .Select(p => new
-				 {
-					 SourceChannelCode = p.SourceChannelCode,
-					 Hour = p.CreationTime.ToString("yyyy-MM-dd")
-				 })
-			   .MergeTable();
-
-			var listOrg = await Db.Queryable<SystemDicData>()
-			  .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
-			  .Where((s, p) => s.DicTypeCode == "SourceChannel")
-			  .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
-			  .GroupBy((s, p) => p.Hour)
-			  .OrderBy((s, p) => p.Hour)
-			  .Select((s, p) => new
-			  {
-				  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
-				  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
-				  DicDataValue = s.DicDataValue,
-				  DicDataName = s.DicDataName
-			  })
-			  .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
-				listOrg.Columns["Hour"].ColumnName = "日期";
-				if (listOrg.Rows[0][listOrg.Rows.Count - 1] == "0")
-				    listOrg.Rows[listOrg.Rows.Count - 1].Delete();
-			return InitDatatTable(listOrg, dto.AddColumnName);
-		}
-
-		/// <summary>
-		/// 处理导出数据
-		/// </summary>
-		/// <param name="dt"></param>
-		/// <param name="AddColumnName"></param>
-		/// <returns></returns>
-		public DataTable InitDatatTable(DataTable dt, List<string> AddColumnName)
+        /// <summary>
+        /// 信件来源统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<object> OrderSource(QueryOrderSourceRequest dto)
+        {
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
+                 .Select(p => new
+                 {
+                     SourceChannelCode = p.SourceChannelCode,
+                     Hour = p.CreationTime.ToString("yyyy-MM-dd")
+                 })
+               .MergeTable();
+
+            var listOrg = await Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+              .Where((s, p) => s.DicTypeCode == "SourceChannel")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => p.Hour)
+              .Select((s, p) => new
+              {
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  DicDataName = s.DicDataName
+              })
+              .ToPivotListAsync(p => p.DicDataValue, p => p.Hour, p => p.Sum(x => x.count));
+            return listOrg;
+
+        }
+
+        /// <summary>
+        /// 信件来源统计---导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public async Task<DataTable> OrderSourceExport(QueryOrderSourceRequest dto)
+        {
+            dto.EndTime = dto.EndTime.Value.AddDays(1).AddSeconds(-1);
+            var listOrder = Db.Queryable<Order>()
+                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 1, p => p.IdentityType == EIdentityType.Citizen)
+                 .WhereIF(dto.TypeId != null && dto.TypeId == 2, p => p.IdentityType == EIdentityType.Enterprise)
+                 .Select(p => new
+                 {
+                     SourceChannelCode = p.SourceChannelCode,
+                     Hour = p.CreationTime.ToString("yyyy-MM-dd")
+                 })
+               .MergeTable();
+
+            var listOrg = await Db.Queryable<SystemDicData>()
+              .LeftJoin(listOrder, (s, p) => s.DicDataValue == p.SourceChannelCode)
+              .Where((s, p) => s.DicTypeCode == "SourceChannel")
+              .GroupBy((s, p) => s.DicDataValue).GroupBy((s, p) => s.DicDataName)
+              .GroupBy((s, p) => p.Hour)
+              .OrderBy((s, p) => p.Hour)
+              .Select((s, p) => new
+              {
+                  Hour = SqlFunc.IIF(p.Hour == null || p.Hour == "", "0", p.Hour),
+                  count = SqlFunc.AggregateSum(SqlFunc.IIF(p.SourceChannelCode != null && p.SourceChannelCode != "", 1, 0)),
+                  DicDataValue = s.DicDataValue,
+                  DicDataName = s.DicDataName
+              })
+              .ToPivotTableAsync(p => p.DicDataName, p => p.Hour, p => p.Sum(x => x.count));
+            listOrg.Columns["Hour"].ColumnName = "日期";
+            if (listOrg.Rows[0][listOrg.Rows.Count - 1] == "0")
+                listOrg.Rows[listOrg.Rows.Count - 1].Delete();
+            return InitDatatTable(listOrg, dto.AddColumnName);
+        }
+
+        /// <summary>
+        /// 处理导出数据
+        /// </summary>
+        /// <param name="dt"></param>
+        /// <param name="AddColumnName"></param>
+        /// <returns></returns>
+        public DataTable InitDatatTable(DataTable dt, List<string> AddColumnName)
         {
             //修改列名
             if (dt.Columns.Contains("Hour"))
@@ -768,7 +779,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                     ActualHandleStepName = x.ActualHandleStepName,
                     ReTransactNum = x.ReTransactNum,
                     IsUrgent = x.IsUrgent,
-                    OrderScreenStatus  = SqlFunc.Subqueryable<OrderScreen>().Where(d=>d.OrderId==x.Id).OrderByDesc(d=>d.CreationTime).Select(d=>d.Status),
+                    OrderScreenStatus = SqlFunc.Subqueryable<OrderScreen>().Where(d => d.OrderId == x.Id).OrderByDesc(d => d.CreationTime).Select(d => d.Status),
                     No = x.No,
                     CreationTime = x.CreationTime,
                     Title = x.Title,
@@ -795,10 +806,10 @@ namespace Hotline.Repository.SqlSugar.Orders
             string Date = dto.Date.ToString("yyyy-MM-dd");
             var query = Db.Queryable<Order>()
                //.Includes(x => x.OrderScreens.OrderByDescending(x => x.CreationTime).FirstOrDefault())
-               .Where(x => x.AcceptTypeCode == dto.AcceptTypeCode && x.CreationTime.ToString("yyyy-MM-dd") == Date )
+               .Where(x => x.AcceptTypeCode == dto.AcceptTypeCode && x.CreationTime.ToString("yyyy-MM-dd") == Date)
                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
-               .WhereIF(!string.IsNullOrEmpty(dto.Title),x=>x.Title.Contains(dto.Title))
-               .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName),x=>x.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
+               .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title))
+               .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
                .Select(x => new HotspotAndAreaStatisticsDetailDto
                {
                    Id = x.Id,
@@ -861,7 +872,7 @@ namespace Hotline.Repository.SqlSugar.Orders
 
             //时间关联工单
             var dateAndOrderList = dateQuery.LeftJoin(orderList, (it, o) => it.ColumnName == o.Date)
-                .Where((it,o)=> string.IsNullOrEmpty(o.AcceptTypeCode) == false)
+                .Where((it, o) => string.IsNullOrEmpty(o.AcceptTypeCode) == false)
                 .GroupBy((it, o) => new
                 {
                     it.ColumnName,
@@ -875,7 +886,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                 }).MergeTable();
             //类型关联工单
             var returnList = await acceptTypeList.LeftJoin(dateAndOrderList, (it, o) => it.DicDataValue == o.AcceptTypeCode)
-                .Where((it,o)=> o.Date!=null)
+                .Where((it, o) => o.Date != null)
                 .GroupBy((it, o) => new
                 {
                     o.Date,
@@ -891,7 +902,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                 .ToPivotListAsync(q => q.AcceptTypeCode, q => new { q.Date }, q => q.Sum(x => x.Count));
 
             //表头
-            var acceptTypeTitleList =await Db.Queryable<SystemDicData>().Where(x => x.DicTypeCode == SysDicTypeConsts.AcceptType).ToListAsync();
+            var acceptTypeTitleList = await Db.Queryable<SystemDicData>().Where(x => x.DicTypeCode == SysDicTypeConsts.AcceptType).ToListAsync();
             return (acceptTypeTitleList, returnList);
         }
 
@@ -1010,8 +1021,7 @@ namespace Hotline.Repository.SqlSugar.Orders
             //添加表头
             foreach (var item in AddColumnName)
             {
-                if (dt.Columns.Contains(item))
-                    dt2.Columns.Add(item);
+                dt2.Columns.Add(item);
             }
 
             //处理数据
@@ -1020,7 +1030,14 @@ namespace Hotline.Repository.SqlSugar.Orders
                 DataRow targetRow = dt2.NewRow();
                 foreach (var item in AddColumnName)
                 {
-                    targetRow[item] = sourceRow[item];
+                    try
+                    {
+                        targetRow[item] = sourceRow[item];
+                    }
+                    catch
+                    {
+                        targetRow[item] = 0;
+                    }
                 }
                 dt2.Rows.Add(targetRow);
             }

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

@@ -424,12 +424,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; }
     }
 
 

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

@@ -31,11 +31,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) + "%";
+        }
+    }
+}

+ 5 - 0
src/Hotline.Share/Dtos/File/FileDto.cs

@@ -133,6 +133,11 @@ namespace Hotline.Share.Dtos.File
 	public class FileJson {
 	
 		public string Id { get; set; }
+
+		public string FileName { get; set; }
+
+		public string FileType { get; set; }
+
 		public string FileId { get; set; }
 
 		public string Path { 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; }
     }
 }

+ 5 - 0
src/Hotline.Share/Dtos/JudicialManagement/JudicialManagementAddOrderDto.cs

@@ -182,5 +182,10 @@ namespace Hotline.Share.Dtos.JudicialManagement
         /// </summary>
         public List<FileDto>? Additions { get; set; } = new();
         public List<FileJson>? FileJson { get; set; }
+
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public DateTime CreationTime { get; set; }
     }
 }

+ 12 - 2
src/Hotline.Share/Dtos/Order/OrderBiDto.cs

@@ -391,9 +391,19 @@ namespace Hotline.Share.Dtos.Order
 		/// <summary>
 		/// 总满意度
 		/// </summary>
-		public double TotalSumRate => Math.Round(VerySatisfiedRate + SatisfiedRate + RegardedAsSatisfiedRate+ DefaultSatisfiedRate, 2) ;
+		//public double TotalSumRate => Math.Round(VerySatisfiedRate + SatisfiedRate + RegardedAsSatisfiedRate+ DefaultSatisfiedRate, 2) ;
+		public double TotalSumRate => CalcTotalSumRate();
 
-		public string TotalSumRateText => TotalSumRate + "%";
+		public double CalcTotalSumRate()
+		{
+			if ((VerySatisfiedCount + SatisfiedCount + RegardedAsSatisfiedCount + DefaultSatisfiedCount + NoSatisfiedCount) == 0)
+				return 0;
+           return Math.Round(((double)VerySatisfiedCount + SatisfiedCount + RegardedAsSatisfiedCount + DefaultSatisfiedCount) / (VerySatisfiedCount + SatisfiedCount + RegardedAsSatisfiedCount + DefaultSatisfiedCount + NoSatisfiedCount) * 100, 2);
+        }
+			
+			
+
+        public string TotalSumRateText => TotalSumRate + "%";
 		/// <summary>
 		/// 非常满意数
 		/// </summary>

+ 39 - 37
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -97,22 +97,22 @@ namespace Hotline.Share.Dtos.Order
         public double AllDuration { 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; }
 
@@ -391,10 +391,17 @@ namespace Hotline.Share.Dtos.Order
         ///// </summary>
         ////public string AcceptTypeText => AcceptType.GetDescription();
 
+        ///// <summary>
+        ///// 紧急程度
+        ///// </summary>
+        //public string EmergencyLevelText => EmergencyLevel.GetDescription();
         /// <summary>
         /// 紧急程度
         /// </summary>
-        public string EmergencyLevelText => EmergencyLevel.GetDescription();
+        //public EEmergencyLevel EmergencyLevel { get; set; }
+        public EEmergencyLevel EmergencyLevel => IsUrgent
+            ? EEmergencyLevel.Emergency
+            : EEmergencyLevel.UnEmergency;
 
         ///// <summary>
         ///// 超期时间描述(需求:超期3天、0.5天后超期)
@@ -441,7 +448,7 @@ namespace Hotline.Share.Dtos.Order
         /// 是否可办理
         /// </summary>
         public bool CanHandle { get; set; }
-        
+
         /// <summary>
         /// 退回意见
         /// </summary>
@@ -452,10 +459,10 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public bool CanInsteadHandle { get; set; }
 
-		/// <summary>
-		/// 延期申请数量
-		/// </summary>
-		public int DelayingCount => OrderDelays?.Count ?? 0;
+        /// <summary>
+        /// 延期申请数量
+        /// </summary>
+        public int DelayingCount => OrderDelays?.Count ?? 0;
 
         /// <summary>
         /// 是否紧急
@@ -464,10 +471,10 @@ namespace Hotline.Share.Dtos.Order
 
         public string IsUrgentText => IsUrgent ? "紧急" : "";
 
-		/// <summary>
-		/// 发布范围
-		/// </summary>
-		public bool? PublishState { get; set; }
+        /// <summary>
+        /// 发布范围
+        /// </summary>
+        public bool? PublishState { get; set; }
 
         /// <summary>
         /// 是否延期 
@@ -518,7 +525,7 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public string DaysOverdueOrgName { get; set; }
 
-		public EExpiredStatus? CalculateExpiredState()
+        public EExpiredStatus? CalculateExpiredState()
         {
             DateTime? dateTime = DateTime.Now;
             if (Status >= EOrderStatus.Filed)
@@ -532,7 +539,7 @@ namespace Hotline.Share.Dtos.Order
                 {
                     return EExpiredStatus.Normal;
                 }
-                else if(!NearlyExpiredTimeOne.HasValue && dateTime< NearlyExpiredTime)
+                else if (!NearlyExpiredTimeOne.HasValue && dateTime < NearlyExpiredTime)
                 {
                     return EExpiredStatus.Normal;
                 }
@@ -649,21 +656,21 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public DateTime? SendBackAuditTime { get; set; }
 
-		/// <summary>
-		/// 退回意见
-		/// </summary>
-		public List<OrderRemarksDto> OrderRemarks { get; set; }
+        /// <summary>
+        /// 退回意见
+        /// </summary>
+        public List<OrderRemarksDto> OrderRemarks { get; set; }
 
-		/// <summary>
-		/// 交办人(派单员)
-		/// </summary>
-		public string? CenterToOrgHandlerId { get; set; }
+        /// <summary>
+        /// 交办人(派单员)
+        /// </summary>
+        public string? CenterToOrgHandlerId { get; set; }
 
-		/// <summary>
-		/// 交办人(派单员)
-		/// </summary>
-		public string? CenterToOrgHandlerName { get; set; }
-	}
+        /// <summary>
+        /// 交办人(派单员)
+        /// </summary>
+        public string? CenterToOrgHandlerName { get; set; }
+    }
 
     public class UpdateOrderDto : AddOrderDto
     {
@@ -769,11 +776,6 @@ namespace Hotline.Share.Dtos.Order
         public string? AcceptType { get; set; }
         public string? AcceptTypeCode { get; set; }
 
-        /// <summary>
-        /// 紧急程度
-        /// </summary>
-        public EEmergencyLevel EmergencyLevel { get; set; }
-
         public string Title { get; set; }
 
         #region 热点
@@ -1026,8 +1028,8 @@ namespace Hotline.Share.Dtos.Order
         public decimal UnsignedTime { get; set; }
     }
 
-    public class OrderRemarksDto 
-    { 
+    public class OrderRemarksDto
+    {
         /// <summary>
         /// 备注信息
         /// </summary>
@@ -1043,5 +1045,5 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public DateTime RemarkTime { get; set; }
 
-	}
+    }
 }

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

@@ -84,6 +84,11 @@ namespace Hotline.Share.Dtos.Order
 		/// </summary>
 		public EBusinessType BusinessType { get; set; }
 
+		/// <summary>
+		/// 节点类型
+		/// </summary>
+		public EStepType? StepType { get; set; }
+
 	}
 	public class AuditOrderSpecialDto
 	{

+ 13 - 13
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,9 @@ namespace Hotline.Share.Dtos.Order
         /// 是否省工单
         /// </summary>
         public bool? IsProvince { get; set; }
-	}
+    }
 
-    public record VisitJudgeQueryReq:PagedKeywordRequest
+    public record VisitJudgeQueryReq : PagedKeywordRequest
     {
         /// <summary>
         /// 工单编号
@@ -77,17 +77,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 +505,7 @@ namespace Hotline.Share.Dtos.Order
         public EJudgeState? JudgeState { get; set; }
 
         public string? JudgeStateText => JudgeState?.GetDescription() ?? string.Empty;
-        
+
         /// <summary>
         /// 评判意见
         /// </summary>
@@ -564,15 +564,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>
         /// 部门办件态度
@@ -740,7 +740,7 @@ namespace Hotline.Share.Dtos.Order
         /// 回访内容
         /// </summary>
         public string? VisitContent { get; set; }
-      
+
     }
 
 

+ 18 - 13
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -28,27 +28,35 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 受理类型(√)
         /// </summary>
-        public List<string> AcceptTypes { get; set; } = new();
+        public string? AcceptType { get; set; }
+        //public List<string> AcceptTypes { get; set; } = new();
 
         /// <summary>
         /// 来源渠道(√)
         /// </summary>
-        public List<string> Channels { get; set; } = new();
+        public string? Channel { get; set; }
+        //public List<string> Channels { get; set; } = new();
 
         /// <summary>
         /// 转接号码(转接来源)(√)
         /// </summary>
         public string? TransferPhone { get; set; }
 
+        ///// <summary>
+        ///// 热点分类(√)
+        ///// </summary>
+        //public List<string> HotspotIds { get; set; } = new();
+
         /// <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; }
+        //public List<string> OrgCodes { get; set; } = new();
 
         /// <summary>
         /// 受理坐席名字或工号(×)
@@ -61,11 +69,6 @@ namespace Hotline.Share.Dtos.Order
         public DateTime? CreationTimeStart { get; set; }
         public DateTime? CreationTimeEnd { get; set; }
 
-        /// <summary>
-        /// 紧急程度(√)
-        /// </summary>
-        public List<EEmergencyLevel> EmergencyLevels { get; set; } = new();
-
         /// <summary>
         /// 来电号码(×)
         /// </summary>
@@ -92,7 +95,8 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 工单状态(√)
         /// </summary>
-        public List<EOrderStatus> Statuses { get; set; } = new();
+        public EOrderStatus? Status { get; set; }
+        //public List<EOrderStatus> Statuses { get; set; } = new();
 
         /// <summary>
         /// 接办人(√)
@@ -107,7 +111,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 当前办理节点(√)(单选)
         /// </summary>
-        public string CurrentStepCode { get; set; }
+        public string? CurrentStepCode { get; set; }
         /// <summary>
         /// 办结时间(√)
         /// </summary>
@@ -132,7 +136,8 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 区域(×)(多选)
         /// </summary>
-        public List<string> AreaCodes { get; set; } = new();
+        public string? AreaCode { get; set; }
+        //public List<string> AreaCodes { get; set; } = new();
 
         /// <summary>
         /// 是否省工单(空为全部  true为省工单 false为市工单)

+ 42 - 1
src/Hotline.Share/Dtos/ProvinceStatistics/ProvinceSendBackListDto.cs

@@ -422,7 +422,7 @@ namespace Hotline.Share.Dtos.ProvinceStatistics
         /// </summary>
         public OrderDto Order { get; set; }
 
-        // <summary>
+        /// <summary>
         /// 补充意见
         /// </summary>
         public string Opinion { get; set; }
@@ -438,4 +438,45 @@ namespace Hotline.Share.Dtos.ProvinceStatistics
         public string? SupplyTime { get; set; }
 
     }
+
+    /// <summary>
+    /// 督办
+    /// </summary>
+    public class ProvinceOrderSuperviseListDto
+    {
+        /// <summary>
+        /// 业务Id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 工单ID
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单
+        /// </summary>
+        public OrderDto Order { get; set; }
+
+        /// <summary>
+        /// 督办发起人
+        /// </summary>
+        public string? CrUser { get; set; }
+
+        /// <summary>
+        /// 督办发起时间
+        /// </summary>
+        public DateTime? SuperviseTime { get; set; }
+
+        /// <summary>
+        /// 督办回复人
+        /// </summary>
+        public string? ReUser { get; set; }
+
+        /// <summary>
+        /// 督办回复时间
+        /// </summary>
+        public DateTime? ReplyTime { get; set; }
+    }
 }

+ 56 - 0
src/Hotline.Share/Dtos/ProvinceStatistics/QueryProvinceSendBackDto.cs

@@ -39,4 +39,60 @@ namespace Hotline.Share.Dtos.ProvinceStatistics
         /// </summary>
         public int State { get; set; } = 0;
     }
+
+    /// <summary>
+    /// 督办
+    /// </summary>
+    public record QueryProvinceSuperviseDto : PagedRequest
+    {
+        /// <summary>
+        /// 本地编号
+        /// </summary>
+        public string? No { get; set; }
+
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string? Title { get; set; }
+
+        /// <summary>
+        /// 省编号
+        /// </summary>
+        public string? ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 督办标题
+        /// </summary>
+        public string? SuperviseTitle { get; set; }
+
+        /// <summary>
+        /// 申请时间
+        /// </summary>
+        public DateTime? ApplyStartTime { get; set; }
+
+        /// <summary>
+        /// 申请时间
+        /// </summary>
+        public DateTime? ApplyEndTime { get; set; }
+
+        /// <summary>
+        /// 被督办部门名称
+        /// </summary>
+        public string OrgName { get; set; }
+
+        /// <summary>
+        /// 反馈时间
+        /// </summary>
+        public DateTime? ReplyStartTime { get; set; }
+
+        /// <summary>
+        /// 反馈时间
+        /// </summary>
+        public DateTime? ReplyEndTime { get; set; }
+
+        /// <summary>
+        ///  督办状态  0 待回复  1 已回复
+        /// </summary>
+        public int? State { get; set; }
+    }
 }

+ 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
 

+ 1 - 1
src/Hotline.Share/Enums/FlowEngine/EWorkflowTraceType.cs

@@ -24,7 +24,7 @@ namespace Hotline.Share.Enums.FlowEngine
         /// <summary>
         /// 撤回
         /// </summary>
-        [Description("撤回")]
+        [Description("特提")]
         Recall = 2,
 
         /// <summary>

+ 1 - 1
src/Hotline.Share/Enums/Order/ESendBackAuditState.cs

@@ -13,7 +13,7 @@ namespace Hotline.Share.Enums.Order
 		/// <summary>
 		/// 待办
 		/// </summary>
-		[Description("待")]
+		[Description("待审批")]
 		Apply = 0,
 
 		/// <summary>

+ 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.85</Version>
+    <Version>1.0.87</Version>
   </PropertyGroup>
 
   <ItemGroup>

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

@@ -306,9 +306,9 @@ public record QueryUnsignedOrdersRequest : ReportPagedRequest
 public record QueryOrderSourceRequest : ReportPagedRequest
 {
     /// <summary>
-    /// 来电/信人身份
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
     /// </summary>
-    public EIdentityType? IdentityType { get; set; }
+    public int? TypeId { get; set; }
 
     /// <summary>
     /// 导出列名
@@ -319,9 +319,9 @@ public record QueryOrderSourceRequest : ReportPagedRequest
 public record QueryOrderSourceDetailRequest : QueryOrderSourceRequest
 {
     /// <summary>
-    /// 来电/信人身份
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
     /// </summary>
-    public EIdentityType? IdentityType { get; set; }
+    public int? TypeId { get; set; }
 
     /// <summary>
     /// 点击时间
@@ -340,9 +340,9 @@ public record QueryOrderSourceDetailRequest : QueryOrderSourceRequest
 public record TimeSharingPagedKeywordRequest : PagedKeywordRequest
 {
     /// <summary>
-    /// 来电/信人身份
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
     /// </summary>
-    public EIdentityType? IdentityType { get; set; }
+    public int? TypeId {  get; set; }
 
     /// <summary>
     /// 导出列名
@@ -381,17 +381,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>
     /// 受理时间(工单创建时间)(√)

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

+ 5 - 8
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -74,6 +74,11 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task RecallToStartStepAsync(string workflowId, string opinion, ISessionContext current, CancellationToken cancellationToken);
 
+        /// <summary>
+        /// 特提至派单节点(无派单节点会抛异常)
+        /// </summary>
+        Task RecallToSendStepAsync(string workflowId, string opinion, ISessionContext current, CancellationToken cancellationToken);
+
         ///// <summary>
         ///// 跳转(直接将流程跳转至任意节点)
         ///// </summary>
@@ -186,14 +191,6 @@ namespace Hotline.FlowEngine.Workflows
         /// <returns></returns>
         Task<Workflow> TerminalCountersignAsync(string countersignId, CancellationToken cancellationToken);
 
-        /// <summary>
-        /// 查询实际办理对象信息
-        /// </summary>
-        /// <param name="workflowId"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        Task<Kv> FindActualHandlerAsync(string workflowId, CancellationToken cancellationToken);
-
         /// <summary>
         /// 办理节点
         /// </summary>

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

@@ -563,9 +563,9 @@ public partial class Workflow
     {
         CurrentStepAcceptTime = step.AcceptTime;
         CurrentHandleTime = step.HandleTime;
-        CurrentHandleOrgLevel ??= handlerOrgLevel;
         CurrentHandleOrgAreaCode = handleOrgAreaCode;
         CurrentHandleOrgAreaName = handleOrgAreaName;
+        CurrentHandleOrgLevel ??= handlerOrgLevel;
 
         //坐席->派单存在不选办理对象的场景,所以要补赋值
         CurrentStepId = step.Id;

+ 81 - 22
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -115,6 +115,9 @@ namespace Hotline.FlowEngine.Workflows
                     current.OrgAreaCode, current.OrgAreaName,
                     current.OrgLevel);
 
+                workflow.UpdateCurrentStepWhenHandle(startStep,
+                    current.OrgAreaCode, current.OrgAreaName, current.OrgLevel);
+
                 var endTrace = await EndAsync(workflow, dto, firstStepDefine,
                     startStep, current, expiredTime, cancellationToken);
                 return;
@@ -636,6 +639,14 @@ namespace Hotline.FlowEngine.Workflows
             //更新实际办理节点信息
             workflow.UpdateActualStepWhenAssign(newPrevStep, prevStep.HandlerOrgId, prevStep.HandlerOrgName);
 
+            workflow.UpdateCurrentStepWhenAssign(newPrevStep, new FlowStepHandler
+            {
+                UserId = prevStep.HandlerId,
+                Username = prevStep.HandlerName,
+                OrgId = prevStep.HandlerOrgId,
+                OrgName = prevStep.HandlerOrgName,
+            });
+
             //更新流程可办理对象
             workflow.UpdatePreviousHandlers(applicantId, applicantOrgId, prevStep);
 
@@ -1047,12 +1058,36 @@ namespace Hotline.FlowEngine.Workflows
             //todo 1.当前待办节点删掉 2.当前待办trace更新(status, opinion) 3.复制startStep为待办 4.更新workflow(status, csStatus, handlers) 5.publish event
             var workflow = await GetWorkflowAsync(workflowId, withDefine: true, withSteps: true, withTraces: true,
                 cancellationToken: cancellationToken);
+            var startStep = workflow.Steps.First(d => d.StepType == EStepType.Start);
+
+
+            await RecallToTargetStepAsync(workflow, startStep, opinion, current, cancellationToken);
+        }
+
+        /// <summary>
+        /// 撤回至派单节点
+        /// </summary>
+        public async Task RecallToSendStepAsync(string workflowId, string opinion, ISessionContext current,
+            CancellationToken cancellationToken)
+        {
+            //todo 1.当前待办节点删掉 2.当前待办trace更新(status, opinion) 3.复制startStep为待办 4.更新workflow(status, csStatus, handlers) 5.publish event
+            var workflow = await GetWorkflowAsync(workflowId, withDefine: true, withSteps: true, withTraces: true,
+                cancellationToken: cancellationToken);
+            var startStep = workflow.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
+            if (startStep is null)
+                throw new UserFriendlyException($"未找到派单节点, workflowId: {workflowId}", "该流程无派单节点");
+
+            await RecallToTargetStepAsync(workflow, startStep, opinion, current, cancellationToken);
+        }
+
+        private async Task RecallToTargetStepAsync(Workflow workflow, WorkflowStep targetStep, string opinion, ISessionContext current,
+            CancellationToken cancellationToken)
+        {
             //update uncompleted traces
             await RecallTraceAsync(workflow.Traces, opinion, current, cancellationToken);
 
-            var startStep = workflow.Steps.First(d => d.StepType == EStepType.Start);
-            workflow.Steps.RemoveAll(d => true);
             await _workflowStepRepository.RemoveRangeAsync(workflow.Steps, cancellationToken);
+            workflow.Steps.RemoveAll(_ => true);
 
             workflow.EndCountersign();
             workflow.ResetOption();
@@ -1060,26 +1095,28 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.SetStatusRunnable();
 
             var newStartStep =
-                await DuplicateStepWithTraceAsync(workflow, startStep, EWorkflowTraceType.Recall, cancellationToken);
+                await DuplicateStepWithTraceAsync(workflow, targetStep, EWorkflowTraceType.Recall, cancellationToken);
 
-            //更新当前办理节点信息
-            //workflow.UpdateWorkflowCurrentStepInfo(false,
-            //    _sessionContext.RequiredUserId, _sessionContext.UserName,
-            //    _sessionContext.RequiredOrgId, _sessionContext.OrgName,
-            //    _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
-            //    nextStep: newStartStep);
-            workflow.UpdateActualStepWhenAssign(startStep, startStep.HandlerOrgId, startStep.HandlerOrgName);
+            workflow.UpdateActualStepWhenAssign(targetStep, targetStep.HandlerOrgId, targetStep.HandlerOrgName);
+
+            workflow.UpdateCurrentStepWhenAssign(targetStep, new FlowStepHandler
+            {
+                UserId = targetStep.HandlerId,
+                Username = targetStep.HandlerName,
+                OrgId = targetStep.HandlerOrgId,
+                OrgName = targetStep.HandlerOrgName,
+            });
 
-            var isOrgToCenter = CheckIfFlowFromOrgToCenter(workflow, startStep);
+            var isOrgToCenter = CheckIfFlowFromOrgToCenter(workflow, targetStep);
 
-            var flowAssignInfo = FlowAssignInfo.Create(startStep.FlowAssignType.Value, startStep.Handlers);
+            var flowAssignInfo = FlowAssignInfo.Create(targetStep.FlowAssignType.Value, targetStep.Handlers);
             workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
 
             await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
-            var dto = _mapper.Map<RecallDto>(startStep);
-            dto.WorkflowId = workflowId;
-            await _mediator.Publish(new RecallNotify(workflow, startStep, dto, isOrgToCenter), cancellationToken);
+            var dto = _mapper.Map<RecallDto>(targetStep);
+            dto.WorkflowId = workflow.Id;
+            await _mediator.Publish(new RecallNotify(workflow, targetStep, dto, isOrgToCenter), cancellationToken);
         }
 
         ///// <summary>
@@ -1375,7 +1412,7 @@ namespace Hotline.FlowEngine.Workflows
 
             var startStep = _mapper.Map<WorkflowStep>(startStepDefine);
             _mapper.Map(workflow, startStep);
-            startStep.FlowAssignType = EFlowAssignType.User;
+            startStep.FlowAssignType = EFlowAssignType.Org;
             startStep.Handlers = new List<Kv> { new(handler.Key, handler.Value) };
             //startStep.StepHandlers = stepHandlers;
             startStep.NextSteps = nextSteps;
@@ -1393,12 +1430,6 @@ namespace Hotline.FlowEngine.Workflows
             return startStep;
         }
 
-        public async Task<Kv> FindActualHandlerAsync(string workflowId, CancellationToken cancellationToken)
-        {
-            var workflow = await GetWorkflowAsync(workflowId, cancellationToken: cancellationToken);
-            return new Kv(workflow.ActualHandleOrgCode, workflow.ActualHandleOrgName);
-        }
-
         /// <summary>
         /// 流程结束
         /// </summary>
@@ -2143,6 +2174,15 @@ namespace Hotline.FlowEngine.Workflows
                 //await _workflowTraceRepository.UpdateRangeAsync(uncompleteTraces, cancellationToken);
                 updateTraces.AddRange(uncompleteTraces);
             }
+            else
+            {
+                var endTrace = workflow.Traces.Where(d => d.StepType == EStepType.End).MaxBy(d => d.CreationTime);
+                if (endTrace is not null)
+                {
+                    endTrace.Opinion += ("\r\n" + dto.Opinion);
+                    updateTraces.Add(endTrace);
+                }
+            }
 
             //get targetStep's previous
             WorkflowStep? targetPrevStep = null;
@@ -2195,6 +2235,14 @@ namespace Hotline.FlowEngine.Workflows
             //更新实际办理节点信息
             workflow.UpdateActualStepWhenAssign(targetStepNew, targetStep.HandlerOrgId, targetStep.HandlerOrgName);
 
+            workflow.UpdateCurrentStepWhenAssign(targetStepNew, new FlowStepHandler
+            {
+                UserId = targetStep.HandlerId,
+                Username = targetStep.HandlerName,
+                OrgId = targetStep.HandlerOrgId,
+                OrgName = targetStep.HandlerOrgName
+            });
+
             workflow.Assign(flowAssignInfo.FlowAssignType, flowAssignInfo.GetHandlerIds());
             workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
 
@@ -2488,10 +2536,21 @@ namespace Hotline.FlowEngine.Workflows
 
                 //当topcsStep结束cs时,实际办理节点应该更新为newStep
                 if (startCountersignStep.Id == workflow.TopCountersignStepId)
+                {
                     workflow.UpdateActualStepWhenAssign(newStep,
                         startCountersignStep.HandlerOrgId,
                         startCountersignStep.HandlerOrgName);
 
+                    workflow.UpdateCurrentStepWhenAssign(newStep,
+                        new FlowStepHandler
+                        {
+                            UserId = startCountersignStep.HandlerId,
+                            Username = startCountersignStep.HandlerName,
+                            OrgId = startCountersignStep.HandlerOrgId,
+                            OrgName = startCountersignStep.HandlerOrgName
+                        });
+                }
+
                 //csEndStep又开启了cs,在结束会签时,如果该节点是topcs的end节点, workflow.topcsStep应该更新为前一cs开启stepId
                 if (startCountersignStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
                     workflow.TopCountersignStepId = startCountersignStep.CountersignStartStepId;

+ 0 - 4
src/Hotline/Hotline.csproj

@@ -22,8 +22,4 @@
     <ProjectReference Include="..\XF.Domain.Repository\XF.Domain.Repository.csproj" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Province\" />
-  </ItemGroup>
-
 </Project>

+ 10 - 15
src/Hotline/Orders/Order.cs

@@ -140,11 +140,6 @@ namespace Hotline.Orders
 
         public string? AcceptTypeCode { get; set; }
 
-        /// <summary>
-        /// 紧急程度
-        /// </summary>
-        public EEmergencyLevel EmergencyLevel { get; set; } = EEmergencyLevel.Normal;
-
         public string Title { get; set; }
 
         #region 热点
@@ -348,22 +343,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; }
 
@@ -1101,28 +1096,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

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

@@ -43,6 +43,11 @@ namespace Hotline.Orders
         /// </summary>
         public EBusinessType? BusinessType { get; set; }
 
+        /// <summary>
+        /// 节点类型
+        /// </summary>
+        public EStepType? StepType { get; set; }
+
 		public string? StepCode { get; set; } = string.Empty;
         public string? StepName { get; set; } = string.Empty;
 

+ 123 - 109
src/Hotline/Orders/OrderSupervise.cs

@@ -1,114 +1,128 @@
-using Hotline.File;
-using Hotline.Users;
+using Hotline.Share.Dtos.File;
 using SqlSugar;
 using System.ComponentModel;
-using Hotline.Share.Dtos.File;
 using XF.Domain.Repository;
 
-namespace Hotline.Orders {
-	[Description("督办")]
-	public class OrderSupervise : FullStateEntity
-	{
-		/// <summary>
-		/// 工单ID
-		/// </summary>
-		[SugarColumn(ColumnDescription = "工单ID")]
-		public string OrderId { get; set; }
-
-		/// <summary>
-		/// 督办回复时限
-		/// </summary>
-		[SugarColumn(ColumnDescription = "督办回复时限")]
-		public DateTime ReplyLimitTime { get; set; }
-
-		/// <summary>
-		/// 被督办部门ID
-		/// </summary>
-		[SugarColumn(ColumnDescription = "被督办部门ID")]
-		public string? OrgId { get; set; }
-
-		/// <summary>
-		/// 被督办部门名称
-		/// </summary>
-		[SugarColumn(ColumnDescription = "被督办部门名称")]
-		public string OrgName { get; set; }
-
-		/// <summary>
-		/// 发起部门名称
-		/// </summary>
-		[SugarColumn(ColumnDescription = "发起部门名称")]
-		public string? LaunchOrgName { get; set; }
-
-		/// <summary>
-		/// 督办状态
-		/// </summary>
-		[SugarColumn(ColumnDescription = "督办状态   0 待回复  1 已回复")]
-		public int State { get; set; }
-
-		/// <summary>
-		/// 督办签收时间
-		/// </summary>
-		[SugarColumn(ColumnDescription = "督办签收时间")]
-		public DateTime? SignTime { get; set; }
-
-		/// <summary>
-		/// 督办回复时间
-		/// </summary>
-		[SugarColumn(ColumnDescription = "督办回复时间")]
-		public DateTime? ReplyTime { get; set; }
-
-		/// <summary>
-		/// 督办申请内容
-		/// </summary>
-		[SugarColumn(ColumnDescription = "督办申请内容", ColumnDataType = "varchar(2000)")]
-		public string? ApplyContent { get; set; }
-
-		/// <summary>
-		/// 督办回复内容
-		/// </summary>
-		[SugarColumn(ColumnDescription = "督办回复内容", ColumnDataType = "varchar(2000)")]
-		public string? ReplyContent { get; set; }
-
-		/// <summary>
-		/// 回复人
-		/// </summary>
-		[SugarColumn(ColumnDescription = "回复人")]
-		public string? ReplyId { get; set; }
-
-
-		/// <summary>
-		/// 是否省督办
-		/// </summary>
-		[SugarColumn(ColumnDescription = "是否省督办")]
-		public bool? Province { get; set; }
-
-
-		/// <summary>
-		/// 
-		/// </summary>
-		[Navigate(NavigateType.OneToOne, nameof(OrderId))]
-		public Order Order { get; set; }
-
-		[SugarColumn(ColumnDescription = "回复人")]
-		public string? ReUser { get; set; }
-
-		[SugarColumn(ColumnDescription = "申请人")]
-		public string? CrUser { get; set; }
-
-		[SugarColumn(ColumnDescription = "签收人")]
-		public string? SignUser { get; set; }
-
-		/// <summary>
-		/// 督办省编号
-		/// </summary>
-		[SugarColumn(ColumnDescription = "省督办编号")]
-		public string? SuperviseSerial {  get; set; }
-
-
-		[SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
-		public List<FileJson>? FileJson { get; set; }
-
-		[SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
-		public List<FileJson>? ReplyFileJson { get; set; }
-	}
+namespace Hotline.Orders
+{
+    [Description("督办")]
+    public class OrderSupervise : FullStateEntity
+    {
+        /// <summary>
+        /// 工单ID
+        /// </summary>
+        [SugarColumn(ColumnDescription = "工单ID")]
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 督办回复时限
+        /// </summary>
+        [SugarColumn(ColumnDescription = "督办回复时限")]
+        public DateTime ReplyLimitTime { get; set; }
+
+        /// <summary>
+        /// 被督办部门ID
+        /// </summary>
+        [SugarColumn(ColumnDescription = "被督办部门ID")]
+        public string? OrgId { get; set; }
+
+        /// <summary>
+        /// 被督办部门名称
+        /// </summary>
+        [SugarColumn(ColumnDescription = "被督办部门名称")]
+        public string OrgName { get; set; }
+
+        /// <summary>
+        /// 发起部门名称
+        /// </summary>
+        [SugarColumn(ColumnDescription = "发起部门名称")]
+        public string? LaunchOrgName { get; set; }
+
+        /// <summary>
+        /// 督办状态
+        /// </summary>
+        [SugarColumn(ColumnDescription = "督办状态   0 待回复  1 已回复")]
+        public int State { get; set; }
+
+        /// <summary>
+        /// 督办签收时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "督办签收时间")]
+        public DateTime? SignTime { get; set; }
+
+        /// <summary>
+        /// 督办回复时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "督办回复时间")]
+        public DateTime? ReplyTime { get; set; }
+
+        /// <summary>
+        /// 督办申请内容
+        /// </summary>
+        [SugarColumn(ColumnDescription = "督办申请内容", ColumnDataType = "varchar(2000)")]
+        public string? ApplyContent { get; set; }
+
+        /// <summary>
+        /// 督办回复内容
+        /// </summary>
+        [SugarColumn(ColumnDescription = "督办回复内容", ColumnDataType = "varchar(2000)")]
+        public string? ReplyContent { get; set; }
+
+        /// <summary>
+        /// 回复人
+        /// </summary>
+        [SugarColumn(ColumnDescription = "回复人")]
+        public string? ReplyId { get; set; }
+
+
+        /// <summary>
+        /// 是否省督办
+        /// </summary>
+        [SugarColumn(ColumnDescription = "是否省督办")]
+        public bool? Province { get; set; }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        [Navigate(NavigateType.OneToOne, nameof(OrderId))]
+        public Order Order { get; set; }
+
+        [SugarColumn(ColumnDescription = "回复人")]
+        public string? ReUser { get; set; }
+
+        [SugarColumn(ColumnDescription = "申请人")]
+        public string? CrUser { get; set; }
+
+        [SugarColumn(ColumnDescription = "签收人")]
+        public string? SignUser { get; set; }
+
+        /// <summary>
+        /// 督办省编号
+        /// </summary>
+        [SugarColumn(ColumnDescription = "省督办编号")]
+        public string? SuperviseSerial { get; set; }
+
+
+        [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
+        public List<FileJson>? FileJson { get; set; }
+
+        [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
+        public List<FileJson>? ReplyFileJson { get; set; }
+
+        /// <summary>
+        /// 督办标题
+        /// </summary>
+        public string? SuperviseTitle { get; set; }
+
+        /// <summary>
+        /// 督办发起时间
+        /// </summary>
+        public DateTime? SuperviseTime { get; set; }
+
+        /// <summary>
+        /// 督办类型
+        /// </summary>
+        public string? SuperviseType { get; set; }
+    }
 }

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

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