瀏覽代碼

Merge branch 'test' into feature/order_handle_main_secondary

xfe 4 月之前
父節點
當前提交
f42808e0bc
共有 34 個文件被更改,包括 833 次插入392 次删除
  1. 13 0
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  2. 3 0
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  3. 54 2
      src/Hotline.Api/Controllers/IPPbxController.cs
  4. 70 50
      src/Hotline.Api/Controllers/OrderController.cs
  5. 1 1
      src/Hotline.Api/StartupExtensions.cs
  6. 12 0
      src/Hotline.Application/Knowledge/KnowApplication.cs
  7. 27 12
      src/Hotline.Application/Mappers/OrderMapperConfigs.cs
  8. 12 7
      src/Hotline.Application/Mappers/WorkflowMapperConfigs.cs
  9. 105 75
      src/Hotline.Application/Orders/OrderApplication.cs
  10. 2 2
      src/Hotline.Application/Orders/OrderScreenHandler/OrderScreenEndWorkflowHandler.cs
  11. 2 0
      src/Hotline.Application/StatisticalReport/ICallReportApplication.cs
  12. 2 1
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  13. 84 0
      src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs
  14. 35 0
      src/Hotline.Share/Dtos/FlowEngine/Workflow/StepBasicDto.cs
  15. 130 90
      src/Hotline.Share/Dtos/Knowledge/KnowledgePagedDto.cs
  16. 43 28
      src/Hotline.Share/Dtos/Order/Detail/OrderFlowTraceDto.cs
  17. 31 6
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  18. 9 0
      src/Hotline.Share/Dtos/Order/OrderStartFlowDto.cs
  19. 5 0
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  20. 12 2
      src/Hotline.Share/Dtos/Order/Publish/QueryOrderPublishDto.cs
  21. 6 0
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  22. 6 1
      src/Hotline.Share/Enums/FlowEngine/EReviewResult.cs
  23. 9 0
      src/Hotline.Share/Enums/Order/EVisitType.cs
  24. 6 0
      src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs
  25. 73 55
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  26. 1 1
      src/Hotline/FlowEngine/Workflows/WorkflowTrace.cs
  27. 7 0
      src/Hotline/Orders/Order.cs
  28. 40 37
      src/Hotline/Orders/OrderDomainService.cs
  29. 5 0
      src/Hotline/Settings/SettingConstants.cs
  30. 5 5
      src/Hotline/Statistics/StatisticsDepart.cs
  31. 5 5
      src/Hotline/Statistics/StatisticsDepartSatisfied.cs
  32. 5 5
      src/Hotline/Statistics/StatisticsHotspotSatisfied.cs
  33. 5 5
      src/Hotline/Statistics/StatisticsPurTypeSatisfied.cs
  34. 8 2
      src/Hotline/dataview.md

+ 13 - 0
src/Hotline.Api/Controllers/Bi/BiCallController.cs

@@ -628,5 +628,18 @@ public class BiCallController : BaseController
             , "企业服务话务明细","Date");
 
 
+    /// <summary>
+    /// 呼出话务统计明细
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("query-callout-date-statistics")]
+    public async Task<object> QueryCallOutDateStatisticsDetail([FromQuery] QueryCallDateStatisticsDetailDto dto)
+    {
+        //var list = await _callReportApplication.QueryCallOutDateStatisticsDetail(dto);
+        //return new { List = null, Total = null };
+        return null;
+
+    }
     #endregion
 }

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

@@ -3858,6 +3858,8 @@ namespace Hotline.Api.Controllers.Bi
             else
                 items = await _systemOrganizeRepository.GetOrgJsonForUser(_sessionContext.RequiredOrgId); ;
 
+            var wfModule = await _workflowApplication.GetWorkflowModuleAsync(WorkflowModuleConsts.OrderHandle, HttpContext.RequestAborted);
+            var definition = wfModule.Definition;
             return new Dictionary<string, dynamic>
             {
                 { "visitSatisfaction", _systemDicDataCacheManager.GetVisitSatisfaction() },
@@ -3867,6 +3869,7 @@ namespace Hotline.Api.Controllers.Bi
                 { "channelOptions",_sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel) },
                 { "acceptTypeOptions",_sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType)},
                 { "orderStatusOptions", EnumExts.GetDescriptions<EOrderStatus>()},
+                { "currentStepOptions",definition?.Steps.Select(x => new Kv(x.Code, x.Name))}
             };
         }
 

+ 54 - 2
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -43,6 +43,7 @@ using Hotline.Repository.SqlSugar.CallCenter;
 using SqlSugar;
 using Hotline.Tools;
 using Hotline.Api.Filter;
+using XF.Domain.Cache;
 
 namespace Hotline.Api.Controllers
 {
@@ -69,7 +70,7 @@ namespace Hotline.Api.Controllers
         private readonly IRepository<QualityTemplate> _qualityTemplate;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
         private readonly IRepository<TelActionRecord> _telActionRecordRepository;
-        
+        private readonly ITypedCache<Work> _cacheWork;
         private readonly ISystemMobilAreaApplication _systemMobilAreaApplication;
         private readonly IRepository<Work> _workRepository;
         private readonly Publisher _publisher;
@@ -85,7 +86,7 @@ namespace Hotline.Api.Controllers
             ITelApplication telApplication, IRepository<Quality.Quality> qualiteyRepository,
             IAiQualityService aiQualityService, IRepository<QualityTemplate> qualityTemplate,
             ISystemSettingCacheManager systemSettingCacheManager, IRepository<TelActionRecord> telActionRecordRepository,
-            ISystemMobilAreaApplication systemMobilAreaApplication, IRepository<Work> workRepository, Publisher publisher, ITrCallRecordRepository callRecordRepository)
+            ISystemMobilAreaApplication systemMobilAreaApplication, IRepository<Work> workRepository, Publisher publisher, ITrCallRecordRepository callRecordRepository, ITypedCache<Work> cacheWork)
         {
             _trClient = trClient;
             _mapper = mapper;
@@ -112,6 +113,7 @@ namespace Hotline.Api.Controllers
             _workRepository = workRepository;
             _publisher = publisher;
             _callRecordRepository = callRecordRepository;
+            _cacheWork = cacheWork;
         }
 
         #region 添添呼
@@ -885,6 +887,56 @@ namespace Hotline.Api.Controllers
 
         #endregion
 
+        #region 话机状态
+
+        /// <summary>
+        /// 重置话机状态
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("tels-status-refreshservice")]
+        [AllowAnonymous]
+        public async Task TelsStatusRefreshService()
+        {
+            try
+            {
+                var list = await _workRepository.Queryable().Where(x => 1 == 1 && !x.EndTime.HasValue).ToListAsync();
+                var tellist = await _trClient.QueryTelStateAsync(new Tr.Sdk.Tels.QueryTelStateRequest { },HttpContext.RequestAborted);
+                foreach (var item in list)
+                {
+                    var telmodel = tellist.AgentList.First(x => x.TelNo == item.TelNo);
+                    if (telmodel != null)
+                    {
+                        if (telmodel.State == "logout")
+                        {
+                            var telRest = await _telRestRepository.GetAsync(x => x.TelNo == item.TelNo && !x.EndTime.HasValue, HttpContext.RequestAborted);
+                            if (telRest is not null)
+                            {
+                                telRest.EndRest();
+                                await _telRestRepository.UpdateAsync(telRest, HttpContext.RequestAborted);
+                            }
+
+                            item.OffDuty();
+                            await _workRepository.UpdateAsync(item, HttpContext.RequestAborted);
+                            _cacheWork.Remove(item.GetKey(KeyMode.UserId));
+                            _cacheWork.Remove(item.GetKey(KeyMode.TelNo));
+                            var listx = await _telActionRecordRepository.Queryable().Where(x => x.TelNo == item.TelNo && !x.EndTime.HasValue).ToListAsync();
+                            foreach (var itemx in listx)
+                            {
+                                itemx.EndAction();
+                                await _telActionRecordRepository.UpdateAsync(itemx);
+                            }
+                        }
+                    }
+                }
+            }
+            catch
+            {
+
+            }
+        }
+
+        #endregion
+
         #endregion
     }
 }

+ 70 - 50
src/Hotline.Api/Controllers/OrderController.cs

@@ -291,11 +291,15 @@ public class OrderController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("publish/items")]
-    public async Task<IList<PublishDto>> GetPublishOrderListAsync([FromQuery] QueryOrderPublishDto dto)
+    public async Task<IReadOnlyList<PublishDto>> GetPublishOrderListAsync([FromQuery] QueryOrderPublishDto dto)
     {
-        var query = _orderApplication.GetPublishOrderList(dto);
-        return (await query.ToFixedListAsync(dto.QueryIndex, 200, HttpContext.RequestAborted))
-            .Adapt<List<PublishDto>>();
+        var orders = await _orderApplication.GetPublishOrderList(dto)
+            .ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
+
+        return _mapper.Map<IReadOnlyList<PublishDto>>(orders);
+
+        //return (await query.ToFixedListAsync(dto.QueryIndex, 200, HttpContext.RequestAborted))
+        //    .Adapt<List<PublishDto>>();
     }
 
     /// <summary>
@@ -604,46 +608,52 @@ public class OrderController : BaseController
 
         //需求251  某些工单需自动发送短信
         //任何类型的省工单都不需要发送短信
