// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! using Furion.InstantMessaging; using Microsoft.AspNetCore.SignalR; namespace Admin.NET.Core; /// /// 在线用户集线器 /// [MapHub("/hubs/onlineUser")] public class OnlineUserHub : Hub { private const string GROUP_ONLINE = "GROUP_ONLINE_"; // 租户分组前缀 private readonly SysMessageService _sysMessageService; private readonly IHubContext _onlineUserHubContext; public OnlineUserHub(SysMessageService sysMessageService, IHubContext onlineUserHubContext) { _sysMessageService = sysMessageService; _onlineUserHubContext = onlineUserHubContext; } /// /// 连接 /// /// public override async Task OnConnectedAsync() { var httpContext = Context.GetHttpContext(); var userId = (httpContext.User.FindFirst(ClaimConst.UserId)?.Value).ToLong(); var account = httpContext.User.FindFirst(ClaimConst.Account)?.Value; if (userId < 0 || string.IsNullOrWhiteSpace(account)) return; var realName = httpContext.User.FindFirst(ClaimConst.RealName)?.Value; var tenantId = (httpContext.User.FindFirst(ClaimConst.TenantId)?.Value).ToLong(); var loginMode = (LoginModeEnum)(httpContext.User.FindFirst(ClaimConst.LoginMode)?.Value).ToInt(); loginMode = loginMode == 0 ? LoginModeEnum.PC : loginMode; // 默认PC登录模式 var device = httpContext.GetClientDeviceInfo().Trim(); var ipAddress = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault(); var user = new OnlineUser { ConnectionId = Context.ConnectionId, UserId = userId, UserName = account, RealName = realName, Time = DateTime.Now, Ip = string.IsNullOrWhiteSpace(ipAddress) ? httpContext.GetRemoteIpAddressToIPv4(true) : ipAddress, Browser = httpContext.GetClientBrowser(), Os = httpContext.GetClientOs(), TenantId = tenantId, LoginMode = loginMode, Device = device }; SysCacheService.HashAdd(CacheConst.KeyUserOnline, Context.ConnectionId, user); // 以租户Id进行分组 var groupName = $"{GROUP_ONLINE}{user.TenantId}"; await _onlineUserHubContext.Groups.AddToGroupAsync(Context.ConnectionId, groupName); // 更新在线用户列表 var userList = SysCacheService.HashGetAll(CacheConst.KeyUserOnline).Values.Where(u => u.TenantId == tenantId).ToList(); await _onlineUserHubContext.Clients.Groups(groupName).OnlineUserList(new OnlineUserList { RealName = user.RealName, Online = true, UserList = userList }); } /// /// 断开 /// /// /// public override async Task OnDisconnectedAsync(Exception exception) { if (string.IsNullOrEmpty(Context.ConnectionId)) return; var user = SysCacheService.HashGetOne(CacheConst.KeyUserOnline, Context.ConnectionId); if (user == null) return; SysCacheService.HashDel(CacheConst.KeyUserOnline, Context.ConnectionId); // 更新在线用户列表 var userList = SysCacheService.HashGetAll(CacheConst.KeyUserOnline).Values.Where(u => u.TenantId == user.TenantId).ToList(); await _onlineUserHubContext.Clients.Groups($"{GROUP_ONLINE}{user.TenantId}").OnlineUserList(new OnlineUserList { RealName = user.RealName, Online = false, UserList = userList }); } /// /// 强制下线 /// /// /// public async Task ForceOffline(OnlineUserHubInput input) { await _onlineUserHubContext.Clients.Client(input.ConnectionId).ForceOffline("强制下线"); } /// /// 发送信息给某人 /// /// /// public async Task SendMessageToUser(MessageInput message) { await _sysMessageService.SendUser(message); } /// /// 发送信息给所有人 /// /// /// public async Task SendMessageToAllUser(MessageInput message) { await _sysMessageService.SendAllUser(message); } }