Kaynağa Gözat

Merge branch 'test' of http://110.188.24.182:10023/Fengwo/hotline into test
合并冲突

guqiang 3 hafta önce
ebeveyn
işleme
5c0d69337e

+ 27 - 2
src/Hotline.Api/Controllers/Bi/BiCallController.cs

@@ -26,6 +26,9 @@ using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Api.Filter;
 using Hotline.Share.Dtos.Order.Publish;
 using Hotline.Application.StatisticalReport.CallReport;
+using DocumentFormat.OpenXml.Spreadsheet;
+using DocumentFormat.OpenXml.Wordprocessing;
+using NPOI.SS.Formula.Functions;
 
 namespace Hotline.Api.Controllers.Bi;
 
@@ -401,8 +404,30 @@ public class BiCallController : BaseController
     /// <returns></returns>
     [HttpGet("seats")]
     [AllowAnonymous]
-    public async Task<IReadOnlyList<BiSeatCallsDto>> QuerySeatCallsAsync([FromQuery] ReportRequiredPagedRequest dto)
-        => await _callReportApplication.QuerySeatCallAsync(dto, HttpContext.RequestAborted);
+    public async Task<TotalList<BiSeatCallsDto>> QuerySeatCallsAsync([FromQuery] ReportRequiredPagedRequest dto)
+    {
+        var items = await _callReportApplication.QuerySeatCallAsync(dto, HttpContext.RequestAborted);
+        var total = new BiSeatCallsDto
+        {
+            Name="合计",                                                  // 坐席姓名
+            UserId="",                                                    // 用户ID
+            StaffNo="",                                                   // 工号
+            TelNo="",                                                     // 分机号
+            InTotal = items.Sum(m => m.InTotal),                          // 呼入总量 
+            OutTotal = items.Sum(m => m.OutTotal),                        // 呼出总量
+            InAnswered = items.Sum(m => m.InAnswered),                    // 呼入接通量
+            OutAnswered = items.Sum(m => m.OutAnswered),                  // 呼出接通量
+            InHangupImmediate = items.Sum(m => m.InHangupImmediate),      // 呼入秒挂
+            InHanguped = items.Sum(m => m.InHanguped),                    // 呼入未接
+            InDurationAvg = items.Sum(m => m.InDurationAvg),              // 呼入平均时长
+            OutDurationAvg = items.Sum(m => m.OutDurationAvg),            // 呼出平均时长
+            InAvailableAnswer = items.Sum(m => m.InAvailableAnswer),      // 有效接通量
+            InHangupImmediateWhenAnswered = items.Sum(m => m.InHangupImmediateWhenAnswered),      // 呼入接通秒挂
+            LoginDuration = items.Sum(m => m.LoginDuration),              // 登录时长(秒)
+            RestDuration = items.Sum(m => m.RestDuration),                // 小休+摘机时长 (秒)
+        };
+        return new TotalList<BiSeatCallsDto>(items, total);
+    }
 
     /// <summary>
     /// 坐席话务统计分析明细

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

@@ -327,8 +327,20 @@ namespace Hotline.Api.Controllers.Bi
         /// </summary>
         /// <returns></returns>
         [HttpGet("visit/quantity")]
-        public async Task<IList<OrderVisitQuantityOutDto>> QueryOrderVisitQuantityAsync([FromQuery] QueryOrderVisitQuantity dto)
-            => await _orderVisitApplication.QueryOrderVisitQuantityAsync(dto);
+        public async Task<TotalList<OrderVisitQuantityOutDto>> QueryOrderVisitQuantityAsync([FromQuery] QueryOrderVisitQuantity dto)
+        {
+            var items = await _orderVisitApplication.QueryOrderVisitQuantityAsync(dto);
+            var total = new OrderVisitQuantityOutDto
+            {
+                EmployeeName = "合计",
+                EmployeeId = "",
+                CallVisitCount = items.Sum(m => m.CallVisitCount),
+                DefaultVisitCount = items.Sum(m => m.DefaultVisitCount),
+                SmsVisitCount = items.Sum(m => m.SmsVisitCount)
+            };
+            return new TotalList<OrderVisitQuantityOutDto>(items, total);
+
+        }
 
         /// <summary>
         /// 回访量统计--导出