-        try
+
+        var isOpenSendEndSms = _systemSettingCacheManager.GetSetting(SettingConstants.IsOpenSendEndSms)?.SettingValue[0];
+        if (isOpenSendEndSms == "true")
         {
-            if (order.Source != ESource.ProvinceStraight && _appOptions.Value.IsYiBin)
+            try
             {
-                var code = "";
-                //受理类型为“投诉、举报”
-                if ((order.AcceptTypeCode == "30" || order.AcceptTypeCode == "35") && orderVisit.VisitState != EVisitState.Visited)
+                if (order.Source != ESource.ProvinceStraight)
                 {
-                    code = "1017";
-                    orderVisit.VisitState = EVisitState.SMSVisiting;
-                    await _orderVisitRepository.UpdateAsync(orderVisit);
-                }
-                else
-                    code = "1018";
 
-                var messageDto = new Share.Dtos.Push.MessageDto
-                {
-                    PushBusiness = EPushBusiness.SearchSms,
-                    ExternalId = visitId,
-                    OrderId = order.Id,
-                    PushPlatform = EPushPlatform.Sms,
-                    Remark = order.Title,
-                    Name = order.FromName,
-                    TemplateCode = code,
-                    Params = new List<string>() { order.No, order.Password },
-                    TelNumber = order.Contact,
-                };
-                await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
-
-                // 发送短信后推送一个 48小时的延迟消息队列. 当消息队列收到消息时, 判断用户是否回复了, 如果未回复短信就 默认满意
-                var delaySecond = _systemSettingCacheManager.DefaultVisitSmsDelaySecond;
-                await _capPublisher.PublishDelayAsync(
-                    TimeSpan.FromSeconds(delaySecond),
-                    EventNames.UpdateVisitDelaySms,
-                    messageDto,
-                    cancellationToken: HttpContext.RequestAborted);
+                    var code = "";
+                    //受理类型为“投诉、举报”
+                    if ((order.AcceptTypeCode == "30" || order.AcceptTypeCode == "35") && orderVisit.VisitState != EVisitState.Visited)
+                    {
+                        code = "1017";
+                        orderVisit.VisitState = EVisitState.SMSVisiting;
+                        await _orderVisitRepository.UpdateAsync(orderVisit);
+                    }
+                    else
+                        code = "1018";
+
+                    var messageDto = new Share.Dtos.Push.MessageDto
+                    {
+                        PushBusiness = EPushBusiness.SearchSms,
+                        ExternalId = visitId,
+                        OrderId = order.Id,
+                        PushPlatform = EPushPlatform.Sms,
+                        Remark = order.Title,
+                        Name = order.FromName,
+                        TemplateCode = code,
+                        Params = new List<string>() { order.No, order.Password },
+                        TelNumber = order.Contact,
+                    };
+                    await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+
+                    // 发送短信后推送一个 48小时的延迟消息队列. 当消息队列收到消息时, 判断用户是否回复了, 如果未回复短信就 默认满意
+                    var delaySecond = _systemSettingCacheManager.DefaultVisitSmsDelaySecond;
+                    await _capPublisher.PublishDelayAsync(
+                        TimeSpan.FromSeconds(delaySecond),
+                        EventNames.UpdateVisitDelaySms,
+                        messageDto,
+                        cancellationToken: HttpContext.RequestAborted);
+                }
+            }
+            catch (Exception)
+            {
             }
-        }
-        catch (Exception)
-        {
         }
 
         if (orderVisit.VisitState == EVisitState.Visited && !order.IsProvince)
@@ -756,11 +766,15 @@ public class OrderController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("published/items")]
-    public async Task<IList<PublishedDto>> GetPublishedOrderListAsync([FromQuery] PublishedPagedRequest dto)
+    public async Task<IReadOnlyList<PublishedDto>> GetPublishedOrderListAsync([FromQuery] PublishedPagedRequest dto)
     {
-        var query = _orderApplication.GetPublishedOrder(dto);
-        return (await query.ToFixedListAsync(dto.QueryIndex, 200, HttpContext.RequestAborted))
-            .Adapt<List<PublishedDto>>();
+        //var query = _orderApplication.GetPublishedOrder(dto);
+        //return (await query.ToFixedListAsync(dto.QueryIndex, 200, HttpContext.RequestAborted))
+            //.Adapt<List<PublishedDto>>();
+            var orderPublishs = await _orderApplication.GetPublishedOrder(dto)
+                .ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
+
+            return _mapper.Map<IReadOnlyList<PublishedDto>>(orderPublishs);
     }
 
     /// <summary>
@@ -998,8 +1012,11 @@ public class OrderController : BaseController
     public async Task<PagedDto<OrderVisitDto>> QueryOrderVisitList([FromQuery] QueryOrderVisitDto dto)
     {
         var (total, items) = await _orderApplication.QueryOrderVisitList(dto).ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-
         return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
+
+        //var orderVisits = await _orderApplication.QueryOrderVisitList(dto)
+        //    .ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
+        //return _mapper.Map<>()
     }
 
     /// <summary>
@@ -1059,7 +1076,8 @@ public class OrderController : BaseController
             { "visitSatisfaction", _sysDicDataCacheManager.GetVisitSatisfaction().Where(m => m.DicDataValue != "-1").ToList() },
             { "visitMananer", _sysDicDataCacheManager.VisitMananer.Where(x => x.DicDataValue != "-1").ToList() },
             { "visitStateQuery", EnumExts.GetDescriptions<EVisitStateQuery>() },
-            { "sourceChannel", _sysDicDataCacheManager.SourceChannel }
+            { "sourceChannel", _sysDicDataCacheManager.SourceChannel },
+            { "aiVisitResult", EnumExts.GetDescriptions<EAiVisitResult>() }
         };
 
     /// <summary>
@@ -3080,12 +3098,14 @@ public class OrderController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet]
-    public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDto dto)
+    public async Task<IReadOnlyList<OrderDto>> Query([FromQuery] QueryOrderDto dto)
     {
-        var query = _orderApplication.QueryOrders(dto);
-        var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
-
-        return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        //var query = _orderApplication.QueryOrders(dto);
+        //var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
+        //return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        var orders = await _orderApplication.QueryOrders(dto)
+            .ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
+        return _mapper.Map<IReadOnlyList<OrderDto>>(orders);
     }
 
     /// <summary>

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

@@ -168,7 +168,7 @@ internal static class StartupExtensions
                     .AddScoped<ICallApplication, TianRunCallApplication>()
                     .AddScoped<ITrApplication, TrApplication>()
                     .AddHostedService<CurrentWaitNumService>()
-                    .AddHostedService<TelsStatusRefreshService>()
+                    //.AddHostedService<TelsStatusRefreshService>()
                     .AddTrSdk(callCenterConfiguration.TianRun.Address,
                         callCenterConfiguration.TianRun.Username,
                         callCenterConfiguration.TianRun.Password);

+ 12 - 0
src/Hotline.Application/Knowledge/KnowApplication.cs

@@ -102,6 +102,18 @@ namespace Hotline.Application.Knowledge
                 .WhereIF(pagedDto.Status ==  EKnowledgeStatus.NewDrafts ,x=>x.Status == EKnowledgeStatus.Drafts || x.Status == EKnowledgeStatus.Revert)
                 .WhereIF(pagedDto.NewDraftsStatus is EKnowledgeStatus.Drafts , x=>x.Status == EKnowledgeStatus.Drafts)
                 .WhereIF(pagedDto.NewDraftsStatus is EKnowledgeStatus.Revert, x => x.Status == EKnowledgeStatus.Revert)
+
+                .WhereIF(pagedDto.CreationStartTime.HasValue,x=>x.CreationTime>= pagedDto.CreationStartTime)
+                .WhereIF(pagedDto.CreationEndTime.HasValue, x => x.CreationTime <= pagedDto.CreationEndTime)
+
+                  .WhereIF(pagedDto.StartOnShelfTime.HasValue, x => x.OnShelfTime >= pagedDto.StartOnShelfTime)
+                  .WhereIF(pagedDto.EndOnShelfTime.HasValue, x => x.OnShelfTime <= pagedDto.EndOnShelfTime)
+
+                   .WhereIF(pagedDto.StartOffShelfTime.HasValue, x => x.OffShelfTime >= pagedDto.StartOffShelfTime)
+                  .WhereIF(pagedDto.EndOffShelfTime.HasValue, x => x.OffShelfTime <= pagedDto.EndOffShelfTime)
+
+                  .WhereIF(pagedDto.StartUpdateTime.HasValue, x => x.LastModificationTime >= pagedDto.StartUpdateTime)
+                  .WhereIF(pagedDto.EndUpdateTime.HasValue, x => x.LastModificationTime <= pagedDto.EndUpdateTime)
                 .WhereIF(!string.IsNullOrEmpty(pagedDto.Attribution),x=>x.Attribution == pagedDto.Attribution)
 				.OrderByDescending(d => d.CreationTime)
                 .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize, cancellationToken);

+ 27 - 12
src/Hotline.Application/Mappers/OrderMapperConfigs.cs

@@ -18,6 +18,7 @@ public class OrderMapperConfigs : IRegister
         config.ForType<Order, OrderDto>()
             .IgnoreIf((s, d) => s.OrderExtension == null, d => d.OrderExtension)
             .IgnoreIf((s, d) => s.Hotspot == null, d => d.Hotspot)
+               .IgnoreIf((s, d) => s.FwCallRecord == null, d => d.FwCallRecord)
             //.Map(d => d.IsRed, s => string.IsNullOrEmpty(s.SignerId) || !s.ActualHandleStepAcceptTime.HasValue)
             .Map(d => d.IsRed, s => s.WorkflowSteps != null
                                     && s.WorkflowSteps.Any()
@@ -230,24 +231,38 @@ public class OrderMapperConfigs : IRegister
             .Map(d => d.No, s => s.CaseSerial);
 
         config.ForType<WorkflowTrace, OrderFlowTraceDto>()
-            .IgnoreIf((s, d) => s.OrderPublish == null, d => d.PublishState)
+            .IgnoreIf((s, d) => s.TraceStyle != ETraceStyle.Publish || s.OrderPublish == null, d => d.PublishState)
             .Map(d => d.PublishState, s => s.OrderPublish.PublishState)
-            .IgnoreIf((s, d) => s.OrderPublish == null, d => d.ArrangeOpinion)
+            .IgnoreIf((s, d) => s.TraceStyle != ETraceStyle.Publish || s.OrderPublish == null, d => d.ArrangeOpinion)
             .Map(d => d.ArrangeOpinion, s => s.OrderPublish.ArrangeOpinion)
-            .IgnoreIf((s, d) => s.OrderVisit == null || s.OrderVisit.OrderVisitDetails.All(x => x.VisitTarget != EVisitTarget.Seat), d => d.VoiceEvaluate)
-            .Map(d => d.VoiceEvaluate, s => s.OrderVisit.OrderVisitDetails.First(x => x.VisitTarget == EVisitTarget.Seat).VoiceEvaluate)
-            .IgnoreIf((s, d) => s.OrderVisit == null || s.OrderVisit.OrderVisitDetails.All(x => x.VisitTarget != EVisitTarget.Seat), d => d.SeatEvaluate)
-            .Map(d => d.SeatEvaluate, s => s.OrderVisit.OrderVisitDetails.First(x => x.VisitTarget == EVisitTarget.Seat).SeatEvaluate)
-            .IgnoreIf((s, d) => s.OrderVisit == null || s.OrderVisit.OrderVisitDetails.All(x => x.VisitTarget != EVisitTarget.Seat), d => d.VisitContent)
-            .Map(d => d.VisitContent, s => s.OrderVisit.OrderVisitDetails.First(x => x.VisitTarget == EVisitTarget.Seat).VisitContent)
-            .IgnoreIf((s, d) => s.OrderVisit == null || s.OrderVisit.OrderVisitDetails.All(x => x.VisitTarget != EVisitTarget.Org), d => d.OrderFlowVisitDetails)
-            .Map(d => d.OrderFlowVisitDetails, s => s.OrderVisit.OrderVisitDetails.Where(x => x.VisitTarget == EVisitTarget.Org))
+            .AfterMapping((s, d) =>
+            {
+                if(s.TraceStyle == ETraceStyle.Visit 
+                   && s.OrderVisit != null 
+                   && s.OrderVisit.OrderVisitDetails.Any(x => x.VisitTarget == EVisitTarget.Seat))
+                {
+                    d.VoiceEvaluate = s.OrderVisit.OrderVisitDetails.First(x => x.VisitTarget == EVisitTarget.Seat).VoiceEvaluate;
+                    d.SeatEvaluate = s.OrderVisit.OrderVisitDetails.First(x => x.VisitTarget == EVisitTarget.Seat).SeatEvaluate;
+                    d.VisitContent = s.OrderVisit.OrderVisitDetails.First(x => x.VisitTarget == EVisitTarget.Seat).VisitContent;
+                }
+                if(s.TraceStyle == ETraceStyle.Visit
+                   && s.OrderVisit != null
+                   && s.OrderVisit.OrderVisitDetails.Any(x => x.VisitTarget == EVisitTarget.Org))
+                {
+                    d.OrderFlowVisitDetails = s.OrderVisit.OrderVisitDetails
+                        .Where(x => x.VisitTarget == EVisitTarget.Org)
+                        .ToList()
+                        .Adapt<IReadOnlyList<OrderFlowVisitDetail>>();
+                }
+            })
             ;
 
         config.ForType<OrderVisitDetail, OrderFlowVisitDetail>()
             .Map(d => d.OrgProcessingResults, s => s.OrgProcessingResults.Value)
-            .Map(d => d.OrgNoSatisfiedReason, s => string.Join(',', s.OrgNoSatisfiedReason.Select(d => d.Value)))
-            .Map(d => d.OrgHandledAttitude, s => s.OrgHandledAttitude.Value);
+            .Map(d => d.OrgNoSatisfiedReason, s => s.OrgNoSatisfiedReason.Select(d => d.Value))
+            .Map(d => d.OrgHandledAttitude, s => s.OrgHandledAttitude.Value)
+            ;
+
 
     }
 }

