愿景规划功能重构
前端并行调用 deepseek-json 替代旧云函数,修复 growth.tsx 语法错误、E2E Alert、云函数超时等 5 个问题
by 于成季
·
愿景规划功能修复记录
功能概述
愿景规划是「知」模块下的核心功能,允许用户:
- 在「愿景」页面(
/zhi/growth)创建/编辑愿望 - 在「规划」页面(
/zhi/vision)查看所有愿望的规划状态 - 在「规划详情」页面(
/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.js的launchBrowser()中注入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
测试覆盖:
- 登录
- 导航到规划详情页
- 点击重新规划
- 等待生成完成(最多 150 秒)
- 验证"重新规划"按钮出现
测试结果:✅ 通过
性能测试
| 阶段 | 耗时 |
|---|---|
| 登录 | ~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
下一步优化方向
- 进度反馈:显示生成进度的详细步骤
- 错误重试:网络异常时自动重试
- 离线支持:Service Worker 缓存
- 性能优化:任务并行数量可配置