一个基于 Flask + Vanilla JS 的手机 PWA,用来拍照、调用 Gemini API 估算食物热量,并把记录保存到 SQLite。
- 手机浏览器直接拍照或从相册选择照片
- 调用 Gemini 图像理解能力估算餐点总热量
- 自动拆分主要食物项目和份量描述
- 把分析结果和缩略图保存在 SQLite + 本地文件中
- 提供按月份浏览的日历视图,查看每天的总热量和当日明细
- 支持安装为 PWA,缓存基础页面外壳
- 安装 Python 3.11+。
- 创建虚拟环境并安装依赖:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt- 配置环境变量:
cp .env.example .env- 填入
GEMINI_API_KEY。 - 启动开发服务器:
flask --app app run --debug --host 0.0.0.0 --port 5000- 手机和电脑在同一局域网时,可以通过电脑 IP 访问,例如
http://192.168.1.10:5000。
- 复制环境变量模板并填写 Gemini Key:
cp .env.example .env- 启动容器:
docker compose up -d --build-
打开
http://localhost:8000。 如果你修改了.env里的APP_PORT,就改用对应端口。 -
查看日志:
docker compose logs -f- 停止服务:
docker compose down- 镜像使用
gunicorn作为生产 WSGI 服务器。 - 没有
.env时容器也能启动,但图片分析会因为缺少GEMINI_API_KEY而失败。 - 默认持久化卷是
calocalc_data,会保存 SQLite 数据库和上传图片。 - 默认
GUNICORN_WORKERS=1,这是为了更稳妥地配合 SQLite;如果以后换成 PostgreSQL,再考虑增加 worker 进程。 - 容器内监听端口固定为
8000,宿主机端口由.env里的APP_PORT控制。 - 健康检查地址是
/healthz。
- 大多数手机浏览器只允许在安全上下文中调用相机,也就是
https://或localhost。 - 如果你是用手机访问局域网 HTTP 地址,PWA 页面可以打开,但“打开相机”很可能会被浏览器拦截。
- 这种情况下仍然可以使用“从相册选择”,或者把 Flask 服务部署到 HTTPS 域名后再使用拍照。
- Docker 只解决容器化,不会自动提供 HTTPS。要让手机浏览器正常调用相机,仍然建议在容器前面再挂一个提供 HTTPS 的反向代理。
- SQLite 数据库:
instance/calocalc.sqlite - 图片文件:
instance/uploads/
- 卡路里结果是视觉估算,不是医学或营养学精确值。
- PWA 离线时仍可打开页面壳,但图片分析需要网络和可用的 Gemini API Key。