项目总览
`doodle` 现在已经不是单一页面,而是一组并排运行的小产品。
共享同一个仓库和部署环境,但它们的用户、页面、路由和工作流各不相同。
这个 handoff 页的存在,就是为了避免每次新 session 都从零重建上下文。
Doodle: 学习动画主产品
Deficit: 家长热量记录模块
Quiz / Vocab / KS2: 练习侧工具
Handoff: 项目沟通与续接面板
这个仓库在解决什么
- Doodle 主线:孩子把知识点复述成动画,按状态机一步步推进。
- Quiz / Vocab / KS2:让学习、考试、词汇复习留在同一体系里。
- Deficit:给家长做日常热量摄入、运动、体重和趋势记录。
- 所有模块共享同一站点、同一部署机、同一 Git 历史,但业务边界要分清。
接手人最容易搞错的地方
- 不要只改 repo 里的静态备份,live 页往往在 `/var/www/edmund-home/`。
- 不要把 Doodle 的孩子状态机逻辑误带进 Deficit;`[deficit]` 是旁路入口。
- 不要一边改多个模块又不做验证,当前项目已经够大,容易相互污染。
- 不要把“开发者解释文字”直接留在用户页面上,页面面向真实使用者,不是面向 AI。
最近完成过的 Deficit 关键工作
06-19
完成首版数据库、API、LLM 解析、bot 标签分发、提醒脚本和前端页面。
06-20
补了历史日期查看与编辑、图表重做、活动档位/BMR 规则调整、常见食物热量表扩展。
06-20
修正 `宝矿力粉 26g` 被错误缓存为水果的问题,基准改为官方 `66g = 257 kcal`。
站点与代码地图
先看站点入口,再看仓库结构。下一位接手时,不用满仓库乱找,可以先定位到正确层级。
线上入口
- `/`:Edmund Workspace 总入口
- `/doodle/`:学习产品集合入口
- `/deficit/index.html`:热量缺口页面
- `/handoff/index.html`:本交接页
repo 里的静态备份
- `frontend/root-index.html`
- `frontend/deficit/index.html`
- `frontend/handoff/index.html`
live 静态目录
- `/var/www/edmund-home/index.html`
- `/var/www/edmund-home/deficit/index.html`
- `/var/www/edmund-home/handoff/index.html`
核心后端模块
| 路径 |
职责 |
备注 |
main.py |
FastAPI 入口,注册 router |
当前已挂 `deficit.router` |
routers/deficit.py |
Deficit 的 REST API |
体重、摄入、运动、总结、趋势、编辑都在这里 |
llm/deficit.py |
`[deficit]` 自然语言解析与落库 |
支持本地食物表、历史回填、USDA 回退 |
bot/handlers.py |
标签分发与主状态机 |
`[deficit]` 必须早于 active project 检查 |
services/usda_fooddata.py |
USDA 查询和缓存 |
中文错配风险高,常见食物应优先写本地表 |
tools/deficit_reminder.py |
每日提醒脚本 |
默认按曼谷时间 21:00 约定运行 |
常用命令
cd /home/ubuntu/doodle
git status --short
pm2 status
pm2 restart doodle
sqlite3 data/doodle.db "SELECT id, food_name, calories, logged_at FROM calorie_intake ORDER BY id DESC LIMIT 10;"
curl -s http://127.0.0.1:8090/doodle/api/health
Deficit 模块交接
这个模块现在已经是一个可独立使用的小产品,不需要登录,入口是 `/deficit/index.html`。
用户是家长,不是孩子,所以它只复用底层设施,不复用 Doodle 的项目状态机体验。
公开入口,无认证
支持补录历史日期与时间
支持体重与 BMI 记录
图表和交互仍可能继续迭代
当前能力
- 记录摄入、运动、体重、活动档位和日汇总。
- 支持自然语言录入:`[deficit] 牛奶 250g + 鸡胸肉 200g`。
- 常见食物先查本地表,查不到再走历史比例或 USDA。
- 活动档位采用基础代谢 `1600`,日常附加 `+200 / +400 / +800`。
- 可查看和编辑历史记录,图表按日 / 周 / 月切换。
关键文件
frontend/deficit/index.html:repo 备份页面
/var/www/edmund-home/deficit/index.html:线上实际页面
data/deficit_food_table.json:本地食物基准表
data/deficit_food_cache.json:USDA 查询缓存
services/deficit_burn_estimator.py:跑步 / 核心 / 力量消耗估算
当前实现链路
网页 /deficit/index.html
├─ GET /doodle/api/deficit/summary/today?date=YYYY-MM-DD
├─ GET /doodle/api/deficit/intake/today?date=YYYY-MM-DD
├─ GET /doodle/api/deficit/burn/today?date=YYYY-MM-DD
├─ POST /doodle/api/deficit/intake
├─ POST /doodle/api/deficit/burn
├─ PATCH /doodle/api/deficit/intake/{id}
└─ PATCH /doodle/api/deficit/burn/{id}
Telegram / Bot
└─ [deficit] xxx
└─ bot/handlers.py
└─ llm/deficit.py
├─ 本地食物表
├─ 历史同名比例
└─ USDA 回退
已经踩过并确认过的坑
| 问题 |
结论 |
| `[deficit]` 被 Doodle 主入口拦住 |
必须在 `on_message()` 里前置分发,不能依赖 active project。 |
| live 页与 repo 页不一致 |
静态页永远双写:`frontend/...` + `/var/www/edmund-home/...`。 |
| 历史记录只能看今天 |
接口与前端都已改成按 `date` 参数走。 |
| 中文食物名被 USDA 缓存错配 |
常见食物优先放本地表;例如 `宝矿力粉` 已修到 `389 kcal / 100g`。 |
马上能继续做的方向
- 继续补常见食物本地基准,减少 USDA 命中率。
- 给 USDA 回退加更严格的语义校验,避免中文词命中无关英文条目。
- 把图表和历史编辑继续打磨到更稳,尤其是密集录入场景。
续接前先核对
- 先看 `DEFICIT_IMPL.md`、`LESSONS.md`、`CODING-LOG.md`。
- 确认 live 页面和 repo 备份页是不是同步。
- 先查数据库真实数据,再决定前端是否真有 bug。
下一次 session 怎么开始
这部分不是功能说明,而是协作规则。下一位无论是人还是 AI,照这个顺序做,能少掉很多上下文消耗和重复犯错。
启动顺序
- 读 `CODEX.md`,再按顺序读 `README.md`、`SPEC.md`、`IMPL.md`、`LESSONS.md`、`CODING-LOG.md`。
- 看这张 handoff 页,确认这次是改 Doodle 主产品、Deficit,还是练习模块。
- 改前先定位 live 文件、repo 文件、后端文件三者关系。
提交前最少验证
- 代码或脚本语法检查通过。
- 如果改了静态页,确认 live 路径可访问、页面包含新内容。
- 如果改了 API,至少打一条真实 curl 或 sqlite 查询核对数据。
- 更新 `CODING-LOG.md`,有新坑就补 `LESSONS.md`。
建议的 handoff 写法
1. 本次做了什么
2. 改了哪些文件
3. 怎么验证的
4. 现在还剩什么
5. 下一步最适合从哪里接