476 lines
13 KiB
JavaScript
476 lines
13 KiB
JavaScript
|
|
// 🔍 全局搜索页面逻辑
|
|||
|
|
// ⚠️ 注意:此文件依赖已删除的 message-search-manager,需要重构为使用 NIM SDK 的搜索功能
|
|||
|
|
// TODO: 集成 NIM SDK 的消息搜索 API
|
|||
|
|
// const messageSearchManager = require('../../../utils/message-search-manager.js');
|
|||
|
|
const app = getApp();
|
|||
|
|
|
|||
|
|
Page({
|
|||
|
|
data: {
|
|||
|
|
// 系统信息
|
|||
|
|
statusBarHeight: 44,
|
|||
|
|
|
|||
|
|
// 搜索状态
|
|||
|
|
searchKeyword: '',
|
|||
|
|
searchFocus: true,
|
|||
|
|
isSearching: false,
|
|||
|
|
isLoadingMore: false,
|
|||
|
|
|
|||
|
|
// 会话搜索
|
|||
|
|
conversationId: null,
|
|||
|
|
conversationName: '',
|
|||
|
|
isConversationSearch: false,
|
|||
|
|
|
|||
|
|
// 搜索结果
|
|||
|
|
searchResults: [],
|
|||
|
|
searchTotal: 0,
|
|||
|
|
currentPage: 1,
|
|||
|
|
hasMoreResults: false,
|
|||
|
|
searchStatusText: '',
|
|||
|
|
|
|||
|
|
// 搜索历史和建议
|
|||
|
|
searchHistory: [],
|
|||
|
|
|
|||
|
|
// 防抖定时器
|
|||
|
|
searchTimer: null
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onLoad(options) {
|
|||
|
|
|
|||
|
|
// 获取系统信息
|
|||
|
|
this.getSystemInfo();
|
|||
|
|
|
|||
|
|
// 初始化搜索管理器
|
|||
|
|
this.initSearchManager();
|
|||
|
|
|
|||
|
|
// 加载搜索历史
|
|||
|
|
this.loadSearchHistory();
|
|||
|
|
|
|||
|
|
// 处理会话内搜索
|
|||
|
|
if (options.conversationId) {
|
|||
|
|
this.setData({
|
|||
|
|
conversationId: options.conversationId,
|
|||
|
|
conversationName: decodeURIComponent(options.conversationName || '聊天'),
|
|||
|
|
isConversationSearch: true
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 更新页面标题
|
|||
|
|
wx.setNavigationBarTitle({
|
|||
|
|
title: `在"${this.data.conversationName}"中搜索`
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理传入的搜索关键词
|
|||
|
|
if (options.keyword) {
|
|||
|
|
this.setData({
|
|||
|
|
searchKeyword: options.keyword,
|
|||
|
|
searchFocus: false
|
|||
|
|
});
|
|||
|
|
this.performSearch();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onShow() {
|
|||
|
|
|
|||
|
|
// 刷新搜索历史
|
|||
|
|
this.loadSearchHistory();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onUnload() {
|
|||
|
|
|
|||
|
|
// 清理定时器
|
|||
|
|
if (this.data.searchTimer) {
|
|||
|
|
clearTimeout(this.data.searchTimer);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取系统信息
|
|||
|
|
getSystemInfo() {
|
|||
|
|
try {
|
|||
|
|
const windowInfo = wx.getWindowInfo();
|
|||
|
|
this.setData({
|
|||
|
|
statusBarHeight: windowInfo.statusBarHeight || 44
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取系统信息失败:', error);
|
|||
|
|
this.setData({
|
|||
|
|
statusBarHeight: 44
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 初始化搜索管理器
|
|||
|
|
async initSearchManager() {
|
|||
|
|
try {
|
|||
|
|
// TODO: 集成 NIM SDK 的搜索初始化
|
|||
|
|
// await messageSearchManager.init();
|
|||
|
|
console.warn('⚠️ 搜索功能需要重构为使用 NIM SDK');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 搜索管理器初始化失败:', error);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 加载搜索历史
|
|||
|
|
loadSearchHistory() {
|
|||
|
|
// TODO: 集成 NIM SDK 的搜索历史
|
|||
|
|
// const history = messageSearchManager.getSearchHistory();
|
|||
|
|
this.setData({
|
|||
|
|
searchHistory: [] // 暂时返回空数组
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 🔍 ===== 搜索输入处理 =====
|
|||
|
|
|
|||
|
|
// 搜索输入
|
|||
|
|
onSearchInput(e) {
|
|||
|
|
const keyword = e.detail.value;
|
|||
|
|
this.setData({
|
|||
|
|
searchKeyword: keyword
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 防抖搜索
|
|||
|
|
this.searchWithDebounce(keyword);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 搜索确认
|
|||
|
|
onSearchConfirm(e) {
|
|||
|
|
const keyword = e.detail.value.trim();
|
|||
|
|
if (keyword) {
|
|||
|
|
this.performSearch();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 防抖搜索
|
|||
|
|
searchWithDebounce(keyword) {
|
|||
|
|
// 清除之前的定时器
|
|||
|
|
if (this.data.searchTimer) {
|
|||
|
|
clearTimeout(this.data.searchTimer);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果关键词为空,清除结果
|
|||
|
|
if (!keyword.trim()) {
|
|||
|
|
this.setData({
|
|||
|
|
searchResults: [],
|
|||
|
|
searchTotal: 0,
|
|||
|
|
hasMoreResults: false
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置新的定时器
|
|||
|
|
const timer = setTimeout(() => {
|
|||
|
|
this.performSearch();
|
|||
|
|
}, 500);
|
|||
|
|
|
|||
|
|
this.setData({
|
|||
|
|
searchTimer: timer
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 清除搜索
|
|||
|
|
clearSearch() {
|
|||
|
|
this.setData({
|
|||
|
|
searchKeyword: '',
|
|||
|
|
searchResults: [],
|
|||
|
|
searchTotal: 0,
|
|||
|
|
hasMoreResults: false,
|
|||
|
|
searchFocus: true
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 🔍 ===== 搜索执行 =====
|
|||
|
|
|
|||
|
|
// 执行搜索
|
|||
|
|
async performSearch() {
|
|||
|
|
const keyword = this.data.searchKeyword.trim();
|
|||
|
|
if (!keyword) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 关键词长度与字符校验(限制过长或异常字符,允许中英文、数字、常见符号)
|
|||
|
|
if (keyword.length > 120) {
|
|||
|
|
wx.showToast({ title: '关键词过长', icon: 'none' });
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const allowedPattern = /^[\u4e00-\u9fa5\w\s\-_.!@#¥$??::;,,。、“”"'’‘()()/\\]{1,120}$/;
|
|||
|
|
if (!allowedPattern.test(keyword)) {
|
|||
|
|
wx.showToast({ title: '含非法字符', icon: 'none' });
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
this.setData({
|
|||
|
|
isSearching: true,
|
|||
|
|
currentPage: 1,
|
|||
|
|
searchResults: [],
|
|||
|
|
searchStatusText: '正在搜索...'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 调用搜索管理器
|
|||
|
|
const searchOptions = {
|
|||
|
|
page: 1
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 如果是会话内搜索,添加会话ID
|
|||
|
|
if (this.data.isConversationSearch && this.data.conversationId) {
|
|||
|
|
searchOptions.conversationId = this.data.conversationId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// TODO: 集成 NIM SDK 的消息搜索
|
|||
|
|
// const result = await messageSearchManager.searchMessages(keyword, searchOptions);
|
|||
|
|
|
|||
|
|
// 暂时返回空结果
|
|||
|
|
const result = { success: false, message: '搜索功能正在重构中' };
|
|||
|
|
|
|||
|
|
if (result.success) {
|
|||
|
|
// 处理搜索结果(按会话聚合)
|
|||
|
|
const processedResults = this.processConversationResults(result.data.conversations || []);
|
|||
|
|
|
|||
|
|
// 更新搜索状态文本
|
|||
|
|
const statusText = this.data.isConversationSearch
|
|||
|
|
? `在"${this.data.conversationName}"中找到 ${result.data.total} 条结果`
|
|||
|
|
: `找到 ${result.data.total} 条相关结果`;
|
|||
|
|
|
|||
|
|
this.setData({
|
|||
|
|
searchResults: processedResults,
|
|||
|
|
searchTotal: result.data.total,
|
|||
|
|
hasMoreResults: result.data.hasMore,
|
|||
|
|
currentPage: 1,
|
|||
|
|
searchStatusText: statusText
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
console.error('❌ 搜索失败:', result.error, result.status);
|
|||
|
|
let toastMsg = result.error || '搜索失败';
|
|||
|
|
if (result.status === 400) toastMsg = '参数错误';
|
|||
|
|
else if (result.status === 404) toastMsg = '未找到相关结果';
|
|||
|
|
else if (result.status === 500) toastMsg = '服务器开小差';
|
|||
|
|
else if (!result.status && /网络|timeout|超时|Network/i.test(result.error || '')) toastMsg = '网络异常';
|
|||
|
|
wx.showToast({ title: toastMsg, icon: 'none' });
|
|||
|
|
this.setData({ searchStatusText: toastMsg });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 搜索异常:', error);
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '搜索出错',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
} finally {
|
|||
|
|
this.setData({
|
|||
|
|
isSearching: false
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 加载更多结果
|
|||
|
|
async loadMoreResults() {
|
|||
|
|
if (!this.data.hasMoreResults || this.data.isLoadingMore) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
this.setData({
|
|||
|
|
isLoadingMore: true
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const nextPage = this.data.currentPage + 1;
|
|||
|
|
const searchOptions = {
|
|||
|
|
page: nextPage
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 如果是会话内搜索,添加会话ID
|
|||
|
|
if (this.data.isConversationSearch && this.data.conversationId) {
|
|||
|
|
searchOptions.conversationId = this.data.conversationId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// TODO: 集成 NIM SDK 的消息搜索
|
|||
|
|
// const result = await messageSearchManager.searchMessages(this.data.searchKeyword, searchOptions);
|
|||
|
|
|
|||
|
|
// 暂时返回空结果
|
|||
|
|
const result = { success: false };
|
|||
|
|
|
|||
|
|
if (result.success) {
|
|||
|
|
const processedResults = this.processConversationResults(result.data.conversations || []);
|
|||
|
|
const allResults = [...this.data.searchResults, ...processedResults];
|
|||
|
|
|
|||
|
|
this.setData({
|
|||
|
|
searchResults: allResults,
|
|||
|
|
hasMoreResults: result.data.hasMore,
|
|||
|
|
currentPage: nextPage
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 加载更多失败:', error);
|
|||
|
|
wx.showToast({
|
|||
|
|
title: '加载失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
} finally {
|
|||
|
|
this.setData({
|
|||
|
|
isLoadingMore: false
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 处理搜索结果(会话聚合)
|
|||
|
|
processConversationResults(conversations) {
|
|||
|
|
try {
|
|||
|
|
const metaMap = wx.getStorageSync('activeConversationMap') || {};
|
|||
|
|
return (conversations || []).map(raw => {
|
|||
|
|
const conv = { ...raw };
|
|||
|
|
const cid = String(conv.conversationId || conv.id || '');
|
|||
|
|
// 兜底补齐名称/头像
|
|||
|
|
const meta = cid && metaMap[cid] ? metaMap[cid] : null;
|
|||
|
|
if (!conv.conversationName && meta && meta.conversationName) {
|
|||
|
|
conv.conversationName = meta.conversationName;
|
|||
|
|
}
|
|||
|
|
if (!conv.conversationAvatar && meta && meta.conversationAvatar) {
|
|||
|
|
conv.conversationAvatar = meta.conversationAvatar;
|
|||
|
|
}
|
|||
|
|
// 与 message 页对齐:提供通用字段 name/avatar
|
|||
|
|
const name = conv.conversationName || (meta && meta.conversationName) || '';
|
|||
|
|
const avatar = conv.conversationAvatar || (meta && meta.conversationAvatar) || '';
|
|||
|
|
const ts = conv.topMatch && conv.topMatch.timestamp ? conv.topMatch.timestamp : null;
|
|||
|
|
const formattedTime = ts ? this.formatMessageTime(ts) : '';
|
|||
|
|
const conversationInitial = this.getConversationInitial(name);
|
|||
|
|
return {
|
|||
|
|
...conv,
|
|||
|
|
name,
|
|||
|
|
avatar,
|
|||
|
|
formattedTime,
|
|||
|
|
conversationInitial
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
} catch (e) {
|
|||
|
|
// 兜底:不因异常影响渲染
|
|||
|
|
return (conversations || []).map(conv => {
|
|||
|
|
const ts = conv.topMatch && conv.topMatch.timestamp ? conv.topMatch.timestamp : null;
|
|||
|
|
const formattedTime = ts ? this.formatMessageTime(ts) : '';
|
|||
|
|
const name = conv.conversationName || '';
|
|||
|
|
const avatar = conv.conversationAvatar || '';
|
|||
|
|
const conversationInitial = this.getConversationInitial(name);
|
|||
|
|
return { ...conv, name, avatar, formattedTime, conversationInitial };
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 格式化消息时间
|
|||
|
|
formatMessageTime(timestamp) {
|
|||
|
|
const now = new Date();
|
|||
|
|
const messageTime = new Date(timestamp);
|
|||
|
|
const diffMs = now.getTime() - messageTime.getTime();
|
|||
|
|
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|||
|
|
|
|||
|
|
if (diffDays === 0) {
|
|||
|
|
// 今天
|
|||
|
|
return messageTime.toLocaleTimeString('zh-CN', {
|
|||
|
|
hour: '2-digit',
|
|||
|
|
minute: '2-digit'
|
|||
|
|
});
|
|||
|
|
} else if (diffDays === 1) {
|
|||
|
|
// 昨天
|
|||
|
|
return '昨天 ' + messageTime.toLocaleTimeString('zh-CN', {
|
|||
|
|
hour: '2-digit',
|
|||
|
|
minute: '2-digit'
|
|||
|
|
});
|
|||
|
|
} else if (diffDays < 7) {
|
|||
|
|
// 一周内
|
|||
|
|
const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
|
|||
|
|
return `周${weekdays[messageTime.getDay()]}`;
|
|||
|
|
} else {
|
|||
|
|
// 更早
|
|||
|
|
return messageTime.toLocaleDateString('zh-CN', {
|
|||
|
|
month: '2-digit',
|
|||
|
|
day: '2-digit'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取会话名称
|
|||
|
|
getConversationName(message) {
|
|||
|
|
// 这里可以根据conversationId获取会话名称
|
|||
|
|
// 暂时返回默认值
|
|||
|
|
if (message.conversationId) {
|
|||
|
|
return message.conversationName || '群聊';
|
|||
|
|
}
|
|||
|
|
return '私聊';
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取会话头像首字
|
|||
|
|
getConversationInitial(name) {
|
|||
|
|
if (!name || typeof name !== 'string') return '聊';
|
|||
|
|
const trimmed = name.trim();
|
|||
|
|
if (!trimmed) return '聊';
|
|||
|
|
// 取首个字符(兼容 emoji/代理空格时的情况)
|
|||
|
|
return trimmed.charAt(0);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// (已移除)搜索类型切换相关逻辑
|
|||
|
|
|
|||
|
|
// 🔍 ===== 搜索历史管理 =====
|
|||
|
|
|
|||
|
|
// 选择历史搜索项
|
|||
|
|
selectHistoryItem(e) {
|
|||
|
|
const keyword = e.currentTarget.dataset.keyword;
|
|||
|
|
this.setData({
|
|||
|
|
searchKeyword: keyword,
|
|||
|
|
searchFocus: false
|
|||
|
|
});
|
|||
|
|
this.performSearch();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 删除历史搜索项
|
|||
|
|
removeHistoryItem(e) {
|
|||
|
|
const keyword = e.currentTarget.dataset.keyword;
|
|||
|
|
// TODO: 集成 NIM SDK 的搜索历史管理
|
|||
|
|
// messageSearchManager.removeSearchHistoryItem(keyword);
|
|||
|
|
this.loadSearchHistory();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 清除搜索历史
|
|||
|
|
clearSearchHistory() {
|
|||
|
|
wx.showModal({
|
|||
|
|
title: '清除搜索历史',
|
|||
|
|
content: '确定要清除所有搜索历史吗?',
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.confirm) {
|
|||
|
|
// TODO: 集成 NIM SDK 的搜索历史管理
|
|||
|
|
// messageSearchManager.clearSearchHistory();
|
|||
|
|
this.loadSearchHistory();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// (已移除)热门搜索相关逻辑
|
|||
|
|
|
|||
|
|
// 🔍 ===== 搜索结果操作 =====
|
|||
|
|
|
|||
|
|
// 打开会话
|
|||
|
|
openConversation(e) {
|
|||
|
|
const item = e.currentTarget.dataset.conversation;
|
|||
|
|
if (!item) return;
|
|||
|
|
const convId = item.conversationId;
|
|||
|
|
const name = encodeURIComponent(item.conversationName || '聊天');
|
|||
|
|
const chatType = typeof item.chatType === 'number' ? item.chatType : 0;
|
|||
|
|
const targetId = item.targetId || '';
|
|||
|
|
|
|||
|
|
// 跳转到聊天页面(遵循消息页约定路径)
|
|||
|
|
wx.navigateTo({
|
|||
|
|
url: `/pages/message/chat/chat?conversationId=${convId}&targetId=${targetId}&name=${name}&chatType=${chatType}`
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 🔍 ===== 页面导航 =====
|
|||
|
|
|
|||
|
|
// 返回上一页
|
|||
|
|
goBack() {
|
|||
|
|
wx.navigateBack();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|