添加已读未读功能

This commit is contained in:
2026-02-26 18:34:00 +08:00
parent 7ff2382025
commit fdb4a56197
2 changed files with 46 additions and 3 deletions

View File

@@ -50,6 +50,9 @@
<PictureMessage v-else-if="msg.type === 'image'" :item="msg" /> <PictureMessage v-else-if="msg.type === 'image'" :item="msg" />
<MiniPKMessage v-else-if="msg.type === 'pk'" :item="msg" /> <MiniPKMessage v-else-if="msg.type === 'pk'" :item="msg" />
<VoiceMessage v-else-if="msg.type === 'audio'" :item="msg.payload.url" :size="msg.payload.duration" /> <VoiceMessage v-else-if="msg.type === 'audio'" :item="msg.payload.url" :size="msg.payload.duration" />
<div v-if="msg.senderId == currentUser.id" class="read-status">
{{ msg.read ? '已读' : '未读' }}
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -276,6 +279,7 @@ onMounted(() => {
if (goeasy) { if (goeasy) {
goeasy.im.on(GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, onMessageReceived) goeasy.im.on(GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, onMessageReceived)
goeasy.im.on(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, onConversationsUpdated) goeasy.im.on(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, onConversationsUpdated)
goeasy.im.on(GoEasy.IM_EVENT.MESSAGE_READ, onMessageRead)
} }
} }
// 切换回消息页面时,滚到聊天记录最底部 // 切换回消息页面时,滚到聊天记录最底部
@@ -297,6 +301,16 @@ function onConversationsUpdated(conversations) {
console.log("chatList返回",chatList.value) console.log("chatList返回",chatList.value)
} }
function onMessageRead(messages) {
// 收到对方已读回执,更新本地消息的 read 状态
messages.forEach(readMsg => {
const target = messagesList.value.find(m => m.messageId === readMsg.messageId)
if (target) {
target.read = true
}
})
}
function onMessageReceived(message) { function onMessageReceived(message) {
if (!isGoEasyEnabled()) return if (!isGoEasyEnabled()) return
// 始终累加会话未读数和更新最后一条消息(全局 unreadStore 由 PkAppaside 统一维护) // 始终累加会话未读数和更新最后一条消息(全局 unreadStore 由 PkAppaside 统一维护)
@@ -319,6 +333,7 @@ onUnmounted(() => {
try { try {
goeasy.im.off(GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, onMessageReceived) goeasy.im.off(GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, onMessageReceived)
goeasy.im.off(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, onConversationsUpdated) goeasy.im.off(GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, onConversationsUpdated)
goeasy.im.off(GoEasy.IM_EVENT.MESSAGE_READ, onMessageRead)
} catch (e) { } catch (e) {
console.warn('清理 GoEasy 监听器失败', e) console.warn('清理 GoEasy 监听器失败', e)
} }
@@ -565,6 +580,17 @@ onUnmounted(() => {
} }
} }
.read-status {
font-size: 11px;
color: #94a3b8;
text-align: right;
margin-top: 4px;
}
.message-item.mine .read-status {
color: #60a5fa;
}
.empty-tip { .empty-tip {
text-align: center; text-align: center;
padding: 50px; padding: 50px;

View File

@@ -121,7 +121,10 @@
<!-- 聊天面板 --> <!-- 聊天面板 -->
<div class="chat-panel"> <div class="chat-panel">
<div v-if="selectedItem" class="chat-container"> <div v-if="selectedItem" class="chat-container">
<div class="chat-header">{{ chatUserInfo.nickName || '聊天' }}</div> <div class="chat-header">
<span class="chat-header-label">聊天</span>
<span v-if="chatUserInfo.nickName" class="chat-header-name">· {{ chatUserInfo.nickName }}</span>
</div>
<div class="chat-messages" ref="chatMessagesRef" :style="{ visibility: isScrollReady ? 'visible' : 'hidden' }"> <div class="chat-messages" ref="chatMessagesRef" :style="{ visibility: isScrollReady ? 'visible' : 'hidden' }">
<div <div
v-for="(msg, index) in messagesList" v-for="(msg, index) in messagesList"
@@ -235,6 +238,9 @@ import PictureMessage from '@/components/pk-mini/chat/PictureMessage.vue'
import MiniPKMessage from '@/components/pk-mini/chat/MiniPKMessage.vue' import MiniPKMessage from '@/components/pk-mini/chat/MiniPKMessage.vue'
import VoiceMessage from '@/components/pk-mini/chat/VoiceMessage.vue' import VoiceMessage from '@/components/pk-mini/chat/VoiceMessage.vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { pkUnreadStore } from '@/stores/pk-mini/notice.js'
const unreadStore = pkUnreadStore()
// 导入本地图片 // 导入本地图片
import iconSearch from '@/assets/pk-mini/Search.png' import iconSearch from '@/assets/pk-mini/Search.png'
@@ -455,6 +461,10 @@ async function sendMessage() {
inputText.value = '' inputText.value = ''
await nextTick() await nextTick()
scrollToBottom() scrollToBottom()
// 发送消息后标记已读,清除导航栏红点
const senderId = String(selectedItem.value.senderId)
goEasyMessageRead({ id: senderId }).catch(() => {})
unreadStore.decrease(1)
} catch (e) { } catch (e) {
console.error('发送消息失败', e) console.error('发送消息失败', e)
if(e =='Error: id can not be the same as your id'){ if(e =='Error: id can not be the same as your id'){
@@ -909,13 +919,20 @@ onUnmounted(() => {
.chat-header { .chat-header {
height: 50px; height: 50px;
text-align: center; display: flex;
line-height: 50px; align-items: center;
justify-content: center;
gap: 6px;
font-weight: bold; font-weight: bold;
color: #666; color: #666;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.chat-header-name {
color: #2563eb;
font-size: 14px;
}
.chat-messages { .chat-messages {
flex: 1; flex: 1;
overflow: auto; overflow: auto;