فهرست منبع

Merge branch 'test' into lib/test

libin 3 روز پیش
والد
کامیت
e512aa1696
47فایلهای تغییر یافته به همراه901 افزوده شده و 162 حذف شده
  1. 22 22
      src/Hotline.Ai.Jths/AiVisitService.cs
  2. 8 52
      src/Hotline.Api/Controllers/KnowledgeApplyController.cs
  3. 68 6
      src/Hotline.Api/Controllers/KnowledgeCommonController.cs
  4. 6 6
      src/Hotline.Api/Controllers/KnowledgeController.cs
  5. 14 0
      src/Hotline.Api/Controllers/OrderController.cs
  6. 9 0
      src/Hotline.Api/Controllers/Snapshot/BiSnapshotController.cs
  7. 11 54
      src/Hotline.Api/Controllers/Snapshot/SnapshotBulletinController.cs
  8. 10 0
      src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs
  9. 9 0
      src/Hotline.Api/Controllers/Snapshot/SnapshotUserController.cs
  10. 24 2
      src/Hotline.Application/Snapshot/BiSnapshotApplication.cs
  11. 7 0
      src/Hotline.Application/Snapshot/Contracts/IBiSnapshotApplication.cs
  12. 11 0
      src/Hotline.Application/Snapshot/Contracts/INotificationApplication.cs
  13. 2 0
      src/Hotline.Application/Snapshot/Contracts/ISnapshotApplication.cs
  14. 26 1
      src/Hotline.Application/Snapshot/Contracts/ISnapshotBulletinApplication.cs
  15. 7 0
      src/Hotline.Application/Snapshot/Contracts/ISnapshotUserApplication.cs
  16. 0 0
      src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs
  17. 12 0
      src/Hotline.Application/Snapshot/NotificationApplication.cs
  18. 15 1
      src/Hotline.Application/Snapshot/Notifications/SnapshotHandler.cs
  19. 17 1
      src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs
  20. 109 2
      src/Hotline.Application/Snapshot/SnapshotBulletinApplication.cs
  21. 22 1
      src/Hotline.Application/Snapshot/SnapshotPointsApplication.cs
  22. 14 0
      src/Hotline.Application/Snapshot/SnapshotUserApplication.cs
  23. 0 0
      src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs
  24. 19 0
      src/Hotline.Repository.SqlSugar/Snapshot/NotificationReceiverRepository.cs
  25. 19 0
      src/Hotline.Repository.SqlSugar/Snapshot/NotificationRepository.cs
  26. 62 0
      src/Hotline.Share/Dtos/Snapshot/NotifyDto.cs
  27. 9 0
      src/Hotline.Share/Dtos/Snapshot/PointsDto.cs
  28. 6 1
      src/Hotline.Share/Dtos/Snapshot/SnapshotBulletinDto.cs
  29. 26 0
      src/Hotline.Share/Dtos/Snapshot/SnapshotUserInfoDto.cs
  30. 28 0
      src/Hotline.Share/Dtos/Snapshot/StatisticsDto.cs
  31. 17 0
      src/Hotline.Share/Enums/Snapshot/ENotificationType.cs
  32. 5 0
      src/Hotline.Share/Mq/EventNames.Snapshot.cs
  33. 5 0
      src/Hotline.Share/Tools/DateTimeExtensions.cs
  34. 13 12
      src/Hotline/Orders/Order.cs
  35. 5 0
      src/Hotline/Settings/SettingConstants.cs
  36. 19 0
      src/Hotline/Snapshot/Contracts/INotificationDomainService.cs
  37. 0 0
      src/Hotline/Snapshot/IRepository/IIndustryLogRepository.cs
  38. 12 0
      src/Hotline/Snapshot/IRepository/INotificationReceiverRepository.cs
  39. 12 0
      src/Hotline/Snapshot/IRepository/INotificationRepository.cs
  40. 27 0
      src/Hotline/Snapshot/Notification.cs
  41. 27 0
      src/Hotline/Snapshot/NotificationReceiver.cs
  42. 40 0
      src/Hotline/Snapshot/Services/NotificationDomainService.cs
  43. 19 0
      src/Hotline/Snapshot/SnapshotBulletin.cs
  44. 1 1
      src/XF.Domain.Repository/Entity.cs
  45. 9 0
      test/Hotline.Tests/Application/BiSnapshotApplicationTest.cs
  46. 91 0
      test/Hotline.Tests/Application/SnapshotBulletionApplicationTest.cs
  47. 7 0
      test/Hotline.Tests/Application/SnapshotUserApplicationTest.cs

+ 22 - 22
src/Hotline.Ai.Jths/AiVisitService.cs

@@ -114,24 +114,24 @@ namespace Hotline.Ai.Jths
                 taskData.VariableList = new List<Variable>();
                
                
-                if (!string.IsNullOrEmpty(item.Order.FromName))
-                {
-                    //来电名称
-                    //开发环境 :OC_SCENE_VAR_FIELD11
-                    //生产环境:OC_SCENE_VAR_FIELD12
-                    taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = item.Order.FromName });
-                }
-                else
-                {
-                    //来电名称
-                    //开发环境 :OC_SCENE_VAR_FIELD11
-                    //生产环境:OC_SCENE_VAR_FIELD12
-                    taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = "市民" });
-                }
-                //来电性别
-                //开发环境: OC_SCENE_VAR_FIELD14
-                //生产环境:OC_SCENE_VAR_FIELD14
-                taskData.VariableList.Add(new Variable() { Code = visitFromGenderKey, Value = item.Order.FromGender == EGender.Female ? "女士" : "先生" });
+                //if (!string.IsNullOrEmpty(item.Order.FromName))
+                //{
+                //    //来电名称
+                //    //开发环境 :OC_SCENE_VAR_FIELD11
+                //    //生产环境:OC_SCENE_VAR_FIELD12
+                //    taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = item.Order.FromName });
+                //}
+                //else
+                //{
+                //    //来电名称
+                //    //开发环境 :OC_SCENE_VAR_FIELD11
+                //    //生产环境:OC_SCENE_VAR_FIELD12
+                //    taskData.VariableList.Add(new Variable() { Code = visitFromNameKey, Value = "市民" });
+                //}
+                ////来电性别
+                ////开发环境: OC_SCENE_VAR_FIELD14
+                ////生产环境:OC_SCENE_VAR_FIELD14
+                //taskData.VariableList.Add(new Variable() { Code = visitFromGenderKey, Value = item.Order.FromGender == EGender.Female ? "女士" : "先生" });
                 //来电时间
                 //开发环境:OC_SCENE_VAR_FIELD17
                 //生产环境:OC_SCENE_VAR_FIELD19
@@ -141,10 +141,10 @@ namespace Hotline.Ai.Jths
                 //生产环境:OC_SCENE_VAR_FIELD20
                 taskData.VariableList.Add(new Variable() { Code = visitOrderTitleKey, Value = item.Order.Title });
 
-                //是否来电工单
-                //开发环境:
-                //生产环境:
-                taskData.VariableList.Add(new Variable() { Code = visitIsCallOrderKey, Value = item.Order.SourceChannelCode == "RGDH" ? "income" : "outbound" });
+                ////是否来电工单
+                ////开发环境:
+                ////生产环境:
+                //taskData.VariableList.Add(new Variable() { Code = visitIsCallOrderKey, Value = item.Order.SourceChannelCode == "RGDH" ? "income" : "outbound" });
                 taskDataList.Add(taskData);
             }
             requestData.TaskDataList = taskDataList;

+ 8 - 52
src/Hotline.Api/Controllers/KnowledgeApplyController.cs

@@ -1,14 +1,9 @@
 using Hotline.Application.Knowledge;
 using Hotline.KnowledgeBase;
-using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Knowledge;
-using Hotline.Share.Dtos.ObservationPiece;
-using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.KnowledgeBase;
-using Hotline.Share.Requests;
-using Hotline.Tools;
 using Hotline.Users;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
@@ -45,8 +40,14 @@ namespace Hotline.Api.Controllers
         /// <param name="userRepository"></param>
         /// <param name="systemOrganizeRepository"></param>
         /// <param name="knowledgeDomainService"></param>
