fix(首页): 来信卡默认收起,等 /letters 结果再决定显示 —— 修掉「先冒出来再缩回去」的闪烁 (v26092003)
现象:从商城切回首页加载 mama-box 时,先渲染出一张「宝宝来信/宝宝回信啦」卡 (用内置样例信 + 本地待投递队列拼的),几百毫秒后 /letters 回来说没有未读, 卡又缩回去,闪一下。 原因:卡在 index.html 里默认可见,pushLatestToHome() 是「先显示、数据回来再决定」; 而首屏渲染远早于 /letters。 改法(反过来:没确定之前一律不显示): - index.html:#homeLetter 默认带 .hide、#homeBody 默认带 .no-letter(首屏按「无卡」排版,不跳) - app.js:新增 lettersResolved 开关;pushLatestToHome() 在未确定、访客态(无 openid)、 或后端明确未建档(pregEmpty)时一律保持收起;applyRemoteLetters 的每条终态 (成功/空列表/接口挂/无身份)与 applyRemoteProfile 的访客分支都置位并重算 - 访客分支顺手补了一次 pushLatestToHome():此前清空 LETTERS 后没人重算, 那张卡会顶着一封已不存在的信留在首页 验证(本地 + 延迟代理四态,浏览器实测): - 有建档 + 0 封信:全程 hidden(修的就是这个) - 有建档 + 1 封未读:接口回来前 hidden → 回来后显示「小汤圆来信」 - 接口全挂:回退内置样例照旧显示(离线行为不变) - 访客(无 openid):hidden
This commit is contained in:
45
js/app.js
45
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26092002';
|
||||
var VER = '26092003';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -1319,10 +1319,30 @@
|
||||
全读完了还硬顶一封旧信在首页正中间,是在假装有新消息。
|
||||
收起来会空出 64px 的流高(卡是 margin-top:-16 + height:80),
|
||||
所以同时给 .home-body 挂 .no-letter 把下面的标题往下推一点,
|
||||
免得「孕期必用工具」直接贴到橙色头图底边上。 */
|
||||
免得「孕期必用工具」直接贴到橙色头图底边上。
|
||||
|
||||
⚠️⚠️ 2026-09-20:卡的显隐**要等 /letters 回来才算数**(lettersResolved)。
|
||||
之前的写法是「先把内置样例/本地队列拼出来的卡显示出来,数据回来再决定」——
|
||||
结果商城↔首页来回切时会闪一下:先冒出一张(甚至写着「宝宝回信啦」)的卡,
|
||||
几百毫秒后数据说没有未读,又缩回去。现在反过来:
|
||||
· index.html 里 #homeLetter 默认带 .hide、#homeBody 默认带 .no-letter;
|
||||
· 没确定(!lettersResolved)→ 一律保持收起;
|
||||
· 确定之后才可能显示,且只有在真有未读/新回信时才显示。
|
||||
代价是「有信」的用户看到卡出现在数据回来那一刻(晚一点点,但不闪)。 */
|
||||
let lettersResolved = false; // /letters 已经问过结果(含失败/访客态)—— 见 applyRemoteLetters
|
||||
|
||||
function hideLetterCard() {
|
||||
const card = $('#homeLetter'), body = $('#homeBody');
|
||||
if (card) { card.classList.add('hide'); card.classList.remove('has-new'); }
|
||||
if (body) body.classList.add('no-letter');
|
||||
}
|
||||
|
||||
function pushLatestToHome() {
|
||||
const card = $('#homeLetter');
|
||||
const body = $('#homeBody');
|
||||
/* 还没问出结果、访客态(没身份)、或后端明确说该用户没建档 —— 都别显示。
|
||||
⚠️ hashParam 是函数声明(在文件靠后定义),这里调用靠提升,没问题。 */
|
||||
if (!lettersResolved || !hashParam('openid') || state.pregEmpty) { hideLetterCard(); return; }
|
||||
const show = () => { card.classList.remove('hide'); body.classList.remove('no-letter'); };
|
||||
let msg = null, owner = null;
|
||||
LETTERS.forEach(L => L.thread.forEach(m => {
|
||||
@@ -3988,6 +4008,10 @@
|
||||
state.curLetter = ''; state.homeLetter = '';
|
||||
syncPregnancy(); /* 占位 + 隐藏脚印时间轴 + 信件引导态 */
|
||||
syncLetterCounts(); /* hero 计数切 '--'(角标 #tabBadge 已不由本地信件数驱动) */
|
||||
/* ⚠️ 必须重算首页来信卡:上面刚把 LETTERS 清空、pregEmpty 置真,
|
||||
不重算的话那张卡会停在「显示」状态,顶着一封已经不存在的信。 */
|
||||
lettersResolved = true;
|
||||
pushLatestToHome();
|
||||
return;
|
||||
}
|
||||
const base = '/api/mp/public/mama-box/';
|
||||
@@ -4119,14 +4143,22 @@
|
||||
拉不到 —— 无 openid / 接口挂 / 返回码不对 —— 就静默回落内置样例,页面照常可用。 */
|
||||
function applyRemoteLetters() {
|
||||
var openid = hashParam('openid');
|
||||
if (!openid) return;
|
||||
/* ⚠️ 下面每条**终态**都必须把 lettersResolved 置 true(含失败/无身份),
|
||||
否则首页那张来信卡会永远停在收起态(宁可收起也不能闪,见 pushLatestToHome)。
|
||||
无身份这条:卡本来就不该出现,置 true 只是让状态机收敛。 */
|
||||
if (!openid) { lettersResolved = true; pushLatestToHome(); return; }
|
||||
var base = '/api/mp/public/mama-box/';
|
||||
var j = function (u) { return fetch(u).then(function (r) { return r.ok ? r.json() : null; }).catch(function () { return null; }); };
|
||||
j(base + 'letters?openid=' + encodeURIComponent(openid)).then(function (lj) {
|
||||
if (!lj || lj.code !== 200 || !lj.result || !lj.result.items) return;
|
||||
/* 拉不到(接口挂/断网/返回码不对)→ 静默回落内置样例。
|
||||
这**也是**一个终态:样板信照样要能上首页卡(离线可用),所以这里要置位并重算。 */
|
||||
if (!lj || lj.code !== 200 || !lj.result || !lj.result.items) {
|
||||
lettersResolved = true; pushLatestToHome(); return;
|
||||
}
|
||||
/* 新用户空态:后端成功返回空列表 → 清掉内置样例信,展示「这里还没有内容」。
|
||||
⚠️ 不能直接 return —— 那会把 LETTERS 留在内置样例上,新用户看到演示信。 */
|
||||
if (!lj.result.items.length) {
|
||||
lettersResolved = true;
|
||||
LETTERS.splice(0, LETTERS.length);
|
||||
state.curLetter = '';
|
||||
state.homeLetter = '';
|
||||
@@ -4155,12 +4187,13 @@
|
||||
LETTERS.splice(0, LETTERS.length, ...apiList);
|
||||
state.curLetter = LETTERS[0].id;
|
||||
state.homeLetter = LETTERS[0].id;
|
||||
lettersResolved = true;
|
||||
renderLetters();
|
||||
syncLetterCounts();
|
||||
pushLatestToHome();
|
||||
} catch (e) { /* 映射 / 渲染异常就回退内置样例 */ }
|
||||
}).catch(function () { /* 静默回退内置样例 */ });
|
||||
}).catch(function () { /* 静默回退内置样例 */ });
|
||||
}).catch(function () { lettersResolved = true; pushLatestToHome(); /* 静默回退内置样例 */ });
|
||||
}).catch(function () { lettersResolved = true; pushLatestToHome(); /* 静默回退内置样例 */ });
|
||||
}
|
||||
|
||||
/* ---------- 今日脚印(box_app → 数胎动对外 API,动态获取) ----------
|
||||
|
||||
Reference in New Issue
Block a user