448 lines
27 KiB
HTML
448 lines
27 KiB
HTML
<!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>
|
||
<!-- 孕期专题 · 生娃计算器(孕期首页「其他妈妈也在搜」第 1 条入口)。
|
||
2026-10-31 v2 重做:按 topic-spec v2(主色 #18A058),改成「一屏一题 → 出结果」的分步计算器。
|
||
开始屏 → 7 个问题(城市 / 医院 / 分娩 / 月子 / 喂养 / 1~3 岁谁带 / 花钱风格)→ 结果屏(生下来 / 养到 1、2、3 岁切换)。
|
||
选择存 localStorage「mmbox.huafei.v2」,再进来直接看上次结果。改价格只改脚本顶部 COST 表。
|
||
自成一页:不引 app.js;返回走 history.back 或相对路径 ../../ 并带回 search + hash。 -->
|
||
<style>
|
||
:root{--c:#18A058;--cbg:#EAF7F0;--h:#1F2329;--t:#4E5969;--s:#86909C;--line:#EEF0F3;--gray:#F7F8FA}
|
||
*{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.75 -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))}
|
||
img{display:block;max-width:100%}
|
||
button{font:inherit;border:0;background:none;color:inherit;cursor:pointer}
|
||
.ic{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
|
||
.hide{position:absolute;width:0;height:0;overflow:hidden}
|
||
|
||
/* 顶栏 */
|
||
.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);background:rgba(255,255,255,0);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 .back .ic{width:22px;height:22px}
|
||
.bar .t{font-size:16px;font-weight:600;color:var(--h)}
|
||
|
||
.screen{display:none;padding:0 20px}
|
||
.screen.on{display:block;animation:fd .35s ease both}
|
||
@keyframes fd{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
|
||
@media (prefers-reduced-motion:reduce){.screen.on{animation:none}}
|
||
|
||
.btn{display:flex;align-items:center;justify-content:center;width:100%;height:46px;border-radius:99px;background:var(--c);color:#fff;font-size:16px;font-weight:600}
|
||
.btn.ghost{background:#fff;color:var(--c);border:1px solid var(--c)}
|
||
|
||
/* 开始屏 */
|
||
.hero{margin-top:8px;height:200px;border-radius:20px;overflow:hidden;background:var(--gray)}
|
||
.hero img{width:100%;height:100%;object-fit:cover}
|
||
h1{margin-top:22px;font-size:26px;font-weight:800;line-height:1.3;color:var(--h)}
|
||
.lead{margin-top:8px;color:var(--t)}
|
||
.start-list{margin:20px 0 26px;padding:14px 16px;border-radius:18px;background:var(--gray);display:grid;grid-template-columns:1fr 1fr;gap:6px 12px;font-size:13.5px;color:var(--t);line-height:1.6}
|
||
.start-list span{display:flex;align-items:center;gap:6px}
|
||
.start-list i{flex:none;width:5px;height:5px;border-radius:50%;background:var(--c)}
|
||
.tiny{margin-top:12px;font-size:12.5px;color:var(--s);text-align:center;line-height:1.6}
|
||
|
||
/* 问题屏 */
|
||
.prog{display:flex;align-items:center;gap:12px;margin-top:6px}
|
||
.prog .pb{flex:1;height:6px;border-radius:9px;background:var(--line);overflow:hidden}
|
||
.prog .pb i{display:block;height:100%;border-radius:9px;background:var(--c);transition:width .3s}
|
||
.prog span{font-size:13px;color:var(--s);font-variant-numeric:tabular-nums}
|
||
.qh{margin-top:26px;font-size:22px;font-weight:800;line-height:1.35;color:var(--h)}
|
||
.qs{margin-top:4px;font-size:13.5px;color:var(--s)}
|
||
.opts{margin-top:20px;display:flex;flex-direction:column;gap:12px}
|
||
.opt{display:flex;align-items:center;gap:12px;width:100%;min-height:68px;padding:12px 16px;border-radius:18px;border:1.5px solid var(--line);background:#fff;text-align:left;transition:border-color .15s,background .15s}
|
||
.opt .ox{flex:1;min-width:0}
|
||
.opt b{display:block;font-size:16.5px;font-weight:700;color:var(--h);line-height:1.4}
|
||
.opt small{display:block;margin-top:2px;font-size:13px;color:var(--s);line-height:1.45}
|
||
.opt .rd{flex:none;width:22px;height:22px;border-radius:50%;border:1.5px solid #D5D9DE;display:grid;place-items:center}
|
||
.opt.on{border-color:var(--c);background:var(--cbg)}
|
||
.opt.on .rd{border-color:var(--c);background:var(--c)}
|
||
.opt.on .rd::after{content:"";width:8px;height:8px;border-radius:50%;background:#fff}
|
||
.prev{display:inline-flex;align-items:center;gap:2px;margin-top:22px;padding:6px 4px;font-size:14px;color:var(--s)}
|
||
.prev .ic{width:18px;height:18px}
|
||
|
||
/* 结果屏 */
|
||
.r-t{margin-top:6px;font-size:20px;font-weight:800;color:var(--h)}
|
||
.chips{margin-top:8px;display:flex;flex-wrap:wrap;gap:6px}
|
||
.chips button{padding:2px 10px;border-radius:99px;background:var(--gray);font-size:12.5px;color:var(--t);line-height:1.8}
|
||
.hint{margin-top:6px;font-size:12.5px;color:var(--s)}
|
||
.tabs{margin-top:16px;display:flex;padding:3px;border-radius:99px;background:var(--gray)}
|
||
.tabs button{flex:1;min-width:0;height:36px;border-radius:99px;font-size:14px;color:var(--t);white-space:nowrap;transition:background .2s,color .2s}
|
||
.tabs button.on{background:#fff;color:var(--c);font-weight:700;box-shadow:0 2px 8px rgba(0,0,0,.06)}
|
||
.total{margin-top:14px;padding:20px 16px 18px;border-radius:18px;background:var(--cbg);text-align:center}
|
||
.total .l{font-size:13px;color:var(--t)}
|
||
.total .v{margin-top:2px;font-size:30px;font-weight:800;color:var(--c);line-height:1.3;font-variant-numeric:tabular-nums}
|
||
.total .v span{white-space:nowrap}
|
||
.total .m{margin-top:4px;font-size:13.5px;color:var(--t)}
|
||
.total .m b{color:var(--h)}
|
||
.stack{margin-top:18px;display:flex;gap:2px;height:12px;border-radius:9px;overflow:hidden}
|
||
.stack i{display:block;height:100%;transition:flex-grow .4s,background .3s}
|
||
.list{margin-top:10px;border-top:1px solid var(--line)}
|
||
.list details{border-bottom:1px solid var(--line)}
|
||
.list summary{list-style:none;display:flex;align-items:center;gap:10px;padding:13px 2px;cursor:pointer}
|
||
.list summary::-webkit-details-marker{display:none}
|
||
.list .dot{flex:none;width:10px;height:10px;border-radius:3px}
|
||
.list .nm{flex:1;min-width:0;font-size:15px;color:var(--h)}
|
||
.list .rg{font-size:15px;font-weight:700;color:var(--h);white-space:nowrap;font-variant-numeric:tabular-nums}
|
||
.list .ar{flex:none;width:16px;height:16px;color:#C0C5CC;transition:transform .2s}
|
||
.list details[open] .ar{transform:rotate(180deg)}
|
||
.list .ds{padding:0 2px 12px 20px;font-size:13px;color:var(--s);line-height:1.6}
|
||
.list details.off .nm,.list details.off .rg{color:#C0C5CC;font-weight:400}
|
||
.list details.off .rg{font-size:13px}
|
||
|
||
.card{margin-top:16px;padding:14px 16px;border-radius:18px;border:1px solid var(--line);background:#fff}
|
||
.row{display:flex;gap:10px;align-items:flex-start}
|
||
.row+.row{margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
|
||
.row .ic{margin-top:3px;color:var(--c)}
|
||
.row b{display:block;font-size:15px;color:var(--h);line-height:1.5}
|
||
.row b em{font-style:normal;color:var(--c)}
|
||
.row p{font-size:13.5px;color:var(--t);line-height:1.6}
|
||
.ins p{margin-top:2px}
|
||
.ins .f span{white-space:nowrap}
|
||
.ins .f{display:inline-block;margin-top:6px;padding:4px 10px;border-radius:10px;background:var(--gray);font-size:12.5px;color:var(--h)}
|
||
.acts{margin-top:22px}
|
||
.note{margin-top:14px;font-size:12px;color:var(--s);line-height:1.6;text-align:center}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<svg class="hide" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
||
<symbol id="i-back" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7"/></symbol>
|
||
<symbol id="i-down" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></symbol>
|
||
<symbol id="i-coin" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M9 7.5l3 4 3-4M12 11.5V17M9 12.5h6M9 15h6"/></symbol>
|
||
<symbol id="i-bulb" viewBox="0 0 24 24"><path d="M9 18.5h6M10.2 21.5h3.6M12 3a6 6 0 0 0-4 10.5c.7.7 1 1.5 1 2.5h6c0-1 .3-1.8 1-2.5A6 6 0 0 0 12 3z"/></symbol>
|
||
<symbol id="i-shield" viewBox="0 0 24 24"><path d="M12 3l7 3v5c0 5-3 8-7 10-4-2-7-5-7-10V6z"/><path d="M9 12l2 2 4-4"/></symbol>
|
||
</svg>
|
||
|
||
<div id="scroll">
|
||
<header class="bar" id="bar">
|
||
<button class="back" id="back" aria-label="返回"><svg class="ic"><use href="#i-back" xlink:href="#i-back"/></svg></button>
|
||
<span class="t">孕期专题</span>
|
||
</header>
|
||
|
||
<!-- 开始屏 -->
|
||
<section class="screen" id="sStart">
|
||
<div class="hero"><img src="img/hero.webp" alt="孕妈在桌前记账"></div>
|
||
<h1>生娃计算器<br>到底要花多少钱?</h1>
|
||
<p class="lead">回答 7 个小问题,算出从怀孕到宝宝 3 岁大概要花多少。</p>
|
||
<div class="start-list">
|
||
<span><i></i>孕期产检</span><span><i></i>分娩住院</span>
|
||
<span><i></i>坐月子</span><span><i></i>养到 1~3 岁</span>
|
||
</div>
|
||
<button class="btn" id="go">开始计算</button>
|
||
<p class="tiny">约 1 分钟 · 不用填个人信息</p>
|
||
</section>
|
||
|
||
<!-- 问题屏 -->
|
||
<section class="screen" id="sQ">
|
||
<div class="prog"><div class="pb"><i id="pbar"></i></div><span id="pnum">1 / 7</span></div>
|
||
<h2 class="qh" id="qh"></h2>
|
||
<p class="qs" id="qs"></p>
|
||
<div class="opts" id="opts"></div>
|
||
<button class="prev" id="prev"><svg class="ic"><use href="#i-back" xlink:href="#i-back"/></svg>上一步</button>
|
||
</section>
|
||
|
||
<!-- 结果屏 -->
|
||
<section class="screen" id="sRes">
|
||
<h2 class="r-t">你家大概要花</h2>
|
||
<div class="chips" id="chips"></div>
|
||
<p class="hint">点任一项可单独修改</p>
|
||
<div class="tabs" id="tabs">
|
||
<button data-s="0">生下来</button><button data-s="1">养到1岁</button><button data-s="2">养到2岁</button><button data-s="3">养到3岁</button>
|
||
</div>
|
||
<div class="total" aria-live="polite">
|
||
<div class="l" id="totL"></div>
|
||
<div class="v" id="totV"></div>
|
||
<div class="m" id="totM"></div>
|
||
</div>
|
||
<div class="stack" id="stack"></div>
|
||
<div class="list" id="list"></div>
|
||
|
||
<div class="card">
|
||
<div class="row"><svg class="ic"><use href="#i-coin" xlink:href="#i-coin"/></svg><div><b id="bigT"></b><p id="bigD"></p></div></div>
|
||
<div class="row"><svg class="ic"><use href="#i-bulb" xlink:href="#i-bulb"/></svg><div><b>能省的地方</b><p id="save"></p></div></div>
|
||
</div>
|
||
|
||
<div class="card ins">
|
||
<div class="row"><svg class="ic"><use href="#i-shield" xlink:href="#i-shield"/></svg><div>
|
||
<b>生育保险能报一部分</b>
|
||
<p>产检和分娩费用可按规定报销;产假期间还能领生育津贴。以当地医保为准。</p>
|
||
<span class="f"><span>生育津贴 = 单位上年度职工月平均工资</span> <span>÷ 30 × 产假天数</span></span>
|
||
</div></div>
|
||
</div>
|
||
|
||
<div class="acts"><button class="btn ghost" id="redo">重新选择</button></div>
|
||
<p class="note">按常见价格区间粗略估算,各地各医院差别很大,以实际为准;不含孕期并发症、早产、住院等意外支出。</p>
|
||
</section>
|
||
</div>
|
||
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
|
||
/* ================= 费用表(单位:元,[低, 高],医保报销前的常见区间,偏保守取整) =================
|
||
城市下标 c:0 一线 / 1 新一线及省会 / 2 普通地级市 / 3 县城及乡镇
|
||
×STYLE 的项是「可选消费」,按第 7 题花钱风格乘系数;其余是刚性支出,不乘。 */
|
||
var COST = {
|
||
// —— 生下来 ——
|
||
// 孕期产检全程(约 10~13 次 + 筛查)[c][医院],医院 0 公立普通 / 1 公立特需或单间 / 2 私立
|
||
check: [
|
||
[[6000, 10000], [15000, 30000], [20000, 50000]],
|
||
[[4000, 8000], [10000, 20000], [15000, 35000]],
|
||
[[3000, 6000], [6000, 12000], [8000, 20000]],
|
||
[[2000, 4000], [4000, 8000], [5000, 12000]]
|
||
],
|
||
// 孕妇装、待产包等孕期用品 [c],×STYLE
|
||
pregGoods: [[2000, 5000], [1500, 4000], [1200, 3000], [1000, 2500]],
|
||
// 分娩住院 [c][医院][方式],方式 0 顺产 / 1 剖宫产;「还不确定」取两者合并区间(顺产低值 ~ 剖宫产高值)
|
||
birth: [
|
||
[[[6000, 12000], [12000, 20000]], [[15000, 30000], [25000, 45000]], [[30000, 60000], [45000, 90000]]],
|
||
[[[4000, 8000], [8000, 15000]], [[10000, 20000], [15000, 30000]], [[18000, 40000], [28000, 60000]]],
|
||
[[[3000, 6000], [6000, 11000]], [[6000, 12000], [10000, 18000]], [[10000, 25000], [15000, 35000]]],
|
||
[[[2000, 4000], [4000, 8000]], [[4000, 8000], [6000, 12000]], [[6000, 15000], [10000, 22000]]]
|
||
],
|
||
// 坐月子(含月子餐、产妇用品)[c][方式],0 家人照顾 / 1 月嫂约 26 天 / 2 月子中心约 28 天
|
||
yuezi: [
|
||
[[3000, 8000], [15000, 30000], [40000, 100000]],
|
||
[[2500, 6000], [10000, 20000], [25000, 60000]],
|
||
[[2000, 5000], [7000, 14000], [15000, 35000]],
|
||
[[1500, 4000], [5000, 10000], [10000, 25000]]
|
||
],
|
||
|
||
// —— 0~1 岁 ——
|
||
eat01: [[1000, 3000], [5000, 9000], [8000, 14000]], // 奶粉/辅食 [喂养]:0 母乳为主 / 1 混合 / 2 奶粉为主(不分城市)
|
||
diaper01: [3000, 5000], // 纸尿裤湿巾(不分城市)
|
||
goods01: [[5000, 10000], [4000, 8000], [3000, 6000], [2500, 5000]], // 衣物、婴儿床推车安全座椅、洗护玩具 [c],×STYLE
|
||
med01: [[1500, 6000], [1200, 5000], [1000, 4000], [800, 3000]], // 看病 + 自费疫苗 [c]
|
||
// 0~1 岁按产假 + 家人带计,不算带娃费用(第 6 题只管 1~3 岁)
|
||
|
||
// —— 1~2 岁 ——
|
||
eat12: [[3000, 6000], [5000, 9000], [6000, 11000]], // 奶粉/辅食/日常饮食 [喂养]
|
||
diaper12: [2500, 4000],
|
||
goods12: [[4000, 8000], [3000, 6000], [2500, 5000], [2000, 4000]], // 衣物用品玩具 [c],×STYLE
|
||
edu12: [[2000, 8000], [1500, 6000], [1000, 4000], [500, 3000]], // 早教、绘本、游乐 [c],×STYLE
|
||
med12: [[1200, 4000], [1000, 3500], [800, 3000], [600, 2500]],
|
||
|
||
// —— 2~3 岁 ——
|
||
eat23: [[6000, 10000], [5000, 8000], [4000, 7000], [3000, 6000]], // 日常饮食 + 牛奶 [c]
|
||
diaper23: [800, 2000], // 逐步戒纸尿裤
|
||
goods23: [[4000, 8000], [3000, 6000], [2500, 5000], [2000, 4000]], // ×STYLE
|
||
edu23: [[3000, 10000], [2000, 8000], [1500, 5000], [800, 3500]], // ×STYLE
|
||
med23: [[1000, 3500], [800, 3000], [600, 2500], [500, 2000]],
|
||
|
||
// —— 1~3 岁谁来带(按年计)[带法][c] ——
|
||
// 0 老人或自己带:少量补贴(约 100~1000 元/月)
|
||
// 1 育儿嫂或保姆:月薪 × 12;2 托育园全日托:月费 × 12
|
||
care: [
|
||
[[4800, 12000], [3600, 9600], [2400, 7200], [1200, 6000]],
|
||
[[7000 * 12, 10000 * 12], [5000 * 12, 7500 * 12], [4000 * 12, 6000 * 12], [3000 * 12, 4500 * 12]],
|
||
[[4000 * 12, 8000 * 12], [2500 * 12, 5000 * 12], [1800 * 12, 3500 * 12], [1200 * 12, 2500 * 12]]
|
||
],
|
||
|
||
STYLE: [0.6, 1, 1.8] // 花钱风格系数:精打细算 / 适中 / 想给最好的
|
||
};
|
||
|
||
/* ================= 问题 ================= */
|
||
var QS = [
|
||
{ k: 'city', h: '你在哪类城市?', s: '各地价格差别最大的一项', o: [
|
||
['一线城市', '北京、上海、广州、深圳'], ['新一线及省会', '如成都、杭州、武汉、各省会'], ['普通地级市', '三四线城市'], ['县城及乡镇', '县城、镇上']] },
|
||
{ k: 'hosp', h: '打算在哪生?', s: '产检一般也在同一家', o: [
|
||
['公立医院普通病房', '多人间,大多数人的选择'], ['公立医院特需或单间', '单人间、特需门诊,部分自费'], ['私立医院', '环境服务好,基本全自费']] },
|
||
{ k: 'way', h: '分娩方式?', s: '最终听医生评估', o: [
|
||
['顺产', '住院约 2~3 天'], ['剖宫产', '住院约 4~6 天,费用更高'], ['还不确定', '两种都算进去,区间宽一些']] },
|
||
{ k: 'yz', h: '月子怎么坐?', s: '这项差距最大', o: [
|
||
['家人照顾', '主要花在月子餐和产妇用品'], ['请月嫂', '上门照顾,一般 26 天'], ['月子中心', '一般 28 天套餐']] },
|
||
{ k: 'feed', h: '宝宝怎么喂?', s: '大概的打算就行', o: [
|
||
['母乳为主', '奶粉钱很少'], ['混合喂养', '母乳加一部分奶粉'], ['奶粉为主', '奶粉是每月固定开销']] },
|
||
{ k: 'care', h: '1~3 岁谁来带?', s: '产假结束后的安排', o: [
|
||
['老人或自己带', '给老人一点补贴'], ['请育儿嫂或保姆', '按月薪算'], ['上托育园(全日托)', '按月费算']] },
|
||
{ k: 'style', h: '平时花钱风格?', s: '影响用品、衣物、玩具、早教', o: [
|
||
['精打细算', '够用就行,能借能用二手'], ['适中', '买点好的,不追高'], ['想给最好的', '用品玩具早教都挑好的']] }
|
||
];
|
||
var SHORT = { // 结果页的选择标签
|
||
city: ['一线', '新一线/省会', '地级市', '县城乡镇'], hosp: ['公立普通', '公立特需', '私立'], way: ['顺产', '剖宫产', '方式未定'],
|
||
yz: ['家人坐月子', '请月嫂', '月子中心'], feed: ['母乳', '混合喂养', '奶粉'], care: ['老人带', '育儿嫂', '托育园'], style: ['精打细算', '适中', '给最好的']
|
||
};
|
||
var STAGES = ['孕期产检', '分娩住院', '坐月子', '0~1岁', '1~2岁', '2~3岁'];
|
||
var SHADES = ['#0B6E3A', '#18A058', '#45B779', '#79CC9E', '#A8DFC0', '#D2F0DF'];
|
||
var TAB_L = ['怀孕到坐完月子', '怀孕到宝宝 1 岁', '怀孕到宝宝 2 岁', '怀孕到宝宝 3 岁'];
|
||
var UPTO = [3, 4, 5, 6]; // 每个标签包含前几段
|
||
var MONTHS = [10, 21, 33, 45]; // 平均每月的分母:怀孕约 9 个月 + 月子 1 个月;之后每岁 12 个月
|
||
var KEY = 'mmbox.huafei.v2';
|
||
|
||
var $ = function (s) { return document.querySelector(s); };
|
||
var sc = $('#scroll');
|
||
var st = { city: 1, hosp: 0, way: 2, yz: 0, feed: 1, care: 0, style: 1 };
|
||
var stage = 1, qi = 0, editing = false;
|
||
|
||
function add(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
|
||
function mul(a, k) { return [a[0] * k, a[1] * k]; }
|
||
function sum() { return [].slice.call(arguments).reduce(add, [0, 0]); }
|
||
|
||
/* 六段费用,返回 [[低, 高] × 6] */
|
||
function calc(s) {
|
||
var c = s.city, k = COST.STYLE[s.style];
|
||
var b = COST.birth[c][s.hosp];
|
||
var birth = s.way === 2 ? [Math.min(b[0][0], b[1][0]), Math.max(b[0][1], b[1][1])] : b[s.way];
|
||
var care = COST.care[s.care][c];
|
||
return [
|
||
sum(COST.check[c][s.hosp], mul(COST.pregGoods[c], k)),
|
||
birth,
|
||
COST.yuezi[c][s.yz],
|
||
sum(COST.eat01[s.feed], COST.diaper01, mul(COST.goods01[c], k), COST.med01[c]),
|
||
sum(COST.eat12[s.feed], COST.diaper12, mul(COST.goods12[c], k), mul(COST.edu12[c], k), COST.med12[c], care),
|
||
sum(COST.eat23[c], COST.diaper23, mul(COST.goods23[c], k), mul(COST.edu23[c], k), COST.med23[c], care)
|
||
];
|
||
}
|
||
|
||
function wan(n) { return (Math.round(n / 1000) / 10) + '万'; }
|
||
function yuan(n) { return String(Math.round(n / 100) * 100).replace(/\B(?=(\d{3})+(?!\d))/g, ','); }
|
||
function rng(a) { return wan(a[0]) + '~' + wan(a[1]); } // 统一用「万」,一位小数
|
||
|
||
function detail(i) {
|
||
var s = st;
|
||
var careTxt = ['老人带的少量补贴', '育儿嫂 12 个月工资', '托育园 12 个月费用'][s.care];
|
||
return [
|
||
'约 10~13 次产检和筛查(' + QS[1].o[s.hosp][0] + '),加孕妇装、待产包',
|
||
(s.way === 2 ? '按顺产到剖宫产的范围算' : QS[2].o[s.way][0] + ',' + QS[2].o[s.way][1].replace(',费用更高', '')) + ';含接生或手术、麻醉、床位、新生儿筛查',
|
||
['月子餐食材、产妇用品、产后复查', '月嫂约 26 天工资,加月子餐和产妇用品', '月子中心约 28 天套餐,含住宿餐食和母婴护理'][s.yz],
|
||
QS[4].o[s.feed][0] + '的奶粉辅食、纸尿裤、衣物和婴儿床推车等用品、看病和自费疫苗',
|
||
'奶粉辅食、纸尿裤、衣物玩具早教、看病疫苗,加' + careTxt,
|
||
'日常饮食、纸尿裤(逐步戒掉)、衣物玩具早教、看病,加' + careTxt
|
||
][i];
|
||
}
|
||
|
||
/* 能省的地方(≤30 字),按最花钱的那段给 */
|
||
function saveTip(i) {
|
||
var s = st;
|
||
if (i === 0) return s.hosp ? '常规产检在公立医院做,只把分娩放在想去的医院。' : '跟着医生的产检表走,不额外加做没必要的项目。';
|
||
if (i === 1) return s.hosp ? '公立医院普通病房也安全,单间按需再升级。' : '提前问清医保能不能直接结算,出院少垫钱。';
|
||
if (i === 2) return s.yz === 2 ? '月子中心可只住 2 周,后面换月嫂或家人接手。' : s.yz === 1 ? '月嫂可只请前 2 周,之后家人接手。' : '月子餐自己做,产妇用品按需买不囤货。';
|
||
if (i === 3) return s.feed ? '奶粉先买小罐试,宝宝适合再按需补,别囤货。' : '大件用品能借就借,衣服各尺码几套够换洗就行。';
|
||
if (s.care === 1) return '老人能搭把手的话,育儿嫂可只请白天或半天。';
|
||
if (s.care === 2) return '托育园可先上半日托,或等 2 岁后再上全日托。';
|
||
return s.style === 2 ? '早教班不用早报,玩具绘本可以轮换或借阅。' : '衣物玩具亲友送、买二手都行,省下的留作备用金。';
|
||
}
|
||
|
||
/* ================= 屏幕切换 ================= */
|
||
function show(id) {
|
||
[].forEach.call(document.querySelectorAll('.screen'), function (el) { el.classList.toggle('on', el.id === id); });
|
||
sc.scrollTop = 0;
|
||
}
|
||
|
||
function renderQ() {
|
||
var q = QS[qi];
|
||
$('#pbar').style.width = ((qi + 1) / QS.length * 100) + '%';
|
||
$('#pnum').textContent = (qi + 1) + ' / ' + QS.length;
|
||
$('#qh').textContent = q.h;
|
||
$('#qs').textContent = q.s;
|
||
$('#opts').innerHTML = q.o.map(function (o, v) {
|
||
return '<button class="opt' + (st[q.k] === v && st._done ? ' on' : '') + '" data-v="' + v + '"><span class="ox"><b>' + o[0] + '</b><small>' + o[1] + '</small></span><span class="rd"></span></button>';
|
||
}).join('');
|
||
$('#prev').style.visibility = editing ? 'hidden' : 'visible';
|
||
show('sQ');
|
||
}
|
||
|
||
$('#opts').addEventListener('click', function (e) {
|
||
var b = e.target.closest('.opt'); if (!b || $('#opts').dataset.lock) return;
|
||
[].forEach.call(this.children, function (x) { x.classList.toggle('on', x === b); });
|
||
st[QS[qi].k] = +b.dataset.v;
|
||
$('#opts').dataset.lock = '1';
|
||
setTimeout(function () {
|
||
delete $('#opts').dataset.lock;
|
||
if (editing || qi === QS.length - 1) { st._done = true; editing = false; save(); renderRes(); show('sRes'); }
|
||
else { qi++; renderQ(); }
|
||
}, 220);
|
||
});
|
||
$('#prev').addEventListener('click', function () { if (qi > 0) { qi--; renderQ(); } else show('sStart'); });
|
||
$('#go').addEventListener('click', function () { qi = 0; editing = false; renderQ(); });
|
||
$('#redo').addEventListener('click', function () { qi = 0; editing = false; renderQ(); });
|
||
|
||
function renderRes() {
|
||
var parts = calc(st), n = UPTO[stage];
|
||
var mids = parts.map(function (p) { return (p[0] + p[1]) / 2; });
|
||
var all = mids.reduce(function (a, b) { return a + b; }, 0);
|
||
var tot = parts.slice(0, n).reduce(add, [0, 0]);
|
||
|
||
[].forEach.call($('#tabs').children, function (b, i) { b.classList.toggle('on', i === stage); });
|
||
$('#chips').innerHTML = QS.map(function (q, i) { return '<button data-q="' + i + '">' + SHORT[q.k][st[q.k]] + '</button>'; }).join('');
|
||
$('#totL').textContent = TAB_L[stage] + ',合计约';
|
||
var w = tot[1] >= 10000;
|
||
$('#totV').innerHTML = '<span>' + (w ? wan(tot[0]) : yuan(tot[0])) + '~</span><wbr><span>' + (w ? wan(tot[1]) : yuan(tot[1]) + '元') + '</span>';
|
||
$('#totM').innerHTML = '平均每月约 <b>' + yuan((tot[0] + tot[1]) / 2 / MONTHS[stage]) + '</b> 元';
|
||
|
||
$('#stack').innerHTML = mids.map(function (m, i) {
|
||
return '<i style="flex-grow:' + (m / all * 1000).toFixed(0) + ';background:' + (i < n ? SHADES[i] : '#E5E8EC') + '"></i>';
|
||
}).join('');
|
||
|
||
var open = {};
|
||
[].forEach.call(document.querySelectorAll('#list details'), function (d, i) { if (d.open) open[i] = 1; });
|
||
$('#list').innerHTML = parts.map(function (p, i) {
|
||
var on = i < n;
|
||
return '<details' + (on ? '' : ' class="off"') + (open[i] ? ' open' : '') + '><summary><span class="dot" style="background:' + (on ? SHADES[i] : '#E5E8EC') + '"></span>' +
|
||
'<span class="nm">' + STAGES[i] + '</span><span class="rg">' + (on ? rng(p) : '未计入') + '</span>' +
|
||
'<svg class="ic ar"><use href="#i-down" xlink:href="#i-down"/></svg></summary><div class="ds">' + detail(i) + '</div></details>';
|
||
}).join('');
|
||
|
||
var big = 0;
|
||
for (var i = 1; i < n; i++) if (mids[i] > mids[big]) big = i;
|
||
$('#bigT').innerHTML = '最花钱的是<em>' + STAGES[big] + '</em>';
|
||
var why = [
|
||
st.hosp ? '特需和私立的产检套餐偏贵' : '主要是产检和筛查',
|
||
st.hosp ? '贵在病房和服务升级' : '主要是接生、手术和住院',
|
||
['主要是月子餐和产妇用品', '主要是月嫂工资', '主要是月子中心套餐'][st.yz],
|
||
st.feed ? '奶粉和纸尿裤每月都要买' : '主要是用品、纸尿裤和看病',
|
||
['主要是日常吃用和老人补贴', '主要是育儿嫂工资', '主要是托育园月费'][st.care]
|
||
][Math.min(big, 4)];
|
||
$('#bigD').textContent = '约 ' + rng(parts[big]) + ',' + why + '。';
|
||
$('#save').textContent = saveTip(big);
|
||
}
|
||
|
||
$('#tabs').addEventListener('click', function (e) {
|
||
var b = e.target.closest('button'); if (!b) return;
|
||
stage = +b.dataset.s; save(); renderRes();
|
||
});
|
||
$('#chips').addEventListener('click', function (e) {
|
||
var b = e.target.closest('button'); if (!b) return;
|
||
qi = +b.dataset.q; editing = true; renderQ();
|
||
});
|
||
|
||
function save() {
|
||
try { var o = {}; QS.forEach(function (q) { o[q.k] = st[q.k]; }); o.stage = stage; localStorage.setItem(KEY, JSON.stringify(o)); } catch (e) {}
|
||
}
|
||
function load() {
|
||
try {
|
||
var o = JSON.parse(localStorage.getItem(KEY) || 'null'); if (!o) return false;
|
||
var ok = QS.every(function (q) { return o[q.k] >= 0 && o[q.k] < q.o.length; });
|
||
if (!ok) return false;
|
||
QS.forEach(function (q) { st[q.k] = o[q.k]; });
|
||
if (o.stage >= 0 && o.stage < 4) stage = o.stage;
|
||
st._done = true; return true;
|
||
} catch (e) { return false; }
|
||
}
|
||
|
||
if (load()) { renderRes(); show('sRes'); } else show('sStart');
|
||
|
||
/* 返回:从首页点进来就 back;直接打开(分享 / 刷新)就回同目录的首页,身份原样带回 */
|
||
$('#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 > 4); }, { passive: true });
|
||
|
||
/* 禁止下拉回弹:固定外壳 + 容器滚动 + 到顶/到底时拦 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>
|
||
</body>
|
||
</html>
|