田爽 2 місяців тому
батько
коміт
4e95903380

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

@@ -183,7 +183,7 @@ namespace Hotline.Api.Controllers
                         .ToListAsync(HttpContext.RequestAborted);
                     if (userlist != null && userlist.Count > 0)
                     {
-                        await _circularRecordDomainService.RecordUserHandle(userlist, true);
+                        await _circularRecordDomainService.RecordUserHandle(userlist, true,circular.Title,circular.Content);
                     }
                 }
                 else
@@ -195,7 +195,7 @@ namespace Hotline.Api.Controllers
                         .ToListAsync(HttpContext.RequestAborted);
                     if (orglist != null && orglist.Count > 0)
                     {
-                        await _circularRecordDomainService.RecordOrgHandle(orglist, true);
+                        await _circularRecordDomainService.RecordOrgHandle(orglist, true,circular.Title,circular.Content);
                     }
                 }
             }
@@ -377,7 +377,7 @@ namespace Hotline.Api.Controllers
                     model.ReadedNum++;
                     await _circularRepository.UpdateAsync(model, HttpContext.RequestAborted);
                     //处理计数
-                    await _circularRecordDomainService.RecordUserHandle(new List<string> { _sessionContext.RequiredUserId }, false, cancellationToken: HttpContext.RequestAborted);
+                    await _circularRecordDomainService.RecordUserHandle(new List<string> { _sessionContext.RequiredUserId }, false,"","", cancellationToken: HttpContext.RequestAborted);
                 }
             }
             else
@@ -396,7 +396,7 @@ namespace Hotline.Api.Controllers
                     model.ReadedNum++;
                     await _circularRepository.UpdateAsync(model, HttpContext.RequestAborted);
                     //处理部门计数
-                    await _circularRecordDomainService.RecordOrgHandle(new List<string> { _sessionContext.RequiredOrgId }, false, cancellationToken: HttpContext.RequestAborted);
+                    await _circularRecordDomainService.RecordOrgHandle(new List<string> { _sessionContext.RequiredOrgId }, false,"","", cancellationToken: HttpContext.RequestAborted);
                 }
             }
 

+ 16 - 8
src/Hotline.Api/Controllers/OrderController.cs

@@ -8,6 +8,7 @@ using Hotline.Application.Orders;
 using Hotline.Application.Quality;
 using Hotline.Application.Snapshot;
 using Hotline.Application.Systems;
+using Hotline.Article;
 using Hotline.Authentications;
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
@@ -156,6 +157,7 @@ public class OrderController : BaseController
     private readonly IRepository<SystemDicData> _sysDicDataRepository;
     private readonly IRepository<SystemOrganize> _systemOrganizeRepository;
     private readonly IRepository<OrderComplement> _orderComplementRepository;
+    private readonly ICircularRecordDomainService _circularRecordDomainService;
 
     public OrderController(
         IOrderDomainService orderDomainService,
@@ -229,7 +231,8 @@ public class OrderController : BaseController
         IOrderSnapshotApplication orderSnapshotApplication,
         IRepository<SystemDicData> sysDicDataRepository,
         IRepository<SystemOrganize> systemOrganizeRepository,
-        IRepository<OrderComplement> orderComplementRepository)
+        IRepository<OrderComplement> orderComplementRepository,
+        ICircularRecordDomainService circularRecordDomainService)
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
@@ -303,6 +306,7 @@ public class OrderController : BaseController
         _sysDicDataRepository = sysDicDataRepository;
         _systemOrganizeRepository = systemOrganizeRepository;
         _orderComplementRepository = orderComplementRepository;
+        _circularRecordDomainService = circularRecordDomainService;
     }
 
     #endregion
@@ -3165,8 +3169,8 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName)) //接办部门(综合查询模糊)
             .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepCode), d => d.Order.CurrentStepCode == dto.CurrentStepCode) //当前办理节点
                .WhereIF(_sessionContext.OrgIsCenter == false, d =>
-               (SqlFunc.IsNullOrEmpty(d.RoleId) && d.OrderId.StartsWith(_sessionContext.RequiredOrgId)) ||
-               (SqlFunc.IsNullOrEmpty(d.RoleId) == false && d.OrderId.StartsWith(_sessionContext.RequiredOrgId)) && _sessionContext.Roles.Contains(d.RoleId)
+               (SqlFunc.IsNullOrEmpty(d.RoleId) == true && d.OrgId.StartsWith(_sessionContext.RequiredOrgId)) ||
+               (SqlFunc.IsNullOrEmpty(d.RoleId) == false && d.OrgId.StartsWith(_sessionContext.RequiredOrgId) && _sessionContext.Roles.Contains(d.RoleId))
                )
 
             //   .WhereIF(_sessionContext.RequiredOrgId!="001", x => x.OrgId == _sessionContext.OrgId)
@@ -4215,12 +4219,15 @@ public class OrderController : BaseController
         //泸州任务 311 投诉件需限制受理内容的字数等需求
         if (_appOptions.Value.IsLuZhou && dto.AcceptTypeCode == "35")
         {
-            if (dto.Content.Length < 25)
-                throw UserFriendlyException.SameMessage("保存失败,投诉类型受理内容字数需要至少25个字!");
+            if (dto.SourceChannelCode != "S12345" && dto.SourceChannelCode != "SZMHD" && dto.SourceChannelCode != "XCX" && dto.SourceChannelCode != "JCeT")
+            {
+                if (dto.Content.Length < 25)
+                    throw UserFriendlyException.SameMessage("保存失败,投诉类型受理内容字数需要至少25个字!");
 
-            if (dto.Title.Contains("咨询") || dto.Title.Contains("建议") || dto.Title.Contains("求助") || dto.Title.Contains("举报")
-                || dto.Content.Contains("咨询") || dto.Content.Contains("建议") || dto.Content.Contains("求助") || dto.Content.Contains("举报"))
-                throw UserFriendlyException.SameMessage("保存失败!投诉类型标题和受理内容不能出现'咨询、建议、求助、举报'");
+                if (dto.Title.Contains("咨询") || dto.Title.Contains("建议") || dto.Title.Contains("求助") || dto.Title.Contains("举报")
+                    || dto.Content.Contains("咨询") || dto.Content.Contains("建议") || dto.Content.Contains("求助") || dto.Content.Contains("举报"))
+                    throw UserFriendlyException.SameMessage("保存失败!投诉类型标题和受理内容不能出现'咨询、建议、求助、举报'");
+            }
         }
 
         //交通工单校验
