Files
mama-box/topic/yuchanqi-js/index.html

194 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<title>预产期计算器</title>
<!-- 孕期计算器 · 预产期(2026-11-04 用户:「孕期增重那个是记录工具、不是算出来的,换掉,给我一个能算的」→ 新做本页替换百宝箱 / topic/jisuan 里的「孕期增重」)。
算法(常规产科算法):
末次月经:预产期 = 末次月经第一天 + 280 天 +(周期 − 28)天;
试管移植:第 3 天胚胎 = 移植日 + 263 天,第 5 天囊胚 = 移植日 + 261 天;
孕周 = 今天 −(预产期 − 280 天),各项产检窗口按孕周换算成日期。
自成一页:不引 app.js;返回走 back,直接打开回 ../../(带回 search + hash)。上次填的值记在 localStorage「mmbox.edd.calc」,再进来直接出结果。 -->
<style>
:root{--c:#E25C7A;--cbg:#FFEEF2;--h:#1F2329;--t:#4E5969;--m:#86909C;--line:#F1E9EB}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden;background:#fff;color:var(--t);font:15px/1.7 -apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif}
#scroll{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;padding-bottom:calc(28px + env(safe-area-inset-bottom))}
button,input{font:inherit;border:0;background:none;color:inherit}
button{cursor:pointer}
.num{font-variant-numeric:tabular-nums}
.ic{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.bar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:4px;height:48px;padding:0 8px;padding-top:env(safe-area-inset-top);border-bottom:1px solid transparent;transition:background .2s,border-color .2s}
.bar.on{background:#fff;border-bottom-color:var(--line)}
.bar .back{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:var(--h)}
.bar .t{font-size:15px;font-weight:700;color:var(--h)}
.hd{margin-top:-48px;padding:60px 20px 6px;background:linear-gradient(180deg,var(--cbg),#fff)}
.hd p{font-size:12.5px;font-weight:700;color:var(--c);letter-spacing:1px}
.hd h1{margin-top:4px;font-size:25px;font-weight:900;line-height:1.3;color:var(--h)}
.hd span{display:block;margin-top:4px;font-size:14px;color:var(--m)}
.calc{margin:12px 16px 0;padding:16px;border-radius:20px;background:#fff;box-shadow:0 10px 30px -18px rgba(226,92,122,.55);border:1px solid #F7E3E8}
.res{padding:16px;border-radius:16px;background:linear-gradient(135deg,#FF8FA8,#E25C7A);color:#fff}
.res .empty{padding:14px 0;text-align:center;font-size:14px;opacity:.9}
.res small{font-size:12.5px;opacity:.9}
.res .due{display:block;margin-top:2px;font-size:28px;font-weight:900;line-height:1.25}
.res .wk{display:flex;gap:10px;margin-top:12px}
.res .wk div{flex:1;padding:8px 10px;border-radius:12px;background:rgba(255,255,255,.18)}
.res .wk b{display:block;font-size:17px;font-weight:900}
.res .pg{position:relative;height:6px;margin-top:12px;border-radius:99px;background:rgba(255,255,255,.3);overflow:hidden}
.res .pg i{position:absolute;left:0;top:0;bottom:0;border-radius:99px;background:#fff}
.tabs{display:flex;gap:6px;margin-top:16px;padding:4px;border-radius:12px;background:#F7F1F3}
.tabs button{flex:1;height:34px;border-radius:9px;font-size:14px;font-weight:700;color:var(--m)}
.tabs button.on{background:#fff;color:var(--c);box-shadow:0 2px 6px rgba(226,92,122,.15)}
.fld{margin-top:14px}
.lb{display:block;font-size:13.5px;font-weight:700;color:var(--h)}
.lb small{margin-left:6px;font-weight:400;color:var(--m)}
.in{display:block;width:100%;height:46px;margin-top:6px;padding:0 14px;border-radius:12px;background:#F8F5F6;font-size:16px;color:var(--h)}
.stp{display:flex;align-items:center;gap:10px;margin-top:6px}
.stp button{width:42px;height:42px;border-radius:12px;background:#F8F5F6;font-size:20px;font-weight:700;color:var(--c)}
.stp b{flex:1;text-align:center;font-size:18px;color:var(--h)}
.seg{display:flex;gap:8px;margin-top:6px}
.seg button{flex:1;height:42px;border-radius:12px;background:#F8F5F6;font-size:14px;font-weight:700;color:var(--t)}
.seg button.on{background:var(--cbg);color:var(--c);box-shadow:inset 0 0 0 1.5px var(--c)}
.hide{display:none!important}
.sec{margin:26px 20px 0}
.sec h2{font-size:18px;font-weight:900;color:var(--h)}
.sec .lead{margin-top:2px;font-size:13px;color:var(--m)}
.tl{list-style:none;margin-top:12px}
.tl li{position:relative;display:flex;gap:12px;padding:0 0 16px 0}
.tl li::before{content:"";position:absolute;left:7px;top:18px;bottom:0;width:2px;background:#F3E3E7}
.tl li:last-child::before{display:none}
.tl .d{flex:none;width:16px;height:16px;margin-top:3px;border-radius:50%;border:3px solid #F6CBD6;background:#fff}
.tl li.done .d{border-color:var(--c);background:var(--c)}
.tl li.now .d{border-color:var(--c);box-shadow:0 0 0 4px rgba(226,92,122,.18)}
.tl .m{flex:1;min-width:0}
.tl .m b{font-size:15px;color:var(--h)}
.tl .m b em{margin-left:6px;padding:0 6px;border-radius:99px;background:var(--cbg);color:var(--c);font-size:11px;font-style:normal;font-weight:800}
.tl .m span{display:block;font-size:13px;color:var(--m)}
.tl .m span i{font-style:normal;font-weight:700;color:var(--t)}
.tip{margin:18px 20px 0;padding:12px 14px;border-radius:14px;background:#FFF8F4;font-size:13px;line-height:1.7;color:var(--t)}
.tip b{color:var(--h)}
.foot{margin:14px 20px 0;font-size:12px;color:var(--m);text-align:center;line-height:1.6}
</style>
</head>
<body>
<svg style="position:absolute;width:0;height:0" aria-hidden="true"><symbol id="i-back" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7"/></symbol></svg>
<div id="scroll">
<header class="bar" id="bar">
<button class="back" id="back" aria-label="返回"><svg class="ic"><use href="#i-back"/></svg></button>
<span class="t">孕期计算器</span>
</header>
<section class="hd"><p>孕期计算器</p><h1>预产期计算器</h1><span>填末次月经或移植日,算出预产期、现在几周、每项产检哪天去</span></section>
<section class="calc">
<div class="res" id="res"><div class="empty">填好下面的日期,马上出结果</div></div>
<div class="tabs" id="tabs"><button type="button" data-m="lmp" class="on">按末次月经</button><button type="button" data-m="ivf">按试管移植</button></div>
<div id="fLmp">
<div class="fld"><label class="lb" for="cLmp">末次月经第一天</label><input class="in num" type="date" id="cLmp"></div>
<div class="fld"><span class="lb">月经周期<small>两次月经第一天间隔几天</small></span>
<div class="stp"><button type="button" id="cyM" aria-label="减一天">−</button><b class="num" id="cyV">28 天</b><button type="button" id="cyP" aria-label="加一天">+</button></div></div>
</div>
<div id="fIvf" class="hide">
<div class="fld"><label class="lb" for="cTr">胚胎移植日</label><input class="in num" type="date" id="cTr"></div>
<div class="fld"><span class="lb">移植的胚胎</span>
<div class="seg" id="cEmb"><button type="button" data-v="3">第 3 天胚胎</button><button type="button" data-v="5" class="on">第 5 天囊胚</button></div></div>
</div>
</section>
<section class="sec hide" id="plan">
<h2>我的产检时间表</h2>
<p class="lead">按预产期倒推的建议时间,具体听你的产检医生安排</p>
<ol class="tl" id="tl"></ol>
</section>
<div class="tip"><b>以早孕 B 超为准:</b>月经不规律、记不清末次月经,或 B 超算出的孕周和月经差得多,医生会按孕早期 B 超(头臀长)改预产期。预产期是个参考,37~41+6 周生都算足月。</div>
<p class="foot">计算结果仅供参考,不能代替医生诊断。</p>
</div>
<script>
(function () {
'use strict';
var $ = function (s) { return document.querySelector(s); };
var sc = $('#scroll'), KEY = 'mmbox.edd.calc', DAY = 864e5;
$('#back').addEventListener('click', function () {
if (document.referrer && document.referrer.indexOf(location.host) >= 0 && history.length > 1) history.back();
else location.href = '../../' + location.search + location.hash;
});
sc.addEventListener('scroll', function () { $('#bar').classList.toggle('on', sc.scrollTop > 8); }, { passive: true });
/* 日期一律按北京时间的「日」算,避免时区差一天 */
function today() { var n = new Date(Date.now() + 288e5); return Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate()); }
function parse(v) { var m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(v || ''); return m ? Date.UTC(+m[1], m[2] - 1, +m[3]) : NaN; }
function fmt(t) { var d = new Date(t); return d.getUTCFullYear() + '-' + ('0' + (d.getUTCMonth() + 1)).slice(-2) + '-' + ('0' + d.getUTCDate()).slice(-2); }
function cn(t, y) { var d = new Date(t); return (y ? d.getUTCFullYear() + ' 年 ' : '') + (d.getUTCMonth() + 1) + ' 月 ' + d.getUTCDate() + ' 日'; }
var WD = '日一二三四五六';
var st = { m: 'lmp', lmp: '', cy: 28, tr: '', emb: 5 };
try { var sv = JSON.parse(localStorage.getItem(KEY) || 'null'); if (sv) Object.keys(st).forEach(function (k) { if (sv[k] != null) st[k] = sv[k]; }); } catch (e) {}
var T = today();
$('#cLmp').max = fmt(T); $('#cLmp').min = fmt(T - 300 * DAY);
$('#cTr').max = fmt(T); $('#cTr').min = fmt(T - 280 * DAY);
function ui() {
[].forEach.call($('#tabs').children, function (b) { b.classList.toggle('on', b.dataset.m === st.m); });
$('#fLmp').classList.toggle('hide', st.m !== 'lmp'); $('#fIvf').classList.toggle('hide', st.m !== 'ivf');
$('#cLmp').value = st.lmp; $('#cTr').value = st.tr; $('#cyV').textContent = st.cy + ' 天';
[].forEach.call($('#cEmb').children, function (b) { b.classList.toggle('on', +b.dataset.v === +st.emb); });
}
function due() {
if (st.m === 'lmp') { var l = parse(st.lmp); return isNaN(l) ? NaN : l + (280 + st.cy - 28) * DAY; }
var t = parse(st.tr); return isNaN(t) ? NaN : t + (+st.emb === 3 ? 263 : 261) * DAY;
}
/* 产检窗口(孕周,含首尾):常规产检时间,具体以医生安排为准 */
var PLAN = [
['建档 + 第一次产检', 6, 12, '查血、B 超确认胎心,拿到孕妇手册'],
['NT 检查', 11, 13.86, '11~13+6 周,错过就不能补'],
['唐筛 / 无创', 15, 20.86, '早唐可和 NT 一起做,中唐 15~20+6 周'],
['大排畸', 20, 24, '系统超声,看宝宝结构'],
['糖耐', 24, 28, '空腹去,喝糖水抽 3 次血'],
['胎心监护', 34, 40, '一般 34~36 周起,每周一次'],
['足月', 37, 37, '这之后生都算足月,待产包备好'],
['预产期', 40, 40, '']
];
function paint() {
var d = due(), R = $('#res');
try { localStorage.setItem(KEY, JSON.stringify(st)); } catch (e) {}
if (isNaN(d)) { R.innerHTML = '<div class="empty">填好下面的日期,马上出结果</div>'; $('#plan').classList.add('hide'); return; }
var s0 = d - 280 * DAY, g = Math.floor((T - s0) / DAY), w = Math.floor(g / 7), dd = g % 7, left = Math.round((d - T) / DAY);
var wk = g < 0 ? '还没开始' : w + ' 周' + (dd ? ' + ' + dd + ' 天' : ''), stage = w < 14 ? '孕早期' : w < 28 ? '孕中期' : '孕晚期';
R.innerHTML = '<small>你的预产期</small><b class="due num">' + cn(d, 1) + ' 周' + WD[new Date(d).getUTCDay()] + '</b>' +
'<div class="wk"><div><small>今天</small><b class="num">' + (g >= 0 && g <= 300 ? '孕 ' + wk : '—') + '</b></div><div><small>' + (left >= 0 ? '离见面还有' : '已过预产期') + '</small><b class="num">' + Math.abs(left) + ' 天</b></div></div>' +
'<div class="pg"><i style="width:' + Math.max(0, Math.min(100, g / 280 * 100)).toFixed(1) + '%"></i></div>' +
'<small style="display:block;margin-top:6px">' + (g >= 0 && left >= 0 ? stage + ' · 已走过 ' + Math.round(g / 280 * 100) + '%' : '预产期仅供参考,以医生判断为准') + '</small>';
$('#tl').innerHTML = PLAN.map(function (p) {
var a = s0 + Math.round(p[1] * 7) * DAY, b = s0 + Math.round(p[2] * 7) * DAY, done = T > b, now = T >= a && T <= b;
return '<li class="' + (done ? 'done' : now ? 'now' : '') + '"><i class="d"></i><div class="m"><b>' + p[0] + (now ? '<em>就是现在</em>' : '') + '</b>' +
'<span><i class="num">' + (a === b ? cn(a) : cn(a) + ' ~ ' + cn(b)) + '</i>' + (p[3] ? ' · ' + p[3] : '') + '</span></div></li>';
}).join('');
$('#plan').classList.remove('hide');
}
$('#tabs').addEventListener('click', function (e) { var b = e.target.closest('button'); if (!b) return; st.m = b.dataset.m; ui(); paint(); });
$('#cLmp').addEventListener('change', function () { st.lmp = this.value; paint(); });
$('#cTr').addEventListener('change', function () { st.tr = this.value; paint(); });
$('#cyM').addEventListener('click', function () { st.cy = Math.max(21, st.cy - 1); ui(); paint(); });
$('#cyP').addEventListener('click', function () { st.cy = Math.min(45, st.cy + 1); ui(); paint(); });
$('#cEmb').addEventListener('click', function (e) { var b = e.target.closest('button'); if (!b) return; st.emb = +b.dataset.v; ui(); paint(); });
ui(); paint();
/* 禁止下拉回弹:固定外壳 + 容器滚动 + 到顶/到底时拦 touchmove */
var y0 = 0;
sc.addEventListener('touchstart', function (e) { y0 = e.touches[0].clientY; }, { passive: true });
sc.addEventListener('touchmove', function (e) {
var dy = e.touches[0].clientY - y0;
if ((sc.scrollTop <= 0 && dy > 0) || (sc.scrollTop + sc.clientHeight >= sc.scrollHeight - 1 && dy < 0)) e.preventDefault();
}, { passive: false });
document.addEventListener('touchmove', function (e) { if (!sc.contains(e.target)) e.preventDefault(); }, { passive: false });
})();
</script>
<script src="../_shared/brand.js?v=26110203"></script>
<script src="../../js/share-card.js?v=26110406"></script>
<script>window.mbShare('../../assets/share/t/yuchanqi-js.jpg', '预产期计算器:宝宝哪天到?还有几天见面'); /* 11-04 微信转发图 */</script>
</body>
</html>