Browse Source

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

田爽 1 year ago
parent
commit
3149f51fc4

+ 148 - 6
src/Hotline.Api/Controllers/ArticleController.cs

@@ -12,6 +12,7 @@ using Hotline.Share.Enums.Article;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.OpenApi.Writers;
+using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
@@ -26,16 +27,160 @@ namespace Hotline.Api.Controllers
         private readonly ISystemDomainService _systemDomainService;
         private readonly ISystemOrganizeRepository _organizeRepository;
         private readonly IWorkflowApplication _workflowApplication;
+        private readonly IRepository<Circular> _circularRepository;
+        private readonly ISessionContext _sessionContext;
+        private readonly IRepository<CircularRecord> _circularRecordRepository;
 
-        public ArticleController(IRepository<Bulletin> bulletinRepository,IMapper mapper, ISystemDomainService systemDomainService, ISystemOrganizeRepository organizeRepository, IWorkflowApplication workflowApplication)
+        public ArticleController(IRepository<Bulletin> bulletinRepository,IMapper mapper, ISystemDomainService systemDomainService, ISystemOrganizeRepository organizeRepository, IWorkflowApplication workflowApplication, IRepository<Circular> circularRepository,ISessionContext sessionContext,IRepository<CircularRecord> circularRecordRepository)
         {
             _bulletinRepository = bulletinRepository;
             _mapper = mapper;
             _systemDomainService = systemDomainService;
             _organizeRepository = organizeRepository;
             _workflowApplication = workflowApplication;
+            _circularRepository = circularRepository;
+            _sessionContext = sessionContext;
+            _circularRecordRepository = circularRecordRepository;
+        }
+        #region 通知
+        /// <summary>
+        /// 查询通知列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.QueryCircularList)]
+        [HttpGet("circular/query")]
+        public async Task<PagedDto<CircularDto>> QueryCircularList([FromQuery] QueryCircularListRequestDto dto)
+        {
+            var (total,items) = await _circularRepository.Queryable()
+                .Includes(x=>x.CircularReadGroups)
+                .WhereIF(!string.IsNullOrEmpty(dto.CircularTypeId), d => d.CircularTypeId == dto.CircularTypeId)
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title.Contains(dto.Title))
+                .WhereIF(dto.CircularTimeStart.HasValue, d => d.CircularTime >= dto.CircularTimeStart)
+                .WhereIF(dto.CircularTimeEnd.HasValue, d => d.CircularTime <= dto.CircularTimeEnd)
+                .OrderByDescending(d => d.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<CircularDto>(total, _mapper.Map<IReadOnlyList<CircularDto>>(items));
+        }
+
+        /// <summary>
+        /// 通知详情(内部)
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [Permission(EPermission.CircularEntity)]
+        [HttpGet("circular/entity/{id}")]
+        public async Task<CircularDto> CircularEntity(string id)
+        {
+            var model = await _circularRepository.Queryable()
+                .Includes(x => x.CircularReadGroups)
+                .FirstAsync(x => x.Id == id, HttpContext.RequestAborted);
+            return _mapper.Map<CircularDto>(model);
+        }
+
+        /// <summary>
+        /// 新增通知
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.AddCircular)]
+        [HttpPost("circular/add")]
+        public async Task AddCircular([FromBody] CircularFlowDto dto)
+        {
+            var model = _mapper.Map<Circular>(dto.Data);
+            model.CircularState = ECircularState.InReview;
+            model.ReadedNum = 0;
+            model.NeedReadNum = model.CircularReadGroups.Count;
+            var id = await _circularRepository.AddAsync(model, HttpContext.RequestAborted);
+            try
+            {
+                var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
+                startDto.DefinitionModuleCode = WorkflowModuleConsts.CircularApply;
+                startDto.Title = model.Title;
+                await _workflowApplication.StartWorkflowAsync(startDto, id, HttpContext.RequestAborted);
+            }
+            catch (Exception ex)
+            {
+                await _circularRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
+                throw new UserFriendlyException($"新增通知流程失败!,{ex.Message}", "新增通知流程失败");
+            }
+        }
+
+        /// <summary>
+        /// 列表页面基础信息
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("circular/listbasedata")]
+        public async Task<object> CircularBaseData()
+        {
+            var rsp = new
+            {
+                CircularType = _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.CircularType)
+            };
+            return rsp;
+        }
+
+        /// <summary>
+        /// 新增页面基础数据
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("circular/addbasedata")]
+        public async Task<object> CircularAddBaseData()
+        {
+            var rsp = new
+            {
+                CircularType = _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.CircularType),
+                OrgsOptions = await _organizeRepository.GetOrgJson(),
+            };
+            return rsp;
         }
 
