| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- // Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
- //
- // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
- //
- // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
- using Microsoft.Extensions.Logging;
- namespace Admin.NET.Core.Service;
- /// <summary>
- /// 系统通知公告服务 🧩
- /// </summary>
- [ApiDescriptionSettings(Order = 380, Description = "通知公告")]
- public class SysNoticeService : IDynamicApiController, ITransient
- {
- private readonly UserManager _userManager;
- private readonly SqlSugarRepository<SysUser> _sysUserRep;
- private readonly SqlSugarRepository<SysNotice> _sysNoticeRep;
- private readonly SqlSugarRepository<SysNoticeUser> _sysNoticeUserRep;
- private readonly SysOnlineUserService _sysOnlineUserService;
- private readonly ILogger<SysNoticeService> _logger;
- public SysNoticeService(
- UserManager userManager,
- SqlSugarRepository<SysUser> sysUserRep,
- SqlSugarRepository<SysNotice> sysNoticeRep,
- SqlSugarRepository<SysNoticeUser> sysNoticeUserRep,
- SysOnlineUserService sysOnlineUserService,
- ILogger<SysNoticeService> logger)
- {
- _userManager = userManager;
- _sysUserRep = sysUserRep;
- _sysNoticeRep = sysNoticeRep;
- _sysNoticeUserRep = sysNoticeUserRep;
- _sysOnlineUserService = sysOnlineUserService;
- _logger = logger;
- }
- /// <summary>
- /// 获取通知公告分页列表 📢
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [DisplayName("获取通知公告分页列表")]
- public async Task<SqlSugarPagedList<SysNotice>> Page(PageNoticeInput input)
- {
- return await _sysNoticeRep.AsQueryable()
- .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.Title.Contains(input.Title.Trim()))
- .WhereIF(input.Type > 0, u => u.Type == input.Type)
- .WhereIF(!_userManager.SuperAdmin, u => u.CreateUserId == _userManager.UserId)
- .OrderBy(u => u.CreateTime, OrderByType.Desc)
- .ToPagedListAsync(input.Page, input.PageSize);
- }
- /// <summary>
- /// 增加通知公告 📢
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [ApiDescriptionSettings(Name = "Add"), HttpPost]
- [DisplayName("增加通知公告")]
- public async Task AddNotice(AddNoticeInput input)
- {
- var notice = input.Adapt<SysNotice>();
- InitNoticeInfo(notice);
- await _sysNoticeRep.InsertAsync(notice);
- }
- /// <summary>
- /// 更新通知公告 📢
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [UnitOfWork]
- [ApiDescriptionSettings(Name = "Update"), HttpPost]
- [DisplayName("更新通知公告")]
- public async Task UpdateNotice(UpdateNoticeInput input)
- {
- if (input.CreateUserId != _userManager.UserId)
- throw Oops.Oh(ErrorCodeEnum.D7003);
- var notice = input.Adapt<SysNotice>();
- InitNoticeInfo(notice);
- await _sysNoticeRep.UpdateAsync(notice);
- }
- /// <summary>
- /// 删除通知公告 📢
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [UnitOfWork]
- [ApiDescriptionSettings(Name = "Delete"), HttpPost]
- [DisplayName("删除通知公告")]
- public async Task DeleteNotice(DeleteNoticeInput input)
- {
- var sysNotice = await _sysNoticeRep.GetByIdAsync(input.Id);
- if (sysNotice.CreateUserId != _userManager.UserId) throw Oops.Oh(ErrorCodeEnum.D7003);
- if (sysNotice.Status == NoticeStatusEnum.PUBLIC) throw Oops.Oh(ErrorCodeEnum.D7001);
- await _sysNoticeRep.DeleteAsync(u => u.Id == input.Id);
- await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == input.Id);
- }
- /// <summary>
- /// 发布通知公告 📢
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [DisplayName("发布通知公告")]
- public async Task Public(NoticeInput input)
- {
- if (!(await _sysNoticeRep.IsAnyAsync(u => u.Id == input.Id && u.CreateUserId == _userManager.UserId)))
- throw Oops.Oh(ErrorCodeEnum.D7003);
- // 更新发布状态和时间
- await _sysNoticeRep.UpdateAsync(u => new SysNotice() { Status = NoticeStatusEnum.PUBLIC, PublicTime = DateTime.Now }, u => u.Id == input.Id);
- var notice = await _sysNoticeRep.GetByIdAsync(input.Id);
- // 通知到的人(所有账号)
- var userIdList = await _sysUserRep.AsQueryable().Select(u => u.Id).ToListAsync();
- await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == notice.Id);
- await DispatchPersistedNoticeAsync(notice, userIdList);
- }
- /// <summary>
- /// 向指定用户发布一条已落库的定向站内信,并尽力实时推送。
- /// SignalR 失败不回滚通知记录。
- /// </summary>
- [NonAction]
- public async Task<long> PublishToUsersAsync(
- string title,
- string content,
- IEnumerable<long> userIds,
- long publicUserId = 0,
- string? publicUserName = null,
- long publicOrgId = 0)
- {
- var targets = (userIds ?? Array.Empty<long>()).Where(id => id > 0).Distinct().ToList();
- if (targets.Count == 0)
- return 0;
- var now = DateTime.Now;
- var publisherId = publicUserId > 0 ? publicUserId : _userManager.UserId;
- var notice = new SysNotice
- {
- Title = TruncateTitle(title),
- Content = content ?? string.Empty,
- Type = NoticeTypeEnum.NOTICE,
- PublicUserId = publisherId,
- PublicUserName = publicUserName ?? _userManager.RealName,
- PublicOrgId = publicOrgId > 0 ? publicOrgId : _userManager.OrgId,
- PublicTime = now,
- Status = NoticeStatusEnum.PUBLIC,
- CreateTime = now,
- CreateUserId = publisherId,
- CreateUserName = publicUserName ?? _userManager.RealName,
- };
- await _sysNoticeRep.InsertAsync(notice);
- await DispatchPersistedNoticeAsync(notice, targets);
- return notice.Id;
- }
- [NonAction]
- public async Task DispatchPersistedNoticeAsync(SysNotice notice, IEnumerable<long> userIds)
- {
- var targets = (userIds ?? Array.Empty<long>()).Where(id => id > 0).Distinct().ToList();
- if (notice == null || notice.Id <= 0 || targets.Count == 0)
- return;
- var noticeUserList = targets.Select(u => new SysNoticeUser
- {
- NoticeId = notice.Id,
- UserId = u,
- ReadStatus = NoticeUserStatusEnum.UNREAD,
- }).ToList();
- await _sysNoticeUserRep.InsertRangeAsync(noticeUserList);
- try
- {
- await _sysOnlineUserService.PublicNotice(notice, targets);
- }
- catch (Exception ex)
- {
- _logger.LogWarning(ex, "定向站内信已落库但实时推送失败 noticeId={NoticeId}", notice.Id);
- }
- }
- private static string TruncateTitle(string? title)
- {
- var value = string.IsNullOrWhiteSpace(title) ? "系统通知" : title.Trim();
- return value.Length <= 32 ? value : value[..32];
- }
- /// <summary>
- /// 设置通知公告已读状态 📢
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [DisplayName("设置通知公告已读状态")]
- public async Task SetRead(NoticeInput input)
- {
- await _sysNoticeUserRep.UpdateAsync(u => new SysNoticeUser
- {
- ReadStatus = NoticeUserStatusEnum.READ,
- ReadTime = DateTime.Now
- }, u => u.NoticeId == input.Id && u.UserId == _userManager.UserId);
- }
- /// <summary>
- /// 获取接收的通知公告
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [DisplayName("获取接收的通知公告")]
- public async Task<SqlSugarPagedList<SysNoticeUser>> PageReceived(PageNoticeInput input)
- {
- return await _sysNoticeUserRep.AsQueryable().Includes(u => u.SysNotice)
- .Where(u => u.UserId == _userManager.UserId)
- .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.SysNotice.Title.Contains(input.Title.Trim()))
- .WhereIF(input.Type is > 0, u => u.SysNotice.Type == input.Type)
- .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc)
- .ToPagedListAsync(input.Page, input.PageSize);
- }
- /// <summary>
- /// 获取未读的通知公告 📢
- /// </summary>
- /// <returns></returns>
- [DisplayName("获取未读的通知公告")]
- public async Task<List<SysNotice>> GetUnReadList()
- {
- var noticeUserList = await _sysNoticeUserRep.AsQueryable().Includes(u => u.SysNotice)
- .Where(u => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD)
- .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc).ToListAsync();
- return noticeUserList.Select(t => t.SysNotice).ToList();
- }
- /// <summary>
- /// 初始化通知公告信息
- /// </summary>
- /// <param name="notice"></param>
- [NonAction]
- private void InitNoticeInfo(SysNotice notice)
- {
- notice.PublicUserId = _userManager.UserId;
- notice.PublicUserName = _userManager.RealName;
- notice.PublicOrgId = _userManager.OrgId;
- }
- }
|