feat: 初始化 ChatOA 企业协作 OA 系统

This commit is contained in:
2026-08-20 19:36:07 +08:00
commit 6d7a1f6e63
90 changed files with 20067 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
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<string, Presence>();
/** userId -> Set<socketId>,同一用户多端登录 */
private readonly sockets = new Map<string, Set<string>>();
markOnline(userId: string, socketId: string) {
const set = this.sockets.get(userId) ?? new Set<string>();
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()];
}
}