You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
4.1 KiB

4 weeks ago
<template>
<view class="tab-page">
<view v-if="loading" class="chat-loading">
<loading :size="50" :mask="false">
<view>消息接收中...</view>
</loading>
</view>
<view v-if="initializing" class="chat-loading">
<loading :size="50" :mask="false">
<view>正在初始化...</view>
</loading>
</view>
<view class="nav-bar" v-if="showSearch">
<view class="nav-search">
<uni-search-bar focus="true" radius="100" v-model="searchText" cancelButton="none"
placeholder="搜索"></uni-search-bar>
</view>
</view>
<view class="chat-tip" v-if="!loading && chats.length == 0">
温馨提示您现在还没有任何聊天消息快跟您的好友发起聊天吧~
</view>
<scroll-view class="scroll-bar" v-else scroll-with-animation="true" scroll-y="true">
<view v-for="(chat, index) in chats" :key="index">
<long-press-menu v-if="isShowChat(chat)" :items="menu.items" @select="onSelectMenu($event, index)">
<chat-item :chat="chat" :index="index" :active="menu.chatIdx == index"></chat-item>
</long-press-menu>
</view>
</scroll-view>
</view>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
data() {
return {
showSearch: false,
searchText: "",
menu: {
show: false,
style: "",
chatIdx: -1,
isTouchMove: false,
items: [
{
key: 'DELETE',
name: '删除该聊天',
icon: 'trash',
color: '#e64e4e'
},
{
key: 'TOP',
name: '置顶该聊天',
icon: 'arrow-up'
}
]
}
}
},
computed: {
// 映射 Vuex state 和 getters
...mapState('chatStore', ['chats']),
...mapGetters('chatStore', ['isLoading']),
// 未读消息总数
unreadCount() {
let count = 0
this.chats.forEach(chat => {
if (!chat.delete) {
count += chat.unreadCount
}
})
return count
},
// 是否正在加载消息(调用 getter 返回的函数)
loading() {
return this.isLoading()
},
// 是否正在初始化(来自全局变量)
initializing() {
return !getApp().$vm.isInit
},
// 搜索过滤(用于模板,但未直接使用,可保留)
showChats() {
return this.chats.filter(chat =>
!chat.delete && chat.showName && chat.showName.includes(this.searchText)
)
}
},
methods: {
// 映射 Vuex actions
...mapActions('chatStore', ['removeChat', 'moveTop']),
onSelectMenu(item, chatIdx) {
switch (item.key) {
case 'DELETE':
this.removeChat(chatIdx)
break
case 'TOP':
this.moveTop(chatIdx)
break
default:
break
}
this.menu.show = false
},
// 不再需要单独定义 removeChat 和 moveToTop已通过 mapActions 映射
isShowChat(chat) {
if (chat.delete) return false
return !this.searchText || chat.showName.includes(this.searchText)
},
onSearch() {
this.showSearch = !this.showSearch
this.searchText = ""
},
refreshUnreadBadge() {
if (this.unreadCount > 0) {
uni.setTabBarBadge({
index: 0,
text: this.unreadCount + ""
})
} else {
uni.removeTabBarBadge({
index: 0,
complete: () => {}
})
}
}
},
watch: {
unreadCount(newCount) {
this.refreshUnreadBadge()
}
},
onShow() {
this.refreshUnreadBadge()
}
}
</script>
<style lang="scss">
.tab-page {
position: relative;
display: flex;
flex-direction: column;
.chat-tip {
position: absolute;
top: 400rpx;
padding: 50rpx;
line-height: 50rpx;
text-align: center;
color: $im-text-color-lighter;
}
.chat-loading {
display: block;
width: 100%;
height: 120rpx;
background: white;
color: $im-text-color-lighter;
.loading-box {
position: relative;
}
}
.scroll-bar {
flex: 1;
height: 100%;
}
}
</style>