@@ -8887,6 +8894,7 @@ public class OrderController : BaseController
                     {
                         circularDto.CircularReadGroups = users;
                         //调用推送消息通用接口
+                        await _circularRecordDomainService.AddCircularMessage(circularDto, HttpContext.RequestAborted);
                     }
                 }
             }

+ 6 - 4
src/Hotline.Api/Realtimes/RealtimeService.cs

@@ -129,16 +129,16 @@ public class RealtimeService : IRealtimeService, IScopeDependency
     /// <param name="id"></param>
     /// <param name="cancellationToken"></param>
     /// <returns></returns>
-    public async Task CircularRecoordAsync(string id, CancellationToken cancellationToken)
+    public async Task CircularRecoordAsync(string id,string title,string sendContent, CancellationToken cancellationToken)
     {
         //获取所有需要推送的
         var record = await _circularRecordRepository.Queryable().Where(x => x.Id == id).FirstAsync();
 
         if (record.CircularType == Share.Enums.Article.ECircularType.Person)
         {
-            //个人
+            //个人数量
             await SendToUserAsync(record.UserId, RealtimeMethods.CircularRecord,
-                new CircularRecoordDto() { CircularType = Share.Enums.Article.ECircularType.Person, Count = record.RecordCount },
+                new CircularRecoordDto() { CircularType = Share.Enums.Article.ECircularType.Person, Count = record.RecordCount,SendContent = sendContent,Title= title },
                 cancellationToken);
         }
         else
@@ -149,10 +149,12 @@ public class RealtimeService : IRealtimeService, IScopeDependency
             {
                 try
                 {
+                    //数量
                     await SendToUserAsync(user.Id, RealtimeMethods.CircularRecord,
                         new CircularRecoordDto()
-                        { CircularType = Share.Enums.Article.ECircularType.Org, Count = record.RecordCount },
+                        { CircularType = Share.Enums.Article.ECircularType.Org, Count = record.RecordCount,SendContent = sendContent,Title = title },
                         cancellationToken);
+
                 }
                 catch
                 {

+ 220 - 19
src/Hotline.Application/IndustryClassification/IndustryClassificationApplication.cs

@@ -3,6 +3,7 @@ using Hotline.IndustryClassification;
 using Hotline.Orders;
 using Hotline.Settings;
 using Hotline.Share.Dtos.IndustryClassification;
+using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Requests;
 using MapsterMapper;
@@ -18,16 +19,19 @@ namespace Hotline.Application.IndustryClassification
         private readonly ISystemOrganizeRepository _organizeRepository;
         private readonly IIndustryClassificationRepositpry _industrialManagementRepository;
         private readonly ISessionContext _sessionContext;
+        private readonly IOrderRepository _orderRepository;
 
         public IndustryClassificationApplication(IMapper mapper,
             ISystemOrganizeRepository organizeRepository,
             IIndustryClassificationRepositpry industrialManagementRepository,
-            ISessionContext sessionContext)
+            ISessionContext sessionContext,
+            IOrderRepository orderRepository)
         {
             _mapper = mapper;
             _organizeRepository = organizeRepository;
             _industrialManagementRepository = industrialManagementRepository;
             _sessionContext = sessionContext;
+            _orderRepository = orderRepository;
         }
 
         /// <summary>
@@ -56,22 +60,86 @@ namespace Hotline.Application.IndustryClassification
         /// </summary>
         /// <param name="dto"></param>
         /// <returns></returns>
-        public ISugarQueryable<IndustrialManagementOrderDto> GetIndustrialManagementOrderList(IndustrialManagementRequestDto dto)
+        public  ISugarQueryable<IndustrialManagementOrderDto> GetIndustrialManagementOrderList(IndustrialManagementRequestDto dto)
         {
             string industrialId = "";
             if (!_sessionContext.OrgIsCenter)
             {
                 var industrial = _industrialManagementRepository.Queryable()
                       .Includes(d => d.Orgs)
-                      .FirstAsync(d => d.Orgs.Any(p => p.Id == _sessionContext.RequiredOrgId)).GetAwaiter();
-                industrialId = industrial.GetResult().Id;
+                      .FirstAsync(d => d.Orgs.Any(p => p.Id == _sessionContext.RequiredOrgId)).GetAwaiter().GetResult();
+                if (industrial is not null)
+                    industrialId = industrial.Id;
+                else
+                    industrialId = "-1";
             }
 
-            var query = _industrialManagementRepository.Queryable()
+            var queryorder = _industrialManagementRepository.Queryable()
+             .InnerJoin<IndustryAssociations>((i, io) => i.Id == io.IndustrialManagementId)
+             .InnerJoin<Order>((i, io, o) => io.OrganizeId == o.ActualHandleOrgCode)
+             // .InnerJoin<Order>((i, io, s, o) => s.ExternalId == o.Id)
+             .Where((i, io, o) => o.Status >= EOrderStatus.Filed)
+             .WhereIF(!string.IsNullOrEmpty(industrialId), (i, io, o) => io.IndustrialManagementId == industrialId)
+             .OrderBy((i, io, o) => i.Id)
+             .GroupBy((i, io, o) => new
+             {
+                 o.Id,
+                 o.Status,
+                 IndustrialId = i.Id,
+                 i.IndustrialName,
+                 o.Title,
+                 o.No,
+                 o.AcceptType,
+                 o.AcceptTypeCode,
+                 o.HotspotId,
+                 o.HotspotName,
+                 o.HotspotSpliceName,
+                 o.HotspotExternal,
+                 o.CreationTime,
+                 o.StartTime,
+                 o.OrgLevelOneCode,
+                 o.OrgLevelOneName,
+                 o.ActualHandleOrgName,
+                 o.ActualHandleOrgCode,
+                 o.CounterSignType,
+                 o.FiledTime,
+                 o.ExpiredTime,
+                 o.NearlyExpiredTime,
+                 o.NearlyExpiredTimeOne
+             })
+             .Select((i, io, o) => new IndustrialManagementOrderDto
+             {
+
+                 Id = o.Id,
+                 Status = o.Status,
+                 IndustrialId = i.Id,
+                 IndustrialName = i.IndustrialName,
+                 Title = o.Title,
+                 No = o.No,
+                 AcceptType = o.AcceptType,
+                 AcceptTypeCode = o.AcceptTypeCode,
+                 HotspotId = o.HotspotId,
+                 HotspotName = o.HotspotName,
+                 HotspotSpliceName = o.HotspotSpliceName,
+                 HotspotExternal = o.HotspotExternal,
+                 CreationTime = o.CreationTime,
+                 StartTime = o.StartTime,
+                 OrgLevelOneCode = o.OrgLevelOneCode,
+                 OrgLevelOneName = o.OrgLevelOneName,
+                 ActualHandleOrgName = o.ActualHandleOrgName,
+                 ActualHandleOrgCode = o.ActualHandleOrgCode,
+                 CounterSignType = o.CounterSignType,
+                 FiledTime = o.FiledTime,
+                 ExpiredTime = o.ExpiredTime,
+                 NearlyExpiredTime = o.NearlyExpiredTime,
+                 NearlyExpiredTimeOne = o.NearlyExpiredTimeOne
+             }).MergeTable()
+               ;
+            var queryhuiqian = _industrialManagementRepository.Queryable()
                 .InnerJoin<IndustryAssociations>((i, io) => i.Id == io.IndustrialManagementId)
-                .InnerJoin<WorkflowStep>((i, io, s) => io.OrganizeId == s.HandlerOrgId)
+                .InnerJoin<WorkflowTrace>((i, io, s) => io.OrganizeId == s.HandlerOrgId)
                 .InnerJoin<Order>((i, io, s, o) => s.ExternalId == o.Id)
-                .Where((i, io, s, o) => o.Status >= EOrderStatus.Filed)
+                .Where((i, io, s, o) => o.Status >= EOrderStatus.Filed && s.CountersignPosition == ECountersignPosition.Direct)
                 .WhereIF(!string.IsNullOrEmpty(industrialId), (i, io, s, o) => io.IndustrialManagementId == industrialId)
                 .OrderBy((i, io, s, o) => i.Id)
                 .GroupBy((i, io, s, o) => new
@@ -127,20 +195,153 @@ namespace Hotline.Application.IndustryClassification
                     NearlyExpiredTime = o.NearlyExpiredTime,
                     NearlyExpiredTimeOne = o.NearlyExpiredTimeOne
                 }).MergeTable()
-                .WhereIF(!string.IsNullOrEmpty(dto.IndustrialName), d => d.IndustrialName.Contains(dto.IndustrialName))
-                .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
-                .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No))
-                .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), d => d.AcceptTypeCode == dto.AcceptTypeCode)
-                  .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime) //受理时间开始
-                .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime) //受理时间结束
-                .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), d => d.HotspotSpliceName.Contains(dto.HotspotSpliceName))
-                .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.OrgLevelOneName.Contains(dto.OrgLevelOneName))
-                .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
-                .OrderByIF(string.IsNullOrEmpty(dto.SortField), d => d.CreationTime, OrderByType.Desc) //默认排序时间为创建时间
-                .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, d => d.CreationTime, OrderByType.Asc) //工单创建时间
-                .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, d => d.CreationTime, OrderByType.Desc) //工单创建时间降序
                 ;