@@ -342,6 +354,94 @@ namespace Hotline.Api.Controllers.Bi
             return _exportApplication.GetExcelFile(dto, items, "回访量统计");
         }
 
+        /// <summary>
+        /// 回访量明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("visit/quantity/list")]
+        public async Task<PagedDto<OrderVisitDto>> QueryOrderVisitQuantityListAsync([FromQuery] QueryOrderVisitListDto dto)
+        {
+            if (_appOptions.Value.IsZiGong == true)
+            {
+                var (total, items) = await _orderApplication.QueryOrderVisitQuantityListByZgAsync(dto)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+                return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
+            }
+            else
+            {
+                var (total, items) = await _orderApplication.QueryOrderVisitQuantityListAsync(dto)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+                return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
+            }
+        }
+
+        /// <summary>
+        /// 回访量明细--导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("visit/quantity/list/export")]
+        [LogFilterAlpha("导出日志")]
+        public async Task<FileStreamResult> QueryOrderVisitQuantityExport([FromBody] ExportExcelDto<QueryOrderVisitListDto> dto)
+        {
+            if (_appOptions.Value.IsZiGong == true)
+            {
+                var query = _orderApplication.QueryOrderVisitQuantityListByZgAsync(dto.QueryDto);
+                List<OrderVisitRecord> orders;
+                if (dto.IsExportAll)
+                {
+                    orders = await query.ToListAsync(HttpContext.RequestAborted);
+                }
+                else
+                {
+                    var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                    orders = items;
+                }
+
+
+                var orderDtos = _mapper.Map<ICollection<OrderVisitDto>>(orders);
+                dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OrderVisitDto>(dto.ColumnInfos);
+
+                var dtos = orderDtos
+                    .Select(stu => _mapper.Map(stu, typeof(OrderVisitDto), dynamicClass))
+                    .Cast<object>()
+                    .ToList();
+
+                var stream = ExcelHelper.CreateStream(dtos);
+                var excelTitle = "回访量明细";
+                return ExcelStreamResult(stream, excelTitle);
+            }
+            else
+            {
+                var query = _orderApplication.QueryOrderVisitQuantityListAsync(dto.QueryDto);
+                List<OrderVisit> orders;
+                if (dto.IsExportAll)
+                {
+                    orders = await query.ToListAsync(HttpContext.RequestAborted);
+                }
+                else
+                {
+                    var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                    orders = items;
+                }
+
+
+                var orderDtos = _mapper.Map<ICollection<OrderVisitDto>>(orders);
+                dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OrderVisitDto>(dto.ColumnInfos);
+
+                var dtos = orderDtos
+                    .Select(stu => _mapper.Map(stu, typeof(OrderVisitDto), dynamicClass))
+                    .Cast<object>()
+                    .ToList();
+
+                var stream = ExcelHelper.CreateStream(dtos);
+                var excelTitle = "回访量明细";
+                return ExcelStreamResult(stream, excelTitle);
+            }
+        }
+
+
         /// <summary>
         /// 部门超期统计明细
         /// </summary>
@@ -3034,14 +3134,14 @@ namespace Hotline.Api.Controllers.Bi
                   //WaitVisitd = SqlFunc.AggregateSum(SqlFunc.IIF(x.VisitState != EVisitState.None && x.VisitState != EVisitState.Visited, 1, 0)),//待回访
               }).FirstAsync();
 