-        public KnowledgeApplyController(IRepositoryWorkflow<Knowledge> knowledgeRepository, IRepository<KnowledgeApply> knowledgeApplyRepository, ISessionContext sessionContext
-            , IMapper mapper, IKnowApplication knowApplication, IRepository<User> userRepository, ISystemOrganizeRepository systemOrganizeRepository, IKnowledgeDomainService knowledgeDomainService)
+        public KnowledgeApplyController(IRepositoryWorkflow<Knowledge> knowledgeRepository,
+            IRepository<KnowledgeApply> knowledgeApplyRepository,
+            ISessionContext sessionContext
+            , IMapper mapper,
+            IKnowApplication knowApplication,
+            IRepository<User> userRepository,
+            ISystemOrganizeRepository systemOrganizeRepository,
+            IKnowledgeDomainService knowledgeDomainService)
         {
             _knowledgeRepository = knowledgeRepository;
             _knowledgeApplyRepository = knowledgeApplyRepository;
@@ -273,51 +274,6 @@ namespace Hotline.Api.Controllers
 
         #endregion
 
-        #region 知识超期未更新统计
-        /// <summary>
-        /// 知识超期未更新统计
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        [HttpGet("get-know-overdue-statistics-list")]
-        public async Task<PagedDto<KnowedgeStatisticsDto>> GetKnowOverdueStatisticsList([FromQuery] PagedKeywordRequest dto)
-        {
-            var (total, items) = await _knowApplication.GetKnowedgeStatistics(dto)
-                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-            return new PagedDto<KnowedgeStatisticsDto>(total, items);
-        }
-
-        /// <summary>
-        ///知识超期未更新统计导出
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        [HttpPost("get-know-overdue-statistics-list-export")]
-        public async Task<FileStreamResult> GetKnowOverdueStatisticsListExport([FromBody] ExportExcelDto<PagedKeywordRequest> dto)
-        {
-            var query = _knowApplication.GetKnowedgeStatistics(dto.QueryDto);
-            List<KnowedgeStatisticsDto> data;
-            if (dto.IsExportAll)
-            {
-                data = await query.ToListAsync(HttpContext.RequestAborted);
-            }
-            else
-            {
-                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
-                data = items;
-            }
-
-            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<KnowedgeStatisticsDto>(dto.ColumnInfos);
-
-            var dtos = data
-                .Select(stu => _mapper.Map(stu, typeof(KnowedgeStatisticsDto), dynamicClass))
-                .Cast<object>()
-                .ToList();
 
-            var stream = ExcelHelper.CreateStream(dtos);
-
-            return ExcelStreamResult(stream, "知识超期未更新统计");
-        } 
-        #endregion
     }
 }

+ 68 - 6
src/Hotline.Api/Controllers/KnowledgeCommonController.cs

@@ -1,9 +1,14 @@
-using Hotline.KnowledgeBase;
-using Hotline.Permissions;
+using Hotline.Application.Knowledge;
+using Hotline.KnowledgeBase;
+using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
+using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Share.Requests;
+using Hotline.Tools;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
 using SqlSugar;
@@ -27,6 +32,7 @@ namespace Hotline.Api.Controllers
         private readonly ISessionContext _sessionContext;
         private readonly ISystemOrganizeRepository _systemOrganizeRepository;
         private readonly IRepository<Hotspot> _hotspotTypeRepository;
+        private readonly IKnowApplication _knowApplication;
 
         /// <summary>
         /// 
@@ -34,10 +40,19 @@ namespace Hotline.Api.Controllers
         /// <param name="knowledgeTypeRepository"></param>
         /// <param name="knowledgeTypeDomainService"></param>
         /// <param name="knowledgeStandardRepository"></param>
+        /// <param name="sessionContext"></param>
         /// <param name="mapper"></param>
-        public KnowledgeCommonController(IRepository<KnowledgeType> knowledgeTypeRepository, IKnowledgeTypeDomainService knowledgeTypeDomainService,
-            IRepository<KnowledgeStandard> knowledgeStandardRepository, ISessionContext sessionContext,
-            IMapper mapper, ISystemOrganizeRepository systemOrganizeRepository, IRepository<Hotspot> hotspotTypeRepository)
+        /// <param name="systemOrganizeRepository"></param>
+        /// <param name="hotspotTypeRepository"></param>
+        /// <param name="knowApplication"></param>
+        public KnowledgeCommonController(IRepository<KnowledgeType> knowledgeTypeRepository,
+            IKnowledgeTypeDomainService knowledgeTypeDomainService,
+            IRepository<KnowledgeStandard> knowledgeStandardRepository,
+            ISessionContext sessionContext,
+            IMapper mapper,
+            ISystemOrganizeRepository systemOrganizeRepository,
+            IRepository<Hotspot> hotspotTypeRepository,
+             IKnowApplication knowApplication)
         {
             _knowledgeTypeRepository = knowledgeTypeRepository;
             _knowledgeTypeDomainService = knowledgeTypeDomainService;
@@ -46,6 +61,7 @@ namespace Hotline.Api.Controllers
             _sessionContext = sessionContext;
             _systemOrganizeRepository = systemOrganizeRepository;
             _hotspotTypeRepository = hotspotTypeRepository;
+            _knowApplication = knowApplication;
         }
         #endregion
 
@@ -158,7 +174,7 @@ namespace Hotline.Api.Controllers
                      KnowledgeNum = SqlFunc.Subqueryable<Knowledge>()
                          .InnerJoin<KnowledgeRelationType>((k, krt) => k.Id == krt.KnowledgeId)
                          .InnerJoin<KnowledgeType>((k, krt, t) => krt.KnowledgeTypeId == t.Id)
-                         .Where((k, krt, t) => t.SpliceName.StartsWith(x.SpliceName) &&  k.IsDeleted == false && t.IsDeleted == false)
+                         .Where((k, krt, t) => t.SpliceName.StartsWith(x.SpliceName) && k.IsDeleted == false && t.IsDeleted == false)
                          .WhereIF(!string.IsNullOrEmpty(attribution) && !isCenter, (k, krt, t) => k.Attribution == attribution)
                          .WhereIF(status != null, k => k.Status == status)
                          .DistinctCount(k => k.Id)
@@ -318,5 +334,51 @@ namespace Hotline.Api.Controllers
         }
         #endregion
 
+        #region 知识超期未更新统计
+        /// <summary>
+        /// 知识超期未更新统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("get-know-overdue-statistics-list")]
+        public async Task<PagedDto<KnowedgeStatisticsDto>> GetKnowOverdueStatisticsList([FromQuery] PagedKeywordRequest dto)
+        {
+            var (total, items) = await _knowApplication.GetKnowedgeStatistics(dto)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<KnowedgeStatisticsDto>(total, items);
+        }
+
+        /// <summary>
+        ///知识超期未更新统计导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("get-know-overdue-statistics-list-export")]
+        public async Task<FileStreamResult> GetKnowOverdueStatisticsListExport([FromBody] ExportExcelDto<PagedKeywordRequest> dto)
+        {
+            var query = _knowApplication.GetKnowedgeStatistics(dto.QueryDto);
+            List<KnowedgeStatisticsDto> data;
+            if (dto.IsExportAll)
+            {
+                data = await query.ToListAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                data = items;
+            }
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<KnowedgeStatisticsDto>(dto.ColumnInfos);
+
+            var dtos = data
+                .Select(stu => _mapper.Map(stu, typeof(KnowedgeStatisticsDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "知识超期未更新统计");
+        }
+        #endregion
     }
 }

+ 6 - 6
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -7,17 +7,21 @@ using Hotline.Application.FlowEngine;
 using Hotline.Application.Knowledge;
 using Hotline.Application.Systems;
 using Hotline.Application.Tools;
+using Hotline.Caching.Interfaces;
+using Hotline.Configurations;
 using Hotline.File;
 using Hotline.FlowEngine.WorkflowModules;
 using Hotline.FlowEngine.Workflows;
 using Hotline.KnowledgeBase;
 using Hotline.KnowledgeBase.Notifies;
+using Hotline.Pdf;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Repository.SqlSugar.Ts;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.FlowEngine;
+using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Knowledge;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.Article;
@@ -30,18 +34,14 @@ using Mapster;
 using MapsterMapper;
 using MediatR;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using MiniExcelLibs;
 using SqlSugar;
 using System.Text;
