Explorar el Código

Merge branch 'master' of http://110.188.24.182:10023/Fengwo/hotline

xf hace 1 año
padre
commit
be6e44cb41
Se han modificado 29 ficheros con 1196 adiciones y 88 borrados
  1. 2 1
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  2. 436 0
      src/Hotline.Api/Controllers/Bigscreen/DataScreenController.cs
  3. 2 0
      src/Hotline.Api/Controllers/KnowledgeController.cs
  4. 56 15
      src/Hotline.Api/Controllers/OrderController.cs
  5. 25 23
      src/Hotline.Api/Controllers/PushMessageController.cs
  6. 1 0
      src/Hotline.Api/Realtimes/RealtimeGroupNames.cs
  7. 8 2
      src/Hotline.Api/Realtimes/RealtimeMethods.cs
  8. 16 3
      src/Hotline.Api/Realtimes/RealtimeService.cs
  9. 94 0
      src/Hotline.Application/Bigscreen/DataScreenRefreshService.cs
  10. 20 2
      src/Hotline.Application/Push/PushMessageNotifyHandler.cs
  11. 19 1
      src/Hotline.Application/Push/PushTextMessageHandler.cs
  12. 16 6
      src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs
  13. 203 0
      src/Hotline.Share/Dtos/Bigscreen/BigscreenDto.cs
  14. 2 2
      src/Hotline.Share/Dtos/Knowledge/KnowledgePagedDto.cs
  15. 12 0
      src/Hotline.Share/Dtos/Order/OrderScreenDto.cs
  16. 8 1
      src/Hotline.Share/Dtos/Order/OrderStartFlowDto.cs
  17. 6 16
      src/Hotline.Share/Dtos/Push/MessageDto.cs
  18. 35 0
      src/Hotline.Share/Dtos/Push/PushMessageDto.cs
  19. 67 0
      src/Hotline.Share/Dtos/Push/PushReceiveMessageDto.cs
  20. 1 1
      src/Hotline.Share/Hotline.Share.csproj
  21. 16 0
      src/Hotline.Share/Mq/EventNames.PushSms.cs
  22. 4 1
      src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs
  23. 8 0
      src/Hotline/KnowledgeBase/Knowledge.cs
  24. 1 4
      src/Hotline/KnowledgeBase/KnowledgeDomainService.cs
  25. 16 0
      src/Hotline/Push/FWMessage/IPushDomainService.cs
  26. 104 7
      src/Hotline/Push/FWMessage/PushDomainService.cs
  27. 1 1
      src/Hotline/Push/Notifies/PushMessageNotify.cs
  28. 13 2
      src/Hotline/Realtimes/IRealtimeService.cs
  29. 4 0
      src/XF.Domain/Constants/SettingConstants.cs

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

@@ -205,7 +205,8 @@ public class BiCallController : BaseController
         //获取配置
         int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
         int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        var list = await _trCallRecordRepositoryEx.GetCallHourList(beginDate,endDate,noConnectByeTimes,effectiveTimes);
+        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+        var list = await _trCallRecordRepositoryEx.GetCallHourList(beginDate,endDate,noConnectByeTimes,effectiveTimes,connectByeTimes);
         return list;
     }
 

+ 436 - 0
src/Hotline.Api/Controllers/Bigscreen/DataScreenController.cs