-			var waitVisitd = await _orderVisitRepository.Queryable()
-			 .Where(x => x.CreationTime >= StartTime && x.CreationTime <= EndTime).Select(x =>
-				   SqlFunc.AggregateSum(SqlFunc.IIF(x.VisitState != EVisitState.None && x.VisitState != EVisitState.Visited, 1, 0)) //待回访
-			  ).FirstAsync();
-			centerReportVisitd.WaitVisitd = waitVisitd;
+            var waitVisitd = await _orderVisitRepository.Queryable()
+             .Where(x => x.CreationTime >= StartTime && x.CreationTime <= EndTime).Select(x =>
+                   SqlFunc.AggregateSum(SqlFunc.IIF(x.VisitState != EVisitState.None && x.VisitState != EVisitState.Visited, 1, 0)) //待回访
+              ).FirstAsync();
+            centerReportVisitd.WaitVisitd = waitVisitd;
 
-			//部门
-			var listOrg = await _orderVisitDetailRepository.Queryable()
+            //部门
+            var listOrg = await _orderVisitDetailRepository.Queryable()
                 .LeftJoin<OrderVisit>((it, o) => it.VisitId == o.Id)
                 .Where((it, o) => it.VisitTarget == EVisitTarget.Org && o.VisitTime >= StartTime && o.VisitTime <= EndTime && o.VisitState == EVisitState.Visited)
                  .Select((it, o) => new Satisfaction
@@ -3277,15 +3377,15 @@ namespace Hotline.Api.Controllers.Bi
               }).FirstAsync();
 
             var waitVisitd = await _orderVisitRepository.Queryable()
-			  .LeftJoin<Order>((x, o) => x.OrderId == o.Id)
-			  .WhereIF(IdentityType.HasValue, (x, o) => o.IdentityType == IdentityType)
-			  .Where((x, o) => x.CreationTime >= StartTime && x.CreationTime <= EndTime).Select((x, o) => 
+              .LeftJoin<Order>((x, o) => x.OrderId == o.Id)
+              .WhereIF(IdentityType.HasValue, (x, o) => o.IdentityType == IdentityType)
+              .Where((x, o) => x.CreationTime >= StartTime && x.CreationTime <= EndTime).Select((x, o) =>
                     SqlFunc.AggregateSum(SqlFunc.IIF(x.VisitState != EVisitState.None && x.VisitState != EVisitState.Visited, 1, 0)) //待回访
                ).FirstAsync();
             centerReportVisitd.WaitVisitd = waitVisitd;
 
-			//部门
-			var listOrg = await _orderVisitDetailRepository.Queryable()
+            //部门
+            var listOrg = await _orderVisitDetailRepository.Queryable()
                 .LeftJoin<OrderVisit>((x, ov) => x.VisitId == ov.Id)
                 .LeftJoin<Order>((x, ov, o) => ov.OrderId == o.Id)
                 .WhereIF(IdentityType.HasValue, (x, ov, o) => o.IdentityType == IdentityType)
@@ -4941,8 +5041,8 @@ namespace Hotline.Api.Controllers.Bi
 
             var stream = ExcelHelper.CreateStream(dtos);
 
-			return ExcelStreamResult(stream, "派单量明细数据");
-		}
+            return ExcelStreamResult(stream, "派单量明细数据");
+        }
 
         /// <summary>
         /// 二次办理统计

+ 2 - 1
src/Hotline.Api/Controllers/WebPortalController.cs

@@ -1991,9 +1991,10 @@ namespace Hotline.Api.Controllers
                 }
 
                 // 工单流转到部门才允许显示办理内容
-                if (data.ActualHandleOrgCode == OrgSeedData.CenterId)
+                if (data.ActualHandleOrgCode == OrgSeedData.CenterId && data.Status < EOrderStatus.Published)
                 {
                     orderDetail.FlowContent = "信件正在办理中...";
+                    orderDetail.FlowResult = "信件正在办理中...";
                 }
 
                 //能否进行评价

+ 33 - 18
src/Hotline.Application/OrderApp/IOrderApplication.cs

