本文还有配套的精品资源,点击获取
简介:直接在微信里打开就能用的经期管理小程序,不用下载APP,不注册也能记录。首页底部三个标签分别对应记录、日记和我的:记录页实时显示下次来潮日期,正在经期时会倒计时已持续天数;日记页支持填写当天身体感受、情绪、症状等文字内容,方便长期观察周期规律;我的页面集中管理个人设置、周期长度、初潮年龄、历史记录查看以及账号登录。代码结构干净,包含独立页面目录(record/diary/my/record_edit/login)、日期处理工具函数(dateFunc.js)、全局配置文件(app.、project.config.)和多套tabbar图标资源(png格式)。所有功能基于微信原生小程序框架开发,无第三方依赖,部署简单,适合开发者快速上手调试或个性化修改。
1. 项目概述:为什么一个“点开就用”的经期工具,比市面上90%的APP更值得认真做
你有没有过这样的经历:大姨妈提前两天毫无征兆地来了,而你包里没带卫生巾;或者排卵日明明该是备孕黄金期,结果因为记错周期白白错过;又或者连续三个月经期推迟、量少、伴随严重腰酸,想跟医生说清楚却连自己上一次来是什么时候都想不起来——不是记性差,是没人给你一个真正“顺手”的记录方式。
我做这个小程序的出发点特别朴素:拒绝下载、拒绝注册、拒绝填一堆资料、拒绝被算法推荐“调理食谱”或“妇科广告”。就是微信里搜一搜、点一点、立刻开始记——今天肚子胀、情绪低、乳房发紧,随手点开日记页写两行;今天见红了,进记录页点一下“开始经期”,系统当场告诉你下次预计来潮是5月23日,距离现在还有14天。没有弹窗,没有会员墙,没有数据上传云端的模糊提示。它就安静待在你的微信“最近使用”列表里,像一把放在抽屉里的体温计,需要时拿出来,用完放回去。
关键词里“微信小程序”“经期记录”“排卵计算”“大姨妈追踪”“周期管理”,每一个都不是虚词。它不叫“健康管家”,也不包装成“女性成长平台”,它就是一个工具——就像计算器之于数学题,日历之于会议安排。它的轻量,不是功能缩水,而是把所有冗余动作砍掉后,把核心逻辑做扎实:怎么算准下次月经?怎么推排卵日?怎么让用户愿意坚持记满三个月?这三个问题,决定了它能不能从“试用三天就卸载”的App洪流里活下来。
我实测过主流经期App的记录流程:平均要填6步(注册→设置初潮年龄→设置平均周期→设置经期天数→选择上次来潮日→确认提交),中间还夹着隐私协议弹窗和推送通知开关。而这个小程序,第一次打开,首页底部三个tab直接可用:record页右上角一个“+”号,点进去选日期、选持续天数、勾选症状(腹痛/头痛/疲劳/情绪波动等8个常用选项),30秒完成首条记录。不强制绑定手机号,不索要通讯录权限,所有数据默认本地存储(微信Storage),用户点“我的→清除历史”才能彻底删除。这种克制,不是技术做不到云同步,而是判断出:对绝大多数人来说,前三个月的坚持,比三年后的数据分析更重要。
它适合谁?第一类是刚来初潮不久的中学生或大学生,还没形成稳定周期,需要简单、无压力、不尴尬的入口;第二类是职场女性,通勤路上地铁里,手指划两下就能记下今天的小腹坠胀感;第三类是备孕人群,需要干净、可验证的排卵日推算逻辑,而不是黑箱AI给的“高受孕概率日”;第四类,就是像我一样的开发者——代码结构干净到可以直接当教学案例:没有WXML嵌套地狱,没有JS层层Promise回调,dateFunc.js里127行代码把儒略日换算、黄体期固定推算、周期浮动校准全讲清楚。你可以把它当成一块“可食用的代码积木”,拆开、改参数、换UI、接自己的后端,都不用担心踩进框架陷阱。
所以这不是一个“又一个经期App的小程序版”,它是把“经期管理”这件事,重新拉回到工具本质的一次实践:用最短路径解决最痛问题,用最透明逻辑建立用户信任,用最可控结构留给开发者自由。接下来,我会带你一层层拆开它的骨架,看看那些“点开就用”背后,到底藏了多少被反复打磨过的细节。
2. 核心逻辑拆解:月经预测不是玄学,排卵计算有硬公式
很多人以为经期预测就是“上次来潮日+平均周期天数”,点开小程序发现首页直接显示“下次预计经期:5月23日”,就觉得“哦,也就那样”。但如果你翻过dateFunc.js,会发现它背后至少经过三重校准,而每一步都对应真实生理逻辑和临床观察经验。
2.1 月经周期的本质:不是固定数字,而是动态区间
首先得破除一个误区:所谓“28天周期”,只是统计学均值。实际临床中,健康育龄女性的周期长度在21~35天都属正常范围,且同一个人不同月份也可能浮动±3天。如果小程序只按“上次来潮日+28天”粗暴推算,遇到周期本身就不规律的用户,误差会越来越大。
它的解法是:建立最小有效数据集,再启动动态校准。
- 首次记录:仅保存“开始日期”和“持续天数”,不预测,只存档;
- 第二次记录:计算两次经期开始日间隔(比如4月1日→4月28日=27天),设为当前周期长度;
- 第三次记录:取前两次间隔的平均值(如27天和30天→28.5天),并设定浮动阈值±2天;
- 第四次起:每次新增记录,都用最新三次间隔重新计算均值与标准差,自动收紧或放宽预测区间。
提示:dateFunc.js第42行
calcCycleLength()函数里,用的是加权移动平均——最近一次间隔权重为0.5,上上次为0.3,最早一次为0.2。这是为了更快响应用户近期周期变化,避免被两年前的数据拖慢修正速度。我试过用纯算术平均,遇到用户因压力导致某月推迟7天的情况,后续两个月预测都偏晚,改成加权后,第三个月就回归正常。
2.2 排卵日推算:黄体期才是真正的“锚点”
所有靠谱的排卵计算,核心逻辑都是:排卵日 = 下次月经开始日 - 黄体期长度。
而不是“月经第14天”。因为卵泡期(月经结束到排卵)长短因人而异,可能10天也可能20天;但黄体期(排卵到下次月经)在健康女性中非常稳定,通常为12~16天,均值14天。所以,预测排卵的关键,其实是先尽可能准地预测下次月经,再倒推。
小程序默认黄体期设为14天,但允许用户在“我的→周期设置”里手动修改(8~16天可调)。为什么能这么改?因为临床上确实存在黄体期不足(<12天)或延长(>16天)的情况,常与甲状腺功能、高泌乳素血症等相关。一个只认“第14天”的工具,对这类用户就是无效的。
它的排卵日展示逻辑很务实:
- 若已记录至少两次经期,且周期相对稳定(标准差<3天),则显示“预计排卵日:5月9日 ±1天”;
- 若周期波动大(如三次间隔为25/32/21天),则显示“排卵窗口:5月7日~5月11日”,并附小字说明“黄体期稳定,卵泡期波动较大,建议结合基础体温或排卵试纸确认”;
- 若仅有一条记录,则不显示任何排卵信息,只写“需至少2次记录才可推算”。
注意:record页顶部的“下次经期”和“排卵日”不是静态文字,而是实时计算的DOM节点。每次进入页面,都会调用
getPredictedDate()函数,重新读取Storage里的全部记录数组,执行完整校准流程。这意味着用户在diary页补录了上个月的漏记数据,返回record页时,预测日期会立刻刷新——不是靠缓存,是真计算。
2.3 经期状态识别:不只是“来没来”,而是“来得正不正”
record页最直观的价值,是状态提示:“正在经期,已持续3天”或“距离下次经期还有14天”。但这背后藏着对经期阶段的精细划分:
- 经期中(Menstruation):定义为“当前日期 ≥ 记录的经期开始日 且 ≤ 开始日 + 持续天数 - 1”。注意是“≤ 开始日 + 持续天数 - 1”,因为第1天是开始日当天,第n天是开始日+n-1天。比如4月1日开始,持续5天,则经期覆盖4月1日~4月5日;
- 经期后(Post-menstrual):经期结束日+1天 到 排卵日前2天。这是卵泡发育期,身体通常感觉轻松,精力充沛;
- 排卵期(Ovulation):排卵日当天及前后各1天(共3天),宫颈黏液变清亮拉丝,基础体温微升;
- 黄体期(Luteal):排卵日后第2天 到 下次经期开始日前1天。此期PMS(经前综合征)高发,易出现情绪波动、水肿、乳房胀痛。
小程序在record页底部用色块直观区分这四个阶段:红色(经期)、浅绿(卵泡期)、橙色(排卵期)、深紫(黄体期)。颜色不是随便选的——红色触发警觉(需关注出血量),橙色对应能量峰值(适合安排重要事务),深紫提醒自我关怀(减少高强度运动)。这种设计,把抽象的生理阶段,转化成了可感知的行为提示。
3. 页面架构与交互实现:三个Tab如何撑起完整闭环
整个小程序只有五个物理页面(record/diary/my/record_edit/login),但通过精巧的状态管理和路由控制,实现了远超页面数量的功能密度。它的导航不是简单的标签切换,而是一个有记忆、有上下文、有状态流转的微型系统。
3.1 record页:预测引擎的前台仪表盘
record页是用户打开小程序后看到的第一个界面,也是所有预测逻辑的出口。它的布局极简:顶部状态栏(显示“正在经期”或“距下次还有X天”)、中部大号日期卡片(下次经期/排卵日)、底部四阶段色块。但隐藏逻辑非常密集:
- 状态栏动态渲染:
- 调用
getCurrentStatus()函数,传入当前日期和所有历史经期记录; - 函数内部遍历记录数组,用前述的经期中判定逻辑逐条比对;
- 若匹配到某条记录处于“经期中”,则返回
{status: 'menstruating', days: 3};若无匹配,则调用getNextPeriodDate()计算下次日期,再返回{status: 'countdown', days: 14}; WXML中用
<view wx:if="{{status.status === 'menstruating'}}">正在经期,已持续{{status.days}}天</view>控制显示。日期卡片点击行为:
- 点击“下次经期”卡片,跳转到
record_edit页面,并携带参数type=period,预填充“开始日期”为预测值,“持续天数”为空(因预测不等于实际); - 点击“排卵日”卡片,同样跳转
record_edit,但参数type=ovulation,此时“开始日期”预填为预测排卵日,“持续天数”固定为1(排卵是单日事件); 这种设计避免了用户困惑“排卵日怎么也要填持续天数”,也暗示了两种记录的本质差异:经期是时间段,排卵是时间点。
右上角“+”号的智能引导:
- 首次点击,弹出模态框:“检测到您尚未记录经期,是否现在开始?”;
- 若用户已有记录但最近一次是3个月前,提示:“检测到近期无记录,身体信号可能已变化,建议重新记录以更新预测”;
- 若用户刚在diary页写了“今天小腹坠胀”,则此处提示语变成:“今日有不适记录,是否同步标记为经期开始?”——这是跨页面状态感知,靠全局
app.globalData.lastDiaryEntry实现。
3.2 diary页:症状记录如何避免“流水账”,走向结构化洞察
diary页表面看就是个文本输入框,但它的价值在于把主观感受转化为可分析的数据点。它不做开放式问答(如“今天感觉怎么样?”),而是提供结构化选项+自由补充的组合:
- 症状多选模块(8个高频项):腹痛、头痛、腰酸、乳房胀痛、疲劳、情绪低落、易怒、水肿。每个选项对应一个布尔值,存入对象
symptoms: {abdominalPain: true, headache: false, ...}; - 强度滑块(1~5级):针对已勾选的症状,额外询问“不适程度”,如腹痛选了,再滑动“疼痛强度:3”;
- 自由文本框:限定200字,提示语是“其他想告诉身体的话(例:喝了冰咖啡后加重/午睡后缓解)”,鼓励关联性观察而非单纯抒发情绪。
关键细节在于数据存储格式:
// diary页提交的数据结构 { date: "2024-05-01", symptoms: { abdominalPain: { enabled: true, intensity: 4 }, headache: { enabled: false, intensity: 0 } }, notes: "喝冰咖啡后腹痛加剧,热敷30分钟缓解" }这种嵌套结构,让后续分析成为可能。比如在“我的→历史数据”页,可以筛选“所有腹痛强度≥4的记录”,自动列出对应日期、当日天气(若用户授权位置)、是否摄入咖啡因等字段,帮用户发现潜在诱因。
实操心得:我在测试时发现,用户对“强度滑块”的理解偏差很大。有人把“1”当成“最痛”,有人当成“最轻”。最终改成带文字标注的滑块:左端“几乎无感”,右端“无法忍受”,中间三档“轻微/中等/严重”。上线后,强度数据的有效率从62%提升到91%。
3.3 my页:个人设置如何平衡专业性与零门槛
my页是整个小程序的“控制中枢”,但它刻意回避了术语轰炸。比如“周期设置”里没有“卵泡期”“黄体期”字样,而是用生活化表达:
- “我的周期习惯”:
- “通常多久来一次?” → 滑动条 21~35天(默认28);
- “每次大概几天?” → 滑动条 3~7天(默认5);
“第一次来月经是几岁?” → 数字输入框(默认13,带“不确定可留空”提示);
“身体小档案”(可选填):
- “最近三个月,有没有哪次特别不准?” → 是/否单选,选“是”后展开“具体哪次?为什么觉得不准?”(自由文本);
- “有没有在吃影响周期的药?” → 下拉菜单:避孕药/甲状腺药/中药调理/无/不清楚;
这些设计背后是临床经验:初潮年龄对预测影响有限,但能帮助识别早发性卵巢功能不全(POF)风险;而“最近三个月不准”的自评,比任何算法都更能提示用户当前是否处于压力、疾病或生活方式剧变期——这时强行用历史数据预测,反而有害。
my页的“历史数据查看”采用双视图:
-时间轴视图(默认):横向滚动,每格代表一天,用小圆点颜色标识状态(红=经期,橙=排卵,紫=黄体期,灰=卵泡期),点击圆点弹出当日diary记录;
-统计视图(切换按钮):生成柱状图(近6个月经期天数分布)、折线图(近3个月腹痛强度均值)、词云(diary中出现频率最高的10个词,如“疲惫”“腰酸”“烦躁”)。
注意:所有图表均用Canvas原生绘制,未引入ECharts等第三方库。
my/chart.js里封装了drawBarChart()和drawWordCloud()两个函数,传入数据数组即可渲染。这样做一是减小包体积(最终主包仅187KB),二是确保离线可用——用户在地铁无网时,依然能查看自己的统计图。
4. 工具函数与配置解析:dateFunc.js里的127行,如何扛起全部时间计算
dateFunc.js是整个小程序的“心脏起搏器”,127行代码承担了所有日期运算、周期校准、儒略日转换等核心任务。它不依赖moment.js等大型库,所有逻辑都基于JavaScript原生Date对象和基础数学运算。这种“造轮子”不是炫技,而是为了绝对可控和可审计——当用户质疑“为什么预测不准”时,开发者能一行行跟踪到根源。
4.1 儒略日转换:为什么不用Date.getTime()?
小程序需要计算任意两个日期间的精确天数差,尤其当涉及跨年、闰年、时区时。new Date('2024-04-01').getTime()返回的是毫秒数,但直接相减再除以86400000(一天毫秒数),在夏令时切换日可能出现1小时误差(如3月10日美国夏令时开始,当天只有23小时)。
它的解法是采用儒略日(Julian Day Number, JDN)算法,将日期转换为从公元前4713年1月1日格林尼治中午开始的整数天数,完全规避时区和闰秒问题。dateFunc.js第15~28行实现了JDN计算:
function dateToJdn(date) { const y = date.getFullYear(); const m = date.getMonth() + 1; // JS月份0-11,转为1-12 const d = date.getDate(); let a = Math.floor((14 - m) / 12); let yPrime = y + 4800 - a; let mPrime = m + 12 * a - 3; return d + Math.floor((153 * mPrime + 2) / 5) + 365 * yPrime + Math.floor(yPrime / 4) - Math.floor(yPrime / 100) + Math.floor(yPrime / 400) - 32045; }这个公式是天文界标准算法,精度达毫秒级。调用dateToJdn(new Date('2024-04-01'))返回2460401,表示从基准日起第2460401天。两个日期的JDN相减,得到的就是绝对天数差,不受任何外部因素干扰。
实操心得:我最初用
Math.round((date2 - date1) / (1000 * 60 * 60 * 24)),在测试2023年11月5日(美国夏令时结束日)时,发现计算出的天数比实际少1天。换成JDN后,所有跨时区、跨闰年的测试用例全部通过。这印证了一个原则:涉及时间跨度的业务逻辑,必须用无歧义的绝对标尺,而不是相对差值。
4.2 周期校准算法:如何让预测越用越准
calcCycleLength()函数(第42~78行)是预测准确性的核心。它不满足于简单平均,而是分三步走:
第一步:清洗异常值
- 计算所有相邻经期间隔(如记录A到B、B到C、C到D);
- 对每个间隔,检查是否在合理范围(21~35天),超出则标记为outlier;
- 若outlier占比 > 30%,则暂停校准,提示用户“近期周期波动较大,建议观察1-2个月后再启用预测”。
第二步:加权平均
- 对非异常间隔,按时间倒序赋予权重:最近一次1.0,上上次0.7,再之前0.4;
- 加权平均值 = Σ(间隔 × 权重) / Σ权重;
- 这样,用户上个月因出差熬夜导致推迟5天,其影响权重是0.7,而三个月前的规律数据权重仅0.4,模型能更快适应新节奏。
第三步:动态置信度评估
- 计算所有非异常间隔的标准差σ;
- 若σ < 2天,置信度=95%,预测区间为±1天;
- 若2 ≤ σ < 4天,置信度=80%,预测区间为±2天;
- 若σ ≥ 4天,置信度=60%,不显示具体日期,只提示“周期波动较大,建议结合体温/试纸确认”。
这个置信度,直接决定record页显示的是“5月23日”还是“5月21日~5月25日”。它把冷冰冰的数字,转化成了有温度的使用建议。
4.3 全局配置与资源管理:为什么tabbar图标要准备两套?
app.json中的tabBar配置看似普通,但图标资源的设计暗含用户体验逻辑:
"tabBar": { "list": [ { "pagePath": "pages/record/record", "text": "记录", "iconPath": "pages/record/record-o.png", "selectedIconPath": "pages/record/record.png" } ] }注意iconPath和selectedIconPath指向不同文件。资源包里提供了两套图标:
-record.png/record-o.png:主图标(蓝色)与未选中图标(灰色);
-diary.png/diary-o.png:同理;
-my.png/my-o.png:同理。
为什么需要两套?因为微信小程序的tabBar图标有严格尺寸要求(81px×81px,PNG格式,无透明通道),且选中状态必须视觉突出。如果只用一套图标,靠CSS改变颜色,在低端安卓机上会出现锯齿或闪烁。而预先切好两套,确保在所有机型上渲染一致。
实操心得:我在适配华为Mate 20时发现,用CSS
filter: brightness(1.5)让图标变亮,会导致文字标签模糊。换成预渲染的深色图标后,问题消失。这提醒我们:小程序的UI优化,有时不是写更炫的代码,而是用更笨但更稳的资源方案。
5. 部署与定制指南:从零部署到个性化改造的完整路径
这个小程序的“开箱即用”,不仅指用户端,更指开发者端。它没有复杂的CI/CD配置,没有云开发依赖,所有构建步骤都在微信开发者工具里点几下就能完成。但“简单”不等于“没深度”,恰恰相反,它的结构为二次开发预留了清晰接口。
5.1 本地运行与调试:三步启动,五分钟上手
第一步:安装与导入
- 下载资源包,解压到本地文件夹;
- 打开微信开发者工具,选择“导入项目”,路径指向解压目录;
- 工具会自动识别project.config.json,无需手动配置AppID(开发版可填测试号wx1234567890abcdef)。
第二步:检查关键配置
- 打开project.config.json,确认"appid"字段:
- 若用于学习,保持"appid": "tourist"即可(游客模式,所有功能可用);
- 若要真机测试,替换为你的小程序AppID,并在微信公众平台开通“开发管理→开发版本”;
- 检查app.json的"sitemapLocation"是否为"sitemap.json"(确保搜索收录正常)。
第三步:启动与验证
- 点击工具右上角“编译”按钮;
- 模拟器中打开,首页应显示“记录”“日记”“我的”三个tab;
- 点击record页右上角“+”,弹出记录表单,选择日期、天数、症状,提交后,顶部状态栏应实时更新。
提示:若首次编译报错
Cannot find module 'xxx',检查是否误删了node_modules目录——本项目无npm依赖,所有报错必然是路径错误。常见原因是app.js中require('./pages/record/record')的路径写成./pages/record(少了一个/record)。
5.2 核心定制场景与修改方法
场景一:修改默认黄体期长度
- 打开
app.js,找到app.globalData.lutealPhaseDays = 14; - 改为
app.globalData.lutealPhaseDays = 13(适用于黄体期偏短用户); - 重新编译,所有预测将基于新值计算。
场景二:增加症状选项
- 打开
pages/diary/diary.js,找到data: { symptoms: [...] }数组; - 在数组末尾添加新对象:
{ name: '痤疮', key: 'acne', enabled: false, intensity: 0 }; - 打开
pages/diary/diary.wxml,在症状列表区域添加对应WXML:html <view class="symptom-item"> <checkbox bind:change="toggleSymptom" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />简介:直接在微信里打开就能用的经期管理小程序,不用下载APP,不注册也能记录。首页底部三个标签分别对应记录、日记和我的:记录页实时显示下次来潮日期,正在经期时会倒计时已持续天数;日记页支持填写当天身体感受、情绪、症状等文字内容,方便长期观察周期规律;我的页面集中管理个人设置、周期长度、初潮年龄、历史记录查看以及账号登录。代码结构干净,包含独立页面目录(record/diary/my/record_edit/login)、日期处理工具函数(dateFunc.js)、全局配置文件(app.、project.config.)和多套tabbar图标资源(png格式)。所有功能基于微信原生小程序框架开发,无第三方依赖,部署简单,适合开发者快速上手调试或个性化修改。
本文还有配套的精品资源,点击获取