夜里喂完一顿奶,手里经常同时占着宝宝和奶瓶,再去翻聊天记录找「上一顿是几点」很不顺手。于是做了这个本地优先、无后端的微信小程序:把喂养、尿布、睡眠、成长和补充剂收成一条时间线,数据写在手机本地;疫苗和体检单独做日程,不跟喂养记录混在同一张表里。
协议 Apache-2.0。源码:GitHub · newborn-feed-tracker
本文偏实现与踩坑。线上小程序名是「小芽拾光记」(简称「小芽拾光」),与仓库同一套代码;下文以仓库与页面逻辑为主。
一、它解决什么问题
对象有两类:正在记新生儿作息的家庭,以及想看原生小程序如何把自定义导航、主题变量和本地数据放在一起的开发者。
交互上就四块:
- 首页:今日喂养次数 / 奶量 / 尿布 / 睡眠,距上次喂养的圆环按分钟刷新,「同上次再记一次」。
- 记录:记一笔。再次进入该 Tab 时表单回到当前时间的空白记录;只有从历史点进某一条,才会带出那条继续改。
- 统计:近 7 天 / 30 天 / 自定义区间的奶量、尿布、睡眠、体重与体温;可与上一周期日均对比。
- 待办:疫苗、体检和其它安排;可按出生日生成常见日程,右侧日期直接改期。
底部只有首页、记录、统计、我的。待办从首页预览和「我的」进入,避免第五个 Tab。
二、界面
首页把「下一顿」放在最显眼的位置;主题可换成晨雾青等配色,深色开关在右上角胶囊左侧。间隔到了、用户打开小程序回到首页时,会进入全屏提醒。
| 首页 | 记录 | 统计 | 我的 |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| 晨雾青 | 深色首页 | 待办 | 提醒闹钟 |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
三、功能分块
| 模块 | 页面上能做什么 |
|---|---|
| 首页 | 今日次数、奶量、尿布、睡眠;距上次喂养圆环;「同上次再记一次」;奶量计算、白噪音哄睡入口;早晚体温待测;待办预览 |
| 记一笔 | 母乳按解封后实际毫升填;奶粉 / 混合;尿布、睡眠、成长、补充剂、体温、洗澡;「同上一次」一键再记 |
| 统计 | canvas 柱状 / 折线;7 天 · 30 天 · 自定义;最高 / 平均 / 最低与环比;WHO 成长对照;点某天看明细 |
| 全部记录 | 按类型筛选、按日分组、左滑删除、点进编辑 |
| 待办 | 疫苗、体检、其它;按出生日生成日程;行内改期、改名称与备注 |
| 提醒 | 超过设定喂养间隔后,进入首页拉起全屏提醒;贪睡约 9 分钟,或停止后静默约 1 小时(间隔约 1.5~4 小时) |
| 数据 | JSON 导出 / 导入(合并或覆盖);CSV;今日摘要 / 7 天周报 / 30 天月报长图 |
| 外观 | 四套主题(靛蓝 / 晨雾青 / 暖阳橘 / 莓果粉)+ 暗黑;老年模式 |
疫苗与体检日程对齐《国家免疫规划疫苗儿童免疫程序及说明(2021 年版)》里的常规剂次,并带上 42 天、满月到 6 岁附近的常见体检节点。这是一份提醒草稿,实际针次以接种门诊和接种证为准。同一标题不会重复生成。
四、技术选型
| 层面 | 选择 | 原因 |
|---|---|---|
| 框架 | 微信小程序原生 | 页面不多,自定义导航和 Tab 用原生更直接 |
| 数据 | wx.setStorageSync,单键 newborn_feed_v1 |
奶量和作息留在设备上,不先注册再上传 |
| 图表 | utils/charts.js canvas 2d 手绘 |
柱状与折线不引入图表库 |
| 图标 | utils/icons.js 生成 SVG data URI |
颜色、尺寸随主题变,无图标字体 |
| 导航 | 自定义 navigationStyle,度量在 utils/nav.js |
右上角胶囊位置每台机器不一样 |
| Tab | custom-tab-bar |
毛玻璃底栏,选中项随主题色变化 |
| 主题 | theme.wxss CSS 变量 |
四套主题与暗黑正交,页面挂 t-{``{theme}} |
| 哄睡 | 背景音频 + 白噪 / 粉噪 / 棕噪等 | 播放中可从侧边停和再开 |
主题和深色记在本机设置里,导入备份时不覆盖这台设备的外观。
1. 一个存储键里的四段数据
宝宝资料、喂养记录、待办、设置放在一起,读的时候缺哪段就补哪段,旧数据没有 todos 也不会坏。
js
var KEY = 'newborn_feed_v1';
function defaultDb() {
return {
baby: { name: '宝宝', gender: 'M', birthday: '', birthWeight: '' },
records: [],
todos: [],
settings: {
theme: 'indigo',
dark: false,
reminderEnabled: true,
feedInterval: 180
}
};
}
记录 id 用 r_ 前缀,待办用 t_。喂养按时间倒序插入,首页取最近几条不用每次全表重排。导出的 JSON 带上待办;导入可以按 id 合并,也可以覆盖。覆盖前先留一份当前数据的快照。清空喂养记录时只动 records,todos 原样留下。
返回给页面的记录列表是数组副本。若把内部数组的引用交出去,后续删除再导入时,旧引用可能把已经删掉的记录又写回来。
2. 出生日加 N 个月,要处理月末
2026-01-31 加 1 个月,不能得到 3 月 2 日或 3 日。做法是先落到目标月的 1 号,查出该月最后一天,再把出生日的「日」夹到这个月末。1 月 31 日加 1 个月得到 2 月 28 日;42 天体检则直接按天加。
js
function addMonths(ymd, months) {
var p = ymd.split('-');
var y = parseInt(p[0], 10);
var m = parseInt(p[1], 10) - 1;
var d = parseInt(p[2], 10);
var first = new Date(y, m + months, 1);
var last = new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();
return new Date(first.getFullYear(), first.getMonth(), Math.min(d, last)).getTime();
}
列表很长时,改期不必滚回页面顶部的表单。每一行右侧就是日期选择器,改完写回 due。
3. 顶栏让开胶囊
自定义导航若写死状态栏高度,刘海机和右上角胶囊之间会空出一条,或者文字钻进胶囊。utils/nav.js 用 statusBarHeight 和 getMenuButtonBoundingClientRect 算出状态栏高度、胶囊那一行的高度、这一行的底边、内容距屏幕右缘要留出的宽度。首页的日期和深色开关、我的页的资料头,都停在胶囊左侧。
4. 提醒发生在小程序被打开的时候
间隔到了以后,进入首页会打开全屏页:脉冲时钟、铃铛动效,真机上循环 wx.vibrateLong。贪睡和停止都会写下一次允许再响的时间,避免同一次超时反复弹。小程序退到后台后,平台不会让它再拉起页面,所以它适合随手打开看,系统闹钟仍要另外设。开发者工具里转发文件和部分震动接口不可用,导出会退回剪贴板,震动需要真机看。
五、目录结构
newborn-feed-tracker/
├── app.js / app.json / app.wxss # 入口、4 个 Tab、公共样式
├── theme.wxss # 四套主题 + 深色变量
├── custom-tab-bar/ # 自定义底栏
├── components/ # 轻提示、左滑删除行
├── assets/ # 男宝 / 女宝头像
├── utils/
│ ├── storage.js # 本地 CRUD、导入、清空
│ ├── schedule.js # 疫苗与体检草稿
│ ├── stats.js / charts.js # 聚合与 canvas
│ ├── export.js # 导出、校验、导入
│ ├── theme.js / icons.js / nav.js
│ └── time.js
└── pages/
├── index/ record/ stats/ mine/ # 四个 Tab
├── history/ baby/ alarm/ todo/ # 记录、资料、提醒、待办
└── calc/ noise/ settings/ data/
六、本地运行
- 克隆仓库:https://github.com/XH-fenger/newborn-feed-tracker
- 用微信开发者工具导入项目根目录;AppID 可先用测试号。
- 编译后从首页记一笔喂养,再看统计和待办是否出现。
- 真机预览用来确认震动、白噪音,以及把 JSON 转发给文件传输助手。导入走聊天文件,单文件大约 2MB 以内,并先做结构校验。
七、边界
- 提醒依赖用户打开小程序,后台没有推送。
- 日程是对照用的草稿,接种以门诊和接种证为准。
- 导入不改本机当前的主题和深色。
- 模拟器里
shareFileMessage常常不可用,导出会走剪贴板。 - 截图中的日期、逾期天数等为演示数据。
相关链接
若实现细节对你有用,欢迎给仓库点 Star,或提 Issue / PR。







