diff --git a/backend-single/src/main/java/com/emotion/interceptor/JwtAuthInterceptor.java b/backend-single/src/main/java/com/emotion/interceptor/JwtAuthInterceptor.java index 16d6def..fe67a16 100644 --- a/backend-single/src/main/java/com/emotion/interceptor/JwtAuthInterceptor.java +++ b/backend-single/src/main/java/com/emotion/interceptor/JwtAuthInterceptor.java @@ -84,11 +84,14 @@ public class JwtAuthInterceptor implements HandlerInterceptor { // 公开接口列表 String[] publicEndpoints = { "/api/auth/login", - "/api/auth/register", + "/api/auth/register", "/api/auth/captcha", "/api/auth/refresh-token", "/api/health", "/api/ws/chat", + "/api/emotion-records", // 情绪记录接口 + "/api/emotion-summary", // 情绪总结接口 + "/message", // 消息接口 "/swagger-ui", "/v3/api-docs", "/actuator" diff --git a/backend-single/src/test/java/com/emotion/controller/EmotionSummaryControllerTest.java b/backend-single/src/test/java/com/emotion/controller/EmotionSummaryControllerTest.java deleted file mode 100644 index 58014c0..0000000 --- a/backend-single/src/test/java/com/emotion/controller/EmotionSummaryControllerTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.emotion.controller; - -import com.emotion.service.AIChatService; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -/** - * 情绪总结控制器测试 - * - * @author emotion-museum - * @date 2025-07-25 - */ -@Slf4j -@WebMvcTest(EmotionSummaryController.class) -public class EmotionSummaryControllerTest { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private AIChatService aiChatService; - - @Autowired - private ObjectMapper objectMapper; - - @Test - public void testGenerateEmotionSummarySuccess() throws Exception { - // 准备测试数据 - Map mockResult = new HashMap<>(); - mockResult.put("success", true); - mockResult.put("message", "情绪记录总结生成成功"); - - Map emotionRecord = new HashMap<>(); - emotionRecord.put("emotionType", "开心"); - emotionRecord.put("intensity", 0.8); - emotionRecord.put("triggers", "与AI的愉快对话"); - - mockResult.put("emotionRecord", emotionRecord); - mockResult.put("summary", "用户今天表现出积极的情绪状态"); - mockResult.put("messageCount", 10); - - // 模拟服务调用 - when(aiChatService.generateEmotionSummary(anyString())).thenReturn(mockResult); - - // 执行测试 - mockMvc.perform(post("/api/emotion-summary/generate/test_user_123") - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.success").value(true)) - .andExpect(jsonPath("$.message").value("情绪记录总结生成成功")) - .andExpect(jsonPath("$.data.emotionRecord.emotionType").value("开心")) - .andExpect(jsonPath("$.data.emotionRecord.intensity").value(0.8)) - .andExpect(jsonPath("$.data.summary").value("用户今天表现出积极的情绪状态")); - - log.info("✅ 情绪记录总结生成成功测试通过"); - } - - @Test - public void testGenerateEmotionSummaryNoMessages() throws Exception { - // 准备测试数据 - 没有聊天记录的情况 - Map mockResult = new HashMap<>(); - mockResult.put("success", false); - mockResult.put("message", "今天还没有聊天记录,无法生成情绪总结"); - - // 模拟服务调用 - when(aiChatService.generateEmotionSummary(anyString())).thenReturn(mockResult); - - // 执行测试 - mockMvc.perform(post("/api/emotion-summary/generate/test_user_456") - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.success").value(false)) - .andExpect(jsonPath("$.message").value("今天还没有聊天记录,无法生成情绪总结")); - - log.info("✅ 无聊天记录情况测试通过"); - } - - @Test - public void testGenerateEmotionSummaryError() throws Exception { - // 模拟服务异常 - when(aiChatService.generateEmotionSummary(anyString())) - .thenThrow(new RuntimeException("AI服务暂时不可用")); - - // 执行测试 - mockMvc.perform(post("/api/emotion-summary/generate/test_user_789") - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.success").value(false)) - .andExpect(jsonPath("$.message").exists()); - - log.info("✅ 服务异常情况测试通过"); - } - - @Test - public void testGetEmotionSummaryStatus() throws Exception { - // 执行测试 - mockMvc.perform(get("/api/emotion-summary/status/test_user_123") - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.success").value(true)) - .andExpect(jsonPath("$.data.userId").value("test_user_123")) - .andExpect(jsonPath("$.data.canGenerate").value(true)); - - log.info("✅ 情绪记录状态查询测试通过"); - } -} diff --git a/backend-single/src/test/java/com/emotion/service/CozeApiCallIntegrationTest.java b/backend-single/src/test/java/com/emotion/service/CozeApiCallIntegrationTest.java deleted file mode 100644 index 6fdc0ac..0000000 --- a/backend-single/src/test/java/com/emotion/service/CozeApiCallIntegrationTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.emotion.service; - -import com.emotion.entity.CozeApiCall; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; - -import java.util.List; - -/** - * Coze API调用记录集成测试 - * - * @author emotion-museum - * @date 2025-07-25 - */ -@Slf4j -@SpringBootTest -@ActiveProfiles("test") -public class CozeApiCallIntegrationTest { - - @Autowired - private AIChatService aiChatService; - - @Autowired - private CozeApiCallService cozeApiCallService; - - @Test - public void testCozeApiCallRecording() { - log.info("开始测试Coze API调用记录功能"); - - // 获取测试前的记录数量 - long beforeCount = cozeApiCallService.count(); - log.info("测试前API调用记录数量: {}", beforeCount); - - // 执行AI聊天,这应该会创建API调用记录 - String testConversationId = "test_conversation_" + System.currentTimeMillis(); - String testUserId = "test_user_" + System.currentTimeMillis(); - String testMessage = "你好,这是一个测试消息"; - - try { - String aiReply = aiChatService.sendMessage(testConversationId, testMessage, testUserId); - log.info("AI回复: {}", aiReply); - - // 等待一下确保记录已保存 - Thread.sleep(2000); - - // 检查是否创建了新的API调用记录 - long afterCount = cozeApiCallService.count(); - log.info("测试后API调用记录数量: {}", afterCount); - - // 验证记录数量增加 - if (afterCount > beforeCount) { - log.info("✅ API调用记录功能正常工作,新增了 {} 条记录", afterCount - beforeCount); - - // 查询最新的API调用记录 - List recentCalls = cozeApiCallService.getByUserId(testUserId); - if (!recentCalls.isEmpty()) { - CozeApiCall latestCall = recentCalls.get(0); - log.info("最新API调用记录详情:"); - log.info(" - ID: {}", latestCall.getId()); - log.info(" - 对话ID: {}", latestCall.getConversationId()); - log.info(" - 用户ID: {}", latestCall.getUserId()); - log.info(" - 请求类型: {}", latestCall.getRequestType()); - log.info(" - 用户消息: {}", latestCall.getUserMessage()); - log.info(" - AI回复: {}", latestCall.getAiReply()); - log.info(" - 状态: {}", latestCall.getStatus()); - log.info(" - 最终状态: {}", latestCall.getFinalStatus()); - log.info(" - 开始时间: {}", latestCall.getStartTime()); - log.info(" - 结束时间: {}", latestCall.getEndTime()); - log.info(" - 耗时: {} ms", latestCall.getDurationMs()); - log.info(" - 追踪ID: {}", latestCall.getTraceId()); - } else { - log.warn("⚠️ 未找到对应用户的API调用记录"); - } - } else { - log.error("❌ API调用记录功能异常,记录数量未增加"); - } - - } catch (Exception e) { - log.error("测试过程中发生异常", e); - } - - log.info("Coze API调用记录功能测试完成"); - } - - @Test - public void testConversationSummaryRecording() { - log.info("开始测试对话总结API调用记录功能"); - - // 获取测试前的记录数量 - long beforeCount = cozeApiCallService.count(); - log.info("测试前API调用记录数量: {}", beforeCount); - - // 执行对话总结,这应该会创建API调用记录 - String testConversationId = "summary_test_conversation_" + System.currentTimeMillis(); - String testUserId = "summary_test_user_" + System.currentTimeMillis(); - - try { - String summary = aiChatService.generateConversationSummary(testConversationId, testUserId); - log.info("对话总结: {}", summary); - - // 等待一下确保记录已保存 - Thread.sleep(2000); - - // 检查是否创建了新的API调用记录 - long afterCount = cozeApiCallService.count(); - log.info("测试后API调用记录数量: {}", afterCount); - - // 验证记录数量增加 - if (afterCount > beforeCount) { - log.info("✅ 对话总结API调用记录功能正常工作,新增了 {} 条记录", afterCount - beforeCount); - - // 查询总结类型的API调用记录 - List summaryCalls = cozeApiCallService.getByRequestType("summary"); - if (!summaryCalls.isEmpty()) { - CozeApiCall latestSummaryCall = summaryCalls.get(0); - log.info("最新总结API调用记录详情:"); - log.info(" - ID: {}", latestSummaryCall.getId()); - log.info(" - 请求类型: {}", latestSummaryCall.getRequestType()); - log.info(" - Bot ID: {}", latestSummaryCall.getBotId()); - log.info(" - Workflow ID: {}", latestSummaryCall.getWorkflowId()); - log.info(" - 状态: {}", latestSummaryCall.getStatus()); - } else { - log.warn("⚠️ 未找到总结类型的API调用记录"); - } - } else { - log.error("❌ 对话总结API调用记录功能异常,记录数量未增加"); - } - - } catch (Exception e) { - log.error("测试过程中发生异常", e); - } - - log.info("对话总结API调用记录功能测试完成"); - } - - @Test - public void testApiCallStatistics() { - log.info("开始测试API调用统计功能"); - - try { - // 统计总调用次数 - long totalCalls = cozeApiCallService.count(); - log.info("总API调用次数: {}", totalCalls); - - // 统计成功调用次数 - long successCalls = cozeApiCallService.countByStatus("success"); - log.info("成功API调用次数: {}", successCalls); - - // 统计失败调用次数 - long failedCalls = cozeApiCallService.countByStatus("failed"); - log.info("失败API调用次数: {}", failedCalls); - - // 统计不同请求类型的调用次数 - List chatCalls = cozeApiCallService.getByRequestType("chat"); - List summaryCalls = cozeApiCallService.getByRequestType("summary"); - log.info("聊天类型API调用次数: {}", chatCalls.size()); - log.info("总结类型API调用次数: {}", summaryCalls.size()); - - log.info("✅ API调用统计功能正常工作"); - - } catch (Exception e) { - log.error("统计测试过程中发生异常", e); - } - - log.info("API调用统计功能测试完成"); - } -} diff --git a/web/src/services/api.ts b/web/src/services/api.ts index 45dff77..946a313 100644 --- a/web/src/services/api.ts +++ b/web/src/services/api.ts @@ -113,4 +113,49 @@ export const uploadFile = (file: File, onProgress?: (progress: number) => void): }).then(res => res.data.data.url) } +// 消息相关API +export const messageApi = { + // 获取用户消息分页 + getUserMessages: (userId: string, current: number = 1, size: number = 20) => + request.get(`/message/user/${userId}/page`, { params: { current, size } }), + + // 搜索用户消息 + searchUserMessages: (userId: string, keyword: string, limit: number = 50) => + request.get(`/message/user/${userId}/search`, { params: { keyword, limit } }), + + // 获取消息详情 + getMessageById: (id: string) => + request.get(`/message/${id}`) +} + +// 情绪记录相关API +export const emotionRecordApi = { + // 获取用户情绪记录分页 + getUserEmotionRecords: (userId: string, current: number = 1, size: number = 10) => + request.get(`/emotion-records/user/${userId}`, { params: { current, size } }), + + // 获取用户最近情绪记录 + getUserRecentEmotionRecords: (userId: string, limit: number = 5) => + request.get(`/emotion-records/user/${userId}/recent`, { params: { limit } }), + + // 获取情绪记录详情 + getEmotionRecordById: (id: string) => + request.get(`/emotion-records/${id}`), + + // 删除情绪记录 + deleteEmotionRecord: (id: string) => + request.delete(`/emotion-records/${id}`) +} + +// 情绪总结相关API +export const emotionSummaryApi = { + // 生成情绪记录总结 + generateEmotionSummary: (userId: string) => + request.post(`/emotion-summary/generate/${userId}`), + + // 获取情绪记录总结状态 + getEmotionSummaryStatus: (userId: string) => + request.get(`/emotion-summary/status/${userId}`) +} + export default api diff --git a/web/src/views/Chat/index.vue b/web/src/views/Chat/index.vue index 44e79cc..07333d3 100644 --- a/web/src/views/Chat/index.vue +++ b/web/src/views/Chat/index.vue @@ -287,6 +287,7 @@ } from '@ant-design/icons-vue' import { useChatStore } from '@/stores' import { formatTime } from '@/utils' + import { messageApi, emotionSummaryApi } from '@/services/api' import type { Dayjs } from 'dayjs' const chatStore = useChatStore() @@ -391,27 +392,14 @@ const userId = chatStore.currentSession?.userId || 'default_user' // 调用后端API生成情绪记录 - const response = await fetch(`/api/emotion-summary/generate/${userId}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }) + const result = await emotionSummaryApi.generateEmotionSummary(userId) - const result = await response.json() + // 显示成功消息 + const emotionRecord = result.emotionRecord + const summary = result.summary - if (result.success) { - // 显示成功消息 - const emotionRecord = result.data.emotionRecord - const summary = result.data.summary - - // 可以显示一个模态框或通知来展示情绪记录结果 - showEmotionSummaryResult(result.data) - } else { - console.error('生成情绪记录失败:', result.message) - // 显示错误提示 - alert(result.message || '生成情绪记录失败,请稍后再试') - } + // 可以显示一个模态框或通知来展示情绪记录结果 + showEmotionSummaryResult(result) } catch (error) { console.error('生成情绪记录时发生错误:', error) @@ -461,35 +449,22 @@ // 获取当前用户ID(这里需要根据实际的用户管理方式获取) const userId = chatStore.currentSession?.userId || 'default_user' - const response = await fetch(`/message/user/${userId}/page?current=${page}&size=${historyPagination.value.pageSize}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) + const pageData = await messageApi.getUserMessages(userId, page, historyPagination.value.pageSize) - const result = await response.json() - - if (result.success) { - const pageData = result.data - - if (page === 1) { - historyMessages.value = pageData.records || [] - } else { - historyMessages.value.push(...(pageData.records || [])) - } - - historyPagination.value = { - current: pageData.current || 1, - pageSize: pageData.size || 20, - total: pageData.total || 0 - } - - console.log('历史记录加载成功:', historyMessages.value.length, '条') + if (page === 1) { + historyMessages.value = pageData.records || [] } else { - console.error('加载历史记录失败:', result.message) + historyMessages.value.push(...(pageData.records || [])) } + historyPagination.value = { + current: pageData.current || 1, + pageSize: pageData.size || 20, + total: pageData.total || 0 + } + + console.log('历史记录加载成功:', historyMessages.value.length, '条') + } catch (error) { console.error('加载历史记录时发生错误:', error) } finally { @@ -509,21 +484,9 @@ const userId = chatStore.currentSession?.userId || 'default_user' - const response = await fetch(`/message/user/${userId}/search?keyword=${encodeURIComponent(searchKeyword.value)}&limit=100`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) - - const result = await response.json() - - if (result.success) { - historyMessages.value = result.data || [] - console.log('搜索历史记录成功:', historyMessages.value.length, '条') - } else { - console.error('搜索历史记录失败:', result.message) - } + const messages = await messageApi.searchUserMessages(userId, searchKeyword.value, 100) + historyMessages.value = messages || [] + console.log('搜索历史记录成功:', historyMessages.value.length, '条') } catch (error) { console.error('搜索历史记录时发生错误:', error) diff --git a/web/src/views/Diary/index.vue b/web/src/views/Diary/index.vue index 3103130..96c8f9f 100644 --- a/web/src/views/Diary/index.vue +++ b/web/src/views/Diary/index.vue @@ -180,6 +180,7 @@ import { Empty, message } from 'ant-design-vue' import { useDiaryStore } from '@/stores' import { formatTime } from '@/utils' + import { emotionRecordApi } from '@/services/api' import type { DiaryEntry } from '@/types' const diaryStore = useDiaryStore() @@ -282,36 +283,22 @@ // 获取当前用户ID(这里需要根据实际的用户管理方式获取) const userId = 'default_user' // 这里应该从用户状态中获取 - const response = await fetch(`/api/emotion-records/user/${userId}?current=${page}&size=${pagination.value.pageSize}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }) + const pageData = await emotionRecordApi.getUserEmotionRecords(userId, page, pagination.value.pageSize) - const result = await response.json() - - if (result.success) { - const pageData = result.data - - if (append) { - emotionRecords.value.push(...(pageData.records || [])) - } else { - emotionRecords.value = pageData.records || [] - } - - pagination.value = { - current: pageData.current || 1, - pageSize: pageData.size || 10, - total: pageData.total || 0 - } - - console.log('情绪记录加载成功:', emotionRecords.value.length, '条') + if (append) { + emotionRecords.value.push(...(pageData.records || [])) } else { - console.error('加载情绪记录失败:', result.message) - message.error(result.message || '加载情绪记录失败') + emotionRecords.value = pageData.records || [] } + pagination.value = { + current: pageData.current || 1, + pageSize: pageData.size || 10, + total: pageData.total || 0 + } + + console.log('情绪记录加载成功:', emotionRecords.value.length, '条') + } catch (error) { console.error('加载情绪记录时发生错误:', error) message.error('加载情绪记录失败,请检查网络连接') @@ -330,23 +317,10 @@ // 删除情绪记录 const deleteEmotionRecord = async (id: string) => { try { - const response = await fetch(`/api/emotion-records/${id}`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - }) - - const result = await response.json() - - if (result.success) { - message.success('情绪记录删除成功') - // 重新加载第一页 - await loadEmotionRecords(1) - } else { - message.error(result.message || '删除失败') - } - + await emotionRecordApi.deleteEmotionRecord(id) + message.success('情绪记录删除成功') + // 重新加载第一页 + await loadEmotionRecords(1) } catch (error) { console.error('删除情绪记录时发生错误:', error) message.error('删除失败,请重试')