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,457 @@
// 🔍 全局搜索页面逻辑
const messageSearchManager = require('../../utils/message-search-manager.js');
const app = getApp();
Page({
data: {
// 系统信息
statusBarHeight: 44,
// 搜索状态
searchKeyword: '',
searchFocus: true,
searchType: 'all',
isSearching: false,
isLoadingMore: false,
// 会话搜索
conversationId: null,
conversationName: '',
isConversationSearch: false,
// 搜索结果
searchResults: [],
searchTotal: 0,
currentPage: 1,
hasMoreResults: false,
searchStatusText: '',
// 搜索历史和建议
searchHistory: [],
hotSearches: ['图片', '文件', '链接', '表情包'],
// 防抖定时器
searchTimer: null
},
onLoad(options) {
console.log('🔍 全局搜索页面加载', 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() {
console.log('🔍 全局搜索页面显示');
// 刷新搜索历史
this.loadSearchHistory();
},
onUnload() {
console.log('🔍 全局搜索页面卸载');
// 清理定时器
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 {
await messageSearchManager.init();
console.log('✅ 搜索管理器初始化完成');
} catch (error) {
console.error('❌ 搜索管理器初始化失败:', error);
}
},
// 加载搜索历史
loadSearchHistory() {
const history = messageSearchManager.getSearchHistory();
this.setData({
searchHistory: history.slice(0, 10) // 只显示前10条
});
},
// 🔍 ===== 搜索输入处理 =====
// 搜索输入
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;
}
console.log('🔍 执行搜索:', keyword);
try {
this.setData({
isSearching: true,
currentPage: 1,
searchResults: [],
searchStatusText: '正在搜索...'
});
// 调用搜索管理器
const searchOptions = {
type: this.data.searchType,
page: 1
};
// 如果是会话内搜索添加会话ID
if (this.data.isConversationSearch && this.data.conversationId) {
searchOptions.conversationId = this.data.conversationId;
}
const result = await messageSearchManager.searchMessages(keyword, searchOptions);
if (result.success) {
// 处理搜索结果
const processedResults = this.processSearchResults(result.data.messages);
// 更新搜索状态文本
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
});
console.log(`🔍 搜索完成,找到 ${result.data.total} 条结果`);
} else {
console.error('❌ 搜索失败:', result.error);
wx.showToast({
title: result.error || '搜索失败',
icon: 'none'
});
}
} 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;
}
console.log('🔍 加载更多搜索结果');
try {
this.setData({
isLoadingMore: true
});
const nextPage = this.data.currentPage + 1;
const searchOptions = {
type: this.data.searchType,
page: nextPage
};
// 如果是会话内搜索添加会话ID
if (this.data.isConversationSearch && this.data.conversationId) {
searchOptions.conversationId = this.data.conversationId;
}
const result = await messageSearchManager.searchMessages(this.data.searchKeyword, searchOptions);
if (result.success) {
const processedResults = this.processSearchResults(result.data.messages);
const allResults = [...this.data.searchResults, ...processedResults];
this.setData({
searchResults: allResults,
hasMoreResults: result.data.hasMore,
currentPage: nextPage
});
console.log(`🔍 加载更多完成,当前共 ${allResults.length} 条结果`);
}
} catch (error) {
console.error('❌ 加载更多失败:', error);
wx.showToast({
title: '加载失败',
icon: 'none'
});
} finally {
this.setData({
isLoadingMore: false
});
}
},
// 处理搜索结果
processSearchResults(messages) {
return messages.map(message => {
// 格式化时间
const formattedTime = this.formatMessageTime(message.timestamp);
// 获取会话名称
const conversationName = this.getConversationName(message);
return {
...message,
formattedTime: formattedTime,
conversationName: conversationName
};
});
},
// 格式化消息时间
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 '私聊';
},
// 🔍 ===== 搜索类型切换 =====
// 切换搜索类型
changeSearchType(e) {
const type = e.currentTarget.dataset.type;
if (type === this.data.searchType) {
return;
}
console.log('🔍 切换搜索类型:', type);
this.setData({
searchType: type
});
// 如果有搜索关键词,重新搜索
if (this.data.searchKeyword.trim()) {
this.performSearch();
}
},
// 🔍 ===== 搜索历史管理 =====
// 选择历史搜索项
selectHistoryItem(e) {
const keyword = e.currentTarget.dataset.keyword;
this.setData({
searchKeyword: keyword,
searchFocus: false
});
this.performSearch();
},
// 删除历史搜索项
removeHistoryItem(e) {
const keyword = e.currentTarget.dataset.keyword;
messageSearchManager.removeSearchHistoryItem(keyword);
this.loadSearchHistory();
},
// 清除搜索历史
clearSearchHistory() {
wx.showModal({
title: '清除搜索历史',
content: '确定要清除所有搜索历史吗?',
success: (res) => {
if (res.confirm) {
messageSearchManager.clearSearchHistory();
this.loadSearchHistory();
}
}
});
},
// 选择热门搜索
selectHotSearch(e) {
const keyword = e.currentTarget.dataset.keyword;
this.setData({
searchKeyword: keyword,
searchFocus: false
});
this.performSearch();
},
// 🔍 ===== 搜索结果操作 =====
// 打开消息
openMessage(e) {
const message = e.currentTarget.dataset.message;
console.log('🔍 打开消息:', message.id);
// 跳转到聊天页面并定位到该消息
this.jumpToMessage(e);
},
// 跳转到消息
jumpToMessage(e) {
const message = e.currentTarget.dataset.message;
// 跳转到聊天页面
wx.navigateTo({
url: `/pages/chat/chat?conversationId=${message.conversationId}&messageId=${message.id}`
});
},
// 🔍 ===== 页面导航 =====
// 返回上一页
goBack() {
wx.navigateBack();
}
});

