愿景规划功能重构

前端并行调用 deepseek-json 替代旧云函数,修复 growth.tsx 语法错误、E2E Alert、云函数超时等 5 个问题

by 于成季 ·

愿景规划功能修复记录

功能概述

愿景规划是「知」模块下的核心功能,允许用户:

  1. 在「愿景」页面(/zhi/growth)创建/编辑愿望
  2. 在「规划」页面(/zhi/vision)查看所有愿望的规划状态
  3. 在「规划详情」页面(/zhi/vision/[id])生成和查看详细规划

数据表结构

表名 用途
user_wishes 用户愿望表,存储愿望标题和状态
wish_milestones 愿望里程碑表,存储生成的里程碑和任务
wish_plan_reports 愿望计划报告表,存储生成状态和 HTML 结果

核心云函数

云函数 用途
deepseek-json 通用 DeepSeek API 调用,返回结构化 JSON
generate-wish 异步生成愿望规划(保留用于兼容性)

架构重构(2026-04-06)

旧架构问题

generate-wish 云函数过于庞大,逻辑全部在服务端执行:

  • 单个函数处理所有业务(查询画像、计划、生成里程碑、生成任务、生成报告)
  • DeepSeek API 调用串行执行,耗时长
  • 前端只能等待,无法并行加速

新架构

┌─────────────────────────────────────────────────────────────┐
│                      前端 App                                 │
│  vision/[id].tsx                                            │
│                                                              │
│  1. 查询用户画像 (RDB)                                       │
│  2. 查询近期计划 (RDB)                                       │
│  3. 调用 deepseek-json → 生成里程碑和类别                    │
│  4. 并行调用 deepseek-json → 生成细化任务                   │
│  5. 写入 wish_milestones                                    │
│  6. 写入 wish_plan_reports                                  │
│  7. 刷新 UI                                                 │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                  deepseek-json 云函数                        │
│                                                              │
│  - 通用 DeepSeek API 调用                                    │
│  - 支持 JSON Schema 验证返回格式                             │
│  - 自动重试机制(最多 3 次)                                 │
│  - 15 秒超时保护                                            │
└─────────────────────────────────────────────────────────────┘

流程图

flowchart TD
    subgraph FE[前端 - vision/id.tsx]
        A[用户点击生成规划] --> B{已有规划?}
        B -->|否| C[直接生成]
        B -->|是| D[显示确认对话框]
        D --> E[确认重新规划]
        C --> F[删除旧数据和报告]
        E --> F
        F --> G[查询用户画像]
        G --> H[查询近期计划]
        H --> I[构建 plansSummary]
        I --> J[调用 deepseek-json 生成里程碑]
        J --> K[并行调用 deepseek-json 生成任务]
        K --> L[写入 wish_milestones]
        L --> M[写入 wish_plan_reports]
        M --> N[刷新 UI 显示结果]
    end

    subgraph CF[云函数 - deepseek-json]
        O[接收请求] --> P[解析参数]
        P --> Q{参数完整?}
        Q -->|否| R[返回错误]
        Q -->|是| S[调用 DeepSeek API]
        S --> T{成功?}
        T -->|否| U[重试?]
        U -->|是| S
        U -->|否| V[返回错误]
        T -->|是| W[验证 JSON Schema]
        W --> X{验证通过?}
        X -->|否| Y[返回错误]
        X -->|是| Z[返回结构化数据]
    end

    G -.->|查询| MP[mysterious_person_reports]
    H -.->|查询| PLANS[plans]
    L -.->|写入| WM[wish_milestones]
    M -.->|写入| WPR[wish_plan_reports]

发现与修复的问题

问题 1:growth.tsx insert 语法错误

文件zhiyuxing-app/app/(tabs)/zhi/growth.tsx

问题.single 缺少括号 ()

修复:✅ 已修复


问题 2:E2E 测试 Alert 对话框无法操作

文件playwright/helpers.js

问题:Playwright headless 模式下 Alert.alert() 无法弹出,导致测试卡住

修复

  • helpers.jslaunchBrowser() 中注入 window.__E2E__ = true
  • 前端检测到此标志时跳过确认对话框直接执行
// helpers.js
await page.addInitScript(() => {
  window.__E2E__ = true;
});

// vision/[id].tsx
if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined' && (window as any).__E2E__) {
  void handleGenerateWishPlan()
  return
}

状态:✅ 已修复


问题 3:deepseek-json 云函数调用失败

