身份模型v3: 显式 authorized 状态(退出只翻状态不清资料); 授权结果同步覆盖应用档案(含新手机号); PUT /profile 收昵称/头像(资料编辑落库); pfSave 头像上传+落库 (v26090709)

This commit is contained in:
2026-09-08 00:10:14 +08:00
parent 712669c651
commit 8289245dd1
2 changed files with 45 additions and 31 deletions

View File

@@ -6,8 +6,8 @@
<meta name="theme-color" content="#F4593C">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>妈妈盒子 · 孕育陪伴</title>
<!-- V:26090708 缓存版本标记:改 css/js 时同步 bump 该值,并给下方资源引用加 ?v= 以强制 webview 刷新子资源 -->
<link rel="stylesheet" href="mama-box.css?v=26090708">
<!-- V:26090709 缓存版本标记:改 css/js 时同步 bump 该值,并给下方资源引用加 ?v= 以强制 webview 刷新子资源 -->
<link rel="stylesheet" href="mama-box.css?v=26090709">
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
@@ -1758,8 +1758,8 @@
加载失败/离线时 window.wx 为 undefined,goMall() 会降级为 toast 提示,
不影响应用其余功能。 -->
<script src="js/app.js?v=26090708"></script>
<!-- 页面版本号(排查 webview 缓存):底部会显示 v26090708 -->
<div id="ver" style="position:fixed;left:0;right:0;bottom:10px;text-align:center;z-index:9999;pointer-events:none;color:#B3A69C;font-size:10px;letter-spacing:.5px">v26090708</div>
<script src="js/app.js?v=26090709"></script>
<!-- 页面版本号(排查 webview 缓存):底部会显示 v26090709 -->
<div id="ver" style="position:fixed;left:0;right:0;bottom:10px;text-align:center;z-index:9999;pointer-events:none;color:#B3A69C;font-size:10px;letter-spacing:.5px">v26090709</div>
</body>
</html>

View File

@@ -1929,18 +1929,11 @@
const day = Math.min(6, Math.max(0, parseInt(pgDay.value, 10) || 0));
const sexBtn = $('#pgSex .pick.is-active');
/* ---- 妈妈那半 ----
身份模型:展示名「授权登录昵称优先」——state.userName 若来自授权登录
(applyRemoteProfile 写入且 _authNameFromAuth 标记),弹窗昵称不覆盖它,
只作本地展示 fallback(state.localName)。 */
if (!state._authNameFromAuth) {
$('#meName').textContent = name;
state.userName = name;
}
if (avBig.classList.contains('has-img')) {
meAvatarImg.src = avPreview.src;
meAvatar.classList.add('has-img');
}
/* ---- 妈妈那半(本地即时生效)----
身份模型:卡片统一读档案;资料编辑的昵称/头像也是档案的一部分(最后写者胜)。
落库在下方 fetch(头像需先上传换 URL)。 */
$('#meName').textContent = name;
state.userName = name;
/* ⚠️ 这里原来还有一行 state.userBio = bio 和一次 syncBio() 调用。
一句话签名整块已按用户要求删除(输入框 #pfBio、展示行 #meBio、
syncBio()、state.userBio 四处一起删),别只加回其中一处。 */
@@ -1952,15 +1945,41 @@
state.babySex = (sexBtn && sexBtn.dataset.sex) || 'unknown';
state.due = parseDay(pgDue.value);
/* ---- 落库:孕育字段走 PUT /profile(只收 babyName/babySex/dueDate,
显示字段后端明确不收)→ 刷新/重进后资料不丢。失败静默,本地已生效。 ---- */
/* ---- 落库:PUT /profile(孕育字段 + 昵称/头像)→ 刷新/重进后资料不丢。
若弹窗里新选了头像(avFile 有文件),先 POST /upload 换正式 URL 再一起提交;
上传失败则跳过头像字段(昵称/孕育照存)。断网/接口失败静默,本地已生效。 ---- */
var _oid = hashParam('openid');
if (_oid) {
function _putProfile(avatarUrl) {
if (!_oid) return;
var body = {
babyName: babyName,
babySex: state.babySex,
dueDate: state.due ? toISO(state.due) : '',
userName: name
};
if (avatarUrl) {
body.avatar = avatarUrl;
meAvatarImg.src = avatarUrl; /* 用正式 URL 替换 base64 预览 */
}
fetch('/api/mp/public/mama-box/profile?openid=' + encodeURIComponent(_oid), {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ babyName: babyName, babySex: state.babySex, dueDate: state.due ? toISO(state.due) : '' })
}).catch(function () { /* 断网时保持本地值,页面照常用 */ });
body: JSON.stringify(body)
}).catch(function () { /* 保持本地值 */ });
}
var newAvatarFile = (avFile.files && avFile.files[0]) || null;
if (newAvatarFile && avBig.classList.contains('has-img')) {
var fd = new FormData();
fd.append('file', newAvatarFile, newAvatarFile.name || 'avatar.png');
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 || '');
})
.catch(function () { _putProfile(''); });
} else {
_putProfile('');
}
/* ⚠️ syncPregnancy() 就是用户说的「同步到孕期卡上边」那一步 ——
@@ -4001,21 +4020,16 @@
if (p.babySex && p.babySex !== 'unknown') state.babySex = p.babySex;
if (p.dueDate) { const d = parseDay(p.dueDate); if (d) state.due = d; }
/* 状态化「我的」页:未授权→占位+显示授权入口;已授权→资料+隐藏授权入口;已建档(B→C)由孕期信息卡引导 */
var _auth = !!(p.userName || p.avatar || p.phone);
var _authorized = !!p.authorized || !!p.isAuthorized;
var _n = $('#meName'); if (_n) _n.textContent = p.userName || '未登录';
if (p.avatar) {
var _ai = $('#meAvatarImg'), _aw = $('#meAvatar');
if (_ai) _ai.src = p.avatar;
if (_aw) _aw.classList.add('has-img');
}
var _box = $('#meAuthBox'); if (_box) _box.style.display = _auth ? 'none' : '';
/* 授权信息优先:后端返回的 userName/avatar 即「授权登录信息」(含 CRMEB 同步),
标记 _authNameFromAuth —— 「我的资料」弹窗保存时不覆盖它(见 pfSave)。 */
if (p.userName) {
state._authNameFromAuth = true;
}
/* 退出按钮只在已登录(任一授权资料非空)时显示 —— 未登录"退出"没有意义 */
var _lx = $('#meLogoutBtn'); if (_lx) _lx.style.display = _auth ? '' : 'none';
/* 授权入口:未授权时显示(引导先授权);退出按钮:已授权时显示 */
var _box = $('#meAuthBox'); if (_box) _box.style.display = _authorized ? 'none' : '';
var _lx = $('#meLogoutBtn'); if (_lx) _lx.style.display = _authorized ? '' : 'none';
if (!p.userName) { var _ai2 = $('#meAvatarImg'); if (_ai2) _ai2.removeAttribute('src'); }
}
if (pg && pg.code === 200 && pg.result) {