+        /// <summary>
+        /// 通知阅读(内部)
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("circular/read/{id}")]
+        public async Task<CircularDto> CircularRead(string id)
+        {
+            var model = await _circularRepository.Queryable()
+                .Includes(x => x.CircularReadGroups)
+                .FirstAsync(x => x.Id == id, HttpContext.RequestAborted);
+
+            //更新阅读信息
+            if (model.CircularType == ECircularType.Person)
+            {
+                //个人阅读
+            }
+            else
+            {
+                //部门阅读
+            }
+
+            return _mapper.Map<CircularDto>(model);
+        }
+
+        /// <summary>
+        /// 获取小红点计数
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("megcount")]
+        public async Task<CircularRecordDto> QueryMegCount()
+        {
+            var list = await _circularRecordRepository.Queryable().Where(x => x.UserId == _sessionContext.UserId || x.OrgId == _sessionContext.OrgId).ToListAsync();
+            if (list!=null && list.Count>0)
+            {
+                var rsp = new CircularRecordDto();
+                rsp.OrgCount = list.FirstOrDefault(x => x.CircularType == ECircularType.Org)?.RecordCount ?? 0;
+                rsp.PersonCount = list.FirstOrDefault(x => x.CircularType == ECircularType.Person)?.RecordCount ?? 0;
+                rsp.SumCount = rsp.OrgCount + rsp.PersonCount;
+            }
+            return new CircularRecordDto() { SumCount = 0, OrgCount = 0, PersonCount = 0 };
+        }
+
+        #endregion
+
+
         #region 公告
 
         /// <summary>
@@ -81,7 +226,6 @@ namespace Hotline.Api.Controllers
         [HttpPost("bulletin/add")]
         public async Task AddBulletin([FromBody]BulletinFlowDto dto)
         {
-
             var model = _mapper.Map<Bulletin>(dto.Data);
             model.BulletinState = Share.Enums.Article.EBulletinState.InReview;
             model.ReadedNum = 0;
@@ -114,6 +258,7 @@ namespace Hotline.Api.Controllers
             return rsp;
         }
 
+
         /// <summary>
         /// 新增页面基础数据
         /// </summary>
@@ -133,10 +278,7 @@ namespace Hotline.Api.Controllers
 
         #endregion
 
-        #region 通知
-
-
-        #endregion
+       
 
     }
 }

+ 1 - 1
src/Hotline.Api/Controllers/OrderController.cs

@@ -705,7 +705,7 @@ public class OrderController : BaseController
         model.DelayState = EDelayState.Examining;
         if (model.BeforeDelay != null)
         {
-            //model.AfterDelay = _timeLimitApplication.CalcEndTime(model.BeforeDelay.Value, dto.DelayUnit, dto.DelayNum)?.EndTime;//todo
+            model.AfterDelay = _timeLimitDomainService.CalcEndTime(model.BeforeDelay.Value, delaydto.DelayUnit, delaydto.DelayNum,false)?.EndTime;//todo
         }
 
         model.ApplyDelayTime = DateTime.Now;

+ 14 - 0
src/Hotline.Api/Realtimes/RealtimeMethods.cs