+
+            var query = _orderRepository.UnionAll(queryorder, queryhuiqian)
+                       .OrderBy(d => d.Id)
+                       .GroupBy(d => new
+                       {
+                           d.Id,
+                           d.Status,
+                           d.IndustrialId,
+                           d.IndustrialName,
+                           d.Title,
+                           d.No,
+                           d.AcceptType,
+                           d.AcceptTypeCode,
+                           d.HotspotId,
+                           d.HotspotName,
+                           d.HotspotSpliceName,
+                           d.HotspotExternal,
+                           d.CreationTime,
+                           d.StartTime,
+                           d.OrgLevelOneCode,
+                           d.OrgLevelOneName,
+                           d.ActualHandleOrgName,
+                           d.ActualHandleOrgCode,
+                           d.CounterSignType,
+                           d.FiledTime,
+                           d.ExpiredTime,
+                           d.NearlyExpiredTime,
+                           d.NearlyExpiredTimeOne
+                       })
+                       .Select(d => new IndustrialManagementOrderDto
+                       {
+
+                           Id = d.Id,
+                           Status = d.Status,
+                           IndustrialId = d.IndustrialId,
+                           IndustrialName = d.IndustrialName,
+                           Title = d.Title,
+                           No = d.No,
+                           AcceptType = d.AcceptType,
+                           AcceptTypeCode = d.AcceptTypeCode,
+                           HotspotId = d.HotspotId,
+                           HotspotName = d.HotspotName,
+                           HotspotSpliceName = d.HotspotSpliceName,
+                           HotspotExternal = d.HotspotExternal,
+                           CreationTime = d.CreationTime,
+                           StartTime = d.StartTime,
+                           OrgLevelOneCode = d.OrgLevelOneCode,
+                           OrgLevelOneName = d.OrgLevelOneName,
+                           ActualHandleOrgName = d.ActualHandleOrgName,
+                           ActualHandleOrgCode = d.ActualHandleOrgCode,
+                           CounterSignType = d.CounterSignType,
+                           FiledTime = d.FiledTime,
+                           ExpiredTime = d.ExpiredTime,
+                           NearlyExpiredTime = d.NearlyExpiredTime,
+                           NearlyExpiredTimeOne = d.NearlyExpiredTimeOne
+                       }).MergeTable()
+                       .WhereIF(!string.IsNullOrEmpty(dto.IndustrialName), d => d.IndustrialName.Contains(dto.IndustrialName))
+                       .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
+                       .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No))
+                       .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), d => d.AcceptTypeCode == dto.AcceptTypeCode)
+                         .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime) //受理时间开始
+                       .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime) //受理时间结束
+                       .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), d => d.HotspotSpliceName.Contains(dto.HotspotSpliceName))
+                       .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.OrgLevelOneName.Contains(dto.OrgLevelOneName))
+                       .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
+                       .OrderByIF(string.IsNullOrEmpty(dto.SortField), d => d.CreationTime, OrderByType.Desc) //默认排序时间为创建时间
+                       .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, d => d.CreationTime, OrderByType.Asc) //工单创建时间
+                       .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, d => d.CreationTime, OrderByType.Desc) //工单创建时间降序
+                       ;
+
             return query;