View file

@ -0,0 +1,7 @@
{
"navigationStyle": "custom",
"backgroundColor": "#F2F2F7",
"backgroundTextStyle": "dark",
"enablePullDownRefresh": false,
"onReachBottomDistance": 50
}

View file

@ -0,0 +1,227 @@
<!-- 🔍 全局搜索页面 -->
<view class="search-container">
<!-- 现代化导航栏 -->
<view class="search-header" style="padding-top: {{statusBarHeight}}px;">
<view class="header-content">
<!-- 返回按钮 -->
<view class="back-btn" bindtap="goBack">
<text class="back-icon">←</text>
</view>
<!-- 搜索输入框 -->
<view class="search-input-container">
<view class="search-input-wrapper">
<text class="search-icon">🔍</text>
<input class="search-input"
placeholder="{{isConversationSearch ? '在此会话中搜索' : '搜索消息、好友、群聊'}}"
value="{{searchKeyword}}"
bindinput="onSearchInput"
bindconfirm="onSearchConfirm"
focus="{{searchFocus}}"
confirm-type="search" />
<view class="clear-btn"
wx:if="{{searchKeyword}}"
bindtap="clearSearch">
<text class="clear-icon">✕</text>
</view>
</view>
</view>
<!-- 搜索按钮 -->
<view class="search-btn" bindtap="performSearch">
<text class="search-btn-text">搜索</text>
</view>
</view>
</view>
<!-- 搜索内容区域 -->
<view class="search-content">
<!-- 搜索建议和历史 -->
<view class="search-suggestions" wx:if="{{!searchResults.length && !isSearching}}">
<!-- 搜索历史 -->
<view class="suggestion-section" wx:if="{{searchHistory.length}}">
<view class="section-header">
<text class="section-title">搜索历史</text>
<view class="clear-history-btn" bindtap="clearSearchHistory">
<text class="clear-text">清除</text>
</view>
</view>
<view class="history-list">
<view class="history-item"
wx:for="{{searchHistory}}"
wx:key="index"
bindtap="selectHistoryItem"
data-keyword="{{item}}">
<text class="history-icon">🕐</text>
<text class="history-text">{{item}}</text>
<view class="remove-history-btn"
bindtap="removeHistoryItem"
data-keyword="{{item}}"
catchtap="true">
<text class="remove-icon">✕</text>
</view>
</view>
</view>
</view>
<!-- 热门搜索 -->
<view class="suggestion-section" wx:if="{{hotSearches.length}}">
<view class="section-header">
<text class="section-title">热门搜索</text>
</view>
<view class="hot-search-list">
<view class="hot-search-item"
wx:for="{{hotSearches}}"
wx:key="index"
bindtap="selectHotSearch"
data-keyword="{{item}}">
<text class="hot-search-text">{{item}}</text>
</view>
</view>
</view>
<!-- 搜索提示 -->
<view class="search-tips" wx:if="{{!searchHistory.length && !hotSearches.length}}">
<view class="tips-icon">🔍</view>
<text class="tips-title">开始搜索</text>
<text class="tips-description">搜索消息、好友、群聊等内容</text>
</view>
</view>
<!-- 搜索结果 -->
<view class="search-results" wx:if="{{searchResults.length || isSearching}}">
<!-- 搜索状态栏 -->
<view class="search-status-bar" wx:if="{{searchKeyword}}">
<text class="search-status-text">
{{searchStatusText}}
</text>
<!-- 搜索类型筛选 -->
<view class="search-type-filter">
<view class="filter-item {{searchType === 'all' ? 'active' : ''}}"
bindtap="changeSearchType"
data-type="all">
<text class="filter-text">全部</text>
</view>
<view class="filter-item {{searchType === 'text' ? 'active' : ''}}"
bindtap="changeSearchType"
data-type="text">
<text class="filter-text">文本</text>
</view>
<view class="filter-item {{searchType === 'image' ? 'active' : ''}}"
bindtap="changeSearchType"
data-type="image">
<text class="filter-text">图片</text>
</view>
<view class="filter-item {{searchType === 'file' ? 'active' : ''}}"
bindtap="changeSearchType"
data-type="file">
<text class="filter-text">文件</text>
</view>
</view>
</view>
<!-- 搜索结果列表 -->
<scroll-view class="results-scroll"
scroll-y="true"
bindscrolltolower="loadMoreResults"
enable-back-to-top="true">
<!-- 消息结果 -->
<view class="result-section" wx:if="{{searchResults.length}}">
<view class="result-item"
wx:for="{{searchResults}}"
wx:key="id"
bindtap="openMessage"
data-message="{{item}}">
<!-- 消息发送者头像 -->
<view class="result-avatar">
<image wx:if="{{item.senderAvatar}}"
src="{{item.senderAvatar}}"
class="avatar-image"
mode="aspectFill" />
<view wx:else class="avatar-placeholder">
<text class="avatar-text">{{item.senderName.charAt(0)}}</text>
</view>
</view>
<!-- 消息内容 -->
<view class="result-content">
<view class="result-header">
<text class="sender-name">{{item.senderName}}</text>
<text class="message-time">{{item.formattedTime}}</text>
</view>
<view class="result-body">
<!-- 文本消息 -->
<view class="message-text" wx:if="{{item.msgType === 0}}">
<rich-text nodes="{{item.highlightedContent || item.content}}"></rich-text>
</view>
<!-- 图片消息 -->
<view class="message-media" wx:elif="{{item.msgType === 1}}">
<text class="media-icon">🖼️</text>
<text class="media-text">[图片]</text>
</view>
<!-- 语音消息 -->
<view class="message-media" wx:elif="{{item.msgType === 2}}">
<text class="media-icon">🎵</text>
<text class="media-text">[语音]</text>
</view>
<!-- 视频消息 -->
<view class="message-media" wx:elif="{{item.msgType === 3}}">
<text class="media-icon">🎬</text>
<text class="media-text">[视频]</text>
</view>
<!-- 文件消息 -->
<view class="message-media" wx:elif="{{item.msgType === 4}}">
<text class="media-icon">📄</text>
<text class="media-text">[文件] {{item.fileName || ''}}</text>
</view>
</view>
<!-- 会话信息 -->
<view class="conversation-info">
<text class="conversation-name">来自: {{item.conversationName || '私聊'}}</text>
</view>
</view>
<!-- 操作按钮 -->
<view class="result-actions">
<view class="action-btn" bindtap="jumpToMessage" data-message="{{item}}">
<text class="action-icon">→</text>
</view>
</view>
</view>
</view>
<!-- 加载更多 -->
<view class="load-more" wx:if="{{hasMoreResults}}">
<view class="loading-spinner" wx:if="{{isLoadingMore}}"></view>
<text class="load-more-text">
{{isLoadingMore ? '加载中...' : '上拉加载更多'}}
</text>
</view>
<!-- 无结果提示 -->
<view class="no-results" wx:if="{{!isSearching && searchKeyword && !searchResults.length}}">
<view class="no-results-icon">🔍</view>
<text class="no-results-title">未找到相关内容</text>
<text class="no-results-description">
尝试使用其他关键词或检查拼写
</text>
</view>
</scroll-view>
</view>
<!-- 加载状态 -->
<view class="loading-state" wx:if="{{isSearching && !searchResults.length}}">
<view class="loading-spinner"></view>
<text class="loading-text">正在搜索...</text>
</view>
</view>
</view>