@@ -2,6 +2,7 @@
 {
     public static class RealtimeMethods
     {
+        #region 通讯通知
         /// <summary>
         /// 电话振铃通知
         /// </summary>
@@ -30,6 +31,19 @@
         /// 话机空闲
         /// </summary>
         public static string Idle = "Idle";
+
+        #endregion
+
+        #region 系统信息通知
+
+        /// <summary>
+        /// 通知用户未读消息
+        /// </summary>
+        public static string CircularRecord = "CircularRecord";
+
+
+        #endregion
+
     }
 }
     

+ 53 - 2
src/Hotline.Api/Realtimes/RealtimeService.cs

@@ -1,4 +1,5 @@
-using Hotline.Caching.Interfaces;
+using Hotline.Article;
+using Hotline.Caching.Interfaces;
 using Hotline.Caching.Services;
 using Hotline.Realtimes;
 using Hotline.Share.Dtos.Realtime;
@@ -7,6 +8,7 @@ using Microsoft.AspNetCore.SignalR;
 using XF.Domain.Cache;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
+using XF.Domain.Repository;
 
 namespace Hotline.Api.Realtimes;
 
@@ -14,14 +16,21 @@ public class RealtimeService : IRealtimeService, IScopeDependency
 {
     private readonly IHubContext<HotlineHub> _hubContext;
     private readonly IRealtimeCacheManager _realtimeCacheManager;
+    private readonly IRepository<CircularRecord> _circularRecordRepository;
+    private readonly IRepository<User> _userRepository;
 
     public RealtimeService(
         IHubContext<HotlineHub> hubContext,
-        IRealtimeCacheManager realtimeCacheManager)
+        IRealtimeCacheManager realtimeCacheManager,
+        IRepository<CircularRecord> circularRecordRepository,
+        IRepository<User> userRepository)
     {
         _hubContext = hubContext;
         _realtimeCacheManager = realtimeCacheManager;
+        _circularRecordRepository = circularRecordRepository;
+        _userRepository = userRepository;
     }
+    #region 通讯通知
 
     /// <summary>
     /// 回铃事件通知
@@ -109,6 +118,42 @@ public class RealtimeService : IRealtimeService, IScopeDependency
     /// <exception cref="UserFriendlyException"></exception>
     public Task IdleAsync(string userId, CancellationToken cancellationToken) =>
         SendCallCenterMsgAsync(userId, RealtimeMethods.Idle, new { EventName = "Idle" }, cancellationToken);
+    #endregion
+
+    #region 系统信息通知
+
+    /// <summary>
+    /// 新消息通知
+    /// </summary>
+    /// <param name="id"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    public async Task CircularRecoordAsync(string id,CancellationToken cancellationToken)
+    {
+        //获取所有需要推送的
+        var list = await _circularRecordRepository.Queryable().Where(x => x.Id == id).ToListAsync();
+        foreach (var item in list)
+        {
+            if (item.CircularType == Share.Enums.Article.ECircularType.Person)
+            {
+                //个人
+                await SendMsgAsync(item.UserId, RealtimeMethods.CircularRecord,null, cancellationToken);
+            }
+            else
+            {
+                //部门
+                var orguserList = await _userRepository.Queryable().Where(x => x.OrgId == item.OrgId).ToListAsync();
+                foreach (var user in orguserList)
+                {
+                    await SendMsgAsync(user.Id, RealtimeMethods.CircularRecord, null, cancellationToken);
+                }
+            }
+        }
+    }
+
+    #endregion
+
+
 
     #region private
 
@@ -126,5 +171,11 @@ public class RealtimeService : IRealtimeService, IScopeDependency
             throw UserFriendlyException.SameMessage("该用户不属于分组:呼叫中心");
     }
 
+    private async Task SendMsgAsync(string userId,string msg,object? value,CancellationToken cancellationToken)
+    {
+        var connection = await _realtimeCacheManager.GetConnectionAsync(userId, cancellationToken);
+        await _hubContext.Clients.Client(connection.ConnectionId).SendAsync(msg, value, cancellationToken);
+    }
+
     #endregion
 }

+ 143 - 0
src/Hotline.Share/Dtos/Article/BulletinDto.cs

@@ -72,6 +72,118 @@ namespace Hotline.Share.Dtos.Article
         public string? CreatorName { get; set; }
     }
 