+
+            //var query = _industrialManagementRepository.Queryable()
+            //    .InnerJoin<IndustryAssociations>((i, io) => i.Id == io.IndustrialManagementId)
+            //    .InnerJoin<WorkflowStep>((i, io, s) => io.OrganizeId == s.HandlerOrgId)
+            //    .InnerJoin<Order>((i, io, s, o) => s.ExternalId == o.Id)
+            //    .Where((i, io, s, o) => o.Status >= EOrderStatus.Filed)
+            //    .WhereIF(!string.IsNullOrEmpty(industrialId), (i, io, s, o) => io.IndustrialManagementId == industrialId)
+            //    .OrderBy((i, io, s, o) => i.Id)
+            //    .GroupBy((i, io, s, o) => new
+            //    {
+            //        o.Id,
+            //        o.Status,
+            //        IndustrialId = i.Id,
+            //        i.IndustrialName,
+            //        o.Title,
+            //        o.No,
+            //        o.AcceptType,
+            //        o.AcceptTypeCode,
+            //        o.HotspotId,
+            //        o.HotspotName,
+            //        o.HotspotSpliceName,
+            //        o.HotspotExternal,
+            //        o.CreationTime,
+            //        o.StartTime,
+            //        o.OrgLevelOneCode,
+            //        o.OrgLevelOneName,
+            //        o.ActualHandleOrgName,
+            //        o.ActualHandleOrgCode,
+            //        o.CounterSignType,
+            //        o.FiledTime,
+            //        o.ExpiredTime,
+            //        o.NearlyExpiredTime,
+            //        o.NearlyExpiredTimeOne
+            //    })
+            //    .Select((i, io, s, o) => new IndustrialManagementOrderDto
+            //    {
+
+            //        Id = o.Id,
+            //        Status = o.Status,
+            //        IndustrialId = i.Id,
+            //        IndustrialName = i.IndustrialName,
+            //        Title = o.Title,
+            //        No = o.No,
+            //        AcceptType = o.AcceptType,
+            //        AcceptTypeCode = o.AcceptTypeCode,
+            //        HotspotId = o.HotspotId,
+            //        HotspotName = o.HotspotName,
+            //        HotspotSpliceName = o.HotspotSpliceName,
+            //        HotspotExternal = o.HotspotExternal,
+            //        CreationTime = o.CreationTime,
+            //        StartTime = o.StartTime,
+            //        OrgLevelOneCode = o.OrgLevelOneCode,
+            //        OrgLevelOneName = o.OrgLevelOneName,
+            //        ActualHandleOrgName = o.ActualHandleOrgName,
+            //        ActualHandleOrgCode = o.ActualHandleOrgCode,
+            //        CounterSignType = o.CounterSignType,
+            //        FiledTime = o.FiledTime,
+            //        ExpiredTime = o.ExpiredTime,
+            //        NearlyExpiredTime = o.NearlyExpiredTime,
+            //        NearlyExpiredTimeOne = o.NearlyExpiredTimeOne
+            //    }).MergeTable()
+            //    .WhereIF(!string.IsNullOrEmpty(dto.IndustrialName), d => d.IndustrialName.Contains(dto.IndustrialName))
+            //    .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
+            //    .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No))
+            //    .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), d => d.AcceptTypeCode == dto.AcceptTypeCode)
+            //      .WhereIF(dto.StartTime.HasValue, d => d.CreationTime >= dto.StartTime) //受理时间开始
+            //    .WhereIF(dto.EndTime.HasValue, d => d.CreationTime <= dto.EndTime) //受理时间结束
+            //    .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), d => d.HotspotSpliceName.Contains(dto.HotspotSpliceName))
+            //    .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), d => d.OrgLevelOneName.Contains(dto.OrgLevelOneName))
+            //    .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), d => d.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
+            //    .OrderByIF(string.IsNullOrEmpty(dto.SortField), d => d.CreationTime, OrderByType.Desc) //默认排序时间为创建时间
+            //    .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, d => d.CreationTime, OrderByType.Asc) //工单创建时间
+            //    .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, d => d.CreationTime, OrderByType.Desc) //工单创建时间降序
+            //    ;
+
         }
     }
 }

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

