Compare commits

...

3 Commits

Author SHA1 Message Date
karlcarlo
b0b0469983 孕期档案头像改用面板 sync:false + commit 正式写法 v26101032
Co-Authored-By: AI 助手
2026-10-11 15:49:52 +00:00
karlcarlo
a55a4e26c8 孕周刷新后「此刻」板块也按新孕周重拉 v26101031
Co-Authored-By: AI 助手
2026-10-11 15:44:05 +00:00
karlcarlo
107fcaca84 孕周统一:回到前台/打开孕期档案重拉共享孕期;保存时预产期未改不回写 v26101030
Co-Authored-By: AI 助手
2026-10-11 15:41:22 +00:00
2 changed files with 72 additions and 48 deletions

View File

@@ -7,7 +7,7 @@
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>兜爸心选 · 孕育陪伴</title>
<!-- V:26101029 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
<!-- V:26101032 缓存版本标记:改 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) -->
@@ -2039,7 +2039,7 @@
不影响应用其余功能。 -->
<!-- 统一头像面板(预设妈妈/宝宝头像 + 从相册上传 + 用微信头像),孕期档案点头像用 -->
<script src="/_bridge/avatar-picker.js?v=26101104"></script>
<script src="/_bridge/avatar-picker.js?v=26101105"></script>
<script src="js/zodiac-art.js"></script>
<script src="js/app.js"></script>
<!-- 2026-10-03 首页彩蛋:宝宝在肚皮底下动(独立文件,删掉这一行即整体下线;开关在「隐私权限」) -->

116
js/app.js
View File

