upload project
This commit is contained in:
commit
06961cae04
422 changed files with 110626 additions and 0 deletions
475
subpackages/search/global-search/global-search.js
Normal file
475
subpackages/search/global-search/global-search.js
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
// 🔍 全局搜索页面逻辑
|
||||
// ⚠️ 注意:此文件依赖已删除的 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();
|
||||
}
|
||||
});
|
||||
|
||||
9
subpackages/search/global-search/global-search.json
Normal file
9
subpackages/search/global-search/global-search.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"navigationStyle": "default",
|
||||
"navigationBarTitleText": "搜索",
|
||||
"navigationBarBackgroundColor": "#000000",
|
||||
"navigationBarTextStyle": "white",
|
||||
"backgroundColor": "#f8f9fa",
|
||||
"enablePullDownRefresh": false,
|
||||
"onReachBottomDistance": 50
|
||||
}
|
||||
179
subpackages/search/global-search/global-search.wxml
Normal file
179
subpackages/search/global-search/global-search.wxml
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<!-- 🔍 全局搜索页面 -->
|
||||
<view class="search-container">
|
||||
<!-- 现代化导航栏 -->
|
||||
<view class="search-header">
|
||||
<view class="header-content">
|
||||
<!-- 使用系统导航栏返回按钮,移除自定义返回按钮 -->
|
||||
|
||||
<!-- 搜索输入框 -->
|
||||
<view class="search-input-container">
|
||||
<view class="search-input-wrapper">
|
||||
<image class="search-icon" src="/images/Search.png" mode="aspectFit" />
|
||||
<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="search-tips" wx:if="{{!searchHistory.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>
|
||||
|
||||
<!-- 搜索结果列表 -->
|
||||
<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="conversationId"
|
||||
bindtap="openConversation"
|
||||
data-conversation="{{item}}">
|
||||
|
||||
<!-- 会话头像(与消息页保持一致:优先 item.avatar,其次 item.conversationAvatar) -->
|
||||
<view class="result-avatar">
|
||||
<image wx:if="{{item.avatar || item.conversationAvatar}}"
|
||||
src="{{item.avatar || item.conversationAvatar}}"
|
||||
class="avatar-image"
|
||||
mode="aspectFill" />
|
||||
<view wx:else class="avatar-placeholder">
|
||||
<text class="avatar-text">{{item.conversationInitial || '聊'}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 会话摘要 -->
|
||||
<view class="result-content">
|
||||
<view class="result-header">
|
||||
<text class="sender-name">{{item.name || item.conversationName || '会话'}}</text>
|
||||
<text class="message-time">{{item.formattedTime}}</text>
|
||||
</view>
|
||||
|
||||
<view class="result-body">
|
||||
<view class="message-text" wx:if="{{item.topMatch.msgTypeCode === 0}}">
|
||||
<rich-text nodes="{{item.topMatch.highlightedContent || item.topMatch.content}}"></rich-text>
|
||||
</view>
|
||||
<view class="message-media" wx:elif="{{item.topMatch.msgTypeCode === 1}}">
|
||||
<text class="media-icon">🖼️</text>
|
||||
<text class="media-text">[图片]</text>
|
||||
</view>
|
||||
<view class="message-media" wx:elif="{{item.topMatch.msgTypeCode === 2}}">
|
||||
<text class="media-icon">🎵</text>
|
||||
<text class="media-text">[语音]</text>
|
||||
</view>
|
||||
<view class="message-media" wx:elif="{{item.topMatch.msgTypeCode === 3}}">
|
||||
<text class="media-icon">🎬</text>
|
||||
<text class="media-text">[视频]</text>
|
||||
</view>
|
||||
<view class="message-media" wx:elif="{{item.topMatch.msgTypeCode === 4}}">
|
||||
<text class="media-icon">📄</text>
|
||||
<text class="media-text">[文件]</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="conversation-info">
|
||||
<text class="conversation-name">匹配 {{item.matchCount}} 条</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="result-actions">
|
||||
<view class="action-btn" bindtap="openConversation" data-conversation="{{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>
|
||||
734
subpackages/search/global-search/global-search.wxss
Normal file
734
subpackages/search/global-search/global-search.wxss
Normal file
|
|
@ -0,0 +1,734 @@
|
|||
/* 🔍 全局搜索页面样式 - 深色主题重构(修复合并破坏) */
|
||||
|
||||
/* 变量(深色默认) */
|
||||
page {
|
||||
--primary-color: #4d7dff;
|
||||
--primary-light: #246bff;
|
||||
--primary-dark: #1c56d4;
|
||||
--background-color: #121212;
|
||||
--surface-color: #1e1e1e;
|
||||
--text-primary: #f5f5f5;
|
||||
--text-secondary: #b0b0b0;
|
||||
--text-tertiary: #666666;
|
||||
--border-color: #2a2a2a;
|
||||
--shadow-light: 0 1rpx 3rpx rgba(0,0,0,0.5);
|
||||
--shadow-medium: 0 4rpx 16rpx rgba(0,0,0,0.65);
|
||||
--radius-small: 8rpx;
|
||||
--radius-medium: 12rpx;
|
||||
--radius-large: 20rpx;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
page {
|
||||
--background-color: #101010;
|
||||
--surface-color: #1c1c1c;
|
||||
}
|
||||
}
|
||||
|
||||
/* 布局容器 */
|
||||
.search-container {
|
||||
height: 100vh;
|
||||
background: var(--background-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 头部 */
|
||||
/* 头部:改为与 social/search 一致的中性深色背景,移除蓝色渐变 */
|
||||
.search-header {
|
||||
background: #1e1e1e; /* 与 search 页面 search-section 暗色一致 */
|
||||
border-bottom: 1rpx solid #2a2a2a;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.4);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 32rpx 20rpx; /* 上下留白更贴近原 search 页面 */
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.search-input-container { flex: 1; }
|
||||
|
||||
/* 搜索输入:圆润 pill 风格,参照 social/search */
|
||||
.search-input-wrapper {
|
||||
height: 88rpx;
|
||||
background: #262626;
|
||||
border-radius: 50rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 32rpx;
|
||||
gap: 20rpx;
|
||||
border: 1rpx solid #333;
|
||||
box-shadow: inset 0 0 0 0 rgba(0,0,0,0.0);
|
||||
transition: border-color .25s, box-shadow .25s;
|
||||
}
|
||||
|
||||
.search-input-wrapper:focus-within {
|
||||
border-color: #3d6bff;
|
||||
box-shadow: 0 0 0 4rpx rgba(77,125,255,0.15);
|
||||
}
|
||||
.search-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: block;
|
||||
}
|
||||
.search-input { flex:1; font-size:32rpx; color:#e0e0e0; background:transparent; line-height:1.4; }
|
||||
.search-input::placeholder { color:#777; }
|
||||
.search-input::placeholder { color:#777; }
|
||||
|
||||
.clear-btn { width:40rpx; height:40rpx; border-radius:50%; background:#444; display:flex; align-items:center; justify-content:center; transition:all .2s; }
|
||||
.clear-btn:active { background:#555; transform:scale(.9); }
|
||||
.clear-icon { font-size:22rpx; color:#fff; font-weight:600; }
|
||||
|
||||
/* 右侧搜索按钮紧凑化 */
|
||||
.search-btn { height:72rpx; padding:0 32rpx; background:linear-gradient(135deg,#4d7dff,#246bff); border-radius:40rpx; display:flex; align-items:center; justify-content:center; border:none; box-shadow:0 4rpx 14rpx rgba(36,107,255,0.35); transition:opacity .2s, transform .15s; }
|
||||
.search-btn:active { opacity:.85; transform:scale(.95); }
|
||||
.search-btn-text { font-size:26rpx; color:#fff; font-weight:600; letter-spacing:2rpx; }
|
||||
|
||||
/* 内容区域 */
|
||||
.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 .2s; }
|
||||
.clear-history-btn:active { background:#1a1a1a; }
|
||||
.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 .2s; }
|
||||
.history-item:active { background:#222; transform:scale(.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 .2s; }
|
||||
.remove-history-btn:active { background:#1f1f1f; transform:scale(.9); }
|
||||
.remove-icon { font-size:24rpx; color:var(--text-secondary); }
|
||||
|
||||
/* 热门搜索(已移除) */
|
||||
|
||||
/* 提示 */
|
||||
.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:.35; }
|
||||
.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; }
|
||||
/* 搜索类型筛选(已移除) */
|
||||
|
||||
/* Scroll 区域 */
|
||||
.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 .2s; }
|
||||
.result-item:active { background:#222; transform:scale(.98); }
|
||||
.result-avatar { margin-right:24rpx; }
|
||||
.avatar-image, .avatar-placeholder { width:88rpx; height:88rpx; border-radius:44rpx; border:2rpx solid var(--border-color); }
|
||||
.avatar-placeholder { background:linear-gradient(135deg,var(--primary-color) 0%, var(--primary-light) 100%); display:flex; align-items:center; justify-content:center; }
|
||||
.avatar-text { font-size:32rpx; font-weight:600; color:#fff; }
|
||||
.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 .2s; box-shadow:0 4rpx 12rpx rgba(36,107,255,0.35); }
|
||||
.action-btn:active { background:var(--primary-dark); transform:scale(.9); box-shadow:0 2rpx 6rpx rgba(36,107,255,0.2); }
|
||||
.action-icon { font-size:28rpx; color:#fff; font-weight:600; }
|
||||
|
||||
/* 高亮 */
|
||||
.search-highlight { background:linear-gradient(135deg, rgba(255,235,59,.3) 0%, rgba(255,193,7,.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:.35; }
|
||||
.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; }
|
||||
.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; }
|
||||
.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, .loading-state { padding:80rpx 32rpx; }
|
||||
}
|
||||
@media screen and (min-height:812px) {
|
||||
.search-suggestions { padding:40rpx; }
|
||||
.no-results, .loading-state { padding:160rpx 32rpx; }
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue