From 849cf7a52160e97e1f5df707762a99cb31fce5d3 Mon Sep 17 00:00:00 2001 From: Karlcarlo Date: Tue, 22 Sep 2026 13:37:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AD=95=E6=9C=9F):=20=E4=BA=A7=E5=90=8E?= =?UTF-8?q?=E6=80=81=E4=B8=8D=E5=86=8D=E6=98=BE=E7=A4=BA=E3=80=8C=E5=AD=95?= =?UTF-8?q?=2042=20=E5=91=A8=E3=80=8D=EF=BC=8C=E6=94=B9=E3=80=8C=E5=AE=9D?= =?UTF-8?q?=E5=AE=9D=E5=B7=B2=E5=87=BA=E7=94=9F=20N=20=E5=A4=A9=E3=80=8D(v?= =?UTF-8?q?26092205)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上游 journey_stage=postpartum / 有 baby_birth_date 时,后端 /pregnancy 返回 postpartum=true 且 week=null。H5 侧补齐: - applyRemoteProfile:**先判 postpartum 再判 empty/week==null** (产后返回体的 week 也是 null,落错分支会给已生产用户弹「完善孕期信息」) - syncPregnancy:新增产后分支(文案集中在这里) · hero:孕周位「已出生」+ 清空紧邻的「孕周」标签 + 出生天数 / 「来到这个世界」 · 我的孕期卡:宝宝已出生 N 天 · 记录宝宝的成长时光(进度 100%) · 档案页:宝宝已出生 N 天 · 孕期陪伴已结束;[data-ga]/[data-wk] 归 '--' - 拦住 syncPregnancy 之后按 state.week 重算的链(syncStaticDates): week=null 会算出「看着正常但全错」的日期 - fillProfileForm:产后不再按已过的预产期回填「孕 42 周」,孕周两格留空并锁住 - renderPoster:week 为 null 时不再拼出「第 null 周档案」,退化成完整档案 ⚠️ 文案(首页/孕期卡/档案页三处)如需调整只改 syncPregnancy 的产后分支 版本 v26092204 → v26092205 --- AGENTS.md | 9 ++++- index.html | 2 +- js/app.js | 106 +++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 103 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 095a96c..3a3bc60 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -62,9 +62,14 @@ nginx:`root /opt/app` + `Cache-Control: no-cache` + `etag on` —— 缓存靠 `navigation.type === 'back_forward'`、从应用页 `location.href` 回来的 `document.referrer`); **绝不能改成「每次加载都清」** —— 宿主恢复会把本页当返回落点加载,误清会毁掉刚用上的记录。 9. **保存资料失败必须提示,不能静默**(2026-09-22「档案以上游为准」): - `PUT /profile` 改**预产期/昵称**时,后端会**先推上游用户中心、成功才落库**,推失败返回 `code=400` 且 - **不落库**。H5 必须弹提示(`_putProfile` 已按此判断 `res.code`)——静默的话下次加载会被上游值覆盖回去, + `PUT /profile` 改**预产期/昵称/宝宝小名**时,后端会**先推上游用户中心、成功才落库**,推失败返回 `code=400` + 且**不落库**。H5 必须弹提示(`_putProfile` 已按此判断 `res.code`)——静默的话下次加载会被上游值覆盖回去, 用户以为"改了没生效"。改这个接口的调用方时别再把失败吞掉。 +10. **产后态必须先判 `postpartum`**(2026-09-22):`/pregnancy` 的产后返回体里 `week` 也是 `null`, + `applyRemoteProfile` 与 `syncPregnancy` 都必须**先判 `state.postpartum` 再判 `empty || week == null`**, + 否则会给**已经生产**的用户弹「完善孕期信息」引导; + 并且 `syncPregnancy()` 之后那条按 `state.week` 重算的链(`syncStaticDates` 等)要一并拦住 —— + `week=null` 会让它算出「看着正常但全错」的日期,页面上看不出来。文案集中在 `syncPregnancy` 的产后分支。 ## 5. 踩坑 diff --git a/index.html b/index.html index 85fa0df..3f179fc 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ 兜爸心选 · 孕育陪伴 - + diff --git a/js/app.js b/js/app.js index 8db916f..f04f7bb 100644 --- a/js/app.js +++ b/js/app.js @@ -3,7 +3,7 @@ (function () { 'use strict'; /* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */ - var VER = '26092204'; + var VER = '26092205'; const $ = (s, c) => (c || document).querySelector(s); const $$ = (s, c) => Array.from((c || document).querySelectorAll(s)); @@ -59,6 +59,13 @@ week: Math.floor(DEFAULT_GA / 7), day: DEFAULT_GA % 7, due: DEFAULT_DUE, babySex: 'unknown', + /* 产后态(2026-09-22,来自上游 journey_stage=postpartum / baby_birth_date): + 已生产的用户不能再按预产期算孕周(会得到「孕 42 周」这种荒谬值), + 改显示「宝宝已出生 N 天」。读写方:applyRemoteProfile 的 /pregnancy 分支 + syncPregnancy。 */ + postpartum: false, + babyAgeTxt: '', // 「宝宝已出生 25 天」/「宝宝已出生 3 个月」(服务端算好) + babyAgeDays: null, // 出生天数(没有出生日期时为 null) + babyBirthDate: '', /* ⚠️ 这里原来还有一条 babyAvatar(来信列表那颗宝宝头像的 data URI)。 它的读写方全在内置来信屏里,随该屏一起删除 —— 别再只加字段不加读写方, 那正是下面 userBio 那条注释警告过的「最难发现的死代码」。 @@ -873,7 +880,14 @@ $('#pfName').value = state.userName || ''; pgName.value = state.babyName || ''; $$('#pgSex .pick').forEach(b => b.classList.toggle('is-active', (b.dataset.sex || 'unknown') === (state.babySex || 'unknown'))); - if (state.due) { + if (state.postpartum) { + /* 产后态:预产期已过,**不要**再按它算出「孕 42 周」回填进表单(那是荒谬值)。 + 预产期本身照常显示/可改;孕周两格留空并锁住。 */ + pgDue.value = state.due ? toISO(state.due) : ''; + pgWeek.value = ''; + pgDay.value = ''; + lockWeekFields(true); + } else if (state.due) { pgDue.value = toISO(state.due); const ga = gaFromDue(state.due); pgWeek.value = Math.floor(ga / 7); @@ -979,6 +993,62 @@ /* 把 state 里的孕期信息刷到「我的」孕期卡 + 首页头部 + 档案页顶部 */ function syncPregnancy() { + /* ---- 产后态:宝宝已出生 → 一律不显示孕周数字(2026-09-22) ---- + ⚠️ 必须放在 pregEmpty 之前:产后返回体的 week 也是 null, + 落到空态分支会给**已经生产**的用户弹「完善孕期信息」引导。 + 文案集中在这里,要改只改这一段: + · 首页 hero:已出生 / N 天 / 「已经生活了 N 天」 + · 我的孕期卡:宝宝已出生 N 天 · 记录宝宝的成长时光 + · 档案页:宝宝已出生 N 天 · 孕期陪伴已结束,继续记录宝宝的成长 + ⚠️ hero 的「孕周」两个字是 #heroWeek **紧邻的兄弟 span**,JS 只写 #heroWeek, + 所以这里要顺手把它清空,否则会读成「已出生 孕周」。 */ + if (state.postpartum) { + const nm = state.babyName || '宝宝'; + const ageTxt = state.babyAgeTxt || '宝宝已出生'; + const ageDays = state.babyAgeDays; + /* ① 我的 · 孕期卡 */ + const pcT = $('#pcTitle'), pcS = $('#pcSub'), pcB = $('#pcBar'), pcR = $('#pcRing'); + if (pcT) pcT.textContent = ageTxt; + if (pcS) pcS.textContent = '记录宝宝的成长时光'; + if (pcB) pcB.style.setProperty('--p', '100%'); + if (pcR) { + const C = 2 * Math.PI * parseFloat(pcR.getAttribute('r')); + pcR.setAttribute('stroke-dasharray', C.toFixed(2) + ' ' + C.toFixed(2)); + } + $$('.pc-stage span').forEach((s) => { + s.textContent = s.textContent.split(' · ')[0]; + s.classList.remove('cur'); + }); + /* ② 首页 hero */ + const hw = $('#heroWeek'); + if (hw) { + hw.textContent = '已出生'; + const lb = hw.nextElementSibling; + if (lb) lb.textContent = ''; + } + const hp = $('#heroPlus'); + if (hp) hp.textContent = (ageDays == null ? '' : ageDays + '天'); + const hd = $('#heroDays'); + if (hd) hd.textContent = (ageDays == null ? '--' : ageDays); + const hwho = $('#heroWho'); + if (hwho) hwho.textContent = nm; + const hwhere = document.querySelector('.hd-where'); + if (hwhere) hwhere.textContent = '来到这个世界'; + setRing($('#heroRing'), 1); + /* ③ 档案页 */ + const arN = $('#arTitleName'); if (arN) arN.textContent = nm; + const arL1 = $('#arLine1'); if (arL1) arL1.textContent = ageTxt; + const arD = $('#arDays'); if (arD) arD.textContent = (ageDays == null ? '--' : ageDays); + const arArt = $('#arSizeArt'); if (arArt) arArt.textContent = '👶'; + const arL2 = $('#arLine2'); if (arL2) arL2.textContent = '孕期陪伴已结束,继续记录宝宝的成长'; + const arP = $('#arPct'); if (arP) arP.textContent = '100%'; + setArBar(100); + const gwt = $('#genWeekTag'); if (gwt) gwt.textContent = '产后'; + $$('[data-ga]').forEach(n => { n.textContent = '--'; }); + $$('[data-wk]').forEach(n => { n.textContent = '--'; }); + syncBabyWords(); + return; + } /* ---- 新用户空态:未完善资料(无预产期)→ 全部显示引导占位,不读演示数据 ---- me 页已有两条引导(授权卡 + 孕期信息必填卡);这里把首页/档案页的 孕周数字换成引导文案,避免新用户看到"孕 27 周"这类假数据。 */ @@ -2319,11 +2389,13 @@ function renderPoster(kind) { posterKind = kind === 'all' ? 'all' : 'week'; + /* ⚠️ 产后态 state.week 是 null:别再拼出「第 null 周档案」,退化成完整档案。 */ + const weekOk = (posterKind === 'week' && state.week != null); const D = posterData(posterKind); const host = $('#pstPages'); beginSheets(host, - posterKind === 'week' ? '第' + state.week + '周档案' : '完整档案', - state.babyName + (posterKind === 'week' ? '的本周档案' : '的成长档案')); + weekOk ? '第' + state.week + '周档案' : '完整档案', + state.babyName + (weekOk ? '的本周档案' : '的成长档案')); let sizeChip; if (posterKind === 'week') { @@ -2716,16 +2788,26 @@ if (!p.userName) { var _ai2 = $('#meAvatarImg'); if (_ai2) _ai2.removeAttribute('src'); } } if (pg && pg.code === 200 && pg.result) { - /* 新用户空态(未完善资料):后端不再给默认孕周 → 显示引导占位, - 不读任何演示数据(详见 syncPregnancy 的 pregEmpty 分支)。 - ⚠️ 同时清掉 state 的内置演示默认值(DEFAULT_DUE=今天+3个月/孕27周), - 否则「我的资料」弹窗回填时又会把它们带回来。 */ - if (pg.result.empty || pg.result.week == null) { + if (pg.result.postpartum) { + /* 产后态(2026-09-22):上游 journey_stage=postpartum / 有 baby_birth_date。 + ⚠️ 必须**先**判它再判 empty/week==null —— 产后返回体的 week 也是 null, + 落到下面那个分支会被当成「未完善资料」,给已生产的用户弹建档引导。 */ + state.postpartum = true; + state.pregEmpty = false; + state.week = null; + state.day = null; + state.babyAgeTxt = pg.result.babyAgeTxt || '宝宝已出生'; + state.babyAgeDays = (pg.result.babyAgeDays == null ? null : pg.result.babyAgeDays); + state.babyBirthDate = pg.result.babyBirthDate || ''; + if (pg.result.due) { const d = parseDay(pg.result.due); if (d) state.due = d; } + } else if (pg.result.empty || pg.result.week == null) { + state.postpartum = false; state.pregEmpty = true; state.due = null; state.week = null; state.day = null; } else { + state.postpartum = false; state.pregEmpty = false; state.week = pg.result.week; state.day = pg.result.day; @@ -2737,8 +2819,10 @@ /* 新用户空态:syncPregnancy 已写完引导占位(含称呼/静态位归零)。 ⚠️ 下面 syncBabyWords/syncStaticDates 全按 state.week 重算, 而 pregEmpty 时 state.week 还是内置默认 27 —— 不拦住的话, - 刚写好的占位会被改回「孕 27 周 / 9月15日」演示值。 */ - if (state.pregEmpty) { return; } + 刚写好的占位会被改回「孕 27 周 / 9月15日」演示值。 + ⚠️ 产后态同样要拦:syncPregnancy 的产后分支已写好「已出生」与 '--' 占位, + 而 state.week 是 null → syncStaticDates 会按 ga=0 算出**看着正常但全错**的日期。 */ + if (state.pregEmpty || state.postpartum) { return; } syncBabyWords(); syncStaticDates(); }).catch(function () { /* 静默回退内置值 */ });