@@ -27,12 +27,12 @@ namespace Hotline.Application.OrderApp
 
         ISugarQueryable<Order> QuerySendOrderDetail(QuerySendOrderDetailRequest dto);
 
-		/// <summary>
-		/// 更新工单办理期满时间
-		/// 1.更新工单 2.更新流程
-		/// </summary>
-		/// <returns></returns>
-		Task DelayOrderExpiredTimeAsync(string orderId, int timeCount, ETimeType timeType, bool IsProDelay, CancellationToken cancellationToken);
+        /// <summary>
+        /// 更新工单办理期满时间
+        /// 1.更新工单 2.更新流程
+        /// </summary>
+        /// <returns></returns>
+        Task DelayOrderExpiredTimeAsync(string orderId, int timeCount, ETimeType timeType, bool IsProDelay, CancellationToken cancellationToken);
 
         // /// <summary>
         // /// 新增工单办理流程记录
@@ -378,6 +378,21 @@ namespace Hotline.Application.OrderApp
         /// <returns></returns>
         ISugarQueryable<OrderVisit> QueryOrderVisitList(QueryOrderVisitDto dto);
 
+        /// <summary>
+        /// 回访量明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrderVisit> QueryOrderVisitQuantityListAsync(QueryOrderVisitListDto dto);
+
+        /// <summary>
+        /// 回访量明细自贡
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrderVisitRecord> QueryOrderVisitQuantityListByZgAsync(QueryOrderVisitListDto dto);
+
+
         /// <summary>
         /// 热点类型小类统计明细
         /// </summary>
@@ -515,18 +530,18 @@ namespace Hotline.Application.OrderApp
         /// <returns></returns>
         ISugarQueryable<OrderDto> SeatSendBackStatisticsDetail(SeatSendBackStatisticsDetail dto);
 
-		/// <summary>
-		/// 自动延期记录写入
-		/// </summary>
-		/// <returns></returns>
-		Task OrderDelayAutomatic();
+        /// <summary>
+        /// 自动延期记录写入
+        /// </summary>
+        /// <returns></returns>
+        Task OrderDelayAutomatic();
 
-		/// <summary>
-		/// 自动延期处理
-		/// </summary>
-		/// <param name="type"></param>
-		/// <returns></returns>
-		Task OrderDelayAutomaticHandle(EOrderDelayAutomaticType type);
+        /// <summary>
+        /// 自动延期处理
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        Task OrderDelayAutomaticHandle(EOrderDelayAutomaticType type);
 
-	}
+    }
 }

+ 115 - 0
src/Hotline.Application/OrderApp/OrderApplication.cs

@@ -89,6 +89,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     private readonly IFileRepository _fileRepository;
     private readonly IRepository<OrderVisit> _orderVisitRepository;
     private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
+    private readonly IRepository<OrderVisitRecord> _orderVisitRecordRepository;
     private readonly IQualityApplication _qualityApplication;
     private readonly ICapPublisher _capPublisher;
     private readonly IRepository<SystemOrganize> _systemOrganizeRepository;
@@ -137,6 +138,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         ISessionContext sessionContext,
         IRepository<OrderVisit> orderVisitRepository,
         IRepository<OrderVisitDetail> orderVisitDetailRepository,
+        IRepository<OrderVisitRecord> orderVisitRecordRepository,
         IQualityApplication qualityApplication,
         ICapPublisher capPublisher,
         IRepository<SystemOrganize> systemOrganizeRepository,
@@ -190,6 +192,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         _repositoryts = repositoryts;
         _fileRepository = fileRepository;
         _orderVisitRepository = orderVisitRepository;
+        _orderVisitRecordRepository = orderVisitRecordRepository;
         _orderVisitDetailRepository = orderVisitDetailRepository;
         _qualityApplication = qualityApplication;
         _capPublisher = capPublisher;
