添加加载,优化气泡弹窗

This commit is contained in:
2026-07-25 18:10:16 +08:00
parent 48452cec2e
commit f240176563
4 changed files with 194 additions and 66 deletions

View File

@@ -41,7 +41,8 @@
<view class="chat-sidebar" :class="{'sidebar-show' : isChatSidebar}">
<ChatSidebar :chatList="UserConversations" v-model:showNewChatModal="showNewChatModal"
v-model:currentSessionId="currentSessionId" v-model:chatType="ChatType"
@refresh-conversations="takeUserConversations">
@refresh-conversations="takeUserConversations"
@select-chat="isChatSidebar = false">
</ChatSidebar>
</view>
@@ -67,6 +68,17 @@
<view class="main-chat">
<scroll-view class="chat-messages" direction="vertical" scroll-y :scroll-into-view="scrollToView"
:upper-threshold="0" :scroll-with-animation="true" @scroll="onScroll">
<!-- 消息加载中弹窗仅会话变化时显示 -->
<view v-if="isLoadingMessages" class="messages-loading-overlay">
<view class="messages-loading-card">
<view class="bubble-loading-dots">
<view class="bubble-dot"></view>
<view class="bubble-dot"></view>
<view class="bubble-dot"></view>
</view>
<text class="messages-loading-text">加载中...</text>
</view>
</view>
<!-- 与AI的对话内容展示 -->
<template v-for="(message, index) in currentMessages" :key="index">
<view v-if="ChatType === 0 && message.role !== 'tool'" class="chat-message" :id="'msg-' + index"
@@ -718,12 +730,14 @@
const isThinking = ref(false)
const isSelfSent = ref(false) // 是否当前设备发起的 AI 对话(用于区分弹窗/仅锁输入)
const isUploading = ref(false)
const isLoadingMessages = ref(false) // 消息加载中状态(仅会话变化时显示)
const uploadedFiles = ref([])
const streamingMessageId = ref(null) // 流式消息的临时 ID用于实时更新 AI 回复
// 消息详情弹窗
const showMessageModal = ref(false)
const detailLinks = ref([])
// 点击气泡内容:拦截链接点击,否则 AI 对话弹出详情
const handleChatContentClick = (e, message) => {
// 在事件路径中向上查找 .chat-inline-link 元素
@@ -738,8 +752,17 @@
}
el = el.parentElement
}
// 非链接点击:仅 AI 对话弹出详情窗
if (message.role) {
// 检查消息内容是否包含链接
const hasLink = message.content && (
message.content.includes('http://') ||
message.content.includes('https://') ||
/<a\s+[^>]*href\s*=\s*['"][^'"]*['"]/i.test(message.content) ||
/\[[^\]]*\]\([^)]*\)/i.test(message.content) // 匹配 Markdown 链接格式
)
// 只有包含链接时才弹出详情窗
if (message.role && hasLink) {
showMessageDetail(message)
}
}
@@ -1347,6 +1370,8 @@
title: `获取ai会话内容失败${error}`,
icon: 'none'
})
} finally {
isLoadingMessages.value = false
}
}
const takeFriendMessages = async () => {
@@ -1360,6 +1385,8 @@
title: `获取好友会话消息失败${error}`,
icon: 'none'
})
} finally {
isLoadingMessages.value = false
}
}
const takeGroupMessages = async () => {
@@ -1382,6 +1409,8 @@
title: `获取群聊会话失败${error}`,
icon: 'none'
})
} finally {
isLoadingMessages.value = false
}
}
// // 加载更多消息
@@ -1443,9 +1472,14 @@
immediate: true
})
watch(currentSessionId, (newId) => {
watch(currentSessionId, async (newId, oldId) => {
if (newId) {
uni.setStorageSync('currentSessionId', currentSessionId.value)
// 会话变化时显示加载弹窗并清空消息
if (oldId && oldId !== newId) {
isLoadingMessages.value = true
allmessages.value = []
}
switch (ChatType.value) {
case 0:
takeConversationMessages();
@@ -1454,10 +1488,10 @@
handleConnect()
break;
case 1:
takeFriendMessages();
await takeFriendMessages();
break;
case 2:
takeGroupMessages();
await takeGroupMessages();
break;
default:
takeConversationMessages();
@@ -1488,6 +1522,7 @@
await takeUserConversations();
// 只有在会话ID存在时才获取消息
if (currentSessionId.value) {
isLoadingMessages.value = true
takeConversationMessages();
}
// AI 对话页面:主动建立 socket 连接,确保消息实时推送
@@ -1496,11 +1531,13 @@
}
} else if (chatType === 1) {
await takeFriendList()
takeFriendMessages();
isLoadingMessages.value = true
await takeFriendMessages();
handleFriendConnect()
} else if (chatType === 2) {
await takeGroupList()
await handleFriendConnect()
isLoadingMessages.value = true
await takeGroupMessages()
}
})
@@ -1626,6 +1663,36 @@
}
}
/* 消息加载中弹窗(仅会话变化时显示) */
.messages-loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(255, 255, 255, 0.9);
z-index: 100;
}
.messages-loading-card {
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx 60rpx;
background: #ffffff;
border-radius: 24rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
}
.messages-loading-text {
margin-top: 20rpx;
font-size: 28rpx;
color: #999;
}
/* 消息详情弹窗 — 链接提取区域 */
.detail-links-section {
margin-top: 24rpx;