Files
jiu/web/assets/nav.js
T
wangjia c7de728c18 feat(site): 导航登录态下拉菜单 + 个人信息/退出登录页,登录不再直跳 App
- 导航「进入系统 · 名字」改为下拉:个人信息 / 进入系统 / 退出登录,导航可重入刷新(window.jiuNavRender)
- 新增 /profile/(账号 / 门店 / 授权三卡,authFetch 实时拉取)与 /logout/(撤销会话 + 清本地凭证)
- 登录成功默认落地 /profile/(?next= 站内白名单不变),不再直跳 /app/
- auth.js 增加 jiuAuth.clear();site.css 含本轮下拉 / profile / 特惠卡样式

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-03 22:24:55 +08:00

91 lines
3.5 KiB
JavaScript

/* 官网导航交互:汉堡菜单 + 登录态感知(Web 版 App 与官网同域时,
localStorage['flutter.*'] 有登录信息 → CTA 变「进入系统 · 姓名」下拉菜单)。
renderAuth 可重复调用(暴露为 window.jiuNavRender,退出登录页清凭证后刷新导航)。零依赖。 */
(function () {
function getAuthUser() {
if (!window.jiuAuth || !jiuAuth.loggedIn()) return null;
var username = jiuAuth.get('username');
if (!username) return null;
return {
username: username,
realName: jiuAuth.get('real_name') || '',
shopNo: jiuAuth.get('shop_no') || '',
};
}
// 汉堡菜单
var burger = document.getElementById('nav-burger');
var mobile = document.getElementById('nav-mobile-menu');
if (burger && mobile) {
burger.addEventListener('click', function (e) {
e.stopPropagation();
var open = mobile.classList.toggle('open');
burger.setAttribute('aria-expanded', open ? 'true' : 'false');
});
document.addEventListener('click', function (e) {
if (!mobile.contains(e.target) && e.target !== burger) {
mobile.classList.remove('open');
}
});
}
// 登录态渲染:桌面 CTA + 移动菜单(data-auth 标记的项按状态重建)
var MENU_ITEMS =
'<a href="/profile/">个人信息</a>' +
'<a href="/app/">进入系统</a>' +
'<div class="sep"></div>' +
'<a class="danger" href="/logout/">退出登录</a>';
function renderAuth() {
var user = getAuthUser();
var cta = document.getElementById('nav-cta');
if (cta) {
if (user) {
cta.innerHTML =
'<div class="nav-user" id="nav-user">' +
'<button class="btn primary nav-user-btn" id="nav-user-btn" aria-haspopup="true" aria-expanded="false">' +
'进入系统 · ' + (user.realName || user.username).replace(/[<>&"]/g, '') +
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>' +
'</button>' +
'<div class="nav-menu">' + MENU_ITEMS + '</div>' +
'</div>';
} else {
cta.innerHTML =
'<a class="btn ghost" href="/login/">登录</a>' +
'<a class="btn primary" href="/register/">注册门店</a>';
}
}
if (mobile) {
Array.prototype.slice.call(mobile.querySelectorAll('[data-auth]')).forEach(function (el) { el.remove(); });
var frag = document.createElement('div');
frag.innerHTML = user
? MENU_ITEMS
: '<a href="/register/">注册门店</a><a href="/login/">登录</a>';
Array.prototype.slice.call(frag.children).forEach(function (el) {
if (el.tagName === 'A') { el.setAttribute('data-auth', ''); mobile.appendChild(el); }
});
}
}
// 下拉开合(事件委托,renderAuth 重建 DOM 后依然有效)
document.addEventListener('click', function (e) {
var wrap = document.getElementById('nav-user');
if (!wrap) return;
var btn = document.getElementById('nav-user-btn');
if (btn && btn.contains(e.target)) {
var open = wrap.classList.toggle('open');
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
} else if (!wrap.contains(e.target)) {
wrap.classList.remove('open');
}
});
document.addEventListener('keydown', function (e) {
if (e.key !== 'Escape') return;
var wrap = document.getElementById('nav-user');
if (wrap) wrap.classList.remove('open');
});
renderAuth();
window.jiuNavRender = renderAuth;
})();