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
This commit is contained in:
2026-08-05 14:17:37 +08:00
parent b53e71c85d
commit 7a2e45e7c4
21 changed files with 1224 additions and 204 deletions
+9 -8
View File
@@ -1,14 +1,15 @@
/* iAOP 配置化驾驶舱样式(issue #131 / PRD 5.5)。
* 调色全部由 plan JSON 的 themeTokens 注入(--cockpit-* CSS 变量),
* 这里只写默认值(= #51 THEME_TOKENS 的 dark 方案),切主题 = 换一套变量。 */
* 这里只写默认值(= #51 THEME_TOKENS 的 light 方案,Ant Design 5 色板,
* 2026-08 全站 Ant Design Pro 风格重构),切主题 = 换一套变量。 */
:root {
--cockpit-bg: #0b1220;
--cockpit-surface: #13203a;
--cockpit-fg: #e6edf6;
--cockpit-fg-muted: #8aa0bd;
--cockpit-accent: #18d3c8;
--cockpit-warn: #f5a623;
--cockpit-grid-line: rgba(255,255,255,0.06);
--cockpit-bg: #f0f2f5;
--cockpit-surface: #ffffff;
--cockpit-fg: rgba(0, 0, 0, 0.88);
--cockpit-fg-muted: rgba(0, 0, 0, 0.45);
--cockpit-accent: #1677ff;
--cockpit-warn: #faad14;
--cockpit-grid-line: rgba(5, 5, 5, 0.06);
}
* { box-sizing: border-box; }
+8 -6
View File
@@ -20,11 +20,12 @@ var TEMPLATES = [
{ id: "ti-cl4", name: "海绵钛(Ti)", plan: "plans/ti-cl4.json", alarmPlan: "plans/alarm_panel.ti.json" },
{ id: "resin", name: "吸附树脂", plan: "plans/resin.json", alarmPlan: null }
];
// 树脂模板暂无告警面板配置资产时的兜底三级配色(语义同 alarm_panel.ti.yaml)
// 树脂模板暂无告警面板配置资产时的兜底三级配色(语义同 alarm_panel.ti.yaml,
// 2026-08 对齐 Ant Design 5 色板)
var FALLBACK_SEVERITY_STYLES = {
P0: { fg: "#ff3b30", bg: "rgba(255,59,48,0.12)", border: "#ff3b30" },
P1: { fg: "#f5a623", bg: "rgba(245,166,35,0.12)", border: "#f5a623" },
P2: { fg: "#3aa0ff", bg: "rgba(58,160,255,0.10)" }
P0: { fg: "#ff4d4f", bg: "rgba(255,77,79,0.10)", border: "#ff4d4f" },
P1: { fg: "#faad14", bg: "rgba(250,173,20,0.10)", border: "#faad14" },
P2: { fg: "#1677ff", bg: "rgba(22,119,255,0.08)" }
};
var state = {
@@ -193,7 +194,7 @@ var ComponentRegistry = {
var min = Math.min.apply(null, points), max = Math.max.apply(null, points);
var span = (max - min) || 1;
ctx.strokeStyle = getComputedStyle(document.documentElement)
.getPropertyValue("--cockpit-accent").trim() || "#18d3c8";
.getPropertyValue("--cockpit-accent").trim() || "#1677ff";
ctx.lineWidth = 1.5;
ctx.beginPath();
points.forEach(function (p, idx) {
@@ -202,7 +203,8 @@ var ComponentRegistry = {
if (idx === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
});
ctx.stroke();
ctx.fillStyle = "#8aa0bd";
ctx.fillStyle = getComputedStyle(document.documentElement)
.getPropertyValue("--cockpit-fg-muted").trim() || "rgba(0,0,0,0.45)";
ctx.font = "11px sans-serif";
ctx.fillText(max.toFixed(1), 4, 12);
ctx.fillText(min.toFixed(1), 4, h - 4);
+9 -1
View File
@@ -5,8 +5,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>iAOP 配置化驾驶舱</title>
<link rel="stylesheet" href="cockpit.css">
<link rel="stylesheet" href="../shared/pro.css">
</head>
<body>
<body data-pro-title="配置化驾驶舱">
<!-- iAOP 配置化驾驶舱(issue #131 / PRD 5.5「⑤ 配置化驾驶舱」)
纯静态 HTML + 原生 JS(无构建链)。页面只消费 plans/*.json 渲染计划,
切换行业模板 = 加载另一份 plan JSON,前端代码零改动。 -->
@@ -24,6 +25,13 @@
<span id="plan-meta"></span>
<span>布局 Schema: iAOP-cockpit-layout-v1 · 首屏静态资源本地化,目标 ≤ 2s(PRD 9)</span>
</footer>
<script src="../auth/user_store.js"></script>
<script src="../shared/session.js"></script>
<script>
// 登录守卫(PRD 8.2):未登录跳登录页,登录后回跳本页(后端优先/本地降级)
IAOP_SESSION.requireLoginElseRedirect("../auth/login.html");
</script>
<script src="../shared/pro-header.js"></script>
<script src="cockpit.js"></script>
</body>
</html>
+8 -8
View File
@@ -2,20 +2,20 @@
"subscribe": "alarm_stream",
"severityStyles": {
"P0": {
"fg": "#ff3b30",
"bg": "rgba(255,59,48,0.12)",
"fg": "#ff4d4f",
"bg": "rgba(255,77,79,0.10)",
"icon": "alert-octagon",
"border": "#ff3b30"
"border": "#ff4d4f"
},
"P1": {
"fg": "#f5a623",
"bg": "rgba(245,166,35,0.12)",
"fg": "#faad14",
"bg": "rgba(250,173,20,0.10)",
"icon": "alert-triangle",
"border": "#f5a623"
"border": "#faad14"
},
"P2": {
"fg": "#3aa0ff",
"bg": "rgba(58,160,255,0.10)",
"fg": "#1677ff",
"bg": "rgba(22,119,255,0.08)",
"icon": "info"
}
},
+8 -8
View File
@@ -1,15 +1,15 @@
{
"$schema": "iAOP-cockpit-layout-v1",
"title": "吸附树脂车间驾驶舱",
"theme": "dark",
"theme": "light",
"themeTokens": {
"--cockpit-bg": "#0b1220",
"--cockpit-surface": "#13203a",
"--cockpit-fg": "#e6edf6",
"--cockpit-fg-muted": "#8aa0bd",
"--cockpit-accent": "#18d3c8",
"--cockpit-warn": "#f5a623",
"--cockpit-grid-line": "rgba(255,255,255,0.06)"
"--cockpit-bg": "#f0f2f5",
"--cockpit-surface": "#ffffff",
"--cockpit-fg": "rgba(0,0,0,0.88)",
"--cockpit-fg-muted": "rgba(0,0,0,0.45)",
"--cockpit-accent": "#1677ff",
"--cockpit-warn": "#faad14",
"--cockpit-grid-line": "rgba(5,5,5,0.06)"
},
"grid": {
"columns": 12
+8 -8
View File
@@ -1,15 +1,15 @@
{
"$schema": "iAOP-cockpit-layout-v1",
"title": "海绵钛车间驾驶舱",
"theme": "dark",
"theme": "light",
"themeTokens": {
"--cockpit-bg": "#0b1220",
"--cockpit-surface": "#13203a",
"--cockpit-fg": "#e6edf6",
"--cockpit-fg-muted": "#8aa0bd",
"--cockpit-accent": "#18d3c8",
"--cockpit-warn": "#f5a623",
"--cockpit-grid-line": "rgba(255,255,255,0.06)"
"--cockpit-bg": "#f0f2f5",
"--cockpit-surface": "#ffffff",
"--cockpit-fg": "rgba(0,0,0,0.88)",
"--cockpit-fg-muted": "rgba(0,0,0,0.45)",
"--cockpit-accent": "#1677ff",
"--cockpit-warn": "#faad14",
"--cockpit-grid-line": "rgba(5,5,5,0.06)"
},
"grid": {
"columns": 12