-using Hotline.Configurations;
-using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
-using Hotline.Caching.Interfaces;
-using MiniExcelLibs;
-using Hotline.Pdf;
-using Hotline.Share.Dtos.FlowEngine.Workflow;
 
 namespace Hotline.Api.Controllers
 {

+ 14 - 0
src/Hotline.Api/Controllers/OrderController.cs

@@ -2891,8 +2891,22 @@ public class OrderController : BaseController
     [HttpGet("delay/basedata")]
     public async Task<object> DelayBaseData()
     {
+        var delayStatisticalNodes = _systemSettingCacheManager.GetSetting(SettingConstants.DelayStatisticalNodes).SettingValue;
+        var delayStatisticalNodesList = new List<Kv>();
+        if (delayStatisticalNodes != null && delayStatisticalNodes.Any())
+        {
+            foreach (var item in delayStatisticalNodes)
+            {
+                delayStatisticalNodesList.Add(new Kv
+                {
+                    Key = item,
+                    Value = item
+                });
+            }
+        }
         var rsp = new
         {
+            DelayStatisticalNodes= delayStatisticalNodesList,
             DelayState = EnumExts.GetDescriptions<EDelayState>(),
             QueryDelayState = EnumExts.GetDescriptions<EQueryDelayState>(),
             TimeType = EnumExts.GetDescriptions<ETimeType>(),

+ 9 - 0
src/Hotline.Api/Controllers/Snapshot/BiSnapshotController.cs

@@ -327,4 +327,13 @@ public class BiSnapshotController : BaseController
     [HttpGet("re_transact-statistics-detail")]
     public async Task<PagedDto<ReTransactStatisticsDetailsOutDto>> GetReTransactStatisticsDetailAsync([FromQuery] ReTransactStatisticsDetailsInDto dto)
         => (await _biSnapshotApplication.GetReTransactStatisticsDetail(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 随手拍区域积分统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("county_points")]
+    public async Task<IList<SnapshotCountyPointsStatisticsOutDto>> Get([FromQuery] SnapshotCountyPointsStatisticsInDto dto)
+        => await _biSnapshotApplication.GetAreaPointsStatistics(dto).ToListAsync(HttpContext.RequestAborted);
 }

+ 11 - 54
src/Hotline.Api/Controllers/Snapshot/SnapshotBulletinController.cs

@@ -15,6 +15,7 @@ using Hotline.Share.Tools;
 using XF.Utility.EnumExtensions;
 using Hotline.Snapshot.IRepository;
 using Hotline.Application.Snapshot.Contracts;
+using Hotline.Share.Dtos.Settings;
 
 namespace Hotline.Api.Controllers.Snapshot;
 
@@ -22,17 +23,17 @@ public class SnapshotBulletinController : BaseController
 {
     private readonly ISnapshotBulletinRepository _bulletinRepository;
     private readonly ISnapshotBulletinApplication _bulletinApplication;
-    private readonly ISessionContext _sessionContext;
     private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
     private readonly ISystemOrganizeRepository _organizeRepository;
+    private readonly ISafetyTypeRepository _safetyTypeRepository;
 
-    public SnapshotBulletinController(ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, ISystemDicDataCacheManager systemDicDataCacheManager, ISystemOrganizeRepository organizeRepository, ISnapshotBulletinApplication bulletinApplication)
+    public SnapshotBulletinController(ISnapshotBulletinRepository bulletinRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISystemOrganizeRepository organizeRepository, ISnapshotBulletinApplication bulletinApplication, ISafetyTypeRepository safetyTypeRepository)
     {
         _bulletinRepository = bulletinRepository;
-        _sessionContext = sessionContext;
         _systemDicDataCacheManager = systemDicDataCacheManager;
         _organizeRepository = organizeRepository;
         _bulletinApplication = bulletinApplication;
+        _safetyTypeRepository = safetyTypeRepository;
     }
 
     #region 公告
@@ -91,7 +92,6 @@ public class SnapshotBulletinController : BaseController
         await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted);
     }
 
-
     /// <summary>
     /// 公告审核
     /// </summary>
@@ -99,37 +99,7 @@ public class SnapshotBulletinController : BaseController
     /// <returns></returns>
     [HttpPost("bulletin/examine")]
     public async Task ExamineBulletin([FromBody] ExamineBulletinDto dto)
-    {
-        var bulletin = await _bulletinRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
-        if (bulletin == null)
-            throw UserFriendlyException.SameMessage("无效数据");
-
-        if (bulletin.BulletinState != EBulletinState.InReview)
-            throw UserFriendlyException.SameMessage("当前状态不能审核");
-
-        if (dto.IsPass)
-        {
-            bulletin.BulletinState = Share.Enums.Article.EBulletinState.ReviewPass;
-            bulletin.BulletinTime = DateTime.Now;
-            bulletin.ExaminOpinion = dto.Reason;
-            bulletin.ExaminTime = DateTime.Now;
-            bulletin.ExaminManId = _sessionContext.RequiredUserId;
-            await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted);
-            var publishBulletin = bulletin.Adapt<PublishBulletinDto>();
-
-            //await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlinePushBulletin, publishBulletin, cancellationToken: HttpContext.RequestAborted);
-
-            //todo await _bulletinService.PushBulletin(publishBulletin, HttpContext.RequestAborted);
-        }
-        else
-        {
-            bulletin.ExaminOpinion = dto.Reason;
-            bulletin.ExaminTime = DateTime.Now;
-            bulletin.ExaminManId = _sessionContext.RequiredUserId;
-            bulletin.BulletinState = Share.Enums.Article.EBulletinState.ReviewNoPass;
-            await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted);
-        }
-    }
+        => await _bulletinApplication.ExamineBulletinAsync(dto, HttpContext.RequestAborted);
 
     /// <summary>
     /// 提交公告
@@ -138,18 +108,7 @@ public class SnapshotBulletinController : BaseController
     /// <returns></returns>
     [HttpGet("bulletin/commit")]
     public async Task CommitBulletin(string id)
-    {
-        var bulletin = await _bulletinRepository.GetAsync(id, HttpContext.RequestAborted);
-        if (bulletin == null)
-            throw UserFriendlyException.SameMessage("无效数据");
-
-        if (bulletin.BulletinState != EBulletinState.Draft && bulletin.BulletinState != EBulletinState.ReviewNoPass)
-            throw UserFriendlyException.SameMessage("当前状态不能提交");
-
-        bulletin.BulletinState = EBulletinState.InReview;
-        bulletin.CommitTime = DateTime.Now;
-        await _bulletinRepository.UpdateAsync(bulletin, HttpContext.RequestAborted);
-    }
+        => await _bulletinApplication.CommitBulletinAsync(id, HttpContext.RequestAborted);
 
     /// <summary>
     /// 修改公告
@@ -195,13 +154,7 @@ public class SnapshotBulletinController : BaseController
     /// <returns></returns>
     [HttpPost("bulletin/add")]
     public async Task AddBulletin([FromBody] AddSnapshotBulletinInDto dto)
-    {
-        var model = dto.Adapt<SnapshotBulletin>();
-        model.BulletinState = Share.Enums.Article.EBulletinState.Draft;
-        model.ReadedNum = 0;
-        if (model.BulletinTime.HasValue == false) model.BulletinTime = DateTime.Now;
-        await _bulletinRepository.AddAsync(model, HttpContext.RequestAborted);
-    }
+        => await _bulletinApplication.AddBulletinAsync(dto, HttpContext.RequestAborted);
 
     /// <summary>
     /// 列表页面基础数据
@@ -226,11 +179,15 @@ public class SnapshotBulletinController : BaseController
     [HttpGet("bulletin/addbasedata")]
     public async Task<object> BulletinAddBaseData()
     {
+        var safetyTypes = await _safetyTypeRepository.Queryable()
+            .Select(m => new SystemDicDataOutDto { Id =  m.Id, DicDataName = m.Name , DicDataValue = m.Id})
+            .ToListAsync(HttpContext.RequestAborted);
         var rsp = new
         {
             BulletinType = _systemDicDataCacheManager.SnapshotBulletinType,
             BulletinSource = _systemDicDataCacheManager.SnapshotBulletinSource,
             OrgsOptions = await _organizeRepository.GetOrgJson(),
+            SafetyTypes = safetyTypes
         };
         return rsp;
     }

+ 10 - 0
src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs

@@ -373,6 +373,16 @@ public class SnapshotController : BaseController
             await _snapshotApplication.PostOrderGuiderSystemAsync(orderId, HttpContext.RequestAborted);
         }
     }
+
+    /// <summary>
+    /// 获取消息
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("notification")]
+    public async Task<IList<GetNotifyOutDto>> GetNotificationAsync([FromQuery] GetNotifyInDto dto)
+        => await _snapshotApplication.GetNotificationAsync(dto, HttpContext.RequestAborted);
+
     #region 积分
     /// <summary>
     /// 积分榜

+ 9 - 0
src/Hotline.Api/Controllers/Snapshot/SnapshotUserController.cs

@@ -62,4 +62,13 @@ public class SnapshotUserController : BaseController
     [HttpDelete("citizen_relation")]
     public async Task DeleteCitizenRelationSafetyType([FromBody] DeleteCitizenRelationSafetyTypeInDto dto)
         => await _snapshotUserApplication.DeleteCitizenRelationSafetyAsync(dto);
+
+    /// <summary>
+    /// 搜索安全志愿者
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("citizen")]
+    public async Task<PagedDto<GetThirdCitizenOutDto>> GetThirdCitizenAsync([FromQuery] GetThirdCitizenInDto dto)
+        => (await _snapshotUserApplication.GetThirdCitizenAsync(dto).ToPagedListAsync(dto)).ToPaged();
 }

