diff --git a/.idea/AugmentWebviewStateStore.xml b/.idea/AugmentWebviewStateStore.xml index 4c66126..4fc5ce0 100644 --- a/.idea/AugmentWebviewStateStore.xml +++ b/.idea/AugmentWebviewStateStore.xml @@ -3,7 +3,7 @@ diff --git a/backend-single/src/main/java/com/emotion/controller/MessageController.java b/backend-single/src/main/java/com/emotion/controller/MessageController.java index 63a4668..47f1d34 100644 --- a/backend-single/src/main/java/com/emotion/controller/MessageController.java +++ b/backend-single/src/main/java/com/emotion/controller/MessageController.java @@ -79,23 +79,14 @@ public class MessageController { @RequestParam(defaultValue = "20") Long size) { log.info("获取用户消息分页: current={}, size={}", current, size); - try { - // 构建请求对象 - MessagePageRequest request = new MessagePageRequest(); - request.setCurrent(current); - request.setSize(size); + // 构建请求对象 + MessagePageRequest request = new MessagePageRequest(); + request.setCurrent(current); + request.setSize(size); - PageResult pageResult = messageService.getUserMessagesWithPage(request); - log.info("获取用户消息分页成功: total={}", pageResult.getTotal()); - return Result.success(pageResult); - - } catch (IllegalStateException e) { - log.error("用户未认证: {}", e.getMessage()); - return Result.error(401, "用户未登录或认证失败"); - } catch (Exception e) { - log.error("获取用户消息失败", e); - return Result.error(500, "获取消息失败,请稍后重试"); - } + PageResult pageResult = messageService.getUserMessagesWithPage(request); + log.info("获取用户消息分页成功: total={}", pageResult.getTotal()); + return Result.success(pageResult); } /** diff --git a/test-message-history-api.html b/test-message-history-api.html new file mode 100644 index 0000000..23f3d0b --- /dev/null +++ b/test-message-history-api.html @@ -0,0 +1,191 @@ + + + + + + 消息历史API测试 + + + +

消息历史API测试

+ +
+

Token设置

+ + + +
+ +
+

API测试

+ + + + +
+ +
+

测试结果

+
等待测试...
+
+ + + + diff --git a/web/src/stores/chat.ts b/web/src/stores/chat.ts index 1a13bdf..485cc35 100644 --- a/web/src/stores/chat.ts +++ b/web/src/stores/chat.ts @@ -173,28 +173,21 @@ export const useChatStore = defineStore('chat', () => { return segments } - // 添加AI回复消息(支持分段显示) - const addAiReplyMessages = (content: string, delay: number = 1000) => { - const segments = splitAiReply(content) + // 添加AI回复消息(直接显示完整内容) + const addAiReplyMessages = (content: string) => { + // 停止输入状态 + isTyping.value = false - segments.forEach((segment, index) => { - setTimeout(() => { - const aiMessage = addMessage({ - content: segment.trim(), - type: 'ai', - sessionId: currentSession.value?.id - }) - - // 强制触发响应式更新 - console.log('AI消息已添加,当前消息总数:', messages.value.length) - console.log('最新AI消息:', aiMessage) - - // 最后一条消息后停止输入状态 - if (index === segments.length - 1) { - isTyping.value = false - } - }, index * delay) + // 直接添加完整的AI回复 + const aiMessage = addMessage({ + content: content.trim(), + type: 'ai', + sessionId: currentSession.value?.id }) + + // 强制触发响应式更新 + console.log('AI消息已添加,当前消息总数:', messages.value.length) + console.log('最新AI消息:', aiMessage) } // WebSocket消息处理 diff --git a/web/src/views/Chat/index.vue b/web/src/views/Chat/index.vue index ea7309e..a66808a 100644 --- a/web/src/views/Chat/index.vue +++ b/web/src/views/Chat/index.vue @@ -31,7 +31,10 @@
- + + 测试API + +
@@ -344,7 +347,7 @@ messageInput.value = '' await chatStore.sendMessage(content) - scrollToBottom() + forceScrollToBottom() } // 获取连接状态文本 @@ -374,14 +377,55 @@ return '和开开说点什么...' } - const scrollToBottom = () => { + const scrollToBottom = (smooth = true) => { nextTick(() => { if (chatMainRef.value) { - chatMainRef.value.scrollTop = chatMainRef.value.scrollHeight + if (smooth) { + // 平滑滚动到底部 + chatMainRef.value.scrollTo({ + top: chatMainRef.value.scrollHeight, + behavior: 'smooth' + }) + } else { + // 立即滚动到底部 + chatMainRef.value.scrollTop = chatMainRef.value.scrollHeight + } } }) } + // 检查用户是否在聊天底部 + const isUserAtBottom = () => { + if (!chatMainRef.value) return true + + const { scrollTop, scrollHeight, clientHeight } = chatMainRef.value + // 允许一些误差(50px),认为用户在底部 + return scrollHeight - scrollTop - clientHeight < 50 + } + + // 智能滚动到底部(只有用户在底部时才滚动) + const smartScrollToBottom = () => { + if (isUserAtBottom()) { + scrollToBottom(true) + } + } + + // 强制滚动到底部(用于发送消息等场景) + const forceScrollToBottom = () => { + // 立即滚动 + scrollToBottom(false) + + // 延迟滚动,确保内容完全渲染 + setTimeout(() => { + scrollToBottom(true) + }, 100) + + // 再次延迟滚动,处理可能的异步内容 + setTimeout(() => { + scrollToBottom(true) + }, 500) + } + // 生成情绪记录总结 const generateEmotionSummary = async () => { if (emotionSummaryLoading.value) return @@ -437,9 +481,64 @@ }) } + // 打开历史记录抽屉 + const openHistoryDrawer = async () => { + console.log('点击聊天记录按钮') + showHistory.value = true + + // 确保抽屉打开后再加载数据 + await nextTick() + await loadHistoryMessages(1) + } + + // 抽屉打开事件 + const onHistoryDrawerOpen = () => { + console.log('聊天记录抽屉已打开,开始加载历史记录') + loadHistoryMessages(1) + } + + // 测试API调用 + const testAPI = async () => { + console.log('=== 开始测试API ===') + + try { + // 测试原始API调用 + console.log('1. 测试原始axios调用...') + const token = localStorage.getItem('token') + console.log('Token:', token ? `${token.substring(0, 20)}...` : 'null') + + const response = await fetch('/api/message/user/page?current=1&size=5', { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } + }) + + console.log('原始响应状态:', response.status) + const rawData = await response.json() + console.log('原始响应数据:', rawData) + + // 测试封装的API调用 + console.log('2. 测试封装的API调用...') + const apiData = await messageApi.getUserMessages(1, 5) + console.log('封装API返回数据:', apiData) + + } catch (error) { + console.error('API测试失败:', error) + } + + console.log('=== API测试完成 ===') + } + // 加载历史记录 const loadHistoryMessages = async (page = 1) => { - if (historyLoading.value) return + console.log('loadHistoryMessages 被调用,page:', page) + + if (historyLoading.value) { + console.log('已经在加载中,跳过') + return + } try { historyLoading.value = true @@ -448,13 +547,17 @@ page, pageSize: historyPagination.value.pageSize, token: !!localStorage.getItem('token'), - userInfo: userStore.userInfo + userInfo: userStore.userInfo, + apiUrl: `/message/user/page?current=${page}&size=${historyPagination.value.pageSize}` }) // 调用API获取用户消息(后端会从token中获取用户信息) + console.log('正在调用 messageApi.getUserMessages...') const pageData = await messageApi.getUserMessages(page, historyPagination.value.pageSize) - console.log('API返回数据:', pageData) + console.log('API调用成功,返回数据:', pageData) + console.log('API返回数据类型:', typeof pageData) + console.log('API返回数据结构:', Object.keys(pageData || {})) if (page === 1) { historyMessages.value = pageData.records || [] @@ -475,14 +578,24 @@ } catch (error) { console.error('加载历史记录时发生错误:', error) + console.error('错误详情:', { + message: error.message, + response: error.response, + status: error.response?.status, + data: error.response?.data + }) // 显示用户友好的错误信息 if (error.response?.status === 401) { console.log('认证失败,可能需要重新登录') + // 可以在这里添加跳转到登录页的逻辑 } else if (error.response?.status === 500) { console.log('服务器错误,请稍后重试') + } else { + console.log('未知错误:', error.message) } } finally { + console.log('加载历史记录完成,设置 loading 为 false') historyLoading.value = false } } @@ -523,11 +636,36 @@ } } - // 监听消息变化,自动滚动到底部 + // 监听消息变化,智能滚动到底部 watch( () => chatStore.messages.length, + (newLength, oldLength) => { + // 如果有新消息添加 + if (newLength > oldLength) { + const lastMessage = chatStore.messages[chatStore.messages.length - 1] + + // 如果是用户发送的消息,强制滚动 + if (lastMessage?.type === 'user') { + forceScrollToBottom() + } else { + // 如果是AI回复,智能滚动(只有用户在底部时才滚动) + smartScrollToBottom() + } + } + } + ) + + // 监听最后一条消息的内容变化(处理AI回复的实时更新) + watch( () => { - scrollToBottom() + const messages = chatStore.messages + return messages.length > 0 ? messages[messages.length - 1]?.content : '' + }, + (newContent, oldContent) => { + // 如果最后一条消息内容发生变化(AI回复更新),智能滚动 + if (newContent !== oldContent && newContent) { + smartScrollToBottom() + } } ) @@ -567,7 +705,7 @@ // 加载最近的聊天记录 await loadRecentMessages() - scrollToBottom() + forceScrollToBottom() }) // 组件卸载 @@ -720,6 +858,26 @@ flex: 1; overflow-y: auto; padding: $spacing-lg; + scroll-behavior: smooth; // 启用平滑滚动 + + // 确保滚动容器正确工作 + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 3px; + } + + &::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.3); + border-radius: 3px; + + &:hover { + background: rgba(0, 0, 0, 0.5); + } + } } .messages-container {