343 lines
9.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="message-center">
<!-- 顶部Tab导航 -->
<div class="tab-container">
<n-tabs v-model:value="activeTab" type="line" size="large" class="message-tabs" @update:value="handleTabChange">
<n-tab-pane name="notification" tab="即时消息">
<template #tab>
<div class="tab-item">
<span>即时消息</span>
<n-badge :value="notificationCount" :show="notificationCount > 0" class="tab-badge">
</n-badge>
</div>
</template>
</n-tab-pane>
<n-tab-pane name="comment" tab="评论和@">
<template #tab>
<div class="tab-item">
<span>评论和@</span>
<n-badge :value="commentCount" :show="commentCount > 0" class="tab-badge">
</n-badge>
</div>
</template>
</n-tab-pane>
<n-tab-pane name="favorite" tab="赞和收藏">
<template #tab>
<div class="tab-item">
<span>赞和收藏</span>
<n-badge :value="favoriteCount" :show="favoriteCount > 0" class="tab-badge">
</n-badge>
</div>
</template>
</n-tab-pane>
<n-tab-pane name="system" tab="系统消息">
<template #tab>
<div class="tab-item">
<span>系统消息</span>
<n-badge :value="systemCount" :show="systemCount > 0" class="tab-badge">
</n-badge>
</div>
</template>
</n-tab-pane>
</n-tabs>
</div>
<!-- Tab内容区域 -->
<div class="tab-content">
<div v-show="activeTab === 'notification'">
<NotificationMessages />
</div>
<div v-show="activeTab === 'comment'">
<CommentLikes />
</div>
<div v-show="activeTab === 'favorite'">
<FavoriteMessages />
</div>
<div v-show="activeTab === 'system'">
<SystemMessages />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { NBadge, NTabs, NTabPane } from 'naive-ui'
import { ChatApi, MessageApi } from '@/api'
// 导入子组件
import NotificationMessages from './components/NotificationMessages.vue'
import CommentLikes from './components/CommentLikes.vue'
import FavoriteMessages from './components/FavoriteMessages.vue'
import SystemMessages from './components/SystemMessages.vue'
// 响应式数据
const activeTab = ref('notification') // 当前激活的tab
// 各类消息数量(角标显示)
const notificationCount = ref(0) // 即时消息数量
const commentCount = ref(0) // 评论和@数量
const favoriteCount = ref(0) // 赞和收藏数量
const systemCount = ref(0) // 系统消息数量
// 加载状态
const loading = ref(false)
// 缓存和防抖
const cacheTimestamp = ref(0)
const CACHE_DURATION = 30000 // 30秒缓存
let refreshTimer: NodeJS.Timeout | null = null
// 生命周期钩子
onMounted(() => {
// 初始化逻辑
loadMessageCounts()
})
onUnmounted(() => {
// 清理定时器
if (refreshTimer) {
clearTimeout(refreshTimer)
refreshTimer = null
}
})
// 加载各类消息数量
const loadMessageCounts = async (forceRefresh = false) => {
// 检查缓存
const now = Date.now()
if (!forceRefresh && now - cacheTimestamp.value < CACHE_DURATION) {
console.log('📋 使用缓存的消息数量,跳过加载')
return
}
console.log('🔄 开始加载消息数量...')
loading.value = true
try {
// 首先尝试使用统一的未读消息数接口
const unreadCountResult = await Promise.allSettled([loadTotalUnreadCount()])
console.log('🔍 统一接口结果:', unreadCountResult[0])
// 如果统一接口失败,则使用原有的分别加载方式
if (unreadCountResult[0].status === 'rejected') {
console.log('⚠️ 统一接口失败,使用分别加载方式')
// 并行加载各类消息数量,使用 Promise.allSettled 确保即使某个接口失败也不影响其他接口
const results = await Promise.allSettled([
loadNotificationCount(),
loadCommentCount(),
loadFavoriteCount(),
loadSystemCount()
])
console.log('📊 分别加载结果:', results)
// 检查是否有接口失败
const failedCount = results.filter(result => result.status === 'rejected').length
if (failedCount > 0) {
console.log(`⚠️ ${failedCount} 个接口加载失败`)
// 静默处理接口失败,不影响用户体验
}
}
console.log('📈 最终消息数量:', {
notification: notificationCount.value,
comment: commentCount.value,
favorite: favoriteCount.value,
system: systemCount.value
})
cacheTimestamp.value = now
} catch (error) {
console.error('加载消息数量失败:', error)
// 不显示错误消息,因为可能只是部分接口失败
} finally {
loading.value = false
}
}
// 防抖刷新
const debouncedRefresh = () => {
if (refreshTimer) {
clearTimeout(refreshTimer)
}
refreshTimer = setTimeout(() => {
loadMessageCounts(true)
}, 1000)
}
// 加载总的未读消息数
const loadTotalUnreadCount = async () => {
try {
console.log('🔄 尝试调用统一未读消息数接口...')
const response = await MessageApi.getUnreadMessageCount()
console.log('🔍 统一接口响应:', response)
if (response.code === 200) {
const result = response.data as any || {}
console.log('📊 统一接口返回数据:', result)
// 使用统一接口返回的数据
// 检查result.result是否存在如果存在则使用其中的数据
if (result.result) {
const countData = result.result
if (countData.commentsUnreadCount !== undefined) {
commentCount.value = countData.commentsUnreadCount || 0
console.log('✅ 评论未读数设置为:', commentCount.value)
}
if (countData.likesUnreadCount !== undefined) {
favoriteCount.value = countData.likesUnreadCount || 0
console.log('✅ 赞和收藏未读数设置为:', favoriteCount.value)
}
if (countData.systemUnreadCount !== undefined) {
systemCount.value = countData.systemUnreadCount || 0
console.log('✅ 系统消息未读数设置为:', systemCount.value)
}
}
// 注意统一接口没有返回即时消息的未读数保持为0
notificationCount.value = 0
return true
}
console.log('❌ 统一接口响应格式不正确')
return false
} catch (error) {
console.error('❌ 获取总未读消息数失败:', error)
return false
}
}
// 加载即时消息数量
const loadNotificationCount = async () => {
// 由于 /aiol/aiolChat/unread-count 接口不存在,直接使用备用方案
try {
const chatsResponse = await ChatApi.getMyChats()
if (chatsResponse.data?.success) {
notificationCount.value = chatsResponse.data.result.reduce((total: number, chat: any) => {
return total + (chat.unreadCount || 0)
}, 0)
} else {
notificationCount.value = 0
}
} catch (chatError) {
// 静默处理错误设置为0
notificationCount.value = 0
}
}
// 加载评论和@数量
const loadCommentCount = async () => {
try {
const response = await MessageApi.getCommentsAtMessageCount()
if (response.data && response.data.result) {
commentCount.value = response.data.result.unread || 0
console.log('✅ 评论和@未读数量设置为:', commentCount.value)
} else {
commentCount.value = 0
console.log('❌ 评论和@接口响应失败设置为0')
}
} catch (error) {
console.error('获取评论数量失败:', error)
commentCount.value = 0
}
}
// 加载赞和收藏数量
const loadFavoriteCount = async () => {
try {
const response = await MessageApi.getLikesMessageCount()
console.log('🔍 loadFavoriteCount 响应数据:', response)
if (response.data && response.data.result) {
favoriteCount.value = response.data.result.unread || 0
console.log('✅ 赞和收藏未读数量设置为:', favoriteCount.value)
} else {
favoriteCount.value = 0
console.log('❌ 赞和收藏接口响应失败设置为0')
}
} catch (error) {
console.error('获取收藏数量失败:', error)
// 如果接口不存在设置为0不显示错误消息
favoriteCount.value = 0
}
}
// 加载系统消息数量
const loadSystemCount = async () => {
try {
console.log('🔍 开始加载系统消息数量')
const response = await MessageApi.getSystemMessageCount()
console.log('🔍 系统消息数量API响应:', response)
if (response.code === 200 && response.data) {
systemCount.value = response.data.unread || 0
console.log('✅ 系统消息数量:', systemCount.value)
} else {
console.warn('⚠️ 系统消息数量API返回错误:', response)
systemCount.value = 0
}
} catch (error) {
console.error('❌ 获取系统消息数量失败:', error)
systemCount.value = 0
}
}
// Tab切换处理
const handleTabChange = (tabName: string) => {
activeTab.value = tabName
// 切换Tab时刷新对应数据
debouncedRefresh()
}
</script>
<style scoped>
.message-center {
padding: 20px;
background-color: #fff;
}
.tab-container {
margin-bottom: 9px;
}
.message-tabs {
--n-tab-text-color: #666;
--n-tab-text-color-active: #1890ff;
--n-bar-color: #1890ff;
}
.tab-item {
position: relative;
display: flex;
align-items: center;
gap: 8px;
}
.tab-badge {
position: relative;
top: -2px;
}
.tab-content {
min-height: 400px;
}
/* 调整badge样式 */
:deep(.n-badge) {
--n-color: #ff4d4f;
--n-text-color: #fff;
--n-font-size: 12px;
}
/* 调整tabs整体样式 */
:deep(.n-tabs .n-tabs-nav .n-tabs-nav-scroll-content) {
gap: 32px;
}
:deep(.n-tabs .n-tabs-tab) {
padding: 12px 0;
font-size: 16px;
font-weight: 500;
}
</style>