Files
frontend/src/stores/message/services/UserCacheService.ts
lafay 94c11062f0
Some checks failed
Frontend CI / ota-android (push) Successful in 11m15s
Frontend CI / build-and-push-web (push) Successful in 29m13s
Frontend CI / build-android-apk (push) Has been cancelled
refactor(message): replace MessageStateManager with zustand store
- Remove MessageStateManager wrapper layer in favor of direct zustand store
- Move service modules to services/ subdirectory (ConversationOperations, MessageDeduplication, MessageSendService, MessageSyncService, ReadReceiptManager, UserCacheService, WSMessageHandler)
- Add new zustand-based store with subscriptionManager for event handling
- Introduce React hooks for message state (useConversations, useMessages, useUnreadCount, etc.)
- Update exports in index.ts to reflect new module structure
- Deprecate messageManager.ts entry point in favor of message/index.ts
- Maintain backward compatibility with existing MessageManager API
2026-03-31 18:22:24 +08:00

119 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 用户信息缓存服务
* 管理用户信息的缓存和获取
*/
import type { MessageResponse, UserDTO } from '../../../types/dto';
import { api } from '../../../services/api';
import { getUserCache, saveUserCache } from '../../../services/database';
import type { IUserCacheService } from '../types';
export class UserCacheService implements IUserCacheService {
// 正在获取用户信息的请求映射(用于去重)
private pendingUserRequests: Map<string, Promise<UserDTO | null>> = new Map();
/**
* 获取用户信息(带缓存和去重)
*/
async getSenderInfo(userId: string): Promise<UserDTO | null> {
// 1. 先检查本地缓存
const cachedUser = await getUserCache(userId);
if (cachedUser) {
return cachedUser;
}
// 2. 检查是否已有正在进行的请求
const pendingRequest = this.pendingUserRequests.get(userId);
if (pendingRequest) {
return pendingRequest;
}
// 3. 发起新请求
const request = this.fetchUserInfo(userId);
this.pendingUserRequests.set(userId, request);
try {
const user = await request;
return user;
} finally {
// 请求完成后清理
this.pendingUserRequests.delete(userId);
}
}
/**
* 从服务器获取用户信息
*/
private async fetchUserInfo(userId: string): Promise<UserDTO | null> {
try {
const response = await api.get<UserDTO>(`/users/${userId}`);
if (response.code === 0 && response.data) {
// 缓存到本地数据库
await saveUserCache(response.data);
return response.data;
}
return null;
} catch (error) {
console.error(`[UserCacheService] 获取用户信息失败: ${userId}`, error);
return null;
}
}
/**
* 批量异步填充消息的 sender 信息
* 填充完成后调用 notifyUpdate 更新内存并通知订阅者
*/
enrichMessagesWithSenderInfo(
conversationId: string,
messages: MessageResponse[],
notifyUpdate: (conversationId: string, messages: MessageResponse[]) => void
): void {
// 收集所有需要查询的唯一 sender_id排除系统用户
const senderIds = [...new Set(
messages
.filter(m => m.sender_id && m.sender_id !== '10000' && !m.sender)
.map(m => m.sender_id)
)];
if (senderIds.length === 0) return;
// 并发获取所有 sender 信息
Promise.all(senderIds.map(id => this.getSenderInfo(id).then(user => ({ id, user }))))
.then(results => {
const senderMap = new Map<string, UserDTO>();
results.forEach(({ id, user }) => {
if (user) senderMap.set(id, user);
});
if (senderMap.size === 0) return;
let changed = false;
const updated = messages.map(m => {
if (!m.sender && m.sender_id && senderMap.has(m.sender_id)) {
changed = true;
return { ...m, sender: senderMap.get(m.sender_id) };
}
return m;
});
if (!changed) return;
// 调用回调通知更新
notifyUpdate(conversationId, updated);
})
.catch(error => {
console.error('[UserCacheService] 批量获取 sender 信息失败:', error);
});
}
/**
* 清除所有待处理的请求
* 用于测试或需要重置的场景
*/
reset(): void {
this.pendingUserRequests.clear();
}
}
// 单例导出
export const userCacheService = new UserCacheService();