import { Injectable } from '@nestjs/common'; export interface Presence { userId: string; online: boolean; lastSeen: number; } /** * 在线状态管理:开发期使用内存 Map(可分布式广播)。 * 后续接入 Redis 时替换为 Redis Hash + Pub/Sub 实现,接口保持一致。 */ @Injectable() export class PresenceService { private readonly map = new Map(); /** userId -> Set,同一用户多端登录 */ private readonly sockets = new Map>(); markOnline(userId: string, socketId: string) { const set = this.sockets.get(userId) ?? new Set(); set.add(socketId); this.sockets.set(userId, set); const p: Presence = { userId, online: true, lastSeen: Date.now() }; this.map.set(userId, p); return p; } markOffline(userId: string, socketId: string): Presence | null { const set = this.sockets.get(userId); if (set) { set.delete(socketId); if (set.size > 0) return this.map.get(userId) ?? null; this.sockets.delete(userId); } const p: Presence = { userId, online: false, lastSeen: Date.now() }; this.map.set(userId, p); return p; } get(userId: string): Presence { return this.map.get(userId) ?? { userId, online: false, lastSeen: 0 }; } getAll(): Presence[] { return [...this.map.values()]; } }