fix(ai-nutritionist): unwrap double-layer Coze API responses

CRMEB wraps CozeBaseResponse again, so chat/retrieve/message payloads live at response.data.data. Added unwrapCozeResponse() and applied it to sendToAI, pollChatStatus, and getChatMessages. Updated test log.

Made-with: Cursor
This commit is contained in:
panchengyong
2026-03-25 17:21:12 +08:00
parent 6ec9487597
commit 3329a2b296
2 changed files with 60 additions and 20 deletions

View File

@@ -0,0 +1,23 @@
# 手动测试问题
## 页面pages/tool/food-encyclopedia测试
- 1. **已修复**页面pages/tool/food-encyclopedia报错
- 2. **已修复**页面pages/tool/food-encyclopedia中class="category-badge"改成显示中文
- 3. **已修复**页面pages/tool/food-encyclopedia点击进入详情页
## 页面pages/tool/nutrient-detail?name=%E9%92%BE
- 1. **已修复**显示空白页返回数据为空如果是因为v2_knowledge 表尚无营养素数据通过ai生成需要的数据可以插入到v2_knowledge表中
## 页面pages/tool/ai-nutritionist
- 1. 优化方案:/Users/a123/msh-system/docs/功能开发详细设计_2026-03-25.md
- 2. 对话响应还是很慢是否可以使用SSE流式对话来优化响应速度
- 3. **已修复** 会话错误:"发起对话失败未返回会话或对话ID"
# 参考文档
- 1. /Users/a123/msh-system/docs/测试问题分析报告_2026-03-22.md
- 2. /Users/a123/msh-system/docs/功能开发详细设计_2026-03-25.md

View File

@@ -637,6 +637,19 @@ export default {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
}, },
/**
* 解包 Coze API 响应:后端返回双层包装 { code, data: { code, data: actualPayload } }
* 此方法统一提取最内层的业务数据
*/
unwrapCozeResponse(response) {
if (!response) return null;
let data = response.data;
if (data && typeof data === 'object' && data.code !== undefined && data.data !== undefined) {
data = data.data;
}
return data;
},
async sendToAI(content, type) { async sendToAI(content, type) {
this.isLoading = true; this.isLoading = true;
@@ -708,14 +721,16 @@ export default {
}; };
if (this.conversationId) requestData.conversationId = this.conversationId; if (this.conversationId) requestData.conversationId = this.conversationId;
const response = await api.cozeChat(requestData); const response = await api.cozeChat(requestData);
if (response && response.data) { const cozeData = this.unwrapCozeResponse(response);
const chat = response.data.chat || response.data; if (cozeData) {
const chat = cozeData.chat || cozeData;
const conversationId = chat.conversation_id || chat.conversationID || chat.conversationId; const conversationId = chat.conversation_id || chat.conversationID || chat.conversationId;
const chatId = chat.id; const chatId = chat.id;
if (conversationId && chatId) { if (conversationId && chatId) {
this.conversationId = conversationId; this.conversationId = conversationId;
await this.pollChatStatus(conversationId, chatId, aiMsg); await this.pollChatStatus(conversationId, chatId, aiMsg);
} else { } else {
console.error('Coze chat response structure:', JSON.stringify(response));
throw new Error('发起对话失败未返回会话或对话ID'); throw new Error('发起对话失败未返回会话或对话ID');
} }
} else { } else {
@@ -751,9 +766,10 @@ export default {
chatId chatId
}); });
if (res && res.data) { const retrieveData = this.unwrapCozeResponse(res);
console.log("====api.cozeRetrieveChat response====", res.data); if (retrieveData) {
const chatObj = res.data.chat || res.data; console.log("====api.cozeRetrieveChat response====", retrieveData);
const chatObj = retrieveData.chat || retrieveData;
const status = chatObj && chatObj.status; const status = chatObj && chatObj.status;
if (status === 'completed') { if (status === 'completed') {
@@ -790,8 +806,9 @@ export default {
}); });
this.isLoading = false; this.isLoading = false;
console.log("====api.cozeMessageList response====", res.data); const msgData = this.unwrapCozeResponse(res);
const rawMessages = res && res.data && (Array.isArray(res.data.messages) ? res.data.messages : (Array.isArray(res.data) ? res.data : null)); console.log("====api.cozeMessageList response====", msgData);
const rawMessages = msgData && (Array.isArray(msgData.messages) ? msgData.messages : (Array.isArray(msgData) ? msgData : null));
if (rawMessages && rawMessages.length > 0) { if (rawMessages && rawMessages.length > 0) {
// 过滤出 type='answer' 且 role='assistant' 的消息 // 过滤出 type='answer' 且 role='assistant' 的消息
const answerMsgs = rawMessages.filter(msg => msg.role === 'assistant' && msg.type === 'answer'); const answerMsgs = rawMessages.filter(msg => msg.role === 'assistant' && msg.type === 'answer');