恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

SparkyFitness 膳食分类与自定义餐食:建议时间规则、个性化配置与删除安全机制详解

  • 首页
  • 资讯中心
  • /
  • SparkyFitness 膳食分类与自定义餐食:建议时间规则、个性化配置与删除安全机制详解

相关资讯

Pulse v6 Provider-First 平台落地页:认证根路由与登录跳转的规范解析机制解析 2026/10/10 5:50:13
聊天已死?ChatGPT 之后,用 TaoToken 统一 Key 打通 Codex 与 API 工作流 2026/10/10 5:50:13
TaoToken 实战:让 AI 帮写注释并直接生成代码的配置指南 2026/10/10 5:50:13

最新资讯

下载提速的底层逻辑:从在线解析工具到直链的正确用法
零改造升维:单路视频直接可计算阵地态势底座技术方案
MediaPipe双模疲劳与姿势检测系统实战指南
火车票订票系统实战:从压缩包到高并发防超卖与订单状态机
单片机毕设选题推荐:基于单片机的实验室大气参数与空气质量安全监测装置设计 基于单片机的室内气压异常与空气污染联动声光报警系统设计(030107)
机器学习驱动的恶意加密流量监测:从特征到决策

今日推荐

Codex 总用英文回答?从 AGENTS.md 到 config.toml 的中文输出调优指南
OpenClaw 自定义插件开发完整指南(2026最新版):从 TypeScript 到 npm 发布
基于Spark的电影推荐系统全链路实战:从爬虫到Web展示

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

SparkyFitness 膳食分类与自定义餐食:建议时间规则、个性化配置与删除安全机制详解

