/* 星空页 · 妈妈们的留言(2026-11-07 用户:广场点「孕妈悄悄话」直接进星空页,留言自带在「说一句悄悄话」下面, 样式跟星空搭,不要白底)。 · 版式:#wcm 盖满星空页、自己滚动、本身不接点击;上面一段透明垫高(点得到星星),下面是留言面板, 把原来的 .whp-bar(说一句悄悄话)挪进面板顶上,往上滑留言就盖上来。 · 数据:广场置顶笔记 wh-<话题 from> 的评论 = cm.json 模拟(AGENTS.md 12c,不得挂星)+ /plaza/comments 已审核通过的真实评论 + 我自己发的(含审核中)。进星空页才拉 cm.json(600K+,gzip 后小很多;版本号跟广场 index.html 引的一致,共用缓存)。 · 赞只记本机 mmbox.whcm.v1(服务端计数是悄悄话第 2 步)。 */ (function () { var page = document.getElementById('whPage'), bar = page && page.querySelector('.whp-bar'); if (!page || !bar || !window.MB_WH_THEME) return; var TH = MB_WH_THEME(), PID = 'wh-' + TH.from.replace(/-/g, ''); var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); }; var m = ((location.hash || '') + '&').match(/[#&]openid=([^&]*)/), OID = m ? decodeURIComponent(m[1]) : ''; var box = document.createElement('div'); box.className = 'wcm'; box.id = 'wcm'; box.innerHTML = '
妈妈们的留言上滑看看
' + '

留言加载中…

'; box.querySelector('.wcm-in').insertBefore(bar, box.querySelector('.wcm-hd')); page.appendChild(box); var ls = box.querySelector('#wcmLs'), more = box.querySelector('#wcmMore'); var LK = 'mmbox.whcm.v1', LIKE = {}; try { LIKE = JSON.parse(localStorage.getItem(LK) || '{}') || {}; } catch (e) {} var avP = function (a) { return typeof a === 'number' ? 'guangchang/av/' + ('000' + a).slice(-4) + '.webp' : a.indexOf('av:') === 0 ? 'guangchang/av/' + a.slice(3) + '.webp' : a.charAt(0) === '/' ? a : 'assets/img/mom/' + a + '.jpg'; }; var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1) + 'w' : String(n); }; var ago = function (ts) { var d = (Date.now() - ts) / 1000; if (d < 3600) return Math.max(1, Math.round(d / 60)) + ' 分钟前'; if (d < 86400) return Math.round(d / 3600) + ' 小时前'; var t = new Date(ts + 8 * 3600e3); return (t.getUTCMonth() + 1) + '-' + t.getUTCDate(); }; var SIM = null, REAL = null, ALL = [], shown = 0, loading = false; function load() { if (loading || SIM) return; loading = true; fetch('guangchang/cm.json?v=26110612').then(function (r) { return r.json(); }).then(function (j) { var P = j.p; SIM = (j.c[PID] || []).map(function (c, k) { var p = P[c[0]]; return { key: 's' + k, n: p[0], av: avP(p[1]), s: p[2], t: c[1], likes: c[2], r: c[3].map(function (x) { var q = x[0] < 0 ? null : P[x[0]]; return { n: q ? q[0] : '孕妈悄悄话', t: x[1] }; }) }; }); build(); }).catch(function () { SIM = []; build(); }); fetch('/api/mp/public/mama-box/plaza/comments?kind=post&target=' + encodeURIComponent(PID) + (OID ? '&openid=' + encodeURIComponent(OID) : '')) .then(function (r) { return r.json(); }).then(function (j) { var R = j && j.code === 200 && j.result || {}, top = function (c) { return !c.parent; }; REAL = (R.list || []).filter(top).map(function (c) { return { key: 'r' + c.id, n: c.nickname || '孕妈', av: c.avatar || 'assets/img/mom/k01.jpg', s: c.stage, t: c.text, likes: 0, ts: c.at, r: [] }; }) .concat((R.mine || []).filter(function (c) { return top(c) && c.status !== 'rejected'; }).map(function (c) { return { key: 'r' + c.id, n: '我', me: 1, av: c.avatar || 'assets/img/mom/k01.jpg', s: c.stage, t: c.text, likes: 0, ts: c.at, st: c.status, r: [] }; })) .sort(function (a, b) { return b.ts - a.ts; }); build(); }).catch(function () { REAL = []; build(); }); } function build() { if (!SIM || !REAL) return; ALL = REAL.concat(SIM); shown = 0; ls.innerHTML = ''; document.getElementById('wcmN').textContent = ALL.length ? ALL.length + ' 条' : ''; if (!ALL.length) { ls.innerHTML = '

还没有留言

'; more.hidden = true; return; } add(20); } function item(c) { var on = !!LIKE[c.key]; return '
' + '

' + esc(c.n) + '' + (c.s ? '' + esc(c.s) + '' : '') + (c.ts ? '' + ago(c.ts) + '' : '') + '

' + '

' + esc(c.t) + '

' + (c.st === 'pending' ? '

审核中 · 通过后大家才能看到

' : '') + (c.r.length ? '
' + c.r.map(function (x) { return '

' + esc(x.n) + ':' + esc(x.t) + '

'; }).join('') + '
' : '') + '
' + '
'; } function add(k) { ls.insertAdjacentHTML('beforeend', ALL.slice(shown, shown + k).map(item).join('')); shown = Math.min(ALL.length, shown + k); more.hidden = shown >= ALL.length; } more.addEventListener('click', function () { add(30); }); ls.addEventListener('click', function (e) { var b = e.target.closest('[data-wcl]'); if (!b) return; var k = b.dataset.wcl, c = ALL.filter(function (x) { return x.key === k; })[0]; if (!c) return; if (LIKE[k]) delete LIKE[k]; else LIKE[k] = 1; try { localStorage.setItem(LK, JSON.stringify(LIKE)); } catch (e2) {} var on = !!LIKE[k]; b.classList.toggle('on', on); b.querySelector('span').textContent = fmt(c.likes + (on ? 1 : 0)); if (on && navigator.vibrate) navigator.vibrate(8); }); /* 上滑过半:面板压暗星空的那层渐变加深,「上滑看看」收起 */ box.addEventListener('scroll', function () { box.classList.toggle('up', box.scrollTop > 40); }, { passive: true }); /* 进星空页才拉数据;关掉回到顶部 */ new MutationObserver(function () { if (page.classList.contains('show')) load(); else { box.scrollTop = 0; box.classList.remove('up'); } }).observe(page, { attributes: true, attributeFilter: ['class'] }); if (page.classList.contains('show')) load(); })();