+    public record CircularDto
+    {
+        public string Id { get; set; }
+
+        public DateTime CreationTime { get; set; }
+
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 通知类型
+        /// </summary>
+        public string CircularTypeId { get; set; }
+
+        /// <summary>
+        /// 通知类型名称
+        /// </summary>
+        public string CircularTypeName { get; set; }
+
+        /// <summary>
+        /// 是否必读
+        /// </summary>
+        public bool IsMustRead { get; set; }
+
+        /// <summary>
+        /// 通知对象
+        /// </summary>
+        public ECircularType CircularType { get; set; }
+
+        /// <summary>
+        /// 通知时间
+        /// </summary>
+        public DateTime? CircularTime { get; set; }
+
+        /// <summary>
+        /// 失效时间
+        /// </summary>
+        public DateTime LostEfficacyTime { get; set; }
+
+        /// <summary>
+        /// 通知状态
+        /// </summary>
+        public ECircularState CircularState { get; set; }
+        /// <summary>
+        /// 来源单位ID
+        /// </summary>
+        public string SourceOrgId { get; set; }
+
+        /// <summary>
+        /// 来源单位名称
+        /// </summary>
+        public string SourceOrgName { get; set; }
+
+        /// <summary>
+        /// 需要阅读数量
+        /// </summary>
+        public int NeedReadNum { get; set; }
+
+        /// <summary>
+        /// 已读数量
+        /// </summary>
+        public int ReadedNum { get; set; }
+
+        /// <summary>
+        /// 阅读明细
+        /// </summary>
+        public List<CircularReadGroupDto> CircularReadGroups { get; set; }
+    }
+
+    public record CircularReadGroupDto
+    {
+        public string CircularId { get; set; }
+
+        public string? UserId { get; set; }
+        public string? UserName { get; set; }
+
+        public string? OrgId { get; set; }
+
+        public string? OrgName { get; set; }
+
+        public bool IsRead { get; set; }
+
+        public DateTime? ReadTime { get; set; }
+
+        public bool? IsTimeOut { get; set; }
+    }
+
+
+    public record AddCircularDto
+    {
+        public string Title { get; set; }
+
+        public string Content { get; set; }
+
+        public string CircularTypeId { get; set; }
+
+        public string CircularTypeName { get; set; }
+
+        public bool IsMustRead { get; set; }
+
+        public DateTime LostEfficacyTime { get; set; }
+
+        public List<CircularReadGroupDto> CircularReadGroups { get; set; }
+    }
+
 
     public record AddBulletinDto
     {
@@ -116,6 +228,26 @@ namespace Hotline.Share.Dtos.Article
         public string SourceOrgName { get; set; }
     }
 
+    public record QueryCircularListRequestDto:PagedRequest
+    {
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+        /// <summary>
+        /// 通知类型
+        /// </summary>
+        public string CircularTypeId { get; set; }
+
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public DateTime? CircularTimeStart { get; set; }
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public DateTime? CircularTimeEnd { get; set; }
+    }
 
     public record QueryBulletinListRequestDto:PagedRequest
     {
@@ -139,4 +271,15 @@ namespace Hotline.Share.Dtos.Article
         /// </summary>
         public DateTime? BulletinTimeEnd { get; set; }
     }
+
+
+
+    public record CircularRecordDto
+    {
+        public int SumCount { get; set; }
+
+        public int PersonCount { get; set; }
+
+        public int OrgCount { get; set; }
+    }
 }

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

@@ -27,4 +27,9 @@ namespace Hotline.Share.Dtos.Order
     {
 
     }
+
+    public class CircularFlowDto:StartWorkflowDto<AddCircularDto>
+    {
+
+    }
 }