@@ -0,0 +1,436 @@
+using Hotline.KnowledgeBase;
+using Hotline.Orders;
+using Hotline.Repository.SqlSugar.Orders;
+using Hotline.Settings;
+using Hotline.Settings.Hotspots;
+using Hotline.Share.Dtos.Bigscreen;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Share.Enums.Order;
+using MapsterMapper;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Api.Controllers.Bigscreen
+{
+    public class DataScreenController: BaseController
+    {
+        private readonly IOrderRepository _orderRepository;
+        private readonly IRepository<OrderDelay> _orderDelayRepository;
+        private readonly IRepository<OrderVisit> _orderVisitRepository;
+        private readonly IRepository<Knowledge> _knowledgeRepository;
+        private readonly IRepository<KnowledgePv> _knowledgePvRepository;
+        private readonly IMapper _mapper;
+        private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
+
+        public DataScreenController(IOrderRepository orderRepository, IRepository<OrderVisit> orderVisitRepository, IRepository<OrderDelay> orderDelayRepository, IRepository<Knowledge> knowledgeRepository, IRepository<KnowledgePv> knowledgePvRepository,IMapper  mapper,IRepository<OrderVisitDetail> orderVisitDetailRepository)
+        {
+            _orderRepository = orderRepository;
+            _orderVisitRepository = orderVisitRepository;
+            _orderDelayRepository = orderDelayRepository;
+            _knowledgeRepository = knowledgeRepository;
+            _knowledgePvRepository = knowledgePvRepository;
+            _mapper = mapper;
+            _orderVisitDetailRepository = orderVisitDetailRepository;
+        }
+
+        /// <summary>
+        /// 工单统计
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("order-statistics")]
+        public async Task<OrderStatisticsDto> OrderStatistics(DateTime StartDate,DateTime EndDate)
+        {
+            EndDate = EndDate.AddDays(1).AddSeconds(-1);
+            var dto = new OrderStatisticsDto();
+
+            #region 办结工单
+            dto.CompletionCount =await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status>= EOrderStatus.Filed).CountAsync();
+            int CompletionSum = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status >= EOrderStatus.Handling).CountAsync();
+            if (CompletionSum==0)
+            {
+                dto.CompletionRate = 0;
+            }
+            else
+            {
+                dto.CompletionRate = Math.Round((dto.CompletionCount / (double)CompletionSum) * 100, 2);
+            }
+            #endregion
+
+            #region 待受理工单
+            dto.HaveToAcceptCount =await _orderRepository.Queryable(false, false, false).Where(x => x.CreationTime > StartDate && x.CreationTime <= EndDate && x.Status == EOrderStatus.WaitForAccept).CountAsync();
+            int HaveToAcceptSum = await _orderRepository.Queryable(false, false, false).Where(x => x.CreationTime >= StartDate && x.CreationTime <= EndDate).CountAsync();
+            if (HaveToAcceptSum == 0)
+            {
+                dto.HaveToAcceptRate = 0;
+            }
+            else
+            {
+                dto.HaveToAcceptRate = Math.Round((dto.HaveToAcceptCount / (double)HaveToAcceptSum) * 100, 2);
+            }
+            #endregion
+
+            #region 超期工单
+            dto.OverTimeCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.ExpiredStatus == EExpiredStatus.Expired).CountAsync();
+            if (CompletionSum==0)
+            {
+                dto.OverTimeRate = 0;
+            }
+            else
+            {
+                dto.OverTimeRate = Math.Round((dto.OverTimeCount / (double)CompletionSum) * 100, 2);
+            }
+            #endregion
+
+            #region 延期工单
+            dto.DelayCount = await _orderDelayRepository.Queryable().Where(x => x.ApplyDelayTime >= StartDate && x.ApplyDelayTime <= EndDate && x.DelayState == EDelayState.Pass).CountAsync();
+            if (CompletionSum==0)
+            {
+                dto.DelayRate = 0;
+            }
+            else
+            {
+                dto.DelayRate = Math.Round((dto.DelayCount / (double)CompletionSum) * 100, 2);
+            }
+
+            #endregion
+
+            #region 满意工单
+            dto.SatisfiedCount =await _orderVisitRepository.Queryable().Where(x => x.VisitTime >= StartDate && x.VisitTime <= EndDate && x.VisitState == EVisitState.Visited && SqlFunc.JsonField(x.NowEvaluate, "Key") != "1" && SqlFunc.JsonField(x.NowEvaluate,"Key")!="2" ).CountAsync();
+            int SatisfiedSum = await _orderVisitRepository.Queryable().Where(x => x.VisitTime >= StartDate && x.VisitTime <= EndDate && x.VisitState == EVisitState.Visited).CountAsync();
+            if (SatisfiedSum==0)
+            {
+                dto.SatisfiedRate = 0;
+            }
+            else
+            {
+                dto.SatisfiedRate = Math.Round((dto.SatisfiedCount / (double)SatisfiedSum) * 100, 2);
+            }
+            #endregion
+
+            #region 省工单量
+
+            dto.ProvinceOrderCount =await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.IsProvince).CountAsync();
+            dto.ProvinceOrderCompletionCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.IsProvince && x.Status >= EOrderStatus.Filed).CountAsync();
+            #endregion
+
+            return dto;
+        }
+
+        /// <summary>
+        /// 知识库统计
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("knowledge-statistics")]
+        public async Task<KnowledgeStatisticsDto> KnowledgeStatistics()
+        {
+            var dto = new KnowledgeStatisticsDto();
+            dto.KnowledgeCount = await _knowledgeRepository.Queryable().Where(x => x.Status == EKnowledgeStatus.OnShelf).CountAsync();//总数
+            dto.TodayAddCount = await _knowledgeRepository.Queryable().Where(x => x.Renewaln==false && x.Status == EKnowledgeStatus.OnShelf && x.OnShelfTime.Value.Date== DateTime.Now.Date).CountAsync();//今日新增
+            dto.ThisMonthModifyCount = await _knowledgeRepository.Queryable().Where(x => x.Renewaln == true && x.Status == EKnowledgeStatus.OnShelf && x.OnShelfTime.Value.Year
+            == DateTime.Now.Year && x.OnShelfTime.Value.Month == DateTime.Now.Month).CountAsync();//本月修改
+            dto.TodayReadCount = await _knowledgePvRepository.Queryable().Where(x => x.CreationTime.Date == DateTime.Now.Date).CountAsync();
+            return dto;
+        }
+
+        /// <summary>
+        /// 受理类型办件分析
+        /// </summary>
+        /// <param name="StartDate"></param>
+        /// <param name="EndDate"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("ordertype-statistics")]
+        public async Task<List<OrderTypeHandleStatisticsDto>> OrderTypeHandleStatistics(DateTime StartDate,DateTime EndDate)
+        {
+            EndDate = EndDate.AddDays(1).AddSeconds(-1);
+            var list =await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status > EOrderStatus.Handling)
+                .GroupBy(x=>x.AcceptType)
+                .Select(x => new OrderTypeHandleStatisticsDto
+                { 
+                     AcceptType = x.AcceptType,
+                     SumCount = SqlFunc.AggregateCount(x.Id),
+                     HandlingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status>= EOrderStatus.Handling && x.Status < EOrderStatus.Filed,1,0)),
+                     FiledCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Status>= EOrderStatus.Filed,1,0)),
+                     OverTimeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.ExpiredStatus == EExpiredStatus.Expired,1,0))
+                }).ToListAsync();
+            return list;
+        }
+
+        /// <summary>
+        /// 预警热点
+        /// </summary>
+        /// <param name="StartDate"></param>
+        /// <param name="EndDate"></param>
+        /// <param name="AreaCode"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("earlywarning-statistics")]
+        public async Task<List<EarlyWarningHotsPotsStatisticsDto>> EarlyWarningHotsPotsStatistics(DateTime StartDate, DateTime EndDate,string AreaCode)
+        {
+            EndDate = EndDate.AddDays(1).AddSeconds(-1);
+            if (AreaCode.Length==6 && AreaCode.IndexOf("0") == 5)
+            {
+                AreaCode = AreaCode.Remove(4);
+            }
+            EndDate = EndDate.AddDays(1).AddSeconds(-1);
+             var list = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.AreaCode.StartsWith(AreaCode))
+                .GroupBy(x => new { x.HotspotId, x.HotspotName })
+                .Select(x => new EarlyWarningHotsPotsStatisticsDto()
+                {
+                     HotspotId = x.HotspotId,
+                     HotspotName = x.HotspotName,
+                     SumCount = SqlFunc.AggregateCount(x.Id)
+                }).OrderByDescending(x=>x.SumCount).Take(5).ToListAsync();
+            return list;
+        }
+
+        /// <summary>
+        /// 工单当日统计及环比
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("ordercount-statistics")]
+        public async Task<OrderCountStatisticsDto> OrderCountStatistics()
+        {
+            var today = DateTime.Now;
+            var dto = new OrderCountStatisticsDto();
+            #region 当日工单量
+
+            dto.ToDayCount =await _orderRepository.Queryable(false,false,false).Where(x => x.StartTime.Value.Date == today.Date && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+            var beforToDayCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.Date == today.AddDays(-1).Date && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+            if (beforToDayCount == 0)
+            {
+                dto.ToDayQoQ = 0;
+            }
+            else
+            {
+                dto.ToDayQoQ = Math.Round(((dto.ToDayCount - beforToDayCount) / (double)beforToDayCount) * 100, 2);
+            }
+            #endregion
+
+            #region 当月工单量
+
+            dto.ToMonthCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy-MM") == today.ToString("yyyy-MM") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+            var beforToMonthCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy-MM") == today.AddMonths(-1).ToString("yyyy-MM") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+            if (beforToMonthCount==0)
+            {
+                dto.ToMonthQoQ = 0;
+            }
+            else
+            {
+                dto.ToMonthQoQ = Math.Round(((dto.ToMonthCount - beforToMonthCount) / (double)beforToMonthCount) * 100, 2);
+            }
+
+            #endregion
+
+            #region 当年工单量
+
+            dto.ToYearCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy") == today.ToString("yyyy") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+            var beforToYearCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy") == today.AddYears(-1).ToString("yyyy") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+            if (beforToYearCount==0)
+            {
+                dto.ToYearQoQ = 0;
+            }
+            else
+            {
+                dto.ToYearQoQ = Math.Round(((dto.ToYearCount - beforToYearCount) / (double)beforToYearCount) * 100, 4);
+            }
+            #endregion
+
+            return dto;
+        }
+
+        /// <summary>
+        /// 区域受理排行
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("orderarea-accept-statistics")]
+        public async Task<List<OrderAreaAcceptStatisticsDto>> OrderAreaAcceptStatistics(DateTime StartDate,DateTime EndDate)
+        {
+            EndDate = EndDate.AddDays(1).AddSeconds(-1);
+
+            var list = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime>= StartDate && x.StartTime<= EndDate && x.Status > EOrderStatus.WaitForAccept)
+                .LeftJoin<SystemArea>((it,o)=> it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == o.Id)
+                .GroupBy((it,o) => new {
+                    AreaCode = it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                    o.AreaName,
+                })
+                .Select((it,o) => new OrderAreaAcceptStatisticsDto()
+                {
+                    AreaCode = it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                    AreaName = o.AreaName,
+                    AcceptedCount = SqlFunc.AggregateCount(it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6"))),
+                    CompletionCount = SqlFunc.AggregateSum(SqlFunc.IIF(it.Status>= EOrderStatus.Filed,1,0))
+                }).MergeTable().OrderByDescending(it=> it.AcceptedCount).ToListAsync();
+            return list;
+        }
+
+        /// <summary>
+        /// 区域明细数据
+        /// </summary>
+        /// <param name="StartDate"></param>
+        /// <param name="EndDate"></param>
+        /// <param name="AreaCode"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("orderareaaccept-query")]
+        public async Task<OrderAreaAcceptQueryDto> OrderAreaAcceptQuery(DateTime StartDate,DateTime EndDate,string AreaCode)
+        {
+            EndDate = EndDate.AddDays(1).AddSeconds(-1);
+            var dto = new OrderAreaAcceptQueryDto();
+            dto.HandlingCount = await _orderRepository.Queryable(false, false, false).Where(x => x.AreaCode == AreaCode && x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status > EOrderStatus.WaitForAccept && x.Status < EOrderStatus.Filed).CountAsync();
+
+            dto.FiledCount = await _orderRepository.Queryable(false, false, false).Where(x => x.AreaCode == AreaCode && x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status >= EOrderStatus.Filed).CountAsync();
+
+            dto.OverTimeCount = await _orderRepository.Queryable(false, false, false).Where(x => x.AreaCode == AreaCode && x.StartTime >= StartDate && x.StartTime <= EndDate && x.ExpiredStatus == EExpiredStatus.Expired).CountAsync();
+
+            var hotsPot =await _orderRepository.Queryable(false, false, false).Where(x => x.AreaCode == AreaCode && x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status > EOrderStatus.WaitForAccept).GroupBy(x => new { x.HotspotId, x.HotspotName })
+                .Select(x => new
+                {
+                    HotsPotName = x.HotspotName,
+                    HotCount =SqlFunc.AggregateCount(x.HotspotId)
+                }).OrderByDescending(x=>x.HotCount).FirstAsync();
+
+            dto.HotspotName = hotsPot.HotsPotName;
+            return dto;
+        }
+
+        /// <summary>
+        /// 办理中工单概览
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("order-handling-query")]
+        public async Task<List<OrderDto>> OrderHandlingDetailQuery()
+        {
+            var list = await _orderRepository.Queryable(false, false, false).Where(x => x.Status > EOrderStatus.WaitForAccept && x.Status < EOrderStatus.Filed).ToListAsync();
+            return _mapper.Map<List<OrderDto>>(list);
+        }
+
+        /// <summary>
+        /// 30天高频事项预警
+        /// </summary>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("highmatter-warning")]
+        public async Task<List<HighMatterWarningDto>> HighMatterWarning()
+        {
+            var endDate = DateTime.Now.Date.AddDays(1).AddSeconds(-1);
+            var startDate = endDate.AddDays(-30).Date;
+
+            var list = await _orderRepository.Queryable(false, false, false)
+                .Where(x => x.CreationTime >= startDate && x.CreationTime <= endDate)
+                .LeftJoin<SystemArea>((it, o) => it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")) == o.Id)
+                .GroupBy((it, o) => new
+                {
+                    it.AcceptTypeCode,
+                    it.HotspotId,
+                    it.HotspotName,
+                    AreaCode = it.AreaCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                    o.AreaName,
+                })
+                .Having((it,o) => SqlFunc.AggregateCount(it.HotspotName)>=5)
+                .Select((it, o) => new HighMatterWarningDto()
+                {
+                    AreaName = o.AreaName,
+                    //Title = it.Title,
+                    HotspotName = it.HotspotName,
+                    SumCount = SqlFunc.AggregateCount(it.HotspotName),
+                    Id = SqlFunc.AggregateMin(it.Id)
+                })
+                .MergeTable()
+                //.Where(x=>x.SumCount>=5)
+                .LeftJoin<Order>((x,d)=>x.Id==d.Id)
+                .Select((x,d)=>new HighMatterWarningDto() { 
+                    AreaName = x.AreaName,
+                    HotspotName = x.HotspotName,
+                    Title = d.Title,
+                    SumCount = x.SumCount,
+                    Id = d.Id,
+                }).ToListAsync();
+
+            return list;
+        }
+
+        /// <summary>
+        /// 部门满意度排行榜
+        /// </summary>
+        /// <param name="StartDate"></param>
+        /// <param name="EndDate"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("ordervisit-orgsatisfaction-rank")]
+        public async Task<List<OrderVisitOrgSatisfactionRankDto>> OrderVisitOrgSatisfactionRank(DateTime StartDate,DateTime EndDate)
+        {
+           var list = await _orderVisitDetailRepository.Queryable()
+                .Includes(x => x.OrderVisit)
+                .Where(x => x.OrderVisit.VisitTime >= StartDate && x.OrderVisit.VisitTime <= EndDate && x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.Length >= 6 && x.OrderVisit.VisitState == EVisitState.Visited)
+                .GroupBy(x => new
+                {
+                    VisitOrgCode = x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                    x.VisitOrgName
+                })
+                .Select(x => new OrderVisitOrgSatisfactionRankDto()
+                {
+                    VisitOrgCode = x.VisitOrgCode.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("6")),
+                    VisitOrgName = x.VisitOrgName,
+                    SatisfiedCount = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.OrgProcessingResults, "Key") != "1" && SqlFunc.JsonField(x.OrgProcessingResults, "Key") != "2", 1, 0)),
+                    VisitCount = SqlFunc.AggregateCount(x.VisitOrgCode)
+                }).MergeTable().OrderByDescending(x=>x.SatisfiedCount).Take(10).ToListAsync();
+            return list;
+        }
+
+        /// <summary>
+        /// 占比分析
+        /// </summary>
+        /// <param name="StartDate"></param>
+        /// <param name="EndDate"></param>
+        /// <param name="IsSource"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpGet("order-source-accepttype-statistics")]
+        public async Task<List<OrderSourceAndAcceptTtoeStatisticsDto>> OrderSourceAndAcceptTtoeStatistics(DateTime StartDate,DateTime EndDate,bool IsSource)
+        {
+            int SumCount = await _orderRepository.Queryable(false, false, false)
+               .Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+            if (IsSource)
+            {
+                var list = await _orderRepository.Queryable(false, false, false)
+                .Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status > EOrderStatus.WaitForAccept)
+                .GroupBy(x => new { x.SourceChannelCode, x.SourceChannel })
+                .Select(x => new OrderSourceAndAcceptTtoeStatisticsDto()
+                {
+                    Name = x.SourceChannel,
+                    SumCount = SumCount,
+                    HasCount = SqlFunc.AggregateCount(x.SourceChannelCode)
+                }).ToListAsync();
+                return list;
+            }
+            else
+            {
+                var list = await _orderRepository.Queryable(false, false, false)
+                .Where(x => x.StartTime >= StartDate && x.StartTime <= EndDate && x.Status > EOrderStatus.WaitForAccept)
+                .GroupBy( x => new { x.AcceptTypeCode, x.AcceptType })
+                .Select(x => new OrderSourceAndAcceptTtoeStatisticsDto()
+                {
+                    Name = x.AcceptType,
+                    SumCount = SumCount,
+                    HasCount = SqlFunc.AggregateCount(x.AcceptTypeCode),
+                }).ToListAsync();
+                return list;
+            }
+        }
+
+    }
+}

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

