// 消息搜索管理器 - 微信小程序专用 // 处理消息搜索、历史记录管理、本地缓存等 const apiClient = require('./api-client.js'); /** * 消息搜索管理器 * 功能: * 1. 全局消息搜索 * 2. 会话内搜索 * 3. 搜索结果高亮 * 4. 搜索历史管理 * 5. 本地缓存优化 * 6. 分页加载 */ class MessageSearchManager { constructor() { this.isInitialized = false; // 搜索配置 this.searchConfig = { // 最小搜索关键词长度 minKeywordLength: 1, // 搜索结果每页数量 pageSize: 20, // 最大搜索历史数量 maxSearchHistory: 50, // 本地缓存过期时间(毫秒) cacheExpireTime: 30 * 60 * 1000, // 30分钟 // 搜索防抖延迟(毫秒) debounceDelay: 300, // 支持的搜索类型 searchTypes: ['text', 'image', 'file', 'all'] }; // 搜索缓存 this.searchCache = new Map(); // 搜索历史 this.searchHistory = []; // 当前搜索状态 this.currentSearch = { keyword: '', type: 'all', conversationId: null, page: 1, hasMore: true, loading: false, results: [] }; // 防抖定时器 this.debounceTimer = null; this.init(); } // 初始化搜索管理器 async init() { if (this.isInitialized) return; console.log('🔍 初始化消息搜索管理器...'); try { // 加载搜索历史 await this.loadSearchHistory(); // 清理过期缓存 this.cleanupExpiredCache(); this.isInitialized = true; console.log('✅ 消息搜索管理器初始化完成'); } catch (error) { console.error('❌ 消息搜索管理器初始化失败:', error); } } // 全局搜索消息 async searchMessages(keyword, options = {}) { try { // 验证搜索关键词 if (!this.validateKeyword(keyword)) { return { success: false, error: '搜索关键词无效' }; } console.log('🔍 搜索消息:', keyword); // 设置搜索参数 const searchParams = { keyword: keyword.trim(), type: options.type || 'all', conversationId: options.conversationId || null, page: options.page || 1, pageSize: options.pageSize || this.searchConfig.pageSize }; // 检查缓存 const cacheKey = this.generateCacheKey(searchParams); const cachedResult = this.getFromCache(cacheKey); if (cachedResult) { console.log('🔍 使用缓存搜索结果'); return cachedResult; } // 更新搜索状态 this.updateSearchState(searchParams); // 执行搜索 const result = await this.performSearch(searchParams); // 缓存结果 if (result.success) { this.saveToCache(cacheKey, result); // 添加到搜索历史 this.addToSearchHistory(keyword); } return result; } catch (error) { console.error('❌ 搜索消息失败:', error); return { success: false, error: error.message }; } } // 会话内搜索 async searchInConversation(conversationId, keyword, options = {}) { return await this.searchMessages(keyword, { ...options, conversationId: conversationId }); } // 防抖搜索 searchWithDebounce(keyword, options = {}, callback) { // 清除之前的定时器 if (this.debounceTimer) { clearTimeout(this.debounceTimer); } // 设置新的定时器 this.debounceTimer = setTimeout(async () => { try { const result = await this.searchMessages(keyword, options); if (callback) { callback(result); } } catch (error) { console.error('❌ 防抖搜索失败:', error); if (callback) { callback({ success: false, error: error.message }); } } }, this.searchConfig.debounceDelay); } // 执行搜索 async performSearch(searchParams) { try { this.currentSearch.loading = true; // 构建搜索请求 const requestData = { keyword: searchParams.keyword, messageType: searchParams.type === 'all' ? null : this.getMessageTypeCode(searchParams.type), page: searchParams.page, pageSize: searchParams.pageSize }; // 如果指定了会话ID,则进行会话内搜索 if (searchParams.conversationId) { requestData.conversationId = searchParams.conversationId; } // 调用搜索API(按统一客户端签名) const response = await apiClient.post('/api/v1/messages/search', requestData); if (response && (response.code === 0 || response.code === 200 || response.success)) { const searchResult = { success: true, data: { messages: response.data?.messages || [], total: response.data?.total || 0, page: searchParams.page, pageSize: searchParams.pageSize, hasMore: response.data?.hasMore || false, keyword: searchParams.keyword, searchTime: Date.now() } }; // 处理搜索结果 searchResult.data.messages = this.processSearchResults( searchResult.data.messages, searchParams.keyword ); console.log(`🔍 搜索完成,找到 ${searchResult.data.total} 条消息`); return searchResult; } else { const msg = response?.message || response?.error || '搜索失败'; throw new Error(msg); } } catch (error) { console.error('❌ 执行搜索失败:', error); return { success: false, error: error.message }; } finally { this.currentSearch.loading = false; } } // 处理搜索结果 processSearchResults(messages, keyword) { return messages.map(message => { // 添加高亮信息 const highlightedContent = this.highlightKeyword(message.content, keyword); return { ...message, highlightedContent: highlightedContent, searchKeyword: keyword, // 添加消息摘要(用于显示上下文) summary: this.generateMessageSummary(message.content, keyword) }; }); } // 关键词高亮 highlightKeyword(content, keyword) { if (!content || !keyword) return content; try { // 转义特殊字符 const escapedKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const regex = new RegExp(`(${escapedKeyword})`, 'gi'); return content.replace(regex, '$1'); } catch (error) { console.error('❌ 关键词高亮失败:', error); return content; } } // 生成消息摘要 generateMessageSummary(content, keyword, maxLength = 100) { if (!content || !keyword) return content; try { const keywordIndex = content.toLowerCase().indexOf(keyword.toLowerCase()); if (keywordIndex === -1) return content.substring(0, maxLength); // 计算摘要范围 const start = Math.max(0, keywordIndex - 30); const end = Math.min(content.length, keywordIndex + keyword.length + 30); let summary = content.substring(start, end); // 添加省略号 if (start > 0) summary = '...' + summary; if (end < content.length) summary = summary + '...'; return summary; } catch (error) { console.error('❌ 生成消息摘要失败:', error); return content.substring(0, maxLength); } } // 加载更多搜索结果 async loadMoreResults() { if (!this.currentSearch.hasMore || this.currentSearch.loading) { return { success: false, error: '没有更多结果' }; } const nextPage = this.currentSearch.page + 1; const result = await this.searchMessages(this.currentSearch.keyword, { type: this.currentSearch.type, conversationId: this.currentSearch.conversationId, page: nextPage }); if (result.success) { // 合并结果 this.currentSearch.results = [...this.currentSearch.results, ...result.data.messages]; this.currentSearch.page = nextPage; this.currentSearch.hasMore = result.data.hasMore; } return result; } // 清除搜索结果 clearSearchResults() { this.currentSearch = { keyword: '', type: 'all', conversationId: null, page: 1, hasMore: true, loading: false, results: [] }; } // 验证搜索关键词 validateKeyword(keyword) { if (!keyword || typeof keyword !== 'string') { return false; } const trimmedKeyword = keyword.trim(); return trimmedKeyword.length >= this.searchConfig.minKeywordLength; } // 获取消息类型代码 getMessageTypeCode(type) { const typeMap = { 'text': 0, 'image': 1, 'voice': 2, 'video': 3, 'file': 4 }; return typeMap[type] || null; } // 更新搜索状态 updateSearchState(searchParams) { this.currentSearch = { keyword: searchParams.keyword, type: searchParams.type, conversationId: searchParams.conversationId, page: searchParams.page, hasMore: true, loading: true, results: [] }; } // 生成缓存键 generateCacheKey(searchParams) { return `search_${searchParams.keyword}_${searchParams.type}_${searchParams.conversationId || 'global'}_${searchParams.page}`; } // 从缓存获取 getFromCache(cacheKey) { const cached = this.searchCache.get(cacheKey); if (cached && (Date.now() - cached.timestamp) < this.searchConfig.cacheExpireTime) { return cached.data; } return null; } // 保存到缓存 saveToCache(cacheKey, data) { this.searchCache.set(cacheKey, { data: data, timestamp: Date.now() }); // 限制缓存大小 if (this.searchCache.size > 100) { const firstKey = this.searchCache.keys().next().value; this.searchCache.delete(firstKey); } } // 清理过期缓存 cleanupExpiredCache() { const now = Date.now(); for (const [key, value] of this.searchCache) { if (now - value.timestamp > this.searchConfig.cacheExpireTime) { this.searchCache.delete(key); } } } // 添加到搜索历史 addToSearchHistory(keyword) { const trimmedKeyword = keyword.trim(); if (!trimmedKeyword) return; // 移除重复项 this.searchHistory = this.searchHistory.filter(item => item !== trimmedKeyword); // 添加到开头 this.searchHistory.unshift(trimmedKeyword); // 限制历史数量 if (this.searchHistory.length > this.searchConfig.maxSearchHistory) { this.searchHistory = this.searchHistory.slice(0, this.searchConfig.maxSearchHistory); } // 保存到本地存储 this.saveSearchHistory(); } // 获取搜索历史 getSearchHistory() { return [...this.searchHistory]; } // 清除搜索历史 clearSearchHistory() { this.searchHistory = []; this.saveSearchHistory(); } // 删除搜索历史项 removeSearchHistoryItem(keyword) { this.searchHistory = this.searchHistory.filter(item => item !== keyword); this.saveSearchHistory(); } // 加载搜索历史 async loadSearchHistory() { try { const history = wx.getStorageSync('messageSearchHistory') || []; this.searchHistory = history; } catch (error) { console.error('❌ 加载搜索历史失败:', error); } } // 保存搜索历史 async saveSearchHistory() { try { wx.setStorageSync('messageSearchHistory', this.searchHistory); } catch (error) { console.error('❌ 保存搜索历史失败:', error); } } // 获取搜索建议 getSearchSuggestions(keyword) { if (!keyword) return this.searchHistory.slice(0, 10); const lowerKeyword = keyword.toLowerCase(); return this.searchHistory .filter(item => item.toLowerCase().includes(lowerKeyword)) .slice(0, 10); } // 获取当前搜索状态 getCurrentSearchState() { return { ...this.currentSearch }; } // 获取搜索统计 getSearchStats() { return { historyCount: this.searchHistory.length, cacheSize: this.searchCache.size, currentKeyword: this.currentSearch.keyword, isLoading: this.currentSearch.loading, hasResults: this.currentSearch.results.length > 0 }; } // 重置搜索管理器 reset() { this.searchCache.clear(); this.clearSearchResults(); this.clearSearchHistory(); } } // 创建全局实例 const messageSearchManager = new MessageSearchManager(); module.exports = messageSearchManager;