@@ -113,7 +113,8 @@ public class OrderMapperConfigs : IRegister
             .Map(d => d.OrderExtension.Id, x => x.Id)
             //.IgnoreIf((s, d) => !string.IsNullOrEmpty(s.FileOpinion), d => d.FileOpinion)
             //.IgnoreIf((s, d) => !string.IsNullOrEmpty(s.CenterOpinion), d => d.CenterToOrgOpinion)
-            .Ignore(d => d.ProvinceNo);
+            .Ignore(d => d.ProvinceNo)
+            .Ignore(d => d.SmsSended);
 
         config.ForType<Workflow, Order>()
             .Map(d => d.WorkflowId, s => s.Id)
@@ -237,15 +238,15 @@ public class OrderMapperConfigs : IRegister
             .Map(d => d.ArrangeOpinion, s => s.OrderPublish.ArrangeOpinion)
             .AfterMapping((s, d) =>
             {
-                if(s.TraceStyle == ETraceStyle.Visit 
-                   && s.OrderVisit != null 
+                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
+                if (s.TraceStyle == ETraceStyle.Visit
                    && s.OrderVisit != null
                    && s.OrderVisit.OrderVisitDetails.Any(x => x.VisitTarget == EVisitTarget.Org))
                 {

+ 4 - 4
src/Hotline.Application/Orders/OrderApplication.cs

@@ -777,8 +777,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                                                                                               //    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.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, d => d.IsProvince == true)
+            .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, d => d.IsProvince == false)
             //.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)
@@ -1528,8 +1528,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 .WhereIF(!string.IsNullOrEmpty(dto.AreaCode) && dto.AreaCode.LastIndexOf("00") > 0,
                     d => d.AreaCode.StartsWith(SqlFunc.Substring(dto.AreaCode, 0, 4)))
                 .WhereIF(!string.IsNullOrEmpty(dto.AreaCode) && dto.AreaCode.LastIndexOf("00") <= 0, d => d.AreaCode.StartsWith(dto.AreaCode))
-                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, d => d.Source == ESource.ProvinceStraight)
-                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, d => d.Source != ESource.ProvinceStraight)
+                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, d => d.IsProvince == true)
+                .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, d => d.IsProvince == false)
                 .WhereIF(!string.IsNullOrEmpty(dto.SensitiveWord), d => SqlFunc.JsonArrayAny(d.Sensitive, dto.SensitiveWord))
                 .WhereIF(dto.IsSensitiveWord.HasValue && dto.IsSensitiveWord == true,
                     d => d.Sensitive != null && SqlFunc.JsonArrayLength(d.Sensitive) > 0)

+ 82 - 66
src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs

@@ -31,6 +31,7 @@ using DocumentFormat.OpenXml.Office2010.Excel;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Validators.FlowEngine;
 using FluentValidation;
+using Hotline.Authentications;
 
 namespace Hotline.Application.Orders
 {
@@ -53,9 +54,9 @@ namespace Hotline.Application.Orders
         private readonly IOrderDomainService _orderDomainService;
         private readonly IOrderScreenRepository _orderScreenRepository;
         private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
-		private readonly IOrderApplication _orderApplication;
+        private readonly IOrderApplication _orderApplication;
 
-		public OrderSecondaryHandlingApplication(
+        public OrderSecondaryHandlingApplication(
             IMapper mapper,
             IRepository<OrderSecondaryHandling> orderSecondaryHandlingRepository,
             IFileRepository fileRepository,
@@ -72,8 +73,8 @@ namespace Hotline.Application.Orders
             IOrderDomainService orderDomainService,
             IOrderScreenRepository orderScreenRepository,
             IOptionsSnapshot<AppConfiguration> appOptions,
-			ICalcExpireTime expireTime,
-			IOrderApplication orderApplication)
+            ICalcExpireTime expireTime,
+            IOrderApplication orderApplication)
         {
             _mapper = mapper;
             _orderSecondaryHandlingRepository = orderSecondaryHandlingRepository;
@@ -92,8 +93,8 @@ namespace Hotline.Application.Orders
             _expireTime = expireTime;
             _orderScreenRepository = orderScreenRepository;
             _appOptions = appOptions;
-			_orderApplication = orderApplication;
-		}
+            _orderApplication = orderApplication;
+        }
 
         /// <summary>
         ///  二次办理新增
@@ -149,9 +150,9 @@ namespace Hotline.Application.Orders
             var visit = await _orderVisitRepository.GetAsync(x => x.Id == model.VisitId, cancellationToken);
             if (visit != null)
             {
-				//visit.VisitState = model.VisitState;
-				visit.IsCanHandle = true;
-				await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+                //visit.VisitState = model.VisitState;
+                visit.IsCanHandle = true;
+                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
             }
         }
 
@@ -168,14 +169,14 @@ namespace Hotline.Application.Orders
             model.AuditUser = _sessionContext.UserName;
             model.AuditTime = DateTime.Now;
             var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == model.OrderId, cancellationToken);
-			if (model.State == ESecondaryHandlingState.End)
+            if (model.State == ESecondaryHandlingState.End)
             {
                 var order = await _orderRepository.GetAsync(x => x.Id == model.OrderId, cancellationToken);
                 if (string.IsNullOrEmpty(order.WorkflowId))
                     throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程信息!");
                 string orgId = order.CounterSignType == ECounterSignType.Department ? model.ApplyOrgId.Substring(0, 6) : model.ApplyOrgId;
-				var step = await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, orgId, cancellationToken);
-				if (step == null)
+                var step = await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, orgId, cancellationToken);
+                if (step == null)
                     throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程节点!");
                 var recall = new RecallDto
                 {
@@ -190,18 +191,18 @@ namespace Hotline.Application.Orders
                 };
                 var reTransactNum = order.ReTransactNum is null ? 1 : order.ReTransactNum + 1;
                 //var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode);