+ 12 - 7
src/Hotline.Application/Mappers/WorkflowMapperConfigs.cs

@@ -45,19 +45,24 @@ public class WorkflowMapperConfigs : IRegister
 
         config.ForType<WorkflowStep, WorkflowTrace>()
             .Ignore(d=>d.Workflow)
+            .Ignore(d=>d.OrderPublish)
+            .Ignore(d=>d.OrderVisit)
+            .Ignore(d=>d.Traces)
             .Ignore(d => d.ParentId)
             .Ignore(d => d.TraceType)
             .Map(d => d.StepId, s => s.Id)
             .AfterMapping((s, d) => d.Id = s.Id)
             ;
 
-        // config.ForType<WorkflowSupplement, WorkflowSupplementDto>()
-        //     .Map(d => d.CreationTime, x => x.CreationTime)
-        //     .Map(d => d.Additions, x => x.Additions)
-        //     .Map(d => d.Opinion, x => x.Opinion)
-        //     .Map(d => d.Creator.Name, x => x.Creator.Name)
-        //     .IgnoreNonMapped(true)
-        //     ;
+        config.ForType<WorkflowTrace, WorkflowTrace>()
+            .Ignore(d=>d.Id)
+            .Ignore(d => d.Workflow)
+            .Ignore(d => d.OrderPublish)
+            .Ignore(d => d.OrderVisit)
+            .Ignore(d => d.Traces)
+            .Ignore(d => d.ParentId)
+            .Ignore(d => d.TraceType)
+            ;
 
         config.ForType<Workflow, WorkflowDto>()
             //.IgnoreIf((s, d) => s.Assigns == null || !s.Assigns.Any(), d => d.AssignOrgs)

+ 105 - 75
src/Hotline.Application/Orders/OrderApplication.cs

@@ -1,4 +1,5 @@
-using DotNetCore.CAP;
+using DocumentFormat.OpenXml.Drawing;
+using DotNetCore.CAP;
 using Hotline.Application.Quality;
 using Hotline.Authentications;
 using Hotline.Caching.Interfaces;
@@ -344,9 +345,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门
-                                                                                                                           //&& stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value
-                                                                                                                           //.Where(d => d.ExpiredTime != null &&
-                                                                                                                           //         d.Status != EOrderStatus.Filed && d.Status != EOrderStatus.Published && d.Status != EOrderStatus.Visited && stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value)
+                                                                                                                                   //&& stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value
+                                                                                                                                   //.Where(d => d.ExpiredTime != null &&
+                                                                                                                                   //         d.Status != EOrderStatus.Filed && d.Status != EOrderStatus.Published && d.Status != EOrderStatus.Visited && stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value)
             .Where(d => d.Status < EOrderStatus.Filed && dateTime > d.NearlyExpiredTime && dateTime < d.ExpiredTime)
             .OrderByIF(dto is { SortField: "no", SortRule: 0 }, x => x.No, OrderByType.Asc) //工单编号升序
             .OrderByIF(dto is { SortField: "no", SortRule: 1 }, x => x.No, OrderByType.Desc) //工单编号降序
@@ -427,9 +428,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门
-             //&& stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value
-             //.Where(d => d.ExpiredTime != null &&
-            // d.Status != EOrderStatus.Filed && d.Status != EOrderStatus.Published && d.Status != EOrderStatus.Visited && stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value)
+                                                                                                                                   //&& stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value
+                                                                                                                                   //.Where(d => d.ExpiredTime != null &&
+                                                                                                                                   // d.Status != EOrderStatus.Filed && d.Status != EOrderStatus.Published && d.Status != EOrderStatus.Visited && stTime >= d.ExpiredTime.Value && stTime2 <= d.ExpiredTime.Value)
             .Where(d => d.Status < EOrderStatus.Filed && dateTime > d.NearlyExpiredTime && dateTime < d.ExpiredTime)
             .OrderByIF(dto is { SortField: "no", SortRule: 0 }, x => x.No, OrderByType.Asc) //工单编号升序
             .OrderByIF(dto is { SortField: "no", SortRule: 1 }, x => x.No, OrderByType.Desc) //工单编号降序
@@ -691,51 +692,57 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     /// <returns></returns>
     public ISugarQueryable<Order> GetPublishOrderList(QueryOrderPublishDto dto)
     {
-        return _orderRepository.Queryable()
-            //.Includes(d => d.OrderPublish)
-            .Where(x => x.Status == EOrderStatus.Filed)
-            .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!))
-            .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No))
-            .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
-            //.WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published)
-            //.WhereIF(dto.PubState == EPubState.NoPub, d => d.Status == EOrderStatus.Filed)
-            .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
-            .WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTagCode == dto.OrderTag!) //工单标签
-            .WhereIF(!string.IsNullOrEmpty(dto.CenterToOrgHandlerName), d => d.CenterToOrgHandlerName.Contains(dto.CenterToOrgHandlerName)) //派单人
-            .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo) || d.AcceptorStaffNo.Contains(dto.NameOrNo)) //受理人/坐席
-            .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
-            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType) //受理类型
-            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.OrgLevelOneName.Contains(dto.OrgLevelOneName)) //一级部门
-            .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone == dto.FromPhone) //来电号码
-                                                                                              //.WhereIF(!string.IsNullOrEmpty(dto.PubMan),
-                                                                                              //    d => d.AcceptorName.Contains(dto.PubMan!) || d.AcceptorStaffNo.Contains(dto.PubMan!))
-                                                                                              //.WhereIF(dto.PubRange == EPublicState.Pub, d => d.OrderPublish.PublishState)
-                                                                                              //.WhereIF(dto.PubRange == EPublicState.NoPub, d => !d.OrderPublish.PublishState)
-            .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(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.ProcessType == EProcessType.Zhiban)
-            //.WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.ProcessType == EProcessType.Jiaoban)
-            .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.FileOrgIsCenter == true)
-            .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.FileOrgIsCenter == false)
-            .WhereIF(dto.IsCountersign != null && dto.IsCountersign == true, d => d.CounterSignType != null)
-            .WhereIF(dto.IsCountersign != null && dto.IsCountersign == false, d => d.CounterSignType == null)
-            .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
-            .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId))
-            //.WhereIF(dto.Resolve.HasValue, d => d.OrderPublish.Resolve == dto.Resolve)
-            .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
-            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
-            .WhereIF(dto.FiledTimeStart.HasValue, d => d.FiledTime >= dto.FiledTimeStart)
-            .WhereIF(dto.FiledTimeEnd.HasValue, d => d.FiledTime <= dto.FiledTimeEnd)
-            .WhereIF(dto.QuerySelf.HasValue && dto.QuerySelf.Value, d => d.WaitForPublisherId == _sessionContext.RequiredUserId)
-             .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
-            .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)) //否 超期
-            .OrderByDescending(d => d.FiledTime);
+        var query = _orderRepository.Queryable();
+        if (_appOptions.Value.IsLuZhou)
+            query = query.Includes(d => d.FwCallRecord);
+        //.Includes(d => d.OrderPublish)
+        return query.Where(x => x.Status == EOrderStatus.Filed)
+              .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!))
+              .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No))
+              .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
+              //.WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published)
+              //.WhereIF(dto.PubState == EPubState.NoPub, d => d.Status == EOrderStatus.Filed)
+              .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.SourceChannelCode == dto.Channel)
+              .WhereIF(!string.IsNullOrEmpty(dto.OrderTag), d => d.OrderTagCode == dto.OrderTag!) //工单标签
+              .WhereIF(!string.IsNullOrEmpty(dto.CenterToOrgHandlerName), d => d.CenterToOrgHandlerName.Contains(dto.CenterToOrgHandlerName)) //派单人
+              .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo) || d.AcceptorStaffNo.Contains(dto.NameOrNo)) //受理人/坐席
+              .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
+              .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.AcceptTypeCode == dto.AcceptType) //受理类型
+              .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.HotspotSpliceName != null && d.HotspotSpliceName.Contains(dto.Hotspot))
+              .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.OrgLevelOneName.Contains(dto.OrgLevelOneName)) //一级部门
+              .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone == dto.FromPhone) //来电号码
+                                                                                                //.WhereIF(!string.IsNullOrEmpty(dto.PubMan),
+                                                                                                //    d => d.AcceptorName.Contains(dto.PubMan!) || d.AcceptorStaffNo.Contains(dto.PubMan!))
+                                                                                                //.WhereIF(dto.PubRange == EPublicState.Pub, d => d.OrderPublish.PublishState)
+                                                                                                //.WhereIF(dto.PubRange == EPublicState.NoPub, d => !d.OrderPublish.PublishState)
+              .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(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.ProcessType == EProcessType.Zhiban)
+              //.WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.ProcessType == EProcessType.Jiaoban)
+              .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.FileOrgIsCenter == true)
+              .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.FileOrgIsCenter == false)
+              .WhereIF(dto.IsCountersign != null && dto.IsCountersign == true, d => d.CounterSignType != null)
+              .WhereIF(dto.IsCountersign != null && dto.IsCountersign == false, d => d.CounterSignType == null)
+              .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
+              .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId))
+              //.WhereIF(dto.Resolve.HasValue, d => d.OrderPublish.Resolve == dto.Resolve)
+              .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
+              .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
+              .WhereIF(dto.FiledTimeStart.HasValue, d => d.FiledTime >= dto.FiledTimeStart)
+              .WhereIF(dto.FiledTimeEnd.HasValue, d => d.FiledTime <= dto.FiledTimeEnd)
+
+              .WhereIF(dto.ExpiredTimeProvinceStart.HasValue, d => d.ExpiredTimeProvince >= dto.ExpiredTimeProvinceStart)//省期满时间开始
+              .WhereIF(dto.ExpiredTimeProvinceEnd.HasValue, d => d.ExpiredTimeProvince <= dto.ExpiredTimeProvinceEnd)//省期满时间结束
+
+              .WhereIF(dto.QuerySelf.HasValue && dto.QuerySelf.Value, d => d.WaitForPublisherId == _sessionContext.RequiredUserId)
+               .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
+              .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))//否 超期
+              .OrderByDescending(d => d.FiledTime);
     }
 
     public ISugarQueryable<OrderPublish> GetPublishedOrder(PublishedPagedRequest dto)
