Grocy 2.5.2 版本解读:家务周期调度升级、购物清单功能开关与日期输入快捷键全解析
【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries & household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocy
本文基于 grocy 2.5.2(2019-10-05 发布)的官方变更记录,深入剖析该版本在库存、菜谱、购物清单、家务(Chores)与日期输入交互五大方向的具体改动。读者将掌握新增的FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS子功能开关的配置方法、家务"年周期 + 周期间隔"调度体系的底层计算逻辑(含 SQL 视图实现)、以及日期字段的完整键盘快捷键速查表,并了解升级到该版本时数据库迁移的注意事项。
一、版本概览:一次以"家务调度"为重心的修复与增强
Grocy 2.5.2 是 2019 年 10 月 5 日发布的维护版本,紧随 2.5.0 / 2.5.1 之后。从变更记录看,该版本的核心工作集中在三块:
- 家务(Chores)模块的功能增强:新增
yearly(每年)周期类型,并引入"周期间隔(period interval)"选项,使调度从"固定周期"走向"每 N 天/周/月/年"的灵活组合; - 大量缺陷修复:覆盖库存(Stock)、菜谱(Recipes)两个核心业务模块;
- 交互效率优化:为日期字段新增以
Shift + 方向键快速增减 1 个月/年的输入快捷键。
下面逐项结合源码剖析其实现与使用方式。
二、库存修复:产品特定数量单位换算覆盖的显示隔离
变更内容:修复了"产品特定数量单位换算(product overrides)在其他具有相同库存数量单位的产品编辑页上也被显示"的问题。
问题背景
在 grocy 中,每个产品可以定义默认数量单位(QU),也可以针对特定产品建立"产品级"的数量单位换算覆盖(即 product overrides)。2.5.2 之前的版本存在一个显示层 bug:当多个产品使用同一个库存数量单位时,某个产品的换算覆盖会被错误地渲染到其他产品的编辑页面上,造成数据混淆——例如给"面粉"配置的500g = 1袋换算,可能错误地出现在同样以克为单位的"砂糖"编辑页上。
修复要点
该问题属于视图(View)层的数据过滤缺陷,修复后每个产品的编辑页(对应views/productform.blade.php所在的表单渲染链路)只展示与自身产品 ID 严格匹配的换算覆盖,不再依据共享的数量单位 ID 做错误关联。从该版本起,涉及数量单位换算配置时,可以确认"一个产品的覆盖配置只会出现在它自己的编辑页"这一行为边界。
三、菜谱修复:总菜谱数超过 100 时成分缺失
变更内容:修复了"当菜谱总数 > 100 时,菜谱显示时缺少成分(ingredients)"的问题。
原因与影响
这是一个典型的分页/查询边界缺陷:当系统中菜谱总量超过 100 条后,菜谱详情页加载成分列表时使用的查询逻辑出现截断,导致成分列表为空或不全。修复后,无论菜谱总量多少,打开单个菜谱都能正确渲染全部成分行。
与菜谱展示相关的完整数据流可参见 controllers/RecipesController.php 与 services/RecipesService.php:前者负责页面路由与渲染参数装配,后者负责从数据库组装菜谱及其recipes_pos(成分明细)数据。2.5.2 的修复即落在这一查询链路的边界条件处理上。
四、购物清单改进:新增FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS子功能开关
变更内容:新增子功能开关FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS,用于在"只需要一个购物清单"的场景下禁用多清单功能;默认值为true,即未配置时行为与之前完全一致。
配置方式
该开关属于"子功能开关(Sub feature flags)"层级,在 config-dist.php 中与同组的其他子功能开关并列定义:
// Sub feature flags Setting('FEATURE_FLAG_STOCK_PRICE_TRACKING', true); Setting('FEATURE_FLAG_STOCK_LOCATION_TRACKING', true); Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING', true); Setting('FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING', true); Setting('FEATURE_FLAG_STOCK_PRODUCT_FREEZING', true); Setting('FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_FIELD_NUMBER_PAD', true); Setting('FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS', true); // ← 2.5.2 新增 Setting('FEATURE_FLAG_RECIPES_MEALPLAN', true); Setting('FEATURE_FLAG_CHORES_ASSIGNMENTS', true); Setting('FEATURE_FLAG_THERMAL_PRINTER', false);与主功能开关(如FEATURE_FLAG_SHOPPINGLIST)不同,这个子开关不会整体隐藏"购物清单"模块,而是控制多清单能力的 UI 与逻辑分支:
true(默认):保留购物清单页面顶部的清单切换下拉框、New shopping list/Edit shopping list等列表操作菜单,支持维护多条清单;false:隐藏清单选择器,购物清单页面退化为"单清单"模式,页面直接使用 id 为 1 的默认清单,界面更简洁。
源码中的实际作用点
该开关在前端三个位置生效,可以直观看到它的控制范围:
- 清单切换器渲染:views/shoppinglist.blade.php 中通过
@if(GROCY_FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS)决定是否渲染下拉切换器;为false时则退化为隐藏域selected-shopping-list(固定值为1),页面始终操作默认清单; - 清单项表单:views/shoppinglistitemform.blade.php 中同样用该标志决定"添加到哪条清单"的选择控件是否出现;
- 清空清单确认文案:public/viewjs/shoppinglist.js 中,关闭多清单时确认弹窗文案由
Are you sure you want to empty shopping list "%s"?简化为Are you sure you want to empty the shopping list?,避免单清单场景下出现无意义的清单名占位。
配置建议
- 个人/家庭单用户场景:若只使用一条清单,可将该开关设为
false以获得更干净的界面; - 多场景(如"日常采购"与"周末大采购"分清单)用户:保持默认
true即可,无需任何改动。
注意:后续版本曾修复"当该开关为
false时,某些操作后清单显示为空"的连带问题(见 changelog/55_2.6.0_2020-01-31.md),若你使用较新版本则无需担心此历史缺陷。
五、家务改进:yearly周期类型与周期间隔(period interval)
变更内容(本版本家务模块的两项核心增强):
- 新增周期类型
yearly(每年),用于年度性家务安排; - 新增每个家务的"周期间隔(period interval)"选项,适用于 daily / weekly / monthly / yearly 四类周期调度,含义是"每 N 天/周/月/年执行一次",例如可实现**双周(biweekly)**调度。
家务周期类型的完整集合
在服务层 services/ChoresService.php 中,定义了 2.5.2 起全部周期类型的常量:
const CHORE_PERIOD_TYPE_HOURLY = 'hourly'; const CHORE_PERIOD_TYPE_DAILY = 'daily'; const CHORE_PERIOD_TYPE_MANUALLY = 'manually'; const CHORE_PERIOD_TYPE_MONTHLY = 'monthly'; const CHORE_PERIOD_TYPE_WEEKLY = 'weekly'; const CHORE_PERIOD_TYPE_YEARLY = 'yearly'; // ← 2.5.2 新增 const CHORE_PERIOD_TYPE_ADAPTIVE = 'adaptive';表单中的调度配置项
在 views/choreform.blade.php 的家务编辑表单中,调度相关字段按周期类型联动显示:
- 周期类型(period_type):下拉选择,
required,含上述全部类型; - 周期天数(period_days):仅对
monthly生效(每月第几天),min = 0; - 每周星期几复选:仅对
weekly生效(周一至周日复选框),选择结果写入隐藏字段period_config; - 周期间隔(period_interval):2.5.2 新增字段,
min = 1,默认1;对hourly / daily / weekly / monthly / yearly五种周期类型均可见,语义为"每隔 N 个基本周期执行一次"(如period_interval = 2+daily即每两天一次,period_interval = 2+weekly即双周一次)。
底层计算逻辑(数据库视图)
家务的下次预计执行时间由数据库视图chores_current统一计算,2.5.2 通过迁移脚本 migrations/0164.sql 重建了该视图,其中period_interval参与各周期类型的推算:
- daily:
DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_interval AS TEXT) || ' day')—— 上次执行时间 + N 天; - weekly:在启用的星期中,取"上次执行时间 + N×7 天(基于
period_interval - 1计算偏移)后下一个匹配星期"作为下次执行时间; - monthly:
start of month偏移 N 个月后再加period_days - 1天,即"每月第 N 天"; - yearly:
MAX(l.tracked_time) + N 年后,取其年份拼接start_date的月日部分,即"每年固定在 start_date 设定的月日执行"。
该视图同时处理manually(固定返回2999-12-31表示永不自动到期)、rollover(过期未做则顺延)等分支逻辑,并只聚合active = 1且未撤销(undone = 0)的跟踪记录,具体可查看 migrations/0164.sql。
迁移脚本对旧数据的兼容处理
migrations/0164.sql 不仅新建了period_interval与start_date字段,还做了三项历史数据适配:
- 为
chores表新增start_date(开始日期),并将已有家务的开始日期回填为最早一次跟踪时间;从未执行过的家务则回填为当天; - 通过
INSERT/UPDATE触发器保证新家务未显式填写开始日期时自动取当前时间; - 将历史遗留的
yearly周期数据转换为daily + period_interval = 365的等价表达(period_interval = IFNULL(period_interval, 1) * 365),确保旧数据迁移后调度语义不变。
配置示例:双周保洁
在"家务"页面新建/编辑家务时:
| 配置项 | 值 | 说明 |
|---|---|---|
| 周期类型 | weekly | 按周调度 |
| 周期间隔 | 2 | 每 2 周执行一次 |
| 星期 | 周六 | 每周期的具体执行日 |
| 开始日期 | 选择首次执行日期 | 作为周期锚点 |
保存后,家务总览页会基于上述配置自动推算下一次预计执行时间。
六、通用改进:日期字段的键盘输入快捷键
变更内容:日期字段新增输入快捷键——通过Shift + 方向键可将日期增减 1 个月/年。
完整快捷键速查表
该能力实现在 public/viewjs/components/datetimepicker.js(前端日期时间选择器组件),综合普通方向键与 Shift 组合键,完整的按键行为如下:
| 按键 | 效果 |
|---|---|
↑ | 日期 -1 天 |
↓ | 日期 +1 天 |
← | 日期 -1 周 |
→ | 日期 +1 周 |
Shift + ↑ | 日期 -1 个月 |
Shift + ↓ | 日期 +1 个月 |
Shift + ← | 日期 -1 年 |
Shift + → | 日期 +1 年 |
| 空输入框 + 任意方向键 | 自动填入今天 |
上述行为对仓库内所有使用日期/日期时间选择器组件的页面(如采购、消费、库存盘点、家务跟踪、任务等)统一生效,无需逐页面配置。
同期的其他日期输入技巧
在 2.5.2 前后,日期输入组件还支持若干文本快捷输入(同样位于 public/viewjs/components/datetimepicker.js):
- 输入
x或X:快捷设为"永不过期"(内部表示为2999-12-31 23:59:59); - 输入
+3d/-2m/+1y:相对今天增减 N 天/月/年; - 输入 4 位数字(如
1015):解析为MMDD,若早于今天则自动顺延到下一年; - 输入 8 位数字(如
20191005):解析为YYYY-MM-DD。
这些快捷键与方向键组合共同构成了 grocy 高效的日期录入体系,尤其适合在购买页批量录入保质期等场景。
七、升级到 2.5.2 的注意事项
从变更记录与迁移脚本可以总结出以下升级要点:
- 数据库会自动迁移:本次升级包含迁移脚本 migrations/0164.sql,会自动为
chores表新增start_date、period_interval字段并重建chores_current视图,无需手工操作,但升级前仍建议备份数据库; - 旧数据兼容:存量家务的开始日期会被自动回填为最早跟踪时间;历史
yearly类型数据会被自动转换为等价的daily + 365表达,调度不会错乱; - 新功能默认开启:
FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS默认true,不修改配置则升级前后行为一致;需要精简界面再将其改为false; - 升级方式:标准 grocy 升级流程为备份数据目录后,以新版本文件覆盖部署并执行一次页面访问以触发数据库迁移(
update.sh与版本文件 version.json 记录了发布版本信息)。
八、小结
Grocy 2.5.2 通过"家务年度周期 + 周期间隔"的组合,将家务调度从"固定每天/每周"扩展为"每 N 天/周/月/年"的灵活模式,配合yearly类型在数据库视图层完成推算;同时以新增子功能开关的方式,让单清单用户能够按需精简购物清单界面;库存与菜谱的两个显示缺陷修复则提升了数据展示的准确性。日期字段的 Shift 快捷键则从交互层面提升了采购、盘点等高频录入场景的效率。该版本是 2.5.x 系列中家务调度能力成型的关键节点,其调度模型与开关设计在此后的版本中持续沿用。
【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries & household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考