-                
-                var expiredTime = await _expireTime.CalcEndTime(DateTime.Now,DateTime.Now, order.AcceptTypeCode);
+
+                var expiredTime = await _expireTime.CalcEndTime(DateTime.Now, DateTime.Now, order.AcceptTypeCode);
                 var processType = step.FlowDirection == EFlowDirection.OrgToCenter || step.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban;
                 var isOrderFiled = order.Status >= EOrderStatus.Filed;
                 order.ExpiredTime = expiredTime.ExpiredTime;
-				order.NearlyExpiredTime = expiredTime.NearlyExpiredTime;
-				order.NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne;
-				order.ReTransactNum = reTransactNum;
-				order.ProcessType = processType;
-				order.Status = EOrderStatus.Special;
+                order.NearlyExpiredTime = expiredTime.NearlyExpiredTime;
+                order.NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne;
+                order.ReTransactNum = reTransactNum;
+                order.ProcessType = processType;
+                order.Status = EOrderStatus.Special;
 
-				await _orderRepository.Updateable().SetColumns(o => new Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ReTransactNum = reTransactNum, ProcessType = processType, Status = EOrderStatus.Handling })
+                await _orderRepository.Updateable().SetColumns(o => new Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ReTransactNum = reTransactNum, ProcessType = processType, Status = EOrderStatus.Handling })
                     .Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
                 var orderDto = _mapper.Map<OrderDto>(order);
                 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: cancellationToken);
@@ -224,29 +225,29 @@ namespace Hotline.Application.Orders
                 if (_appOptions.Value.IsYiBin)
                 {
                     var screen = await _orderScreenRepository.Queryable().FirstAsync(
-					x => x.OrderId == model.OrderId &&
-					     (x.Status != EScreenStatus.End && x.Status != EScreenStatus.Refuse), cancellationToken);
-					if (screen != null)
-					{
-						await _orderScreenRepository.RemoveAsync(screen, false, cancellationToken);
-					}
+                    x => x.OrderId == model.OrderId &&
+                         (x.Status != EScreenStatus.End && x.Status != EScreenStatus.Refuse), cancellationToken);
+                    if (screen != null)
+                    {
+                        await _orderScreenRepository.RemoveAsync(screen, false, cancellationToken);
+                    }
                 }
 
-				var (workflow, targetStepDefine, currentStep, targetStep, newStep, isOrgToCenter) = await _workflowDomainService.RecallAsync(recall,
-						recall.NextHandlers.FirstOrDefault(), EWorkflowTraceType.SecondHandle,
-						order.ExpiredTime, order.Status >= EOrderStatus.Filed, EHandleMode.SecondaryHandle,
-						async (workflow, currentStep, targetStepDefine, targetStep, targetStepNew) =>
-						{
-							var basicWorkflowDto = _mapper.Map<BasicWorkflowDto>(dto);
-							var stepAssignInfo = await _orderApplication.GetOrderRecallAssignInfoAsync(workflow, targetStepDefine, targetStep,
-								basicWorkflowDto, cancellationToken);
-							if (stepAssignInfo is null) return;
-							var validator = new StepAssignInfoValidator();
-							await validator.ValidateAndThrowAsync(stepAssignInfo, cancellationToken);
-
-							targetStepNew.Assign(stepAssignInfo);
-						},
-						cancellationToken);
+                var (workflow, targetStepDefine, currentStep, targetStep, newStep, isOrgToCenter) = await _workflowDomainService.RecallAsync(recall,
+                        recall.NextHandlers.FirstOrDefault(), EWorkflowTraceType.SecondHandle,
+                        order.ExpiredTime, order.Status >= EOrderStatus.Filed, EHandleMode.SecondaryHandle,
+                        async (workflow, currentStep, targetStepDefine, targetStep, targetStepNew) =>
+                        {
+                            var basicWorkflowDto = _mapper.Map<BasicWorkflowDto>(dto);
+                            var stepAssignInfo = await _orderApplication.GetOrderRecallAssignInfoAsync(workflow, targetStepDefine, targetStep,
+                                basicWorkflowDto, cancellationToken);
+                            if (stepAssignInfo is null) return;
+                            var validator = new StepAssignInfoValidator();
+                            await validator.ValidateAndThrowAsync(stepAssignInfo, cancellationToken);
+
+                            targetStepNew.Assign(stepAssignInfo);
+                        },
+                        cancellationToken);
                 _mapper.Map(workflow, order);
                 order.FileEmpty();
                 await _orderRepository.UpdateAsync(order, false, cancellationToken);
@@ -280,7 +281,7 @@ namespace Hotline.Application.Orders
                 .Where(x => x.OrderVisit.Order.IsProvince == false)
                 .LeftJoin<OrderScreen>((x, s) => x.Id == s.VisitDetailId && s.Status < EScreenStatus.End && s.IsDeleted == false)
                 //.Where((x, s) => s.Id == null && (x.SecondaryHandling.State == ESecondaryHandlingState.NotApply || x.SecondaryHandling.Id == null))
-                .Where(x=> SqlFunc.Subqueryable<OrderSecondaryHandling>().Where(osh => osh.VisitDetailId == x.Id &&  osh.State != ESecondaryHandlingState.NotApply).NotAny())
+                .Where(x => SqlFunc.Subqueryable<OrderSecondaryHandling>().Where(osh => osh.VisitDetailId == x.Id && osh.State != ESecondaryHandlingState.NotApply).NotAny())
                 //.Where(x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart)
                 .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order!.No!.Contains(dto.No!))
                 .WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince)
@@ -300,7 +301,7 @@ namespace Hotline.Application.Orders
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason), x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
                 //.Where(x => SqlFunc.Subqueryable<OrderVisit>().Where(ov => ov.Id == x.VisitId && ov.VisitState == EVisitState.Visited && ov.IsCanHandle).Any())
                 .Where((x, s) => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle)