@@ -1028,7 +1035,14 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         }
         else if (dto.Workflow.FlowDirection is EFlowDirection.CenterToOrg)
         {
-            expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, DateTime.Now, EFlowDirection.CenterToOrg, order.Adapt<OrderTimeClacInfo>());
+            if (_appOptions.Value.IsLuZhou)
+            {
+                expiredTimeConfig = await _expireTime.CalcEndTime(DateTime.Now, DateTime.Now, new TimeConfig() { Count = dto.Data.TimeLimit, TimeType = dto.Data.TimeLimitUnit.Value }, order.AcceptTypeCode);
+            }
+            else
+            {
+                expiredTimeConfig = await _expireTime.CalcExpiredTime(DateTime.Now, DateTime.Now, EFlowDirection.CenterToOrg, order.Adapt<OrderTimeClacInfo>());
+            }
             var canUpdateOrderSender = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CanUpdateOrderSender).SettingValue[0]);
             order.CenterToOrg(
                 expiredTimeConfig.TimeText, expiredTimeConfig.Count,
@@ -1337,7 +1351,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
          .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.StartTimeStart.HasValue, d => d.StartTime >= dto.StartTimeStart) //流程开启时间开始
+         .WhereIF(dto.StartTimeEnd.HasValue, d => d.StartTime <= dto.StartTimeEnd) //流程开启时间结束
+                                                                                   //.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) //推送分类
@@ -2978,8 +2994,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门
             .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.Order.OrgLevelOneName.Contains(dto.OrgLevelOneName)) //一级部门
             .WhereIF(dto.IdentityType != null, d => d.Order.IdentityType == dto.IdentityType) //来电主体
-           .WhereIF(dto.CreationTimeStart.HasValue, d => d.Order.CreationTime >= dto.CreationTimeStart)
+            .WhereIF(dto.CreationTimeStart.HasValue, d => d.Order.CreationTime >= dto.CreationTimeStart)
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.Order.CreationTime <= dto.CreationTimeEnd)
+            .WhereIF(dto.AiVisitResult.HasValue && dto.AiVisitResult == EAiVisitResult.OrgProcessingResultsNoSatisfied, d => d.VisitState == EVisitState.WaitForVisit && d.VisitType == EVisitType.ChipVoiceVisit && d.OrderVisitDetails.Any(m => SqlFunc.JsonField(m.OrgProcessingResults, "Key") == "2"))
             .OrderByDescending(x => x.PublishTime)
             .WhereIF(!string.IsNullOrEmpty(dto.Channel), d => d.Order.SourceChannelCode == dto.Channel)
             .OrderByDescending(d => d.PublishTime);
@@ -3439,33 +3456,46 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                     : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept or EOrderStatus.SpecialToUnAccept or EOrderStatus.HandOverToUnAccept or EOrderStatus.Handling)
             .ToArray();
 
-        var query = _orderRepository.Queryable()
-            .Includes(d => d.WorkflowSteps.Where(step =>
-                    ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
-                     (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
-                     (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)) ||
-                     (step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)
-                      && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId)))
-                .OrderByDescending(step => step.CreationTime)
-                .Take(1)
-                .ToList()
-            );
+        //var query = _orderRepository.Queryable()
+        //    .Includes(d => d.WorkflowSteps.Where(step =>
+        //            ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
+        //             (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
+        //             (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)) ||
+        //             (step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)
+        //              && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId)))
+        //        .OrderByDescending(step => step.CreationTime)
+        //        .Take(1)
+        //        .ToList()
+        //    );
+        var query = _orderRepository.Queryable();
 
         var hasHandled = dto.IsHandled.HasValue && dto.IsHandled.Value;
         if (hasHandled)
         {
-            query.Where(d => d.WorkflowSteps
-                .Any(step =>
-                    ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
-                     (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
-                     (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)) ||
-                     (step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)
-                      && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId))
-                    && step.Status == EWorkflowStepStatus.Handled));
+            query.Includes(d => d.WorkflowSteps.Where(step =>
+                    !string.IsNullOrEmpty(step.HandlerId)
+                    && step.HandlerId == _sessionContext.UserId
+                    && step.Status == EWorkflowStepStatus.Handled
+                ))
+                .Where(d => d.WorkflowSteps
+                    .Any(step =>
+                        !string.IsNullOrEmpty(step.HandlerId)
+                        && step.HandlerId == _sessionContext.UserId
+                        && step.Status == EWorkflowStepStatus.Handled));
         }
         else
         {
-            query.Where(d => d.WorkflowSteps
+
+            query.Includes(d => d.WorkflowSteps.Where(step =>
+                        ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
+                         (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||
+                         (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)) ||
+                         (step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && _sessionContext.Roles.Contains(step.RoleId)
+                          && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId)))
+                    .OrderByDescending(step => step.CreationTime)
+                    .Take(1)
+                    .ToList())
+                .Where(d => d.WorkflowSteps
                 .Any(step =>
                     ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == _sessionContext.RequiredUserId) ||
                      (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == _sessionContext.RequiredOrgId) ||

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

@@ -81,8 +81,8 @@ public class OrderScreenEndWorkflowHandler : INotificationHandler<EndWorkflowNot
                         {
                             var screenSatisfy = new Kv() { Key = "-1", Value = "视为满意" };
                             visitDetail.OrgProcessingResults = screenSatisfy;
-                            if (_appOptions.Value.IsYiBin)
-                                visitDetail.OrgNoSatisfiedReason = new List<Kv>();
+                            //if (_appOptions.Value.IsYiBin)
+                            //    visitDetail.OrgNoSatisfiedReason = new List<Kv>();
 
                             //visitDetail.OrgHandledAttitude = screenSatisfy;
                             await _orderVisitedDetailRepository.UpdateAsync(visitDetail, cancellationToken);

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

@@ -69,5 +69,7 @@ namespace Hotline.Application.StatisticalReport
         /// <param name="dto"></param>
         /// <returns></returns>
         Task<List<QueryEnterpriseCallDateStatisticsDetailResp>> QueryEnterpriseCallDateStatisticsDetail(QueryCallDateStatisticsDetailDto dto);
+
+        //Task<List<object>> QueryCallOutDateStatisticsDetail(QueryCallDateStatisticsDetailDto dto);
     }
 }

+ 2 - 1
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -1648,7 +1648,8 @@ namespace Hotline.Application.StatisticalReport
                 .WhereIF(dto.StartTime.HasValue, x => x.OrderVisit.VisitTime >= dto.StartTime.Value)
                 .WhereIF(dto.EndTime.HasValue, x => x.OrderVisit.VisitTime <= dto.EndTime.Value)
                 .WhereIF(isCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.RequiredOrgId))
