feat: 实现饮食记录确认流程

- 新增饮食记录确认流程,将自动记录模式升级为用户确认模式,提升用户交互体验。
- 实现两阶段饮食记录流程,支持AI识别食物并生成确认选项,用户选择后记录到数据库并提供营养分析。
- 扩展DTO层,新增相关数据结构以支持确认流程。
- 更新服务层,新增处理确认逻辑的方法,优化饮食记录的创建流程。
- 增强API文档,详细说明新流程及使用建议,确保开发者理解和使用新功能。
This commit is contained in:
richarjiang
2025-08-18 18:59:36 +08:00
parent 485ba1f67c
commit ede5730647
7 changed files with 903 additions and 30 deletions

View File

@@ -5,7 +5,7 @@ import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
import { CurrentUser } from '../common/decorators/current-user.decorator';
import { AccessTokenPayload } from '../users/services/apple-auth.service';
import { AiCoachService } from './ai-coach.service';
import { AiChatRequestDto, AiChatResponseDto } from './dto/ai-chat.dto';
import { AiChatRequestDto, AiChatResponseDto, AiResponseDataDto } from './dto/ai-chat.dto';
import { PostureAssessmentRequestDto, PostureAssessmentResponseDto } from './dto/posture-assessment.dto';
@ApiTags('ai-coach')
@@ -36,14 +36,31 @@ export class AiCoachController {
// 体重和饮食指令处理现在已经集成到 streamChat 方法中
// 通过 # 字符开头的指令系统进行统一处理
const result = await this.aiCoachService.streamChat({
userId,
conversationId,
userContent,
imageUrls: body.imageUrls,
selectedChoiceId: body.selectedChoiceId,
confirmationData: body.confirmationData,
});
// 检查是否返回结构化数据(如确认选项)
// 结构化数据必须使用非流式模式返回
if (typeof result === 'object' && 'type' in result) {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.send({
conversationId,
data: result.data
});
return;
}
// 普通流式/非流式响应
const readable = result as any;
if (!stream) {
// 非流式:聚合后一次性返回文本
const readable = await this.aiCoachService.streamChat({
userId,
conversationId,
userContent,
imageUrls: body.imageUrls,
});
let text = '';
for await (const chunk of readable) {
text += chunk.toString();
@@ -58,13 +75,6 @@ export class AiCoachController {
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Transfer-Encoding', 'chunked');
const readable = await this.aiCoachService.streamChat({
userId,
conversationId,
userContent,
imageUrls: body.imageUrls,
});
readable.on('data', (chunk) => {
res.write(chunk);
});