其他妈妈也在搜:首页固定为参考图6问,全部24问+测一测小测试,头像10个 v26103109

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
deploy
2026-10-31 12:54:17 +00:00
parent b70236a354
commit 6f110cbd18
40 changed files with 117 additions and 87 deletions

118
js/app.js
View File

@@ -3,7 +3,7 @@
(function () {
'use strict';
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
var VER = '26103108';
var VER = '26103109';
const $ = (s, c) => (c || document).querySelector(s);
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
@@ -5057,77 +5057,106 @@
sec.classList.remove('hide');
revealTipsGrid();
}
/* 2026-10-31 首页「其他妈妈也在搜」:问题库 assets/data/qa/<周>.json(孕 4–40 周,每周 18 条问答),
首页只露 6 条(孕 12 周起第一条是妊娠纹专题),点任意一条 / 「查看全部」进 #detailQA 看答案和其余问题。
问题库没加载到时退回 6 条本周小知识入口(落点 #detailTips),首页不空。 */
/* 2026-10-31 首页「其他妈妈也在搜」(用户给了参考图,定了问题):问题库 assets/data/qa/hot.json,共 24 条,
前 6 条就是参考图上那 6 个问题,首页只露这 6 条;点任意一条 / 「查看全部」进 #detailQA 看答案和其余问题。
条目字段:q 问题 / a 答案 / tag 分类 / hot 热 / href 有专题页的直接跳 / quiz 答案区是「测一测」小测试。
问题库没加载到时退回 5 条本周小知识入口(落点 #detailTips),首页不空。 */
let QA = null, qaLoading = null;
/* 按周拆成小文件 assets/data/qa/<周>.json(每份约 6KB),只拉当前孕周;孕周变了再拉新的一份 */
function loadQA() {
const w = qaWeek();
if (QA && QA[w]) return Promise.resolve(QA);
if (!qaLoading || qaLoading.w !== w) {
qaLoading = fetch('assets/data/qa/' + w + '.json?v=' + VER).then(r => (r.ok ? r.json() : [])).catch(() => [])
.then(a => { QA = QA || {}; QA[w] = Array.isArray(a) ? a : []; return QA; });
qaLoading.w = w;
}
if (QA) return Promise.resolve(QA);
if (!qaLoading) qaLoading = fetch('assets/data/qa/hot.json?v=' + VER).then(r => (r.ok ? r.json() : [])).catch(() => [])
.then(a => (QA = Array.isArray(a) ? a : []));
return qaLoading;
}
const QA_CATS = ['产检', '身体', '饮食', '补剂', '宝宝', '生活', '心情', '准备'];
let qaCat = '全部';
function qaWeek() { return Math.max(4, Math.min(40, state.week || 0)); }
const qaHref = h => h + location.search + location.hash;
function renderSearch(wk, today, size) {
const W = state.week, L = $('#msList');
if (!L) return;
if (!QA || !QA[qaWeek()]) { loadQA().then(q => { if (q[qaWeek()] && q[qaWeek()].length) renderSearch(wk, today, size); }); }
if (!QA) loadQA().then(q => { if (q.length) renderSearch(wk, today, size); });
$('#msWk').textContent = '孕 ' + W + ' 周';
$('#msCnt').textContent = '孕 ' + W + ' 周的妈妈都在看';
const pool = AVA_TOP.concat(AVA_FEED), s0 = (W * 7) % pool.length;
$('#msAvs').innerHTML = [0, 1, 2, 3, 4, 5, 6, 7].map(i => avaImg(pool[(s0 + i * 3) % pool.length])).join('');
const bank = (QA && QA[qaWeek()]) || [];
const items = [];
if (W >= 12) items.push({ q: '妊娠纹怎么防?现在该抹什么', tag: '专题', cls: 'hot', href: 'topic/wen/' + location.search + location.hash });
$('#msAvs').innerHTML = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(i => avaImg(pool[(s0 + i * 3) % pool.length])).join('');
const bank = QA || [];
let items;
if (bank.length) {
bank.slice(0, 6 - items.length).forEach((x, i) => items.push({ q: x.q, tag: x.hot ? '热' : '', cls: 'hot', qa: i }));
items = bank.slice(0, 6).map((x, i) => ({ q: x.q, href: x.href ? qaHref(x.href) : '', qa: i }));
} else {
const q = t => /[??吗呢]$/.test(t) ? t : t + (/怎么办|什么|多少|怎么|几/.test(t) ? '?' : '');
const d0 = wk.days[today];
if (d0 && d0.t) items.push({ q: q(d0.t), tag: '今日', cls: 'new', pt: '' });
items.push({ q: '孕' + W + '周,宝宝长多大了?', tag: '热', cls: 'hot', pt: 'baby' });
items = [];
if (d0 && d0.t) items.push({ q: q(d0.t), pt: '' });
items.push({ q: '孕' + W + '周,宝宝长多大了?', pt: 'baby' });
items.push({ q: '这周身体会有哪些变化?', pt: 'mom' });
items.push({ q: '孕' + W + '周吃什么对宝宝好?', pt: 'eat' });
items.push({ q: '这周产检和生活要留心什么?', pt: 'care' });
}
L.textContent = '';
items.slice(0, 6).forEach((it, i) => {
items.forEach((it, i) => {
const el = document.createElement(it.href ? 'a' : 'button');
el.className = 'ms-it ripple';
if (it.href) el.href = it.href;
else { el.type = 'button'; el.addEventListener('click', () => (it.qa != null ? openQA(it.qa) : openTips(it.pt))); }
const no = document.createElement('i'); no.className = 'ms-no'; no.textContent = i + 1;
const t = document.createElement('span'); t.className = 'ms-q'; t.textContent = it.q;
el.appendChild(no); el.appendChild(t);
if (it.tag) { const g = document.createElement('span'); g.className = 'ms-tag' + (it.cls ? ' ' + it.cls : ''); g.textContent = it.tag; el.appendChild(g); }
const go = document.createElement('i'); go.className = 'ms-go'; go.textContent = '›'; el.appendChild(go);
const go = document.createElement('i'); go.className = 'ms-go'; go.textContent = '›';
el.appendChild(no); el.appendChild(t); el.appendChild(go);
L.appendChild(el);
});
const all = $('#msAll');
if (all) {
const n = bank.length + (W >= 12 ? 1 : 0);
all.classList.toggle('hide', !bank.length);
all.textContent = '查看全部 ' + n + ' 个问题 ›';
all.classList.toggle('hide', bank.length <= 6);
all.textContent = '查看全部 ' + bank.length + ' 个问题 ›';
}
}
/* 全部问题页:focus = 从首页点的那条在本周问题库里的下标(展开 + 滚到它);不传 = 从「查看全部」进来 */
/* 「测一测你是什么样的妈妈」:5 题,每个选项记一种类型,选得最多的就是结果。纯娱乐,不存数据 */
const QUIZ = [
['宝宝哭了,你的第一反应是?', ['马上抱起来哄', '先看看是饿了还是尿了', '等一等,看他能不能自己安静', '先拍下来发家庭群']],
['准备待产包,你会怎么做?', ['早早列清单,反复核对', '对照医院和过来人的清单买', '想到什么买什么', '和姐妹们一起逛一起买']],
['孕期刷手机,你最常看?', ['宝宝发育和护理知识', '好物测评和攻略', '搞笑视频,放松一下', '晒孕照、看别人的孕期日记']],
['宝宝以后上什么兴趣班?', ['从小做好规划', '先了解每种的利弊再定', '他喜欢什么就学什么', '和朋友家孩子一起报']],
['理想的周末是?', ['在家布置婴儿房', '去听一场孕妈课堂', '睡到自然醒', '约朋友吃饭拍照']],
];
const QUIZ_R = [
['暖心守护型妈妈', '你的爱藏在每一个细节里,宝宝一有动静你就在身边。记得也照顾好自己,累了就让家人搭把手。'],
['理性学习型妈妈', '你相信知识带来的安全感,凡事先了解清楚再行动。别被信息淹没,抓大放小,相信自己的判断。'],
['松弛自在型妈妈', '你心态稳、不焦虑,这份松弛感会传递给宝宝。孕期的产检和关键时间点,记得设个提醒。'],
['热情分享型妈妈', '你乐于分享,身边总有一群好姐妹。多和过来人交流,但遇到问题以医生的意见为准。'],
];
function buildQuiz(box) {
box.textContent = '';
const pick = [];
const draw = () => {
box.textContent = '';
const i = pick.length;
if (i >= QUIZ.length) {
const cnt = [0, 0, 0, 0]; pick.forEach(k => cnt[k]++);
const r = QUIZ_R[cnt.indexOf(Math.max.apply(null, cnt))];
box.innerHTML = '<div class="qz-r"><span>你是</span><b></b><p></p><button type="button" class="qz-again">再测一次</button></div>';
box.querySelector('b').textContent = r[0]; box.querySelector('p').textContent = r[1];
box.querySelector('.qz-again').addEventListener('click', () => { pick.length = 0; draw(); });
return;
}
const h = document.createElement('div'); h.className = 'qz-h'; h.textContent = (i + 1) + ' / ' + QUIZ.length + ' ' + QUIZ[i][0];
box.appendChild(h);
QUIZ[i][1].forEach((o, k) => {
const b = document.createElement('button'); b.type = 'button'; b.className = 'qz-o'; b.textContent = o;
b.addEventListener('click', () => { haptic(); pick.push(k); draw(); });
box.appendChild(b);
});
};
draw();
}
/* 全部问题页:focus = 从首页点的那条的下标(展开 + 滚到它);不传 = 从「查看全部」进来 */
function openQA(focus) {
const W = state.week, bank = (QA && QA[qaWeek()]) || [];
const bank = QA || [];
if (!bank.length) { openTips(); return; }
$('#qaTitle').textContent = '孕 ' + W + ' 周 · 其他妈妈也在搜';
$('#qaHeroT').textContent = '孕 ' + W + ' 周,妈妈们最常问的 ' + bank.length + ' 个问题';
$('#qaHeroD').textContent = '点开问题看答案,每周按孕周自动更新';
const tp = $('#qaTopic');
tp.classList.toggle('hide', !(W >= 12));
tp.setAttribute('href', 'topic/wen/' + location.search + location.hash);
const cats = QA_CATS.filter(c => bank.some(x => x.tag === c));
$('#qaTitle').textContent = '其他妈妈也在搜';
$('#qaHeroT').textContent = '妈妈们最常问的 ' + bank.length + ' 个问题';
$('#qaHeroD').textContent = '点开问题看答案';
$('#qaTopic').classList.add('hide');
const cats = [];
bank.forEach(x => { if (x.tag && cats.indexOf(x.tag) < 0) cats.push(x.tag); });
const cb = $('#qaCats');
cb.textContent = '';
['全部'].concat(cats).forEach(c => {
@@ -5143,15 +5172,18 @@
L.textContent = '';
bank.forEach((x, i) => {
const it = document.createElement('div');
it.className = 'qa-it' + (i < 3 ? ' top' : '');
it.className = 'qa-it' + (i < 6 ? ' top' : '');
it.dataset.cat = x.tag || '';
const h = document.createElement('button'); h.type = 'button'; h.className = 'qa-q';
const no = document.createElement('i'); no.className = 'qa-no'; no.textContent = i + 1;
const t = document.createElement('span'); t.className = 'qa-tx'; t.textContent = x.q;
const g = document.createElement('span'); g.className = 'qa-tag' + (x.hot ? ' hot' : ''); g.textContent = x.hot ? '热' : (x.tag || '');
const g = document.createElement('span'); g.className = 'qa-tag' + (x.hot ? ' hot' : ''); g.textContent = x.tag || '';
const ch = document.createElement('i'); ch.className = 'qa-ch'; ch.textContent = '›';
h.appendChild(no); h.appendChild(t); if (g.textContent) h.appendChild(g); h.appendChild(ch);
const a = document.createElement('div'); a.className = 'qa-a'; a.textContent = x.a || '';
const a = document.createElement('div'); a.className = 'qa-a';
if (x.quiz) { const p = document.createElement('p'); p.className = 'qz-lead'; p.textContent = x.a || ''; a.appendChild(p); const qz = document.createElement('div'); qz.className = 'qz'; a.appendChild(qz); buildQuiz(qz); }
else a.textContent = x.a || '';
if (x.href) { const go = document.createElement('a'); go.className = 'qa-go'; go.href = qaHref(x.href); go.textContent = '进专题页看完整内容 ›'; a.appendChild(go); }
h.addEventListener('click', () => { it.classList.toggle('open'); haptic(); });
it.appendChild(h); it.appendChild(a);
L.appendChild(it);
@@ -5170,10 +5202,8 @@
}
}
function qaFilter(c) {
qaCat = c;
$$('#qaCats .qa-cat').forEach(b => b.classList.toggle('on', b.dataset.cat === c));
$$('#qaList .qa-it').forEach(it => it.classList.toggle('hide', c !== '全部' && it.dataset.cat !== c));
const tp = $('#qaTopic'); if (tp) tp.style.display = c === '全部' ? '' : 'none';
}
(function () {
const all = $('#msAll'); if (all) all.addEventListener('click', () => openQA());