Files
im/pages/common/search/index.vue
T
cansnow 22ee59cd3d 11
2025-12-08 02:29:46 +08:00

399 lines
11 KiB
Vue

<template>
<view style="display: flex;flex-direction: column;background-color: #ececec;">
<u-status-bar bgColor="transparent"></u-status-bar>
<uni-search-bar class="search_bar"
:focus="true"
bgColor="#fff"
cancelButton="always"
:placeholder="getPlaceholder"
v-model="searchValue"
@confirm="search"
@input="input"
@cancel="cancel"
@clear="clear">
</uni-search-bar>
<u-tabs :list="searchTypeList" :current="currentTabIndex" @change="changeSearchType"></u-tabs>
<scroll-view scroll-y="true" class="scroll-view">
<!-- 加载状态 -->
<view v-if="status === 'loading'" class="empty-container">
<u-loading-icon mode="spinner" size="40"></u-loading-icon>
<text class="empty-text">搜索中...</text>
</view>
<!-- 空状态 -->
<view v-else-if="status === 'done' && isEmpty" class="empty-container">
<text class="empty-text">暂无搜索结果</text>
</view>
<!-- 等待搜索状态 -->
<view v-else-if="status === 'wait'" class="empty-container">
<text class="empty-text">请输入关键词进行搜索</text>
</view>
<!-- 搜索结果 -->
<view v-else>
<!-- 会话搜索结果 -->
<ConversationItem
v-if="currentSearchType === 'conversation'"
:source="conversation"
:key="index"
v-for="(conversation,index) in conversationList"
></ConversationItem>
<!-- 好友搜索结果 -->
<user-item
v-if="currentSearchType === 'friend'"
@itemClick="userClick"
@updateCheck="()=>{}"
:checked="false"
:disabled="false"
:checkVisible="false"
v-for="cell in friendList"
:item="cell"
:key="cell.userID"
/>
<!-- 消息搜索结果 -->
<view v-if="['message', 'file', 'location'].includes(currentSearchType)">
<view
v-for="(resultItem, resultIndex) in messageList"
:key="resultIndex"
class="conversation-group"
>
<view class="conversation-header" @click="goToConversation(resultItem)">
<my-avatar
:src="resultItem.faceURL"
:desc="resultItem.showName"
:isGroup="resultItem.conversationType === 2"
size="36"
/>
<text class="conversation-title">{{ resultItem.showName }}</text>
<text class="message-count">{{ resultItem.messageCount }}条相关消息</text>
</view>
<message-search-item
v-for="(message, msgIndex) in resultItem.messageList"
:key="msgIndex"
:message="message"
:conversation="resultItem"
@click="messageClick"
></message-search-item>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import {mapGetters} from "vuex";
import ConversationItem from "@/pages/conversation/conversationList/components/ConversationItem.vue";
import UserItem from "@/components/UserItem/index.vue";
import MessageSearchItem from "./components/MessageSearchItem.vue";
import MyAvatar from "@/components/MyAvatar/index.vue";
import IMSDK,{MessageType, SessionType} from "openim-uniapp-polyfill";
import {prepareConversationState, navigateToDesignatedConversation} from "@/util/imCommon";
export default {
components:{
ConversationItem,
UserItem,
MessageSearchItem,
MyAvatar
},
data() {
return {
searchValue:"",
currentSearchType:"message", // conversation, friend, message, file, location
searchTypeList:[
{
name: '会话',
value: 'conversation'
},
{
name: '好友',
value: 'friend'
},
{
name: '消息',
value: 'message'
},
{
name: '文件',
value: 'file'
},
{
name: '位置',
value: 'location'
}
],
conversationList:[],
friendList:[],
messageList:[],
status:"wait", // wait, loading, done
conversationID:"",
}
},
computed: {
...mapGetters([
"storeConversationList",
"storeFriendList",
]),
currentTabIndex() {
const index = this.searchTypeList.findIndex(item => item.value === this.currentSearchType);
return index >= 0 ? index : 2;
},
getPlaceholder() {
const placeholders = {
conversation: "搜索会话名称",
friend: "搜索好友昵称或备注",
message: "搜索消息内容",
file: "搜索文件",
location: "搜索位置"
};
return placeholders[this.currentSearchType] || "请输入您要搜索的内容";
},
isEmpty() {
if (this.currentSearchType === 'conversation') {
return this.conversationList.length === 0;
} else if (this.currentSearchType === 'friend') {
return this.friendList.length === 0;
} else if (['message', 'file', 'location'].includes(this.currentSearchType)) {
return this.messageList.length === 0;
}
return true;
}
},
onLoad(opt) {
if(opt.type){
this.currentSearchType = opt.type;
}
if(opt.conversationID){
this.conversationID = opt.conversationID;
}
},
methods: {
clear(){
this.searchValue = "";
this.status = "wait";
this.conversationList = [];
this.friendList = [];
this.messageList = [];
},
cancel(){
uni.navigateBack();
},
input(){
// 可以在这里实现实时搜索
},
async search(){
if(!this.searchValue || this.searchValue.trim() === ''){
uni.showToast({
title: '请输入搜索关键词',
icon: 'none'
});
return;
}
this.status = 'loading';
try {
if(this.currentSearchType === 'conversation'){
await this.searchConversation();
} else if(this.currentSearchType === 'friend'){
await this.searchFriend();
} else if(['message', 'file', 'location'].includes(this.currentSearchType)){
await this.searchMessage();
}
} catch(e) {
console.error('搜索失败:', e);
uni.showToast({
title: '搜索失败,请重试',
icon: 'none'
});
} finally {
this.status = 'done';
}
},
changeSearchType(e){
//console.log(e,this.searchTypeList[e]);
this.currentSearchType = e.value;//this.searchTypeList[index].value;
this.search();
// 切换类型时清空之前的搜索结果
//this.clear();
},
userClick(item){
// 跳转到用户详情或聊天页面
uni.navigateTo({
url: `/pages/common/userCard/index?sourceID=${item.userID}`
});
},
messageClick(item){
// 跳转到对应的聊天页面
const conversation = item.conversation;
if(conversation){
prepareConversationState(conversation);
}
},
goToConversation(resultItem){
// 根据会话类型跳转
const sessionType = resultItem.conversationType === 2 ? SessionType.WorkingGroup : SessionType.Single;
// 从 conversationID 中解析 sourceID,或者从 store 中获取
let sourceID = resultItem.groupID || resultItem.userID;
if(!sourceID){
// 从 conversationID 解析:si_userID1_userID2 或 g_groupID
const convID = resultItem.conversationID || '';
if(convID.startsWith('si_')) {
// 单聊:si_userID1_userID2,取第二个 userID(对方)
const parts = convID.split('_');
if(parts.length >= 3){
const selfID = this.$store.getters.storeCurrentUserID;
sourceID = parts[1] === selfID ? parts[2] : parts[1];
}
} else if(convID.startsWith('g_')) {
// 群聊:g_groupID
sourceID = convID.substring(2);
}
}
// 如果还是没有,尝试从 store 中获取
if(!sourceID){
const allConversations = this.storeConversationList || [];
const conv = allConversations.find(c => c.conversationID === resultItem.conversationID);
if(conv){
sourceID = conv.groupID || conv.userID;
}
}
if(sourceID){
navigateToDesignatedConversation(sourceID, sessionType).catch(() => {
uni.showToast({
title: '跳转失败',
icon: 'none'
});
});
} else {
uni.showToast({
title: '无法跳转,会话信息不完整',
icon: 'none'
});
}
},
// 搜索会话
searchConversation(){
const keyword = this.searchValue.toLowerCase();
const allConversations = this.storeConversationList || [];
this.conversationList = allConversations.filter(conversation => {
const showName = (conversation.showName || '').toLowerCase();
return showName.includes(keyword);
});
},
// 搜索好友
searchFriend(){
const keyword = this.searchValue.toLowerCase();
const allFriends = this.storeFriendList || [];
this.friendList = allFriends.filter(friend => {
const nickname = (friend.nickname || '').toLowerCase();
const remark = (friend.remark || '').toLowerCase();
const userID = (friend.userID || '').toLowerCase();
return nickname.includes(keyword) || remark.includes(keyword) || userID.includes(keyword);
});
},
// 搜索消息(包括文件、位置)
async searchMessage(){
const _this = this;
// 根据搜索类型确定消息类型
let messageTypeList = [];
if(this.currentSearchType === 'file'){
messageTypeList = [MessageType.FileMessage];
} else if(this.currentSearchType === 'location'){
messageTypeList = [MessageType.LocationMessage];
} else {
// 消息搜索:文本消息
messageTypeList = [MessageType.TextMessage];
}
try {
const result = await IMSDK.asyncApi('searchLocalMessages', IMSDK.uuid(), {
conversationID: _this.conversationID || '',
keywordList: [_this.searchValue],
keywordListMatchType: 0,
senderUserIDList: [],
messageTypeList: messageTypeList,
searchTimePosition: 0,
searchTimePeriod: 0,
pageIndex: 1,
count: 50,
});
if(result && result.errCode === 0 && result.data){
// 直接使用返回的 searchResultItems,它们已经包含了会话信息和消息列表
this.messageList = result.data.searchResultItems || [];
// 如果需要补充更多会话信息,可以从store中获取
const allConversations = this.storeConversationList || [];
this.messageList.forEach(item => {
const conv = allConversations.find(c => c.conversationID === item.conversationID);
if(conv){
// 补充会话信息(如果返回的数据不完整)
item.userID = item.userID || conv.userID;
item.groupID = item.groupID || conv.groupID;
}
});
} else {
this.messageList = [];
}
} catch(e) {
console.error('搜索消息失败:', e);
this.messageList = [];
throw e;
}
}
}
}
</script>
<style lang="scss" scoped>
.scroll-view{
flex: 1;
height: 0;
::v-deep .uni-scroll-view-content{
background-color: #fff;
}
}
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 200rpx 0;
.empty-text {
margin-top: 24rpx;
font-size: 28rpx;
color: #999;
}
}
.conversation-group {
background-color: #fff;
margin-bottom: 20rpx;
.conversation-header {
display: flex;
align-items: center;
padding: 24rpx 44rpx;
background-color: #f5f5f5;
border-bottom: 1px solid #eee;
.conversation-title {
flex: 1;
margin-left: 24rpx;
font-size: 30rpx;
font-weight: 500;
color: #333;
}
.message-count {
font-size: 24rpx;
color: #999;
}
}
}
</style>