diff --git a/Infrastructure/Constant/SysNoticeLogStatus.cs b/Infrastructure/Constant/SysNoticeLogStatus.cs new file mode 100644 index 0000000..e8b52ac --- /dev/null +++ b/Infrastructure/Constant/SysNoticeLogStatus.cs @@ -0,0 +1,8 @@ +namespace ZR.Infrastructure.Constant; + +public class SysNoticeLogStatus +{ + public const string Unread = "0"; + + public const string Read = "1"; +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/Controllers/System/SysNoticeController.cs b/ZR.Admin.WebApi/Controllers/System/SysNoticeController.cs index 43f2b8b..72f364d 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysNoticeController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysNoticeController.cs @@ -80,18 +80,23 @@ namespace ZR.Admin.WebApi.Controllers.System public IActionResult AddSysNotice([FromBody] SysNoticeDto parm) { var modal = parm.Adapt().ToCreate(HttpContext); + modal.Create_by = HttpContext.GetUId(); + modal.Create_name = HttpContext.GetNickName(); + modal.Create_time = DateTime.Now; + + // int result = _SysNoticeService.Insert(modal, it => new + // { + // it.NoticeTitle, + // it.NoticeType, + // it.NoticeContent, + // it.Status, + // it.Remark, + // it.Create_by, + // it.Create_time + // }); + + var result = _SysNoticeService.Insertable(modal).ExecuteReturnSnowflakeId(); - int result = _SysNoticeService.Insert(modal, it => new - { - it.NoticeTitle, - it.NoticeType, - it.NoticeContent, - it.Status, - it.Remark, - it.Create_by, - it.Create_time - }); - return SUCCESS(result); } @@ -104,9 +109,11 @@ namespace ZR.Admin.WebApi.Controllers.System [Log(Title = "修改公告", BusinessType = BusinessType.UPDATE)] public IActionResult UpdateSysNotice([FromBody] SysNoticeDto parm) { - var model = parm.Adapt().ToUpdate(HttpContext); - model.Update_by = HttpContext.GetUId(); - model.Update_name = HttpContext.GetNickName(); + var config = new TypeAdapterConfig(); + config.ForType() + .Map(dest => dest.NoticeId, src => src.NoticeId.ParseToLong()); + var model = parm.Adapt(config).ToUpdate(HttpContext); + var response = _SysNoticeService.Update(w => w.NoticeId == model.NoticeId, it => new SysNotice() { NoticeTitle = model.NoticeTitle, @@ -128,7 +135,7 @@ namespace ZR.Admin.WebApi.Controllers.System [HttpPut("send/{NoticeId}")] [ActionPermissionFilter(Permission = "system:notice:update")] [Log(Title = "发送通知公告", BusinessType = BusinessType.OTHER)] - public IActionResult SendNotice(int NoticeId = 0) + public IActionResult SendNotice(long NoticeId = 0) { if (NoticeId <= 0) { diff --git a/ZR.Admin.WebApi/appsettings.json b/ZR.Admin.WebApi/appsettings.json index 5d01ebf..ae1d6e5 100644 --- a/ZR.Admin.WebApi/appsettings.json +++ b/ZR.Admin.WebApi/appsettings.json @@ -101,9 +101,9 @@ }, //redis服务配置 "RedisServer": { - "open": 0, //是否启用redis - "Cache": "127.0.0.1:6379,defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240,prefix=cache:", - "Session": "127.0.0.1:6379,defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240,prefix=session:" + "open": 1, //是否启用redis + "Cache": "8.140.174.251:6379,password=Wyd210213,defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240,prefix=cache:", + "Session": "8.140.174.251:6379,password=Wyd210213,defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240,prefix=session:" }, //接口请求限制 "IpRateLimiting": { @@ -135,6 +135,17 @@ }, //验证码配置 "CaptchaOptions": { - "IgnoreCase": true // 比较时是否忽略大小写 + "CaptchaType": 10, + "IgnoreCase": true, // 比较时是否忽略大小写 + "ImageOption": { + "FontSize": 36, // 字体大小 + "Animation": true, // 是否启用动画 + "TextBold": true, // 是否启用粗体 + "InterferenceLineCount": 4, // 干扰线数量 + "BubbleMinRadius": 5, // 气泡最小半径 + "BubbleMaxRadius": 10, // 气泡最大半径 + "BubbleCount": 3, // 气泡数量 + "BubbleThickness": 1.0 // 气泡边沿厚度 + } } } diff --git a/ZR.ServiceCore/Model/Dto/SysNoticeDto.cs b/ZR.ServiceCore/Model/Dto/SysNoticeDto.cs index d1683bd..5167320 100644 --- a/ZR.ServiceCore/Model/Dto/SysNoticeDto.cs +++ b/ZR.ServiceCore/Model/Dto/SysNoticeDto.cs @@ -8,13 +8,14 @@ namespace ZR.ServiceCore.Model.Dto /// public class SysNoticeDto { - public int NoticeId { get; set; } + public string NoticeId { get; set; } [Required] public string NoticeTitle { get; set; } public int NoticeType { get; set; } public string NoticeContent { get; set; } public int Status { get; set; } public string Remark { get; set; } + public DateTime Create_time { get; set; } } /// diff --git a/ZR.ServiceCore/Model/SysNotice.cs b/ZR.ServiceCore/Model/SysNotice.cs index a09e0e4..08476b4 100644 --- a/ZR.ServiceCore/Model/SysNotice.cs +++ b/ZR.ServiceCore/Model/SysNotice.cs @@ -15,8 +15,9 @@ namespace ZR.ServiceCore.Model /// /// 公告ID /// - [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "notice_id")] - public int NoticeId { get; set; } + [SugarColumn(IsPrimaryKey = true, ColumnName = "notice_id")] + [JsonConverter(typeof(ValueToStringConverter))] + public long NoticeId { get; set; } /// /// 公告标题 /// diff --git a/ZR.ServiceCore/Model/SysNoticeLog.cs b/ZR.ServiceCore/Model/SysNoticeLog.cs new file mode 100644 index 0000000..e4a1ea1 --- /dev/null +++ b/ZR.ServiceCore/Model/SysNoticeLog.cs @@ -0,0 +1,13 @@ +namespace ZR.Model.System; + +[SugarTable("sys_notice_log")] +public class SysNoticeLog +{ + [JsonConverter(typeof(ValueToStringConverter))] + public long NoticeId { get; set; } + + [JsonConverter(typeof(ValueToStringConverter))] + public long UserId { get; set; } + + public string Status { get; set; } +} \ No newline at end of file diff --git a/ZR.ServiceCore/Services/IService/ISysNoticeLogService.cs b/ZR.ServiceCore/Services/IService/ISysNoticeLogService.cs new file mode 100644 index 0000000..242067c --- /dev/null +++ b/ZR.ServiceCore/Services/IService/ISysNoticeLogService.cs @@ -0,0 +1,9 @@ +using ZR.Model.System; +using ZR.Service; + +namespace ZR.ServiceCore.Services.IService; + +public interface ISysNoticeLogService : IBaseService +{ + +} \ No newline at end of file diff --git a/ZR.ServiceCore/Services/IService/ISysRoleFieldService.cs b/ZR.ServiceCore/Services/IService/ISysRoleFieldService.cs new file mode 100644 index 0000000..f21a380 --- /dev/null +++ b/ZR.ServiceCore/Services/IService/ISysRoleFieldService.cs @@ -0,0 +1,6 @@ +namespace ZR.ServiceCore.Services.IService; + +public class ISysRoleFieldService +{ + +} \ No newline at end of file diff --git a/ZR.ServiceCore/Services/SysNoticeLogService.cs b/ZR.ServiceCore/Services/SysNoticeLogService.cs new file mode 100644 index 0000000..40aa84f --- /dev/null +++ b/ZR.ServiceCore/Services/SysNoticeLogService.cs @@ -0,0 +1,12 @@ +using Infrastructure.Attribute; +using ZR.Model.System; +using ZR.Service; +using ZR.ServiceCore.Services.IService; + +namespace ZR.ServiceCore.Services; + +[AppService(ServiceType = typeof(ISysNoticeLogService), ServiceLifetime = LifeTime.Transient)] +public class SysNoticeLogService : BaseService, ISysNoticeLogService +{ + +} \ No newline at end of file diff --git a/ZR.ServiceCore/Signalr/MessageHub.cs b/ZR.ServiceCore/Signalr/MessageHub.cs index a2b365e..a491aad 100644 --- a/ZR.ServiceCore/Signalr/MessageHub.cs +++ b/ZR.ServiceCore/Signalr/MessageHub.cs @@ -3,8 +3,14 @@ using Infrastructure.Model; using IPTools.Core; using Microsoft.AspNetCore.SignalR; using System.Web; +using Mapster; using UAParser; +using ZR.Infrastructure.Constant; +using ZR.Model.System; using ZR.Service.System.IService; +using ZR.ServiceCore.Model; +using ZR.ServiceCore.Model.Dto; +using ZR.ServiceCore.Services.IService; namespace ZR.ServiceCore.Signalr { @@ -18,10 +24,12 @@ namespace ZR.ServiceCore.Signalr public static List users = new(); //private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private readonly ISysNoticeService SysNoticeService; + private readonly ISysNoticeLogService _sysNoticeLogService; - public MessageHub(ISysNoticeService noticeService) + public MessageHub(ISysNoticeService noticeService, ISysNoticeLogService sysNoticeLogService) { SysNoticeService = noticeService; + _sysNoticeLogService = sysNoticeLogService; } private ApiResult SendNotice() @@ -68,7 +76,55 @@ namespace ZR.ServiceCore.Signalr onlineClients.Add(onlineUser); Log.WriteLine(msg: $"{name},{Context.ConnectionId}连接服务端success,当前已连接{onlineClients.Count}个"); //Clients.All.SendAsync("welcome", $"欢迎您:{name},当前时间:{DateTime.Now}"); - Clients.Caller.SendAsync(HubsConstant.MoreNotice, SendNotice()); + + var noticeRes = (List) SendNotice()[ApiResult.DATA_TAG]; + var notifications = _sysNoticeLogService.Queryable() + .Where(it => it.UserId == userid) + .ToList(); + var unreadNotificationIds = notifications + .Where(it => it.Status == SysNoticeLogStatus.Unread) + .Select(it => it.NoticeId) + .ToList(); + var readNotificationIds = notifications + .Where(it => it.Status == SysNoticeLogStatus.Read) + .Select(it => it.NoticeId) + .ToList(); + var unreadAndReadNoticeIds = unreadNotificationIds + .Union(readNotificationIds).ToList(); + + foreach (var notice in noticeRes.Select(it => it.NoticeId).ToList().Except(unreadAndReadNoticeIds)) + { + _sysNoticeLogService.Insertable(new SysNoticeLog + { + NoticeId = notice, + UserId = userid, + Status = SysNoticeLogStatus.Unread + }).ExecuteCommand(); + } + + foreach (var notice in unreadAndReadNoticeIds.Except(noticeRes.Select(it => it.NoticeId).ToList())) + { + _sysNoticeLogService.Deleteable() + .Where(it => it.UserId == userid && it.NoticeId == notice) + .ExecuteCommand(); + } + var newUnReadNotificationIds = _sysNoticeLogService + .Queryable().Where(it => it.Status == SysNoticeLogStatus.Unread && it.UserId == userid) + .Select(it => it.NoticeId) + .ToList(); + var newReadNotificationIds = _sysNoticeLogService + .Queryable().Where(it => it.Status == SysNoticeLogStatus.Read && it.UserId == userid) + .Select(it => it.NoticeId) + .ToList(); + var config = new TypeAdapterConfig(); + config.ForType() + .Map(dest => dest.NoticeId, src => src.NoticeId.ToString()); + var newUnReadNotifications = noticeRes.Where(it => + newUnReadNotificationIds.Contains(it.NoticeId)).ToList().Adapt>(config); + var newReadNotifications = noticeRes.Where(it => + newReadNotificationIds.Contains(it.NoticeId)).ToList().Adapt>(config); + Clients.Caller.SendAsync(HubsConstant.MoreNotice, newUnReadNotifications, newReadNotifications); + // Clients.Caller.SendAsync(HubsConstant.MoreNotice, SendNotice()); // Clients.Caller.SendAsync(HubsConstant.ConnId, onlineUser.ConnnectionId); } OnlineUsers userInfo = GetUserById(userid); @@ -174,6 +230,82 @@ namespace ZR.ServiceCore.Signalr Console.WriteLine($"用户{userName}对{toConnectId}-{toUserId}说:{message}"); } + /// + /// 全部标为已读 + /// + [HubMethodName("AllReadNotice")] + public async Task AllReadNotice() + { + var userId = HttpContextExtension.GetUId(App.HttpContext); + var unreadNotificationIds = await _sysNoticeLogService.Queryable() + .Where(it => it.Status == SysNoticeLogStatus.Unread && it.UserId == userId) + .Select(it => it.NoticeId) + .ToListAsync(); + foreach (var notice in unreadNotificationIds) + { + await _sysNoticeLogService.Updateable(new SysNoticeLog + { + Status = SysNoticeLogStatus.Read + }) + .IgnoreColumns(it => new { it.NoticeId, it.UserId }) + .Where(it => it.UserId == userId && it.NoticeId == notice + && it.Status == SysNoticeLogStatus.Unread) + .ExecuteCommandAsync(); + } + var newNotifications = await _sysNoticeLogService.Queryable() + .Where(it => it.UserId == userId) + .ToListAsync(); + var newUnReadNotificationIds = newNotifications + .Where(it => it.Status == SysNoticeLogStatus.Unread) + .Select(it => it.NoticeId) + .ToList(); + var newReadNotificationIds = newNotifications + .Where(it => it.Status == SysNoticeLogStatus.Read) + .Select(it => it.NoticeId) + .ToList(); + var noticeRes = (List) SendNotice()[ApiResult.DATA_TAG]; + var newUnReadNotifications = noticeRes.Where(it => + newUnReadNotificationIds.Contains(it.NoticeId)).ToList(); + var newReadNotifications = noticeRes.Where(it => + newReadNotificationIds.Contains(it.NoticeId)).ToList(); + await Clients.Caller.SendAsync(HubsConstant.MoreNotice, newUnReadNotifications, newReadNotifications); + } + + /// + /// 标记已读 + /// + /// + [HubMethodName("ReadNotice")] + public async Task ReadNotice(string noticeId) + { + var userid = HttpContextExtension.GetUId(App.HttpContext); + await _sysNoticeLogService.Updateable(new SysNoticeLog + { + Status = SysNoticeLogStatus.Read + }) + .IgnoreColumns(it => new { it.NoticeId, it.UserId }) + .Where(it => it.NoticeId == noticeId.ParseToLong() && it.UserId == userid + && it.Status == SysNoticeLogStatus.Unread) + .ExecuteCommandAsync(); + var newNotifications = await _sysNoticeLogService.Queryable() + .Where(it => it.UserId == userid) + .ToListAsync(); + var newUnReadNotificationIds = newNotifications + .Where(it => it.Status == SysNoticeLogStatus.Unread) + .Select(it => it.NoticeId) + .ToList(); + var newReadNotificationIds = newNotifications + .Where(it => it.Status == SysNoticeLogStatus.Read) + .Select(it => it.NoticeId) + .ToList(); + var noticeRes = (List) SendNotice()[ApiResult.DATA_TAG]; + var newUnReadNotifications = noticeRes.Where(it => + newUnReadNotificationIds.Contains(it.NoticeId)).ToList(); + var newReadNotifications = noticeRes.Where(it => + newReadNotificationIds.Contains(it.NoticeId)).ToList(); + await Clients.Caller.SendAsync(HubsConstant.MoreNotice, newUnReadNotifications, newReadNotifications); + } + private OnlineUsers GetUserByConnId(string connId) { return onlineClients.Where(p => p.ConnnectionId == connId).FirstOrDefault(); diff --git a/ZR.ServiceCore/SqlSugar/SqlSugarCache.cs b/ZR.ServiceCore/SqlSugar/SqlSugarCache.cs index c1e8f40..f9d5e4a 100644 --- a/ZR.ServiceCore/SqlSugar/SqlSugarCache.cs +++ b/ZR.ServiceCore/SqlSugar/SqlSugarCache.cs @@ -1,4 +1,5 @@ using ZR.Common; +using ZR.Common.Cache; namespace ZR.ServiceCore.SqlSugar { @@ -6,32 +7,32 @@ namespace ZR.ServiceCore.SqlSugar { public void Add(string key, V value) { - //RedisServer.Cache.Set(key, value, 3600 + RedisHelper.RandomExpired(5, 30)); - CacheHelper.SetCache(key, value); + RedisServer.Cache.Set(key, value, 3600 + RedisHelper.RandomExpired(5, 30)); + // CacheHelper.SetCache(key, value); } public void Add(string key, V value, int cacheDurationInSeconds) { - //RedisServer.Cache.Set(key, value, cacheDurationInSeconds); - CacheHelper.SetCaches(key, value, cacheDurationInSeconds); + RedisServer.Cache.Set(key, value, cacheDurationInSeconds); + // CacheHelper.SetCaches(key, value, cacheDurationInSeconds); } public bool ContainsKey(string key) { - //return RedisServer.Cache.Exists(key); - return CacheHelper.Exists(key); + return RedisServer.Cache.Exists(key); + // return CacheHelper.Exists(key); } public V Get(string key) { - //return RedisServer.Cache.Get(key); - return (V)CacheHelper.Get(key); + return RedisServer.Cache.Get(key); + // return (V)CacheHelper.Get(key); } public IEnumerable GetAllKey() { - //return RedisServer.Cache.Keys("*"); - return CacheHelper.GetCacheKeys(); + return RedisServer.Cache.Keys("*"); + // return CacheHelper.GetCacheKeys(); } public V GetOrCreate(string cacheKey, Func create, int cacheDurationInSeconds = int.MaxValue) @@ -59,8 +60,8 @@ namespace ZR.ServiceCore.SqlSugar public void Remove(string key) { - //RedisServer.Cache.Del(key); - CacheHelper.Remove(key); + RedisServer.Cache.Del(key); + // CacheHelper.Remove(key); } } } \ No newline at end of file