此刻标题行降权;首页广场分类字居中;生娃计算器去性别题加 4 题、给妈妈的话改轻提示;妊娠纹加成分含量;v26110127

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
deploy
2026-11-01 23:48:14 +00:00
parent 243b0f93a1
commit 8012e9ced1
5 changed files with 251 additions and 251 deletions

View File

@@ -402,8 +402,8 @@ button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:poin
<div id="sheet" role="dialog" aria-modal="true"><i class="sg"></i><div class="sbd" id="sbd"></div></div> <div id="sheet" role="dialog" aria-modal="true"><i class="sg"></i><div class="sbd" id="sbd"></div></div>
<div class="toast" id="toast"></div> <div class="toast" id="toast"></div>
<script src="topics.js?v=26110126"></script> <script src="topics.js?v=26110127"></script>
<script src="data.js?v=26110126"></script> <script src="data.js?v=26110127"></script>
<script> <script>
(function () { (function () {
'use strict'; 'use strict';

View File

@@ -7,7 +7,7 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<title>兜爸心选 · 孕育陪伴</title> <title>兜爸心选 · 孕育陪伴</title>
<!-- V:26110126 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 --> <!-- V:26110127 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
<link rel="stylesheet" href="mama-box.css"> <link rel="stylesheet" href="mama-box.css">
<link rel="stylesheet" href="night.css"> <link rel="stylesheet" href="night.css">
<!-- 夜晚模式:首屏绘制前就按上次的选择加 class,避免先白后黑闪一下(开关在首页右上角 #nightBtn,逻辑见 app.js) --> <!-- 夜晚模式:首屏绘制前就按上次的选择加 class,避免先白后黑闪一下(开关在首页右上角 #nightBtn,逻辑见 app.js) -->
@@ -550,7 +550,8 @@
/* 11-01 第四版:四块分类(家庭/婚姻/职场/母婴)放不进标题行 → 分类单独占第二行,五段等宽 */ /* 11-01 第四版:四块分类(家庭/婚姻/职场/母婴)放不进标题行 → 分类单独占第二行,五段等宽 */
.gch-head{flex-wrap:wrap;row-gap:10px} .gch-head{flex-wrap:wrap;row-gap:10px}
#gchCat{order:3;flex-basis:100%} #gchCat{order:3;flex-basis:100%}
#gchCat button{flex:1;height:28px;font-size:13px;white-space:nowrap} /* 11-01 用户:分类滑块里的字放在每段正中间 */
#gchCat button{flex:1;min-width:0;height:28px;padding:0 4px;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;white-space:nowrap}
.gch-note{display:flex;align-items:center;gap:8px;width:100%;margin:10px 0 0;padding:9px 12px;border:0;border-radius:14px;background:#FFF1DE;font:inherit;font-size:13px;font-weight:800;color:#A86312;text-align:left} .gch-note{display:flex;align-items:center;gap:8px;width:100%;margin:10px 0 0;padding:9px 12px;border:0;border-radius:14px;background:#FFF1DE;font:inherit;font-size:13px;font-weight:800;color:#A86312;text-align:left}
.gch-note span{flex:1;min-width:0} .gch-note span{flex:1;min-width:0}
.gch-note i{flex:none;font-style:normal;font-size:12px;font-weight:800} .gch-note i{flex:none;font-style:normal;font-size:12px;font-weight:800}
@@ -628,6 +629,17 @@
@media (prefers-reduced-motion:reduce){.gb-b,.gb-w,.gb-m i{animation:none}} @media (prefers-reduced-motion:reduce){.gb-b,.gb-w,.gb-m i{animation:none}}
html.night .gb-map{background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.06) 0 2px,transparent 2.5px) 0 0/22px 22px,transparent} html.night .gb-map{background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.06) 0 2px,transparent 2.5px) 0 0/22px 22px,transparent}
html.night .gb-path path{stroke:rgba(255,255,255,.18)} html.night .gb-path path{stroke:rgba(255,255,255,.18)}
/* 11-01 用户:「此刻 N 位孕 X 周妈妈和你同一周」保留但降低视觉权重,别和「今天 N 位妈妈陪宝宝数了胎动」两行数字同时抢注意力
→ 标题行改成一行浅灰小字的辅助信息(数字不再放大、不用品牌色),主信息让给下面那行 */
#pulse .pl-title{font-size:11.5px;font-weight:500;color:#A8928C;line-height:1.4}
#pulse .pl-title b{font-size:11.5px;font-weight:700;letter-spacing:0;color:#8E7773}
#pulse .pl-live{font-size:11px}
#pulse .pl-live::after{height:10px}
#pulse .pp-crowd{margin-top:7px}
#pulse .pp-crowd-t{font-size:13px;color:#5E4A47}
#pulse .pp-crowd-t b{font-size:15px;font-weight:900;color:#2F2424}
html.night #pulse .pl-title{color:#9C8A94}
html.night #pulse .pl-title b{color:#B9A6B1}
html.night .gch-title{color:#F1E6EE} html.night .gch-title{color:#F1E6EE}
html.night .gch-cat{background:rgba(255,255,255,.08)} html.night .gch-cat{background:rgba(255,255,255,.08)}
</style> </style>
@@ -2480,7 +2492,7 @@
<script src="/_bridge/avatar-picker.js?v=26101105"></script> <script src="/_bridge/avatar-picker.js?v=26101105"></script>
<script src="/_bridge/hand-icons.js?v=26101202"></script> <script src="/_bridge/hand-icons.js?v=26101202"></script>
<script src="js/zodiac-art.js"></script> <script src="js/zodiac-art.js"></script>
<script src="guangchang/topics.js?v=26110126"></script> <script src="guangchang/topics.js?v=26110127"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
<!-- 2026-10-03 首页彩蛋:宝宝在肚皮底下动(独立文件,删掉这一行即整体下线;开关在「隐私权限」) --> <!-- 2026-10-03 首页彩蛋:宝宝在肚皮底下动(独立文件,删掉这一行即整体下线;开关在「隐私权限」) -->
<script src="js/bump.js"></script> <script src="js/bump.js"></script>
@@ -2489,7 +2501,7 @@
<!-- 2026-10-05 首页头图:宝宝时不时动一动小手小脚(独立文件,删掉这一行即下线) --> <!-- 2026-10-05 首页头图:宝宝时不时动一动小手小脚(独立文件,删掉这一行即下线) -->
<script src="js/baby-limbs.js?v=26101201"></script> <script src="js/baby-limbs.js?v=26101201"></script>
<script src="js/coach.js?v=26101211"></script> <script src="js/coach.js?v=26101211"></script>
<script src="js/birth-flow.js?v=26110126"></script> <script src="js/birth-flow.js?v=26110127"></script>
<!-- 禁止下拉回弹(2026-10-11 统一规则,与孕期体重同一段):竖向拖动时从手指下往上找还能朝该方向滚的容器,找不到才拦;横滑、双指、可滚列表不受影响 --> <!-- 禁止下拉回弹(2026-10-11 统一规则,与孕期体重同一段):竖向拖动时从手指下往上找还能朝该方向滚的容器,找不到才拦;横滑、双指、可滚列表不受影响 -->
<script> <script>

View File

@@ -3,7 +3,7 @@
(function () { (function () {
'use strict'; 'use strict';
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */ /* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
var VER = '26110126'; var VER = '26110127';
const $ = (s, c) => (c || document).querySelector(s); const $ = (s, c) => (c || document).querySelector(s);
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s)); const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));

View File

@@ -8,11 +8,18 @@
<!-- 孕期专题 · 生娃计算器(孕期首页「其他妈妈也在搜」第 1 条入口)。主色 #18A058,浅底 #EAF7F0。 <!-- 孕期专题 · 生娃计算器(孕期首页「其他妈妈也在搜」第 1 条入口)。主色 #18A058,浅底 #EAF7F0。
2026-11-01 v5(在 v4 三条路线 + 养娃账单小票上继续改): 2026-11-01 v5(在 v4 三条路线 + 养娃账单小票上继续改):
① 首屏大标题「生娃计算器」+ 副标题;三张路线卡带 01/02/03 序号;结果揭晓前全程不出现任何金额; ① 首屏大标题「生娃计算器」+ 副标题;三张路线卡带 01/02/03 序号;结果揭晓前全程不出现任何金额;
② 问题(按所选阶段出现):你是女生/男生 → 算哪一段(多选,默认全部)→ 城市 → 头胎二胎 → 0~3 岁谁带 → 上学路线 → 课外班 → 家庭月收入(可跳过); ② 问题(按所选阶段出现):算哪一段(多选,默认全部)→ 城市 → 头胎二胎 → 0~3 岁谁带 → 上学路线 → 课外班 → 家庭月收入(可跳过);
③ 账单只列所选阶段,每段 12~24 项明细,单项取中间值、小计合计能加对;1/2/3 岁累计只在含 0~1 / 1~3 岁时显示; ③ 账单只列所选阶段,每段 12~24 项明细,单项取中间值、小计合计能加对;1/2/3 岁累计只在含 0~1 / 1~3 岁时显示;
④ 填了收入:账单里给「≈ 你家 X 个月 / X 年收入」+ 所选阶段平均每月占收入比例条;收尾卡、生成卡片呼应一句;收入只存本机; ④ 填了收入:账单里给「≈ 你家 X 个月 / X 年收入」+ 所选阶段平均每月占收入比例条;收入只存本机;
⑤ 收尾卡、复制、生成卡片、推荐工具、打印动画同 v4; ⑤ 推荐工具、打印动画同 v4(收尾卡、复制、生成卡片 v7 已删);
⑥ v6(11-01):账单下加「保存账单图片」,canvas 把整张小票画成长图(宽 750,高按内容,超 15800px 先压行高再整体缩小),复用卡片弹层、长图可滚动。改价格只改脚本里的 COST 表。 ⑥ v6(11-01):账单下加「保存账单图片」,canvas 把整张小票画成长图(宽 750,高按内容,超 15800px 先压行高再整体缩小),复用卡片弹层、长图可滚动。改价格只改脚本里的 COST 表。
⑦ v7(2026-11-01,用户:题少了加几道、去掉男女题、给妈妈的话只留提示):
· 去掉「你是女生/男生」题及所有按性别换说法的文案;
· 新增 4 题并接进计算:在哪类医院(公立普通/公立特需/私立 → 产检、B 超、分娩、病房、筛查、住院餐、生育保险报销)、
顺产还是剖宫产(顺产/剖宫产/还不确定 → 分娩费、无痛或镇痛泵、报销额)、月子打算(家人/月嫂/月子中心 → 月子主项、月子餐食材)、
喂养方式(母乳为主/混合/奶粉 → 0~1 岁奶粉量、1~3 岁奶粉、吸奶器/催乳/哺乳内衣);医院、月子跟路线默认,分娩、喂养默认「还不确定」「混合」;
· 现在的题序:算哪一段 → 城市 → 头胎二胎 → 医院 → 顺产剖宫产 → 月子 → 喂养 → 0~3 岁谁带 → 上学路线 → 课外班 → 家庭月收入(按所选阶段出现);
· 「写在账单后面 / 给妈妈的话」整块删掉(换一句、复制发给妈妈、生成卡片、drawCard 都删了),只留一行浅色小提示;卡片弹层只给「保存账单图片」用。
存储 localStorage「mmbox.huafei.v5」(兼容读取 v4)。推荐工具走 ../_shared/tools.js;自成一页:不引 app.js; 存储 localStorage「mmbox.huafei.v5」(兼容读取 v4)。推荐工具走 ../_shared/tools.js;自成一页:不引 app.js;
返回走 history.back 或相对路径 ../../ 并带回 search + hash。v4 备份 /tmp/huafei5/huafei-v4-before-v5.html。 --> 返回走 history.back 或相对路径 ../../ 并带回 search + hash。v4 备份 /tmp/huafei5/huafei-v4-before-v5.html。 -->
<style> <style>
@@ -156,7 +163,6 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
.qh{margin-top:4px;font-size:24px;font-weight:800;line-height:1.35;color:var(--h)} .qh{margin-top:4px;font-size:24px;font-weight:800;line-height:1.35;color:var(--h)}
.qs{margin-top:4px;font-size:13.5px;color:var(--s)} .qs{margin-top:4px;font-size:13.5px;color:var(--s)}
.opts{margin-top:20px;display:flex;flex-direction:column;gap:10px} .opts{margin-top:20px;display:flex;flex-direction:column;gap:10px}
.opts.two{flex-direction:row}
.opts.hide2{display:none} .opts.hide2{display:none}
.opt{display:flex;align-items:center;gap:12px;width:100%;min-height:70px;padding:12px 14px;border-radius:18px;border:1.5px solid var(--line);background:#fff;text-align:left;transition:border-color .15s,background .15s,transform .15s} .opt{display:flex;align-items:center;gap:12px;width:100%;min-height:70px;padding:12px 14px;border-radius:18px;border:1.5px solid var(--line);background:#fff;text-align:left;transition:border-color .15s,background .15s,transform .15s}
.opt:active{transform:scale(.98)} .opt:active{transform:scale(.98)}
@@ -172,13 +178,6 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
.opt.on .oi{background:var(--c);color:#fff} .opt.on .oi{background:var(--c);color:#fff}
.opt.on .rd{border-color:var(--c);background:var(--c)} .opt.on .rd{border-color:var(--c);background:var(--c)}
.opt.on .rd::after{content:"";width:8px;height:8px;border-radius:50%;background:#fff} .opt.on .rd::after{content:"";width:8px;height:8px;border-radius:50%;background:#fff}
/* 第 1 题:两张大卡 */
.opts.two .opt{flex:1;min-width:0;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-height:188px;padding:18px 10px;text-align:center}
.opts.two .opt .oi{width:76px;height:76px;border-radius:50%}
.opts.two .opt .oi .ic{width:40px;height:40px;stroke-width:1.5}
.opts.two .opt b{font-size:18px}
.opts.two .opt .rd{position:absolute;opacity:0}
.opts.two .opt{position:relative}
.qa{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:20px} .qa{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:20px}
.prev{display:inline-flex;align-items:center;gap:2px;padding:8px 4px;font-size:14px;color:var(--s)} .prev{display:inline-flex;align-items:center;gap:2px;padding:8px 4px;font-size:14px;color:var(--s)}
.prev .ic{width:18px;height:18px} .prev .ic{width:18px;height:18px}
@@ -250,26 +249,8 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
.racts{display:flex;gap:10px;margin-top:10px} .racts{display:flex;gap:10px;margin-top:10px}
.racts .btn{flex:1;height:44px;font-size:15px} .racts .btn{flex:1;height:44px;font-size:15px}
/* ============ 情感收尾 ============ */ /* ============ 收尾一行小提示 ============ */
.mom{position:relative;margin-top:34px;padding:24px 20px 20px;border-radius:26px;background:linear-gradient(170deg,var(--warm) 0%,#FFFBF6 60%,#fff 100%);border:1px solid #F6E7D6;overflow:hidden} .hint{margin-top:22px;font-size:12.5px;line-height:1.6;color:#B4936F;text-align:center}
.mom .art{position:absolute;right:14px;top:16px;width:74px;height:74px;opacity:.9}
.mom .k{font-size:12px;font-weight:700;letter-spacing:.18em;color:var(--wt)}
.mom h3{margin-top:8px;font-size:25px;font-weight:800;line-height:1.35;color:var(--h)}
.mom p{margin-top:10px;font-size:15px;line-height:1.85;color:#5B5249}
.mom p b{color:var(--h)}
.mom p em{white-space:nowrap;font-style:normal;font-weight:800;color:var(--wt)}
.mom .say{margin-top:14px;font-size:17px;font-weight:700;line-height:1.7;color:var(--h)}
.mom .say q{quotes:none;display:inline;background:linear-gradient(transparent 60%,rgba(244,196,140,.45) 0)}
.msg{position:relative;margin-top:16px;padding:14px 14px 12px;border-radius:18px;background:#fff;border:1px solid #F3E3D0}
.msg .q{font-size:14.5px;line-height:1.75;color:var(--h);min-height:51px}
.msg .ft{display:flex;align-items:center;justify-content:space-between;margin-top:8px}
.msg .dt{display:flex;gap:5px}
.msg .dt i{width:6px;height:6px;border-radius:50%;background:#EAD8C3;transition:all .2s}
.msg .dt i.on{width:16px;border-radius:9px;background:var(--wt)}
.msg .sw{display:inline-flex;align-items:center;gap:4px;height:30px;padding:0 10px;border-radius:99px;background:var(--warm);font-size:13px;font-weight:600;color:var(--wt)}
.msg .sw .ic{width:15px;height:15px}
.macts{display:flex;flex-direction:column;gap:10px;margin-top:14px}
.macts .btn.w{background:#fff;color:var(--c);border:1px solid var(--c);box-shadow:none}
.blk{margin-top:30px} .blk{margin-top:30px}
.note{margin-top:16px;font-size:12px;color:var(--s);line-height:1.65;text-align:center} .note{margin-top:16px;font-size:12px;color:var(--s);line-height:1.65;text-align:center}
@@ -296,14 +277,20 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
<symbol id="i-check" viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5"/></symbol> <symbol id="i-check" viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5"/></symbol>
<symbol id="i-refresh" viewBox="0 0 24 24"><path d="M20 11a8 8 0 0 0-14.3-4.9L4 8M4 4v4h4M4 13a8 8 0 0 0 14.3 4.9L20 16M20 20v-4h-4"/></symbol> <symbol id="i-refresh" viewBox="0 0 24 24"><path d="M20 11a8 8 0 0 0-14.3-4.9L4 8M4 4v4h4M4 13a8 8 0 0 0 14.3 4.9L20 16M20 20v-4h-4"/></symbol>
<symbol id="i-edit" viewBox="0 0 24 24"><path d="M4 20h4L19 9l-4-4L4 16z"/><path d="M13.5 6.5l4 4"/></symbol> <symbol id="i-edit" viewBox="0 0 24 24"><path d="M4 20h4L19 9l-4-4L4 16z"/><path d="M13.5 6.5l4 4"/></symbol>
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="8.5" y="8.5" width="11.5" height="11.5" rx="2.5"/><path d="M15.5 8.5V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7.5a2 2 0 0 0 2 2h2.5"/></symbol>
<symbol id="i-img" viewBox="0 0 24 24"><rect x="3.5" y="4" width="17" height="16" rx="3"/><circle cx="9" cy="9.5" r="1.8"/><path d="M4 17l4.5-4.5 3.5 3.5 2.5-2.5L20 18.5"/></symbol> <symbol id="i-img" viewBox="0 0 24 24"><rect x="3.5" y="4" width="17" height="16" rx="3"/><circle cx="9" cy="9.5" r="1.8"/><path d="M4 17l4.5-4.5 3.5 3.5 2.5-2.5L20 18.5"/></symbol>
<symbol id="i-hand" viewBox="0 0 24 24"><path d="M9 11V5.5a1.5 1.5 0 0 1 3 0V11M12 10V4.5a1.5 1.5 0 0 1 3 0V11M15 10.5V6a1.5 1.5 0 0 1 3 0v8c0 4-2.5 6.5-6 6.5-2.6 0-4.2-1.3-5.6-3.6L4.3 13.6a1.5 1.5 0 0 1 2.5-1.6L9 14.5V8.5"/></symbol> <symbol id="i-hand" viewBox="0 0 24 24"><path d="M9 11V5.5a1.5 1.5 0 0 1 3 0V11M12 10V4.5a1.5 1.5 0 0 1 3 0V11M15 10.5V6a1.5 1.5 0 0 1 3 0v8c0 4-2.5 6.5-6 6.5-2.6 0-4.2-1.3-5.6-3.6L4.3 13.6a1.5 1.5 0 0 1 2.5-1.6L9 14.5V8.5"/></symbol>
<symbol id="i-leaf" viewBox="0 0 24 24"><path d="M5 19c0-8 5-14 15-15-1 10-7 15-15 15z"/><path d="M5 19l8-8"/></symbol> <symbol id="i-leaf" viewBox="0 0 24 24"><path d="M5 19c0-8 5-14 15-15-1 10-7 15-15 15z"/><path d="M5 19l8-8"/></symbol>
<symbol id="o-shield2" 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> <symbol id="o-shield2" 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>
<!-- 选项图标 --> <!-- 选项图标 -->
<symbol id="o-girl" viewBox="0 0 24 24"><circle cx="12" cy="8.5" r="4"/><path d="M8 8.5c0-3.5 1.5-5.5 4-5.5s4 2 4 5.5v3.8M8 8.5v3.8"/><path d="M5.5 21c.7-3.6 3.2-5.8 6.5-5.8s5.8 2.2 6.5 5.8"/></symbol> <symbol id="o-hosp" viewBox="0 0 24 24"><path d="M3 21h18M5 21V8h14v13M9 21v-4h6v4"/><path d="M12 10v5M9.5 12.5h5"/><path d="M9 8V4.5h6V8"/></symbol>
<symbol id="o-boy" viewBox="0 0 24 24"><circle cx="12" cy="9" r="4"/><path d="M8.2 7.8c1.2.2 3.4-.2 4.8-1.8.8 1.2 2 1.8 2.8 1.8"/><path d="M5.5 21c.7-3.6 3.2-5.8 6.5-5.8s5.8 2.2 6.5 5.8"/></symbol> <symbol id="o-star" viewBox="0 0 24 24"><path d="M3 21h12M5 21V9h8v12M8 12.5h2M8 16h2"/><path d="M18 3.5l1.2 2.5 2.6.4-1.9 1.8.5 2.6-2.4-1.3-2.4 1.3.5-2.6-1.9-1.8 2.6-.4z"/></symbol>
<symbol id="o-gem" viewBox="0 0 24 24"><path d="M6.5 4h11L21 9l-9 11L3 9z"/><path d="M3 9h18M9.5 4L8 9l4 11 4-11-1.5-5"/></symbol>
<symbol id="o-heart" viewBox="0 0 24 24"><path d="M12 20c-5-3.6-8.5-7-8.5-11 0-2.7 2-4.7 4.5-4.7 1.7 0 3.1.9 4 2.4.9-1.5 2.3-2.4 4-2.4 2.5 0 4.5 2 4.5 4.7 0 4-3.5 7.4-8.5 11z"/></symbol>
<symbol id="o-med" viewBox="0 0 24 24"><rect x="3.5" y="6.5" width="17" height="13" rx="3"/><path d="M9 6.5V4.5h6v2M12 10v6M9 13h6"/></symbol>
<symbol id="o-ask" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M9.5 9.5a2.5 2.5 0 1 1 3.6 2.2c-.7.4-1.1.9-1.1 1.8v.5"/><path d="M12 17v.2"/></symbol>
<symbol id="o-drop" viewBox="0 0 24 24"><path d="M12 3.5c3.5 4.3 6 7.6 6 10.8a6 6 0 0 1-12 0c0-3.2 2.5-6.5 6-10.8z"/><path d="M9.2 14.5a2.9 2.9 0 0 0 2.6 2.8"/></symbol>
<symbol id="o-mix" viewBox="0 0 24 24"><path d="M7 3.5c2.3 2.8 4 5 4 7.2a4 4 0 0 1-8 0c0-2.2 1.7-4.4 4-7.2z"/><path d="M15 8h4M15.5 8v3l-1 1.5V20h5.5v-7.5l-1-1.5V8"/></symbol>
<symbol id="o-bottle" viewBox="0 0 24 24"><path d="M10 2.5h4M10.5 2.5v2.5L9 6.5h6l-1.5-1.5V2.5"/><path d="M8 9l1-2.5h6L16 9v10.5a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2z"/><path d="M8 12.5h3M8 15.5h3M8 18.5h3"/></symbol>
<symbol id="o-bldg" viewBox="0 0 24 24"><path d="M3 21h18M5 21V9l5-3v15M10 21V3l9 4v14M13.5 9h2M13.5 12.5h2M13.5 16h2M7 12h1M7 15.5h1"/></symbol> <symbol id="o-bldg" viewBox="0 0 24 24"><path d="M3 21h18M5 21V9l5-3v15M10 21V3l9 4v14M13.5 9h2M13.5 12.5h2M13.5 16h2M7 12h1M7 15.5h1"/></symbol>
<symbol id="o-bldg2" viewBox="0 0 24 24"><path d="M3 21h18M5 21V10h6v11M11 21V6h8v15M14 9.5h2M14 13h2M14 16.5h2M7.5 13.5h1M7.5 17h1"/></symbol> <symbol id="o-bldg2" viewBox="0 0 24 24"><path d="M3 21h18M5 21V10h6v11M11 21V6h8v15M14 9.5h2M14 13h2M14 16.5h2M7.5 13.5h1M7.5 17h1"/></symbol>
<symbol id="o-house" viewBox="0 0 24 24"><path d="M3.5 11L12 4l8.5 7M6 9.5V20h12V9.5"/><path d="M10 20v-5h4v5"/></symbol> <symbol id="o-house" viewBox="0 0 24 24"><path d="M3.5 11L12 4l8.5 7M6 9.5V20h12V9.5"/><path d="M10 20v-5h4v5"/></symbol>
@@ -381,32 +368,18 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
<button class="btn ghost press" id="reAns"><svg class="ic"><use href="#i-edit" xlink:href="#i-edit"/></svg>改一下答案</button> <button class="btn ghost press" id="reAns"><svg class="ic"><use href="#i-edit" xlink:href="#i-edit"/></svg>改一下答案</button>
</div> </div>
<div class="mom fu" id="mom"> <p class="hint">账单算完了,也记得和家人说说心里话。</p>
<svg class="art" viewBox="0 0 80 80" aria-hidden="true"><circle cx="40" cy="40" r="38" fill="#FFEBD6"/><path d="M40 60c-9-6.3-16-12.4-16-20.2 0-5 3.7-8.8 8.3-8.8 3.3 0 6 1.8 7.7 4.6 1.7-2.8 4.4-4.6 7.7-4.6 4.6 0 8.3 3.8 8.3 8.8C56 47.6 49 53.7 40 60z" fill="#F7B98A" stroke="#C9824A" stroke-width="2" stroke-linejoin="round"/><path d="M40 60v8M36 66c1.5-1.8 2.8-2.5 4-2.5s2.5.7 4 2.5" fill="none" stroke="#18A058" stroke-width="2" stroke-linecap="round"/><path d="M33.5 38.5c.6-1.8 2-3 3.8-3.2" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>
<div class="k">写在账单后面</div>
<h3 id="momH"></h3>
<p id="momP"></p>
<p class="say">如果可以的话,今天对她说一句:<br><q>妈,辛苦了。</q></p>
<div class="msg">
<div class="q" id="msgQ"></div>
<div class="ft"><span class="dt" id="msgDt"></span><button class="sw press" id="msgSw"><svg class="ic"><use href="#i-refresh" xlink:href="#i-refresh"/></svg>换一句</button></div>
</div>
<div class="macts">
<button class="btn press" id="copyBtn"><svg class="ic"><use href="#i-copy" xlink:href="#i-copy"/></svg>复制这句话,发给妈妈</button>
<button class="btn w press" id="cardBtn"><svg class="ic"><use href="#i-img" xlink:href="#i-img"/></svg>生成卡片</button>
</div>
</div>
<div id="tools" class="fu"></div> <div id="tools" class="fu"></div>
<p class="note"><b>估算区间,仅供参考。</b>按 2025~2026 年国内常见公开行情粗算,单项取中间值;收入只用来做对比,只存在你的手机上;按有生育保险估报销,不含早产、大病、住院等意外支出,不计通胀和房子;各地各家差别很大,看个大概就好。</p> <p class="note"><b>估算区间,仅供参考。</b>按 2025~2026 年国内常见公开行情粗算,单项取中间值;收入只用来做对比,只存在你的手机上;按有生育保险估报销、剖宫产按无并发症估,不含早产、大病、住院等意外支出,不计通胀和房子;各地各家差别很大,看个大概就好。</p>
</section> </section>
</div> </div>
<div class="mask" id="mask"> <div class="mask" id="mask">
<div class="mwrap" id="mwrap"><img id="maskImg" alt="给妈妈的卡片"></div> <div class="mwrap" id="mwrap"><img id="maskImg" alt="我的养娃账单"></div>
<p><svg class="ic"><use href="#i-hand" xlink:href="#i-hand"/></svg><span id="maskTip">长按图片,保存或发给妈妈</span></p> <p><svg class="ic"><use href="#i-hand" xlink:href="#i-hand"/></svg><span id="maskTip">长按图片,保存到相册</span></p>
<div class="row"><a id="dlBtn" download="给妈妈的卡片.png" hidden>下载图片</a><button id="maskClose">关闭</button></div> <div class="row"><a id="dlBtn" download="养娃账单.png" hidden>下载图片</a><button id="maskClose">关闭</button></div>
</div> </div>
<div class="toast" id="toast"></div> <div class="toast" id="toast"></div>
@@ -418,11 +391,11 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
/* ================= 路线 ================= */ /* ================= 路线 ================= */
var ROUTES = [ var ROUTES = [
{ id: 'rich', badge: 'b-rich', who: '我是大富豪', how: '富养娃', line: '钱能解决的,都不让娃将就', { id: 'rich', badge: 'b-rich', who: '我是大富豪', how: '富养娃', line: '钱能解决的,都不让娃将就',
tags: ['私立高端产检', '月子中心', '育儿嫂', '国际学校'], def: { care: 2, school: 2, extra: 2 } }, tags: ['私立高端产检', '月子中心', '育儿嫂', '国际学校'], def: { hosp: 2, yuezi: 2, care: 2, school: 2, extra: 2 } },
{ id: 'mid', badge: 'b-mid', who: '我是中产家', how: '从容养', line: '不卷也不亏待,日子过得舒展', { id: 'mid', badge: 'b-mid', who: '我是中产家', how: '从容养', line: '不卷也不亏待,日子过得舒展',
tags: ['公立特需', '月嫂', '托班', '适度早教'], def: { care: 1, school: 0, extra: 1 } }, tags: ['公立特需', '月嫂', '托班', '适度早教'], def: { hosp: 1, yuezi: 1, care: 1, school: 0, extra: 1 } },
{ id: 'low', badge: 'b-low', who: '我是普通人', how: '量力养', line: '能省则省,爱一点不少', { id: 'low', badge: 'b-low', who: '我是普通人', how: '量力养', line: '能省则省,爱一点不少',
tags: ['公立医院', '家人坐月子', '老人帮带', '能省则省'], def: { care: 0, school: 0, extra: 0 } } tags: ['公立医院', '家人坐月子', '老人帮带', '能省则省'], def: { hosp: 0, yuezi: 0, care: 0, school: 0, extra: 0 } }
]; ];
function tierOf(r) { return [2, 1, 0][r]; } // 档次 T:0 量力 / 1 从容 / 2 富养 function tierOf(r) { return [2, 1, 0][r]; } // 档次 T:0 量力 / 1 从容 / 2 富养
@@ -444,14 +417,23 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
/* ================= 问题(按所选阶段出现) ================= */ /* ================= 问题(按所选阶段出现) ================= */
var QS = [ var QS = [
{ k: 'sex', h: '先认识一下,你是…', s: '账单最后,有句话想对你说', two: 1, o: [
['女生', '我是准妈妈', 'girl'], ['男生', '我是准爸爸', 'boy']] },
{ k: 'st', type: 'stage', h: '这次想算哪一段?', s: '默认从怀孕算到 18 岁,也可以只算其中几段' }, { k: 'st', type: 'stage', h: '这次想算哪一段?', s: '默认从怀孕算到 18 岁,也可以只算其中几段' },
{ k: 'city', h: '你家在哪类城市?', s: '月嫂、托班、学费都跟着城市走', o: [ { k: 'city', h: '你家在哪类城市?', s: '月嫂、托班、学费都跟着城市走', o: [
['一线城市', '北京、上海、广州、深圳', 'bldg'], ['新一线及省会', '成都、杭州、武汉、各省会', 'bldg2'], ['一线城市', '北京、上海、广州、深圳', 'bldg'], ['新一线及省会', '成都、杭州、武汉、各省会', 'bldg2'],
['普通地级市', '三四线城市', 'house'], ['县城及乡镇', '县城、镇上', 'tree']] }, ['普通地级市', '三四线城市', 'house'], ['县城及乡镇', '县城、镇上', 'tree']] },
{ k: 'kid', h: '这是第几个宝宝?', s: '老大的东西能接着用', if: function (st) { return has(st, [0, 1, 2, 3, 4]); }, o: [ { k: 'kid', h: '这是第几个宝宝?', s: '老大的东西能接着用', if: function (st) { return has(st, [0, 1, 2, 3, 4]); }, o: [
['头胎', '推车、衣服、玩具都要新添置', 'one'], ['二胎及以上', '大件和衣物能复用一部分', 'layers']] }, ['头胎', '推车、衣服、玩具都要新添置', 'one'], ['二胎及以上', '大件和衣物能复用一部分', 'layers']] },
{ k: 'hosp', h: '打算在哪类医院产检、生娃?', s: '产检和分娩的费用,主要看医院', if: function (st) { return has(st, [0, 1]); }, o: [
['公立医院普通门诊', '建档产检、普通病房,医保能报', 'hosp'], ['公立医院特需', '特需门诊、单间病房,自费多一些', 'star'],
['私立妇产医院', '产检分娩套餐、VIP 病房', 'gem']] },
{ k: 'birth', h: '预计顺产还是剖宫产?', s: '剖宫产手术费更高、要多住几天', d: 2, if: function (st) { return has(st, [1]); }, o: [
['顺产', '一般住院 2~3 天,可选无痛', 'heart'], ['剖宫产', '一般住院 4~6 天,手术和麻醉另算', 'med'],
['还不确定', '按顺产估,再留一点剖宫产的差价', 'ask']] },
{ k: 'yuezi', h: '月子打算怎么坐?', s: '坐月子是生娃前后最大的一笔', if: function (st) { return has(st, [2]); }, o: [
['家里人照顾', '家人做月子餐、帮带宝宝', 'family'], ['请月嫂到家', '26 天住家月嫂', 'nurse'],
['住月子中心', '28 天,吃住护理都包', 'bldg2']] },
{ k: 'feed', h: '宝宝打算怎么喂?', s: '第一年奶粉花多少,差别就在这', d: 1, if: function (st) { return has(st, [2, 3]); }, o: [
['母乳为主', '偶尔补一点奶粉', 'drop'], ['混合喂养', '母乳加奶粉', 'mix'], ['奶粉喂养', '主要喝奶粉', 'bottle']] },
{ k: 'care', h: '0~3 岁,白天谁带娃?', s: '产假结束后的安排,差别很大', if: function (st) { return has(st, [3, 4, 5]); }, o: [ { k: 'care', h: '0~3 岁,白天谁带娃?', s: '产假结束后的安排,差别很大', if: function (st) { return has(st, [3, 4, 5]); }, o: [
['老人或自己带', '给老人一点补贴,3 岁上幼儿园', 'family'], ['家里带,2 岁上托班', '第 3 年交托班费', 'flag'], ['老人或自己带', '给老人一点补贴,3 岁上幼儿园', 'family'], ['家里带,2 岁上托班', '第 3 年交托班费', 'flag'],
['请育儿嫂', '住家或白班阿姨,带到上幼儿园', 'nurse'], ['1 岁半上托育园', '全日托,按月费算', 'school']] }, ['请育儿嫂', '住家或白班阿姨,带到上幼儿园', 'nurse'], ['1 岁半上托育园', '全日托,按月费算', 'school']] },
@@ -466,21 +448,36 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
/* ================= 费用表(单位:元,2025~2026 国内常见公开行情;基准 = 新一线及省会) ================= /* ================= 费用表(单位:元,2025~2026 国内常见公开行情;基准 = 新一线及省会) =================
I(名称, [量力低,高], [从容低,高], [富养低,高], 城市系数, 二胎复用系数)。名称可以是 [量力名, 从容名, 富养名];某档 [0,0] 表示这档不花这笔。 I(名称, [量力低,高], [从容低,高], [富养低,高], 城市系数, 二胎复用系数)。名称可以是 [量力名, 从容名, 富养名];某档 [0,0] 表示这档不花这笔。
D(答案键, 名称或按答案的名称数组, [按答案的 [低,高]...], 城市系数):随答案变(上学路线 school / 课外班 extra)。 D(答案键, 名称或按答案的名称数组, [按答案的 [低,高]...], 城市系数):随答案变(医院 hosp / 上学路线 school / 课外班 extra 等)。
F(名称或 s=>名称, s=>[低,高], 城市系数, 二胎复用系数):要同时看几道题的项(分娩方式 × 医院、月子 × 档次、喂养 × 档次);名称为空或 [0,0] 不列。
城市系数:s 人工/服务/教育,g 吃穿用,m 医疗,0 不随城市变。 */ 城市系数:s 人工/服务/教育,g 吃穿用,m 医疗,0 不随城市变。 */
var CF = { s: [1.45, 1, 0.72, 0.55], g: [1.1, 1, 0.9, 0.82], m: [1.25, 1, 0.8, 0.65], '0': [1, 1, 1, 1] }; var CF = { s: [1.45, 1, 0.72, 0.55], g: [1.1, 1, 0.9, 0.82], m: [1.25, 1, 0.8, 0.65], '0': [1, 1, 1, 1] };
function I(n, a, b, c, k, r) { return { n: n, v: [a, b, c], k: k, r: r }; } function I(n, a, b, c, k, r) { return { n: n, v: [a, b, c], k: k, r: r }; }
function D(g, n, vs, k) { return { g: g, n: n, dv: vs, k: k }; } function D(g, n, vs, k) { return { g: g, n: n, dv: vs, k: k }; }
function F(n, fv, k, r) { return { n: typeof n === 'function' ? n : function () { return n; }, fv: fv, k: k, r: r }; }
function sc3(v, f) { return [v[0] * f, v[1] * f]; }
// 分娩主项 [医院][分娩方式:顺产/剖宫产/还不确定](不确定 ≈ 顺产 + 约三成剖宫产差价)
var DELIV = [
[[3000, 6000], [8000, 15000], [4500, 9000]],
[[6000, 12000], [15000, 25000], [8500, 16000]],
[[25000, 50000], [45000, 90000], [31000, 62000]]
];
var YUEZI = [ // 月子主项 [月子打算][档次 T]
[[2000, 4000], [2500, 5000], [3000, 6000]],
[[8000, 13000], [12000, 20000], [18000, 30000]],
[[25000, 40000], [35000, 60000], [50000, 120000]]
];
var MILK1 = [[8000, 14000], [12000, 20000], [18000, 28000]], MILK_F = [0.15, 0.5, 1]; // 0~1 岁全奶粉喂养 [档次];按喂养方式乘系数
var SUB = [3600, 9600], NANNY = [60000, 90000], TUOBAN = [20000, 45000], DAYCARE = [27500, 55000]; var SUB = [3600, 9600], NANNY = [60000, 90000], TUOBAN = [20000, 45000], DAYCARE = [27500, 55000];
var COST = [ var COST = [
// ① 孕期产检 // ① 孕期产检
[ [
I(['建档和常规产检(约 12 次)', '特需门诊产检(约 12 次)', '私立医院产检套餐'], [1500, 3000], [5000, 10000], [15000, 30000], 'm'), D('hosp', ['建档和常规产检(约 12 次)', '特需门诊产检(约 12 次)', '私立医院产检套餐'], [[1500, 3000], [5000, 10000], [15000, 30000]], 'm'),
I('B 超(NT、大排畸、晚孕)', [800, 1500], [1500, 3000], [2000, 4000], 'm'), D('hosp', 'B 超(NT、大排畸、晚孕)', [[800, 1500], [1500, 3000], [2000, 4000]], 'm'),
I(['唐氏筛查', '无创 DNA(NIPT)', '无创 DNA 加强版'], [200, 400], [1500, 2500], [2500, 4000], 'm'), I(['唐氏筛查', '无创 DNA(NIPT)', '无创 DNA 加强版'], [200, 400], [1500, 2500], [2500, 4000], 'm'),
I('四维彩超', [300, 600], [500, 1000], [800, 2000], 'm'), D('hosp', '四维彩超', [[300, 600], [500, 1000], [800, 2000]], 'm'),
I('糖耐量和血液检查', [300, 600], [500, 1000], [800, 1500], 'm'), D('hosp', '糖耐量和血液检查', [[300, 600], [500, 1000], [800, 1500]], 'm'),
I('胎心监护', [200, 500], [400, 800], [800, 1500], 'm'), D('hosp', '胎心监护', [[200, 500], [400, 800], [800, 1500]], 'm'),
I('孕妇奶粉', [0, 600], [1200, 2400], [2400, 4800], 'g'), I('孕妇奶粉', [0, 600], [1200, 2400], [2400, 4800], 'g'),
I('叶酸、DHA、钙铁维生素', [500, 1200], [1500, 3000], [3000, 6000], 'g'), I('叶酸、DHA、钙铁维生素', [500, 1200], [1500, 3000], [3000, 6000], 'g'),
I('孕妇装和孕妇内衣', [600, 1500], [1500, 3500], [4000, 10000], 'g'), I('孕妇装和孕妇内衣', [600, 1500], [1500, 3500], [4000, 10000], 'g'),
@@ -494,26 +491,30 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
], ],
// ② 分娩住院 // ② 分娩住院
[ [
I(['公立普通病房分娩', '公立特需分娩', '私立医院分娩套餐'], [3000, 8000], [8000, 18000], [35000, 80000], 'm'), F(function (s) { return ['公立普通病房', '公立特需', '私立医院'][s.hosp] + ['顺产', '剖宫产', '分娩(顺剖未定)'][s.birth]; },
I(['无痛分娩', '无痛分娩和导乐', '无痛和一对一助产'], [1000, 2500], [2000, 4000], [3000, 8000], 'm'), function (s) { return DELIV[s.hosp][s.birth]; }, 'm'),
I(['病房床位', '单间升级', 'VIP 套房升级'], [300, 800], [2000, 5000], [5000, 15000], 'm'), F(function (s) { return s.birth === 1 ? '术后镇痛泵' : ['无痛分娩', '无痛分娩和导乐', '无痛和一对一助产'][s.hosp]; },
function (s) { return s.birth === 1 ? [[500, 1200], [800, 1500], [1000, 3000]][s.hosp] : [[1000, 2500], [2000, 4000], [3000, 8000]][s.hosp]; }, 'm'),
F(function (s) { return ['病房床位', '单间升级', 'VIP 套房升级'][s.hosp] + (s.birth === 1 ? '(多住几天)' : ''); },
function (s) { return sc3([[300, 800], [2000, 5000], [5000, 15000]][s.hosp], [1, 1.6, 1.2][s.birth]); }, 'm'),
I('陪护床和护工', [300, 800], [1000, 2500], [2000, 5000], 's'), I('陪护床和护工', [300, 800], [1000, 2500], [2000, 5000], 's'),
I('新生儿筛查(听力、足跟血)', [300, 800], [500, 1200], [1500, 3000], 'm'), D('hosp', '新生儿筛查(听力、足跟血)', [[300, 800], [500, 1200], [1500, 3000]], 'm'),
I('新生儿尿片、衣服、包被', [200, 500], [400, 800], [800, 1500], 'g'), I('新生儿尿片、衣服、包被', [200, 500], [400, 800], [800, 1500], 'g'),
I('产妇用品(产褥垫、收腹带)', [200, 500], [400, 800], [800, 1500], 'g'), I('产妇用品(产褥垫、收腹带)', [200, 500], [400, 800], [800, 1500], 'g'),
I(['住院餐', '住院营养餐', '院内营养月子餐'], [300, 800], [800, 1500], [2000, 4000], 's'), F(function (s) { return ['住院餐', '住院营养餐', '院内营养月子餐'][s.hosp]; }, function (s) { return sc3([[300, 800], [800, 1500], [2000, 4000]][s.hosp], [1, 1.6, 1.2][s.birth]); }, 's'),
I('脐带血存储', [0, 0], [0, 0], [15000, 25000], '0'), I('脐带血存储', [0, 0], [0, 0], [15000, 25000], '0'),
I('报喜红包和喜糖', [500, 1500], [1000, 3000], [3000, 8000], 'g'), I('报喜红包和喜糖', [500, 1500], [1000, 3000], [3000, 8000], 'g'),
I('家属交通和餐费', [300, 800], [500, 1500], [1000, 3000], 's'), I('家属交通和餐费', [300, 800], [500, 1500], [1000, 3000], 's'),
I('生育保险报销(预估)', [-5000, -2500], [-4500, -2000], [-2500, -500], 'm') F('生育保险报销(预估)', function (s) { return sc3([[-5000, -2500], [-4500, -2000], [-2500, -500]][s.hosp], [1, 1.4, 1.1][s.birth]); }, 'm')
], ],
// ③ 坐月子 // ③ 坐月子
[ [
I(['月子餐食材(家人做)', '月嫂 26 天', '高端月子中心 28 天'], [2500, 5000], [12000, 20000], [50000, 120000], 's'), F(function (s) { return ['月子餐食材(家人做)', '住家月嫂 26 天', s.T === 2 ? '高端月子中心 28 天' : '月子中心 28 天'][s.yuezi]; },
I('月子餐食材和营养汤', [0, 0], [2000, 4000], [0, 0], 'g'), function (s) { return YUEZI[s.yuezi][s.T]; }, 's'),
I('催乳和通乳', [0, 500], [800, 2000], [2000, 5000], 's'), F('月子餐食材和营养汤', function (s) { return s.yuezi === 1 ? [[1500, 3000], [2000, 4000], [3000, 6000]][s.T] : [0, 0]; }, 'g'),
I('吸奶器和储奶袋', [300, 800], [800, 2000], [2000, 4000], 'g', 0.5), F('催乳和通乳', function (s) { return s.feed === 2 ? [0, 0] : [[0, 500], [800, 2000], [2000, 5000]][s.T]; }, 's'),
I('哺乳内衣和防溢乳垫', [200, 500], [400, 900], [800, 2000], 'g'), F('吸奶器和储奶袋', function (s) { return s.feed === 2 ? [0, 0] : [[300, 800], [800, 2000], [2000, 4000]][s.T]; }, 'g', 0.5),
F('哺乳内衣和防溢乳垫', function (s) { return s.feed === 2 ? [0, 0] : [[200, 500], [400, 900], [800, 2000]][s.T]; }, 'g'),
I('产妇卫生巾和月子服', [300, 700], [500, 1200], [1000, 2500], 'g'), I('产妇卫生巾和月子服', [300, 700], [500, 1200], [1000, 2500], 'g'),
I(['产后盆底康复(医院)', '产后修复疗程', '产后修复和私教塑形'], [500, 1500], [3000, 6000], [10000, 25000], 's'), I(['产后盆底康复(医院)', '产后修复疗程', '产后修复和私教塑形'], [500, 1500], [3000, 6000], [10000, 25000], 's'),
I('产后 42 天复查', [200, 500], [400, 1000], [1000, 3000], 'm'), I('产后 42 天复查', [200, 500], [400, 1000], [1000, 3000], 'm'),
@@ -524,7 +525,8 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
], ],
// ④ 0~1 岁 // ④ 0~1 岁
[ [
I(['国产奶粉(混合喂养)', '国产高端奶粉', '进口有机奶粉'], [3000, 6000], [6000, 10000], [12000, 20000], 'g'), F(function (s) { return ['国产奶粉', '国产高端奶粉', '进口有机奶粉'][s.T] + ['(偶尔补充)', '(混合喂养)', '(全奶粉喂养)'][s.feed]; },
function (s) { return sc3(MILK1[s.T], MILK_F[s.feed]); }, 'g'),
I('米粉和辅食', [800, 1500], [1500, 3000], [3000, 6000], 'g'), I('米粉和辅食', [800, 1500], [1500, 3000], [3000, 6000], 'g'),
I('奶瓶和奶嘴', [200, 400], [400, 800], [800, 1500], 'g'), I('奶瓶和奶嘴', [200, 400], [400, 800], [800, 1500], 'g'),
I('温奶器、消毒器', [200, 400], [400, 900], [1000, 2500], 'g', 0.5), I('温奶器、消毒器', [200, 400], [400, 900], [1000, 2500], 'g', 0.5),
@@ -552,7 +554,7 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
], ],
// ⑤ 1~3 岁(f1 = 属于 1~2 岁那一年的比例,用来算 2 岁累计) // ⑤ 1~3 岁(f1 = 属于 1~2 岁那一年的比例,用来算 2 岁累计)
[ [
I(['国产奶粉', '国产高端奶粉', '进口高端奶粉'], [3000, 6000], [6000, 10000], [12000, 18000], 'g'), F(function (s) { return ['国产奶粉', '国产高端奶粉', '进口高端奶粉'][s.T]; }, function (s) { return sc3([[3000, 6000], [6000, 10000], [12000, 18000]][s.T], [0.7, 0.85, 1][s.feed]); }, 'g'),
I('纸尿裤和拉拉裤', [2000, 3500], [3000, 5000], [4500, 7000], 'g'), I('纸尿裤和拉拉裤', [2000, 3500], [3000, 5000], [4500, 7000], 'g'),
I('湿巾和洗护用品', [600, 1200], [1000, 2000], [2000, 4000], 'g'), I('湿巾和洗护用品', [600, 1200], [1000, 2000], [2000, 4000], 'g'),
I('辅食、水果和零食', [4000, 8000], [6000, 12000], [12000, 24000], 'g'), I('辅食、水果和零食', [4000, 8000], [6000, 12000], [12000, 24000], 'g'),
@@ -676,15 +678,17 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
var $ = function (s) { return document.querySelector(s); }; var $ = function (s) { return document.querySelector(s); };
var sc = $('#scroll'); var sc = $('#scroll');
var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches; var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
var route = -1, A = {}, cur = 0, hasBill = false, msgI = 0, bill = null, billNo = '', billAt = ''; var route = -1, A = {}, cur = 0, hasBill = false, bill = null, billNo = '', billAt = '';
/* ================= 计算 ================= */ /* ================= 计算 ================= */
function r100(n) { return Math.round(n / 100) * 100; } function r100(n) { return Math.round(n / 100) * 100; }
function sel() { return A.st && A.st.length ? A.st : ALL; } function sel() { return A.st && A.st.length ? A.st : ALL; }
function ctx(r, a) { function ctx(r, a) {
var d = ROUTES[r].def; var d = ROUTES[r].def;
function g(k) { return a[k] != null ? a[k] : d[k] != null ? d[k] : QK[k].d; }
return { T: tierOf(r), city: a.city == null ? 1 : a.city, kid: a.kid || 0, return { T: tierOf(r), city: a.city == null ? 1 : a.city, kid: a.kid || 0,
care: a.care == null ? d.care : a.care, school: a.school == null ? d.school : a.school, extra: a.extra == null ? d.extra : a.extra }; hosp: g('hosp'), birth: g('birth'), yuezi: g('yuezi'), feed: g('feed'),
care: g('care'), school: g('school'), extra: g('extra') };
} }
function calc(r, a, stages) { function calc(r, a, stages) {
var s = ctx(r, a); var s = ctx(r, a);
@@ -773,7 +777,7 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
$('#routes').addEventListener('click', function (e) { $('#routes').addEventListener('click', function (e) {
var b = e.target.closest('.rt'); if (!b) return; var b = e.target.closest('.rt'); if (!b) return;
var r = +b.dataset.r; var r = +b.dataset.r;
if (r !== route) { route = r; delete A.care; delete A.school; delete A.extra; } // 换路线:后几题回到新路线的默认 if (r !== route) { route = r; Object.keys(ROUTES[r].def).forEach(function (k) { delete A[k]; }); } // 换路线:后几题回到新路线的默认
markRoute(); markRoute();
}); });
$('#goQ').addEventListener('click', function () { if (route < 0) return; cur = 0; renderQ(); }); $('#goQ').addEventListener('click', function () { if (route < 0) return; cur = 0; renderQ(); });
@@ -781,7 +785,7 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
/* ================= 问题屏 ================= */ /* ================= 问题屏 ================= */
function flow() { var st = sel(); return QS.filter(function (q) { return !q.if || q.if(st); }); } function flow() { var st = sel(); return QS.filter(function (q) { return !q.if || q.if(st); }); }
function val(k) { if (A[k] != null) return A[k]; var d = ROUTES[route].def; return d[k] != null ? d[k] : null; } function val(k) { if (A[k] != null) return A[k]; var d = ROUTES[route].def; return d[k] != null ? d[k] : QK[k].d != null ? QK[k].d : null; }
var stTmp = null, incTmp = ''; var stTmp = null, incTmp = '';
function renderQ() { function renderQ() {
var list = flow(), q = list[cur], R = ROUTES[route], v = val(q.k), last = cur === list.length - 1; var list = flow(), q = list[cur], R = ROUTES[route], v = val(q.k), last = cur === list.length - 1;
@@ -809,14 +813,15 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
markInc(); markInc();
$('#qtip').textContent = ''; $('#qtip').textContent = '';
} else { } else {
opts.className = 'opts' + (q.two ? ' two' : ''); opts.className = 'opts';
var rd = ROUTES[route].def[q.k], dTag = rd != null ? '路线默认' : '默认', dv = rd != null ? rd : q.d;
opts.innerHTML = q.o.map(function (o, i) { opts.innerHTML = q.o.map(function (o, i) {
var isDef = ROUTES[route].def[q.k] === i; var isDef = dv === i;
return '<button class="opt' + (v === i ? ' on' : '') + '" data-v="' + i + '"><span class="oi"><svg class="ic"><use href="#o-' + o[2] + '" xlink:href="#o-' + o[2] + '"/></svg></span>' + return '<button class="opt' + (v === i ? ' on' : '') + '" data-v="' + i + '"><span class="oi"><svg class="ic"><use href="#o-' + o[2] + '" xlink:href="#o-' + o[2] + '"/></svg></span>' +
'<span class="ox"><b>' + o[0] + (isDef ? '<em>路线默认</em>' : '') + '</b><small>' + o[1] + '</small></span><span class="rd"></span></button>'; '<span class="ox"><b>' + o[0] + (isDef ? '<em>' + dTag + '</em>' : '') + '</b><small>' + o[1] + '</small></span><span class="rd"></span></button>';
}).join(''); }).join('');
keep.classList.toggle('on', v != null); keep.classList.toggle('on', v != null);
$('#keepT').textContent = last ? '就这样,出账单' : (A[q.k] == null && ROUTES[route].def[q.k] != null ? '按路线默认,下一题' : '就这样,下一题'); $('#keepT').textContent = last ? '就这样,出账单' : (A[q.k] == null && dv != null ? (rd != null ? '按路线默认,下一题' : '按默认,下一题') : '就这样,下一题');
$('#qtip').textContent = '选完自动下一题'; $('#qtip').textContent = '选完自动下一题';
} }
$('#prevT').textContent = cur > 0 ? '上一题' : '换路线'; $('#prevT').textContent = cur > 0 ? '上一题' : '换路线';
@@ -898,7 +903,7 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
var R = ROUTES[route], st = sel(), b = calc(route, A, st), s = b.s, isAll = st.length === ALL.length; var R = ROUTES[route], st = sel(), b = calc(route, A, st), s = b.s, isAll = st.length === ALL.length;
var full = isAll ? b : calc(route, A, ALL); var full = isAll ? b : calc(route, A, ALL);
bill = b; bill.full = full; bill.range = rangeName(st); bill.isAll = isAll; bill = b; bill.full = full; bill.range = rangeName(st); bill.isAll = isAll;
var sexW = A.sex === 1 ? '准爸爸' : '准妈妈', inc = incomeOf(b); var inc = incomeOf(b);
$('#rRoute').textContent = R.who.replace('我是', '') + ' · ' + R.how; $('#rRoute').textContent = R.who.replace('我是', '') + ' · ' + R.how;
$('#rMeta').textContent = CITY_S[s.city] + (has(st, [0, 1, 2, 3, 4]) ? ' · ' + (s.kid ? '二胎' : '头胎') : ''); $('#rMeta').textContent = CITY_S[s.city] + (has(st, [0, 1, 2, 3, 4]) ? ' · ' + (s.kid ? '二胎' : '头胎') : '');
$('#rTitle').innerHTML = isAll ? '养到 18 岁,大约 <em>' + w(b.m) + ' 万</em>' : esc(bill.range) + ',合计约 <em>' + w(b.m) + ' 万</em>'; $('#rTitle').innerHTML = isAll ? '养到 18 岁,大约 <em>' + w(b.m) + ' 万</em>' : esc(bill.range) + ',合计约 <em>' + w(b.m) + ' 万</em>';
@@ -949,15 +954,6 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
'<div class="rc-f"><b>谢谢惠顾</b>宝宝一经签收,不退不换<br>账单按行情中间值估算,仅供参考' + barcode(+billNo.slice(-5) || 7) + '<div class="rc-no mono">' + billNo + '</div></div>'; '<div class="rc-f"><b>谢谢惠顾</b>宝宝一经签收,不退不换<br>账单按行情中间值估算,仅供参考' + barcode(+billNo.slice(-5) || 7) + '<div class="rc-no mono">' + billNo + '</div></div>';
$('#paper').innerHTML = h; $('#paper').innerHTML = h;
// 情感收尾
$('#momH').textContent = A.sex === 1 ? '你就要做爸爸了。' : '你就要做妈妈了。';
var p = isAll ? '你的妈妈在养你长大的路上,也花了这么多钱。放在今天,差不多也是这样一张 <em>' + w(b.m) + ' 万</em>的账单;'
: '光是' + esc(bill.range) + ',就要 <em>' + w(b.m) + ' 万</em>。你的妈妈把你从怀孕一路养到 18 岁,放在今天,差不多是一张 <em>' + w(full.m) + ' 万</em>的账单;';
var fi = incomeOf(full);
if (fi) p += '相当于你家现在 <em>' + fi.txt + '</em>的收入;';
p += '还有数不清的时间和心思,<b>没有一项写在账单上</b>。';
$('#momP').innerHTML = p;
renderMsg();
renderTools(); renderTools();
[].forEach.call(document.querySelectorAll('#sRes .fu'), function (el) { el.classList.remove('in'); }); [].forEach.call(document.querySelectorAll('#sRes .fu'), function (el) { el.classList.remove('in'); });
@@ -990,139 +986,25 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
}, dur + 60); }, dur + 60);
} }
/* ================= 给妈妈的话 ================= */
function msgs() {
var who = A.sex === 1 ? '爸爸' : '妈妈';
return [
'妈,我今天算了算养一个孩子要花多少钱,才知道你当年有多不容易。辛苦了。',
'妈,我也快当' + who + '了。以前没好好说过,这些年辛苦你了,谢谢你把我养这么大。',
'妈,钱能算出来,你给我的时间和心思算不出来。辛苦了,周末回家吃饭。'
];
}
function renderMsg() {
var L = msgs();
msgI = msgI % L.length;
$('#msgQ').textContent = L[msgI];
$('#msgDt').innerHTML = L.map(function (x, i) { return '<i class="' + (i === msgI ? 'on' : '') + '"></i>'; }).join('');
}
$('#msgSw').addEventListener('click', function () { msgI++; renderMsg(); save(); });
var tt; var tt;
function toast(msg) { function toast(msg) {
var el = $('#toast'); el.textContent = msg; el.classList.add('on'); var el = $('#toast'); el.textContent = msg; el.classList.add('on');
clearTimeout(tt); tt = setTimeout(function () { el.classList.remove('on'); }, 2400); clearTimeout(tt); tt = setTimeout(function () { el.classList.remove('on'); }, 2400);
} }
function copy(text) {
function legacy() { return new Promise(function (ok, no) {
var ta = document.createElement('textarea');
ta.value = text; ta.setAttribute('readonly', ''); ta.style.cssText = 'position:fixed;top:-999px;opacity:0';
document.body.appendChild(ta); ta.select();
var r = false; try { r = document.execCommand('copy'); } catch (e) {}
document.body.removeChild(ta);
r ? ok() : no();
}); }
if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text).catch(legacy);
return legacy();
}
$('#copyBtn').addEventListener('click', function () {
copy(msgs()[msgI]).then(function () { toast('已复制,去微信发给妈妈吧'); }, function () { toast('复制没成功,点「生成卡片」发图给她也很好'); });
});
/* ================= 生成卡片:canvas → <img> 长按保存 ================= */ /* ================= canvas 小工具 ================= */
var FONT = '-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif'; var FONT = '-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif';
var MONO = '"SF Mono",Menlo,Consolas,"Roboto Mono","Courier New",monospace'; var MONO = '"SF Mono",Menlo,Consolas,"Roboto Mono","Courier New",monospace';
function rr(c, x, y, w2, h2, r) { function rr(c, x, y, w2, h2, r) {
c.beginPath(); c.moveTo(x + r, y); c.arcTo(x + w2, y, x + w2, y + h2, r); c.arcTo(x + w2, y + h2, x, y + h2, r); c.beginPath(); c.moveTo(x + r, y); c.arcTo(x + w2, y, x + w2, y + h2, r); c.arcTo(x + w2, y + h2, x, y + h2, r);
c.arcTo(x, y + h2, x, y, r); c.arcTo(x, y, x + w2, y, r); c.closePath(); c.arcTo(x, y + h2, x, y, r); c.arcTo(x, y, x + w2, y, r); c.closePath();
} }
function wrap(c, text, maxW) {
var lines = [], line = '';
text.split('').forEach(function (ch) {
if (c.measureText(line + ch).width > maxW && line) { lines.push(line); line = ch; } else line += ch;
});
if (line) lines.push(line);
for (var i = 1; i < lines.length; i++) if (/^[,。、;:!?」]/.test(lines[i])) { lines[i - 1] += lines[i][0]; lines[i] = lines[i].slice(1); }
return lines.filter(function (l) { return l; });
}
function fit(c, text, maxW, size, weight, fam) { // 字太长就缩小
do { c.font = weight + ' ' + size + 'px ' + fam; size -= 2; } while (c.measureText(text).width > maxW && size > 16);
}
function drawCard() {
var b = bill, R = ROUTES[route], W = 750, H = 1240, inc = incomeOf(b.full);
var cv = document.createElement('canvas'); cv.width = W; cv.height = H;
var c = cv.getContext('2d');
var g = c.createLinearGradient(0, 0, 0, H);
g.addColorStop(0, '#FFF3E6'); g.addColorStop(.5, '#FFFBF6'); g.addColorStop(1, '#EAF7F0');
c.fillStyle = g; c.fillRect(0, 0, W, H);
c.fillStyle = 'rgba(255,255,255,.6)'; c.beginPath(); c.arc(660, 70, 200, 0, 7); c.fill();
c.fillStyle = 'rgba(24,160,88,.06)'; c.beginPath(); c.arc(40, 1120, 170, 0, 7); c.fill();
c.textAlign = 'center'; c.textBaseline = 'alphabetic';
c.font = '700 24px ' + FONT;
var lb = '兜爸心选 · 养娃账单', lw = c.measureText(lb).width + 48;
c.fillStyle = '#fff'; rr(c, (W - lw) / 2, 54, lw, 48, 24); c.fill();
c.fillStyle = '#18A058'; c.fillText(lb, W / 2, 86);
c.fillStyle = '#1F2329'; c.font = '800 54px ' + FONT;
c.fillText(A.sex === 1 ? '你就要做爸爸了。' : '你就要做妈妈了。', W / 2, 190);
c.fillStyle = '#86909C'; c.font = '400 25px ' + FONT;
c.fillText(R.who + ' · ' + R.how + ' · ' + CITY_S[b.s.city], W / 2, 238);
/* 小票:始终画「怀孕到 18 岁」的全程合计,和下面「你的妈妈也付过这样一张账单」对上 */
var f = b.full, px = 110, py = 286, pw = W - 220, ph = inc ? 440 : 400;
c.save(); c.shadowColor = 'rgba(120,80,40,.14)'; c.shadowBlur = 30; c.shadowOffsetY = 10;
c.fillStyle = '#fff'; c.beginPath(); c.moveTo(px, py); c.lineTo(px + pw, py); c.lineTo(px + pw, py + ph);
var n = Math.floor(pw / 20);
for (var i = 0; i < n; i++) { var x0 = px + pw - i * (pw / n); c.lineTo(x0 - pw / n / 2, py + ph + 12); c.lineTo(x0 - pw / n, py + ph); }
c.closePath(); c.fill(); c.restore();
c.fillStyle = '#86909C'; c.font = '500 23px ' + FONT; c.fillText('养一个孩子 · 怀孕到 18 岁 · 合计', W / 2, py + 62);
c.fillStyle = '#18A058'; fit(c, '¥' + money(f.m), pw - 40, 66, '800', MONO); c.fillText('¥' + money(f.m), W / 2, py + 142);
c.fillStyle = '#4E5969'; c.font = '400 23px ' + FONT; c.fillText('约 ' + w(f.m) + ' 万 · 区间 ' + wr(f.lo, f.hi), W / 2, py + 186);
c.strokeStyle = '#C9CED4'; c.lineWidth = 2; c.setLineDash([8, 7]);
c.beginPath(); c.moveTo(px + 30, py + 220); c.lineTo(px + pw - 30, py + 220); c.stroke();
var cols = [[' 1 岁', f.n1], [' 2 岁', f.n2], [' 3 岁', f.n3]], cw = (pw - 60) / 3;
cols.forEach(function (x, k) {
var cx = px + 30 + cw * k + cw / 2;
c.fillStyle = '#86909C'; c.font = '400 21px ' + FONT; c.fillText('养到' + x[0], cx, py + 264);
c.fillStyle = '#1F2329'; c.font = '800 32px ' + MONO; c.fillText(w(x[1]) + '万', cx, py + 306);
});
c.beginPath(); c.moveTo(px + 30, py + 336); c.lineTo(px + pw - 30, py + 336); c.stroke(); c.setLineDash([]);
var yy = py + 376;
if (inc) {
c.textAlign = 'left'; c.fillStyle = '#4E5969'; c.font = '400 22px ' + FONT; c.fillText('≈ 你家现在的收入', px + 30, yy);
c.textAlign = 'right'; c.fillStyle = '#18A058'; c.font = '800 24px ' + FONT; c.fillText(inc.txt, px + pw - 30, yy);
yy += 42;
}
c.textAlign = 'left'; c.fillStyle = '#B4733A'; c.font = '700 23px ' + FONT; c.fillText('时间、心思和拥抱', px + 30, yy);
c.textAlign = 'right'; c.fillText('无法计价', px + pw - 30, yy);
c.textAlign = 'center';
var oy = inc ? 40 : 0;
c.fillStyle = '#5B5249'; c.font = '400 28px ' + FONT;
c.fillText('你的妈妈养你长大,', W / 2, 778 + oy);
c.fillText('也付过这样一张账单。', W / 2, 822 + oy);
c.font = '800 60px ' + FONT;
var say = '妈,辛苦了。', sw = c.measureText(say).width;
c.fillStyle = 'rgba(244,190,130,.45)'; c.fillRect((W - sw) / 2 - 6, 896 + oy, sw + 12, 24);
c.fillStyle = '#1F2329'; c.fillText(say, W / 2, 914 + oy);
c.fillStyle = '#4E5969'; c.font = '400 26px ' + FONT;
var ls = wrap(c, '「' + msgs()[msgI] + '」', W - 170);
ls.slice(0, 3).forEach(function (l, k) { c.fillText(l, W / 2, 986 + oy + k * 40); });
c.strokeStyle = 'rgba(24,160,88,.25)'; c.lineWidth = 2;
c.beginPath(); c.moveTo(W / 2 - 150, 1148); c.lineTo(W / 2 + 150, 1148); c.stroke();
c.fillStyle = '#18A058'; c.font = '700 25px ' + FONT; c.fillText('兜爸心选', W / 2, 1188);
c.fillStyle = '#86909C'; c.font = '400 20px ' + FONT; c.fillText('孕期专题 · 生娃计算器 · 估算仅供参考', W / 2, 1218);
return cv.toDataURL('image/png');
}
var isWx = /MicroMessenger/i.test(navigator.userAgent); var isWx = /MicroMessenger/i.test(navigator.userAgent);
$('#cardBtn').addEventListener('click', function () {
if (!bill) return;
try {
openMask(drawCard(), '给妈妈的卡片', '给妈妈的卡片.png', '长按图片,保存或发给妈妈', false);
} catch (e) { toast('生成失败,截个图保存也可以'); }
});
/* ================= 保存账单图片:把整张小票原样画成长图(宽 750,高按内容算) ================= /* ================= 保存账单图片:把整张小票原样画成长图(宽 750,高按内容算) =================
iOS 单张 canvas 建议 ≤ 约 16000px 高 / 1600 万像素:先按标准行高量一遍,超了就压行高(最低 32),仍超就整体缩小。 */ iOS 单张 canvas 建议 ≤ 约 16000px 高 / 1600 万像素:先按标准行高量一遍,超了就压行高(最低 32),仍超就整体缩小。 */
var BILL_MAX_H = 15800; var BILL_MAX_H = 15800;
function drawBill() { function drawBill() {
var b = bill, R = ROUTES[route], s = b.s, st = sel(), inc = incomeOf(b); var b = bill, R = ROUTES[route], s = b.s, st = sel(), inc = incomeOf(b);
var sexW = A.sex === 1 ? '准爸爸' : '准妈妈';
var nodes = []; var nodes = [];
if (b.n1 != null) nodes.push(['养到 1 岁累计', b.n1]); if (b.n1 != null) nodes.push(['养到 1 岁累计', b.n1]);
if (b.n2 != null) { nodes.push(['养到 2 岁累计', b.n2]); nodes.push(['养到 3 岁累计', b.n3]); } if (b.n2 != null) { nodes.push(['养到 2 岁累计', b.n2]); nodes.push(['养到 3 岁累计', b.n3]); }
@@ -1358,7 +1240,7 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
/* ================= 存取(v5;兼容读取 v4:路线 + 6 题答案,阶段按全部、收入为空) ================= */ /* ================= 存取(v5;兼容读取 v4:路线 + 6 题答案,阶段按全部、收入为空) ================= */
function save() { function save() {
try { localStorage.setItem(KEY, JSON.stringify({ route: route, a: A, done: hasBill, no: billNo, at: billAt, msg: msgI })); } catch (e) {} try { localStorage.setItem(KEY, JSON.stringify({ route: route, a: A, done: hasBill, no: billNo, at: billAt })); } catch (e) {}
} }
function load() { function load() {
try { try {
@@ -1369,11 +1251,10 @@ h1 .mk{background:linear-gradient(transparent 64%,rgba(24,160,88,.24) 0)}
QS.forEach(function (q) { var v = a[q.k]; if (q.o && typeof v === 'number' && v >= 0 && v < q.o.length) A[q.k] = v; }); QS.forEach(function (q) { var v = a[q.k]; if (q.o && typeof v === 'number' && v >= 0 && v < q.o.length) A[q.k] = v; });
if (Array.isArray(a.st)) { var st = a.st.filter(function (i) { return ALL.indexOf(i) >= 0; }); if (st.length) A.st = st.sort(function (x, y) { return x - y; }); } if (Array.isArray(a.st)) { var st = a.st.filter(function (i) { return ALL.indexOf(i) >= 0; }); if (st.length) A.st = st.sort(function (x, y) { return x - y; }); }
if (typeof a.inc === 'number' && a.inc >= 0) A.inc = a.inc; if (typeof a.inc === 'number' && a.inc >= 0) A.inc = a.inc;
msgI = +o.msg || 0;
billNo = o.no || ''; billAt = o.at || ''; billNo = o.no || ''; billAt = o.at || '';
if (!A.st) A.st = ALL.slice(); if (!A.st) A.st = ALL.slice();
var need = QS.filter(function (q) { return q.o && (!q.if || q.if(A.st)); }); var need = QS.filter(function (q) { return q.o && (!q.if || q.if(A.st)); });
var all = need.every(function (q) { return A[q.k] != null; }); var all = need.every(function (q) { return val(q.k) != null; }); // 新加的题没答过就按默认(旧账单照样能看)
if (all && !billNo) newBill(); if (all && !billNo) newBill();
return !!o.done && all; return !!o.done && all;
} catch (e) { return false; } } catch (e) { return false; }

View File

@@ -10,7 +10,11 @@
01 体重:按孕周的增重推荐区间曲线(SVG)+ 按孕前 BMI 分组卡(点卡切换曲线,有孕周时标出「你在这里」); 01 体重:按孕周的增重推荐区间曲线(SVG)+ 按孕前 BMI 分组卡(点卡切换曲线,有孕周时标出「你在这里」);
02 阶段时间轴(按 openid 读孕周点亮,逻辑同 v2);「为什么这样做」本页例外:可见的一句话(≤30 字); 02 阶段时间轴(按 openid 读孕周点亮,逻辑同 v2);「为什么这样做」本页例外:可见的一句话(≤30 字);
03 成分对照两栏。推荐工具走 ../_shared/tools.js(原 #goWeight 跳 /yunqi-tizhong/ 已并入组件,不再单独放按钮)。 03 成分对照两栏。推荐工具走 ../_shared/tools.js(原 #goWeight 跳 /yunqi-tizhong/ 已并入组件,不再单独放按钮)。
只写成分和品类、不点名品牌;百分比只出现在页底「参考来源」。 只写成分和品类、不点名品牌。
2026-11-01 按用户「妊娠纹内容丰富一点,说含量(成分)不说品牌」:03 由两栏速查扩为「看成分怎么选」三组
(孕期可以用 / 产后再用·停止哺乳后 / 孕期别用),每条=成分名 + 常见添加量或浓度(没有可靠数值就不写数)+ 作用 + 证据强弱(●●●);
加「说句实话」卡;新增 04「怎么抹」四格清单;页底参考来源补成分依据。03 起页面正文开始出现浓度数字(原「百分比只在页底」规则作废)。
(/tmp/wen-before-cssclean.html 为本次删旧 .vs 样式前的中间稿。)
自成一页:不引 app.js;回首页走相对路径 ../../,站内跳转带 location.search + location.hash。 自成一页:不引 app.js;回首页走相对路径 ../../,站内跳转带 location.search + location.hash。
v2 备份 /tmp/pl/wen-v2-before-v3.html;更早 /tmp/pl/wen-v2-backup.html。 --> v2 备份 /tmp/pl/wen-v2-before-v3.html;更早 /tmp/pl/wen-v2-backup.html。 -->
<style> <style>
@@ -127,24 +131,44 @@ h2{font-size:18px;font-weight:700;line-height:1.4;color:var(--ink)}
.st .why{margin-top:8px;padding-top:8px;border-top:1px dashed #F3D3DA;font-size:12.5px;line-height:1.6;color:var(--sub)} .st .why{margin-top:8px;padding-top:8px;border-top:1px dashed #F3D3DA;font-size:12.5px;line-height:1.6;color:var(--sub)}
.st .why em{margin-right:6px;font-style:normal;font-weight:600;color:var(--c)} .st .why em{margin-right:6px;font-style:normal;font-weight:600;color:var(--c)}
/* 03 成分对照 */ /* 去医院提示条 */
.vs{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}
.vs .col{padding:14px 12px;border-radius:18px;border:1px solid var(--line);background:#fff}
.vs .col.ok{background:var(--c4);border-color:#FBE3E8}
.vs .ch{display:flex;align-items:center;gap:6px;font-size:13.5px;font-weight:700;color:var(--ink)}
.vs .ch .ic{width:18px;height:18px}
.vs .no .ic{stroke:var(--ink)}
.vs ul{list-style:none;margin-top:8px}
.vs li{padding:6px 0;border-top:1px solid rgba(0,0,0,.05);font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.4}
.vs li:first-child{border-top:0}
.vs li span{display:block;font-size:11.5px;font-weight:400;color:var(--sub)}
.vs .no li{text-decoration:line-through;text-decoration-color:rgba(31,35,41,.35)}
.vs .no li span{text-decoration:none;display:block}
.vs .no p{margin-top:8px;font-size:12px;color:var(--sub);line-height:1.55}
.ask{display:flex;align-items:center;gap:10px;margin-top:8px;padding:12px 14px;border-radius:18px;border:1px dashed #E5E6EB;font-size:13px;line-height:1.5} .ask{display:flex;align-items:center;gap:10px;margin-top:8px;padding:12px 14px;border-radius:18px;border:1px dashed #E5E6EB;font-size:13px;line-height:1.5}
.ask .tag{flex:none;background:var(--sec);color:var(--tx)} .ask .tag{flex:none;background:var(--sec);color:var(--tx)}
.ask b{font-size:13.5px} .ask b{font-size:13.5px}
/* 03 看成分怎么选:三组成分卡(2026-11-01) */
.grp{margin-top:12px;padding:14px 14px 6px;border-radius:20px;border:1px solid var(--line);background:#fff}
.grp.ok{background:var(--c4);border-color:#FBE3E8}
.grp.later{background:var(--sec);border-color:var(--sec)}
.grp-h{display:flex;align-items:center;gap:6px}
.grp-h b{font-size:15px}
.grp-h .ic{width:18px;height:18px}
.grp.no .grp-h .ic,.grp.later .grp-h .ic{stroke:var(--ink)}
.grp-h .tag{margin-left:auto;font-size:11px;line-height:20px;padding:0 8px;white-space:nowrap}
.grp.no .grp-h .tag,.grp.later .grp-h .tag{background:#fff;color:var(--tx)}
.ing{padding:10px 0;border-top:1px solid rgba(0,0,0,.05)}
.grp-h + .ing{margin-top:6px;border-top:0}
.ing-t{display:flex;align-items:flex-start;gap:8px}
.ing-t b{flex:1;min-width:0;font-size:14px;line-height:1.45}
.ing-t b small{display:block;font-size:11.5px;font-weight:400;color:var(--sub)}
.ing .amt{flex:none;max-width:46%;font-size:11.5px;font-weight:700;line-height:1.45;padding:1px 8px;border-radius:8px;background:#fff;color:var(--c);text-align:right}
.grp.ok .ing .amt{background:#fff}
.grp.later .ing .amt,.grp.no .ing .amt{background:#fff;color:var(--ink);border:1px solid var(--line)}
.ing p{margin-top:3px;font-size:13px;line-height:1.6}
.ing .ev{display:flex;align-items:baseline;gap:6px;margin-top:2px;font-size:12px;line-height:1.55;color:var(--sub)}
.ing .ev em{flex:none;font-style:normal;font-weight:700;font-size:11px;letter-spacing:.04em;color:var(--c)}
.ing .ev em i{font-style:normal;color:#E9C3CB}
.grp.no .ing-t b{text-decoration:line-through;text-decoration-color:rgba(31,35,41,.35)}
.grp.no .ing-t b small{display:inline-block;width:100%}
.truth{margin-top:12px;padding:14px 16px;border-radius:18px;background:var(--cs);font-size:13.5px;line-height:1.7}
.truth .tag{background:#fff;margin-bottom:6px}
.truth b{color:var(--c)}
/* 04 怎么抹 */
.how{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px}
.how .pt b{margin-top:8px}
.how .pt .no{font-size:28px}
.how .pt span{font-size:12.5px;color:var(--tx)}
/* 来源 + 免责 */ /* 来源 + 免责 */
.src{margin-top:36px;border-radius:18px;background:var(--sec)} .src{margin-top:36px;border-radius:18px;background:var(--sec)}
.src summary{list-style:none;display:flex;align-items:center;gap:8px;padding:13px 16px;font-size:14px;font-weight:600;color:var(--ink)} .src summary{list-style:none;display:flex;align-items:center;gap:8px;padding:13px 16px;font-size:14px;font-weight:600;color:var(--ink)}
@@ -170,6 +194,7 @@ h2{font-size:18px;font-weight:700;line-height:1.4;color:var(--ink)}
<symbol id="i-ok" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M8 12.2l2.7 2.7L16 9.6"/></symbol> <symbol id="i-ok" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M8 12.2l2.7 2.7L16 9.6"/></symbol>
<symbol id="i-no" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M5.8 5.8l12.4 12.4"/></symbol> <symbol id="i-no" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M5.8 5.8l12.4 12.4"/></symbol>
<symbol id="i-down" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></symbol> <symbol id="i-down" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></symbol>
<symbol id="i-time" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.2 2"/></symbol>
</svg> </svg>
<div id="scroll"> <div id="scroll">
@@ -260,26 +285,100 @@ h2{font-size:18px;font-weight:700;line-height:1.4;color:var(--ink)}
</div> </div>
</section> </section>
<!-- 03 成分对照 --> <!-- 03 看成分怎么选(2026-11-01 由两栏速查扩成三组:孕期可用 / 产后再用 / 孕期别用;只写成分不写品牌) -->
<section class="sec" id="s3"> <section class="sec" id="s3">
<div class="sec-h"><span class="n num">03</span><h2>成分速查</h2><small>INGREDIENTS</small></div> <div class="sec-h"><span class="n num">03</span><h2>看成分怎么选</h2><small>INGREDIENTS</small></div>
<p class="key">买之前翻成分表,左边这栏孕期别碰。</p> <p class="key">不认牌子,翻成分表:分三组对照着挑。</p>
<div class="vs fade"> <p class="note">含量是市面常见添加范围,不是越高越好;证据 ●●● 越满越可靠。</p>
<div class="col no">
<div class="ch"><svg class="ic"><use href="#i-no" xlink:href="#i-no"/></svg>孕期别碰</div> <div class="grp ok fade">
<ul><li>维 A 酸</li><li>视黄醇</li><li>视黄醛</li></ul> <div class="grp-h"><svg class="ic"><use href="#i-ok" xlink:href="#i-ok"/></svg><b>孕期可以用</b><span class="tag">打底预防</span></div>
<p>可能影响胎儿<br>哺乳期也别用</p> <div class="ing">
<div class="ing-t"><b>积雪草提取物<small>积雪草苷、羟基积雪草苷</small></b><span class="amt">多不标含量</span></div>
<p>抗炎、促胶原,帮皮肤扛拉伸。</p>
<div class="ev"><em>证据 ●●<i>●</i></em>防纹研究里相对靠谱的一个,但多是复方小样本。</div>
</div> </div>
<div class="col ok"> <div class="ing">
<div class="ch"><svg class="ic"><use href="#i-ok" xlink:href="#i-ok"/></svg>放心用</div> <div class="ing-t"><b>透明质酸<small>玻尿酸、透明质酸钠</small></b><span class="amt num">常见 0.1%~1%</span></div>
<ul> <p>强力补水,让皮肤更软、更有弹性。</p>
<li>透明质酸<span>补水,日常打底</span></li> <div class="ev"><em>证据 ●●<i>●</i></em>复方凝胶小试验有效,单用效果不确定。</div>
<li>神经酰胺、角鲨烷<span>修护屏障</span></li> </div>
<li>医用硅酮凝胶<span>成膜保湿,帮红纹变淡</span></li> <div class="ing">
</ul> <div class="ing-t"><b>甜杏仁油 + 按摩</b><span class="amt">纯油直接抹</span></div>
<p>润滑皮肤,方便每天按摩。</p>
<div class="ev"><em>证据 ●<i>●●</i></em>小研究里按摩组长纹更少,功劳更像按摩。</div>
</div>
<div class="ing">
<div class="ing-t"><b>神经酰胺、甘油、角鲨烷<small>乳木果油同类</small></b><span class="amt">护肤常规量</span></div>
<p>修护屏障、止痒,打底保湿用。</p>
<div class="ev"><em>证据 ●<i>●●</i></em>没有专门防纹研究,胜在温和、止痒。</div>
</div>
<div class="ing">
<div class="ing-t"><b>可可脂、橄榄油</b><span class="amt">纯油或高比例</span></div>
<p>便宜好用的保湿油。</p>
<div class="ev"><em>证据 <i>●●●</i></em>随机对照试验:防纹和不抹差不多。</div>
</div>
<div class="ing">
<div class="ing-t"><b>医用硅酮凝胶<small>以聚硅氧烷为主</small></b><span class="amt">按说明书</span></div>
<p>成膜锁水,冒红纹时薄涂。</p>
<div class="ev"><em>证据 ●<i>●●</i></em>小样本显示红纹变淡,证据多来自疤痕。</div>
</div> </div>
</div> </div>
<div class="ask fade"><span class="tag">先问医生</span><div><b>积雪草类修护霜</b><br>抗炎促修复,用前问产检医生</div></div>
<div class="grp later fade">
<div class="grp-h"><svg class="ic"><use href="#i-time" xlink:href="#i-time"/></svg><b>产后再用</b><span class="tag">停止哺乳后 · 听医生</span></div>
<div class="ing">
<div class="ing-t"><b>维 A 酸<small>处方药,皮肤科开</small></b><span class="amt num">0.05%~0.1%</span></div>
<p>促新胶原,主要对早期红纹管用。</p>
<div class="ev"><em>证据 ●●<i>●</i></em>小样本随机对照有效;白纹效果差,会发红脱皮。</div>
</div>
<div class="ing">
<div class="ing-t"><b>视黄醇类身体乳<small>视黄醇、视黄醛</small></b><span class="amt">添加量低</span></div>
<p>作用同维 A 酸,但弱得多。</p>
<div class="ev"><em>证据 ●<i>●●</i></em>缺少专门针对妊娠纹的研究。</div>
</div>
<div class="ing">
<div class="ing-t"><b>果酸<small>羟基乙酸 / 甘醇酸</small></b><span class="amt num">居家 5%~10%</span></div>
<p>加速角质更新,让纹路颜色更匀。</p>
<div class="ev"><em>证据 ●<i>●●</i></em>20% 以上属医院换肤;小研究多和维 A 酸合用。</div>
</div>
</div>
<div class="ask fade"><span class="tag">去医院</span><div><b>点阵激光、微针、强脉冲光</b><br>对白纹更管用,选正规医院皮肤科,别去美容店</div></div>
<div class="grp no fade">
<div class="grp-h"><svg class="ic"><use href="#i-no" xlink:href="#i-no"/></svg><b>孕期别用</b><span class="tag">翻成分表认准</span></div>
<div class="ing">
<div class="ing-t"><b>维 A 酸、阿达帕林、他扎罗汀<small>外用维 A 酸类处方药</small></b><span class="amt">任何浓度</span></div>
<p>口服有明确致畸性,外用也不冒险。孕期、哺乳期都别用。</p>
</div>
<div class="ing">
<div class="ing-t"><b>视黄醇、视黄醛、视黄醇棕榈酸酯<small>护肤品里的「A 醇」</small></b><span class="amt">任何浓度</span></div>
<p>和维 A 酸同一家族,孕期别用;哺乳期先问医生。</p>
</div>
<div class="ing">
<div class="ing-t"><b>对苯二酚<small>氢醌,常见于祛斑美白</small></b><span class="amt">任何浓度</span></div>
<p>皮肤吸收多,孕期别用。</p>
</div>
<div class="ing">
<div class="ing-t"><b>高浓度水杨酸<small>刷酸换肤、大面积涂</small></b><span class="amt">换肤级</span></div>
<p>孕期别做;洗面奶里小面积低浓度的,先问医生。</p>
</div>
</div>
<div class="truth fade"><span class="tag">说句实话</span><br>没有哪瓶霜能<b>保证不长纹</b>。遗传和体重长得快不快,影响更大。<br>早抹、坚持、配合按摩、控体重,最实在。</div>
</section>
<!-- 04 怎么抹(2026-11-01 新增) -->
<section class="sec" id="s4">
<div class="sec-h"><span class="n num">04</span><h2>怎么抹</h2><small>HOW TO</small></div>
<p class="key">早开始、抹全、天天抹,比挑贵的管用。</p>
<div class="how">
<div class="pt fade"><span class="no num">1</span><b>什么时候开始</b><span>孕早期就开始,一直抹到产后。</span></div>
<div class="pt fade"><span class="no num">2</span><b>抹哪些部位</b><span>肚子、腰侧、大腿、臀部、胸部。</span></div>
<div class="pt fade"><span class="no num">3</span><b>一天几次</b><span>早晚各一次,洗澡后趁皮肤微湿。</span></div>
<div class="pt fade"><span class="no num">4</span><b>手法</b><span>打圈抹到吸收,每处 1~2 分钟;肚子轻抹不按压。</span></div>
</div>
<p class="note">新产品先在手肘内侧试抹 1 天,不红不痒再大面积用。</p>
</section> </section>
<div id="tools"></div> <div id="tools"></div>
@@ -293,6 +392,14 @@ h2{font-size:18px;font-weight:700;line-height:1.4;color:var(--ink)}
<li><b>透明质酸复方凝胶:</b>约 50 人连用 12 周,红纹深度和颜色明显减轻,但不会完全消失。</li> <li><b>透明质酸复方凝胶:</b>约 50 人连用 12 周,红纹深度和颜色明显减轻,但不会完全消失。</li>
<li><b>点阵激光:</b>联合强脉冲光的 60 人研究中纹路面积平均缩小约 37%,约 25% 有不良反应。</li> <li><b>点阵激光:</b>联合强脉冲光的 60 人研究中纹路面积平均缩小约 37%,约 25% 有不良反应。</li>
<li><b>可可脂、橄榄油:</b>210 人随机对照研究,可可脂 45% 长纹、安慰剂 49%;70 人研究,橄榄油 45.7% 对 62.9%,均无统计学差异,润肤可以、防纹别指望。</li> <li><b>可可脂、橄榄油:</b>210 人随机对照研究,可可脂 45% 长纹、安慰剂 49%;70 人研究,橄榄油 45.7% 对 62.9%,均无统计学差异,润肤可以、防纹别指望。</li>
<li><b>外用防纹总体证据:</b>Cochrane 关于孕期外用制剂预防妊娠纹的系统评价认为,目前没有高质量证据证明任何外用产品能预防妊娠纹;多篇皮肤科综述认为积雪草提取物、透明质酸类复方是现有研究中相对有希望的,但试验规模小、多为复方。</li>
<li><b>积雪草:</b>早年欧洲一项孕妇对照试验,用含积雪草提取物的复方霜,长纹比例低于安慰剂,主要对既往有妊娠纹的人更明显;产品含量多不公开,本页不给推荐浓度。</li>
<li><b>甜杏仁油:</b>土耳其一项孕妇研究,甜杏仁油加按摩组长纹比例明显低于对照,只抹不按摩与对照差别不大,提示按摩本身可能起作用(非盲法、小样本)。</li>
<li><b>透明质酸浓度:</b>「0.1%~1%」为护肤品常见添加范围的经验值,不是防纹的推荐剂量。</li>
<li><b>维 A 酸类、A 醇:</b>国内维 A 酸乳膏(常见 0.025%、0.05%、0.1% 规格)说明书写明孕妇及哺乳期妇女禁用;阿达帕林、他扎罗汀同属维 A 酸类,孕期不用。视黄醇等 A 醇护肤品按主流保守口径孕期避免。</li>
<li><b>果酸:</b>小样本研究中 20% 羟基乙酸联合维 A 酸或维 C,对妊娠纹外观有一定改善;居家产品常见 5%~10%,更高浓度属医院化学换肤。</li>
<li><b>对苯二酚、水杨酸:</b>对苯二酚外用吸收比例较高,孕期护肤建议中普遍列为避免;水杨酸大面积或高浓度换肤孕期避免,低浓度小面积洗去型多认为风险低,仍建议先问医生。</li>
<li><b>医美:</b>点阵激光、微针、强脉冲光 / 脉冲染料激光对妊娠纹有改善报道,红纹偏向血管类激光、白纹偏向点阵和微针,需在正规医院皮肤科评估,孕期不做。</li>
</ul> </ul>
</details> </details>
<p class="foot">本页为科普参考,不能代替医生诊断。孕期用药、护肤有疑问请咨询医生。</p> <p class="foot">本页为科普参考,不能代替医生诊断。孕期用药、护肤有疑问请咨询医生。</p>