@@ -224,6 +224,7 @@ namespace Hotline.Api.Controllers
 			//if (update.Tags.Any()) await _repositoryts.UpdateVectorAsync(update.Id, update.Tags, HttpContext.RequestAborted);
 
 			if (dto.Data.Files.Any()) knowledge.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, knowledge.Id, "", HttpContext.RequestAborted);
+			if (dto.Workflow != null) knowledge.Renewaln =  update.Status != EKnowledgeStatus.Drafts;
 			await _knowledgeRepository.UpdateAsync(knowledge, HttpContext.RequestAborted);
 			if (dto.Workflow != null)
 			{
@@ -534,6 +535,7 @@ namespace Hotline.Api.Controllers
 				.WhereIF(pagedDto.RetrievalType == EKnowledgeRetrievalType.Summary && !string.IsNullOrEmpty(pagedDto.Keyword), d => d.Summary != null && d.Summary.Contains(pagedDto.Keyword!))
 				.WhereIF(!string.IsNullOrEmpty(typeSpliceName), x => x.KnowledgeType.SpliceName.EndsWith(typeSpliceName!))
 				.WhereIF(!string.IsNullOrEmpty(hotspotHotSpotFullName), x => x.HotspotType.HotSpotFullName.EndsWith(hotspotHotSpotFullName!))
+				.WhereIF(!string.IsNullOrEmpty(pagedDto.HotspotName), x => x.HotspotType.HotSpotFullName.EndsWith(pagedDto.HotspotName!))
 				.WhereIF(!string.IsNullOrEmpty(pagedDto.CreateOrgId), x => x.CreatorOrgId != null && x.CreatorOrgId.EndsWith(pagedDto.CreateOrgId!))
 				.WhereIF(!string.IsNullOrEmpty(pagedDto.Attribution), x => x.Attribution == pagedDto.Attribution!);
 			switch (pagedDto.Sort)

+ 56 - 15
src/Hotline.Api/Controllers/OrderController.cs

@@ -41,8 +41,7 @@ using Hotline.Share.Dtos.Push;
 using Hotline.Share.Enums.Push;
 using XF.Domain.Cache;
 using Hotline.Api.Filter;
-using Microsoft.AspNetCore.Authorization;
-using XF.Domain.Entities;
+using Hotline.Push.Notifies;
 
 namespace Hotline.Api.Controllers;
 
@@ -1348,14 +1347,20 @@ public class OrderController : BaseController
         if (dto.Status is EScreenStatus.Apply)
         {
             query.Where(x => (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval)
-                             && SqlFunc.JsonListObjectAny(x.Workflow.HandlerUsers, "Key",
-                                 _sessionContext.RequiredUserId));
+                            && ((SqlFunc.JsonArrayLength(x.Workflow.HandlerUsers) > 0 
+                            &&  SqlFunc.JsonListObjectAny(x.Workflow.HandlerUsers, "Key",_sessionContext.RequiredUserId)) 
+                            ||(SqlFunc.JsonArrayLength(x.Workflow.HandlerUsers)  == 0
+	                        && SqlFunc.JsonListObjectAny(x.Workflow.HandlerOrgs, "Key",
+		                        _sessionContext.RequiredOrgId))));
         }
         if (dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle)
         {
             query.Where(x => (x.Status != EScreenStatus.Apply)
-                             && SqlFunc.JsonListObjectAny(x.Workflow.HandlerUsers, "Key",
-                                 _sessionContext.RequiredUserId));
+							  && ((SqlFunc.JsonArrayLength(x.Workflow.HandlerUsers) > 0
+							       && SqlFunc.JsonListObjectAny(x.Workflow.HandlerUsers, "Key", _sessionContext.RequiredUserId))
+							      || (SqlFunc.JsonArrayLength(x.Workflow.HandlerUsers) == 0
+							          && SqlFunc.JsonListObjectAny(x.Workflow.HandlerOrgs, "Key",
+								          _sessionContext.RequiredOrgId))));
         }
         var (total, items) = await query
             //.WhereIF(dto.Status.HasValue && dto.Status == EScreenStatus.MyHandle,