+ 24 - 2
src/Hotline.Application/Snapshot/BiSnapshotApplication.cs

@@ -5,6 +5,7 @@ using Hotline.Settings;
 using Hotline.Settings.Hotspots;
 using Hotline.Share.Attributes;
 using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Snapshot;
@@ -36,8 +37,9 @@ public class BiSnapshotApplication : IBiSnapshotApplication, IScopeDependency
     private readonly ICommunityInfoRepository _communityInfoRepository;
     private readonly IRepository<SystemArea> _systemAreaRepository;
     private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
+    private readonly ISnapshotPointsRecordRepository _snapshotPointsRecordRepository;
 
-    public BiSnapshotApplication(IOrderSnapshotRepository orderSnapshotRepository, IRedPackRecordRepository redPackRecordRepository, IIndustryRepository industryRepository, IIndustryCaseRepository industryCaseRepository, IRedPackAuditRepository redPackAuditRepository, IRepository<Hotspot> hotspotTypeRepository, ISessionContext sessionContext, IOrderRepository orderRepository, ICommunityInfoRepository communityInfoRepository, IRepository<SystemArea> systemAreaRepository, IOptionsSnapshot<AppConfiguration> appOptions)
+    public BiSnapshotApplication(IOrderSnapshotRepository orderSnapshotRepository, IRedPackRecordRepository redPackRecordRepository, IIndustryRepository industryRepository, IIndustryCaseRepository industryCaseRepository, IRedPackAuditRepository redPackAuditRepository, IRepository<Hotspot> hotspotTypeRepository, ISessionContext sessionContext, IOrderRepository orderRepository, ICommunityInfoRepository communityInfoRepository, IRepository<SystemArea> systemAreaRepository, IOptionsSnapshot<AppConfiguration> appOptions, ISnapshotPointsRecordRepository snapshotPointsRecordRepository)
     {
         _orderSnapshotRepository = orderSnapshotRepository;
         _redPackRecordRepository = redPackRecordRepository;
@@ -50,6 +52,7 @@ public class BiSnapshotApplication : IBiSnapshotApplication, IScopeDependency
         _communityInfoRepository = communityInfoRepository;
         _systemAreaRepository = systemAreaRepository;
         _appOptions = appOptions;
+        _snapshotPointsRecordRepository = snapshotPointsRecordRepository;
     }
 
     public ISugarQueryable<HotspotStatisticsOutDto> GetHotspotStatistics(HotspotStatisticsInDto dto)
@@ -734,7 +737,7 @@ public class BiSnapshotApplication : IBiSnapshotApplication, IScopeDependency
             .LeftJoin<OrderSendBackAudit>((snapshot, order, back) => snapshot.Id == back.OrderId && back.State == ESendBackAuditState.End)
             .LeftJoin<OrderVisit>((snapshot, order, back, visit) => snapshot.Id == visit.OrderId && visit.VisitState == EVisitState.Visited)
             .LeftJoin<OrderSecondaryHandling>((snapshot, order, back, visit, second) => snapshot.Id == second.OrderId && second.State == ESecondaryHandlingState.End)
-            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime 
+            .Where((snapshot, order) => snapshot.CreationTime >= dto.StartTime && snapshot.CreationTime <= dto.EndTime
             && order.ActualHandleOrgCode != null && order.ActualHandleOrgCode != "001")
             .GroupBy((snapshot, order) => new
             {
@@ -972,4 +975,23 @@ public class BiSnapshotApplication : IBiSnapshotApplication, IScopeDependency
             .Select((snapshot, order) => new IndustryStatisticsDetailsOutDto(), true);
         return query;
     }
+
+    public ISugarQueryable<SnapshotCountyPointsStatisticsOutDto> GetAreaPointsStatistics(SnapshotCountyPointsStatisticsInDto dto)
+    {
+        var query = _snapshotPointsRecordRepository.Queryable(includeDeleted: true)
+            .LeftJoin<Order>((points, order) => points.OrderId == order.Id)
+            .Where((points, order) => order.CreationTime >= dto.StartTime && order.CreationTime <= dto.EndTime && order.County != "" && order.County != null)
+            .GroupBy((points, order) => order.County)
+            .Select((points, order) => new SnapshotCountyPointsStatisticsOutDto
+            {
+                CountyName = order.County,
+                Points = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.In, points.Points, 0)),
+                ExchangePoints = SqlFunc.AggregateSum(SqlFunc.IIF(points.Source == EPointsSource.Exchange, points.Points, 0)),
+            });
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        return query;
+    }
+
 }

+ 7 - 0
src/Hotline.Application/Snapshot/Contracts/IBiSnapshotApplication.cs

@@ -111,4 +111,11 @@ public interface IBiSnapshotApplication
     /// <param name="dto"></param>
     /// <returns></returns>
     ISugarQueryable<IndustryStatisticsDetailsOutDto> GetIndustryStatisticsDetails(IndustryStatisticsDetailsInDto dto);
+
+    /// <summary>
+    /// 区域积分统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<SnapshotCountyPointsStatisticsOutDto> GetAreaPointsStatistics(SnapshotCountyPointsStatisticsInDto dto);
 }

+ 11 - 0
src/Hotline.Application/Snapshot/Contracts/INotificationApplication.cs

@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Snapshot.Contracts;
+
+public interface INotificationApplication
+{
+}

+ 2 - 0
src/Hotline.Application/Snapshot/Contracts/ISnapshotApplication.cs

@@ -233,4 +233,6 @@ public interface ISnapshotApplication
     /// <param name="requestAborted"></param>
     /// <returns></returns>
     Task<int> GetPointsTotalAsync(PointItemsInDto dto, CancellationToken requestAborted);
+
+    Task<IList<GetNotifyOutDto>> GetNotificationAsync(GetNotifyInDto dto, CancellationToken requestAborted);
 }

+ 26 - 1
src/Hotline.Application/Snapshot/Contracts/ISnapshotBulletinApplication.cs

@@ -1,4 +1,5 @@
-using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Dtos.Article;
+using Hotline.Share.Dtos.Snapshot;
 using SqlSugar;
 using System;
 using System.Collections.Generic;
@@ -9,6 +10,29 @@ using System.Threading.Tasks;
 namespace Hotline.Application.Snapshot.Contracts;
 public interface ISnapshotBulletinApplication
 {
+    /// <summary>
+    /// 新增公告
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    Task<string> AddBulletinAsync(AddSnapshotBulletinInDto dto, CancellationToken requestAborted);
+
+    /// <summary>
+    /// 审核公告
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    Task ExamineBulletinAsync(ExamineBulletinDto dto, CancellationToken requestAborted);
+
+    /// <summary>
+    /// 发送通知公告
+    /// </summary>
+    /// <param name="bullutionId"></param>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    Task NotifyUserAsync(string bullutionId, CancellationToken token);
 
     /// <summary>
     /// 处理通知公告图片附件路径
@@ -17,4 +41,5 @@ public interface ISnapshotBulletinApplication
     /// <returns></returns>
     string GetSiteUrls(string sHtmlText);
     ISugarQueryable<SnapshotBulletinItemsOutDto> QueryBulletinItems(SnapshotBulletinItemsInDto dto);
+    Task CommitBulletinAsync(string id, CancellationToken requestAborted);
 }

+ 7 - 0
src/Hotline.Application/Snapshot/Contracts/ISnapshotUserApplication.cs

@@ -21,4 +21,11 @@ public interface ISnapshotUserApplication
     /// <param name="dto"></param>
     /// <returns></returns>
     Task DeleteCitizenRelationSafetyAsync(DeleteCitizenRelationSafetyTypeInDto dto);
+
+    /// <summary>
+    /// 获取第三方市民列表
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    ISugarQueryable<GetThirdCitizenOutDto> GetThirdCitizenAsync(GetThirdCitizenInDto dto);
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs


+ 12 - 0
src/Hotline.Application/Snapshot/NotificationApplication.cs

@@ -0,0 +1,12 @@
+using Hotline.Application.Snapshot.Contracts;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Snapshot;
+
+public class NotificationApplication : INotificationApplication
+{
+}

+ 15 - 1
src/Hotline.Application/Snapshot/Notifications/SnapshotHandler.cs

