Initial Commit

This commit is contained in:
Rajuahamedkst 2025-09-12 16:08:17 +08:00
commit 1d71a02738
237 changed files with 64293 additions and 0 deletions

View file

@ -0,0 +1,671 @@
// 消息历史记录管理器 - 微信小程序专用
// 处理消息历史记录的本地缓存、分页加载、存储优化等
const apiClient = require('./api-client.js');
/**
* 消息历史记录管理器
* 功能
* 1. 消息历史记录缓存
* 2. 分页加载优化
* 3. 存储空间管理
* 4. 消息去重和排序
* 5. 离线消息处理
* 6. 数据压缩存储
*/
class MessageHistoryManager {
constructor() {
this.isInitialized = false;
// 历史记录配置
this.historyConfig = {
// 每页消息数量
pageSize: 20,
// 本地缓存的最大消息数量(每个会话)
maxCachedMessages: 500,
// 缓存过期时间(毫秒)
cacheExpireTime: 24 * 60 * 60 * 1000, // 24小时
// 存储压缩阈值(字节)
compressionThreshold: 1024,
// 自动清理间隔(毫秒)
cleanupInterval: 60 * 60 * 1000, // 1小时
// 预加载页数
preloadPages: 2
};
// 消息缓存 Map<conversationId, MessageCache>
this.messageCache = new Map();
// 加载状态 Map<conversationId, LoadingState>
this.loadingStates = new Map();
// 存储统计
this.storageStats = {
totalSize: 0,
messageCount: 0,
conversationCount: 0,
lastCleanup: 0
};
// 清理定时器
this.cleanupTimer = null;
this.init();
}
// 初始化历史记录管理器
async init() {
if (this.isInitialized) return;
console.log('📚 初始化消息历史记录管理器...');
try {
// 加载缓存的消息
await this.loadCachedMessages();
// 计算存储统计
this.calculateStorageStats();
// 启动定时清理
this.startCleanupTimer();
this.isInitialized = true;
console.log('✅ 消息历史记录管理器初始化完成');
} catch (error) {
console.error('❌ 消息历史记录管理器初始化失败:', error);
}
}
// 获取会话消息历史
async getConversationHistory(conversationId, options = {}) {
try {
console.log('📚 获取会话消息历史:', conversationId);
const {
page = 1,
pageSize = this.historyConfig.pageSize,
forceRefresh = false,
loadDirection = 'up' // 'up' 向上加载更早的消息, 'down' 向下加载更新的消息
} = options;
// 获取或创建消息缓存
let messageCache = this.getMessageCache(conversationId);
if (!messageCache) {
messageCache = this.createMessageCache(conversationId);
}
// 检查是否需要从服务器加载
const needServerLoad = forceRefresh ||
this.shouldLoadFromServer(messageCache, page, pageSize, loadDirection);
if (needServerLoad) {
// 从服务器加载消息
const serverResult = await this.loadMessagesFromServer(
conversationId,
page,
pageSize,
loadDirection,
messageCache
);
if (!serverResult.success) {
return serverResult;
}
}
// 从缓存获取消息
const messages = this.getMessagesFromCache(messageCache, page, pageSize, loadDirection);
return {
success: true,
data: {
messages: messages,
page: page,
pageSize: pageSize,
total: messageCache.totalCount,
hasMore: this.hasMoreMessages(messageCache, page, pageSize, loadDirection),
cached: !needServerLoad
}
};
} catch (error) {
console.error('❌ 获取会话消息历史失败:', error);
return { success: false, error: error.message };
}
}
// 预加载消息
async preloadMessages(conversationId, currentPage = 1) {
try {
console.log('📚 预加载消息:', conversationId);
const preloadPromises = [];
// 预加载后续页面
for (let i = 1; i <= this.historyConfig.preloadPages; i++) {
const nextPage = currentPage + i;
preloadPromises.push(
this.getConversationHistory(conversationId, {
page: nextPage,
loadDirection: 'up'
})
);
}
// 并行执行预加载
await Promise.allSettled(preloadPromises);
console.log('✅ 消息预加载完成');
} catch (error) {
console.error('❌ 消息预加载失败:', error);
}
}
// 添加新消息到缓存
addMessageToCache(conversationId, message) {
try {
let messageCache = this.getMessageCache(conversationId);
if (!messageCache) {
messageCache = this.createMessageCache(conversationId);
}
// 检查消息是否已存在
const existingIndex = messageCache.messages.findIndex(m => m.id === message.id);
if (existingIndex !== -1) {
// 更新现有消息
messageCache.messages[existingIndex] = message;
} else {
// 添加新消息(按时间排序)
const insertIndex = this.findInsertIndex(messageCache.messages, message);
messageCache.messages.splice(insertIndex, 0, message);
messageCache.totalCount++;
}
// 限制缓存大小
this.limitCacheSize(messageCache);
// 更新缓存时间
messageCache.lastUpdated = Date.now();
// 保存到本地存储
this.saveMessageCache(conversationId, messageCache);
console.log('📚 消息已添加到缓存:', message.id);
} catch (error) {
console.error('❌ 添加消息到缓存失败:', error);
}
}
// 更新消息状态
updateMessageInCache(conversationId, messageId, updates) {
try {
const messageCache = this.getMessageCache(conversationId);
if (!messageCache) return false;
const messageIndex = messageCache.messages.findIndex(m => m.id === messageId);
if (messageIndex === -1) return false;
// 更新消息
messageCache.messages[messageIndex] = {
...messageCache.messages[messageIndex],
...updates
};
// 更新缓存时间
messageCache.lastUpdated = Date.now();
// 保存到本地存储
this.saveMessageCache(conversationId, messageCache);
console.log('📚 消息状态已更新:', messageId);
return true;
} catch (error) {
console.error('❌ 更新消息状态失败:', error);
return false;
}
}
// 删除消息
deleteMessageFromCache(conversationId, messageId) {
try {
const messageCache = this.getMessageCache(conversationId);
if (!messageCache) return false;
const messageIndex = messageCache.messages.findIndex(m => m.id === messageId);
if (messageIndex === -1) return false;
// 删除消息
messageCache.messages.splice(messageIndex, 1);
messageCache.totalCount--;
// 更新缓存时间
messageCache.lastUpdated = Date.now();
// 保存到本地存储
this.saveMessageCache(conversationId, messageCache);
console.log('📚 消息已从缓存删除:', messageId);
return true;
} catch (error) {
console.error('❌ 删除消息失败:', error);
return false;
}
}
// 从服务器加载消息
async loadMessagesFromServer(conversationId, page, pageSize, loadDirection, messageCache) {
try {
// 设置加载状态
this.setLoadingState(conversationId, true);
// 计算请求参数
const requestParams = this.calculateRequestParams(
messageCache,
page,
pageSize,
loadDirection
);
// 调用API
const response = await apiClient.request({
url: '/api/v1/messages/history',
method: 'GET',
data: {
conversationId: conversationId,
...requestParams
}
});
if (response.success) {
// 处理返回的消息
const messages = response.data.messages || [];
const total = response.data.total || 0;
// 更新缓存
this.updateCacheWithServerData(messageCache, messages, total, loadDirection);
// 保存到本地存储
this.saveMessageCache(conversationId, messageCache);
console.log(`📚 从服务器加载了 ${messages.length} 条消息`);
return { success: true };
} else {
throw new Error(response.error || '加载消息失败');
}
} catch (error) {
console.error('❌ 从服务器加载消息失败:', error);
return { success: false, error: error.message };
} finally {
this.setLoadingState(conversationId, false);
}
}
// 计算请求参数
calculateRequestParams(messageCache, page, pageSize, loadDirection) {
const params = {
pageSize: pageSize
};
if (loadDirection === 'up') {
// 向上加载更早的消息
if (messageCache.messages.length > 0) {
const oldestMessage = messageCache.messages[messageCache.messages.length - 1];
params.beforeTimestamp = oldestMessage.timestamp;
}
} else {
// 向下加载更新的消息
if (messageCache.messages.length > 0) {
const newestMessage = messageCache.messages[0];
params.afterTimestamp = newestMessage.timestamp;
}
}
return params;
}
// 更新缓存数据
updateCacheWithServerData(messageCache, newMessages, total, loadDirection) {
if (loadDirection === 'up') {
// 向上加载:添加到数组末尾(更早的消息)
messageCache.messages.push(...newMessages);
} else {
// 向下加载:添加到数组开头(更新的消息)
messageCache.messages.unshift(...newMessages);
}
// 去重和排序
this.deduplicateAndSortMessages(messageCache);
// 更新总数
messageCache.totalCount = Math.max(total, messageCache.messages.length);
// 限制缓存大小
this.limitCacheSize(messageCache);
// 更新时间戳
messageCache.lastUpdated = Date.now();
}
// 消息去重和排序
deduplicateAndSortMessages(messageCache) {
// 去重
const uniqueMessages = new Map();
messageCache.messages.forEach(message => {
uniqueMessages.set(message.id, message);
});
// 排序(最新的在前面)
messageCache.messages = Array.from(uniqueMessages.values())
.sort((a, b) => b.timestamp - a.timestamp);
}
// 查找插入位置
findInsertIndex(messages, newMessage) {
for (let i = 0; i < messages.length; i++) {
if (newMessage.timestamp > messages[i].timestamp) {
return i;
}
}
return messages.length;
}
// 限制缓存大小
limitCacheSize(messageCache) {
if (messageCache.messages.length > this.historyConfig.maxCachedMessages) {
// 保留最新的消息
const keepCount = Math.floor(this.historyConfig.maxCachedMessages * 0.8);
messageCache.messages = messageCache.messages.slice(0, keepCount);
console.log(`📚 缓存大小已限制到 ${keepCount} 条消息`);
}
}
// 获取消息缓存
getMessageCache(conversationId) {
return this.messageCache.get(conversationId);
}
// 创建消息缓存
createMessageCache(conversationId) {
const cache = {
conversationId: conversationId,
messages: [],
totalCount: 0,
lastUpdated: Date.now(),
loadedPages: new Set(),
hasMoreUp: true,
hasMoreDown: false
};
this.messageCache.set(conversationId, cache);
return cache;
}
// 从缓存获取消息
getMessagesFromCache(messageCache, page, pageSize, loadDirection) {
const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize;
return messageCache.messages.slice(startIndex, endIndex);
}
// 检查是否有更多消息
hasMoreMessages(messageCache, page, pageSize, loadDirection) {
if (loadDirection === 'up') {
return messageCache.hasMoreUp &&
(page * pageSize) < messageCache.totalCount;
} else {
return messageCache.hasMoreDown;
}
}
// 检查是否需要从服务器加载
shouldLoadFromServer(messageCache, page, pageSize, loadDirection) {
// 如果缓存为空,需要加载
if (messageCache.messages.length === 0) {
return true;
}
// 如果请求的页面超出缓存范围,需要加载
const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize;
if (endIndex > messageCache.messages.length && messageCache.hasMoreUp) {
return true;
}
// 如果缓存过期,需要刷新
const cacheAge = Date.now() - messageCache.lastUpdated;
if (cacheAge > this.historyConfig.cacheExpireTime) {
return true;
}
return false;
}
// 设置加载状态
setLoadingState(conversationId, loading) {
this.loadingStates.set(conversationId, {
loading: loading,
timestamp: Date.now()
});
}
// 获取加载状态
getLoadingState(conversationId) {
const state = this.loadingStates.get(conversationId);
return state ? state.loading : false;
}
// 保存消息缓存到本地存储
saveMessageCache(conversationId, messageCache) {
try {
const cacheKey = `message_cache_${conversationId}`;
const cacheData = this.compressMessageCache(messageCache);
wx.setStorageSync(cacheKey, cacheData);
} catch (error) {
console.error('❌ 保存消息缓存失败:', error);
}
}
// 加载缓存的消息
async loadCachedMessages() {
try {
const storageInfo = wx.getStorageInfoSync();
const cacheKeys = storageInfo.keys.filter(key => key.startsWith('message_cache_'));
for (const key of cacheKeys) {
try {
const conversationId = key.replace('message_cache_', '');
const cacheData = wx.getStorageSync(key);
if (cacheData) {
const messageCache = this.decompressMessageCache(cacheData);
this.messageCache.set(conversationId, messageCache);
}
} catch (error) {
console.error(`❌ 加载缓存失败 [${key}]:`, error);
// 删除损坏的缓存
wx.removeStorageSync(key);
}
}
console.log(`📚 加载了 ${this.messageCache.size} 个会话的消息缓存`);
} catch (error) {
console.error('❌ 加载缓存消息失败:', error);
}
}
// 压缩消息缓存
compressMessageCache(messageCache) {
try {
const data = JSON.stringify(messageCache);
// 如果数据较大,可以考虑压缩
if (data.length > this.historyConfig.compressionThreshold) {
// 这里可以实现压缩算法
// 目前直接返回原数据
return { compressed: false, data: messageCache };
}
return { compressed: false, data: messageCache };
} catch (error) {
console.error('❌ 压缩消息缓存失败:', error);
return { compressed: false, data: messageCache };
}
}
// 解压消息缓存
decompressMessageCache(cacheData) {
try {
if (cacheData.compressed) {
// 这里可以实现解压算法
return cacheData.data;
}
return cacheData.data;
} catch (error) {
console.error('❌ 解压消息缓存失败:', error);
return null;
}
}
// 计算存储统计
calculateStorageStats() {
let totalSize = 0;
let messageCount = 0;
for (const [conversationId, cache] of this.messageCache) {
messageCount += cache.messages.length;
// 估算缓存大小
const cacheSize = JSON.stringify(cache).length;
totalSize += cacheSize;
}
this.storageStats = {
totalSize: totalSize,
messageCount: messageCount,
conversationCount: this.messageCache.size,
lastCleanup: Date.now()
};
}
// 启动定时清理
startCleanupTimer() {
if (this.cleanupTimer) {
clearInterval(this.cleanupTimer);
}
this.cleanupTimer = setInterval(() => {
this.performCleanup();
}, this.historyConfig.cleanupInterval);
}
// 执行清理
performCleanup() {
try {
console.log('📚 执行消息缓存清理...');
const now = Date.now();
let cleanedCount = 0;
for (const [conversationId, cache] of this.messageCache) {
// 清理过期缓存
const cacheAge = now - cache.lastUpdated;
if (cacheAge > this.historyConfig.cacheExpireTime * 2) {
this.messageCache.delete(conversationId);
wx.removeStorageSync(`message_cache_${conversationId}`);
cleanedCount++;
}
}
// 更新统计
this.calculateStorageStats();
console.log(`📚 清理完成,删除了 ${cleanedCount} 个过期缓存`);
} catch (error) {
console.error('❌ 消息缓存清理失败:', error);
}
}
// 清除会话缓存
clearConversationCache(conversationId) {
this.messageCache.delete(conversationId);
wx.removeStorageSync(`message_cache_${conversationId}`);
console.log('📚 已清除会话缓存:', conversationId);
}
// 清除所有缓存
clearAllCache() {
for (const conversationId of this.messageCache.keys()) {
wx.removeStorageSync(`message_cache_${conversationId}`);
}
this.messageCache.clear();
this.calculateStorageStats();
console.log('📚 已清除所有消息缓存');
}
// 获取存储统计
getStorageStats() {
this.calculateStorageStats();
return { ...this.storageStats };
}
// 获取会话统计
getConversationStats(conversationId) {
const cache = this.getMessageCache(conversationId);
if (!cache) {
return null;
}
return {
messageCount: cache.messages.length,
totalCount: cache.totalCount,
lastUpdated: cache.lastUpdated,
cacheAge: Date.now() - cache.lastUpdated,
hasMoreUp: cache.hasMoreUp,
hasMoreDown: cache.hasMoreDown
};
}
// 重置管理器
reset() {
this.clearAllCache();
this.loadingStates.clear();
if (this.cleanupTimer) {
clearInterval(this.cleanupTimer);
this.cleanupTimer = null;
}
}
// 销毁管理器
destroy() {
this.reset();
this.isInitialized = false;
}
}
// 创建全局实例
const messageHistoryManager = new MessageHistoryManager();
module.exports = messageHistoryManager;