+ 1 - 6
src/Hotline.Share/Enums/Article/EBulletinState.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.ComponentModel;
 
 namespace Hotline.Share.Enums.Article
 {

+ 32 - 0
src/Hotline.Share/Enums/Article/ECircularState.cs

@@ -0,0 +1,32 @@
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Article
+{
+    public enum ECircularState
+    {
+        /// <summary>
+        /// 审批中
+        /// </summary>
+        [Description("审批中")]
+        InReview = 1,
+
+        /// <summary>
+        /// 审批通过
+        /// </summary>
+        [Description("审批通过")]
+        ReviewPass = 2,
+
+        /// <summary>
+        /// 审批驳回
+        /// </summary>
+        [Description("审批驳回")]
+        ReviewNoPass = 3,
+
+        /// <summary>
+        /// 已失效
+        /// </summary>
+        [Description("已失效")]
+        LoseEfficacy = 4,
+
+    }
+}

+ 21 - 0
src/Hotline.Share/Enums/Article/ECircularType.cs

@@ -0,0 +1,21 @@
+
+
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Article
+{
+    public enum ECircularType
+    {
+        /// <summary>
+        /// 个人
+        /// </summary>
+        [Description("个人")]
+        Person = 1,
+
+        /// <summary>
+        /// 部门
+        /// </summary>
+        [Description("部门")]
+        Org = 2,
+    }
+}

+ 4 - 3
src/Hotline/Article/Bulletin.cs

@@ -1,11 +1,12 @@
-using Hotline.Settings;
-using Hotline.Settings.Hotspots;
-using Hotline.Share.Enums.Article;
+using Hotline.Share.Enums.Article;
 using SqlSugar;
 using XF.Domain.Repository;
 
 namespace Hotline.Article
 {
+    /// <summary>
+    /// 公告
+    /// </summary>
     public class Bulletin : CreationEntity
     {
         public string Title { get; set; }

+ 84 - 0
src/Hotline/Article/Circular.cs

@@ -0,0 +1,84 @@
+using Hotline.Orders;
+using Hotline.Share.Enums.Article;
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Article
+{
+    /// <summary>
+    /// 通知
+    /// </summary>
+    public class Circular: CreationEntity
+    {
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        [SugarColumn(ColumnDataType = "varchar(2000)")]
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 通知类型
+        /// </summary>
+        public string CircularTypeId { get; set; }
+
+        /// <summary>
+        /// 通知类型名称
+        /// </summary>
+        public string CircularTypeName { get; set; }
+
+        /// <summary>
+        /// 是否必读
+        /// </summary>
+        public bool IsMustRead { get; set; }
+
+        /// <summary>
+        /// 通知对象
+        /// </summary>
+        public ECircularType CircularType { get; set; }
+
+        /// <summary>
+        /// 通知时间
+        /// </summary>
+        public DateTime? CircularTime { get; set; }
+
+        /// <summary>
+        /// 失效时间
+        /// </summary>
+        public DateTime LostEfficacyTime { get; set; }
+
+        /// <summary>
+        /// 通知状态
+        /// </summary>
+        public ECircularState CircularState { get; set; }
+        /// <summary>
+        /// 来源单位ID
+        /// </summary>
+        public string SourceOrgId { get; set; }
+
+        /// <summary>
+        /// 来源单位名称
+        /// </summary>
+        public string SourceOrgName { get; set; }
+
+        /// <summary>
+        /// 需要阅读数量
+        /// </summary>
+        public int NeedReadNum { get; set; }
+
+        /// <summary>
+        /// 已读数量
+        /// </summary>
+        public int ReadedNum { get; set; }
+
+        /// <summary>
+        /// 阅读明细
+        /// </summary>
+        [Navigate(NavigateType.OneToMany, nameof(CircularReadGroup.CircularId))]
+        public List<CircularReadGroup> CircularReadGroups { get; set; }
+    }
+}

+ 22 - 0
src/Hotline/Article/CircularReadGroup.cs

@@ -0,0 +1,22 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Article
+{
+    public class CircularReadGroup:CreationEntity
+    {
+        public string CircularId { get; set; }
+
+        public string? UserId{ get; set; }
+        public string? UserName { get; set; } 
+
+        public string? OrgId { get; set; }
+
+        public string? OrgName { get; set; }
+
+        public bool IsRead { get; set; }
+
+        public DateTime? ReadTime { get; set; }
+
+        public bool? IsTimeOut { get; set; }
+    }
+}

+ 19 - 0
src/Hotline/Article/CircularRecord.cs

@@ -0,0 +1,19 @@
+using Hotline.Share.Enums.Article;
+using XF.Domain.Repository;
+
+namespace Hotline.Article
+{
+    /// <summary>
+    /// 记录数
+    /// </summary>
+    public class CircularRecord: CreationEntity
+    {
+        public ECircularType CircularType { get; set; }
+
+        public string? UserId { get; set; }
+
+        public string? OrgId { get; set; }
+
+        public int RecordCount { get; set; }
+    }
+}

+ 8 - 1
src/Hotline/FlowEngine/WorkflowModules/WorkflowModuleConsts.cs

@@ -49,6 +49,12 @@ public class WorkflowModuleConsts
     /// </summary>
     public const string BulletinApply = "BulletinApply";
 
+    /// <summary>
+    /// 通知审批
+    /// </summary>
+    public const string CircularApply = "CircularApply";
+
+
     public static List<WorkflowModule> AllModules =>
         new()
         {
@@ -60,6 +66,7 @@ public class WorkflowModuleConsts
             new(OrderDelay,"工单延期"),
             new(OrderPrevious,"工单退回"),
             new(OrderScreen,"工单甄别"),
-            new(BulletinApply,"公告审批")
+            new(BulletinApply,"公告审批"),
+            new(CircularApply,"通知审批")
         };
 }

+ 19 - 1
src/Hotline/Permissions/EPermission.cs

@@ -1233,7 +1233,7 @@ namespace Hotline.Permissions
         [Display(GroupName = "辅助功能", Name = "辅助功能", Description = "辅助功能")]
         Auxiliary = 600000,
 
-
+        #region 公告列表
         /// <summary>
         /// 查询公告列表
         /// </summary>
@@ -1250,6 +1250,24 @@ namespace Hotline.Permissions
         [Display(GroupName = "AddBulletin",Name ="新增公告",Description ="新增公告")]
         AddBulletin = 600102,
         #endregion
+        #region 通知列表
+        /// <summary>
+        /// 查询通知列表
+        /// </summary>
+        [Display(GroupName = "QueryCircularList",Name ="查询通知列表",Description ="查询通知列表")]
+        QueryCircularList = 600200,
+        /// <summary>
+        /// 通知详情
+        /// </summary>
+        [Display(GroupName = "CircularEntity",Name ="通知详情",Description ="通知详情")]
+        CircularEntity = 600201,
+        /// <summary>
+        /// 新增通知
+        /// </summary>
+        [Display(GroupName = "AddCircular",Name ="新增通知",Description = "新增通知")]
+        AddCircular = 600202,
+        #endregion
+        #endregion
 
         #region 公用(999)
         #region 上/下班

+ 9 - 0
src/Hotline/Realtimes/IRealtimeService.cs

@@ -5,6 +5,7 @@ namespace Hotline.Realtimes
 {
     public interface IRealtimeService
     {
+        #region 话机状态通知
         Task AlertAsync(string userId, AlertDto dto, CancellationToken cancellationToken);
 
         Task RingAsync(string userId, RingDto dto, CancellationToken cancellationToken);
@@ -18,5 +19,13 @@ namespace Hotline.Realtimes
         Task CallQueueAsync(List<CallCacheManager.CallDtoRedis> list, CancellationToken cancellationToken);
 
         Task IdleAsync(string userId, CancellationToken cancellationToken);
+
+        #endregion
+
+        #region 系统消息通知
+
+        Task CircularRecoordAsync(string id, CancellationToken cancellationToken);
+
+        #endregion
     }
 }

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

@@ -169,4 +169,9 @@ public class SysDicTypeConsts
     /// 公告类型
     /// </summary>      
     public const string BulletinType = "BulletinType";
+
+    /// <summary>
+    /// 通知类型
+    /// </summary>
+    public const string CircularType = "CircularType";
 }