聊天室完成
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
<button
|
||||
v-for="room in filteredRooms.slice(0, 8)"
|
||||
:key="room.roomId"
|
||||
@click="selectRoom(room.roomId!); toggleSidebar()"
|
||||
@click="selectRoom(room)"
|
||||
class="sidebar-icon-btn"
|
||||
:class="{ active: currentRoomId === room.roomId }"
|
||||
:title="room.roomName"
|
||||
@@ -55,7 +55,7 @@
|
||||
:key="room.roomId"
|
||||
class="room-item"
|
||||
:class="{ active: currentRoomId === room.roomId }"
|
||||
@click="selectRoom(room.roomId!)"
|
||||
@click="selectRoom(room)"
|
||||
>
|
||||
<!-- 头像 -->
|
||||
<div class="room-avatar">
|
||||
@@ -85,21 +85,28 @@
|
||||
<!-- 主聊天区域 -->
|
||||
<main class="chat-main" :class="{ 'sidebar-open': isSidebarOpen }">
|
||||
<template v-if="currentRoomId">
|
||||
<ChatRoom
|
||||
ref="chatRoomRef"
|
||||
:messages="messages"
|
||||
:current-user-id="loginDomain.user.userId"
|
||||
:room-name="currentRoom?.roomName"
|
||||
:meeting-url="currentMeetingUrl"
|
||||
:show-meeting="showMeetingIframe"
|
||||
:file-download-url="FILE_DOWNLOAD_URL"
|
||||
:has-more="hasMore"
|
||||
:loading-more="loadingMore"
|
||||
@send-message="handleSendMessage"
|
||||
@start-meeting="startMeeting"
|
||||
@download-file="downloadFile"
|
||||
@load-more="loadMoreMessages"
|
||||
>
|
||||
<div class="chat-room-wrapper">
|
||||
<!-- 自动填充加载遮罩 -->
|
||||
<div v-if="autoFilling" class="auto-fill-mask">
|
||||
<div class="loading-spinner"></div>
|
||||
<div class="loading-text">正在加载历史消息...</div>
|
||||
</div>
|
||||
|
||||
<ChatRoom
|
||||
ref="chatRoomRef"
|
||||
:messages="messages"
|
||||
:current-user-id="loginDomain.user.userId"
|
||||
:room-name="currentRoom?.roomName"
|
||||
:meeting-url="currentMeetingUrl"
|
||||
:show-meeting="showMeetingIframe"
|
||||
:file-download-url="FILE_DOWNLOAD_URL"
|
||||
:has-more="hasMore"
|
||||
:loading-more="loadingMore"
|
||||
@send-message="handleSendMessage"
|
||||
@start-meeting="startMeeting"
|
||||
@download-file="downloadFile"
|
||||
@load-more="loadMoreMessages"
|
||||
>
|
||||
<template #header>
|
||||
<div class="chat-room-header">
|
||||
<div class="header-left">
|
||||
@@ -123,6 +130,7 @@
|
||||
</ElButton>
|
||||
</template>
|
||||
</ChatRoom>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 空状态 -->
|
||||
@@ -193,6 +201,8 @@ const userType = true //web端固定这个
|
||||
const loading = ref(false)
|
||||
const messageLoading = ref(false)
|
||||
const loadingMore = ref(false)
|
||||
// 自动填充加载状态
|
||||
const autoFilling = ref(false)
|
||||
|
||||
// 分页状态
|
||||
const PAGE_SIZE = 5
|
||||
@@ -242,9 +252,11 @@ const fetchChatRooms = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await workcaseChatAPI.getChatRoomPage({
|
||||
filter: { status: 'active' },
|
||||
filter: {
|
||||
status: 'active'
|
||||
},
|
||||
pageParam: { page: 1, pageSize: 100, total: 0 }
|
||||
}, loginDomain.user.userId)
|
||||
})
|
||||
if (result.success && result.pageDomain) {
|
||||
chatRooms.value = result.pageDomain.dataList || []
|
||||
}
|
||||
@@ -258,24 +270,25 @@ const fetchChatRooms = async () => {
|
||||
}
|
||||
|
||||
// 选择聊天室
|
||||
const selectRoom = async (roomId: string) => {
|
||||
currentRoomId.value = roomId
|
||||
const selectRoom = async (room: ChatRoomVO) => {
|
||||
currentRoomId.value = room.roomId!
|
||||
|
||||
// 自动加入聊天室成员表(如果不存在)
|
||||
try {
|
||||
const memberData: TbChatRoomMemberDTO = {
|
||||
roomId: roomId,
|
||||
roomId: room.roomId,
|
||||
userId: loginDomain.user.userId,
|
||||
userName: loginDomain.userInfo.username,
|
||||
userType: 'staff'
|
||||
}
|
||||
await workcaseChatAPI.addChatRoomMember(memberData)
|
||||
room.unreadCount = 0
|
||||
} catch (error) {
|
||||
// 已存在成员或其他错误,忽略
|
||||
console.debug('加入聊天室:', error)
|
||||
}
|
||||
|
||||
loadMessages(roomId)
|
||||
loadMessages(room.roomId!)
|
||||
}
|
||||
|
||||
// 加载消息(初始加载page1,后端降序返回)
|
||||
@@ -296,6 +309,9 @@ const loadMessages = async (roomId: string) => {
|
||||
// 后端降序返回,需要反转后显示(早的在上,新的在下)
|
||||
const dataList = result.pageDomain.dataList || []
|
||||
messages.value = [...dataList].reverse()
|
||||
|
||||
// 首次加载后自动填充消息直到出现滚动条
|
||||
await autoFillMessages(roomId)
|
||||
}
|
||||
// 加载完成后滚动到底部
|
||||
scrollToBottom()
|
||||
@@ -307,6 +323,85 @@ const loadMessages = async (roomId: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 自动填充消息直到出现滚动条
|
||||
const autoFillMessages = async (roomId: string) => {
|
||||
autoFilling.value = true
|
||||
console.log('[autoFill] 开始检查消息高度, hasMore:', hasMore.value, 'messages:', messages.value.length)
|
||||
|
||||
// 等待DOM渲染
|
||||
await nextTick()
|
||||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
|
||||
let attempts = 0
|
||||
const maxAttempts = 20
|
||||
|
||||
while (hasMore.value && attempts < maxAttempts) {
|
||||
attempts++
|
||||
|
||||
const container = chatRoomRef.value?.$el?.querySelector?.('.messages-container')
|
||||
const messagesList = chatRoomRef.value?.$el?.querySelector?.('.messages-list')
|
||||
|
||||
if (!container || !messagesList) {
|
||||
console.warn('[autoFill] 找不到容器或消息列表')
|
||||
break
|
||||
}
|
||||
|
||||
// 容器高度(可视区域)
|
||||
const containerHeight = container.clientHeight
|
||||
// 消息列表实际高度(内容)
|
||||
const listHeight = messagesList.offsetHeight
|
||||
const fillPercent = containerHeight > 0 ? Math.round(listHeight / containerHeight * 100) : 0
|
||||
|
||||
console.log(`[autoFill] 第${attempts}次检查 - 容器高度: ${containerHeight}px, 列表高度: ${listHeight}px, 填充率: ${fillPercent}%, 消息数: ${messages.value.length}`)
|
||||
|
||||
// 判断是否已经溢出(列表高度 >= 容器高度)
|
||||
if (containerHeight > 0 && listHeight >= containerHeight) {
|
||||
console.log(`[autoFill] ✓ 列表已溢出(${fillPercent}%),可以滚动!停止加载`)
|
||||
break
|
||||
}
|
||||
|
||||
// 内容不足,继续加载下一页
|
||||
console.log('[autoFill] → 内容不足,继续加载历史消息...')
|
||||
const nextPage = currentPage.value + 1
|
||||
const result = await workcaseChatAPI.getChatMessagePage({
|
||||
filter: { roomId },
|
||||
pageParam: { page: nextPage, pageSize: PAGE_SIZE }
|
||||
})
|
||||
|
||||
if (result.success && result.pageDomain) {
|
||||
const pageInfo = result.pageDomain.pageParam
|
||||
const actualTotalPages = pageInfo?.totalPages || 1
|
||||
const dataList = result.pageDomain.dataList || []
|
||||
|
||||
if (dataList.length > 0) {
|
||||
currentPage.value = nextPage
|
||||
hasMore.value = actualTotalPages > currentPage.value
|
||||
|
||||
// 反转后插入到列表前面
|
||||
const reversedList = [...dataList].reverse()
|
||||
messages.value.unshift(...reversedList)
|
||||
console.log(`[autoFill] ✓ 加载第${nextPage}页完成, 新增${dataList.length}条, 总消息数: ${messages.value.length}`)
|
||||
|
||||
await nextTick()
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
} else {
|
||||
hasMore.value = false
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (attempts >= maxAttempts) {
|
||||
console.warn('[autoFill] ⚠ 达到最大尝试次数')
|
||||
}
|
||||
|
||||
console.log(`[autoFill] 自动填充结束 - 共尝试${attempts}次, 最终消息数: ${messages.value.length}, hasMore: ${hasMore.value}`)
|
||||
|
||||
autoFilling.value = false
|
||||
}
|
||||
|
||||
// 加载更多历史消息(滚动到顶部触发)
|
||||
const loadMoreMessages = async () => {
|
||||
if (!currentRoomId.value || loadingMore.value || !hasMore.value) return
|
||||
|
||||
Reference in New Issue
Block a user