Files
SoonDesign/frontend-web/js/common/portal-topbar.js
T
24kycj ebe191b06d 永久会员与模板库后台化:预览门控、轻量首页与 Admin CRUD
- 会员改为永久激活方案;云端文件不再拦截非会员;预览弹窗内导出/打印才校验
- 首页最近文件支持本地记录,登录后与云端合并;移除独立会员页与订阅页
- 模板库入库管理:soon_templates 表、Admin 上传 CRUD、/templates 轻量列表与按需下载

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 23:52:56 +08:00

105 lines
4.5 KiB
JavaScript

(function () {
'use strict';
var STANDARD_LINKS = [
{ id: 'home', href: 'index.web.html', label: '设计首页', show: 'always' },
{ id: 'admin', href: 'admin/index.html', label: '管理', show: 'admin', elId: 'auth_admin' },
];
function esc(s) {
if (s == null) return '';
return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}
function authBlock() {
return '<div class="soon-portal-topbar__guest" id="auth_guest">' +
'<a href="login.web.html" id="auth_login" class="soon-btn soon-btn--sm">登录</a>' +
'<a href="register.web.html" id="auth_register" class="soon-btn soon-btn--sm soon-btn--ghost">注册</a>' +
'</div>' +
'<div class="soon-portal-topbar__account" id="auth_account" style="display:none">' +
'<span id="auth_avatar" class="soon-portal-avatar" style="display:none"></span>' +
'<span id="auth_identity" class="soon-portal-identity" style="display:none"></span>' +
'</div>' +
'<nav class="soon-portal-topbar__session" id="auth_session" style="display:none" aria-label="账户">' +
'<a href="admin/index.html" id="auth_admin" class="soon-portal-topbar__link" style="display:none">管理</a>' +
'<a href="#" id="auth_logout" class="soon-portal-topbar__link" style="display:none">退出</a>' +
'</nav>';
}
function renderLinks(links, active) {
return links.map(function (lnk) {
if (lnk.id === 'admin') return '';
var cls = 'soon-portal-topbar__link' + (active === lnk.id ? ' is-active' : '');
return '<a href="' + esc(lnk.href) + '" class="' + cls + '">' + esc(lnk.label) + '</a>';
}).join('');
}
function toolsBlock(lang, linksHtml) {
return '<div class="soon-portal-topbar__tools">' +
lang +
(linksHtml ? '<nav class="soon-portal-topbar__links" aria-label="导航">' + linksHtml + '</nav>' : '') +
'</div>';
}
/**
* @param {object} opts
* @param {string} [opts.variant] standard | auth | design
* @param {string} [opts.active] home
* @param {string} [opts.extraClass]
*/
function html(opts) {
opts = opts || {};
var base = opts.assetBase || '../';
var variant = opts.variant || 'standard';
var extraCls = opts.extraClass ? ' ' + opts.extraClass : '';
if (variant === 'auth') {
return '<header class="soon-portal-topbar soon-auth-topbar' + extraCls + '">' +
'<div class="soon-portal-topbar__brand"><a href="index.web.html">' +
'<img src="' + esc(base) + 'assets/images/logo.png" alt=""><span>SoonDesign</span></a></div>' +
'<div class="soon-portal-topbar__actions">' +
toolsBlock('', '<a href="index.web.html" class="soon-portal-topbar__link">返回首页</a>') +
'</div></header>';
}
if (variant === 'design') {
return '<header class="soon-portal-topbar soon-design-portal-bar' + extraCls + '">' +
'<div class="soon-portal-topbar__brand"><a href="index.web.html">' +
'<img src="' + esc(base) + 'assets/images/logo.png" alt=""><span>SoonDesign</span></a></div>' +
'<div class="soon-portal-topbar__actions">' +
toolsBlock('', '<a href="index.web.html" class="soon-portal-topbar__link">返回首页</a>') +
authBlock() + '</div></header>';
}
var active = opts.active || '';
var showLang = opts.showLanguage !== false;
var links = opts.links || STANDARD_LINKS;
var lang = showLang
? '<select id="language_select" class="soon-portal-topbar__lang" aria-label="语言">' +
'<option value="zh">中文-简体</option><option value="ozh">中文-繁體</option><option value="en">English</option></select>'
: '';
return '<header class="soon-portal-topbar' + extraCls + '">' +
'<div class="soon-portal-topbar__brand"><a href="' + esc(opts.brandHref || 'index.web.html') + '">' +
'<img src="' + esc(base) + 'assets/images/logo.png" alt=""><span>SoonDesign</span></a></div>' +
'<div class="soon-portal-topbar__actions">' +
toolsBlock(lang, renderLinks(links, active)) +
authBlock() + '</div></header>';
}
function mount(selector, opts) {
var el = typeof selector === 'string' ? document.querySelector(selector) : selector;
if (!el) return;
el.innerHTML = html(opts);
if (opts && opts.initLang !== false) {
var sel = document.getElementById('language_select');
if (sel) {
sel.value = localStorage.getItem('lang') || 'zh';
sel.onchange = function () { localStorage.setItem('lang', sel.value); };
}
}
}
window.SoonPortalTopbar = { html: html, mount: mount };
})();