@@ -1429,11 +1434,36 @@ public class OrderController : BaseController
         }
     }
 
-    /// <summary>
-    /// 查询工单甄别流程开启参数
-    /// </summary>
-    /// <returns></returns>
-    [HttpGet("screen/startflow")]
+
+	/// <summary>
+	/// 工单甄别修改后下一步流程
+	/// </summary>
+	[HttpPost("screen/initial_nextFlow")]
+	[LogFilter("开始工单甄别流程")]
+	public async Task InitialNextFlow([FromBody] ScreenNextFlowDto dto)
+	{
+        var screen = await _orderScreenRepository.GetAsync(dto.Data.Id);
+        _mapper.Map(dto.Data, screen);
+		if (dto.Data.Files.Any())
+			screen.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, screen.Id, "", HttpContext.RequestAborted);
+		await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
+		try
+		{
+            dto.NextWorkflow.WorkflowId = screen.WorkflowId;
+			await _workflowApplication.NextAsync(dto.NextWorkflow,
+					cancellationToken: HttpContext.RequestAborted);
+		}
+		catch (Exception e)
+		{
+			throw new UserFriendlyException($"工单甄别下一步流程失败!, {e.Message}", "工单甄别下一步流程失败");
+		}
+	}
+
+	/// <summary>
+	/// 查询工单甄别流程开启参数
+	/// </summary>
+	/// <returns></returns>
+	[HttpGet("screen/startflow")]
     public async Task<NextStepsDto> GetScreenFlowStartOptionsAsync()
     {
         //return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderScreen,
@@ -1478,12 +1508,14 @@ public class OrderController : BaseController
     public async Task<OrderScreenListDto> ScreenEntity(string id)
     {
         var model = await _orderScreenRepository.Queryable(workflowFilter:false)
+            .Includes(x=> x.Order)
             .Includes(x => x.Workflow)
             .Includes(x => x.Visit, d => d.Order)
             .FirstAsync(x => x.Id == id);
         var rspModel = _mapper.Map<OrderScreenListDto>(model);
         rspModel.IsCanHandle = model.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
-        if (rspModel.FileJson != null && rspModel.FileJson.Any())
+        rspModel.Handle = rspModel.IsCanHandle && "start".Equals(model.Workflow.CurrentStepCode) && model.Workflow.FlowType == EFlowType.Review;
+		if (rspModel.FileJson != null && rspModel.FileJson.Any())
         {
             var ids = rspModel.FileJson.Select(x => x.Id).ToList();
             rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
@@ -2039,7 +2071,8 @@ public class OrderController : BaseController
             if (order.AcceptSms)
             {
                 _logger.LogInformation($"推送短信: orderNo: {order.No}");
-                await _pushDomainService.PushAsync(new MessageDto
+
+                var messageDto = new MessageDto
                 {
                     PushBusiness = EPushBusiness.OrderAccept,
                     ExternalId = order.Id,
@@ -2050,7 +2083,10 @@ public class OrderController : BaseController
                     Remark = order.Title,
                     Name = order.FromName,
                     TelNumber = order.Contact
-                }, HttpContext.RequestAborted);
+                };
+                await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+                //await _pushDomainService.PushAsync(MessageDto, HttpContext.RequestAborted);
+
                 order.SmsSended = true;
                 await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
             }
@@ -2385,7 +2421,7 @@ public class OrderController : BaseController
 
             var applyOrg = _organizeRepository.Get(currentStep.AcceptorOrgId);
             var sendBackOrg = _organizeRepository.Get(prevStep.AcceptorOrgId);
-            if ((twoSendBack && 2.Equals(applyOrg.Level) && 1.Equals(sendBackOrg.Level) && !sendBackOrg.IsCenter) || (oneSendBack && 1.Equals(applyOrg.Level) && sendBackOrg.IsCenter))
+            if ((twoSendBack && 2.Equals(applyOrg.Level) && 1.Equals(sendBackOrg.Level) && !sendBackOrg.IsCenter) || (oneSendBack && 1.Equals(applyOrg.Level) && sendBackOrg.IsCenter && !applyOrg.IsCenter))
             {
                 var audit = new OrderSendBackAudit
                 {
@@ -2402,6 +2438,11 @@ public class OrderController : BaseController
                 };
                 await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
             }
+            //中心内部流转  不走审批流程
+            if (sendBackOrg.IsCenter &&  applyOrg.IsCenter)
+            {
+				await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+			}
         }
         else {
 			await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);

+ 25 - 23
src/Hotline.Api/Controllers/PushMessageController.cs

@@ -47,9 +47,11 @@ namespace Hotline.Api.Controllers
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpPut("add")]
+        [AllowAnonymous]
         public async Task AddMessage([FromBody] MessageDto dto)
         {
-            await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
+            //  await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
+            await _pushDomainService.PushMsgAsync(dto, HttpContext.RequestAborted);
         }
 
         /// <summary>
@@ -60,28 +62,28 @@ namespace Hotline.Api.Controllers
         [HttpGet("{id}")]
         public async Task ResendMessage(string id)
         {
-            var data = await _messageRepository.GetAsync(p => p.Id == id, HttpContext.RequestAborted);
-            if (data is null)
-                throw UserFriendlyException.SameMessage("重新发送失败");
-
-            //修改重发次数
-            data.ResendCount++;
-            await _messageRepository.UpdateAsync(data, HttpContext.RequestAborted);
-            //组装数据
-            MessageDto dto = new()
-            {
-                PushBusiness = data.PushBusiness,
-                ExternalId = data.ExternalId,
-                PushPlatform = data.PushPlatform,
-                //  Status = EPushStatus.Pushing,
-                Template = data.Template,
-                Content = data.Content,
-                Remark = data.Remark,
-                Name = data.Name,
-                TelNumber = data.TelNumber,
-                OrderId = data.OrderId
-            };
-            await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
+            //var data = await _messageRepository.GetAsync(p => p.Id == id, HttpContext.RequestAborted);
+            //if (data is null)
+            //    throw UserFriendlyException.SameMessage("重新发送失败");
+
+            ////修改重发次数
+            //data.ResendCount++;
+            //await _messageRepository.UpdateAsync(data, HttpContext.RequestAborted);
+            ////组装数据
+            //MessageDto dto = new()
+            //{
+            //    PushBusiness = data.PushBusiness,
+            //    ExternalId = data.ExternalId,
+            //    PushPlatform = data.PushPlatform,
+            //    //  Status = EPushStatus.Pushing,
+            //    Template = data.Template,
+            //    Content = data.Content,
+            //    Remark = data.Remark,
+            //    Name = data.Name,
+            //    TelNumber = data.TelNumber,
+            //    OrderId = data.OrderId
+            //};
+            //await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
         }
 
         #endregion

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

@@ -5,5 +5,6 @@
         public const string CallCenter = "CallCenter";
         public const string BigScreenDataShow = "BigScreen-DataShow";
         public const string BigScreenSeatState = "BigScreen-SeatState";
+        public const string BigDataScreen = "BigData-Screen";
     }
 }

+ 8 - 2
src/Hotline.Api/Realtimes/RealtimeMethods.cs

@@ -62,7 +62,13 @@
 		public static string BsSeatStateDataShowArea2 = "BsSeatStateDataShowArea2";
 		public static string BsSeatStateDataShowArea3 = "BsSeatStateDataShowArea3";
 		public static string BsSeatStateDataShowArea4 = "BsSeatStateDataShowArea4";
-		#endregion
-	}
+        #endregion
+
+        #region 大屏数据
+
+        public static string OrderCountStatistics = "OrderCountStatistics";
+
+        #endregion
+    }
 }
     

+ 16 - 3
src/Hotline.Api/Realtimes/RealtimeService.cs