-                .WhereIF(!isAdmin, (x, s) => (x.OrderVisit.Order.CounterSignType ==  ECounterSignType.Department || x.OrderVisit.Order.CounterSignType == null) && x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
+                .WhereIF(!isAdmin, (x, s) => (x.OrderVisit.Order.CounterSignType == ECounterSignType.Department || x.OrderVisit.Order.CounterSignType == null) && x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
                 ;
             if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
             {
@@ -327,14 +328,14 @@ namespace Hotline.Application.Orders
                     ));
             }
 
-			return query.OrderByDescending((x, s) => x.CreationTime);
-		}
+            return query.OrderByDescending((x, s) => x.CreationTime);
+        }
 
-		/// <summary>
-		/// 二次办理列表查询
-		/// </summary>
-		/// <returns></returns>
-		public ISugarQueryable<OrderSecondaryHandling> Query(SecondaryHandlingListDto dto, CancellationToken cancellationToken)
+        /// <summary>
+        /// 二次办理列表查询
+        /// </summary>
+        /// <returns></returns>
+        public ISugarQueryable<OrderSecondaryHandling> Query(SecondaryHandlingListDto dto, CancellationToken cancellationToken)
         {
             if (dto.CreationTimeEnd.HasValue)
                 dto.CreationTimeEnd = dto.CreationTimeEnd.Value.AddDays(1).AddSeconds(-1);
@@ -344,7 +345,7 @@ namespace Hotline.Application.Orders
                 .Includes(x => x.Visit, d => d.Order)
                 .Where(x => x.State > ESecondaryHandlingState.NotApply)
                 .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Visit.Order.Title.Contains(dto.Keyword!) || x.Visit.Order.No.Contains(dto.Keyword!))
-				.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Visit.Order.Title.Contains(dto.Title!))
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Visit.Order.Title.Contains(dto.Title!))
                 .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Visit.Order.No.Contains(dto.No!))
                 .WhereIF(dto.Status is ESecondaryHandlingState.Apply, x => x.State == ESecondaryHandlingState.Apply)
                 .WhereIF(dto.Status is ESecondaryHandlingState.Handled, x => x.State != ESecondaryHandlingState.Apply)
@@ -376,20 +377,27 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         public ISugarQueryable<SecondaryHandlingVo> SecondaryHandlingReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
         {
-            return _orderSecondaryHandlingRepository.Queryable()
-                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
-                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
-                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
-                .Where(x => x.State == ESecondaryHandlingState.End)
-                .GroupBy(x => new { x.ApplyOrgId, x.ApplyOrgName })
-                .Select(x => new SecondaryHandlingVo
-                {
-                    OrgId = x.ApplyOrgId,
-                    OrgName = x.ApplyOrgName,
-                    Num = SqlFunc.AggregateCount(x.Id)
-                })
-                .OrderByIF(dto.SortRule is 0, x => x.Num, OrderByType.Asc)
-                .OrderByIF(dto.SortRule is 1, x => x.Num, OrderByType.Desc);
+            var query = _orderSecondaryHandlingRepository.Queryable();
+
+            var isCenter = _sessionContext.OrgIsCenter;
+            if (!isCenter)
+            {
+                query.Where(x => x.ApplyOrgId.StartsWith(_sessionContext.OrgId));
+            }
+
+            return query.WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
+                        .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
+                        .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
+                        .Where(x => x.State == ESecondaryHandlingState.End)
+                        .GroupBy(x => new { x.ApplyOrgId, x.ApplyOrgName })
+                        .Select(x => new SecondaryHandlingVo
+                        {
+                            OrgId = x.ApplyOrgId,
+                            OrgName = x.ApplyOrgName,
+                            Num = SqlFunc.AggregateCount(x.Id)
+                        })
+                        .OrderByIF(dto.SortRule is 0, x => x.Num, OrderByType.Asc)
+                        .OrderByIF(dto.SortRule is 1, x => x.Num, OrderByType.Desc);
         }
 
         /// <summary>
@@ -418,7 +426,15 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         public ISugarQueryable<SecondaryHandlingSatisfactionVo> SecondaryHandlingSatisfactionReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
         {
-            return _orderSecondaryHandlingRepository.Queryable()
+            var query = _orderSecondaryHandlingRepository.Queryable();
+
+            var isCenter = _sessionContext.OrgIsCenter;
+            if (!isCenter)
+            {
+                query.Where(x => x.ApplyOrgId.StartsWith(_sessionContext.OrgId));
+            }
+
+            return query
                 .Includes(x => x.Order)
                 .Includes(x => x.Visit)
                 .Includes(x => x.VisitDetail)

+ 1 - 5
src/Hotline.Share/Dtos/Article/BulletinDto.cs

@@ -250,11 +250,7 @@ namespace Hotline.Share.Dtos.Article
 
         public bool? IsTimeOut { get; set; }
     }
-
-    public record AddCircularMessage: AddCircularDto
-    {
-
-    }
+   
     public record AddCircularDto
     {
         /// <summary>

+ 4 - 0
src/Hotline.Share/Dtos/Realtime/RingDto.cs

@@ -31,4 +31,8 @@ public record CircularRecoordDto
     public int Count { get; set; }
 
     public ECircularType CircularType { get; set; }
+
+    public string? SendContent { get; set; }
+
+    public string? Title { get; set; }
 }

+ 66 - 8
src/Hotline/Article/CircularRecordDomainService.cs

@@ -1,6 +1,9 @@
 using Hotline.Realtimes;
 using Hotline.Share.Dtos.Article;
 using Hotline.Share.Enums.Article;
+using MapsterMapper;
+using Microsoft.AspNetCore.Http;
+using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Repository;
 