View file

@ -0,0 +1,712 @@
/* 🔍 全局搜索页面样式 - 现代化设计 */
/* CSS变量定义 - 与其他页面保持一致 */
page {
--primary-color: #007AFF;
--primary-light: #5AC8FA;
--primary-dark: #0051D5;
--background-color: #F2F2F7;
--surface-color: #FFFFFF;
--text-primary: #000000;
--text-secondary: #8E8E93;
--text-tertiary: #C7C7CC;
--border-color: #E5E5EA;
--shadow-light: 0 1rpx 3rpx rgba(0, 0, 0, 0.1);
--shadow-medium: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
--radius-small: 8rpx;
--radius-medium: 12rpx;
--radius-large: 20rpx;
}
/* 🌙 深色模式支持 */
@media (prefers-color-scheme: dark) {
page {
--primary-color: #0A84FF;
--primary-light: #64D2FF;
--primary-dark: #0056CC;
--background-color: #000000;
--surface-color: #1C1C1E;
--text-primary: #FFFFFF;
--text-secondary: #8E8E93;
--text-tertiary: #48484A;
--border-color: #38383A;
--shadow-light: 0 1rpx 3rpx rgba(0, 0, 0, 0.3);
--shadow-medium: 0 4rpx 12rpx rgba(0, 0, 0, 0.4);
}
}
.search-container {
height: 100vh;
background: var(--background-color);
display: flex;
flex-direction: column;
}
/* 🎨 现代化搜索头部 */
.search-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
box-shadow: var(--shadow-medium);
z-index: 1000;
}
.header-content {
height: 88rpx;
display: flex;
align-items: center;
padding: 0 24rpx;
gap: 16rpx;
}
.back-btn {
width: 72rpx;
height: 72rpx;
border-radius: var(--radius-medium);
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.back-btn:active {
background: rgba(255, 255, 255, 0.3);
transform: scale(0.95);
}
.back-icon {
font-size: 36rpx;
color: white;
font-weight: 600;
}
/* 🎨 现代化搜索输入框 */
.search-input-container {
flex: 1;
}
.search-input-wrapper {
height: 72rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: var(--radius-large);
display: flex;
align-items: center;
padding: 0 24rpx;
gap: 16rpx;
backdrop-filter: blur(10rpx);
border: 1rpx solid rgba(255, 255, 255, 0.3);
}
.search-icon {
font-size: 32rpx;
color: var(--text-secondary);
}
.search-input {
flex: 1;
font-size: 32rpx;
color: var(--text-primary);
background: transparent;
line-height: 1.4;
}
.search-input::placeholder {
color: var(--text-secondary);
}
.clear-btn {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
background: var(--text-tertiary);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.clear-btn:active {
background: var(--text-secondary);
transform: scale(0.9);
}
.clear-icon {
font-size: 24rpx;
color: white;
font-weight: 600;
}
.search-btn {
padding: 20rpx 32rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: var(--radius-medium);
transition: all 0.3s ease;
}
.search-btn:active {
background: rgba(255, 255, 255, 0.3);
transform: scale(0.95);
}
.search-btn-text {
font-size: 28rpx;
color: white;
font-weight: 600;
}
/* 🎨 搜索内容区域 */
.search-content {
flex: 1;
background: var(--background-color);
overflow: hidden;
}
/* 🎨 搜索建议和历史 */
.search-suggestions {
padding: 32rpx;
}
.suggestion-section {
margin-bottom: 40rpx;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: var(--text-primary);
}
.clear-history-btn {
padding: 12rpx 24rpx;
background: var(--background-color);
border-radius: var(--radius-small);
border: 1rpx solid var(--border-color);
transition: all 0.2s ease;
}
.clear-history-btn:active {
background: var(--border-color);
}
.clear-text {
font-size: 26rpx;
color: var(--text-secondary);
}
/* 🎨 搜索历史列表 */
.history-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.history-item {
display: flex;
align-items: center;
padding: 24rpx;
background: var(--surface-color);
border-radius: var(--radius-medium);
border: 1rpx solid var(--border-color);
transition: all 0.2s ease;
}
.history-item:active {
background: var(--background-color);
transform: scale(0.98);
}
.history-icon {
font-size: 32rpx;
color: var(--text-secondary);
margin-right: 24rpx;
}
.history-text {
flex: 1;
font-size: 30rpx;
color: var(--text-primary);
line-height: 1.4;
}
.remove-history-btn {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
background: var(--background-color);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.remove-history-btn:active {
background: var(--border-color);
transform: scale(0.9);
}
.remove-icon {
font-size: 24rpx;
color: var(--text-secondary);
}
/* 🎨 热门搜索 */
.hot-search-list {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.hot-search-item {
padding: 16rpx 24rpx;
background: var(--surface-color);
border-radius: var(--radius-large);
border: 1rpx solid var(--border-color);
transition: all 0.2s ease;
}
.hot-search-item:active {
background: var(--primary-color);
border-color: var(--primary-color);
}
.hot-search-item:active .hot-search-text {
color: white;
}
.hot-search-text {
font-size: 28rpx;
color: var(--text-primary);
transition: color 0.2s ease;
}
/* 🎨 搜索提示 */
.search-tips {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 32rpx;
text-align: center;
}
.tips-icon {
font-size: 120rpx;
margin-bottom: 32rpx;
opacity: 0.4;
}
.tips-title {
font-size: 36rpx;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 16rpx;
}
.tips-description {
font-size: 28rpx;
color: var(--text-secondary);
line-height: 1.5;
}
/* 🎨 搜索结果区域 */
.search-results {
flex: 1;
display: flex;
flex-direction: column;
}
.search-status-bar {
padding: 24rpx 32rpx;
background: var(--surface-color);
border-bottom: 1rpx solid var(--border-color);
}
.search-status-text {
font-size: 28rpx;
color: var(--text-secondary);
margin-bottom: 16rpx;
display: block;
}
/* 🎨 搜索类型筛选 */
.search-type-filter {
display: flex;
gap: 16rpx;
}
.filter-item {
padding: 12rpx 24rpx;
background: var(--background-color);
border-radius: var(--radius-large);
border: 1rpx solid var(--border-color);
transition: all 0.2s ease;
}
.filter-item.active {
background: var(--primary-color);
border-color: var(--primary-color);
}
.filter-item:active {
transform: scale(0.95);
}
.filter-text {
font-size: 26rpx;
color: var(--text-primary);
transition: color 0.2s ease;
}
.filter-item.active .filter-text {
color: white;
}
/* 🎨 搜索结果滚动区域 */
.results-scroll {
flex: 1;
background: var(--background-color);
}
.result-section {
padding: 16rpx 32rpx;
}
/* 🎨 搜索结果项 */
.result-item {
display: flex;
align-items: flex-start;
padding: 28rpx;
background: var(--surface-color);
border-radius: var(--radius-medium);
border: 1rpx solid var(--border-color);
margin-bottom: 16rpx;
transition: all 0.2s ease;
}
.result-item:active {
background: var(--background-color);
transform: scale(0.98);
}
.result-avatar {
margin-right: 24rpx;
}
.avatar-image {
width: 88rpx;
height: 88rpx;
border-radius: 44rpx;
border: 2rpx solid var(--border-color);
}
.avatar-placeholder {
width: 88rpx;
height: 88rpx;
border-radius: 44rpx;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid var(--border-color);
}
.avatar-text {
font-size: 32rpx;
font-weight: 600;
color: white;
}
.result-content {
flex: 1;
min-width: 0;
}
.result-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12rpx;
}
.sender-name {
font-size: 30rpx;
font-weight: 600;
color: var(--text-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
margin-right: 16rpx;
}
.message-time {
font-size: 24rpx;
color: var(--text-secondary);
white-space: nowrap;
}
.result-body {
margin-bottom: 12rpx;
}
.message-text {
font-size: 28rpx;
color: var(--text-primary);
line-height: 1.5;
word-break: break-word;
}
.message-media {
display: flex;
align-items: center;
gap: 12rpx;
}
.media-icon {
font-size: 28rpx;
}
.media-text {
font-size: 28rpx;
color: var(--text-secondary);
}
.conversation-info {
margin-top: 8rpx;
}
.conversation-name {
font-size: 24rpx;
color: var(--text-tertiary);
}
.result-actions {
margin-left: 16rpx;
}
.action-btn {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: var(--primary-color);
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.action-btn:active {
background: var(--primary-dark);
transform: scale(0.9);
}
.action-icon {
font-size: 28rpx;
color: white;
font-weight: 600;
}
/* 🎨 搜索高亮样式 */
.search-highlight {
background: linear-gradient(135deg, rgba(255, 235, 59, 0.3) 0%, rgba(255, 193, 7, 0.3) 100%);
border-radius: 4rpx;
padding: 0 4rpx;
font-weight: 600;
}
/* 🎨 加载更多 */
.load-more {
display: flex;
align-items: center;
justify-content: center;
padding: 40rpx;
gap: 16rpx;
}
.load-more-text {
font-size: 28rpx;
color: var(--text-secondary);
}
/* 🎨 无结果提示 */
.no-results {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 32rpx;
text-align: center;
}
.no-results-icon {
font-size: 120rpx;
margin-bottom: 32rpx;
opacity: 0.4;
}
.no-results-title {
font-size: 36rpx;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 16rpx;
}
.no-results-description {
font-size: 28rpx;
color: var(--text-secondary);
line-height: 1.5;
}
/* 🎨 加载状态 */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 32rpx;
gap: 32rpx;
}
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 4rpx solid var(--border-color);
border-top: 4rpx solid var(--primary-color);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
font-size: 28rpx;
color: var(--text-secondary);
}
/* 📱 响应式设计 - 适配不同屏幕尺寸 */
@media screen and (max-width: 375px) {
.header-content {
height: 80rpx;
padding: 0 20rpx;
}
.search-input-wrapper {
height: 64rpx;
}
.search-input {
font-size: 28rpx;
}
.search-suggestions {
padding: 24rpx;
}
.suggestion-item {
padding: 20rpx;
}
.suggestion-text {
font-size: 28rpx;
}
.result-item {
padding: 24rpx;
}
.avatar-image, .avatar-placeholder {
width: 72rpx;
height: 72rpx;
border-radius: 36rpx;
}
.sender-name {
font-size: 28rpx;
}
.message-text {
font-size: 26rpx;
}
}
@media screen and (min-width: 414px) {
.header-content {
height: 96rpx;
padding: 0 32rpx;
}
.search-input-wrapper {
height: 80rpx;
}
.search-input {
font-size: 36rpx;
}
.search-suggestions {
padding: 40rpx;
}
.suggestion-item {
padding: 28rpx;
}
.suggestion-text {
font-size: 32rpx;
}
.result-item {
padding: 32rpx;
}
.avatar-image, .avatar-placeholder {
width: 96rpx;
height: 96rpx;
border-radius: 48rpx;
}
.sender-name {
font-size: 32rpx;
}
.message-text {
font-size: 30rpx;
}
}
@media screen and (max-height: 667px) {
.search-suggestions {
padding: 24rpx;
}
.no-results {
padding: 80rpx 32rpx;
}
.loading-state {
padding: 80rpx 32rpx;
}
}
@media screen and (min-height: 812px) {
.search-suggestions {
padding: 40rpx;
}
.no-results {
padding: 160rpx 32rpx;
}
.loading-state {
padding: 160rpx 32rpx;
}
}