@@ -197,11 +197,24 @@ public class RealtimeService : IRealtimeService, IScopeDependency
 
 	public Task BsSeatStateDataShowChangedAsync4(object obj, CancellationToken cancellationToken) =>
 		SendToGroupAsync(RealtimeGroupNames.BigScreenSeatState, RealtimeMethods.BsSeatStateDataShowArea4, obj, cancellationToken);
-	#endregion
+    #endregion
+
+    #region 数据大屏
+
+    /// <summary>
+    /// 推送年月日工单量数据
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    public Task OrderCountStatisticsAsync(object obj, CancellationToken cancellationToken) =>
+        SendToGroupAsync(RealtimeGroupNames.BigDataScreen, RealtimeMethods.OrderCountStatistics, obj, cancellationToken);
+
+    #endregion
 
-	#region private
+    #region private
 
-	private async Task SendCallCenterMsgAsync(string userId, string msg, object? value, CancellationToken cancellationToken)
+    private async Task SendCallCenterMsgAsync(string userId, string msg, object? value, CancellationToken cancellationToken)
     {
         var connection = await _realtimeCacheManager.GetConnectionAsync(userId, cancellationToken);
         CheckIfInGroup(connection, RealtimeGroupNames.CallCenter);

+ 94 - 0
src/Hotline.Application/Bigscreen/DataScreenRefreshService.cs

@@ -0,0 +1,94 @@
+using Hotline.Caching.Interfaces;
+using Hotline.Orders;
+using Hotline.Realtimes;
+using Hotline.Share.Dtos.Bigscreen;
+using Hotline.Share.Enums.Order;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Constants;
+
+namespace Hotline.Application.Bigscreen
+{
+    public class DataScreenRefreshService: BackgroundService
+    {
+        private readonly IServiceScopeFactory _serviceScopeFactory;
+
+        public DataScreenRefreshService(IServiceScopeFactory serviceScopeFactory)
+        {
+            _serviceScopeFactory = serviceScopeFactory;
+        }
+
+        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+        {
+            using var scope = _serviceScopeFactory.CreateScope();
+            var realtimeService = scope.ServiceProvider.GetRequiredService<IRealtimeService>();
+            var _orderRepository = scope.ServiceProvider.GetRequiredService<IOrderRepository>();
+            var systemSettingCacheManager = scope.ServiceProvider.GetRequiredService<ISystemSettingCacheManager>();
+            try
+            {
+                int times = int.Parse(systemSettingCacheManager.GetSetting(SettingConstants.BsDataStateChangedTimes)?.SettingValue[0]);
+                while (!stoppingToken.IsCancellationRequested)
+                {
+                    var today = DateTime.Now;
+                    var dto = new OrderCountStatisticsDto();
+                    #region 当日工单量
+
+                    dto.ToDayCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.Date == today.Date && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+                    var beforToDayCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.Date == today.AddDays(-1).Date && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+                    if (beforToDayCount == 0)
+                    {
+                        dto.ToDayQoQ = 0;
+                    }
+                    else
+                    {
+                        dto.ToDayQoQ = Math.Round(((dto.ToDayCount - beforToDayCount) / (double)beforToDayCount) * 100, 2);
+                    }
+                    #endregion
+
+                    #region 当月工单量
+
+                    dto.ToMonthCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy-MM") == today.ToString("yyyy-MM") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+                    var beforToMonthCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy-MM") == today.AddMonths(-1).ToString("yyyy-MM") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+                    if (beforToMonthCount == 0)
+                    {
+                        dto.ToMonthQoQ = 0;
+                    }
+                    else
+                    {
+                        dto.ToMonthQoQ = Math.Round(((dto.ToMonthCount - beforToMonthCount) / (double)beforToMonthCount) * 100, 2);
+                    }
+
+                    #endregion
+
+                    #region 当年工单量
+
+                    dto.ToYearCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy") == today.ToString("yyyy") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+                    var beforToYearCount = await _orderRepository.Queryable(false, false, false).Where(x => x.StartTime.Value.ToString("yyyy") == today.AddYears(-1).ToString("yyyy") && x.Status > EOrderStatus.WaitForAccept).CountAsync();
+
+                    if (beforToYearCount == 0)
+                    {
+                        dto.ToYearQoQ = 0;
+                    }
+                    else
+                    {
+                        dto.ToYearQoQ = Math.Round(((dto.ToYearCount - beforToYearCount) / (double)beforToYearCount) * 100, 4);
+                    }
+                    #endregion
+
+                    await realtimeService.OrderCountStatisticsAsync(dto, stoppingToken);
+                    await Task.Delay(times);
+                }
+            }
+            catch {}
+        }
+    }
+}

+ 20 - 2
src/Hotline.Application/Push/PushMessageNotifyHandler.cs

@@ -1,21 +1,39 @@
-using Hotline.Push.Notifies;
+using Hotline.Push.FWMessage;
+using Hotline.Push.Notifies;
 using MediatR;
 
 namespace Hotline.Application.Push
 {
+    /// <summary>
+    /// 内部发送短信
+    /// </summary>
     public class PushMessageNotifyHandler : INotificationHandler<PushMessageNotify>
     {
-
+        /// <summary>
+        /// 
+        /// </summary>
+        private readonly IPushDomainService _pushDomainService;
 
         /// <summary>
         /// 
         /// </summary>
+        /// <param name="pushDomainService"></param>
+        public PushMessageNotifyHandler(IPushDomainService pushDomainService)
+        {
+            _pushDomainService = pushDomainService;
+        }
+
+        /// <summary>
+        /// 内部发送短信
+        /// </summary>
         /// <param name="notification"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         public async Task Handle(PushMessageNotify notification, CancellationToken cancellationToken)
         {
             var data = notification.NotifyDto;
+            await _pushDomainService.PushMsgAsync(data, cancellationToken);
+
         }
     }
 }

+ 19 - 1
src/Hotline.Application/Push/PushTextMessageHandler.cs

@@ -7,9 +7,15 @@ namespace Hotline.Application.Push
 {
     public class PushTextMessageHandler : ICapSubscribe, IScopeDependency
     {
-
+        /// <summary>
+        /// 
+        /// </summary>
         private readonly IPushDomainService _pushDomainService;
 
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="pushDomainService"></param>
         public PushTextMessageHandler(IPushDomainService pushDomainService)
         {
             _pushDomainService = pushDomainService;
@@ -26,5 +32,17 @@ namespace Hotline.Application.Push
         {
             await _pushDomainService.PushAsync(messageDto, cancellation);
         }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="messageDto"></param>
+        /// <param name="cancellation"></param>
+        /// <returns></returns>
+        [CapSubscribe(Hotline.Share.Mq.EventNames.UpdateSendSmsState)]
+        public async Task UpdateSendSmsState(PushReceiveMessageDto messageDto, CancellationToken cancellation)
+        {
+            await _pushDomainService.PushMsgUpdateStateAsync(messageDto, cancellation);
+        }
     }
 }

+ 16 - 6
src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs

@@ -20,19 +20,19 @@ namespace Hotline.Repository.SqlSugar.CallCenter
         {
         }
 
-        public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate,DateTime? endDate,int noConnectByeTimes,int effectiveTimes)
+        public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate,DateTime? endDate,int noConnectByeTimes,int effectiveTimes,int connectByeTimes)
         {
             //计算小时差
             if (!endDate.HasValue)
             {
-                endDate = beginDate.Date.AddDays(1).AddMilliseconds(-1);
+                endDate = beginDate.Date.AddDays(1).AddSeconds(-1);
             }
             TimeSpan timeDifference = endDate.Value.Subtract(beginDate).Duration();
 
             int hourDiff = (int)(timeDifference.TotalHours);
             if (!endDate.HasValue)
             {
-                endDate = beginDate.Date.AddDays(1).AddMilliseconds(-1);
+                endDate = beginDate.Date.AddDays(1).AddSeconds(-1);
             }
             //计算时间差
             int hour = Convert.ToInt32((endDate - beginDate).Value.TotalHours);
@@ -50,9 +50,9 @@ namespace Hotline.Repository.SqlSugar.CallCenter
                 .Select((it, o) => new TrCallHourDto()
                 {
                     Hour = it.ColumnName.Hour, //小时段
-                    EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.Duration >= 15, 1, 0)),//有效接通
-                    ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.Duration > 0 && o.Duration <= 5, 1, 0)), //接通秒挂
-                    NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.Duration == 0 && o.RingTimes <= 5 && o.RingTimes>0, 1, 0)), //未接通秒挂
+                    EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.Duration >= effectiveTimes, 1, 0)),//有效接通
+                    ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.Duration > 0 && o.Duration <= connectByeTimes, 1, 0)), //接通秒挂
+                    NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.Duration == 0 && o.RingTimes <= noConnectByeTimes && o.RingTimes>0, 1, 0)), //未接通秒挂
                     QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.QueueTims > 0 && o.RingTimes == 0, 1, 0)), //队列挂断
                     IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallDirection == ECallDirection.In && o.BeginIvrTime.HasValue && !o.BeginQueueTime.HasValue && !o.BeginRingTime.HasValue && o.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
                 })