@@ -10,12 +13,21 @@ namespace Hotline.Article
     {
         private readonly IRepository<CircularRecord> _circularRecordRepository;
         private readonly IRealtimeService _realtimeService;
-        public CircularRecordDomainService(IRepository<CircularRecord> circularRecordRepository, IRealtimeService realtimeService)
+        private readonly IMapper _mapper;
+        private readonly IRepository<Circular> _circularRepository;
+        private readonly IRepository<CircularReadGroup> _circularReadGroupRepository;
+        private readonly ISessionContext _sessionContext;
+
+        public CircularRecordDomainService(IRepository<CircularRecord> circularRecordRepository, IRealtimeService realtimeService, IMapper mapper, IRepository<Circular> circularRepository, IRepository<CircularReadGroup> circularReadGroupRepository, ISessionContext sessionContext)
         {
             _circularRecordRepository = circularRecordRepository;
             _realtimeService = realtimeService;
+            _mapper = mapper;
+            _circularRepository = circularRepository;
+            _circularReadGroupRepository = circularReadGroupRepository;
+            _sessionContext = sessionContext;
         }
-        public async Task RecordUserHandle(List<string> userIds, bool isAdd,int count = 1, CancellationToken cancellationToken= default)
+        public async Task RecordUserHandle(List<string> userIds, bool isAdd,string title,string sendContent,int count = 1, CancellationToken cancellationToken= default)
         {
             foreach (var item in userIds)
             {
@@ -53,14 +65,14 @@ namespace Hotline.Article
                 }
                 try
                 {
-                    await _realtimeService.CircularRecoordAsync(userRecord.Id, cancellationToken);
+                    await _realtimeService.CircularRecoordAsync(userRecord.Id,title,sendContent, cancellationToken);
                 }
                 catch{}
             }
             
         }
 
-        public async Task RecordOrgHandle(List<string> orgIds, bool isAdd,int count =1, CancellationToken cancellationToken = default)
+        public async Task RecordOrgHandle(List<string> orgIds, bool isAdd,string title, string sendContent, int count =1, CancellationToken cancellationToken = default)
         {
             foreach (var item in orgIds)
             {
@@ -101,15 +113,61 @@ namespace Hotline.Article
                 }
                 try
                 {
-                    await _realtimeService.CircularRecoordAsync(orgRecord.Id, cancellationToken);
+                    await _realtimeService.CircularRecoordAsync(orgRecord.Id, title, sendContent, cancellationToken);
                 }
                 catch{}
             }
         }
 
-        //public async Task AddCircularMessage(AddCircularMessage dto,ECircularType circularType,List<string> ids,,CancellationToken cancellationToken = default)
-        //{
+        public async Task AddCircularMessage(AddCircularDto dto, CancellationToken cancellationToken = default)
+        {
+            var model = _mapper.Map<Circular>(dto);
+            model.CommitTime = DateTime.Now;
+            model.ExaminTime = DateTime.Now;
+            model.ExaminManId = _sessionContext.UserId;
+            model.CircularState = ECircularState.ReviewPass;
+            model.ExaminOpinion = "内部消息,系统默认通过";
+            model.ReadedNum = 0;
+            model.NeedReadNum = model.CircularReadGroups.Count;
+            model.LostEfficacyTime = DateTime.Now.AddYears(50);
+            var id = await _circularRepository.AddAsync(model,cancellationToken);
+            //子表
+            var list = dto.CircularReadGroups;
+            var readGroupList = new List<CircularReadGroup>();
+            foreach (var item in list)
+            {
+                var readGroup = _mapper.Map<CircularReadGroup>(item);
+                readGroup.CircularId = id;
+                readGroup.IsRead = false;
+                readGroupList.Add(readGroup);
+            }
+            await _circularReadGroupRepository.AddRangeAsync(readGroupList);
 
-        //}
+            //更新阅读数量
+            if (model.CircularType == Share.Enums.Article.ECircularType.Person)
+            {
+                //个人
+                var userlist = await _circularReadGroupRepository.Queryable()
+                    .Where(x => x.CircularId == model.Id)
+                .Select(x => x.UserId)
+                    .ToListAsync();
+                if (userlist != null && userlist.Count > 0)
+                {
+                    await this.RecordUserHandle(userlist, true,model.Title,model.Content);
+                }
+            }
+            else
+            {
+                //部门
+                var orglist = await _circularReadGroupRepository.Queryable()
+                    .Where(x => x.CircularId == model.Id)
+                .Select(x => x.OrgId)
+                    .ToListAsync();
+                if (orglist != null && orglist.Count > 0)
+                {
+                    await this.RecordOrgHandle(orglist, true,model.Title,model.Content);
+                }
+            }
+        }
     }
 }

+ 12 - 2
src/Hotline/Article/ICircularRecordDomainService.cs

@@ -1,10 +1,20 @@
 
+using Hotline.Share.Dtos.Article;
+
 namespace Hotline.Article
 {
     public interface ICircularRecordDomainService
     {
-        Task RecordUserHandle(List<string> userIds,bool isAdd,int count = 1,CancellationToken cancellationToken = default);
+        Task RecordUserHandle(List<string> userIds,bool isAdd,string title, string sendContent, int count = 1,CancellationToken cancellationToken = default);
+
+        Task RecordOrgHandle(List<string> orgIds, bool isAdd,string title, string sendContent, int count = 1, CancellationToken cancellationToken= default);
 
-        Task RecordOrgHandle(List<string> orgIds, bool isAdd, int count = 1, CancellationToken cancellationToken= default);
+        /// <summary>
+        /// 内部通知(无视审核)
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task AddCircularMessage(AddCircularDto dto, CancellationToken cancellationToken = default);
     }
 }

+ 1 - 1
src/Hotline/Realtimes/IRealtimeService.cs

@@ -24,7 +24,7 @@ namespace Hotline.Realtimes
 
         #region 系统消息通知
 
-        Task CircularRecoordAsync(string id, CancellationToken cancellationToken);
+        Task CircularRecoordAsync(string id,string title,string sendContent, CancellationToken cancellationToken);
 
         #endregion