-                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonListObjectAny(x.OrgProcessingResults, "Key", dto.OrgProcessingResults))
+                .WhereIF(dto.OrgProcessingResults == "-1", x => SqlFunc.JsonArrayLength(x.OrgNoSatisfiedReason) > 0)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
                 .GroupBy((x, org) => new { VisitOrgName = org.Name, VisitOrgCode = x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) })
                 .Select((x, org) => new BiVisitNoSatisfiedDto
                 {

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

@@ -394,4 +394,88 @@ public class QueryEnterpriseCallDateStatisticsDetailResp
     public string EnterpriseCallPutthorughRateText => EnterpriseCallPutthorughRate + "%";
 }
 
+public class QueryCallOutDateStatisticsDetailResp
+{
+    /// <summary>
+    /// 日期
+    /// </summary>
+    public string Date { get; set; }
+
+    /// <summary>
+    /// 呼出总量
+    /// </summary>
+    public int CallOutTotal => PersonCallOutCount + EnterpriseCallOutCount + AiVisitCallOutCount + AiCallOutCount;
+
+    /// <summary>
+    /// 个人服务呼出总量
+    /// </summary>
+    public int PersonCallOutCount { get; set; }
+
+    /// <summary>
+    /// 企业服务呼出总量
+    /// </summary>
+    public int EnterpriseCallOutCount { get; set; }
+
+    /// <summary>
+    /// 智能回访呼出总量
+    /// </summary>
+    public int AiVisitCallOutCount { get; set; }
+
+    /// <summary>
+    /// 智能外呼呼出总量
+    /// </summary>
+    public int AiCallOutCount { get; set; }
+
+    /// <summary>
+    /// 呼出接通数
+    /// </summary>
+    public int CallOutPutthroughCount => PersonCallOutPutthroughCount + EnterpriseCallOutPutthroughCount + AiVisitCallOutPutthroughCount + AiCallOutPutthroughCount;
+
+    /// <summary>
+    /// 个人服务呼出接通数
+    /// </summary>
+    public int PersonCallOutPutthroughCount { get; set; }
+
+    /// <summary>
+    /// 企业服务呼出接通数
+    /// </summary>
+    public int EnterpriseCallOutPutthroughCount { get; set; }
+
+    /// <summary>
+    /// 智能回访呼出接通数
+    /// </summary>
+    public int AiVisitCallOutPutthroughCount { get; set; }
+
+    /// <summary>
+    /// 智能外呼呼出接通数
+    /// </summary>
+    public int AiCallOutPutthroughCount { get; set; }
+
+    /// <summary>
+    /// 呼出接通率
+    /// </summary>
+    public double CallOutPutthroughRate => CallOutTotal == 0 ? 0 : Math.Round(((double)CallOutPutthroughCount / CallOutTotal) * 100, 2);
+
+    
+    /// <summary>
+    /// 个人服务呼出接通率
+    /// </summary>
+    public double PersonCallOutPutthroughRate => PersonCallOutCount == 0 ? 0 : Math.Round(((double)PersonCallOutPutthroughCount / PersonCallOutCount) * 100, 2);
+
+    /// <summary>
+    /// 企业服务呼出接通率
+    /// </summary>
+    public double EnterpriseCallOutPutthroughRate => EnterpriseCallOutCount == 0 ? 0 : Math.Round(((double)EnterpriseCallOutPutthroughCount / EnterpriseCallOutCount) * 100, 2);
+
+    /// <summary>
+    /// 智能回访呼出接通率
+    /// </summary>
+    public double AiVisitCallOutPutthroughRate => AiVisitCallOutCount == 0 ? 0 : Math.Round(((double)AiVisitCallOutPutthroughCount / AiVisitCallOutCount) * 100, 2);
+
+    /// <summary>
+    /// 智能外呼呼出接通率
+    /// </summary>
+    public double AiCallOutPutthroughRate => AiCallOutCount == 0 ? 0 : Math.Round(((double)AiCallOutPutthroughCount / AiCallOutCount) * 100, 2);
+}
+
 #endregion

+ 35 - 0
src/Hotline.Share/Dtos/FlowEngine/Workflow/StepBasicDto.cs

@@ -1,5 +1,6 @@
 using Hotline.Share.Dtos.File;
 using Hotline.Share.Enums.FlowEngine;
+using XF.Utility.EnumExtensions;
 
 namespace Hotline.Share.Dtos.FlowEngine.Workflow
 {
@@ -25,6 +26,26 @@ namespace Hotline.Share.Dtos.FlowEngine.Workflow
         /// </summary>
         public string? PrevChosenStepCode { get; set; }
 
+        #region 交办
+
+        /// <summary>
+        /// 交办人
+        /// </summary>
+        public string? AssignerId { get; set; }
+
+        public string? AssignerName { get; set; }
+
+        /// <summary>
+        /// 交办人部门Id
+        /// </summary>
+        public string? AssignerOrgId { get; set; }
+
+        public string? AssignerOrgName { get; set; }
+
+        public bool? AssignerOrgIsCenter { get; set; }
+
+        #endregion
+
         #region 接办
 
         /// <summary>
@@ -92,6 +113,20 @@ namespace Hotline.Share.Dtos.FlowEngine.Workflow
         /// </summary>
         public DateTime? HandleTime { get; set; }
 
+        /// <summary>
+        /// 办理方式
+        /// </summary>
+        public EHandleMode? HandleMode { get; set; }
+
+        public string? HandleModeText => HandleMode.HasValue ? HandleMode.GetDescription() : "";
+
+        /// <summary>
+        /// 审核结果(非审批流程无意义)
+        /// </summary>
+        public EReviewResult ReviewResult { get; set; }
+
+        public string ReviewResultText => ReviewResult.GetDescription();
+
         #endregion
 
         #region Definition

+ 130 - 90
src/Hotline.Share/Dtos/Knowledge/KnowledgePagedDto.cs

@@ -14,68 +14,68 @@ namespace Hotline.Share.Dtos.Knowledge
     /// <param name="id"></param>
     public record AuditLogListPagedDto(string? id) : PagedKeywordRequest;
 
-	/// <summary>
-	/// 审核管理
-	/// </summary>
-	/// <param name="EKnowledgeApplyType">申请类型</param>
-	/// <param name="EKnowledgeWorkFlowStatus">审核状态</param>
-	public record KnowledgeApprovalPagedListDto(EKnowledgeApplyType? EKnowledgeApplyType, EKnowledgeWorkFlowStatus? EKnowledgeWorkFlowStatus) : PagedKeywordRequest;
-
-	/// <summary>
-	/// 知识检索
-	/// </summary>
-	/// <param name="RetrievalType">检索类型</param>
-	/// <param name="Attribution">归属</param>
-	/// <param name="Sort">排序字段</param>
-	/// <param name="CreateOrgId">部门id</param>
-	/// <param name="HotspotId">热点id</param>
-	/// <param name="HotspotName">热点名称</param>;
-	/// <param name="KnowledgeTypeId">类型id</param>
-	/// <param name="Content">受理内容</param>
-	public record KnowledgeRetrievalPagedListDto : PagedKeywordRequest
-	{
-		/// <summary>
-		/// 检索类型
-		/// </summary>
-		public EKnowledgeRetrievalType? RetrievalType { get; set; }
-
-		/// <summary>
-		/// 归属
-		/// </summary>
-		public string? Attribution { get; set; }
-
-		/// <summary>
-		/// 排序字段
-		/// </summary>
-		public string Sort { get; set; }
-
-		/// <summary>
-		/// 部门id
-		/// </summary>
-		public string? CreateOrgId { get; set; }
-
-		/// <summary>
-		/// 热点id
-		/// </summary>
-		public string? HotspotId { get; set; }
-
-		/// <summary>
-		/// 热点名称
-		/// </summary>
-		public string? HotspotName { get; set; }
-
-		/// <summary>
-		/// 类型id
-		/// </summary>
-		public string? KnowledgeTypeId { get; set; }
-
-		/// <summary>
-		/// 受理内容
-		/// </summary>
-		public string? Content { get; set; }
-	};
-
-	/// <summary>
+    /// <summary>
+    /// 审核管理
+    /// </summary>
+    /// <param name="EKnowledgeApplyType">申请类型</param>
+    /// <param name="EKnowledgeWorkFlowStatus">审核状态</param>
+    public record KnowledgeApprovalPagedListDto(EKnowledgeApplyType? EKnowledgeApplyType, EKnowledgeWorkFlowStatus? EKnowledgeWorkFlowStatus) : PagedKeywordRequest;
+
+    /// <summary>
+    /// 知识检索
+    /// </summary>
+    /// <param name="RetrievalType">检索类型</param>
+    /// <param name="Attribution">归属</param>
+    /// <param name="Sort">排序字段</param>
+    /// <param name="CreateOrgId">部门id</param>
+    /// <param name="HotspotId">热点id</param>
+    /// <param name="HotspotName">热点名称</param>;
+    /// <param name="KnowledgeTypeId">类型id</param>
+    /// <param name="Content">受理内容</param>
+    public record KnowledgeRetrievalPagedListDto : PagedKeywordRequest
+    {
+        /// <summary>
+        /// 检索类型
+        /// </summary>
+        public EKnowledgeRetrievalType? RetrievalType { get; set; }
+
+        /// <summary>
+        /// 归属
+        /// </summary>
+        public string? Attribution { get; set; }
+
+        /// <summary>
+        /// 排序字段
+        /// </summary>
+        public string Sort { get; set; }
+
+        /// <summary>
+        /// 部门id
+        /// </summary>
+        public string? CreateOrgId { get; set; }
+
+        /// <summary>
+        /// 热点id
+        /// </summary>
+        public string? HotspotId { get; set; }
+
+        /// <summary>
+        /// 热点名称
+        /// </summary>
+        public string? HotspotName { get; set; }
+
+        /// <summary>
+        /// 类型id
+        /// </summary>
+        public string? KnowledgeTypeId { get; set; }
+
+        /// <summary>
+        /// 受理内容
+        /// </summary>
+        public string? Content { get; set; }
+    };
+
+    /// <summary>
     /// 来电弹屏知识库查询
     /// </summary>
     /// <param name="HotspotId">热点ID</param>
@@ -87,7 +87,7 @@ namespace Hotline.Share.Dtos.Knowledge
     /// <param name="EKnowledgeWorkFlowStatus"></param>
     /// <param name="StartApplyTime"></param>
     /// <param name="EndApplyTime"></param>
-    public record KnowledgeDeletelPagedListDto(EKnowledgeWorkFlowStatus? EKnowledgeWorkFlowStatus,DateTime? StartApplyTime, DateTime? EndApplyTime) : PagedKeywordRequest;
+    public record KnowledgeDeletelPagedListDto(EKnowledgeWorkFlowStatus? EKnowledgeWorkFlowStatus, DateTime? StartApplyTime, DateTime? EndApplyTime) : PagedKeywordRequest;
 
     /// <summary>
     /// 
@@ -105,42 +105,42 @@ namespace Hotline.Share.Dtos.Knowledge
     //public record KnowPagedListDto(string? CreateOrgId, string? HotspotId, string? KnowledgeTypeId, EKnowledgeStatus? Status, DateTime? CreationStartTime, DateTime? CreationEndTime,
     //  DateTime? StartOnShelfTime, DateTime? EndOnShelfTime, DateTime? StartOffShelfTime, DateTime? EndOffShelfTime) : PagedKeywordRequest;
 
-    public record KnowPagedListDto : PagedKeywordRequest 
+    public record KnowPagedListDto : PagedKeywordRequest
     {
         /// <summary>
         /// 标题
         /// </summary>
-        public string? Title { get; set; }  
+        public string? Title { get; set; }
 
         /// <summary>
         /// 状态
         /// </summary>
         public EKnowledgeStatus? Status { get; set; }
 
-		/// <summary>
-		/// 草稿状态下的查询条件
-		/// </summary>
-		public EKnowledgeStatus? NewDraftsStatus { get; set; }
+        /// <summary>
+        /// 草稿状态下的查询条件
+        /// </summary>
+        public EKnowledgeStatus? NewDraftsStatus { get; set; }
 
-		/// <summary>
-		/// 是否公开
-		/// </summary>
-		public bool? IsPublic { get; set; }
+        /// <summary>
+        /// 是否公开
+        /// </summary>
+        public bool? IsPublic { get; set; }
 
-		/// <summary>
-		/// 摘要
-		/// </summary>
-		public string? Summary { get; set; }
+        /// <summary>
+        /// 摘要
+        /// </summary>
+        public string? Summary { get; set; }
 
-		/// <summary>
-		/// 部门
-		/// </summary>
-		public string? CreateOrgId { get; set; }
+        /// <summary>
+        /// 部门
+        /// </summary>
+        public string? CreateOrgId { get; set; }
 
-		/// <summary>
-		/// 热点
-		/// </summary>
-		public string? HotspotId { get; set; }
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string? HotspotId { get; set; }
 
         /// <summary>
         /// 分类
@@ -152,10 +152,50 @@ namespace Hotline.Share.Dtos.Knowledge
         /// </summary>
         public string? ModuleCode { get; set; }
 
-		/// <summary>
-		///   归属
-		/// </summary>
-		public string? Attribution { get; set; }
+        /// <summary>
+        ///   归属
+        /// </summary>
+        public string? Attribution { get; set; }
+
+        /// <summary>
+        /// 创建开始
+        /// </summary>
+        public DateTime? CreationStartTime { get; set; }
+
+        /// <summary>
+        /// 创建结束
+        /// </summary>
+        public DateTime? CreationEndTime { get; set; }
+
+        /// <summary>
+        /// 上架开始
+        /// </summary>
+        public DateTime? StartOnShelfTime { get; set; }
+
+        /// <summary>
+        /// 上架结束
+        /// </summary>
+        public DateTime? EndOnShelfTime { get; set; }
+
+        /// <summary>
+        /// 下架开始
+        /// </summary>
+        public DateTime? StartOffShelfTime { get; set; }
+
+        /// <summary>
+        /// 下架结束
+        /// </summary>
+        public DateTime? EndOffShelfTime { get; set; }
+
+        /// <summary>
+        /// 更新时间开始
+        /// </summary>
+        public DateTime? StartUpdateTime { get; set; }
+
+        /// <summary>
+        /// 更新时间结束
+        /// </summary>
+        public DateTime? EndUpdateTime { get; set; }
 
-	}
+    }
 }

