ebe191b06d
- 会员改为永久激活方案;云端文件不再拦截非会员;预览弹窗内导出/打印才校验 - 首页最近文件支持本地记录,登录后与云端合并;移除独立会员页与订阅页 - 模板库入库管理:soon_templates 表、Admin 上传 CRUD、/templates 轻量列表与按需下载 Co-authored-by: Cursor <cursoragent@cursor.com>
105 lines
4.5 KiB
JavaScript
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, '&').replace(/</g, '<').replace(/"/g, '"');
|
|
}
|
|
|
|
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 };
|
|
})();
|