@@ -38,10 +38,12 @@ namespace Hotline.Application.Snapshot.Notifications;
 public class SnapshotHandler : ICapSubscribe, IScopeDependency
 {
     private readonly ISnapshotApplication _snapshotApplication;
+    private readonly ISnapshotBulletinApplication _snapshotBulletinApplication;
 
-    public SnapshotHandler(ISnapshotApplication snapshotApplication)
+    public SnapshotHandler(ISnapshotApplication snapshotApplication, ISnapshotBulletinApplication snapshotBulletinApplication)
     {
         _snapshotApplication = snapshotApplication;
+        _snapshotBulletinApplication = snapshotBulletinApplication;
     }
 
     /// <summary>
@@ -55,6 +57,18 @@ public class SnapshotHandler : ICapSubscribe, IScopeDependency
     {
         await _snapshotApplication.GuiderSystemReplyDelayAsync(message.OrderId, cancellationToken);
     }
+
+    /// <summary>
+    /// 通知公告审核通过
+    /// </summary>
+    /// <param name="bulletinId"></param>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    [CapSubscribe(EventNames.BulletinIsPass, Group = "snapshot")]
+    public async Task BulletinIsPassHandler(string bulletinId, CancellationToken token)
+    {
+        await _snapshotBulletinApplication.NotifyUserAsync(bulletinId, token);
+    }
 }
 
 /// <summary>

+ 17 - 1
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -87,8 +87,9 @@ public abstract class SnapshotApplicationBase
     private readonly ICitizenRepository _citizenRepository;
     private readonly ISnapshotPointsRecordRepository _pointsRecordRepository;
     private readonly IOptionsSnapshot<MqConfiguration> _mqConfiguration;
+    private readonly INotificationReceiverRepository _notificationReceiverRepository;
 
-    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IIndustryRepository industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRedPackRecordRepository redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository, IPractitionerRepository practitionerRepository, IRepository<SystemArea> systemAreaRepository, IVolunteerRepository volunteerRepository, IVolunteerReportRepository volunteerReportRepository, ISystemLogRepository systemLog, IGuiderSystemService guiderSystemService, ICapPublisher capPublisher, Publisher publisher, IFileDomainService fileDomainService, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IOrderVisitRepository orderVisitRepository, IOrderVisitDetailRepository orderVisitDetailRepository, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IInviteCodeRecordRepository inviteCodeRecordRepository, IInviteCodeRepository inviteCodeRepository, ICitizenRepository citizenRepository, ISnapshotPointsRecordRepository snapshotPointsRecordRepository, IOptionsSnapshot<MqConfiguration> mqConfiguration)
+    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IIndustryRepository industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRedPackRecordRepository redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository, IPractitionerRepository practitionerRepository, IRepository<SystemArea> systemAreaRepository, IVolunteerRepository volunteerRepository, IVolunteerReportRepository volunteerReportRepository, ISystemLogRepository systemLog, IGuiderSystemService guiderSystemService, ICapPublisher capPublisher, Publisher publisher, IFileDomainService fileDomainService, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IOrderVisitRepository orderVisitRepository, IOrderVisitDetailRepository orderVisitDetailRepository, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IInviteCodeRecordRepository inviteCodeRecordRepository, IInviteCodeRepository inviteCodeRepository, ICitizenRepository citizenRepository, ISnapshotPointsRecordRepository snapshotPointsRecordRepository, IOptionsSnapshot<MqConfiguration> mqConfiguration, INotificationReceiverRepository notificationReceiverRepository)
     {
         _thirdLoginService = thirdLoginService;
         _industryRepository = industryRepository;
@@ -123,6 +124,7 @@ public abstract class SnapshotApplicationBase
         _citizenRepository = citizenRepository;
         _pointsRecordRepository = snapshotPointsRecordRepository;
         _mqConfiguration = mqConfiguration;
+        _notificationReceiverRepository = notificationReceiverRepository;
     }
 
     #region 小程序
@@ -392,6 +394,20 @@ public abstract class SnapshotApplicationBase
             .SumAsync(m => m.Points);
     }
 
+    public async Task<IList<GetNotifyOutDto>> GetNotificationAsync(GetNotifyInDto dto, CancellationToken requestAborted)
+    {
+        var items = await _notificationReceiverRepository.Queryable()
+            .LeftJoin<Notification>((m , notify) => m.NotificationId == notify.Id)
+            .Where(m => m.ReceiverId == _sessionContext.UserId)
+            .Select((m, notify) => new GetNotifyOutDto 
+            {
+                NotificationId = m.NotificationId,
+                Title = notify.Title ,
+                CreationTime = m.CreationTime
+            }, true)
+            .ToFixedListAsync(dto, requestAborted);
+        return items;
+    }
 
     /// <summary>
     /// 获取工单详情

+ 109 - 2
src/Hotline.Application/Snapshot/SnapshotBulletinApplication.cs

@@ -1,9 +1,19 @@
-using Hotline.Application.Snapshot.Contracts;
+using DocumentFormat.OpenXml.Vml.Office;
+using DotNetCore.CAP;
+using Hotline.Application.Snapshot.Contracts;
 using Hotline.Caching.Interfaces;
+using Hotline.Orders;
 using Hotline.Settings;
 using Hotline.Share.Attributes;
+using Hotline.Share.Dtos.Article;
 using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Enums.Article;
+using Hotline.Share.Enums.Snapshot;
+using Hotline.Share.Tools;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Contracts;
 using Hotline.Snapshot.IRepository;
+using Mapster;
 using Microsoft.AspNetCore.Http;
 using SqlSugar;
 using System;
@@ -12,7 +22,9 @@ using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
+using XF.Domain.Authentications;
 using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Application.Snapshot;
 public class SnapshotBulletinApplication : ISnapshotBulletinApplication, IScopeDependency
@@ -20,11 +32,81 @@ public class SnapshotBulletinApplication : ISnapshotBulletinApplication, IScopeD
 
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly ISnapshotBulletinRepository _bulletinRepository;
+    private readonly INotificationDomainService _notificationDomainService;
+    private readonly ISessionContext _sessionContext;
+    private readonly ISafetyTypeRepository _safetyTypeRepository;
+    private readonly ICapPublisher _capPublisher;
 
-    public SnapshotBulletinApplication(ISystemSettingCacheManager systemSettingCacheManager, ISnapshotBulletinRepository bulletinRepository)
+    public SnapshotBulletinApplication(ISystemSettingCacheManager systemSettingCacheManager, ISnapshotBulletinRepository bulletinRepository, INotificationDomainService notificationDomainService, ISessionContext sessionContext, ISafetyTypeRepository safetyTypeRepository, ICapPublisher capPublisher)
     {
         _systemSettingCacheManager = systemSettingCacheManager;
         _bulletinRepository = bulletinRepository;
+        _notificationDomainService = notificationDomainService;
+        _sessionContext = sessionContext;
+        _safetyTypeRepository = safetyTypeRepository;
+        _capPublisher = capPublisher;
+    }
+
+    public async Task ExamineBulletinAsync(ExamineBulletinDto dto, CancellationToken token)
+    {
+        var bulletin = await _bulletinRepository.GetAsync(dto.Id, token)
+            ?? throw UserFriendlyException.SameMessage("无效数据");
+        if (bulletin.BulletinState != EBulletinState.InReview)
+            throw UserFriendlyException.SameMessage("当前状态不能审核");
+
+        if (dto.IsPass == false)
+        {
+            bulletin.ExaminOpinion = dto.Reason;
+            bulletin.ExaminTime = DateTime.Now;
+            bulletin.ExaminManId = _sessionContext.RequiredUserId;
+            bulletin.BulletinState = EBulletinState.ReviewNoPass;
+            await _bulletinRepository.UpdateAsync(bulletin, token);
+            return;
+        }
+
+        bulletin.BulletinState = EBulletinState.ReviewPass;
+        bulletin.BulletinTime = DateTime.Now;
+        bulletin.ExaminOpinion = dto.Reason;
+        bulletin.ExaminTime = DateTime.Now;
+        bulletin.ExaminManId = _sessionContext.RequiredUserId;
+        await _bulletinRepository.UpdateAsync(bulletin, token);
+
+        await _capPublisher.PublishAsync(Share.Mq.EventNames.BulletinIsPass, bulletin.Id, cancellationToken: token);
+    }
+
+    /// <summary>
+    /// 执行发送通知公告
+    /// </summary>
+    /// <param name="bullutionId"></param>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    public async Task NotifyUserAsync(string bullutionId, CancellationToken token)
+    {
+        await _bulletinRepository.GetAsync(bullutionId, token)
+            .Then(async bulletion =>
+            {
+                if (bulletion!.IsSnapshot == false) return;
+                if (bulletion!.SafetyTypeId!.IsNullOrEmpty()) return;
+                foreach (var safetyTypeId in bulletion!.SafetyTypeId!)
+                {
+                    await _safetyTypeRepository.Queryable()
+                        .LeftJoin<CitizenRelationSafetyType>((safety, relation) => safety.Id == relation.SafetyTypeId)
+                        .LeftJoin<Citizen>((safety, relation, citizen) => relation.CitizenId == citizen.Id)
+                        .Where((safety, relation, citizen) => safety.Id == safetyTypeId)
+                        .Select((safety, relation, citizen) => relation.CitizenId)
+                        .ToListAsync(token)
+                        .Then(async citizenIds =>
+                        {
+                            var inDto = bulletion.Adapt<AddNotifyInDto>();
+                            inDto.UserIds = citizenIds;
+                            if (bulletion.VideoPath.NotNullOrEmpty())
+                            {
+                                inDto.NotifyType = ENotificationType.Video;
+                            }
+                            await _notificationDomainService.AddNotifyAsync(inDto, token);
+                        });
+                }
+            });
     }
 
     /// <summary>
