From 06512a2134d127105aa67f39496c369f628ad637 Mon Sep 17 00:00:00 2001 From: karlcarlo Date: Sun, 11 Oct 2026 13:44:25 +0000 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=B7=A5=E5=85=B7=E5=8D=A1?= =?UTF-8?q?=E6=8C=89=E5=AD=95=E5=91=A8=E8=87=AA=E5=8A=A8=E6=8D=A2=EF=BC=9A?= =?UTF-8?q?=E6=95=B0=E8=83=8E=E5=8A=A8/=E8=83=8E=E5=84=BF=E4=BC=B0?= =?UTF-8?q?=E9=87=8D/=E6=95=B0=E5=AE=AB=E7=BC=A9=E6=B2=A1=E5=88=B0?= =?UTF-8?q?=E5=AD=95=E5=91=A8=E6=97=B6=E6=8D=A2=E6=88=90=E8=83=BD=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E5=90=83=E3=80=81=E8=A1=A5=E6=B0=B4=E8=A1=A5=E5=89=82?= =?UTF-8?q?=E3=80=81=E8=A1=80=E5=8E=8B=E7=AD=89=E6=9B=BF=E8=A1=A5=EF=BC=8C?= =?UTF-8?q?=E5=88=B0=E5=AD=95=E5=91=A8=E8=87=AA=E5=8A=A8=E6=8D=A2=E5=9B=9E?= =?UTF-8?q?=20v26101014?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: AI 助手 --- index.html | 2 +- js/app.js | 73 +++++++++++++++++++++++++++++++++++++++++++++------- mama-box.css | 2 ++ 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index 88fdf86..f4281e3 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ 兜爸心选 · 孕育陪伴 - + diff --git a/js/app.js b/js/app.js index b5fc8f9..12c69ed 100644 --- a/js/app.js +++ b/js/app.js @@ -3,7 +3,7 @@ (function () { 'use strict'; /* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */ - var VER = '26101013'; + var VER = '26101014'; const $ = (s, c) => (c || document).querySelector(s); const $$ = (s, c) => Array.from((c || document).querySelectorAll(s)); @@ -384,13 +384,62 @@ b.classList.toggle('is-locked', on); if (on) b.dataset.lock = g.wk + '周+'; else delete b.dataset.lock; }); - [['kick', 'taidong'], ['curve', 'gongsuopinlv'], ['fweight', 'taierguzhong']].forEach(([slot, id]) => { - const el = $('.mini-card[data-mini="' + slot + '"]'), g = STAGE_GATE.find(x => x.id === id); + swapHomeCards(); + } + /* 首页工具卡按孕周自动换(2026-10-11 用户:「孕育工具卡片替换成其他几个能让用户用的,否则首页体验特别差, + 系统根据用户填写的孕周自动调用」)。 + · 数胎动 / 胎儿估重 / 数宫缩 三个坑位,孕周没到门槛就换成替补,到了自动换回原工具。 + · 替补按 SWAP_POOL 顺序依次填:能不能吃 → 补水补剂 → 血压 → 血糖 → 待产清单(孕早期最用得上的排前面), + 同一个替补不会出现两次;体重、孕检日历本来就在首页,不进池子。 + · 只换卡里的内容,坑位的尺寸和底色不动(五张卡的高度账、配色都是排好的,见 CSS .bento)。 + · 原内容存在 data 里,换回时原样放回,再用上一次卡片接口的数据补一遍(数胎动次数等)。 */ + const SWAP_SLOTS = [['kick', 'taidong'], ['fweight', 'taierguzhong'], ['curve', 'gongsuopinlv']]; + const SWAP_ART = { /* 白色线稿,和其余卡片插画同一套笔触 */ + yunqinengbuchi: '', + bushui: '', + yun: '', + yunqixuetang: '', + daichanqingdan: '', + }; + const SWAP_POOL = [ + { id: 'yunqinengbuchi', name: '能不能吃', sub: '馋了先查一下', btn: '去查查' }, + { id: 'bushui', name: '补水补剂', sub: '叶酸吃了吗', btn: '去记录' }, + { id: 'yun', name: '孕期血压', sub: '量一量更安心', btn: '去记录' }, + { id: 'yunqixuetang', name: '孕期血糖', sub: '餐后记一笔', btn: '去记录' }, + { id: 'daichanqingdan', name: '待产清单', sub: '提前备起来', btn: '去看看' }, + ]; + let lastCards = null; /* 上一次 tool-cards 的结果:换回原卡后重放 */ + function swapArt(id) { + return ''; + } + function swapHomeCards() { + const used = new Set(); + let restored = false; + SWAP_SLOTS.forEach(([slot, id]) => { + const el = $('.mini-card[data-mini="' + slot + '"]'); if (!el) return; - const on = stageLocked(g); - el.classList.toggle('is-locked', on); - if (on) el.dataset.lock = g.wk + '周+'; else delete el.dataset.lock; + const g = STAGE_GATE.find(x => x.id === id); + if (!stageLocked(g)) { + if (el.dataset.swap) { el.innerHTML = el._orig; delete el.dataset.swap; el.classList.remove('is-swap'); el.removeAttribute('aria-label'); restored = true; } + return; + } + const sub = SWAP_POOL.find(x => !used.has(x.id) && APP_BY_ID[x.id] && APP_BY_ID[x.id].url) || + SWAP_POOL.find(x => !used.has(x.id)); + if (!sub) return; + used.add(sub.id); + if (el.dataset.swap === sub.id) return; + if (!el.dataset.swap) el._orig = el.innerHTML; + el.dataset.swap = sub.id; + el.classList.add('is-swap'); + el.classList.remove('is-warn'); + el.setAttribute('aria-label', sub.name + ',' + sub.sub); + el.innerHTML = slot === 'kick' + ? '
' + sub.name + '
' + sub.sub + '
' + + '
孕 ' + g.wk + ' 周后这里换成' + g.name + '
' + + '' + sub.btn + '' + swapArt(sub.id) + : '
' + sub.name + '
' + sub.sub + '
' + swapArt(sub.id); }); + if (restored && lastCards) applyRemoteCards(lastCards); } /* 跳转到其它 H5 应用。identifier 可选(来自 App 表),用于 last_app 上报的服务端在架校验; @@ -736,9 +785,10 @@ const APP_BY_ID = {}; $$('[data-mini]').forEach(b => b.addEventListener('click', () => { const map = { kick: '数胎动', weight: '孕期体重', cal: '孕检日历', curve: '数宫缩', fweight: '胎儿估重' }; - const app = APP_BY_ID[MINI_APP_MAP[b.dataset.mini]]; + const sw = b.dataset.swap; /* 孕周没到、坑位换成了替补(见 swapHomeCards) */ + const app = APP_BY_ID[sw || MINI_APP_MAP[b.dataset.mini]]; if (app && app.url) { jumpApp(app.url, app.identifier); return; } - toast('「' + map[b.dataset.mini] + '」即将上线'); + toast('「' + (sw ? (SWAP_POOL.find(x => x.id === sw) || {}).name : map[b.dataset.mini]) + '」即将上线'); })); /* 记一下弹层只保留「全部孕期工具」,不再提供输入框 */ @@ -3420,8 +3470,13 @@ const cardsOwned = { kick: false, cal: false }; // 卡片接口已接管哪些格(本地源据此让位) function applyRemoteCards(r) { if (!r || r.ok === false || !(r.cards || []).length) return; // 降级:保留现有值 + lastCards = r; const bySlot = {}; - r.cards.forEach(c => { if (c && c.slot) bySlot[c.slot] = c; }); + /* 换成替补的坑位(孕周没到)不吃原工具的数据,免得把「馋了先查一下」改成「今天 0 次」 */ + r.cards.forEach(c => { + const el = c && c.slot ? $('.mini-card[data-mini="' + c.slot + '"]') : null; + if (c && c.slot && !(el && el.dataset.swap)) bySlot[c.slot] = c; + }); const cardOf = slot => $('.mini-card[data-mini="' + slot + '"]'); const mark = (slot, c) => { const el = cardOf(slot); if (el) el.classList.toggle('is-warn', !!c.warn); }; const setText = (sel, v) => { const el = $(sel); if (el) el.textContent = v || ''; }; diff --git a/mama-box.css b/mama-box.css index 538fe67..0db3527 100644 --- a/mama-box.css +++ b/mama-box.css @@ -4776,4 +4776,6 @@ a.skip:focus{left:16px;top:16px} .sg-ends{display:flex;justify-content:space-between;margin-top:6px;font-size:11.5px;font-weight:700;color:var(--muted)} .sg-left{margin-top:10px;font-size:13px;font-weight:700;color:var(--ink-2)} .sg-modal .modal-foot{margin-top:18px} +/* 首页工具卡自动换成替补(swapHomeCards):尺寸、底色沿用坑位原样,只换内容;插画是白色线稿 svg */ +.mini-card .sw-art{height:auto;aspect-ratio:1;opacity:.95}