+ 43 - 28
src/Hotline.Share/Dtos/Order/Detail/OrderFlowTraceDto.cs

@@ -13,122 +13,132 @@ public class OrderFlowTraceDto
     public DateTime CreationTime { get; set; }
 
     /// <summary>
-    /// 节点名称
+    /// 鑺傜偣鍚嶇О
     /// </summary>
     public string Name { get; set; }
 
     /// <summary>
-    /// 交办人
+    /// 浜ょ彮浜哄悕绉�
     /// </summary>
     public string? AssignerName { get; set; }
 
     /// <summary>
-    /// 交办部门
+    /// 浜ょ彮浜洪儴闂�
     /// </summary>
     public string AssignOrgName { get; set; }
 
     /// <summary>
-    /// 接办人
+    /// 鍙楃悊浜�
     /// </summary>
     public string? AcceptorName { get; set; }
 
     public string? AcceptorOrgName { get; set; }
 
     /// <summary>
-    /// 接办时间
+    /// 鍙楃悊鏃堕棿
     /// </summary>
     public DateTime? AcceptTime { get; set; }
 
     /// <summary>
-    /// 办理人
+    /// 鍔炵悊浜�
     /// </summary>
 
     public string? HandlerName { get; set; }
 
     /// <summary>
-    /// 办理人部门名称
+    /// 鍔炵悊浜洪儴闂�
     /// </summary>
     public string? HandlerOrgName { get; set; }
 
     /// <summary>
-    /// 办理完成时间
+    /// 鍔炵悊鏃堕棿
     /// </summary>
     public DateTime? HandleTime { get; set; }
 
     /// <summary>
-    /// 节点期满时间
+    /// 鑺傜偣鏈熸弧鏃堕棿
     /// </summary>
     public DateTime? StepExpiredTime { get; set; }
 
     /// <summary>
-    /// 节点超期状态
+    /// 瓒呮湡鐘舵€�
     /// </summary>
     public EExpiredStatus? ExpiredStatus { get; set; }
 
+    public string? ExpiredStatusText => ExpiredStatus.HasValue ? ExpiredStatus.GetDescription() : "";
+
     /// <summary>
-    /// 办理方式
+    /// 鍔炵悊鏂瑰紡
     /// </summary>
     public EHandleMode? HandleMode { get; set; }
 
     public string HandleModeText => HandleMode.HasValue ? HandleMode.GetDescription() : "";
 
     /// <summary>
-    /// 快照类型
+    /// 鑺傜偣绫诲瀷
     /// </summary>
     public ETraceStyle TraceStyle { get; set; }
 
-    #region 流程节点展开
+    public EWorkflowStepStatus Status { get; set; }
+    public string StatusText => Status.GetDescription();
+
+    /// <summary>
+    /// 浼氱�娴佽浆璁板綍
+    /// </summary>
+    public List<OrderFlowTraceDto> Traces { get; set; }
+
+    #region 娴佺▼鑺傜偣灞曞紑
 
     /// <summary>
-    /// 办理意见
+    /// 鍔炵悊鎰忚�
     /// </summary>
     public string? Opinion { get; set; }
 
     /// <summary>
-    /// 附件
+    /// 闄勪欢
     /// </summary>
     public List<FileDto>? Files { get; set; }
 
     /// <summary>
-    /// 备注
+    /// 澶囨敞
     /// </summary>
     public string? Remark { get; set; }
 
     #endregion
 
-    #region 发布节点展开
+    #region 鍙戝竷鑺傜偣灞曞紑
 
 
     /// <summary>
-    /// 发布范围
+    /// 鍙戝竷鑼冨洿
     /// </summary>
     public bool PublishState { get; set; }
 
     /// <summary>
-    /// 整理结果
+    /// 鏁寸悊缁撴灉
     /// </summary>
     public string ArrangeOpinion { get; set; }
 
     #endregion
 
-    #region 回访节点展开
+    #region 鍥炶�鑺傜偣灞曞紑
 
 
     /// <summary>
-    /// 语音评价(话务评价)
+    /// 璇�煶璇勪环锛堣瘽鍔¤瘎浠凤級
     /// </summary>
     public EVoiceEvaluate? VoiceEvaluate { get; set; }
 
     public string? VoiceEvaluateText => VoiceEvaluate.HasValue ? VoiceEvaluate.GetDescription() : "";
 
     /// <summary>
-    /// 话务员评价(话务评价)
+    /// 璇濆姟鍛樿瘎浠凤紙璇濆姟璇勪环锛�
     /// </summary>
     public ESeatEvaluate? SeatEvaluate { get; set; }
     public string? SeatEvaluateText => SeatEvaluate.HasValue ? SeatEvaluate.GetDescription() : "";
 
     /// <summary>
-    /// 回访内容
+    /// 鍥炶�鍐呭�
     /// </summary>
     public string? VisitContent { get; set; }
 
@@ -139,27 +149,32 @@ public class OrderFlowTraceDto
 }
 
 /// <summary>
-/// 流程明细回访节点展开元素
+/// 宸ュ崟鍔炵悊娴佺▼鏄庣粏鍥炶�鏄庣粏椤�
 /// </summary>
 public class OrderFlowVisitDetail
 {
     /// <summary>
-    /// 部门办件结果
+    /// 鍥炶�閮ㄩ棬鍚嶇О
+    /// </summary>
+    public string VisitOrgName { get; set; }
+
+    /// <summary>
+    /// 閮ㄩ棬鍔炰欢缁撴灉
     /// </summary>
     public string? OrgProcessingResults { get; set; }
 
     /// <summary>
-    /// 不满意原因
+    /// 涓嶆弧鎰忓師鍥�
     /// </summary>
     public List<string>? OrgNoSatisfiedReason { get; set; }
 
     /// <summary>
-    /// 部门办件态度
+    /// 閮ㄩ棬鍔炰欢鎬佸害
     /// </summary>
     public string? OrgHandledAttitude { get; set; }
 
     /// <summary>
-    /// 回访内容
+    /// 鍥炶�鍐呭�
     /// </summary>
     public string? VisitContent { get; set; }
 }

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

@@ -1,4 +1,5 @@
-using Hotline.Share.Dtos.File;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.File;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Hotspots;
 using Hotline.Share.Enums.FlowEngine;
@@ -31,10 +32,10 @@ namespace Hotline.Share.Dtos.Order
 
         public string ActualHandleOrgName { get; set; }
 
-		/// <summary>
-		/// 工单状态
-		/// </summary>
-		public EOrderStatus Status { get; set; }
+        /// <summary>
+        /// 工单状态
+        /// </summary>
+        public EOrderStatus Status { get; set; }
 
         public string StatusText => Status.GetDescription();
     }
@@ -171,7 +172,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 第一次评价结果代码
         /// </summary>
-        public string? FirstVisitResultCode { get; set; }        
+        public string? FirstVisitResultCode { get; set; }
 
         #region 实际办理信息(节点,部门,意见)
 
@@ -648,6 +649,28 @@ namespace Hotline.Share.Dtos.Order
             return string.Empty;
         }
 
+        /// <summary>
+        /// 剩余办理时长
+        /// </summary>
+        public string RemainingTime => RemainingTimeTextVoid();
+
+        public string RemainingTimeTextVoid()
+        {
+            if (Status >= EOrderStatus.Filed && FiledTime !=null)
+            {
+                return Math.Round((ExpiredTime.Value - FiledTime.Value).TotalDays,1) + "天";
+            }
+            else if(Status < EOrderStatus.Filed && ExpiredTime!=null)
+            {
+                return Math.Round((ExpiredTime.Value - DateTime.Now).TotalDays,1) + "天";
+            }
+            else
+            {
+                return "-";
+            }
+        }
+
+
         /// <summary>
         /// 超期部门
         /// </summary>
@@ -707,6 +730,8 @@ namespace Hotline.Share.Dtos.Order
 
         public List<OrderVisitDto>? OrderVisits { get; set; }
 
+        public CallNativeDto? FwCallRecord { get; set; }
+
         public List<FileJson>? FileJson { get; set; }
 
         /// <summary>

+ 9 - 0
src/Hotline.Share/Dtos/Order/OrderStartFlowDto.cs

@@ -2,6 +2,7 @@
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Org;
 using Hotline.Share.Enums.FlowEngine;
+using Hotline.Share.Enums.Settings;
 
 namespace Hotline.Share.Dtos.Order
 {
@@ -131,6 +132,14 @@ namespace Hotline.Share.Dtos.Order
         public string? TranspondCityValue { get; set; }
 
         #endregion
+
+        #region 延期信息
+
+        public int TimeLimit { get; set; }
+
+        public ETimeType? TimeLimitUnit { get; set; }
+
+        #endregion
     }
 
     public class CrossStep : BasicWorkflowDto

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

@@ -132,6 +132,11 @@ namespace Hotline.Share.Dtos.Order
         public DateTime? CreationTimeStart { get; set; }
         public DateTime? CreationTimeEnd { get; set; }
 
+        /// <summary>
+        /// 智能回访结果
+        /// </summary>
+        public EAiVisitResult? AiVisitResult { get; set; }
+
     }
 
     public record QueryOrderPublishStatisticsAllDto : PagedRequest

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

@@ -27,9 +27,19 @@ public record QueryOrderPublishDto : PagedKeywordRequest
 	public DateTime? CreationTimeEnd { get; set; }
 
 	/// <summary>
-	/// 来电号码(×)
+	/// 省期满时间开始
 	/// </summary>
-	public string? FromPhone { get; set; }
+	public DateTime? ExpiredTimeProvinceStart { get; set; }
+
+	/// <summary>
+	/// 省期满时间结束
+	/// </summary>
+    public DateTime? ExpiredTimeProvinceEnd { get; set; }
+
+    /// <summary>
+    /// 来电号码(×)
+    /// </summary>
+    public string? FromPhone { get; set; }
 
 	/// <summary>
 	/// 接办名称(综合查询使用)

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

