孕期首页测试修复 (v26102201):档案入口 v10、隐私页去假开关、资料保存等接口成功再提示、头像上传失败提示、产后不显示孕 0 周、悄悄话页不被刷新关掉、出生登记小名性别保存失败可重试
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>兜爸心选 · 孕育陪伴</title>
|
||||
<!-- V:26102105 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<!-- V:26102201 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<link rel="stylesheet" href="mama-box.css">
|
||||
<link rel="stylesheet" href="night.css">
|
||||
<!-- 夜晚模式:首屏绘制前就按上次的选择加 class,避免先白后黑闪一下(开关在首页右上角 #nightBtn,逻辑见 app.js) -->
|
||||
@@ -2050,7 +2050,7 @@
|
||||
<!-- 2026-10-05 首页头图:宝宝时不时动一动小手小脚(独立文件,删掉这一行即下线) -->
|
||||
<script src="js/baby-limbs.js?v=26101201"></script>
|
||||
<script src="js/coach.js?v=26101211"></script>
|
||||
<script src="js/birth-flow.js?v=26102108"></script>
|
||||
<script src="js/birth-flow.js?v=26102201"></script>
|
||||
|
||||
<!-- 禁止下拉回弹(2026-10-11 统一规则,与孕期体重同一段):竖向拖动时从手指下往上找还能朝该方向滚的容器,找不到才拦;横滑、双指、可滚列表不受影响 -->
|
||||
<script>
|
||||
|
||||
118
js/app.js
118
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26102105';
|
||||
var VER = '26102201';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
/* 2026-10-01 用户要求「档案」Tab 改跳孕期档案 H5(会话 19875b1b 提供)。
|
||||
⚠️ 对方说明:目前是设计演示版(写死演示数据),还不读 URL 参数;接真实数据时按 ?openid=&unionid= 读,
|
||||
所以这里照旧拼上。无 return_url,返回靠宿主自带返回。原来跳的是 /chanjian-rili/(孕检日历)。 */
|
||||
const ARCHIVE_H5 = '/chengzhang-dangan/v8/'; // 2026-10-04 v7 → v8(会话 19875b1b 要求;正式入口不带 ?demo=1,带了只出示例数据);2026-10-09 改同源相对路径(mp nginx 反代)
|
||||
const ARCHIVE_H5 = '/chengzhang-dangan/v10/'; // 2026-10-04 v7 → v8(会话 19875b1b 要求;正式入口不带 ?demo=1,带了只出示例数据);2026-10-09 改同源相对路径(mp nginx 反代);2026-10-22 v8 → v10(10-16 定版,与育儿首页一致)
|
||||
function goArchiveH5() {
|
||||
const oid = hashParam('openid');
|
||||
const uid = hashParam('unionid');
|
||||
@@ -1939,49 +1939,68 @@
|
||||
const day = Math.min(6, Math.max(0, parseInt(pgDay.value, 10) || 0));
|
||||
const sexBtn = $('#pgSex .pick.is-active');
|
||||
|
||||
/* ---- 妈妈那半(本地即时生效)----
|
||||
身份模型:卡片统一读档案;资料编辑的昵称/头像也是档案的一部分(最后写者胜)。
|
||||
落库在下方 fetch(头像需先上传换 URL)。 */
|
||||
const babySex = (sexBtn && sexBtn.dataset.sex) || 'unknown';
|
||||
const due = parseDay(pgDue.value);
|
||||
/* 未授权时妈妈栏是隐藏的:不写昵称/头像,否则会把旧昵称重新存回去 */
|
||||
const _unauth = state.authorized === false;
|
||||
if (!_unauth) {
|
||||
$('#meName').textContent = name;
|
||||
state.userName = name;
|
||||
}
|
||||
/* ⚠️ 这里原来还有一行 state.userBio = bio 和一次 syncBio() 调用。
|
||||
一句话签名整块已按用户要求删除(输入框 #pfBio、展示行 #meBio、
|
||||
syncBio()、state.userBio 四处一起删),别只加回其中一处。 */
|
||||
|
||||
/* ---- 宝宝那半(原 #pgSave) ---- */
|
||||
state.babyName = babyName;
|
||||
state.week = week;
|
||||
state.day = day;
|
||||
state.babySex = (sexBtn && sexBtn.dataset.sex) || 'unknown';
|
||||
state.due = parseDay(pgDue.value);
|
||||
/* 2026-10-22(测试会话 150e0991):原来本地先改、先关弹窗、先提示「资料已更新」,接口还没回来;
|
||||
失败时用户已经看到成功提示、输入也没了。现在改成**接口成功后**才写本地 state / 刷孕期卡 / 关弹窗 / 提示,
|
||||
失败(含头像上传失败)弹「保存失败,请重试」、弹窗不关、输入原样保留。
|
||||
无 openid(浏览器直访)没有可落的库,照旧只改本地。 */
|
||||
function applyLocal(avatarUrl) {
|
||||
/* ---- 妈妈那半 ----
|
||||
⚠️ 这里原来还有一行 state.userBio = bio 和一次 syncBio() 调用。
|
||||
一句话签名整块已按用户要求删除(输入框 #pfBio、展示行 #meBio、
|
||||
syncBio()、state.userBio 四处一起删),别只加回其中一处。 */
|
||||
if (!_unauth) {
|
||||
$('#meName').textContent = name;
|
||||
state.userName = name;
|
||||
if (avatarUrl) { $('#meAvatar').classList.add('has-img'); meAvatarImg.src = avatarUrl; }
|
||||
}
|
||||
/* ---- 宝宝那半(原 #pgSave) ---- */
|
||||
state.babyName = babyName;
|
||||
/* 2026-10-22:产后态孕周两格是空的(见上面回填),parseInt 出来是 0 → 原来会把 state.week 写成 0、
|
||||
提示「孕 0 周」。产后不碰孕周,提示里也不带孕周 */
|
||||
if (!state.postpartum) {
|
||||
state.week = week;
|
||||
state.day = day;
|
||||
}
|
||||
state.babySex = babySex;
|
||||
state.due = due;
|
||||
/* ⚠️ syncPregnancy() 就是用户说的「同步到孕期卡上边」那一步 ——
|
||||
它把孕周环、剩余天数、预产期、宝宝多大重刷一遍,顺带 syncBabyWords()
|
||||
把全站写着小名的地方(首页三个模块名、来信提醒卡文案…)一起改。
|
||||
少调这一句,弹窗里改完了、外面还是旧数字,而且没有任何报错。 */
|
||||
syncPregnancy();
|
||||
closeModal();
|
||||
setTimeout(() => toast('资料已更新 · ' + name + ' · ' + babyName +
|
||||
(state.postpartum ? '' : ' 孕 ' + week + ' 周' + (day ? '+' + day + ' 天' : ''))), 260);
|
||||
}
|
||||
|
||||
/* ---- 落库:PUT /profile(孕育字段 + 昵称/头像)→ 刷新/重进后资料不丢。
|
||||
若弹窗里新选了头像(avFile 有文件),先 POST /upload 换正式 URL 再一起提交;
|
||||
上传失败则跳过头像字段(昵称/孕育照存)。断网/接口失败静默,本地已生效。 ---- */
|
||||
若弹窗里新选了头像(avFile 有文件),先 POST /upload 换正式 URL 再一起提交。 ---- */
|
||||
var _oid = hashParam('openid');
|
||||
var _wasEmpty = state.pregEmpty; /* 新用户完善资料后 → 重载拉真实孕周 */
|
||||
var saveBtn = $('#pfSave');
|
||||
if (saveBtn.dataset.busy === '1') return; /* 接口没回来前连点只算一次 */
|
||||
function setBusy(on) { saveBtn.dataset.busy = on ? '1' : ''; saveBtn.disabled = !!on; }
|
||||
function fail(msg) { setBusy(false); toast(msg || '保存失败,请重试'); }
|
||||
/* 保存时才把头像写进共享资料:avatarPicker.commit 已授权才写 auth/profile,并派发 mmbox:avatar */
|
||||
function syncSharedAvatar(url) {
|
||||
if (url && window.avatarPicker && window.avatarPicker.commit) window.avatarPicker.commit(url);
|
||||
}
|
||||
function _putProfile(avatarUrl) {
|
||||
if (!_oid) return;
|
||||
if (!_oid) { applyLocal(avatarUrl); setBusy(false); return; }
|
||||
var body = {
|
||||
babyName: babyName,
|
||||
babySex: state.babySex,
|
||||
babySex: babySex,
|
||||
};
|
||||
/* 预产期没改就不传:表单可能是几分钟前回填的,别的应用这期间改过的话会被旧值盖回去 */
|
||||
var _due = state.due ? toISO(state.due) : '';
|
||||
var _due = due ? toISO(due) : '';
|
||||
if (_due !== filledDue || _wasEmpty) body.dueDate = _due;
|
||||
if (!_unauth) body.userName = name;
|
||||
if (avatarUrl && !_unauth) {
|
||||
body.avatar = avatarUrl;
|
||||
meAvatarImg.src = avatarUrl; /* 用正式 URL 替换 base64 预览 */
|
||||
}
|
||||
if (avatarUrl && !_unauth) body.avatar = avatarUrl;
|
||||
fetch('/api/mp/public/mama-box/profile?openid=' + encodeURIComponent(_oid), {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -1992,45 +2011,36 @@
|
||||
/* ⚠️ 2026-09-22(档案以上游为准):预产期/昵称会**先推上游、推失败后端返回 400 且不落库**。
|
||||
这里必须让用户看见失败 —— 静默的话下次加载会被上游值覆盖回去,用户以为"改了没生效"。 */
|
||||
if (!res || res.code !== 200) {
|
||||
toast((res && res.message) || '保存失败,请检查网络后重试');
|
||||
fail(res && res.message ? res.message + ',请重试' : '');
|
||||
return;
|
||||
}
|
||||
setBusy(false);
|
||||
if (avatarUrl && !_unauth) { syncSharedAvatar(avatarUrl); pickedAvatar = ''; }
|
||||
applyLocal(_unauth ? '' : avatarUrl);
|
||||
/* 新用户首次完善资料:重载页面 → pregnancy 出真实孕周 */
|
||||
if (_wasEmpty) setTimeout(bustReload, 700);
|
||||
}).catch(function () {
|
||||
toast('保存失败,请检查网络后重试');
|
||||
});
|
||||
}).catch(function () { fail(); });
|
||||
}
|
||||
setBusy(true);
|
||||
var newAvatarFile = (avFile.files && avFile.files[0]) || null;
|
||||
if (pickedAvatar && !_unauth) {
|
||||
/* 头像面板选的已经是正式 URL(预设图 / 面板自己上传过),直接写 */
|
||||
$('#meAvatar').classList.add('has-img');
|
||||
_putProfile(pickedAvatar);
|
||||
syncSharedAvatar(pickedAvatar);
|
||||
pickedAvatar = '';
|
||||
} else if (newAvatarFile && avBig.classList.contains('has-img')) {
|
||||
} else if (newAvatarFile && avBig.classList.contains('has-img') && !_unauth) {
|
||||
var fd = new FormData();
|
||||
fd.append('file', newAvatarFile, newAvatarFile.name || 'avatar.png');
|
||||
/* 2026-10-22:上传失败原来静默跳过头像、其余照存,用户以为头像也换好了 → 现在整次不存、提示重试 */
|
||||
fetch('/api/upload', { method: 'POST', body: fd })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (res) {
|
||||
var url = res && res.result && res.result.url;
|
||||
_putProfile(url || '');
|
||||
if (!_unauth) syncSharedAvatar(url);
|
||||
if (!url) { fail('头像上传失败,请重试'); return; }
|
||||
_putProfile(url);
|
||||
})
|
||||
.catch(function () { _putProfile(''); });
|
||||
.catch(function () { fail('头像上传失败,请检查网络后重试'); });
|
||||
} else {
|
||||
_putProfile('');
|
||||
}
|
||||
|
||||
/* ⚠️ syncPregnancy() 就是用户说的「同步到孕期卡上边」那一步 ——
|
||||
它把孕周环、剩余天数、预产期、宝宝多大重刷一遍,顺带 syncBabyWords()
|
||||
把全站写着小名的地方(首页三个模块名、来信提醒卡文案…)一起改。
|
||||
少调这一句,弹窗里改完了、外面还是旧数字,而且没有任何报错。 */
|
||||
syncPregnancy();
|
||||
closeModal();
|
||||
setTimeout(() => toast('资料已更新 · ' + name + ' · ' + babyName +
|
||||
' 孕 ' + week + ' 周' + (day ? '+' + day + ' 天' : '')), 260);
|
||||
});
|
||||
|
||||
/* 「我的二维码」按需求已整块移除 */
|
||||
@@ -2049,19 +2059,16 @@
|
||||
title: '隐私与权限', more: '你的记录只属于你',
|
||||
lead: '孕期的记录是很私人的东西。默认情况下,只有你自己能看到它们。',
|
||||
groups: [
|
||||
{ t: '谁能看到', rows: [
|
||||
['sw', '档案仅自己可见', '关掉后可生成分享链接', 1],
|
||||
['sw', '允许家人查看', '爸爸可看孕周与产检日程', 1]
|
||||
] },
|
||||
/* 2026-10-22 删「谁能看到」两个开关(档案仅自己可见 / 允许家人查看):只变色 + toast,什么都不存 */
|
||||
/* 2026-10-03 首页彩蛋开关(js/bump.js):第 5 项是 localStorage 键,开关状态真的存下来,不是摆设 */
|
||||
{ t: '首页小彩蛋', rows: [
|
||||
['sw', '宝宝在肚皮下动', '孕 20 周起,首页偶尔被宝宝顶起来,摁一下会躲开', 1, 'mb_bump']
|
||||
] },
|
||||
{ t: '', rows: [
|
||||
['txt', '我们不会把你的孕期数据用于广告投放,也不会卖给第三方。数据加密存储,你可以随时导出或删除。']
|
||||
['txt', '我们不会把你的孕期数据用于广告投放,也不会卖给第三方。数据加密存储。']
|
||||
] }
|
||||
],
|
||||
foot: '《隐私政策》最近一次更新:2024 年 8 月 12 日'
|
||||
foot: '《隐私政策》最近一次更新:2026 年 10 月 22 日'
|
||||
},
|
||||
|
||||
help: {
|
||||
@@ -4266,7 +4273,8 @@
|
||||
entry.classList.toggle('hide', !on);
|
||||
const sec = $('#pulse');
|
||||
if (sec) sec.classList.toggle('has-wh', on);
|
||||
if (!on) closePage();
|
||||
/* 2026-10-22(测试会话 150e0991):原来这里 if (!on) closePage() —— 「此刻」每 60 秒刷新一次,
|
||||
某次接口抖一下 / 返回 show=false,就把用户正在看的悄悄话页关掉。现在只收首页入口,开着的页面让用户自己关 */
|
||||
}
|
||||
function load(w, silent) {
|
||||
wk = w;
|
||||
@@ -4288,7 +4296,7 @@
|
||||
})
|
||||
.catch(() => { if (!silent) show(false); });
|
||||
}
|
||||
whLoad = w => load(w, false);
|
||||
whLoad = w => load(w, w === wk); /* 同一孕周的重拉(「此刻」每 60 秒一次)按静默刷新走:失败不收入口 */
|
||||
setInterval(() => { if (wk && !document.hidden && !busy) load(wk, true); }, 300000);
|
||||
|
||||
/* 抱抱:先变(心跳 + 一串小心飘上去),失败再退回 */
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
'.bf-card.born .bf-ic{background:#CFEEDC}.bf-card.born .bf-go{color:#2F8A5E;border-color:#2F8A5E}' +
|
||||
'.bf-me{display:flex;align-items:center;gap:10px;width:100%;margin-top:12px;padding:14px 16px;border:0;border-radius:18px;background:#fff;text-align:left;font-size:15px;color:#2B2320;box-shadow:0 2px 10px rgba(80,40,20,.05)}' +
|
||||
'.bf-me i{font-style:normal}.bf-me .bf-me-ic{flex:none;width:30px;height:30px;border-radius:10px;background:#FFE0D1;display:flex;align-items:center;justify-content:center}' +
|
||||
'.bf-me.born .bf-me-ic{background:#D8EFE1}.bf-me.born .bf-me-v{color:#3A7A52}' +
|
||||
'.bf-me .bf-me-t{flex:1}.bf-me .bf-me-v{font-size:12.5px;color:#9A8E86}.bf-me .bf-me-a{color:#C9BEB6}' +
|
||||
'.bf-ov{position:fixed;inset:0;z-index:135;display:none;background:rgba(30,20,15,.45);font-family:inherit;color:#2B2320}' +
|
||||
'.bf-ov.on{display:flex;align-items:flex-end}' +
|
||||
@@ -259,7 +260,7 @@
|
||||
if (d > t) { $('#bfErr').textContent = '出生日期不能晚于今天'; return; }
|
||||
/* 不拿预产期卡出生日期:在分流页误选了「孕期」的育儿用户,预产期是随手填的,宝宝可能早就出生了(2026-10-21) */
|
||||
var v = iso(d), btn = $('#bfSubmit');
|
||||
btn.disabled = true; btn.textContent = '正在保存…';
|
||||
btn.disabled = true; btn.textContent = '正在保存…'; $('#bfErr').textContent = '';
|
||||
var put = function (body) {
|
||||
return fetch(API + 'mama-box/profile?openid=' + encodeURIComponent(openid), {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body)
|
||||
@@ -271,9 +272,19 @@
|
||||
var extra = {};
|
||||
if (name && name !== S.babyName) extra.babyName = name;
|
||||
if (sex !== S.babySex) extra.babySex = sex;
|
||||
return (Object.keys(extra).length ? put(extra) : Promise.resolve()).then(function () { return ok; });
|
||||
/* 2026-10-22(测试会话 150e0991):第二次 PUT(小名 / 性别)原来不看结果,失败也照跳育儿首页 →
|
||||
小名性别静默丢了。现在失败就停在登记页提示重试;重试会把出生日期再 PUT 一次(同值,幂等)。
|
||||
出生日期本身没存上仍按原设计放行(pending,育儿首页会自动再交),但那份补交不含小名性别,所以这里必须拦。 */
|
||||
if (!Object.keys(extra).length) return ok;
|
||||
return put(extra).then(function (r2) {
|
||||
if (r2 && r2.code === 200) return ok;
|
||||
btn.disabled = false; btn.textContent = '重试保存';
|
||||
$('#bfErr').textContent = (r2 && r2.message ? r2.message + ',' : '') + '宝宝小名和性别没保存上,请重试';
|
||||
return null;
|
||||
});
|
||||
});
|
||||
done.then(function (ok) {
|
||||
if (ok === null) return; /* 小名 / 性别保存失败,已提示,留在登记页 */
|
||||
if (!openid && !DEMO) { btn.disabled = false; btn.textContent = '完成,切换到育儿模式'; $('#bfErr').textContent = '没有拿到你的身份信息,请从小程序里重新打开再试'; return; }
|
||||
/* 本机记下阶段:分流页下次直接送育儿首页;没存上服务器时 pending=true,育儿首页会自动再交 */
|
||||
if (!DEMO) try {
|
||||
@@ -344,8 +355,10 @@
|
||||
|
||||
var pc = $('#screen-me .preg-card'), me = $('#bfMe');
|
||||
if (me) me.remove();
|
||||
if (pc && !S.postpartum) pc.insertAdjacentHTML('afterend',
|
||||
'<button class="bf-me ripple" id="bfMe" data-bf-open="reg"><span class="bf-me-ic">' + BABY('#F4593C', 18) + '</span><span class="bf-me-t">宝宝出生了?</span><span class="bf-me-v">切换到育儿模式</span><i class="bf-me-a">›</i></button>');
|
||||
/* 2026-10-22(测试会话 150e0991):产后用户「我的」里原来什么入口都没有 → 换成「宝宝已出生 · 去育儿首页」,走同一个 goBaby() */
|
||||
if (pc) pc.insertAdjacentHTML('afterend', S.postpartum
|
||||
? '<button class="bf-me born ripple" id="bfMe" data-bf-open="baby"><span class="bf-me-ic">' + BABY('#2F8A5E', 18) + '</span><span class="bf-me-t">宝宝已出生</span><span class="bf-me-v">去育儿首页</span><i class="bf-me-a">›</i></button>'
|
||||
: '<button class="bf-me ripple" id="bfMe" data-bf-open="reg"><span class="bf-me-ic">' + BABY('#F4593C', 18) + '</span><span class="bf-me-t">宝宝出生了?</span><span class="bf-me-v">切换到育儿模式</span><i class="bf-me-a">›</i></button>');
|
||||
}
|
||||
|
||||
function maybeAsk() {
|
||||
|
||||
Reference in New Issue
Block a user