v26110605 退出登录后只看不写:js/login-gate.js(首页/广场/专题页共用),首页按访客显示,记录/评论/点赞/收藏/投稿/兑换/改档案弹登录提示;退出确认文案更新

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
deploy
2026-11-07 00:27:34 +00:00
parent 19662753d9
commit 2f2a0a5029
5 changed files with 146 additions and 11 deletions

121
js/login-gate.js Normal file
View File

@@ -0,0 +1,121 @@
/* 退出登录后「只看不写」(2026-11-07 用户定):
· 退出登录 ≠ 从没授权过:后端 user_auths.loggedOut 只在点了「退出登录」时置位,重新授权清掉;
从没授权过的新用户不受影响。
· 本机标记 localStorage mmbox.out.v1 = 退出时的 openid(首屏立刻知道,不等接口);
每次进页面再和服务器(auth/profile 的 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]) : '';
}
var O = param('openid'), out = false;
try { out = !!O && localStorage.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) localStorage.setItem(KEY, O); else localStorage.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) {
fetch('/api/mp/public/auth/profile?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;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 = '<div class="mbg-c"><h3>登录后才能使用</h3><p>你已退出登录。登录后就能记录、评论和点赞,之前的孕期资料和记录都还在。</p>' +
'<div class="mbg-b"><button type="button" class="mbg-x">再看看</button><button type="button" class="mbg-ok">去登录</button></div></div>';
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"]',
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 = { plaza: '#cin', topic: '.tc-in textarea' };
function page() {
if (document.getElementById('homeBody')) return 'home';
if (document.getElementById('wf')) return 'plaza';
return 'topic';
}
document.addEventListener('click', function (e) {
if (!G.out || !e.target.closest) return;
var s = SEL[page()];
if (s && e.target.closest(s)) G.need(e);
}, true);
/* 评论输入框:一点进去就提示(别让人打完一段字才发现发不出去) */
document.addEventListener('focusin', function (e) {
if (!G.out || !e.target.matches) return;
var s = IN[page()];
if (s && e.target.matches(s)) { e.target.blur(); prompt(); }
}, true);
})();