@@ -4571,6 +4574,118 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return query;
     }
 
+    /// <summary>
+    /// 回访量明细
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public ISugarQueryable<OrderVisit> QueryOrderVisitQuantityListAsync(QueryOrderVisitListDto dto)
+    {
+        var query = _orderVisitRepository.Queryable()
+             .Includes(d => d.Order, d => d.OrderTags)
+             .Includes(d => d.Employee)
+             .Includes(d => d.OrderVisitDetails)
+             .Where(d => d.VisitTime >= dto.StartTime && d.VisitTime <= dto.EndTime && d.VisitType != null && d.EmployeeId != "" && d.EmployeeId != null)
+             .WhereIF(!string.IsNullOrEmpty(dto.UserID), d => !string.IsNullOrEmpty(d.EmployeeId) && d.EmployeeId == dto.UserID)
+             .WhereIF(!string.IsNullOrEmpty(dto.UserName), d => d.Employee.Name == dto.UserName)
+             .WhereIF(dto.FieldName == "callVisitCount", d => d.VisitType == EVisitType.CallVisit)
+             .WhereIF(dto.FieldName == "defaultVisitCount", d => d.VisitType == EVisitType.ArtificialVisit)
+             .WhereIF(dto.FieldName == "smsVisitCount", d => d.VisitType == EVisitType.SmsVisit)
+             .WhereIF(dto.FieldName == "totalVisitCount", d => d.VisitType == EVisitType.CallVisit || d.VisitType == EVisitType.ArtificialVisit || d.VisitType == EVisitType.SmsVisit);
+
+        query = query
+            .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)                                                                 // 工单编号
+            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Order.Title.Contains(dto.Title!))                                          // 标题
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) // 接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.Order.AcceptTypeCode == dto.AcceptType)                               // 受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptorName), d => d.Order.AcceptorName == dto.AcceptorName!)                            // 受理人
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.Order.ActualHandlerName == dto.ActualHandlerName)              // 接办人
+            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.Order.FromPhone.Contains(dto.FromPhone!))                              // 来电号码
+            .WhereIF(!string.IsNullOrEmpty(dto.Contact), d => d.Order.Contact == dto.Contact)                                            // 联系电话
+            .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.Order.FromName == dto.FromName)                                         // 来电人姓名
+            .WhereIF(dto.CreationTimeStart.HasValue, d => d.Order.CreationTime >= dto.CreationTimeStart)                                 // 受理时间开始
+            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.Order.CreationTime <= dto.CreationTimeEnd)                                     // 受理时间结束
+            .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.Order.ExpiredTime >= dto.ExpiredTimeStart)                                    // 期满时间开始
+            .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.Order.ExpiredTime <= dto.ExpiredTimeEnd)                                        // 期满时间结束
+            .WhereIF(dto.Status.HasValue, d => d.Order.Status == dto.Status)                                                             // 工单状态
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.Order.AreaCode == dto.AreaCode)                                         // 区域
+            .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.Order.SourceChannelCode == dto.Channel)                                  // 来源渠道
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value, d => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == d.OrderId && q.VisitDetailId == d.Id).Any())             // 是否甄别
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value == false, d => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == d.OrderId && q.VisitDetailId == d.Id).NotAny())
+            .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepName), d => d.Order.CurrentStepName == dto.CurrentStepName)                    // 当前办理节点
+            .WhereIF(dto.FiledTimeStart.HasValue, d => d.Order.FiledTime >= dto.FiledTimeStart)                                          // 办结时间开始
+            .WhereIF(dto.FiledTimeEnd.HasValue, d => d.Order.FiledTime <= dto.FiledTimeEnd)                                              // 办结时间结束
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.Order.HotspotSpliceName != null && d.Order.HotspotSpliceName.Contains(dto.Hotspot)) // 热点类型
+            .WhereIF(dto.IsSecret.HasValue, d => d.Order.IsSecret == dto.IsSecret)                                                       // 是否紧急
+
+            .OrderByIF(_appOptions.Value.IsZiGong == false, d => d.PublishTime, OrderByType.Desc)
+            .OrderByIF(dto is { SortField: "publishTime", SortRule: 0 }, x => x.PublishTime, OrderByType.Asc) // 发布时间升序
+            .OrderByIF(dto is { SortField: "publishTime", SortRule: 1 }, x => x.PublishTime, OrderByType.Desc)// 发布时间升序
+            .OrderByIF(dto is { SortField: "order.creationTime", SortRule: 0 }, x => x.Order.CreationTime, OrderByType.Asc) // 受理时间升序
+            .OrderByIF(dto is { SortField: "order.creationTime", SortRule: 1 }, x => x.Order.CreationTime, OrderByType.Desc) // 受理时间升序
+            .OrderByIF(dto is { SortField: "order.filedTime", SortRule: 0 }, x => x.Order.FiledTime, OrderByType.Asc) // 办结时间升序
+            .OrderByIF(dto is { SortField: "order.filedTime", SortRule: 1 }, x => x.Order.FiledTime, OrderByType.Desc) // 办结时间升序
+            .OrderByIF(dto is { SortField: "visitTime", SortRule: 0 }, x => x.VisitTime, OrderByType.Asc) // 回访时间升序
+            .OrderByIF(dto is { SortField: "visitTime", SortRule: 1 }, x => x.VisitTime, OrderByType.Desc) // 回访时间升序
+            .OrderByIF(_appOptions.Value.IsZiGong && string.IsNullOrEmpty(dto.SortField), d => d.PublishTime, OrderByType.Desc)
+            ;
+        return query;
+    }
+
+    /// <summary>
+    /// 回访量明细自贡
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public ISugarQueryable<OrderVisitRecord> QueryOrderVisitQuantityListByZgAsync(QueryOrderVisitListDto dto)
+    {
+        var query = _orderVisitRecordRepository.Queryable()
+            .Includes(d => d.Order, d => d.OrderTags)
+            .Includes(d => d.Employee)
+            .WhereIF(!string.IsNullOrEmpty(dto.UserID), d => !string.IsNullOrEmpty(d.EmployeeId) && d.EmployeeId == dto.UserID)
+            .WhereIF(!string.IsNullOrEmpty(dto.UserName), d => d.Employee.Name == dto.UserName)
+            .WhereIF(dto.StartTime != null, d => d.VisitTime >= dto.StartTime && d.VisitType != null && d.EmployeeId != "" && d.EmployeeId != null)
+            .WhereIF(dto.EndTime != null, d => d.VisitTime <= dto.EndTime && d.VisitType != null && d.EmployeeId != "" && d.EmployeeId != null)
+            .WhereIF(dto.FieldName == "callVisitCount", d => d.VisitType == EVisitType.CallVisit)
+            .WhereIF(dto.FieldName == "defaultVisitCount", d => d.VisitType == EVisitType.ArtificialVisit)
+            .WhereIF(dto.FieldName == "smsVisitCount", d => d.VisitType == EVisitType.SmsVisit)
+            .WhereIF(dto.FieldName == "totalVisitCount", d => d.VisitType == EVisitType.CallVisit || d.VisitType == EVisitType.ArtificialVisit || d.VisitType == EVisitType.SmsVisit);
+
+        query = query
+            .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)                                                                 // 工单编号
+            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Order.Title.Contains(dto.Title!))                                          // 标题
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) // 接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.Order.AcceptTypeCode == dto.AcceptType)                               // 受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptorName), d => d.Order.AcceptorName == dto.AcceptorName!)                            // 受理人
+            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.Order.ActualHandlerName == dto.ActualHandlerName)              // 接办人
+            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.Order.FromPhone.Contains(dto.FromPhone!))                              // 来电号码
+            .WhereIF(!string.IsNullOrEmpty(dto.Contact), d => d.Order.Contact == dto.Contact)                                            // 联系电话
+            .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.Order.FromName == dto.FromName)                                         // 来电人姓名
+            .WhereIF(dto.CreationTimeStart.HasValue, d => d.Order.CreationTime >= dto.CreationTimeStart)                                 // 受理时间开始
+            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.Order.CreationTime <= dto.CreationTimeEnd)                                     // 受理时间结束
+            .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.Order.ExpiredTime >= dto.ExpiredTimeStart)                                    // 期满时间开始
+            .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.Order.ExpiredTime <= dto.ExpiredTimeEnd)                                        // 期满时间结束
+            .WhereIF(dto.Status.HasValue, d => d.Order.Status == dto.Status)                                                             // 工单状态
+            .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.Order.AreaCode == dto.AreaCode)                                         // 区域
+            .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.Order.SourceChannelCode == dto.Channel)                                  // 来源渠道
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value, d => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == d.OrderId && q.VisitDetailId == d.Id).Any())             // 是否甄别
+            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value == false, d => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == d.OrderId && q.VisitDetailId == d.Id).NotAny())
+            .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepName), d => d.Order.CurrentStepName == dto.CurrentStepName)                    // 当前办理节点
+            .WhereIF(dto.FiledTimeStart.HasValue, d => d.Order.FiledTime >= dto.FiledTimeStart)                                          // 办结时间开始
+            .WhereIF(dto.FiledTimeEnd.HasValue, d => d.Order.FiledTime <= dto.FiledTimeEnd)                                              // 办结时间结束
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.Order.HotspotSpliceName != null && d.Order.HotspotSpliceName.Contains(dto.Hotspot)) // 热点类型
+            .WhereIF(dto.IsSecret.HasValue, d => d.Order.IsSecret == dto.IsSecret)                                                       // 是否紧急
+
+            .OrderByIF(dto is { SortField: "order.creationTime", SortRule: 0 }, x => x.Order.CreationTime, OrderByType.Asc) // 受理时间升序
+            .OrderByIF(dto is { SortField: "order.creationTime", SortRule: 1 }, x => x.Order.CreationTime, OrderByType.Desc) // 受理时间升序
+            .OrderByIF(dto is { SortField: "order.filedTime", SortRule: 0 }, x => x.Order.FiledTime, OrderByType.Asc) // 办结时间升序
+            .OrderByIF(dto is { SortField: "order.filedTime", SortRule: 1 }, x => x.Order.FiledTime, OrderByType.Desc) // 办结时间升序
+            .OrderByIF(dto is { SortField: "visitTime", SortRule: 0 }, x => x.VisitTime, OrderByType.Asc) // 回访时间升序
+            .OrderByIF(dto is { SortField: "visitTime", SortRule: 1 }, x => x.VisitTime, OrderByType.Desc) // 回访时间升序
+            ;
+        return query;
+    }
+
     /// <summary>
     /// 热点类型小类统计明细
     /// </summary>