发布时间:2026/10/10 5:50:13
SparkyFitness 膳食分类与自定义餐食:建议时间规则、个性化配置与删除安全机制详解 后端前端移动开发【免费下载链接】SparkyFitnessSparkyFitness: Built for Families. Powered by AI. Track food, fitness, water, and health — together.项目地址https://gitcode.com/gh_mirrors/sp/SparkyFitness点击查看免费下载本文围绕 SparkyFitness 的 Meals Meal Categories 功能展开系统讲解日记Diary中膳食分类Meal Category的自动建议时间算法、Web 与移动端的个性化配置入口、自定义餐食Custom Meals的创建方式以及删除膳食分类时涉及的引用统计、数据迁移与级联保护机制。读完本文你将理解default_time从数据库字段到前端选型算法的完整链路并掌握安全删除膳食分类的正确姿势。一、功能全景膳食分类在 SparkyFitness 中扮演的角色SparkyFitness 的膳食模块围绕膳食分类Meal Category / Meal Type组织日记中的所有食物记录。每个分类本质上是meal_types表中的一行记录既包含内置的系统默认分类Breakfast、Lunch、Dinner、Snacks也允许用户创建自定义分类如 Pre-Workout、Brunch。所有食物条目food_entries、已登录的餐食food_entry_meals、膳食计划meal_plans以及膳食计划模板条目meal_plan_template_assignments都通过meal_type_id外键关联到某个分类上。从数据库结构看meal_types表最初由 custom_meal_feature.sql 创建其核心字段包括字段类型说明iduuid主键默认gen_random_uuid()nametext分类名称如breakfast、lunch、snacks、dinneruser_iduuid为空表示系统默认分类非空表示该用户的自定义分类sort_orderint排序权重默认 0created_attimestamptz创建时间default_timetime分类的默认时间后迁移加入迁移脚本还为内置分类写入了固定的排序权重breakfast10、lunch20、snacks30、dinner40并通过meal_types_name_user_unique唯一约束UNIQUE NULLS NOT DISTINCT (name, user_id)保证同名分类不重复。在服务端分类的完整 CRUD 由 mealTypeRoutes.ts 暴露为 REST 接口GET/POST/PUT/DELETE /meal-types、GET /meal-types/:id/deletion-impact底层数据操作则集中在 mealType.ts 模型层。前端Web 与 Mobile和 AI 工具均通过这些接口读写分类。二、建议膳食分类时间default_time的选型算法2.1 核心规则取小于等于当前时间的最近一个默认时间当你记录食物时SparkyFitness 会根据当前时刻动态推荐合适的膳食分类。其规则为找出所有设置了default_time的分类选取其中默认时间小于等于当前时间≤ now且最接近当前时间的那个分类。default_time定义了该分类的时间窗起点直到下一个设置了时间的分类开始之前都归当前分类管。原文档给出的例子若Snacks设为17:00、Dinner设为19:00在17:0018:59之间记录食物 → 自动建议Snacks在19:00及之后记录 → 自动建议Dinner。2.2 源码级实现shared 层的defaultMealTypeForTime该算法并非散落在前端各页面而是集中实现在 shared/src/utils/entryTime.ts 的defaultMealTypeForTime函数中Web、Mobile 与 AI 工具共用同一份规则避免三端行为漂移。其核心逻辑如下把当前时刻转换为分钟数nowMinutes hour * 60 minute遍历所有分类仅保留default_time是合法时间字符串HH:MM或HH:MM:SS的分类找出满足minutes nowMinutes且minutes最大的那一个——即最近一次已到点的默认时间若没有任何分类的默认时间 ≤ 当前时间例如现在是凌晨 2 点而最早的分类默认时间设为 8 点则回退到内置的时段桶fallback bucketsbreakfast小时 11lunch小时 15dinner小时 20其余一律snacks。如果回退桶对应的名称不在用户分类列表中则取列表第一个分类兜底。同文件中的pickMealTypeForTime则返回匹配到的分类行对象而非名称供需要持久化meal_type_id的场景使用——例如移动端添加食物界面或从关联水杯water container按下记录饮水时。prefillEntryTime则负责给日记条目的时间选择器提供预填值若用户正在记录今天的条目预填当前本地时间否则优先用分类的default_time裁剪为HH:MM仍无值则留空时间保持可选。移动端侧constants/meals.ts 的getDefaultMealTypeId直接调用 shared 层的pickMealTypeForTime把后端下发的分类列表与当前时间换算成默认分类 id列表为空时返回null。该文件同时保留了旧的getDefaultMealType静态时段函数h 11早餐、11–14午餐、15–19晚餐、20零食它是default_time机制引入前的兜底逻辑。2.3 时间字符串的合法性校验由于default_time在网络传输中表现为无时区的本地钟面时间PostgresTIME列返回HH:MM:SS请求端通常发HH:MMshared 层用isEntryTimeString正则^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$校验toHourMinute负责把HH:MM:SS归一化为HH:MM。服务端路由在创建/更新分类时也会复用该校验default_time非空且不合法时直接返回400错误信息为default_time must be in HH:MM (24h) format.。三、自定义默认时间的两种入口原文档指出default_time的个性化定制在 Web 与移动端各有入口Web进入设置 → Meal Categories膳食分类为任意分类编辑默认时间HH:MM移动端进入设置 → Food Settings → Suggested Meal Times建议用餐时间调整各分类的目标时间HH:MM。3.1 数据落点系统默认与用户覆盖分离值得深入的是系统默认值与用户覆盖值的分层存储设计。迁移文件 add_entry_time_and_meal_default_time.sql 同时给meal_types与user_meal_visibilities各加了一个default_time列注释明确说明meal_types.default_time系统层面的基础默认时间对内置分类而言是全局基础值user_meal_visibilities.default_time按用户覆盖meal_types.default_time的值与is_visible、show_in_quick_log采用相同的覆盖模式。模型层getAllMealTypes与getMealTypeById都用COALESCE(umv.default_time, mt.default_time)把两层值合并后返回——用户没设置过就用系统默认设置过则用个人值。这样同一份系统默认时间可以被所有用户继承而某个用户调整自己的建议时间不会影响他人。updateMealType中针对default_time的写入采用了显式 flag而非COALESCE合并因为需要区分本次请求没传该字段保持原状与显式传null清除个人覆盖、回落到系统默认两种语义。测试文件 mealTypeDefaultTime.test.ts 用两条用例锁定了这一行为传default_time: 11:30时 upsert 进user_meal_visibilities并写入该值传default_time: null时写入null以清除覆盖。这一个人覆盖优先的设计还体现在其他功能对时间的复用上例如 foodMisc.ts 中咖啡因动力学查询会以COALESCE(umv.default_time, mt.default_time)作为未记录entry_time的条目的时间锚点默认12:00确保用户自定义的用餐时间能正确影响咖啡因窗口计算而不是一律锚定在正午。四、删除自定义膳食分类的安全机制4.1 谁能删、谁不能删系统默认分类user_id IS NULL的四条种子数据只能隐藏、不能删除模型层会抛出Cannot delete system default meal types.并映射为 HTTP403。自定义分类则可以删除但删除前需要审视引用情况。4.2 删除影响预检deletion-impact接口如果分类从未被使用删除会立即生效如果仍有记录引用它Web 端会先展示一个对话框精确列出受影响的范围共四类日记条目food_entries已记录的餐食food_entry_meals膳食计划条目meal_plans膳食计划模板条目meal_plan_template_assignments。服务端为此提供了GET /meal-types/:id/deletion-impact接口见 mealTypeRoutes.ts。其实现countMealTypeReferences对四张表分别计数后汇总totalReferences前端拿到精确数字后即可向用户呈现将要影响 N 条记录。值得注意的实现细节meal_plan_template_assignments表没有user_id列其 RLS 策略通过父模板推导归属因此计数时必须先 join 到meal_plan_templatestemplate_id IN (SELECT id FROM meal_plan_templates WHERE user_id $2)否则会被 RLS 静默过滤成 0。4.3 两种删除选项迁移保留 vs 连坐删除原文档明确给出对话框中的两个选项选项一Move items and delete迁移后删除推荐把所有引用记录重新分配到用户指定的另一个分类。营养数值、日期和时间全部保留仅分类标签改变因此每日总热量不受影响。选项二Delete everything连坐删除不可撤销连同已记录的营养数据一并永久删除。模型层用mode参数区分三种删除模式见 mealType.tsmode行为说明strict默认只要分类仍被引用就拒绝删除对应从未使用则立即删除reassign先把引用记录改指到targetMealTypeId再删除分类对应Move items and deleteforce直接删除引用记录和分类对应Delete everythingreassign模式要求targetMealTypeId合法且不等于被删分类目标同样必须是自己的分类或系统默认分类与getAllMealTypes的可见性规则一致随后对food_entries、food_entry_meals、meal_plans、meal_plan_template_assignments四张表依次执行UPDATE ... SET meal_type_id $target其中food_entries与food_entry_meals使用同一谓词保证餐食容器与其组成条目一起迁移、保持一致。force模式则有一处精妙的级联保护food_entries.food_entry_meal_id引用food_entry_meals且为ON DELETE CASCADE直接删除容器会把子条目一并级联删除。为避免误删用户没要求删除的数据实现会先把属于其他分类但挂在被删容器下的子条目解除关联SET food_entry_meal_id NULL再删除容器与条目——这样级联只会命中目标分类自己的数据。三种模式全部在单个事务中执行且任何 UPDATE/DELETE 之前先做所有权校验分类存在、非系统默认、属于当前用户一旦校验失败立即回滚杜绝改了半截才发现无权限的脏数据。4.4 共享日记人的保护如果与你共享日记的人family access / 委托访问在该分类下仍有条目删除会被拒绝因为这些记录不属于你无权替他人移除。这一点在代码层面由两层机制兜底一是 RLS行级安全天然限制只能操作自己的行二是删除末尾捕获 Postgres 外键错误——四个引用外键均为ON DELETE RESTRICT违反时抛出23001restrict_violation模型层据此抛出Cannot delete this meal type because it is still in use.并映射为409。文件注释特别说明只有同时处理23001与23503两种外键错误码友好提示才真正可达此前只处理23503导致被 RLS 绕过检查的共享记录删除一律变成裸 500。4.5 隐藏 vs 删除原文档给出的实践建议值得强调如果只是想让某个分类从日记中消失优先使用隐藏眼睛图标。隐藏is_visible false只是通过user_meal_visibilities按用户关掉可见性历史记录完整保留随时可以恢复删除则可能涉及不可逆的数据迁移或销毁。五、自定义餐食Custom Meals把食物分组为一顿饭5.1 概念与使用场景自定义餐食由之前添加过的食物组合而成目的是把经常一起吃的食物例如固定的早餐组合打包成一个可复用的餐之后记录时一次添加、不必逐条选择。原文档给出的界面示意如下餐食管理添加餐食5.2 数据模型容器与条目的层级关系从服务端结构看自定义餐食对应food_entry_meals表已登录的餐食它通过meal_type_id归属到某个膳食分类而组成餐食的各个食物条目food_entries通过food_entry_meal_id挂在餐食之下。这种容器 子条目的两级结构正是上一节删除/迁移逻辑中需要同时处理两张表的原因迁移餐食时其子条目必须跟随迁移保持归属一致强制删除时则要先解除其他分类子条目的挂载、再借助ON DELETE CASCADE带走本分类的容器与子条目。5.3 分类与餐食的配合在实际使用中分类Meal Category负责这顿饭属于哪个时间槽、显示在日记的哪一行自定义餐食负责这顿饭由哪些食物组成、一键复用。两者叠加的效果是你可以在某个分类比如 Breakfast下预先做好燕麦 蓝莓 咖啡的自定义餐食记录时系统按当前时间自动建议 Breakfast 分类再从该分类的自定义餐食中一键选择完成一次快速记录。六、AI 工具侧的接入分类数据不仅服务于界面也服务于 AI 工具。在 foodTools.ts 中AI 工具读取膳食分类时会把default_time一并返回给模型使 AI 在帮助用户记录食物时也能感知当前应该建议哪个分类。default_time因此成为一条贯穿数据库 → 服务端 API → 三端 UI → AI 工具的完整数据链路任何一端的个性化设置都会同步影响所有消费方。七、小结与最佳实践清单建议时间的原理取default_time ≤ 当前时间的最近分类无匹配时回退到固定时段桶早餐 11、午餐 15、晚餐 20、其余零食。规则集中在 entryTime.ts三端共享。个性化配置Web 在设置 → Meal Categories移动端在设置 → Food Settings → Suggested Meal Times个人覆盖存于user_meal_visibilities.default_time不影响他人。删除分类前先看影响服务端GET /meal-types/:id/deletion-impact返回四类引用计数reassign迁移保留营养数据force连坐删除且不可撤销优先选reassign。只想眼不见为净就隐藏隐藏保留全部历史删除则有不可逆风险。共享日记人的条目删除会被拒绝409因为记录不属于你无权替他人移除。如需深入了解实现细节可继续阅读以下仓库文件服务端模型层mealType.ts创建/查询/更新/删除/影响统计服务端路由层mealTypeRoutes.tsREST API 与错误码映射共享算法层entryTime.tsdefaultMealTypeForTime/pickMealTypeForTime/prefillEntryTime移动端接入meals.tsgetDefaultMealTypeId与 MealTypeFormSheet.tsx默认时间表单数据库迁移custom_meal_feature.sql 与 add_entry_time_and_meal_default_time.sql单元测试mealTypeDefaultTime.test.tsdefault_time覆盖/清除语义赞分享后端前端移动开发【免费下载链接】SparkyFitnessSparkyFitness: Built for Families. Powered by AI. Track food, fitness, water, and health — together.项目地址https://gitcode.com/gh_mirrors/sp/SparkyFitness点击查看免费下载相关推荐SparkyFitness 食物 API 全解析搜索、分页、日志与自定义食物创建实战指南SparkyFitness 食物 API 全解析搜索、分页、日志与自定义食物创建实战指南 本文基于 SparkyFitness 开源仓库中 food_api.后端前端移动开发Mealie API手册构建自定义膳食应用Mealie API手册构建自定义膳食应用 引言解决膳食管理的开发痛点 你是否正在寻找一个强大的自托管食谱管理解决方案却受限于现有应用的固定功能Meal后端前端TimelineJS医院饮食从流质食品到治疗膳食时间轴TimelineJS医院饮食从流质食品到治疗膳食时间轴 你还在为医院饮食管理的复杂性感到困惑吗医护人员是否需要清晰可视化的方式向患者解释饮食阶段变化本文将前端数据可视化上一篇抖音弹幕抓取神器完整指南3分钟搭建实时数据监控系统下一篇Photon光影包为Minecraft打造电影级视觉体验的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号