孕期首页测试修复 (v26102201):档案入口 v10、隐私页去假开关、资料保存等接口成功再提示、头像上传失败提示、产后不显示孕 0 周、悄悄话页不被刷新关掉、出生登记小名性别保存失败可重试

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
deploy
2026-10-22 02:37:44 +00:00
parent b2ab8368e7
commit 1c32bce8bd
3 changed files with 82 additions and 61 deletions

118
js/app.js
View File

@@ -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);
/* 抱抱:先变(心跳 + 一串小心飘上去),失败再退回 */