MessageHub.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using Infrastructure;
  2. using Infrastructure.Model;
  3. using Mapster;
  4. using Microsoft.AspNetCore.SignalR;
  5. using System.Collections.Concurrent;
  6. using System.Web;
  7. using ZR.Infrastructure.IPTools;
  8. using ZR.Model.Dto;
  9. using ZR.Model.Models;
  10. using ZR.ServiceCore.Monitor.IMonitorService;
  11. using ZR.ServiceCore.Services;
  12. namespace ZR.ServiceCore.Signalr
  13. {
  14. public class MessageHub : Hub
  15. {
  16. public static readonly ConcurrentDictionary<string, OnlineUsers> OnlineClients = new();
  17. private static readonly ConcurrentDictionary<long, OnlineUsers> Users = new();
  18. private readonly ISysNoticeService _sysNoticeService;
  19. private readonly ISysUserService _userService;
  20. private readonly IUserOnlineLogService _userOnlineLogService;
  21. public MessageHub(ISysNoticeService noticeService, ISysUserService userService, IUserOnlineLogService userOnlineLogService)
  22. {
  23. _sysNoticeService = noticeService;
  24. _userService = userService;
  25. _userOnlineLogService = userOnlineLogService;
  26. }
  27. private ApiResult SendNotice()
  28. {
  29. var result = _sysNoticeService.GetSysNotices();
  30. return new ApiResult(200, "success", result);
  31. }
  32. public override async Task OnConnectedAsync()
  33. {
  34. try
  35. {
  36. var context = App.HttpContext;
  37. var name = HttpContextExtension.GetName(context);
  38. var ip = HttpContextExtension.GetClientUserIp(context);
  39. var device = HttpContextExtension.GetClientInfo(context).ToString();
  40. var qs = HttpUtility.ParseQueryString(HttpContextExtension.GetQueryString(context));
  41. var from = qs.Get("from") ?? "web";
  42. var clientId = qs.Get("clientId");
  43. long userId = HttpContextExtension.GetUId(context);
  44. string uuid = $"{device}{userId}{ip}";
  45. if (!Context.User.Identity.IsAuthenticated || OnlineClients.ContainsKey(Context.ConnectionId))
  46. return;
  47. var ipInfo = IpTool.Search(ip);
  48. var onlineUser = new OnlineUsers(Context.ConnectionId, name, userId, ip, device)
  49. {
  50. Location = ipInfo?.City,
  51. Uuid = uuid,
  52. Platform = from,
  53. ClientId = clientId ?? Context.ConnectionId
  54. };
  55. OnlineClients[Context.ConnectionId] = onlineUser;
  56. var userInfo = Users.GetOrAdd(userId, _ => new OnlineUsers { Userid = userId, Name = name, LoginTime = DateTime.Now });
  57. UpdateUserOnlineTime(userInfo);
  58. await Clients.Caller.SendAsync(HubsConstant.MoreNotice, SendNotice());
  59. await Clients.All.SendAsync(HubsConstant.OnlineNum, new { num = OnlineClients.Count, OnlineClients });
  60. }
  61. catch (Exception ex)
  62. {
  63. Log.WriteLine(ConsoleColor.Red, $"OnConnectedAsync Error: {ex.Message}");
  64. }
  65. }
  66. private void UpdateUserOnlineTime(OnlineUsers userInfo)
  67. {
  68. if (userInfo.LoginTime <= DateTime.Today)
  69. {
  70. userInfo.LoginTime = DateTime.Now;
  71. userInfo.TodayOnlineTime = 0;
  72. }
  73. }
  74. public override async Task OnDisconnectedAsync(Exception exception)
  75. {
  76. if (OnlineClients.TryRemove(Context.ConnectionId, out var user))
  77. {
  78. if (Users.TryGetValue(user.Userid, out var userInfo))
  79. {
  80. userInfo.TodayOnlineTime += user.OnlineTime;
  81. await _userOnlineLogService.AddUserOnlineLog(new UserOnlineLog { TodayOnlineTime = Math.Round(userInfo.TodayOnlineTime, 2) }, user);
  82. }
  83. await Clients.All.SendAsync(HubsConstant.OnlineNum, new { num = OnlineClients.Count, OnlineClients, leaveUser = user });
  84. }
  85. }
  86. [HubMethodName("sendMessage")]
  87. public async Task SendMessage(long toUserId, string message)
  88. {
  89. try
  90. {
  91. var userName = HttpContextExtension.GetName(App.HttpContext);
  92. long userId = HttpContextExtension.GetUId(App.HttpContext);
  93. var fromUser = await _userService.GetByIdAsync(userId);
  94. var toUserConnections = OnlineClients.Values.Where(u => u.Userid == toUserId).Select(u => u.ConnnectionId).ToList();
  95. toUserConnections.Add(Context.ConnectionId);
  96. ChatMessageDto messageDto = new()
  97. {
  98. MsgType = 0,
  99. StoredKey = $"{userId}-{toUserId}",
  100. UserId = userId,
  101. ChatId = Guid.NewGuid().ToString(),
  102. ToUserId = toUserId,
  103. Message = message,
  104. Online = toUserConnections.Count > 1 ? 1 : 0,
  105. ChatTime = DateTimeHelper.GetUnixTimeSeconds(DateTime.Now),
  106. FromUser = fromUser.Adapt<ChatUserDto>()
  107. };
  108. if (messageDto.Online == 0)
  109. {
  110. await StoreOfflineMessage(messageDto);
  111. }
  112. else
  113. {
  114. await Clients.Clients(toUserConnections).SendAsync("receiveChat", messageDto);
  115. }
  116. }
  117. catch (Exception ex)
  118. {
  119. Log.WriteLine(ConsoleColor.Red, $"SendMessage Error: {ex.Message}");
  120. }
  121. }
  122. private Task StoreOfflineMessage(ChatMessageDto message)
  123. {
  124. Console.WriteLine($"Storing offline message for {message.ToUserId}");
  125. return Task.CompletedTask;
  126. }
  127. [HubMethodName("getConnId")]
  128. public string GetConnectId() => Context.ConnectionId;
  129. [HubMethodName("logOut")]
  130. public async Task LogOut()
  131. {
  132. var singleLogin = AppSettings.Get<bool>("singleLogin");
  133. long userId = HttpContextExtension.GetUId(App.HttpContext);
  134. if (singleLogin)
  135. {
  136. var connections = OnlineClients.Values.Where(u => u.Userid == userId && u.ConnnectionId != Context.ConnectionId).Select(u => u.ConnnectionId).ToList();
  137. await Clients.Clients(connections).SendAsync("logOut");
  138. }
  139. }
  140. }
  141. }