+ 4 - 2
src/Hotline.Application/StatisticalReport/CallReport/CallReportApplicationBase.cs

@@ -148,7 +148,8 @@ public abstract class CallReportApplicationBase : ICallReportApplication
                      RecordingFileUrl = recordPrefix + p.AudioFile,
                      RecordingFileName = p.AudioFile,
                      RecordingBaseAddress = recordPrefix,
-                     RecordingAbsolutePath = p.AudioFile
+                     RecordingAbsolutePath = p.AudioFile,
+                     CreatedTime = p.CreationTime
                  }, true);
 
         if (isAll)
@@ -206,7 +207,8 @@ public abstract class CallReportApplicationBase : ICallReportApplication
                     RecordingFileUrl = recordPrefix + p.AudioFile,
                     RecordingFileName = p.AudioFile,
                     RecordingBaseAddress = recordPrefix,
-                    RecordingAbsolutePath = p.AudioFile
+                    RecordingAbsolutePath = p.AudioFile,
+                    CreatedTime = p.CreationTime
                 }, true);
 
         if (isAll)

+ 4 - 2
src/Hotline.Application/StatisticalReport/CallReport/YiBinCallReportApplication.cs

@@ -127,7 +127,8 @@ public class YiBinCallReportApplication : CallReportApplicationBase, ICallReport
                      EndTime = m.OverTime,
                      OrderId = m.Order.Id,
                      OrderTitle = m.Order.Title,
