用户使用流程图 — AI助手
端口说明: 📱 小程序 | 🖥 管理后台 | 📋 规划师端 | ⚙️ 系统自动
分层说明: 🏠 页面 → 🔗 API → ⚙️ Service → 📦 数据实体
flowchart TD
%% ============ 颜色定义 ============
classDef page fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
classDef api fill:#fff3e0,stroke:#f57c00,stroke-width:1px
classDef service fill:#e8f5e9,stroke:#388e3c,stroke-width:1px
classDef data fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1px
classDef external fill:#fce4ec,stroke:#d32f2f,stroke-width:1px,stroke-dasharray:3 2
classDef actor fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,stroke-dasharray:5 3
%% ============ 角色 ============
ROLE_USER(("👤 用户(家长/孩子)")):::actor
ROLE_DIFY(("🤖 Dify AI引擎")):::external
ROLE_LG(("🐍 LangGraph Python")):::external
%% ================================================================
%% 阶段一:AI对话
%% ================================================================
subgraph 阶段一[阶段一:AI对话]
direction TB
P1["🏠 小程序:AI聊天页"]:::page
P1 -->|"输入消息"| P1a["🏠 消息输入框"]:::page
P1a -->|"query, conversationId, reportId, surveyId"| A1["🔗 POST /api/ai/chat/send"]:::api
A1 -->|"userId, query, conversationId, inputs"| S1{"⚙️ AIService.sendMessage()<br>优先LangGraph → 回退Dify"}:::service
S1 -->|"query, userId, conversationId"| LG1["⚙️ AiGateway.chat()<br>Python推荐服务"]:::service
LG1 -->|"超时/熔断回退"| DIFY1["⚙️ Dify Chatbot API<br>/chat-messages"]:::service
DIFY1 -->|"answer, conversation_id"| LG1
S1 -->|"解析[TASK]标记"| S1a["⚙️ TaskParseService.parseTasks()"]:::service
S1a -->|"任务标题, 维度, 奖励"| S1b["⚙️ GrowthTaskService.createDynamicTask()"]:::service
S1b -->|"写入动态成长任务"| D_TASKS["📦 growth_tasks 表"]:::data
S1 -->|"镜像会话到本地"| S1c["⚙️ ChatMirrorService.upsertConversation()"]:::service
S1c -->|"userId, difyConversationId, 消息"| D_CHAT["📦 chat_conversations + chat_messages"]:::data
S1 -->|"构建家庭上下文输入"| S2["⚙️ FamilyContextService.buildContext()"]:::service
S2 -->|"用户信息, 孩子列表, 健康报告, 任务统计"| D_CTX["📦 User, ChildInfoDTO, HealthReport<br>(内存组装)"]:::data
S1 -->|"注入AI记忆层"| S2a["⚙️ AIService.enrichInputsWithMemory()"]:::service
S2a -->|"最近3条会话摘要"| D_SUM["📦 ai_conversation_summaries 表"]:::data
S2a -->|"关键事实列表"| D_FACT["📦 ai_user_facts 表"]:::data
A1 -->|"answer, conversationId, tasks[]"| P1b["🏠 显示AI回答 + 推荐任务卡片"]:::page
end
%% ================================================================
%% 阶段二:会话管理
%% ================================================================
subgraph 阶段二[阶段二:会话管理]
P1b -->|"查看历史"| P2["🏠 会话列表页"]:::page
P2 -->|"userId"| A2["🔗 POST /api/ai/chat/conversations"]:::api
A2 -->|"调用Dify GET /conversations"| S3["⚙️ AIService.getConversations()"]:::service
S3 -->|"Dify失败回退本地"| S3a["⚙️ ChatMirrorService.getConversations()"]:::service
S3a -->|"本地镜像会话"| D_CHAT
P2 -->|"选择会话"| P2a["🏠 消息历史页"]:::page
P2a -->|"conversationId"| A3["🔗 POST /api/ai/chat/messages"]:::api
A3 -->|"调用Dify GET /messages"| S4["⚙️ AIService.getMessages()"]:::service
S4 -->|"Dify失败回退本地"| S4a["⚙️ ChatMirrorService.getMessages()"]:::service
S4a -->|"本地消息记录"| D_CHAT
P2a -->|"删除会话"| A4["🔗 POST /api/ai/chat/conversations/{id}/delete"]:::api
A4 -->|"调用Dify DELETE /conversations/{id}"| S5["⚙️ AIService.deleteConversation()"]:::service
end
%% ================================================================
%% 阶段三:精准营养分析
%% ================================================================
subgraph 阶段三[阶段三:精准营养分析]
P1b -->|"报告ID参数"| P3["🏠 营养分析对话页"]:::page
P3 -->|"query, conversationId, reportId"| A5["🔗 POST /api/ai/nutrition/send"]:::api
A5 -->|"reportId"| S6["⚙️ HealthAnalysisService.analyze()"]:::service
S6 -->|"菌群分析结果"| D_HR["📦 HealthReport 肠道报告数据"]:::data
S6 -->|"分析结果 + 家庭上下文"| S7["⚙️ AIService.sendNutritionMessage()"]:::service
S7 -->|"专用dify.nutrition-api-key"| DIFY2["⚙️ Dify精准营养助手<br>/chat-messages"]:::external
A5 -->|"解析[RECOMMEND]标记"| S7a["⚙️ 解析推荐标签 tags/types/limit"]:::service
S7a -->|"营养标签, 类型筛选"| S7b["⚙️ RecommendationService.search()"]:::service
S7b -->|"Product/Activity/Article多表搜索"| D_PROD["📦 products, activities, articles 表"]:::data
A5 -->|"解析[TASK]标记"| S7c["⚙️ TaskParseService + GrowthTaskService"]:::service
S7c -->|"动态成长任务"| D_TASKS
A5 -->|"answer, recommendations[], tasks[]"| P3a["🏠 显示营养建议 + 推荐内容"]:::page
end
%% ================================================================
%% 阶段四:智能推荐
%% ================================================================
subgraph 阶段四[阶段四:智能推荐]
P3a -->|"搜索推荐"| P4["🏠 营养推荐搜索页"]:::page
P4 -->|"nutritionTags, types, limit"| A6["🔗 POST /api/recommend/search"]:::api
A6 -->|"5%灰度→LangGraph"| S8["⚙️ AiGateway.recommend()"]:::service
S8 -->|"Python推荐服务"| LG2["🐍 LangGraph推荐API"]:::external
A6 -->|"本地搜索"| S9["⚙️ RecommendationService.search()"]:::service
S9 -->|"按标签模糊搜索上架商品"| D_PROD
S9 -->|"按标签搜索进行中活动"| D_ACT["📦 activities 表"]:::data
S9 -->|"按标签搜索已发布文章"| D_ART["📦 articles 表"]:::data
P4 -->|"复购提醒"| P4a["🏠 复购提醒列表"]:::page
P4a -->|"userId"| A7["🔗 POST /api/recommend/repurchase-reminders"]:::api
A7 -->|"userId"| S10["⚙️ RecommendationService.getRepurchaseReminders()"]:::service
S10 -->|"未购买提醒记录"| D_REP["📦 repurchase_reminder_record 表"]:::data
P4a -->|"点击提醒"| A8["🔗 POST /api/recommend/repurchase-reminder/{id}/click"]:::api
A8 -->|"reminderId"| S11["⚙️ RecommendationService.markRepurchaseClicked()"]:::service
S11 -->|"更新clicked=1"| D_REP
end
%% ================================================================
%% 阶段五:饮食推荐
%% ================================================================
subgraph 阶段五[阶段五:饮食推荐]
P1b -->|"饮食推荐"| P5["🏠 食谱推荐页"]:::page
P5 -->|"mealType, conversationId"| A9["🔗 POST /api/meal/recommend"]:::api
A9 -->|"userId"| S12["⚙️ MealRecommendService.aggregateContext()"]:::service
S12 -->|"候选食材 + 营养摘要"| D_FOOD["📦 foods, recipes 表"]:::data
S12 -->|"inputs"| S13["⚙️ AIService.sendNutritionMessage()"]:::service
S13 -->|"Dify营养助手"| DIFY2
A9 -->|"answer, replaceOptions, nutritionSummary"| P5a["🏠 展示AI生成食谱"]:::page
P5a -->|"替换食材"| A10["🔗 POST /api/meal/replace"]:::api
A10 -->|"foodId, userId"| S14["⚙️ MealRecommendService.findReplaceCandidate()"]:::service
S14 -->|"同类替代食材"| D_FOOD
P5a -->|"记录饮食"| A11["🔗 POST /api/meal/log"]:::api
A11 -->|"userId, childId, mealType, foods, note"| S15["⚙️ MealLogService.create()"]:::service
S15 -->|"写入饮食记录"| D_LOG["📦 meal_logs 表"]:::data
P5a -->|"查看近期饮食"| A12["🔗 POST /api/meal/logs"]:::api
A12 -->|"userId, days"| S16["⚙️ MealLogService.getRecentMeals()"]:::service
S16 -->|"近N天饮食记录"| D_LOG
P5a -->|"营养摄入统计"| A13["🔗 POST /api/meal/nutrition-summary"]:::api
end
%% ================================================================
%% 阶段六:AI上下文
%% ================================================================
subgraph 阶段六[阶段六:AI上下文与知识库]
A13 -->|"intentType, params"| A14["🔗 POST /api/ai/context"]:::api
A14 -->|"意图: health_report / task_progress / child_info / emotion_status / user_facts"| S17["⚙️ AiContextService.getContext()"]:::service
S17 -->|"健康报告"| D_HR
S17 -->|"任务进度"| D_TASKS
S17 -->|"孩子信息"| D_CHILD["📦 User(孩子角色)"]:::data
S17 -->|"情绪打卡"| D_EMO["📦 emotion_checkins 表"]:::data
S17 -->|"会话摘要Layer1"| D_SUM
S17 -->|"用户事实Layer2"| D_FACT
end
%% ================================================================
%% 角色关联
%% ================================================================
ROLE_USER -.- P1
ROLE_USER -.- P3
ROLE_USER -.- P4
ROLE_USER -.- P5
ROLE_DIFY -.- DIFY1
ROLE_DIFY -.- DIFY2
ROLE_LG -.- LG1
ROLE_LG -.- LG2
端点明细
AI对话
| 端点 |
说明 |
端口 |
请求数据 |
响应数据 |
POST /api/ai/chat/send |
发送聊天消息 |
📱小程序 |
{query, conversationId, reportId, surveyId} |
{answer, conversationId, tasks[]} |
POST /api/ai/chat/conversations |
获取会话列表 |
📱小程序 |
Header: Authorization |
[{id, name, last_message_at, ...}] |
POST /api/ai/chat/messages |
获取消息历史 |
📱小程序 |
{conversationId} |
[{role, content, created_at, ...}] |
POST /api/ai/chat/conversations/{id}/delete |
删除会话 |
📱小程序 |
path: id |
null |
POST /api/ai/nutrition/send |
发送营养分析消息 |
📱小程序 |
{query, conversationId, reportId} |
{answer, conversationId, recommendations[], tasks[]} |
POST /api/ai/context |
获取AI上下文(供Dify回调) |
⚙️系统自动 |
{intentType, userId, params} |
{has_data, ...根据意图的结构化数据} |
智能推荐
| 端点 |
说明 |
端口 |
请求数据 |
响应数据 |
POST /api/recommend/search |
按营养标签推荐搜索 |
📱小程序 |
{userId, nutritionTags[], types[], limit} |
[{type, id, name, description, price, url, source}] |
POST /api/recommend/repurchase-reminders |
获取复购提醒列表 |
📱小程序 |
Header: Authorization |
[{id, productId, name, price, coverImage, reason}] |
POST /api/recommend/repurchase-reminder/{id}/click |
标记复购提醒已点击 |
📱小程序 |
path: id |
null |
POST /api/recommend/repurchase-reminders/list |
获取待处理复购提醒 |
📱小程序 |
Header: Authorization |
[{id, productId, productName, ...}] |
POST /api/recommend/repurchase-reminders/click |
标记已点击 |
📱小程序 |
{id} |
null |
POST /api/recommend/repurchase-reminders/purchased |
标记已购买 |
📱小程序 |
{id, orderId} |
null |
饮食推荐
| 端点 |
说明 |
端口 |
请求数据 |
响应数据 |
POST /api/meal/recommend |
获取AI食谱推荐 |
📱小程序 |
{mealType, conversationId} |
{answer, replaceOptions[], nutritionSummary} |
POST /api/meal/replace |
替换指定食材 |
📱小程序 |
{foodId} |
Food(替代食材) |
POST /api/meal/log |
记录饮食日志 |
📱小程序 |
{childId, mealType, foods[], mealDate, note} |
{id, message} |
POST /api/meal/logs |
获取近期饮食日志 |
📱小程序 |
{days} |
[MealLog] |
POST /api/meal/nutrition-summary |
获取营养摄入统计 |
📱小程序 |
{days} |
{...营养统计数据} |
营养知识库(北京报告)
| 端点 |
说明 |
端口 |
请求数据 |
响应数据 |
POST /api/nutrition/beijing/bacteria/save |
保存/更新菌群状态 |
📱小程序 |
{userId, bacteriaList[{latinName, chineseName, status}]} |
"保存成功" |
POST /api/nutrition/beijing/recommend |
基于菌群数据获取食材推荐 |
📱小程序 |
{userId, limit} |
{foods[], categories[], ...} |
POST /api/nutrition/beijing/recommend/custom |
直接传入菌群状态获取推荐 |
📱小程序 |
{userId, bacteriaList[...], limit} |
{foods[], categories[], ...} |
POST /api/nutrition/beijing/kb/query |
查询菌属知识库 |
📱小程序 |
{name} |
BacteriaEntry(菌属详细) |
POST /api/nutrition/beijing/kb/list |
获取菌属知识库列表 |
📱小程序 |
— |
[BacteriaEntry] |
POST /api/nutrition/beijing/kb/info |
获取知识库概况 |
📱小程序 |
— |
{metadata, 总菌属数, 菌属列表} |
数据实体关系
erDiagram
User ||--o{ ChatConversation : "userId"
ChatConversation ||--o{ ChatMessage : "会话消息"
User ||--o{ AiConversationSummary : "对话摘要"
User ||--o{ AiUserFact : "关键事实"
User ||--o{ HealthReport : "健康报告"
User ||--o{ MealLog : "饮食记录"
Product ||--o{ RepurchaseReminderRecord : "复购提醒"
Article ||--o{ RecommendationResult : "推荐结果"
Activity ||--o{ RecommendationResult : "推荐结果"
GrowthTask ||--o{ AIChatController : "动态任务"
ChatConversation {
Long id PK
Long userId FK
string difyConversationId "Dify会话ID"
string assistantType "family/nutrition"
string title "会话标题"
date lastMessageAt
}
ChatMessage {
Long id PK
Long conversationId FK
string role "user/assistant"
text content
text inputs "上下文快照"
}
AiConversationSummary {
Long id PK
Long userId FK
string conversationId
text summaryText
int messageCount
}
AiUserFact {
Long id PK
Long userId FK
string factKey
string factValue
string sourceConversation
}
HealthReport {
Long id PK
Long userId FK
date reportDate
int overallScore
int gutHealthScore
int nutritionScore
string gutType
}
完整性分析
| # |
维度 |
评估 |
说明 |
| 1 |
流程完整性 |
✅ 完整 |
覆盖AI对话(含LangGraph/Dify双引擎)、会话管理、精准营养分析、智能推荐、饮食推荐、AI上下文6个阶段,路径完整 |
| 2 |
异常路径 |
✅ 完整 |
LangGraph超时/熔断自动回退Dify(AiGateway熔断器);Dify失败回退本地镜像数据(ChatMirrorService);5%灰度流量走LangGraph;所有外部调用有try-catch包裹 |
| 3 |
端点覆盖 |
✅ 完整 |
24个端点全部映射到流程图中,与代码实际暴露的/api/ai/*、/api/recommend/*、/api/meal/*、/api/nutrition/beijing/*一致 |
| 4 |
角色覆盖 |
✅ 完整 |
所有端点为📱小程序端口,家长/孩子/规划师均可使用AI助手;Dify AI引擎和LangGraph Python服务标注为⚙️外部系统 |
| 5 |
数据实体 |
✅ 完整 |
chat_conversations、chat_messages(本地镜像)、ai_conversation_summaries(记忆Layer1)、ai_user_facts(记忆Layer2)、health_reports、foods/meal_logs、repurchase_reminder_record等均在图中映射 |
| 6 |
一致性 |
✅ 与代码一致 |
所有端点路径与实际Controller(AIChatController、RecommendationController、MealRecommendController、BeijingNutritionController)中的@PostMapping匹配 |