@@ -70,5 +70,15 @@ namespace Hotline.Repository.SqlSugar.CallCenter
 
             return resultList;
         }
+
+        public async Task GetCallHotLineList(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes)
+        {
+            endDate = endDate.AddDays(1).AddSeconds(-1);
+            Db.Queryable<TrCallRecord>()
+                .Where(x => x.CreatedTime >= beginDate && x.CreatedTime <= endDate);
+                //.GroupBy(x=>x.);
+        }
+
+
     }
 }

+ 203 - 0
src/Hotline.Share/Dtos/Bigscreen/BigscreenDto.cs

@@ -0,0 +1,203 @@
+
+namespace Hotline.Share.Dtos.Bigscreen
+{
+    public class OrderStatisticsDto
+    {
+        /// <summary>
+        /// 办结数
+        /// </summary>
+        public int CompletionCount { get; set; }
+        /// <summary>
+        /// 办结率
+        /// </summary>
+        public double CompletionRate { get; set; }
+
+        /// <summary>
+        /// 待受理
+        /// </summary>
+        public int HaveToAcceptCount { get; set; }
+
+        /// <summary>
+        /// 待受理率
+        /// </summary>
+        public double HaveToAcceptRate { get; set;}
+
+        /// <summary>
+        /// 超期工单数
+        /// </summary>
+        public int OverTimeCount { get; set; }
+
+        /// <summary>
+        /// 超期率
+        /// </summary>
+        public double OverTimeRate { get; set; }
+
+        /// <summary>
+        /// 延期工单数
+        /// </summary>
+        public int DelayCount { get; set; }
+
+        /// <summary>
+        /// 延期率
+        /// </summary>
+        public double DelayRate { get; set; }
+
+        /// <summary>
+        /// 满意工单数
+        /// </summary>
+        public int SatisfiedCount { get; set; }
+
+        /// <summary>
+        /// 满意率
+        /// </summary>
+        public double SatisfiedRate { get; set; }
+
+        /// <summary>
+        /// 省工单量
+        /// </summary>
+        public int ProvinceOrderCount { get; set; }
+
+        /// <summary>
+        /// 省工单办结
+        /// </summary>
+        public int ProvinceOrderCompletionCount { get; set; }
+    }
+
+    public class KnowledgeStatisticsDto
+    {
+        public int TodayAddCount { get; set; }
+
+        public int ThisMonthModifyCount { get; set; }
+
+        public int TodayReadCount { get; set; }
+
+        public int KnowledgeCount { get; set; }
+    }
+
+    public class OrderTypeHandleStatisticsDto
+    {
+        public string AcceptType { get; set; }
+
+        public int SumCount { get; set; }
+
+        public int HandlingCount { get; set; }
+
+        public int FiledCount { get; set; }
+
+        public int OverTimeCount { get; set; }
+    }
+
+    public class EarlyWarningHotsPotsStatisticsDto
+    {
+        public string HotspotId { get; set; }
+
+        public string HotspotName { get; set; }
+
+        public int SumCount { get; set; }
+    }
+
+    public class OrderCountStatisticsDto
+    {
+        public int ToDayCount { get; set; }
+
+        public double ToDayQoQ { get; set; }
+
+        public int ToMonthCount { get; set;}
+
+        public double ToMonthQoQ { get; set; }
+
+        public int ToYearCount { get; set;}
+
+        public double ToYearQoQ { get; set; }
+    }
+
+    public class OrderAreaAcceptStatisticsDto
+    {
+        public string AreaCode { get; set; }
+        public string AreaName { get; set; }
+
+        public int AcceptedCount { get; set; }
+
+        public int CompletionCount { get; set; }
+
+        public double CompletionRate => CalcCompletion();
+
+        public double CalcCompletion()
+        {
+            if(CompletionCount==0 || AcceptedCount == 0)
+            {
+                return 0;
+            }
+            else
+            {
+                return Math.Round((CompletionCount / (double)AcceptedCount) * 100, 2) ;
+            }
+        }
+
+    }
+
+    public class OrderAreaAcceptQueryDto
+    {
+        public int HandlingCount { get; set; }
+
+        public int FiledCount { get; set; }
+
+        public int OverTimeCount { get; set; }
+
+        public string HotspotName { get; set; }
+    }
+
+    public class HighMatterWarningDto
+    {
+        public string AreaName { get; set; }
+
+        public string Title { get; set; }
+
+        public string HotspotName { get; set; }
+
+        public int SumCount { get; set; }
+
+        public string Id { get; set; }
+    }
+
+    public class OrderVisitOrgSatisfactionRankDto
+    {
+        public string VisitOrgCode { get; set; }
+
+        public string VisitOrgName { get; set; }
+
+        public int SatisfiedCount { get; set; }
+
+        public int VisitCount { get; set; }
+
+        public double SatisfiedRate => CalcSatisfiedRate();
+
+        public double CalcSatisfiedRate()
+        {
+            if (SatisfiedCount == 0 || VisitCount == 0)
+            {
+                return 0;
+            }
+            else
+            {
+                return Math.Round((SatisfiedCount / (double)VisitCount) * 100, 2) ;
+            }
+        }
+    }
+
+    public class OrderSourceAndAcceptTtoeStatisticsDto
+    {
+        public string Name { get; set; }
+
+        public int SumCount { get; set; }
+
+        public int HasCount { get; set; }
+
+        public double HasRate => CalcHasRate();
+
+        public double CalcHasRate()
+        {
+            return Math.Round((HasCount / (double)SumCount) * 100, 2);
+        }
+    }
+}

+ 2 - 2
src/Hotline.Share/Dtos/Knowledge/KnowledgePagedDto.cs

@@ -15,7 +15,6 @@ namespace Hotline.Share.Dtos.Knowledge
     /// <param name="EKnowledgeWorkFlowStatus">审核状态</param>
     public record KnowledgeApprovalPagedListDto(EKnowledgeApplyType? EKnowledgeApplyType, EKnowledgeWorkFlowStatus? EKnowledgeWorkFlowStatus) : PagedKeywordRequest;
 
-
 	/// <summary>
 	/// 知识检索
 	/// </summary>
@@ -24,8 +23,9 @@ namespace Hotline.Share.Dtos.Knowledge
 	/// <param name="Sort">排序字段</param>
 	/// <param name="CreateOrgId">部门id</param>
 	/// <param name="HotspotId">热点id</param>
+    /// <param name="HotspotName">热点名称</param>;
 	/// <param name="KnowledgeTypeId">类型id</param>
-	public record KnowledgeRetrievalPagedListDto(EKnowledgeRetrievalType? RetrievalType,string? Attribution,string Sort, string? CreateOrgId, string? HotspotId, string? KnowledgeTypeId) : PagedKeywordRequest;
+	public record KnowledgeRetrievalPagedListDto(EKnowledgeRetrievalType? RetrievalType,string? Attribution,string Sort, string? CreateOrgId, string? HotspotId, string? HotspotName, string? KnowledgeTypeId) : PagedKeywordRequest;
 
     /// <summary>
     /// 来电弹屏知识库查询

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