@@ -88,4 +170,29 @@ public class SnapshotBulletinApplication : ISnapshotBulletinApplication, IScopeD
             .Select<SnapshotBulletinItemsOutDto>();
         return query;
     }
+
+
+    public async Task CommitBulletinAsync(string id, CancellationToken requestAborted)
+    {
+        var bulletin = await _bulletinRepository.GetAsync(id, requestAborted);
+        if (bulletin == null)
+            throw UserFriendlyException.SameMessage("无效数据");
+
+        if (bulletin.BulletinState != EBulletinState.Draft && bulletin.BulletinState != EBulletinState.ReviewNoPass)
+            throw UserFriendlyException.SameMessage("当前状态不能提交");
+
+        bulletin.BulletinState = EBulletinState.InReview;
+        bulletin.CommitTime = DateTime.Now;
+        await _bulletinRepository.UpdateAsync(bulletin, requestAborted);
+    }
+
+
+    public async Task<string> AddBulletinAsync(AddSnapshotBulletinInDto dto, CancellationToken token)
+    {
+        var model = dto.Adapt<SnapshotBulletin>();
+        model.BulletinState = EBulletinState.Draft;
+        model.ReadedNum = 0;
+        if (model.BulletinTime.HasValue == false) model.BulletinTime = DateTime.Now;
+        return await _bulletinRepository.AddAsync(model, token);
+    }
 }

+ 22 - 1
src/Hotline.Application/Snapshot/SnapshotPointsApplication.cs

@@ -19,18 +19,23 @@ public class SnapshotPointsApplication : ISnapshotPointsApplication, IScopeDepen
 {
     private readonly ISnapshotPointsRecordRepository _snapshotPointsRecordRepository;
     private readonly ICitizenRepository _citizenRepository;
+    private readonly ISafetyTypeRepository _safetyTypeRepository;
 
-    public SnapshotPointsApplication(ISnapshotPointsRecordRepository snapshotPointsRecordRepository, ICitizenRepository citizenRepository)
+    public SnapshotPointsApplication(ISnapshotPointsRecordRepository snapshotPointsRecordRepository, ICitizenRepository citizenRepository, ISafetyTypeRepository safetyTypeRepository)
     {
         _snapshotPointsRecordRepository = snapshotPointsRecordRepository;
         _citizenRepository = citizenRepository;
+        _safetyTypeRepository = safetyTypeRepository;
     }
 
     public ISugarQueryable<PointsItemsOutDto> GetPointsItems(PointsItemsInDto dto)
     {
         var query = _snapshotPointsRecordRepository.Queryable()
             .LeftJoin<Citizen>((points, citizen) => points.UserId == citizen.Id)
+            .LeftJoin<Order>((points, citizen, order) => order.Id == points.OrderId)
             .WhereIF(dto.PhoneNumber.NotNullOrEmpty(), (points, citizen) => citizen.PhoneNumber.Contains(dto.PhoneNumber!))
+            .WhereIF(dto.County.NotNullOrEmpty(), (points, citizen, order) => order.County == dto.County)
+            .WhereIF(dto.StartTime != null && dto.EndTime != null, (points, citizen) => points.CreationTime >= dto.StartTime && points.CreationTime <= dto.EndTime)
             .Where((points, citizen) => points.CreationTime >= dto.StartTime && points.CreationTime <= dto.EndTime)
             .GroupBy((points, citizen) => new { points.UserId, citizen.IsSecurityMax, citizen.Name, citizen.PhoneNumber })
             .Select((points, citizen) => new PointsItemsOutDto
@@ -55,9 +60,25 @@ public class SnapshotPointsApplication : ISnapshotPointsApplication, IScopeDepen
 
     public async Task UpdateIsSecurityMaxAsync(UpdateIsSecurityMaxAsync dto, CancellationToken token)
     {
+        // TODO 紧急
         await _citizenRepository.Updateable()
             .SetColumns(citizen => citizen.IsSecurityMax, dto.IsSecurityMax)
             .Where(citizen => citizen.Id == dto.UserId)
             .ExecuteCommandAsync(token);
+        await _citizenRepository.Queryable()
+            .Includes(m => m.SafetyTypes)
+            .Where(m => m.Id == dto.UserId)
+            .FirstAsync(token)
+            .Then(async citizen =>
+            {
+                await _safetyTypeRepository.Queryable()
+                    .Where(m => m.Name == "安全卫士")
+                    .Select(m => m.Id)
+                    .FirstAsync(token)
+                    .Then(async id =>
+                    {
+                        //citizen.
+                    });
+            });
     }
 }

+ 14 - 0
src/Hotline.Application/Snapshot/SnapshotUserApplication.cs

@@ -10,6 +10,7 @@ using Hotline.Snapshot.IRepository;
 using Hotline.ThirdAccountDomainServices;
 using Hotline.Tools;
 using Mapster;
+using NPOI.POIFS.Properties;
 using SqlSugar;
 using System;
 using System.Collections.Generic;
@@ -88,4 +89,17 @@ public class SnapshotUserApplication : ISnapshotUserApplication, IScopeDependenc
                 .ExecuteCommand();
         }
     }
+
+    public ISugarQueryable<GetThirdCitizenOutDto> GetThirdCitizenAsync(GetThirdCitizenInDto dto)
+    {
+        var query = _citizenRepository.Queryable(includeDeleted: true)
+            .LeftJoin<ThirdAccount>((citizen, third) => citizen.Id == third.ExternalId)
+            .WhereIF(dto.PhoneNumber.NotNullOrEmpty(), (citizen, third) => citizen.PhoneNumber.Contains(dto.PhoneNumber))
+            .Select((citizen, third) => new GetThirdCitizenOutDto(), true);
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+
+        return query;
+    }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs


+ 19 - 0
src/Hotline.Repository.SqlSugar/Snapshot/NotificationReceiverRepository.cs

@@ -0,0 +1,19 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Snapshot;
+using Hotline.Snapshot.IRepository;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Snapshot;
+
+public class NotificationReceiverRepository : BaseRepository<NotificationReceiver>, INotificationReceiverRepository, IScopeDependency
+{
+    public NotificationReceiverRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
+    {
+    }
+}

+ 19 - 0
src/Hotline.Repository.SqlSugar/Snapshot/NotificationRepository.cs

@@ -0,0 +1,19 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Snapshot;
+using Hotline.Snapshot.IRepository;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Snapshot;
+
+public class NotificationRepository : BaseRepository<Notification>, INotificationRepository, IScopeDependency
+{
+    public NotificationRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
+    {
+    }
+}

+ 62 - 0
src/Hotline.Share/Dtos/Snapshot/NotifyDto.cs

@@ -0,0 +1,62 @@
+using Hotline.Share.Enums.Snapshot;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Snapshot;
+
+public class NotifyDto
+{
+}
+
+public class AddNotifyInDto
+{
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 类型
+    /// </summary>
+    public ENotificationType NotifyType { get; set; }
+
+    /// <summary>
+    /// 用户
+    /// </summary>
+    public IList<string> UserIds { get; set; }
+}
+
+public class GetNotifyInDto : QueryFixedDto
+{
+    /// <summary>
+    /// 消息类型
+    /// </summary>
+    public ENotificationType NotifyType { get; set; }
+}
+
+public class GetNotifyOutDto
+{
+    /// <summary>
+    /// 通知Id
+    /// </summary>
+    public string NotificationId { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 创建时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+}

+ 9 - 0
src/Hotline.Share/Dtos/Snapshot/PointsDto.cs

@@ -38,6 +38,15 @@ public record PointsItemsInDto : PagedKeywordRequest
     /// 联系方式
     /// </summary>
     public string? PhoneNumber { get; set; }
+
+    /// <summary>
+    /// 区域名称
+    /// </summary>
+    public string? County { get; set; }
+
+    public DateTime? StartTime { get; set; }
+
+    public DateTime? EndTime { get; set; }
 }
 
 public class PointsItemsOutDto