文件zhiyuxing-app/src/lib/deepseek-json.ts

问题cloudbase.functions.invoke 中的 cloudbase 是未初始化的 Proxy,导致调用失败

错误日志

Cannot read properties of undefined (reading 'invoke')

修复:改用 cloudbaseClient.functions.invoke

// 错误
import { cloudbase } from "./cloudbase";
const result = await cloudbase.functions.invoke("deepseek-json", {...});

// 正确
import { cloudbaseClient } from "./cloudbase";
const result = await cloudbaseClient.functions.invoke("deepseek-json", {...});

状态:✅ 已修复


问题 4:生成完成后状态不更新

文件zhiyuxing-app/app/(tabs)/zhi/vision/[id].tsx

问题handleGenerateWishPlan 没有创建 wish_plan_reports 记录,导致 planStatus 始终为 idle

修复:添加记录创建

// ========== 创建报告记录 ==========
await cloudbaseClient.from('wish_plan_reports').insert({
  wish_id: wishId,
  status: 'succeeded',
  result_html: null,
  updated_at: nowStr,
})

状态:✅ 已修复


问题 5:云函数调用缺少超时保护

文件zhiyuxing-app/src/lib/cloudbase.ts

问题:云函数调用没有超时限制,可能导致请求挂起

修复:添加 15 秒超时

const res = await Promise.race([
  cloudbase.callFunction({ name, data: body }),
  new Promise((_, reject) =>
    setTimeout(() => reject(new Error(`云函数 ${name} 调用超时 (15s)`)), 15000)
  ),
]);

状态:✅ 已修复


修复清单

序号 问题 文件 状态
1 .single 缺少括号 growth.tsx ✅ 已修复
2 E2E Alert 无法操作 helpers.js ✅ 已修复
3 deepseek-json 调用失败 deepseek-json.ts ✅ 已修复
4 生成后状态不更新 vision/[id].tsx ✅ 已修复
5 云函数缺少超时 cloudbase.ts ✅ 已修复

测试验证

E2E 测试

cd /Users/orange/github/zhiyuxing/playwright
node test-vision-e2e-20260406-150833.js

测试覆盖

  1. 登录
  2. 导航到规划详情页
  3. 点击重新规划
  4. 等待生成完成(最多 150 秒)
  5. 验证"重新规划"按钮出现

测试结果:✅ 通过

性能测试

阶段 耗时
登录 ~7.4s
导航页面 ~5.2s
检查按钮 ~16ms
点击+确认 ~0.5s
生成总耗时 ~20s
E2E 总耗时 ~33s

说明

  • 生成阶段包括:查询数据 → 生成里程碑 → 分析知行
  • 总耗时约 20 秒,远低于云函数 60s 超时限制

云函数日志查询

# 查看 deepseek-json 调用
tcb fn log deepseek-json --envId jiulou-4gu5ljkpa1082b3c

# 查看 record-token-usage 调用
tcb fn log record-token-usage --envId jiulou-4gu5ljkpa1082b3c

相关文件

前端

文件 用途
zhiyuxing-app/app/(tabs)/zhi/growth.tsx 愿景页(显示愿望列表,点击进入规划详情)
zhiyuxing-app/app/(tabs)/zhi/vision/[id].tsx 规划详情页(独立页面,不显示 Tab)
zhiyuxing-app/src/lib/deepseek-json.ts DeepSeek 调用封装
zhiyuxing-app/src/lib/cloudbase.ts CloudBase 客户端(含超时)
zhiyuxing-app/src/components/WebCapsuleTabBar.tsx Web Tab 栏(规划详情页隐藏)

云函数

文件 用途
cloudbase/functions/deepseek-json/index.js 通用 LLM 调用函数
cloudbase/functions/generate-wish/index.js 原生成函数(保留)

测试

文件 用途
playwright/test-vision-e2e-20260406-150833.js 愿景规划 E2E 测试
playwright/helpers.js Playwright 辅助函数

导航结构

知 (Tab)
├── 主页 (/zhi)
├── 自我 (/zhi/self)
├── 愿景 (/zhi/growth) → 点击愿望卡片 → /zhi/vision/[id](独立页面,无 Tab)
└── 规划详情 (/zhi/vision/[id]) - 独立页面,不显示 Tab

下一步优化方向

  1. 进度反馈:显示生成进度的详细步骤
  2. 错误重试:网络异常时自动重试
  3. 离线支持:Service Worker 缓存
  4. 性能优化:任务并行数量可配置
← 所有文章