@@ -75,6 +75,12 @@ namespace Hotline.Share.Dtos.Order
         public DateTime? CreationTimeStart { get; set; }
         public DateTime? CreationTimeEnd { get; set; }
 
+         /// <summary>
+        /// 开始时间(流程开启时间)
+        /// </summary>
+        public DateTime? StartTimeStart { get; set; }
+        public DateTime? StartTimeEnd { get; set; }
+
         /// <summary>
         /// 来电号码(×)
         /// </summary>

+ 6 - 1
src/Hotline.Share/Enums/FlowEngine/EReviewResult.cs

@@ -1,19 +1,24 @@
-namespace Hotline.Share.Enums.FlowEngine;
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.FlowEngine;
 
 public enum EReviewResult
 {
     /// <summary>
     /// 未知
     /// </summary>
+    [Description("未办理")]
     Unknown = 0,
 
     /// <summary>
     /// 通过
     /// </summary>
+    [Description("同意")]
     Approval = 1,
 
     /// <summary>
     /// 审核失败
     /// </summary>
+    [Description("不同意")]
     Failed = 2,
 }

+ 9 - 0
src/Hotline.Share/Enums/Order/EVisitType.cs

@@ -57,4 +57,13 @@ namespace Hotline.Share.Enums.Order
         [Description("其他")]
         OtherVisit = 100,
     }
+
+    public enum EAiVisitResult
+    {
+        /// <summary>
+        /// 部门办件不满意
+        /// </summary>
+        [Description("部门办件不满意")]
+        OrgProcessingResultsNoSatisfied = 1,
+    }
 }

+ 6 - 0
src/Hotline/FlowEngine/Workflows/StepBasicEntity.cs

@@ -249,6 +249,12 @@ public abstract class StepBasicEntity : CreationEntity
     /// </summary>
     public EHandleMode? HandleMode { get; set; } = EHandleMode.Normal;
 
+    /// <summary>
+    /// 审核结果(非审批流程无意义)
+    /// </summary>
+    [SugarColumn(DefaultValue = "0")]
+    public EReviewResult ReviewResult { get; set; }
+
     #endregion
 
     #region Definition

+ 73 - 55
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -2073,6 +2073,7 @@ namespace Hotline.FlowEngine.Workflows
             step.IsSms = dto.IsSms;
             step.Opinion = dto.Opinion;
             step.Remark = dto.Remark;
+            step.ReviewResult = dto.ReviewResult;
 
             //step办理状态
             HandleStep(step, handleMode, dto.Opinion, dto.NextStepCode);
@@ -2107,45 +2108,57 @@ namespace Hotline.FlowEngine.Workflows
                 .FirstAsync(d => d.WorkflowId == workflowId
                           && d.TraceStyle == ETraceStyle.Publish
                           && d.Status == EWorkflowStepStatus.WaitForAccept, cancellation);
-            if (pubTrace is null) throw new UserFriendlyException($"未查询到待办的发布节点, workflowId:{workflowId}");
-            pubTrace.OrderPublishId = orderPublishId;
-            pubTrace.AcceptorId = acceptor.UserId;
-            pubTrace.AcceptorName = acceptor.UserName;
-            pubTrace.AcceptorOrgId = acceptor.OrgId;
-            pubTrace.AcceptorOrgName = acceptor.OrgName;
-            pubTrace.HandlerId = handler.UserId;
-            pubTrace.HandlerName = handler.UserName;
-            pubTrace.HandlerOrgId = handler.OrgId;
-            pubTrace.HandlerOrgName = handler.OrgName;
-            pubTrace.HandleTime = handleTime;
-            pubTrace.Status = EWorkflowStepStatus.Handled;
+            if (pubTrace is not null)
+            {
+                pubTrace.OrderPublishId = orderPublishId;
+                pubTrace.AcceptorId = acceptor.UserId;
+                pubTrace.AcceptorName = acceptor.UserName;
+                pubTrace.AcceptorOrgId = acceptor.OrgId;
+                pubTrace.AcceptorOrgName = acceptor.OrgName;
+                pubTrace.HandlerId = handler.UserId;
+                pubTrace.HandlerName = handler.UserName;
+                pubTrace.HandlerOrgId = handler.OrgId;
+                pubTrace.HandlerOrgName = handler.OrgName;
+                pubTrace.HandleTime = handleTime;
+                pubTrace.Status = EWorkflowStepStatus.Handled;
 
-            await _workflowTraceRepository.UpdateAsync(pubTrace, cancellation);
+                await _workflowTraceRepository.UpdateAsync(pubTrace, cancellation);
 
-            //create visit trace
-            await CreateVisitTraceAsync(pubTrace, visitAcceptor, orderVisitId, cancellation);
+                //create visit trace
+                await CreateVisitTraceAsync(pubTrace, visitAcceptor, orderVisitId, cancellation);
+            }
+            else
+            {
+                //throw new UserFriendlyException($"未查询到待办的发布节点, workflowId:{workflowId}");
+            }
         }
 
         public async Task HandleVisitTraceAsync(string orderVisitId, UserInfo visitor, DateTime visitTime, CancellationToken cancellation)
         {
             var visitTrace = await _workflowTraceRepository.GetAsync(d => d.OrderVisitId == orderVisitId,
                 cancellationToken: cancellation);
-            if (visitTrace is null) throw new UserFriendlyException($"未查询到待办的发布节点, orderVisitId:{orderVisitId}");
-            visitTrace.AcceptorId = visitor.UserId;
-            visitTrace.AcceptorName = visitor.UserName;
-            visitTrace.AcceptorOrgId = visitor.OrgId;
-            visitTrace.AcceptorOrgName = visitor.OrgName;
-            visitTrace.HandlerId = visitor.UserId;
-            visitTrace.HandlerName = visitor.UserName;
-            visitTrace.HandlerOrgId = visitor.OrgId;
-            visitTrace.HandlerOrgName = visitor.OrgName;
-            visitTrace.HandleTime = visitTime;
-            visitTrace.Status = EWorkflowStepStatus.Handled;
+            if (visitTrace is not null)
+            {
+                visitTrace.AcceptorId = visitor.UserId;
+                visitTrace.AcceptorName = visitor.UserName;
+                visitTrace.AcceptorOrgId = visitor.OrgId;
+                visitTrace.AcceptorOrgName = visitor.OrgName;
+                visitTrace.HandlerId = visitor.UserId;
+                visitTrace.HandlerName = visitor.UserName;
+                visitTrace.HandlerOrgId = visitor.OrgId;
+                visitTrace.HandlerOrgName = visitor.OrgName;
+                visitTrace.HandleTime = visitTime;
+                visitTrace.Status = EWorkflowStepStatus.Handled;
 
-            await _workflowTraceRepository.UpdateAsync(visitTrace, cancellation);
+                await _workflowTraceRepository.UpdateAsync(visitTrace, cancellation);
 
-            //create append end trace
-            await CreateTrashEndTraceAsync(visitTrace, cancellation);
+                //create append end trace
+                await CreateTrashEndTraceAsync(visitTrace, cancellation);
+            }
+            else
+            {
+                //throw new UserFriendlyException($"未查询到待办的发布节点, orderVisitId:{orderVisitId}");
+            }
         }
 
         #region private method
@@ -3226,6 +3239,7 @@ namespace Hotline.FlowEngine.Workflows
             pubTrace.HandlerOrgAreaName = null;
             pubTrace.StepExpiredTime = null;
 
+            pubTrace.CreationTime = endTrace.CreationTime.AddSeconds(1);
             await _workflowTraceRepository.AddAsync(pubTrace, cancellation);
 
             return pubTrace;
