using System.Collections.Concurrent; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; namespace F9WebAiTest.Api.Hubs; /// 在线用户登记表(用于判断用户是否在线,离线则走"拉取兜底") public static class OnlineUserRegistry { private static readonly ConcurrentDictionary _users = new(); public static void Add(long userId) => _users[userId] = 0; public static void Remove(long userId) => _users.TryRemove(userId, out _); public static bool IsOnline(long userId) => _users.ContainsKey(userId); } /// 通知推送 Hub(客户端连接后按 UserId 标识,服务端用 Clients.User(userId) 定向推送) public class NotificationHub : Hub { public override async Task OnConnectedAsync() { var userId = GetUserId(); if (userId > 0) OnlineUserRegistry.Add(userId); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception exception) { var userId = GetUserId(); if (userId > 0) OnlineUserRegistry.Remove(userId); await base.OnDisconnectedAsync(exception); } private long GetUserId() { var raw = Context.User?.FindFirst("id")?.Value; return long.TryParse(raw, out var id) ? id : 0; } } /// 自定义用户标识:使用 JWT 中的 "id" 声明作为 SignalR 的 UserIdentifier public class NotificationUserIdProvider : IUserIdProvider { public string GetUserId(HubConnectionContext connection) => connection.User?.FindFirst("id")?.Value ?? connection.ConnectionId; }