/* 退出登录后「只看不写」(2026-11-07 用户定): · 退出登录 ≠ 从没授权过:后端 user_auths.loggedOut 只在点了「退出登录」时置位,重新授权清掉; 从没授权过的新用户不受影响。 · 本机标记 localStorage mmbox.out.v1 = 退出时的 openid(首屏立刻知道,不等接口); 每次进页面再和服务器(只读接口 auth/status 的 loggedOut,查不到不建记录)对一次,对不上就改标记、重载一次。 · 退出后:首页按访客显示(app.js 里 hashParam 不给 openid);记录、评论、点赞、收藏、投稿、 兑换、改档案这些按钮点了弹「登录后才能使用」,去登录 = 小程序授权页(没有共享库的页面回首页「我的」)。 · 后端同样拦(box_app 返回 401 needLogin),这里只是让用户别白填。 首页 / 孕妈广场 / 专题页共用;按页面挑要拦的按钮(SEL)。 */ (function () { if (window.mbGate) return; var KEY = 'mmbox.out.v1', RL = 'mmbox.out.rl'; var me = document.currentScript && document.currentScript.src; function param(n) { var m = ((location.hash || '') + '&' + (location.search || '')).match(new RegExp('[#?&]' + n + '=([^&#?]*)')); return m ? decodeURIComponent(m[1]) : ''; } /* 11-07(消消乐 80d347e2 实测):maternal-bridge 会把 window.localStorage 换成落库的镜像,标记写进镜像会被同步到服务端 app_states, 刷新首屏又读不到 → 卡在登录态。退出标记只放本机真实存储:本脚本先于 bridge 加载时当场拿住;bridge 已接管时借一个同源隐藏 iframe 的。 */ var LS = (function () { try { if (!window.MaternalBridge) return window.localStorage; var f = document.createElement('iframe'); f.style.display = 'none'; f.setAttribute('aria-hidden', 'true'); f.src = 'about:blank'; (document.body || document.documentElement).appendChild(f); return f.contentWindow.localStorage; } catch (e) { try { return window.localStorage; } catch (e2) { return null; } } })(); var O = param('openid'), out = false; try { out = !!O && LS.getItem(KEY) === O; } catch (e) {} var root = document.documentElement; if (out) root.classList.add('mb-out'); var G = window.mbGate = { out: out, openid: O, set: function (v) { G.out = !!v; try { if (v) LS.setItem(KEY, O); else LS.removeItem(KEY); } catch (e) {} root.classList.toggle('mb-out', !!v); }, login: function () { if (window.wxAuth && window.wxAuth.requestProfile) { window.wxAuth.requestProfile(); return; } /* 广场 / 专题页没引共享授权库:回首页「我的」,那里有「点击登录」 */ var home = me ? new URL('../', me).pathname : '../'; location.href = home + '?go=me' + location.hash; }, /* 退出状态下拦一次操作:返回 true = 已拦 */ need: function (e) { if (!G.out) return false; if (e) { e.preventDefault(); e.stopPropagation(); if (e.stopImmediatePropagation) e.stopImmediatePropagation(); } prompt(); return true; } }; /* 和服务器对一次(在别的应用重新登录过 / 在别处退出过,本机标记会过期) */ if (O) { /* 11-07 从 taidong.douba.top 进来时那边没有 auth/status(404)→ 非 mp 域名改查 mp 绝对地址(mp 已允许跨域 *,体重会话 0c1f342e 提) */ var ST = location.hostname === 'mp.yizhezhe.com' ? '' : 'https://mp.yizhezhe.com'; fetch(ST + '/api/mp/public/auth/status?openid=' + encodeURIComponent(O)) /* 只读,查不到不建记录 */ .then(function (r) { return r.ok ? r.json() : null; }) .then(function (j) { if (!j || j.code !== 200 || !j.result) return; var lo = !!j.result.loggedOut; if (lo === G.out) return; G.set(lo); /* 防循环:10 秒内只重载一次 */ var last = 0; try { last = +sessionStorage.getItem(RL) || 0; } catch (e) {} if (Date.now() - last < 10000) return; try { sessionStorage.setItem(RL, String(Date.now())); } catch (e) {} location.reload(); }) .catch(function () {}); } /* 弹窗:自带样式,夜间模式跟着变 */ var box = null; function prompt() { if (!box) { var st = document.createElement('style'); st.textContent = '.mbg-m{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;background:rgba(40,25,30,.42);opacity:0;transition:opacity .18s}' + '.mbg-m.on{opacity:1}' + '.mbg-c{width:min(300px,82vw);background:#fff;border-radius:20px;padding:24px 20px 18px;text-align:center;box-shadow:0 18px 50px rgba(60,20,30,.25);font-family:inherit}' + '.mbg-c h3{margin:0 0 8px;font-size:18px;color:#3B2A2A}' + '.mbg-c p{margin:0 0 18px;font-size:14px;line-height:1.6;color:#8A7470}' + '.mbg-b{display:flex;gap:10px}.mbg-b button{flex:1;display:flex;align-items:center;justify-content:center;padding:0;text-align:center;height:42px;border-radius:21px;border:0;font-size:15px;font-weight:600;font-family:inherit}' + '.mbg-x{background:#F6EEEC;color:#8A7470}.mbg-ok{background:linear-gradient(135deg,#FF8A7A,#F25F6B);color:#fff}' + 'html.night .mbg-c{background:#2D2730}html.night .mbg-c h3{color:#F4EAEF}html.night .mbg-c p{color:#B9A9AF}html.night .mbg-x{background:#3A3239;color:#C9B9BE}'; document.head.appendChild(st); box = document.createElement('div'); box.className = 'mbg-m'; box.setAttribute('role', 'dialog'); box.setAttribute('aria-modal', 'true'); box.innerHTML = '

' + (window.MB_GATE_TITLE || '登录后才能使用') + '

' + (window.MB_GATE_TEXT || '你已退出登录。登录后就能记录、评论和点赞,之前的孕期资料和记录都还在。') + '

' + '
'; box.addEventListener('click', function (e) { if (e.target.closest('.mbg-ok')) { hide(); G.login(); return; } if (e.target === box || e.target.closest('.mbg-x')) hide(); }); } if (!box.parentNode) document.body.appendChild(box); box.style.display = 'flex'; requestAnimationFrame(function () { box.classList.add('on'); }); } function hide() { if (!box) return; box.classList.remove('on'); setTimeout(function () { box.style.display = 'none'; }, 180); } /* 要拦的按钮(各页面的写操作) */ var REC = ['taidong', 'yunqitizhong', 'yun', 'yunqixuetang', 'gongsuopinlv', 'taierguzhong', 'chanjianrili', 'bushui'] .map(function (t) { return '#htGrid .tg[data-tool="' + t + '"]'; }).join(','); var SEL = { home: REC + ',#vitals .vt-it,.tab-fab,.fab,.fab-w,#htEdit,.tg-add,#homeExchMod,#meExchCard,#meExchGo,#meExchOrders,#bbBanner,[data-modal="modalProfile"],[data-modal="modalWhisper"],#bfMe,.preg-card,#whSay,[data-hug],[data-wcl],[data-wrp],#wcsSend', plaza: '#blk,#bfv,#csend,#cpic,#cemo,#cpOk,[data-like],[data-cl],[data-rk],#cmgo,[data-write],[data-mywrite],#tabRec', topic: '.tc-lk,.tc-go,.tc-in .pic-b,.tc-in .emo-b' }; var IN = { home: '#wcsIn', plaza: '#cin', topic: '.tc-in textarea' }; function page() { if (document.getElementById('homeBody')) return 'home'; if (document.getElementById('wf')) return 'plaza'; if (/\/topic\//.test(location.pathname)) return 'topic'; return 'other'; } /* 其他应用(数胎动、体重……)引本文件时自己指定: window.MB_GATE_SEL = '.save-btn,.add-record'; 点了要拦的按钮(CSS 选择器) window.MB_GATE_IN = '.note-input'; 一聚焦就提示的输入框 window.MB_GATE_TEXT = '登录后就能兑换好物…'; 弹窗正文(可选,标题用 MB_GATE_TITLE) 或在自己的提交函数里:if (window.mbGate && mbGate.need()) return; */ function selFor(map, cus) { return window[cus] || map[page()] || ''; } document.addEventListener('click', function (e) { if (!G.out || !e.target.closest) return; var s = selFor(SEL, 'MB_GATE_SEL'); if (s && e.target.closest(s)) G.need(e); }, true); /* 评论输入框:一点进去就提示(别让人打完一段字才发现发不出去) */ document.addEventListener('focusin', function (e) { if (!G.out || !e.target.matches) return; var s = selFor(IN, 'MB_GATE_IN'); if (s && e.target.matches(s)) { e.target.blur(); prompt(); } }, true); })();