Files
iAOP/web/shared/pro-header.js
T
bot_dev1 7a2e45e7c4 feat: 全站 Ant Design Pro 风格重构 + 登录守卫与角色门户(issue #131/#134)
- 新增 web/shared:pro.css(AntD 5 设计系统,旧 CSS 变量统一映射 AntD 色板)、
  session.js(后端优先+本地账号降级双轨会话,IAOP_AUTH 兼容层)、
  pro-header.js(全站统一 Pro 导航条:logo/页题/用户角色 Tag/退出)
- 门户 web/index.html:未登录跳登录页(next 回跳),登录后按角色过滤
  可见模块(readonly→驾驶舱/助手/移动端;engineer→+配置台;admin→全部)
- 登录页 auth/login.html 重写为 Ant Design Pro 风格,本地降级模式自动
  播种演示账号(admin/engineer/viewer),保留 OIDC SSO 双轨入口
- user_store.js 新增 verify() + seedDefaults() 默认账号播种
- 六模块页统一接入 pro.css + 统一导航条 + 登录守卫(PRD 8.2)
- 驾驶舱主题 dark→light(Ant Design 5 色板):renderer.py THEME_TOKENS、
  ti-cl4/resin 模板 theme、告警三级配色对齐 AntD(P0 #ff4d4f/P1 #faad14/
  P2 #1677ff),渲染计划已重编(build_plans.py)
- 验证:core/cockpit 86 单测通过;JS 语法检查通过;静态冒烟全 200
2026-08-05 14:17:37 +08:00

90 lines
3.2 KiB
JavaScript

/* iAOP 全站统一导航条(Ant Design Pro 风格重构,2026-08)。
*
* 在页面 <body> 末尾引入即可自动注入一条 48px 白色 Pro 导航条
* (logo + 平台名 + 当前页标题 + 门户入口 + 当前用户/角色 Tag + 退出登录),
* 各模块页视觉框架统一。样式在 pro.css 的 .pro-header 系列。
*
* 用法:
* <body data-pro-title="配置化驾驶舱" data-pro-home="../index.html">
* ...
* <script src="../auth/user_store.js"></script>
* <script src="../shared/session.js"></script>
* <script src="../shared/pro-header.js"></script>
*
* data-pro-title:当前页标题(显示在平台名右侧,竖线分隔)。
* data-pro-home :门户(首页)相对路径,缺省 ../index.html。
* data-pro-login:登录页相对路径(退出后跳转),缺省 ../auth/login.html。
*
* 本组件不强制登录(守卫由页面或 IAOP_SESSION.requireLoginElseRedirect 负责);
* 已登录时显示用户徽章,未登录时用户区显示「未登录」。
*/
"use strict";
(function () {
function el(tag, cls, text) {
var n = document.createElement(tag);
if (cls) n.className = cls;
if (text !== undefined) n.textContent = text;
return n;
}
function build() {
var body = document.body;
if (!body || document.querySelector(".pro-header")) return;
var title = body.getAttribute("data-pro-title") || document.title || "";
var home = body.getAttribute("data-pro-home") || "../index.html";
var loginUrl = body.getAttribute("data-pro-login") || "../auth/login.html";
var bar = el("div", "pro-header");
var logo = el("a", "pro-logo");
logo.href = home;
logo.appendChild(el("span", "pro-logo-badge", "iA"));
logo.appendChild(el("span", "pro-logo-text", "iAOP 云美工业AI优化平台"));
bar.appendChild(logo);
if (title) bar.appendChild(el("span", "pro-page-title", title));
var right = el("div", "pro-header-right");
var userBox = el("span", "pro-user");
right.appendChild(userBox);
var homeLink = el("a", "pro-nav-link", "门户");
homeLink.href = home;
right.appendChild(homeLink);
var logoutBtn = el("button", "pro-logout", "退出");
logoutBtn.type = "button";
logoutBtn.addEventListener("click", function () {
IAOP_SESSION.logout(loginUrl);
});
right.appendChild(logoutBtn);
bar.appendChild(right);
body.insertBefore(bar, body.firstChild);
// 异步填充当前用户(后端优先、本地降级由 session.js 内部处理)
IAOP_SESSION.currentUser().then(function (u) {
userBox.innerHTML = "";
if (!u) {
userBox.appendChild(el("span", "pro-tag pro-tag-default", "未登录"));
return;
}
var avatar = el("span", "pro-avatar",
(u.username || "?").slice(0, 1).toUpperCase());
userBox.appendChild(avatar);
userBox.appendChild(el("span", null, u.username));
var color = IAOP_SESSION.ROLE_TAG_COLORS[u.role] || "default";
var label = IAOP_SESSION.ROLE_LABELS[u.role] || u.role;
userBox.appendChild(el("span", "pro-tag pro-tag-" + color, label));
});
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", build);
} else {
build();
}
})();