@@ -11,6 +11,12 @@ namespace Hotline.Share.Dtos.Order
 {
 	public class OrderScreenDto
 	{
+
+		/// <summary>
+		/// 工单编号
+		/// </summary>
+		public string Id { get; set; }
+
 		/// <summary>
 		/// 工单编号
 		/// </summary>
@@ -77,6 +83,12 @@ namespace Hotline.Share.Dtos.Order
 		/// </summary>
 		public bool IsCanHandle { get; set; }
 
+
+		/// <summary>
+		/// 办理 true  审批 false 
+		/// </summary>
+		public bool Handle { get; set; }
+
 		/// <summary>
 		/// 工单编号
 		/// </summary>

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

@@ -18,7 +18,14 @@ namespace Hotline.Share.Dtos.Order
 
     }
 
-    public class DelayStartFlowDto : StartWorkflowDto<ApplyDelayDto>
+    public class ScreenNextFlowDto 
+    {
+		public OrderScreenDto Data { get; set; }
+
+		public NextWorkflowDto NextWorkflow { get; set; }
+	}
+
+	public class DelayStartFlowDto : StartWorkflowDto<ApplyDelayDto>
     {
 
     }

+ 6 - 16
src/Hotline.Share/Dtos/Push/MessageDto.cs

@@ -14,20 +14,20 @@ namespace Hotline.Share.Dtos.Push
         /// </summary>
         public string ExternalId { get; set; }
 
+        /// <summary>
+        /// 关联工单编号
+        /// </summary>
+        public string? OrderId { get; set; }
+
         /// <summary>
         /// 推送平台
         /// </summary>
         public EPushPlatform PushPlatform { get; set; }
 
-        ///// <summary>
-        ///// 推送状态
-        ///// </summary>
-        //public EPushStatus Status { get; set; }
-
         /// <summary>
         /// 模板
         /// </summary>
-        public string? Template { get; set; }
+        public string? TemplateCode { get; set; }
 
         /// <summary>
         /// 内容
@@ -49,16 +49,6 @@ namespace Hotline.Share.Dtos.Push
         /// </summary>
         public string TelNumber { get; set; }
 
-        /// <summary>
-        /// 发送时间
-        /// </summary>
-        public DateTime? SendTime { get; set; }
-
-        /// <summary>
-        /// 关联工单编号
-        /// </summary>
-        public string? OrderId { get; set; }
-
         /// <summary>
         /// 参数
         /// </summary>

+ 35 - 0
src/Hotline.Share/Dtos/Push/PushMessageDto.cs

@@ -0,0 +1,35 @@
+namespace Hotline.Share.Dtos.Push
+{
+    public class PushMessageDto
+    {
+        /// <summary>
+        /// 业务类型(区分从哪个平台来的短信数据)
+        /// </summary>
+        public string ClientId { get; set; }
+
+        /// <summary>
+        /// 外部业务唯一编号
+        /// </summary>
+        public string? ExternalId { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string? Remark { get; set; }
+
+        /// <summary>
+        /// 接收姓名
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 接收手机号码
+        /// </summary>
+        public string TelNumber { get; set; }
+    }
+}

+ 67 - 0
src/Hotline.Share/Dtos/Push/PushReceiveMessageDto.cs

@@ -0,0 +1,67 @@
+using Hotline.Share.Enums.Push;
+
+namespace Hotline.Share.Dtos.Push
+{
+    public class PushReceiveMessageDto
+    {
+        /// <summary>
+        /// 消息处理类型  0:推送状态修改,2:发送状态,3:短信回复
+        /// </summary>
+        public string Type { get; set; }
+
+        /// <summary>
+        /// 外部业务唯一编号
+        /// </summary>
+        public string? ExternalId { get; set; }
+
+        /// <summary>
+        /// 推送状态
+        /// </summary>
+        public EPushStatus Status { get; set; }
+
+        /// <summary>
+        /// 短信中心待发送ID
+        /// </summary>
+        public string? SmsWaitSendingId { get; set; }
+
+        /// <summary>
+        /// 短信中心已发送ID
+        /// </summary>
+        public string? SmsSendingCompletedId { get; set; }
+
+        /// <summary>
+        /// 短信发送状态
+        /// </summary>
+        public ESendState SendState { get; set; }
+
+        /// <summary>
+        /// 发送时间
+        /// </summary>
+        public DateTime? SendTime { get; set; }
+
+        /// <summary>
+        /// 短信回复是否回复
+        /// </summary>   
+        public bool IsSmsReply { get; set; }
+
+        /// <summary>
+        /// 短信回复内容
+        /// </summary>   
+        public string? SmsReplyContent { get; set; }
+
+        /// <summary>
+        /// 短信回复时间
+        /// </summary>
+        public DateTime? SmsReplyTime { get; set; }
+
+        /// <summary>
+        /// 业务系统短信ID
+        /// </summary>
+        public int WaitSendId { get; set; } = 0;
+
+        /// <summary>
+        /// 发送短信使用的数量
+        /// </summary>
+        public int? MsgCount { get; set; }
+    }
+}

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

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

+ 16 - 0
src/Hotline.Share/Mq/EventNames.PushSms.cs

@@ -0,0 +1,16 @@
+namespace Hotline.Share.Mq
+{
+    public partial class EventNames
+    {
+        /// <summary>
+        /// 发送短信
+        /// </summary>
+        public const string SendSms = "send.sms";
+
+        /// <summary>
+        /// 修改发送状态
+        /// </summary>
+        public const string UpdateSendSmsState = "update.send.sms.state";
+
+    }
+}

+ 4 - 1
src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs

@@ -6,7 +6,10 @@ namespace Hotline.CallCenter.Calls
     public interface ITrCallRecordRepository
     {
 
-        Task<List<TrCallHourDto>?> GetCallHourList(DateTime date, DateTime? endDate, int noConnectByeTimes, int effectiveTimes);
+        Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes,int connectByeTimes);
+
+
+        Task GetCallHotLineList(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes);
 
     }
 }

+ 8 - 0
src/Hotline/KnowledgeBase/Knowledge.cs

@@ -172,6 +172,12 @@ public class Knowledge : WorkflowEntity//   WorkflowEntity  FullStateEntity
 	[SugarColumn(ColumnDescription = "来源部门")]
 	public string? SourceOrganizeId { get; set; }
 
+	/// <summary>
+	/// 是否更新
+	/// </summary>
+	[SugarColumn(ColumnDescription = "是否更新")]
+	public bool? Renewaln { get; set; } = false;
+
 	/// <summary>
 	/// 来源部门
 	/// </summary>
@@ -190,4 +196,6 @@ public class Knowledge : WorkflowEntity//   WorkflowEntity  FullStateEntity
 	[SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)]
 	public List<FileJson>? FileJson { get; set; }
 
+
+
 }

+ 1 - 4
src/Hotline/KnowledgeBase/KnowledgeDomainService.cs

@@ -277,15 +277,12 @@ namespace Hotline.KnowledgeBase
                        .OrderByDescending(p => p.Version)
                        .Take(1)
                        .FirstAsync();
-                    if (oldKnowledge == null)
+                    if (!knowledge.Renewaln.Value)
                     {
-                        knowledge.Version = 1;
                         isSendType = "0";
                     }
                     else
                     {
-                        knowledge.Version = oldKnowledge.Version + 1;
-                        knowledge.PageView = oldKnowledge.PageView;
                         isSendType = "1";
                     }
 

+ 16 - 0
src/Hotline/Push/FWMessage/IPushDomainService.cs

