# 数据与 AI 结合 — 实现计划 ## 依赖关系图 ``` Phase 1.1 (DB迁移) ──→ 1.3 (createDynamicTask) ──→ 1.4 (Controller改造) │ Phase 1.2 (TaskParseService) ──────────────────────────┘ │ Phase 1.8 (FamilyContext增强) ─────────────────────────┘ ↓ 1.9 (编译验证) │ ┌───────────────────────────────────────┘ ↓ Phase 1.5 (AITaskCard组件) ──→ 1.6 (chat.vue改造) ──→ 1.7 (报告详情页入口) │ ↓ Phase 2.x (持续增强) ``` ## Phase 1: 基础能力 — 2周 ### 1.1 数据库迁移 — growth_tasks 表扩展 **目标:** 支持 AI_GENERATED 类型任务,新增维度跟踪字段 **文件:** - `cfc-backend/src/main/resources/schema.sql` — 同步建表语句 - `cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java` — 迁移代码 - `cfc-backend/src/main/java/com/etotem/cfc/entity/GrowthTask.java` — 新增字段 **迁移内容:** ```sql -- migration N: growth_tasks 支持 AI 生成任务 ALTER TABLE growth_tasks MODIFY COLUMN type ENUM('DAILY','NEWBIE','AI_GENERATED') NOT NULL DEFAULT 'DAILY'; ALTER TABLE growth_tasks ADD COLUMN dimension VARCHAR(20) NULL COMMENT '五维维度'; ALTER TABLE growth_tasks ADD COLUMN source_conversation_id VARCHAR(100) NULL COMMENT '来源AI会话ID'; ``` **实体类新增字段:** ```java @TableField("dimension") private String dimension; @TableField("source_conversation_id") private String sourceConversationId; ``` **验收:** `mvn clean compile` 通过,迁移可重复执行不报错 --- ### 1.2 TaskParseService — [TASK] 标记解析 **目标:** 新建服务解析 Dify 返回的 `[TASK:{...}]` 标记,提取任务参数 **文件:** 新建 `cfc-backend/src/main/java/com/etotem/cfc/service/TaskParseService.java` ``` 1. TASK: 解析 Dify answer 中的 [TASK:{"title":"...","description":"...",...}] 标记 2. EXPECTED OUTCOME: 返回解析后的 TaskParseResult 对象列表 3. REQUIRED TOOLS: 正则 Pattern + Jackson ObjectMapper 4. MUST DO: - 正则 `\[TASK:\s*(\{.*?\})\](?:\s*\[TASK:...)*` 提取所有 TASK 标记 - 解析 JSON → TaskParseResult 对象 - 校验 title 必填 - 返回解析结果列表 - 从原 answer 中移除所有 TASK 标记 5. MUST NOT DO: 不写入数据库(由调用方控制) ``` **TaskParseResult DTO:** ```java public class TaskParseResult { private String title; // 必填 private String description; // 选填 private String deadline; // 选填 yyyy-MM-dd private String dimension; // 选填 body/mind/wisdom/action/wealth private Integer rewardPoints; // 选填 } ``` **验收:** `"[TASK:{\"title\":\"读书30分钟\",\"dimension\":\"wisdom\"}]"` → 解析出 title=读书30分钟, dimension=wisdom --- ### 1.3 GrowthTaskService.createDynamicTask() **目标:** 新增方法,根据 AI 生成的任务参数创建 growth_tasks + growth_task_log **文件:** `cfc-backend/src/main/java/com/etotem/cfc/service/GrowthTaskService.java` **新增方法:** ```java /** * 创建 AI 动态生成任务 * @param userId 目标用户ID * @param task 解析后的任务参数 * @param conversationId 来源AI会话ID * @return 创建的任务ID */ @Transactional public Long createDynamicTask(Long userId, TaskParseResult task, String conversationId) { // 1. 插入 growth_tasks (type=AI_GENERATED, enabled=1) // 2. 插入 growth_task_log (progress=0, completed=0, claimed=0) // 3. 返回 taskId } ``` **验收:** 调用后 growth_tasks 和 growth_task_log 各多一条记录 --- ### 1.4 AIChatController 通用化改造 **目标:** 统一处理 `[RECOMMEND]` 和 `[TASK]` 标记,全模式支持推荐 **文件:** `cfc-backend/src/main/java/com/etotem/cfc/controller/ai/AIChatController.java` **改动点:** 1. **sendMessage() 方法改造:** - 将原来只在 sendNutritionMessage() 中的 RECOMMEND 解析提取为通用方法 - 在 sendMessage() 返回前统一调用 `parseAndHandleMarkers(answer)` - 返回值结构扩展:`{ answer, conversationId, recommendations, tasks }` 2. **parseAndHandleMarkers() 新增方法:** ```java private Map parseAndHandleMarkers(String answer, Long userId, String conversationId) { // 1. 解析 [RECOMMEND:...] → RecommendationService.search // 2. 解析 [TASK:...] → TaskParseService → GrowthTaskService.createDynamicTask // 3. 返回 { cleanAnswer, recommendations, tasks } } ``` 3. **sendNutritionMessage() 简化:** 复用 parseAndHandleMarkers() 避免重复 **验收:** - 普通对话输入"帮我推荐一些健康食品" → response 含 recommendations 列表 - 普通对话输入"给我安排一个每天读书的任务" → response 含 tasks 列表 - 旧功能不受影响(回归:营养对话仍能正常推荐) --- ### 1.5 AITaskCard 组件 **目标:** 可复用的任务卡片组件,展示任务信息 + 接受按钮 **文件:** 新建 `cfc-frontend/components/AITaskCard.vue` ```vue ``` **验收:** 组件在 chat.vue 中导入后可正常渲染和点击接受 --- ### 1.6 chat.vue 改造 **目标:** 支持任务卡片渲染、全模式推荐展示、报告解读模式 **文件:** `cfc-frontend/pages/ai/chat.vue` **改动点:** 1. **消息结构扩展** — 在 data 中支持 tasks 字段 2. **模板新增任务卡片区域** — messages 循环中插入 AITaskCard 3. **推荐卡片区域增强** — 从 only nutrition 模式扩展到所有模式 4. **新模版:`mode=report`** — 接收 reportId 参数,sendMessage 时自动传入 5. **消息气泡标注来源** — 如果是报告解读,气泡上显示"基于健康报告"标签 ``` 改动区段: -