@@ -3,7 +3,7 @@
(function () {
'use strict';
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
var VER = '26101029';
var VER = '26101032';
const $ = (s, c) => (c || document).querySelector(s);
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
@@ -980,7 +980,10 @@
m.classList.add('show');
haptic();
/* 「我的资料」打开时按服务端档案回填表单(新用户全空,不残留演示默认值) */
if (id === 'modalProfile') fillProfileForm();
if (id === 'modalProfile') {
fillProfileForm();
refreshPregnancy().then(function (changed) { if (changed && openedModal === m) fillProfileForm(); });
}
/* 有些弹窗的主角不是输入框。企业微信那个弹窗正中间是一张二维码,
用户要做的第一件事是**举起另一台手机去扫它**;自动聚焦输入框会把
手机键盘顶上来,恰好盖住二维码的下半截。所以给一个显式的退出口,
@@ -1255,6 +1258,7 @@
/* 打开资料弹窗时的表单回填:全部以服务端档案为准(最后写入者胜)。
新用户(未完善资料):昵称/小名/预产期/孕周全空 + 孕周锁定,只留 placeholder。 */
let filledDue = '';
function fillProfileForm() {
pickedAvatar = '';
$('#pfName').value = state.userName || '';
@@ -1283,6 +1287,7 @@
pgDay.value = '';
lockWeekFields(true);
}
filledDue = pgDue.value || '';
syncDuePh();
setPgMode('due');
if (pgLmp) { pgLmp.value = ''; pgLmp.dispatchEvent(new Event('change')); }
@@ -1873,23 +1878,16 @@
这里 avFile 排在 pfName 前面,所以 openModal 用的选择器只取 .modal-ta/input
可能命中 file input——用 :not([type=file]) 排除掉,见 openModal */
/* 2026-10-11 用户:点头像弹预设选项,也能从相册上传、用微信头像 → 走统一头像面板 avatarPicker
(/_bridge/avatar-picker.js:选完自己上传、派发 mmbox:avatar;共享资料改到保存时写)。
(/_bridge/avatar-picker.js:sync:false 选完只回调;保存时 commit 写共享资料、派发 mmbox:avatar)。
选中的是正式 URL,记在 pickedAvatar,保存时一起 PUT 进首页档案;面板没加载上才退回系统选图。 */
function openAvatarPanel() {
if (window.avatarPicker && window.avatarPicker.open) {
window.avatarPicker.open({
current: avBig.classList.contains('has-img') ? avPreview.src : '',
accent: '#F4593C', accentSoft: '#FDECE7',
/* 2026-10-11 用户:点「保存资料」后才让所有应用同步头像 → 面板只回调,保存时 commit */
sync: false,
onPick: function (url) {
/* 2026-10-11 用户:点「保存资料」后才让所有应用同步头像。面板 done() 里紧接着 onPick
会同步调 syncShared → wxAuth.identity(),这里让那一次拿到空身份,面板就不写共享资料;
真正的共享写入放到 #pfSave 里(syncSharedAvatar)。 */
var wa = window.wxAuth;
if (wa && wa.identity) {
var _id = wa.identity, _back = function () { wa.identity = _id; };
wa.identity = function () { _back(); return {}; };
setTimeout(_back, 0);
}
pickedAvatar = url;
avFile.value = '';
avPreview.src = url; avBig.classList.add('has-img');
@@ -1964,21 +1962,19 @@
上传失败则跳过头像字段(昵称/孕育照存)。断网/接口失败静默,本地已生效。 ---- */
var _oid = hashParam('openid');
var _wasEmpty = state.pregEmpty; /* 新用户完善资料后 → 重载拉真实孕周 */
/* 保存时才把头像写进共享资料(auth/profile),其它应用读 user-center/info 就会跟着换 */
/* 保存时才把头像写进共享资料:avatarPicker.commit 已授权才写 auth/profile,并派发 mmbox:avatar */
function syncSharedAvatar(url) {
var id = (window.wxAuth && wxAuth.identity && wxAuth.identity()) || {};
if (!url || !id.openid) return;
var q = '?openid=' + encodeURIComponent(id.openid) + (id.unionid ? '&unionid=' + encodeURIComponent(id.unionid) : '');
fetch('/api/mp/public/auth/profile' + q + '&avatar=' + encodeURIComponent(url), { method: 'POST' }).catch(function () {});
try { window.dispatchEvent(new CustomEvent('mmbox:avatar', { detail: { url: url, source: 'save', for: 'mom' } })); } catch (e) {}
if (url && window.avatarPicker && window.avatarPicker.commit) window.avatarPicker.commit(url);
}
function _putProfile(avatarUrl) {
if (!_oid) return;
var body = {
babyName: babyName,
babySex: state.babySex,
dueDate: state.due ? toISO(state.due) : ''
};
/* 预产期没改就不传:表单可能是几分钟前回填的,别的应用这期间改过的话会被旧值盖回去 */
var _due = state.due ? toISO(state.due) : '';
if (_due !== filledDue || _wasEmpty) body.dueDate = _due;
if (!_unauth) body.userName = name;
if (avatarUrl && !_unauth) {
body.avatar = avatarUrl;
@@ -3454,6 +3450,60 @@
/* ② 资料最多等这么久(ms)就让 ③ 应用数据照常发出:上游慢/挂住时首页不能空等 */
const REMOTE_PROFILE_WAIT_MS = 10000;
/* 孕期状态写进 state(/pregnancy 返回体)。首屏和「回到前台 / 打开孕期档案」重拉共用。
2026-10-11 用户:所有应用孕周必须统一 —— 别的应用改了预产期,回到首页要跟着变。 */
function applyPregnancy(pg) {
if (pg && pg.code === 200 && pg.result) {
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;
if (pg.result.due) { const d = parseDay(pg.result.due); if (d) state.due = d; }
}
}
}
let _pregAt = 0;
function refreshPregnancy() {
const openid = hashParam('openid');
if (!openid || DEMO) return Promise.resolve(false);
return fetch('/api/mp/public/mama-box/pregnancy?openid=' + encodeURIComponent(openid))
.then(r => (r.ok ? r.json() : null))
.then(function (pg) {
if (!pg || pg.code !== 200 || !pg.result) return false;
const before = state.due ? toISO(state.due) : '';
applyPregnancy(pg);
_pregAt = Date.now();
if ((state.due ? toISO(state.due) : '') === before) return false;
syncPregnancy();
if (!state.pregEmpty && !state.postpartum) { syncBabyWords(); syncStaticDates(); }
if (plHook) setTimeout(plHook, 0); // 「此刻」按新孕周重拉
return true;
}).catch(function () { return false; });
}
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'visible' && Date.now() - _pregAt > 5000) refreshPregnancy();
});
window.addEventListener('pageshow', function (e) { if (e.persisted) refreshPregnancy(); });
let _profileApplied = false;
/* ⚠️ 返回 Promise:调用方要**等资料落地**再取应用数据(预产期/小名来自上游同步,
它决定 state.pregEmpty,而今日脚印的显隐依赖它)。别改成 fire-and-forget。 */
@@ -3525,33 +3575,7 @@
if (_aw2) _aw2.classList.remove('has-img');
}
}
if (pg && pg.code === 200 && pg.result) {
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;
if (pg.result.due) { const d = parseDay(pg.result.due); if (d) state.due = d; }
}
}
applyPregnancy(pg);
if (DEMO) { // 示例模式:固定孕 29 周 0 天,预产期 = 今天 + (280 - 203) 天
state.postpartum = false; state.pregEmpty = false;
state.week = DEMO_WEEK; state.day = 0;