+ 6 - 1
src/Hotline.Share/Dtos/Snapshot/SnapshotBulletinDto.cs

@@ -263,7 +263,7 @@ public class AddSnapshotBulletinInDto
     /// <summary>
     /// 志愿者类型Id
     /// </summary>
-    public string? SafetyTypeId { get; set; }
+    public IList<string>? SafetyTypeId { get; set; }
 
     /// <summary>
     /// 时间
@@ -279,4 +279,9 @@ public class AddSnapshotBulletinInDto
     /// 视频地址
     /// </summary>
     public string? VideoPath { get; set; }
+
+    /// <summary>
+    /// 视频封面
+    /// </summary>
+    public string? VideoCoverImgUrl { get; set; }
 }

+ 26 - 0
src/Hotline.Share/Dtos/Snapshot/SnapshotUserInfoDto.cs

@@ -124,3 +124,29 @@ public class CitizenIdRelationSafetyTypeId
     /// </summary>
     public string SafetyTypeId { get; set; }
 }
+
+public record GetThirdCitizenInDto : PagedRequest
+{
+    /// <summary>
+    /// 电话号码
+    /// </summary>
+    public string? PhoneNumber { get; set; }
+}
+
+public class GetThirdCitizenOutDto
+{
+    /// <summary>
+    /// Id
+    /// </summary>
+    public string CitizenId { get; set; }
+
+    /// <summary>
+    /// Name
+    /// </summary>
+    public string Name { get; set; }
+
+    /// <summary>
+    /// 电话
+    /// </summary>
+    public string PhoneNumber { get; set; }
+}

+ 28 - 0
src/Hotline.Share/Dtos/Snapshot/StatisticsDto.cs

@@ -3113,3 +3113,31 @@ public class IndustryStatisticsDetailsOutDto
     public string FileOpinion { get; set; }
 
 }
+
+public class SnapshotCountyPointsStatisticsInDto
+{
+    [Required]
+    public DateTime StartTime { get; set; }
+
+    [Required]
+    public DateTime EndTime { get; set; }
+
+}
+
+public class SnapshotCountyPointsStatisticsOutDto
+{
+    /// <summary>
+    /// 区域名称
+    /// </summary>
+    public string CountyName { get; set; }
+
+    /// <summary>
+    /// 积分
+    /// </summary>
+    public long Points { get; set; }
+
+    /// <summary>
+    /// 兑换积分
+    /// </summary>
+    public long ExchangePoints { get; set; }
+}

+ 17 - 0
src/Hotline.Share/Enums/Snapshot/ENotificationType.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Enums.Snapshot;
+
+public enum ENotificationType
+{
+    [Description("消息")]
+    Message = 0,
+
+    [Description("视频")]
+    Video = 1
+}

+ 5 - 0
src/Hotline.Share/Mq/EventNames.Snapshot.cs

@@ -11,4 +11,9 @@ public partial class  EventNames
     /// 延迟检查网格员系统是否回复
     /// </summary>
     public const string GuiderSystemReplyDelay = "snapshot.guider.reply.delay";
+
+    /// <summary>
+    /// 通知公告审核通过
+    /// </summary>
+    public const string BulletinIsPass = "snapshot.bulletin.pass";
 }

+ 5 - 0
src/Hotline.Share/Tools/DateTimeExtensions.cs

@@ -35,6 +35,11 @@ public static class DateTimeExtensions
         return dateTime.ToString("yyyy-MM-dd HH:mm:ss");
     }
 
+    public static string ToShortDateTimeString(this DateTime dateTime)
+    {
+        return dateTime.ToString("yyyy-MM-dd");
+    }
+
     public static long ToUnixTimeMilliseconds(this DateTime value)
     {
         return new DateTimeOffset(value).ToUnixTimeMilliseconds();

+ 13 - 12
src/Hotline/Orders/Order.cs

@@ -963,16 +963,16 @@ namespace Hotline.Orders
         [SugarColumn(ColumnDescription = "重办次数")]
         public int? ReTransactNum { get; set; }
 
-		/// <summary>
-		/// 回访重办次数
-		/// </summary>
-		[SugarColumn(ColumnDescription = "重办次数")]
-		public int? VisitReTransactNum { get; set; }
-
-		/// <summary>
-		/// 派单退回次数
-		/// </summary>
-		[SugarColumn(ColumnDescription = "派单退回次数")]
+        /// <summary>
+        /// 回访重办次数
+        /// </summary>
+        [SugarColumn(ColumnDescription = "重办次数")]
+        public int? VisitReTransactNum { get; set; }
+
+        /// <summary>
+        /// 派单退回次数
+        /// </summary>
+        [SugarColumn(ColumnDescription = "派单退回次数")]
         public int? SendBackNum { get; set; }
 
         /// <summary>
@@ -1180,7 +1180,7 @@ namespace Hotline.Orders
         /// <summary>
         /// 预警信息
         /// </summary>
-        [Navigate(NavigateType.OneToOne, nameof(Id),nameof(OrderEarlyWarning.OrderId))]
+        [Navigate(NavigateType.OneToOne, nameof(Id), nameof(OrderEarlyWarning.OrderId))]
         public OrderEarlyWarning OrderEarlyWarning { get; set; }
 
         /// <summary>
@@ -1367,7 +1367,8 @@ namespace Hotline.Orders
             FirstVisitResult = result;
 
             //Progress = EProgress.Visited;
-            Status = EOrderStatus.Visited;
+            if (Status >= EOrderStatus.Filed)
+                Status = EOrderStatus.Visited;
         }
 
         public void CenterToOrg(string timelimit, int timelimitCount, ETimeType timilimitUnit,

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

@@ -781,6 +781,11 @@ namespace Hotline.Settings
         /// </summary>
         public const string ScreenStatisticalNodes = "ScreenStatisticalNodes";
 
+        /// <summary>
+        /// 延期统计查询节点
+        /// </summary>
+        public const string DelayStatisticalNodes = "DelayStatisticalNodes";
+
         /// <summary>
         /// 小休审批人角色
         /// </summary>

+ 19 - 0
src/Hotline/Snapshot/Contracts/INotificationDomainService.cs

@@ -0,0 +1,19 @@
+using Hotline.Share.Dtos.Snapshot;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Snapshot.Contracts;
+
+public interface INotificationDomainService
+{
+    /// <summary>
+    /// 添加通知
+    /// </summary>
+    /// <param name="inDto"></param>
+    /// <param name="token"></param>
+    /// <returns></returns>
+    Task AddNotifyAsync(AddNotifyInDto inDto, CancellationToken token);
+}

+ 0 - 0
src/Hotline/Snapshot/IRepository/IndustryLogRepository.cs → src/Hotline/Snapshot/IRepository/IIndustryLogRepository.cs


+ 12 - 0
src/Hotline/Snapshot/IRepository/INotificationReceiverRepository.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot.IRepository;
+
+public interface INotificationReceiverRepository : IRepository<NotificationReceiver>
+{
+}

+ 12 - 0
src/Hotline/Snapshot/IRepository/INotificationRepository.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot.IRepository;
+
+public interface INotificationRepository : IRepository<Notification>
+{
+}

+ 27 - 0
src/Hotline/Snapshot/Notification.cs

@@ -0,0 +1,27 @@
+using Hotline.Share.Enums.Snapshot;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot;
+
+public class Notification : CreationSoftDeleteEntity
+{
+    /// <summary>
+    /// 标题
+    /// </summary>
+    public string Title { get; set; }
+
+    /// <summary>
+    /// 内容
+    /// </summary>
+    public string Content { get; set; }
+
+    /// <summary>
+    /// 类型
+    /// </summary>
+    public ENotificationType NotifyType { get; set; }
+}

+ 27 - 0
src/Hotline/Snapshot/NotificationReceiver.cs

@@ -0,0 +1,27 @@
+using SqlSugar;
+using System.ComponentModel;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot;
+
+[Description("通知关联消息")]
+public class NotificationReceiver : CreationSoftDeleteEntity
+{
+    /// <summary>
+    /// 通知ID
+    /// </summary>
+    [SugarColumn(ColumnDescription = "通知Id")]
+    public string NotificationId { get; set; }
+
+    /// <summary>
+    /// 接收人ID
+    /// </summary>
+    [SugarColumn(ColumnDescription = "接收人ID")]
+    public string ReceiverId { get; set; }
+
+    /// <summary>
+    /// 是否已读
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否已读")]
+    public bool IsRead { get; set; }
+}

+ 40 - 0
src/Hotline/Snapshot/Services/NotificationDomainService.cs

@@ -0,0 +1,40 @@
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Snapshot.Contracts;
+using Hotline.Snapshot.IRepository;
+using Mapster;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Snapshot.Services;
+
+public class NotificationDomainService : INotificationDomainService, IScopeDependency
+{
+    private readonly INotificationRepository _notificationRepository;
+    private readonly INotificationReceiverRepository _notificationReceiverRepository;
+
+    public NotificationDomainService(INotificationRepository notificationRepository, INotificationReceiverRepository notificationReceiverRepository)
+    {
+        _notificationRepository = notificationRepository;
+        _notificationReceiverRepository = notificationReceiverRepository;
+    }
+
+    public async Task AddNotifyAsync(AddNotifyInDto inDto, CancellationToken token)
+    {
+        var entity = inDto.Adapt<Notification>();
+        var id = await _notificationRepository.AddAsync(entity, token);
+        var items = new List<NotificationReceiver>();
+        foreach (var userId in inDto.UserIds)
+        {
+            items.Add(new NotificationReceiver { 
+                NotificationId = id,
+                ReceiverId = userId,
+                IsRead = false
+            });
+        }
+        await _notificationReceiverRepository.AddRangeAsync(items, token);
+    }
+}

+ 19 - 0
src/Hotline/Snapshot/SnapshotBulletin.cs

@@ -175,5 +175,24 @@ public class SnapshotBulletin : CreationEntity
     {
         ReadedNum++;
     }
+
+    /// <summary>
+    /// 是否随手拍
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否随手拍")]
+    public bool? IsSnapshot { get; set; }
+
+    /// <summary>
+    /// 志愿者类型Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "志愿者类型Id", ColumnDataType = "json", IsJson = true)]
+    public List<string>? SafetyTypeId { get; set; }
+
+    /// <summary>
+    /// 视频封面
+    /// </summary>
+    [SugarColumn(ColumnDescription = "视频封面")]
+    public string? VideoCoverImgUrl { get; set; }
+
 }
 