@@ -5,6 +5,22 @@ namespace Hotline.Push.FWMessage
 {
     public interface IPushDomainService
     {
+        /// <summary>
+        /// 短信发送
+        /// </summary>
+        /// <param name="messageDto"></param>
+        /// <param name="cancellation"></param>
+        /// <returns></returns>
+        Task PushMsgAsync(MessageDto messageDto, CancellationToken cancellation);
+
+        /// <summary>
+        /// 修改短信推送状态
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <param name="cancellation"></param>
+        /// <returns></returns>
+        Task PushMsgUpdateStateAsync(PushReceiveMessageDto dto, CancellationToken cancellation);
+
         /// <summary>
         /// 短信发送
         /// </summary>

+ 104 - 7
src/Hotline/Push/FWMessage/PushDomainService.cs

@@ -1,5 +1,4 @@
 using DotNetCore.CAP;
-using Hotline.Push.Notifies;
 using Hotline.Share.Dtos.Push;
 using Hotline.Share.Dtos.Push.FWMessage;
 using Hotline.Share.Enums.Push;
@@ -30,6 +29,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     private readonly IMediator _mediator;
     private readonly ITypedCache<CacheWaitSendId> _cacheWaitSendId;
     private readonly IRepository<MessageTemplate> _messageTemplateRepository;
+    private readonly ICapPublisher _capPublisher;
 
     /// <summary>
     /// 
@@ -40,10 +40,12 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// <param name="config"></param>
     /// <param name="mediator"></param>
     /// <param name="cacheWaitSendId"></param>
+    /// <param name="messageTemplateRepository"></param>
+    /// <param name="capPublisher"></param>
     public PushDomainService(IRepository<Message> messageRepository, IHttpClientFactory httpClientFactory
         , IMapper mapper, IConfiguration config, IMediator mediator,
         ITypedCache<CacheWaitSendId> cacheWaitSendId,
-        IRepository<MessageTemplate> messageTemplateRepository)
+        IRepository<MessageTemplate> messageTemplateRepository, ICapPublisher capPublisher)
     {
         _messageRepository = messageRepository;
         _httpClientFactory = httpClientFactory;
@@ -53,9 +55,104 @@ public class PushDomainService : IPushDomainService, IScopeDependency
         _mediator = mediator;
         _cacheWaitSendId = cacheWaitSendId;
         _messageTemplateRepository = messageTemplateRepository;
+        _capPublisher = capPublisher;
     }
     #endregion
 
+    /// <summary>
+    /// 短信发送
+    /// </summary>
+    /// <param name="messageDto"></param>
+    /// <param name="cancellation"></param>
+    /// <returns></returns>
+    public async Task PushMsgAsync(MessageDto messageDto, CancellationToken cancellation)
+    {
+        if (messageDto == null)
+            throw UserFriendlyException.SameMessage("消息不能为空!");
+
+        if (string.IsNullOrEmpty(messageDto.TemplateCode) && string.IsNullOrEmpty(messageDto.Content))
+            throw UserFriendlyException.SameMessage("模板和内容不能同时为空!");
+
+        #region 替换模板内容
+        //如果模板为空,参数为空则直接用短信内容
+        if (!string.IsNullOrEmpty(messageDto.TemplateCode) && messageDto.Params.Count > 0)
+        {
+            //查询模板信息
+            var messageTemplate = await _messageTemplateRepository.GetAsync(p => p.Code == messageDto.TemplateCode, cancellation);
+            if (messageTemplate == null || string.IsNullOrEmpty(messageTemplate.Content))
+                throw UserFriendlyException.SameMessage("未找到模板短信!");
+
+            string Template = messageTemplate.Content;
+            //正则查询模板中需要替换的内容
+            Regex regex = new(@"\{[a-zA-Z0-9]{1,}\}");
+            var matches = regex.Matches(Template);
+            if (matches != null && matches.Count != messageDto.Params.Count)
+                //参数与需要替换的字符数不匹配
+                throw UserFriendlyException.SameMessage("模板需要参数与实际传递参数个数不匹配!");
+            //reason = "模板需要参数与实际传递参数个数不匹配!";
+
+            //根据正则查询出来的匹配项替换内容
+            for (int i = 0; i < matches.Count; i++)
+                Template = Template.Replace(matches[i].ToString(), messageDto.Params[i]);
+
+            messageDto.Content = Template;
+        }
+        #endregion
+        var message = _mapper.Map<Message>(messageDto);
+        var id = await _messageRepository.AddAsync(message);//写入本地数据库
+
+        PushMessageDto pushMessage = new()
+        {
+            ClientId = "Hotline",
+            ExternalId = id,
+            Content = message.Content,
+            Remark = message.Remark,
+            Name = message.Name,
+            TelNumber = message.TelNumber
+        };
+
+        await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SendSms, pushMessage, cancellationToken: cancellation);
+    }
+
+    /// <summary>
+    /// 修改短信推送状态
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="cancellation"></param>
+    /// <returns></returns>
+    public async Task PushMsgUpdateStateAsync(PushReceiveMessageDto dto, CancellationToken cancellation)
+    {
+        var data = await _messageRepository.GetAsync(p => p.Id == dto.ExternalId, cancellation);
+        if (data != null)
+        {
+            if (dto.Type == "0")
+            {
+                if (dto.SendState == ESendState.Sending)
+                {
+                    data.SmsWaitSendingId = dto.SmsWaitSendingId;
+                    data.SendState = ESendState.Sending;
+                    data.Status = EPushStatus.Success;
+                }
+                else
+                    data.Status = EPushStatus.Failed;
+            }
+            else if (dto.Type == "1")
+            {
+                data.SendTime = Convert.ToDateTime(dto.SendTime);
+                data.SendState = dto.SendState;
+                data.MsgCount = dto.MsgCount;
+                data.SmsSendingCompletedId = dto.SmsSendingCompletedId;
+            }
+            else if (dto.Type == "2")
+            {
+                data.IsSmsReply = dto.IsSmsReply;
+                data.SmsReplyTime = Convert.ToDateTime(dto.SmsReplyTime);
+                data.SmsReplyContent = dto.SmsReplyContent;
+            }
+
+            await _messageRepository.UpdateAsync(data, cancellation);
+        }
+    }
 
 
     #region 短信发送
@@ -70,7 +167,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
         if (messageDto == null)
             throw UserFriendlyException.SameMessage("消息不能为空!");
 
-        if (string.IsNullOrEmpty(messageDto.Template) && string.IsNullOrEmpty(messageDto.Content))
+        if (string.IsNullOrEmpty(messageDto.TemplateCode) && string.IsNullOrEmpty(messageDto.Content))
             throw UserFriendlyException.SameMessage("模板和内容不能同时为空!");
 
         Message message = new();
@@ -88,10 +185,10 @@ public class PushDomainService : IPushDomainService, IScopeDependency
             #region 替换模板内容
             string reason = null;
             //如果模板为空,参数为空则直接用短信内容
-            if (!string.IsNullOrEmpty(messageDto.Template) && messageDto.Params.Count > 0)
+            if (!string.IsNullOrEmpty(messageDto.TemplateCode) && messageDto.Params.Count > 0)
             {
                 //查询模板信息
-                var messageTemplate = await _messageTemplateRepository.GetAsync(p => p.Code == messageDto.Template, cancellation);
+                var messageTemplate = await _messageTemplateRepository.GetAsync(p => p.Code == messageDto.TemplateCode, cancellation);
                 if (messageTemplate == null || string.IsNullOrEmpty(messageTemplate.Content))
                     throw UserFriendlyException.SameMessage("未找到模板短信!");
 
@@ -186,7 +283,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// <returns></returns>
     public async Task<string> ReceiveObtain(ReceiveMessageDto receiveMessageDto)
     {
-        string strResult = "error,缺少参数";
+        string strResult = "ok";
         if (receiveMessageDto.account != accountInfo.ReturnAccountUser || receiveMessageDto.pswd != accountInfo.ReturnAccountPwd)
         {
             strResult = "error,参数错误";
@@ -250,7 +347,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
             await _messageRepository.UpdateAsync(data);
 
             //消息处理
-            await _mediator.Publish(new PushMessageNotify(_mapper.Map<PushMessageNotifyDto>(data)));
+            //   await _mediator.Publish(new PushMessageNotify(_mapper.Map<PushMessageNotifyDto>(data)));
 
         }
         // 成功返回值必须是ok

+ 1 - 1
src/Hotline/Push/Notifies/PushMessageNotify.cs

@@ -3,5 +3,5 @@ using MediatR;
 
 namespace Hotline.Push.Notifies
 {
-    public record PushMessageNotify(PushMessageNotifyDto NotifyDto) : INotification;
+    public record PushMessageNotify(MessageDto NotifyDto) : INotification;
 }

+ 13 - 2
src/Hotline/Realtimes/IRealtimeService.cs

@@ -47,7 +47,18 @@ namespace Hotline.Realtimes
         Task BsSeatStateDataShowChangedAsync2(object obj, CancellationToken cancellationToken);
         Task BsSeatStateDataShowChangedAsync3(object obj, CancellationToken cancellationToken);
         Task BsSeatStateDataShowChangedAsync4(object obj, CancellationToken cancellationToken);
-		#endregion
+        #endregion
+
+        #region 大屏数据
+        /// <summary>
+        /// 推送年月日工单量数据
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task OrderCountStatisticsAsync(object obj, CancellationToken cancellationToken);
+
+        #endregion
 
-	}
+    }
 }

+ 4 - 0
src/XF.Domain/Constants/SettingConstants.cs

@@ -116,6 +116,10 @@ namespace XF.Domain.Constants
         /// </summary>
         public const string EffectiveTimes = "EffectiveTimes";
         /// <summary>
+        /// 接通秒挂时间
+        /// </summary>
+        public const string ConnectByeTimes = "ConnectByeTimes";
+        /// <summary>
         /// 大屏数据展示推送间隔时间
         /// </summary>
         public const string BsDataShowChangedTimes = "BsDataShowChangedTimes";