@@ -3235,30 +3249,30 @@ namespace Hotline.FlowEngine.Workflows
         {
             if (string.IsNullOrEmpty(orderVisitId))
                 throw new UserFriendlyException($"参数异常,orderVisitId不能为空, pubTraceId: {pubTrace.Id}");
-            var visitTrace = new WorkflowTrace
-            {
-                OrderVisitId = orderVisitId,
-                TraceStyle = ETraceStyle.Visit,
-                Name = "中心回访",
-                Status = EWorkflowStepStatus.WaitForAccept,
-                Code = "visit",
-                CreationTime = pubTrace.HandleTime ?? DateTime.Now,
-                PrevStepId = pubTrace.Id,
-                PrevStepCode = pubTrace.Code,
-                PrevStepName = pubTrace.Name,
-                AssignerId = pubTrace.HandlerId,
-                AssignerName = pubTrace.HandlerName,
-                AssignerOrgId = pubTrace.HandlerOrgId,
-                AssignerOrgName = pubTrace.HandlerOrgName,
-                AssignerOrgIsCenter = pubTrace.HandlerOrgIsCenter ?? false,
-
-                AcceptorId = acceptor.UserId,
-                AcceptorName = acceptor.UserName,
-                AcceptorOrgId = acceptor.OrgId,
-                AcceptorOrgName = acceptor.OrgName,
-
-                StepExpiredTime = null,
-            };
+            var visitTrace = _mapper.Map<WorkflowTrace>(pubTrace);
+
+            visitTrace.OrderPublishId = null;
+            visitTrace.OrderVisitId = orderVisitId;
+            visitTrace.TraceStyle = ETraceStyle.Visit;
+            visitTrace.Name = "中心回访";
+            visitTrace.Status = EWorkflowStepStatus.WaitForAccept;
+            visitTrace.Code = "visit";
+            visitTrace.CreationTime = pubTrace.HandleTime ?? DateTime.Now;
+            visitTrace.PrevStepId = pubTrace.Id;
+            visitTrace.PrevStepCode = pubTrace.Code;
+            visitTrace.PrevStepName = pubTrace.Name;
+            visitTrace.AssignerId = pubTrace.HandlerId;
+            visitTrace.AssignerName = pubTrace.HandlerName;
+            visitTrace.AssignerOrgId = pubTrace.HandlerOrgId;
+            visitTrace.AssignerOrgName = pubTrace.HandlerOrgName;
+            visitTrace.AssignerOrgIsCenter = pubTrace.HandlerOrgIsCenter ?? false;
+
+            visitTrace.AcceptorId = acceptor.UserId;
+            visitTrace.AcceptorName = acceptor.UserName;
+            visitTrace.AcceptorOrgId = acceptor.OrgId;
+            visitTrace.AcceptorOrgName = acceptor.OrgName;
+
+            visitTrace.StepExpiredTime = null;
 
             await _workflowTraceRepository.AddAsync(visitTrace, cancellation);
 
@@ -3269,6 +3283,10 @@ namespace Hotline.FlowEngine.Workflows
         {
             var now = DateTime.Now;
             var TrashEndTrace = _mapper.Map<WorkflowTrace>(visitTrace);
+            TrashEndTrace.StepId = null;
+            TrashEndTrace.OrderPublishId = null;
+            TrashEndTrace.OrderVisitId = null;
+
             TrashEndTrace.TraceStyle = ETraceStyle.TrashEnd;
             TrashEndTrace.Name = "结束";
             TrashEndTrace.Status = EWorkflowStepStatus.Handled;
@@ -3299,9 +3317,9 @@ namespace Hotline.FlowEngine.Workflows
 
             TrashEndTrace.StepExpiredTime = null;
 
-            await _workflowTraceRepository.AddAsync(visitTrace, cancellation);
+            await _workflowTraceRepository.AddAsync(TrashEndTrace, cancellation);
 
-            return visitTrace;
+            return TrashEndTrace;
         }
 
         /// <summary>

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

@@ -16,7 +16,7 @@ public class WorkflowTrace : StepBasicEntity
     /// <summary>
     /// 节点Id
     /// </summary>
-    public string StepId { get; set; }
+    public string? StepId { get; set; }
 
     /// <summary>
     /// 会签从属关系

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

@@ -1157,6 +1157,13 @@ namespace Hotline.Orders
         [Navigate(NavigateType.OneToOne, nameof(CallId), nameof(TrCallRecord.OtherAccept))]
         public TrCallRecord CallRecord { get; set; }
 
+        /// <summary>
+        /// 兴唐通话记录
+        /// </summary>
+        //[Navigate(NavigateType.OneToOne, nameof(CallId), nameof(TrCallRecord.CallAccept))] //由CallAccept改成OtherAccept
+        [Navigate(NavigateType.OneToOne, nameof(CallId), nameof(CallNative.Id))]
+        public CallNative FwCallRecord { get; set; }
+
         [Navigate(NavigateType.OneToMany, nameof(WorkflowStep.ExternalId))]
         public List<WorkflowStep> WorkflowSteps { get; set; }
 

+ 40 - 37
src/Hotline/Orders/OrderDomainService.cs

@@ -295,49 +295,52 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
 
         //需求251  某些工单需自动发送短信
         //任何类型的省工单都不需要发送短信
-        try
+        var isOpenSendEndSms = _systemSettingCacheManager.GetSetting(SettingConstants.IsOpenSendEndSms)?.SettingValue[0];
+        if (isOpenSendEndSms == "true")
         {
-            if (order.Source != ESource.ProvinceStraight && _appOptions.Value.IsYiBin)
+            try
             {
-                var code = "";
-                //受理类型为“投诉、举报”
-                if ((order.AcceptTypeCode == "30" || order.AcceptTypeCode == "35") && orderVisit.VisitState != EVisitState.Visited)
-                {
-                    code = "1017";
-                    orderVisit.VisitState = EVisitState.SMSVisiting;
-                    await _orderVisitRepository.UpdateAsync(orderVisit);
-                }
-                else
-                    code = "1018";
-
-                //发送查询短信
-                var messageDto = new Share.Dtos.Push.MessageDto
+                if (order.Source != ESource.ProvinceStraight)
                 {
-                    PushBusiness = EPushBusiness.SearchSms,
-                    ExternalId = visitId,
-                    OrderId = order.Id,
-                    PushPlatform = EPushPlatform.Sms,
-                    Remark = order.Title,
-                    Name = order.FromName,
-                    TemplateCode = code,
-                    Params = new List<string>() { order.No, order.Password },
-                    TelNumber = order.Contact,
-                };
-                await _mediator.Publish(new PushMessageNotify(messageDto), cancellationToken);
+                    var code = "";
+                    //受理类型为“投诉、举报”
+                    if ((order.AcceptTypeCode == "30" || order.AcceptTypeCode == "35") && orderVisit.VisitState != EVisitState.Visited)
+                    {
+                        code = "1017";
+                        orderVisit.VisitState = EVisitState.SMSVisiting;
+                        await _orderVisitRepository.UpdateAsync(orderVisit);
+                    }
+                    else
+                        code = "1018";
 
-                // 发送短信后推送一个 48小时的延迟消息队列. 当消息队列收到消息时, 判断用户是否回复了, 如果未回复短信就 默认满意
-                var delaySecond = _systemSettingCacheManager.DefaultVisitSmsDelaySecond;
-                await _capPublisher.PublishDelayAsync(
-                    TimeSpan.FromSeconds(delaySecond),
-                    EventNames.UpdateVisitDelaySms,
-                    messageDto,
-                    cancellationToken: cancellationToken);
+                    //发送查询短信
+                    var messageDto = new Share.Dtos.Push.MessageDto
+                    {
+                        PushBusiness = EPushBusiness.SearchSms,
+                        ExternalId = visitId,
+                        OrderId = order.Id,
+                        PushPlatform = EPushPlatform.Sms,
+                        Remark = order.Title,
+                        Name = order.FromName,
+                        TemplateCode = code,
+                        Params = new List<string>() { order.No, order.Password },
+                        TelNumber = order.Contact,
+                    };
+                    await _mediator.Publish(new PushMessageNotify(messageDto), cancellationToken);
+
+                    // 发送短信后推送一个 48小时的延迟消息队列. 当消息队列收到消息时, 判断用户是否回复了, 如果未回复短信就 默认满意
+                    var delaySecond = _systemSettingCacheManager.DefaultVisitSmsDelaySecond;
+                    await _capPublisher.PublishDelayAsync(
+                        TimeSpan.FromSeconds(delaySecond),
+                        EventNames.UpdateVisitDelaySms,
+                        messageDto,
+                        cancellationToken: cancellationToken);
+                }
+            }
+            catch (Exception)
+            {
             }
         }
-        catch (Exception)
-        {
-        }
-
         if (order.IsProvince == false && orderVisit.VisitState == EVisitState.Visited)
         {
             //推省上

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

@@ -667,5 +667,10 @@ namespace Hotline.Settings
         /// 交办单是否保密
         /// </summary>
         public const string IsTheAssignmentFormConfidential = "IsTheAssignmentFormConfidential";
+
+        /// <summary>
+        /// 办结是否发送查询短信
+        /// </summary>
+        public const string IsOpenSendEndSms = "IsOpenSendEndSms";
     }
 }

+ 5 - 5
src/Hotline/Statistics/StatisticsDepart.cs

@@ -198,11 +198,11 @@ namespace Hotline.Statistics
 		[SugarColumn(Length = 10, DecimalDigits = 6, ColumnDescription = "总满意率")]
 		public decimal AllSatisfaction { get; set; }
 
-		/// <summary>
-		/// 统计日期
-		/// </summary>
-		[SugarColumn(ColumnDescription = "统计日期")]
-		public int DateTime { get; set; }
+		///// <summary>
+		///// 统计日期
+		///// </summary>
+		//[SugarColumn(ColumnDescription = "统计日期")]
+		//public int DateTime { get; set; }
 
 		/// <summary>
 		/// 统计时限

+ 5 - 5
src/Hotline/Statistics/StatisticsDepartSatisfied.cs

@@ -132,11 +132,11 @@ namespace Hotline.Statistics
 		public int ScreenWaitNum { get; set; }
 
 
-		/// <summary>
-		/// 统计日期
-		/// </summary>
-		[SugarColumn(ColumnDescription = "统计日期")]
-		public int DateTime { get; set; }
+		///// <summary>
+		///// 统计日期
+		///// </summary>
+		//[SugarColumn(ColumnDescription = "统计日期")]
+		//public int DateTime { get; set; }
 
 		/// <summary>
 		/// 统计时限

+ 5 - 5
src/Hotline/Statistics/StatisticsHotspotSatisfied.cs

@@ -101,11 +101,11 @@ namespace Hotline.Statistics
 		[SugarColumn(ColumnDescription = "(自贡)甄别为满意 自贡的视为满意名字是甄别为满意")]
 		public int ScreenSatisfaction { get; set; }
 
-		/// <summary>
-		/// 统计日期
-		/// </summary>
-		[SugarColumn(ColumnDescription = "统计日期")]
-		public int DateTime { get; set; }
+		///// <summary>
+		///// 统计日期
+		///// </summary>
+		//[SugarColumn(ColumnDescription = "统计日期")]
+		//public int DateTime { get; set; }
 
 		/// <summary>
 		/// 统计时限

+ 5 - 5
src/Hotline/Statistics/StatisticsPurTypeSatisfied.cs

@@ -102,11 +102,11 @@ namespace Hotline.Statistics
 		[SugarColumn(ColumnDescription = "无效")]
 		public int Invalid { get; set; }
 
-		/// <summary>
-		/// 统计日期
-		/// </summary>
-		[SugarColumn(ColumnDescription = "统计日期")]
-		public int DateTime { get; set; }
+		///// <summary>
+		///// 统计日期
+		///// </summary>
+		//[SugarColumn(ColumnDescription = "统计日期")]
+		//public int DateTime { get; set; }
 
 		/// <summary>
 		/// 统计时限

+ 8 - 2
src/Hotline/dataview.md

@@ -342,7 +342,7 @@ WHERE ordervisitdetailtemp."VisitTarget" = 20 and ordervisittemp."VisitTime">='2
 
 
  ### 信件清单查询(新)
- select '' as "序号",
+  select '' as "序号",
 aaa.信件状态,aaa."是否超期",aaa.来源,aaa.转接来源,aaa.当前节点,aaa.重办次数,aaa.甄别状态,aaa.受理编号,aaa.省编号,aaa.受理时间,aaa.标题,aaa.期满时间,aaa."一级部门",
 aaa.二级部门,aaa."接办部门",aaa."办结时间",aaa."受理类型",aaa."热点类型",aaa.热点全称,aaa."区域",aaa.区域全称,aaa."受理人",aaa."姓名",aaa."联系电话",aaa."来电电话",
 aaa."事发地址",aaa."具体对象",aaa."来电人主体",aaa."性别",ccc."SeatVisitResult" as "坐席满意度",bbb."OrgProcessingResults" as "满意度",aaa."推送分类",aaa."受理内容",
@@ -411,7 +411,12 @@ CASE
   WHEN "County" is not null and "County" <>'' THEN "County"
 	ELSE "City"
 END AS "区域",
-"Address"  As "区域全称",
+--"Address"  As "区域全称",
+CASE 
+	WHEN "Town" is not null and "Town" <> '' THEN "City" || '-' || "County" || '-' || "Town"
+	WHEN "County" is not null and "Town" <> '' THEN "City" || '-' || "County"
+	ELSE "City"
+END "区域全称",
 "AcceptorName" AS "受理人" ,
  "FromName" AS "姓名" , 
  "Contact" AS "联系电话" , 
@@ -458,6 +463,7 @@ where visittemp."CreationTime">='2024-08-29' and visitdetailtemp."VisitTarget"=1
 on aaa."SugarNav_Id" = ccc."OrderId"
 
 
+
 ### 重置工单回访部门信息
 update order_visit_detail set 
 "VisitOrgCode"= hhh."HandlerOrgId","VisitOrgName"=hhh."HandlerOrgName"