Dev/App
APP
考虑到跨平台和开发效率,计划使用:
云乐坊 SSO 回调
移动端使用系统浏览器打开云乐坊授权页,并通过已验证的 HTTPS Universal Links / App Links
返回 https://cook.yunyoujun.cn/auth/callback?platform=native。不要改用自定义 URL Scheme;
PKCE 能阻止授权码被旁路窃取,但不能阻止恶意 App 主动冒充公开客户端发起授权。
iOS 的 Associated Domains 与站点 apple-app-site-association 已纳入项目。Android 上架前还需用
Google Play App Signing 的发布证书 SHA-256 生成站点文件public/.well-known/assetlinks.json,关系必须限定为:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "cn.yunyoujun.cook",
"sha256_cert_fingerprints": [""]
}
}
]不要把本机 debug keystore 指纹发布到生产站点。完成证书配置后,需在真机验证已登录快捷授权、
显式同意、取消、返回键、超时、伪造回调和授权码重放。
Dev/Cli
Cook CLI
Cook CLI 是一个命令行工具,用于管理菜谱数据。
安装
项目依赖已在 workspace 中配置,无需单独安装。
环境配置
数据源
菜谱数据存储在飞书 Wiki 电子表格中:
配置飞书应用
- 复制环境变量模板:
cp .env.example .env- 填写飞书开放平台应用凭证:
# .env
FEISHU_APP_ID=cli_xxxxxxxxxxxxxxxx
FEISHU_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx- 获取飞书凭证:
- 访问 飞书开放平台
- 创建或选择你的应用
- 在"凭证与基础信息"中获取 App ID 和 App Secret
::: tip.env 文件已被 .gitignore 忽略,不会被提交到 Git。
:::
命令
fetch
从飞书拉取菜谱数据并生成 CSV + JSON 文件。
pnpm fetch功能:
- 从飞书 Wiki 获取电子表格数据
- 解析并清洗数据
- 生成
app/data/recipe.csv - 生成
app/data/recipe.json
输出示例:
✔ 从飞书 Wiki 获取电子表格 token...
✔ 读取到 600 行数据 (含表头)
✔ 解析出 599 条菜谱
✔ 写入 app/data/recipe.csv
✔ 写入 app/data/recipe.json::: warning 注意
此命令会覆盖现有的 recipe.csv 和 recipe.json 文件。
:::
convert
将本地 CSV 数据转换为 JSON 格式。
pnpm convert功能:
- 读取
app/data/recipe.csv - 转换为 JSON 格式
- 生成
app/data/recipe.json
使用场景:
- 手动编辑 CSV 后需要重新生成 JSON
- 确保 CSV 和 JSON 数据同步
工作流程
更新菜谱数据
# 1. 从飞书拉取最新数据
pnpm fetch
# 2. 启动开发服务器查看效果
pnpm dev手动编辑数据
# 1. 编辑 app/data/recipe.csv
# 2. 转换为 JSON
pnpm convert
# 3. 查看效果
pnpm dev数据格式
CSV 格式
名称,别名,类别,主料,辅料,调料,做法,难度,耗时,口味,图片,视频
宫保鸡丁,,,鸡胸肉,花生米,干辣椒,炒,简单,30分钟,麻辣,https://...,https://...JSON 格式
[
{
"名称": "宫保鸡丁",
"别名": "",
"类别": "",
"主料": "鸡胸肉",
"辅料": "花生米",
"调料": "干辣椒",
"做法": "炒",
"难度": "简单",
"耗时": "30分钟",
"口味": "麻辣",
"图片": "https://...",
"视频": "https://..."
}
]故障排查
飞书 API 调用失败
错误信息:
Error: Feishu API failed with code 99991663解决方案:
- 检查
.env文件是否存在 - 确认
FEISHU_APP_ID和FEISHU_APP_SECRET是否正确 - 验证应用是否有访问 Wiki 的权限
- 检查飞书 Wiki 链接是否正确配置在代码中
CSV 解析错误
错误信息:
Error: Failed to parse CSV解决方案:
- 检查 CSV 文件格式是否正确
- 确认字段分隔符为逗号
- 检查是否有未闭合的引号
- 验证编码是否为 UTF-8
相关文档
测试
运行测试
# 运行所有测试
pnpm test
# 运行 CLI 相关测试
pnpm test packages/cook
# 运行特定测试文件
pnpm test packages/cook/src/utils/csv.test.ts测试覆盖
CLI 工具包含以下测试:
- CSV 解析测试 (
csv.test.ts)
- ✅ BV 号清洗和 URL 处理
- ✅ CSV 格式解析
- ✅ 空值和边界情况处理
- ✅ 数组字段过滤空值
- ✅ CSV 往返一致性(parse → stringify → parse)
- ✅ 与 fetch 命令输出格式一致性
测试确保 fetch 和 convert 命令产生完全一致的数据格式。
Guide/Getting Started
快速开始
欢迎使用 Cook! 这是一个帮助你决定"今天吃什么"的应用。
环境准备
系统要求
- Node.js >= 22
- pnpm >= 11.21
安装依赖
# 克隆项目
git clone https://github.com/YunYouJun/cook.git
cd cook
# 安装依赖
pnpm install开发
启动开发服务器
pnpm dev访问 <http://localhost:3000> 查看应用。
数据管理
菜谱数据存储在飞书 Wiki 电子表格中:菜谱数据表格
配置飞书应用
如果需要从飞书拉取菜谱数据,请先配置环境变量:
# 1. 复制环境变量模板
cp .env.example .env
# 2. 编辑 .env 文件
# FEISHU_APP_ID=cli_xxxxxxxxxxxxxxxx
# FEISHU_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx获取飞书凭证:
- 访问 飞书开放平台
- 创建或选择应用
- 复制 App ID 和 App Secret
更新菜谱数据
# 从飞书拉取最新数据
pnpm fetch
# 或手动编辑 app/data/recipe.csv 后转换为 JSON
pnpm convert详细的 CLI 使用说明请查看 Cook CLI 文档。
构建
Web 应用
# 构建生产版本
pnpm build
# 预览构建结果
pnpm preview移动应用
iOS
# 构建 iOS 应用
pnpm build:ios
# 在 Xcode 中打开
open ios/App/App.xcworkspaceAndroid
# 构建 Android 应用
pnpm build:android
# 在 Android Studio 中打开
# File > Open > android/项目结构
cook/
├── app/ # 应用源码
│ ├── components/ # Vue 组件
│ ├── composables/ # 组合式函数
│ ├── data/ # 菜谱数据 (CSV + JSON)
│ ├── pages/ # 页面路由
│ └── utils/ # 工具函数
├── docs/ # 文档网站
├── packages/
│ └── cook/ # CLI 工具
├── android/ # Android 应用
├── ios/ # iOS 应用
└── public/ # 静态资源下一步
Index
https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "Cook"
text: "食用手册"
tagline: 今天吃什么
actions:
- theme: brand
text: 开始使用
link: https://cook.yunyoujun.cn
- theme: alt
text: 使用说明
link: /guide/getting-started
features:
- title: Feature A
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
- title: Feature B
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
- title: Feature C
details: Lorem ipsum dolor sit amet, consectetur adipiscing elit