-                     OrderNo = m.Order.No
+                     OrderNo = m.Order.No,
+                     CreatedTime = m.CreationTime
                  }, true);
         if (isAll)
         {
@@ -175,7 +176,8 @@ public class YiBinCallReportApplication : CallReportApplicationBase, ICallReport
                      EndTime = p.OverTime,
                      OrderId = p.Order.Id,
                      OrderTitle = p.Order.Title,
-                     OrderNo = p.Order.No
+                     OrderNo = p.Order.No,
+                     CreatedTime = p.CreationTime
                  }, true);
 
         if (isAll)

+ 80 - 2
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -156,10 +156,88 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 回访人是否为空
         /// </summary>
-        public bool? IsEmployeeNameNull { get; set;}
+        public bool? IsEmployeeNameNull { get; set; }
 
     }
 
+    public record QueryOrderVisitListDto : QueryOrderVisitDto
+    {
+        public string? UserID { get; set; }
+        public string? UserName { get; set; }
+        public string? FieldName { get; set; }
+        public string? Title { get; set; }
+
+        /// <summary>
+        /// 受理类型
+        /// </summary>
+        public string? AcceptType { get; set; }
+
+        /// <summary>
+        /// 受理人
+        /// </summary>
+        public string? AcceptorName { get; set; }
+
+        /// <summary>
+        /// 接办人
+        /// </summary>
+        public string? ActualHandlerName { get; set; }
+
+        /// <summary>
+        /// 来电人
+        /// </summary>
+        public string? FromName { get; set; }
+
+        /// <summary>
+        /// 期满时间开始
+        /// </summary>
+        public DateTime? ExpiredTimeStart { get; set; }
+
+        /// <summary>
+        /// 期满时间结束
+        /// </summary>
+        public DateTime? ExpiredTimeEnd { get; set; }
+
+        /// <summary>
+        /// 工单状态
+        /// </summary>
+        public EOrderStatus? Status { get; set; }
+
+        /// <summary>
+        /// 区域
+        /// </summary>
+        public string? AreaCode { get; set; }
+
+        /// <summary>
+        /// 当前节点
+        /// </summary>
+        public string? CurrentStepName { get; set; }
+
+        /// <summary>
+        /// 办结时间开始
+        /// </summary>
+        public DateTime? FiledTimeStart { get; set; }
+
+        /// <summary>
+        /// 办结时间结束
+        /// </summary>
+        public DateTime? FiledTimeEnd { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string? Hotspot { get; set; }
+
+        /// <summary>
+        /// 是否紧急
+        /// </summary>
+        public bool? IsSecret { get; set; }
+
+        /// <summary>
+        /// 是否甄别
+        /// </summary>
+        public bool? IsScreen { get; set; }
+    }
+
     public record QueryOrderPublishStatisticsAllDto : PagedRequest
     {
         /// <summary>
@@ -495,7 +573,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 是否观察件
         /// </summary>
-        public bool? IsObservationPiece {  get; set; }
+        public bool? IsObservationPiece { get; set; }
 
 
     }

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

@@ -861,6 +861,11 @@ namespace Hotline.Share.Dtos.TrCallCenter
         /// 用户名
         /// </summary>
         public string UserName { get; set; }
+        
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public DateTime? CreatedTime { get; set; }
 
         /// <summary>
         /// 开始等待时间