using Infrastructure; 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 { /// /// msghub /// public class MessageHub : Hub { //创建用户集合,用于存储所有链接的用户数据 public static readonly List onlineClients = new(); 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, ISysNoticeLogService sysNoticeLogService) { SysNoticeService = noticeService; _sysNoticeLogService = sysNoticeLogService; } private ApiResult SendNotice() { var result = SysNoticeService.GetSysNotices(); return new ApiResult(200, "success", result); } #region 客户端连接 /// /// 客户端连接的时候调用 /// /// public override Task OnConnectedAsync() { var context = App.HttpContext; var name = HttpContextExtension.GetName(context); var ip = HttpContextExtension.GetClientUserIp(context); var ip_info = IpTool.Search(ip); ClientInfo clientInfo = HttpContextExtension.GetClientInfo(context); string device = clientInfo.ToString(); string qs = HttpContextExtension.GetQueryString(context); var query = HttpUtility.ParseQueryString(qs); string from = query.Get("from") ?? "web"; string clientId = query.Get("clientId"); long userid = HttpContextExtension.GetUId(context); string uuid = device + userid + ip; var user = onlineClients.Any(u => u.ConnnectionId == Context.ConnectionId); var user2 = onlineClients.Any(u => u.Uuid == uuid); //判断用户是否存在,否则添加集合!user2 && !user && if (!user2 && !user && Context.User.Identity.IsAuthenticated) { OnlineUsers onlineUser = new(Context.ConnectionId, name, userid, ip, device) { Location = ip_info.City, Uuid = uuid, Platform = from, ClientId = clientId ?? Context.ConnectionId }; onlineClients.Add(onlineUser); Log.WriteLine(msg: $"{name},{Context.ConnectionId}连接服务端success,当前已连接{onlineClients.Count}个"); //Clients.All.SendAsync("welcome", $"欢迎您:{name},当前时间:{DateTime.Now}"); 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); if (userInfo == null) { userInfo = new OnlineUsers() { Userid = userid, Name = name, LoginTime = DateTime.Now }; users.Add(userInfo); } else { if (userInfo.LoginTime <= Convert.ToDateTime(DateTime.Now.ToShortDateString())) { userInfo.LoginTime = DateTime.Now; userInfo.TodayOnlineTime = 0; } var clientUser = onlineClients.Find(x => x.Userid == userid); userInfo.TodayOnlineTime += Math.Round(clientUser?.OnlineTime ?? 0, 2); } //给当前所有登录当前账号的用户下发登录时长 var connIds = onlineClients.Where(f => f.Userid == userid).ToList(); userInfo.ClientNum = connIds.Count; // Clients.Clients(connIds.Select(f => f.ConnnectionId)).SendAsync("onlineInfo", userInfo); Log.WriteLine(ConsoleColor.Blue, msg: $"用户{name}已连接,今日已在线{userInfo?.TodayOnlineTime}分钟,当前已连接{onlineClients.Count}个"); //给所有用户更新在线人数 Clients.All.SendAsync(HubsConstant.OnlineNum, new { num = onlineClients.Count, onlineClients }); return base.OnConnectedAsync(); } /// /// 连接终止时调用。 /// /// public override Task OnDisconnectedAsync(Exception exception) { var user = onlineClients.Where(p => p.ConnnectionId == Context.ConnectionId).FirstOrDefault(); if (user != null) { onlineClients.Remove(user); //给所有用户更新在线人数 Clients.All.SendAsync(HubsConstant.OnlineNum, new { num = onlineClients.Count, onlineClients, leaveUser = user }); //累计用户时长 OnlineUsers userInfo = GetUserById(user.Userid); if (userInfo != null) { userInfo.TodayOnlineTime += user?.OnlineTime ?? 0; } Log.WriteLine(ConsoleColor.Red, msg: $"用户{user?.Name}离开了,已在线{userInfo?.TodayOnlineTime}分,当前已连接{onlineClients.Count}个"); } return base.OnDisconnectedAsync(exception); } #endregion /// /// 发送信息 /// /// 对方链接id /// /// /// [HubMethodName("sendMessage")] public async Task SendMessage(string toConnectId, long toUserId, string message) { var userName = HttpContextExtension.GetName(App.HttpContext); long userid = HttpContextExtension.GetUId(App.HttpContext); var toUserList = onlineClients.Where(p => p.Userid == toUserId); var toUserInfo = toUserList.FirstOrDefault(); IList sendToUser = toUserList.Select(x => x.ConnnectionId).ToList(); sendToUser.Add(GetConnectId()); if (toUserInfo != null) { await Clients.Clients(sendToUser) .SendAsync("receiveChat", new { msgType = 0,//文本 chatid = Guid.NewGuid().ToString(), userName, userid, toUserName = toUserInfo.Name, toUserid = toUserInfo.Userid, message, chatTime = DateTime.Now }); } else { //TODO 存储离线消息 Console.WriteLine($"{toUserId}不在线"); } 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(); } private static OnlineUsers GetUserById(long userid) { return users.Where(f => f.Userid == userid).FirstOrDefault(); } /// /// 移动端使用获取链接id /// /// [HubMethodName("getConnId")] public string GetConnectId() { return Context.ConnectionId; } /// /// 退出其他设备登录 /// /// [HubMethodName("logOut")] public async Task LogOut() { var singleLogin = AppSettings.Get("singleLogin"); long userid = HttpContextExtension.GetUId(App.HttpContext); if (singleLogin) { var onlineUsers = onlineClients.Where(p => p.ConnnectionId != Context.ConnectionId && p.Userid == userid); await Clients.Clients(onlineUsers.Select(x => x.ConnnectionId)) .SendAsync("logOut"); } } } }