+ 1 - 1
src/XF.Domain.Repository/Entity.cs

@@ -79,7 +79,7 @@ public abstract class SoftDeleteEntity : Entity, IHasDeletionTime, ISoftDelete
     [SugarColumn(ColumnDescription = "删除时间")]
     public DateTime? DeletionTime { get; set; }
 
-    [SugarColumn(ColumnDescription = "是否删除")]
+    [SugarColumn(ColumnDescription = "是否删除", DefaultValue = "f")]
     public bool IsDeleted { get; set; }
 
     public void SoftDelete()

+ 9 - 0
test/Hotline.Tests/Application/BiSnapshotApplicationTest.cs

@@ -13,6 +13,7 @@ using Mapster;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using SqlSugar;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -110,6 +111,14 @@ public class BiSnapshotApplicationTest : TestBase
 
         var e = _biSnapshotApplication.GetIndustryStatistics(inDto.Adapt<IndustryStatisticsInDto>());
         e.ShouldNotBeNull();
+
+        var areaPointsInDto = new SnapshotCountyPointsStatisticsInDto
+        {
+            StartTime = DateTime.Now.AddDays(-30),
+            EndTime = DateTime.Now,
+        };
+        var areaPointsOutDto = _biSnapshotApplication.GetAreaPointsStatistics(areaPointsInDto).ToList();
+        areaPointsOutDto.ShouldNotBeNull();
     }
 
     [Fact]

+ 91 - 0
test/Hotline.Tests/Application/SnapshotBulletionApplicationTest.cs

@@ -0,0 +1,91 @@
+using Hotline.Api.Controllers;
+using Hotline.Application.Snapshot.Contracts;
+using Hotline.Caching.Interfaces;
+using Hotline.Identity.Accounts;
+using Hotline.Identity.Roles;
+using Hotline.Repository.SqlSugar.Snapshot;
+using Hotline.Settings;
+using Hotline.Share.Dtos.Article;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Tools;
+using Hotline.Snapshot.IRepository;
+using Hotline.ThirdAccountDomainServices;
+using Hotline.ThirdAccountDomainServices.Interfaces;
+using Hotline.Users;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Authentications;
+using XF.Domain.Cache;
+using XF.Domain.Repository;
+
+namespace Hotline.Tests.Application;
+
+public class SnapshotBulletionApplicationTest : TestBase
+{
+    private readonly ISnapshotBulletinApplication _snapshotBulletinApplication;
+    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
+    private readonly ISafetyTypeRepository _safetyTypeRepository;
+    private readonly ISnapshotUserApplication _snapshotUserApplication;
+    private readonly ISessionContext _sessionContext;
+    private readonly ISnapshotApplication _snapshotApplication;
+    private readonly ISnapshotBulletinRepository _bulletinRepository;
+
+    public SnapshotBulletionApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, IServiceProvider serviceProvider, ISnapshotBulletinApplication snapshotBulletinApplication, ISystemDicDataCacheManager systemDicDataCacheManager, ISafetyTypeRepository safetyTypeRepository, ISnapshotUserApplication snapshotUserApplication, ISessionContext sessionContext, ISnapshotApplication snapshotApplication, ISnapshotBulletinRepository bulletinRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData, thirdAccountDomainFactory, serviceProvider)
+    {
+        _snapshotBulletinApplication = snapshotBulletinApplication;
+        _systemDicDataCacheManager = systemDicDataCacheManager;
+        _safetyTypeRepository = safetyTypeRepository;
+        _snapshotUserApplication = snapshotUserApplication;
+        _sessionContext = sessionContext;
+        _snapshotApplication = snapshotApplication;
+        _bulletinRepository = bulletinRepository;
+    }
+
+    [Fact]
+    public async Task Bulletin_Test()
+    {
+        SetWeiXin();
+        var bulletinType =  _systemDicDataCacheManager.SnapshotBulletinType.First();
+        var safetyType = await _safetyTypeRepository.Queryable().FirstAsync();
+        var addRelationInDto = new AddCitizenRelationSafetyTypeInDto { SafetyTypeId = safetyType.Id, CitizenIds = [_sessionContext.UserId] };
+        await _snapshotUserApplication.AddCitizenRelationSafetyType(addRelationInDto, CancellationToken.None);
+        var inDto = new AddSnapshotBulletinInDto
+        {
+            Title = "测试公告" + DateTime.Now.ToLongDateTimeString(),
+            Content = "没什么内容",
+            BulletinTime = DateTime.Now,
+            IsSnapshot = true,
+            BulletinTypeId = bulletinType.DicDataValue,
+            BulletinTypeName = bulletinType.DicDataName,
+            SafetyTypeId = [safetyType.Id],
+            VideoCoverImgUrl = "222222",
+            VideoPath = "333333"
+        };
+        var bulletinId = await _snapshotBulletinApplication.AddBulletinAsync(inDto, CancellationToken.None);
+        var bulletin = await _bulletinRepository.GetAsync(bulletinId);
+        bulletin.IsSnapshot.ShouldBe(true);
+        bulletin.SafetyTypeId.First().ShouldBe(safetyType.Id);
+        bulletin.VideoPath.ShouldBe(inDto.VideoPath);
+        bulletin.VideoCoverImgUrl.ShouldBe(inDto.VideoCoverImgUrl);
+        await _snapshotBulletinApplication.CommitBulletinAsync(bulletinId, CancellationToken.None);
+        var examineDto = new ExamineBulletinDto
+        {
+            Id = bulletinId,
+            IsPass = true,
+            Reason = "审核通过"
+        };
+        await _snapshotBulletinApplication.ExamineBulletinAsync(examineDto, CancellationToken.None);
+        Thread.Sleep(5 * 1000);
+        //await _snapshotBulletinApplication.NotifyUserAsync(bulletinId, CancellationToken.None);
+
+
+        var notifyItems = await _snapshotApplication.GetNotificationAsync(new GetNotifyInDto(), CancellationToken.None);
+        notifyItems.Any(m => m.Title == inDto.Title).ShouldBeTrue();
+    }
+}

+ 7 - 0
test/Hotline.Tests/Application/SnapshotUserApplicationTest.cs

@@ -37,6 +37,13 @@ public class SnapshotUserApplicationTest : TestBase
     [Fact]
     public async Task SnapshotUserApplication_Test()
     {
+        var searchInDto = new GetThirdCitizenInDto
+        {
+            PhoneNumber = "33"
+        };
+        var citizenSearchItems = await _snapshotUserApplication.GetThirdCitizenAsync(searchInDto).ToListAsync();
+        citizenSearchItems.ShouldNotBeNull();
+        citizenSearchItems.Count.ShouldNotBe(0);
         var newSafetyType = new SafetyType { Name = "安全卫士" };
         var safetyType = await _safetyTypeRepository.Queryable().Where(m => m.Name == newSafetyType.Name).FirstAsync();
         safetyType ??= new SafetyType

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است