Files
xiaobai-review/xiaobai-datahub/admin/styles.css
T
fab9a70451 feat(HEL-539): 数据中枢 admin 按第八版「星港中枢」重做星体中枢
- styles.css:舞台改为全幅星空(100vw × 100vh-52px,去卡片边框/圆角/外边距),
  cabin 定位随安全盒 x0 同步(24px),响应式断点对齐 1024;清理未使用/格式错误
  的旧版画布配色变量(--face/--edge/--slab/--ring/--chan1-4),新增星港中枢
  文档留存 token(--star-*/--orbit-line/--sat1-4,与 app.js PAL 对应)。
- app.js:Stage/StaticShell 模块整体重写为 Canvas 2D 自写透视投影的星体+双轨+
  四卫星连续舞台(不用 CSS 3D/SVG/新依赖);安全盒/缩放严格按 HEL-538 复审公式
  x0=cabinW+24,x1=W-24,y0=64,y1=H-118 与 S=min(...) 计算,1440/1280/1024 三档
  构造性不裁切;卫星径向锚定 14px + 安全盒硬钳制,双灯/去向端文字同样钳制且
  双灯永不隐藏;六幕改为固定投影 + 内容层参数(不再用自由 3D 摄像机),任务环/
  数据集卡片/审计尾迹增加与卫星芯片的避让逻辑防遮挡;A2 灯引擎/真实事件轮询/
  reduced-motion 监听/后台暂停逻辑保持原样复用,未引入 demo 钩子。
- 卫星轨道配对采用 HEL-537 已确认样图口径(tushare/eastmoney 内轨,
  tencent/ifind 外轨),逐源相位/角速度/方向沿用 HEL-536 §3 数值,已在评论中
  向总管说明与 HEL-536 文字表述的差异。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-09-13 11:58:32 +08:00

279 lines
15 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* xiaobai-datahub 数据中枢后台 —— 第八版「星港中枢」
整页星空 + 中央星体 + 四颗数据源卫星的连续舞台,六幕滚动换场。
统一动效 Token:进入/退出用强 ease-out,屏内移动用强 ease-in-out,持续流动用 linear。
禁止 ease-in、禁止 transition:all —— 全文件遵守。 */
:root {
color-scheme: light;
--bar-h: 52px;
--radius: 14px;
--pad: 16px;
--font-cn: "Segoe UI", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
--font-mono: "JetBrains Mono", "DejaVu Sans Mono", Consolas, monospace;
--ease-out: cubic-bezier(.22, 1, .36, 1);
--ease-in-out: cubic-bezier(.65, 0, .35, 1);
--ease-linear: linear;
/* day (default) */
--bg0: #EDF0F7;
--bg1: #F8FAFF;
--surface: #ffffff;
--text: #1B2547;
--muted: #5B6785;
--faint: #93A0BD;
--line: rgba(47, 99, 214, .18);
--action: #2F63D6;
--cyan: #0A9C93;
--amber: #B97A0E;
--danger: #D64F4F;
--ok: #1E9E6A;
--warn: #B97A0E;
--glass: rgba(255, 255, 255, .82);
--chip: rgba(47, 99, 214, .08);
/* 星港中枢 · 画布调色(与 app.js PAL.day 保持一致,仅作文档留存) */
--star-hi: #FFFFFF; --star-a: #EAF6FF; --star-b: #A9CCF0; --star-c: #5488C4; --star-d: #2E5A94;
--orbit-line: rgba(90, 120, 180, .40);
--sat1: #3997B4; --sat2: #BF873F; --sat3: #537EBF; --sat4: #BF525F;
}
:root[data-theme="night"] {
color-scheme: dark;
--bg0: #05080F;
--bg1: #0A1020;
--surface: #12172A;
--text: #E8EEFC;
--muted: #8B97B8;
--faint: #59637F;
--line: rgba(120, 160, 255, .16);
--action: #4A86FF;
--cyan: #2FD8CE;
--amber: #FFB84D;
--danger: #FF6B6B;
--ok: #3ED598;
--warn: #FFB84D;
--glass: rgba(13, 20, 38, .72);
--chip: rgba(74, 134, 255, .10);
/* 星港中枢 · 画布调色(与 app.js PAL.night 保持一致,仅作文档留存) */
--star-hi: #F2FAFF; --star-a: #C9E7FF; --star-b: #7FB2EA; --star-c: #3E6FAE; --star-d: #16305E;
--orbit-line: rgba(140, 180, 255, .22);
--sat1: #4CC9F0; --sat2: #FFB454; --sat3: #6FA8FF; --sat4: #FF6E7F;
}
* { box-sizing: border-box; }
html, body { margin: 0; background: var(--bg0); color: var(--text); font-family: var(--font-cn); }
body { overflow-x: hidden; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
.error { color: var(--danger); }
.ok { color: var(--ok); }
.warn { color: var(--warn); }
.fail { color: var(--danger); }
/* ---------- 登录 / 改密(未进入舞台的前置流程) ---------- */
.auth-panel {
max-width: 420px; margin: 12vh auto; padding: 30px 32px; border-radius: var(--radius);
background: var(--glass); border: 1px solid var(--line); backdrop-filter: blur(14px);
box-shadow: 0 30px 70px -32px rgba(20, 30, 60, .35);
}
.auth-panel h1 { margin: 0 0 6px; font-size: 21px; }
.auth-panel label { display: block; margin: 12px 0; font-size: 13px; color: var(--muted); }
.auth-panel input {
width: 100%; margin-top: 6px; padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px;
background: var(--chip); color: var(--text); font-family: var(--font-cn);
}
.auth-panel input:focus { outline: 2px solid var(--action); outline-offset: 1px; }
.auth-panel .badge-sim { display: inline-block; margin-bottom: 10px; }
button { font-family: var(--font-cn); cursor: pointer; }
.btn, button.primary, .auth-panel button[type="submit"] {
background: linear-gradient(135deg, var(--action), var(--cyan)); color: #fff; border: 0; border-radius: 8px;
padding: 8px 16px; font-size: 13px; transition: transform .12s var(--ease-out), opacity .12s var(--ease-out);
}
.btn:active, button:active { transform: translateY(1px); }
.btn.ghost, button.ghost {
background: var(--chip); color: var(--text); border: 1px solid var(--line);
}
.btn.warn { background: transparent; color: var(--warn); border: 1px solid var(--warn); }
.btn.danger, button.danger { background: var(--danger); color: #fff; border: 0; }
.btn.pri { background: linear-gradient(135deg, var(--action), var(--cyan)); color: #fff; border: 0; }
.btn { padding: 6px 13px; border-radius: 8px; font-size: 12px; }
.badge-sim {
font-size: 11px; padding: 3px 10px; border-radius: 99px; letter-spacing: .1em;
color: var(--amber); border: 1px solid var(--amber); opacity: .85;
}
/* ---------- 通用表格 / 卡片(cabin、detail、reduced 三处共用同一来源) ---------- */
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
th, td { text-align: left; padding: 7px 6px; border-bottom: 1px dashed var(--line); vertical-align: top; }
th { color: var(--faint); font-weight: 500; font-size: 11px; letter-spacing: .04em; }
.pill { font-size: 12px; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--line); color: var(--muted); }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-bottom: 14px; }
.card { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; background: var(--chip); }
.card strong { font-size: 18px; }
.toolbar { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; align-items: center; }
.toolbar label { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.toolbar input { padding: 6px 9px; border: 1px solid var(--line); border-radius: 6px; background: var(--chip); color: var(--text); }
h2 { font-size: 16px; margin: 4px 0 10px; }
h3 { font-size: 13px; margin: 14px 0 6px; color: var(--muted); }
/* ---------- 顶部总控条 ---------- */
#topbar {
height: var(--bar-h); display: flex; align-items: center; gap: 14px; padding: 0 22px;
border-bottom: 1px solid var(--line); background: linear-gradient(180deg, var(--bg1), transparent);
backdrop-filter: blur(10px);
position: sticky; top: 0; z-index: 4;
}
#topbar .logo { font-weight: 700; font-size: 15px; letter-spacing: .04em; }
#topbar .logo em { font-style: normal; color: var(--cyan); }
#topbar .crumb { font-size: 12px; color: var(--faint); }
#topbar .spacer { flex: 1; }
#topbar .who { font-size: 12px; }
/* ---------- 全幅星空舞台(100vw × (100vh-52px),六幕连续场景) ----------
第八版取消卡片式舞台:星空即整页背景,无圆角、无边框、无外边距。
#track 的六段高幕(每段 130vh)在它身后正常参与文档流把页面撑高,
#stageWrap 用 sticky 钉在视口里,滚动时只有 #track 的高度被“划过”,
舞台本体在这段距离内始终可见、位置不变,直到 #track 撑出的空间耗尽才随之离场。
星系几何(星体/轨道/卫星/去向端/双灯)的安全盒与缩放公式见 app.js Stage.resize()。 */
#stageWrap {
flex: none; width: 100vw; height: calc(100vh - var(--bar-h)); min-height: 480px;
margin: 0; border-radius: 0; overflow: hidden; border: 0;
box-shadow: inset 0 0 160px rgba(0, 0, 0, .10);
position: sticky; top: var(--bar-h); z-index: 2;
}
#scene { position: absolute; inset: 0; width: 100%; height: 100%; display: block; cursor: crosshair; }
/* ---------- 控制舱:当前场景的关键数据与操作 ---------- */
#cabin {
position: absolute; left: 24px; top: 24px; width: 300px; z-index: 5; max-height: calc(100% - 48px);
overflow: auto; background: var(--glass); border: 1px solid var(--line); border-radius: 14px;
backdrop-filter: blur(14px); padding: 16px 18px;
transition: opacity .45s var(--ease-out), transform .45s var(--ease-out);
}
#cabin.hide { opacity: 0; transform: translateX(-14px); pointer-events: none; }
#cabin .eyebrow { font-size: 10px; letter-spacing: .22em; color: var(--cyan); margin-bottom: 6px; }
#cabin h2 { font-size: 18px; margin: 0 0 4px; }
#cabin .sub { font-size: 11.5px; color: var(--muted); line-height: 1.6; margin-bottom: 10px; }
#cabin .rows { display: flex; flex-direction: column; gap: 7px; margin-bottom: 4px; }
#cabin .row { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
#cabin .row b { color: var(--text); font-weight: 600; }
#cabin .row .fill { flex: 1; }
#cabin .dotlamp { width: 7px; height: 7px; border-radius: 99px; background: var(--ok); box-shadow: 0 0 8px var(--ok); flex: none; }
#cabin .dotlamp.warn { background: var(--warn); box-shadow: 0 0 8px var(--warn); }
#cabin .dotlamp.fail { background: var(--danger); box-shadow: 0 0 8px var(--danger); }
#cabin .actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
/* ---------- 底部章节轨(导航等同滚动跳转) ---------- */
#rail {
position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 5;
display: flex; gap: 6px; align-items: center; padding: 8px 12px; border-radius: 99px;
background: var(--glass); border: 1px solid var(--line); backdrop-filter: blur(14px);
}
#rail .stop {
display: flex; align-items: center; gap: 7px; padding: 5px 11px; border-radius: 99px; cursor: pointer;
font-size: 11.5px; color: var(--faint); background: transparent; border: 0;
transition: color .25s var(--ease-in-out), background .25s var(--ease-in-out);
font-family: var(--font-cn); white-space: nowrap;
}
#rail .stop i { width: 6px; height: 6px; border-radius: 99px; background: var(--faint); transition: background .25s var(--ease-in-out), box-shadow .25s var(--ease-in-out); display: inline-block; }
#rail .stop.on { color: var(--text); background: var(--chip); }
#rail .stop.on i { background: var(--cyan); box-shadow: 0 0 10px var(--cyan); }
#rail .sep { width: 12px; height: 1px; background: var(--line); }
/* ---------- 图例 ---------- */
#legend {
position: absolute; right: 22px; top: 22px; z-index: 5; font-size: 10.5px; color: var(--muted);
background: var(--glass); border: 1px solid var(--line); border-radius: 12px; padding: 10px 13px;
backdrop-filter: blur(14px); line-height: 1.9;
}
#legend .lampico { display: inline-block; width: 14px; height: 5px; border-radius: 99px; vertical-align: middle; margin-right: 6px; }
#legend .li-link { background: rgba(47, 216, 206, .5); box-shadow: 0 0 6px rgba(47, 216, 206, .6); }
#legend .li-act { background: var(--amber); box-shadow: 0 0 8px var(--amber); }
/* ---------- 详情面板:从端口/来源空间位置展开的功能抽屉 ---------- */
#detail {
position: absolute; z-index: 8; width: 360px; max-width: calc(100% - 40px); max-height: calc(100% - 40px);
overflow: auto; pointer-events: auto; background: var(--glass); border: 1px solid var(--line);
border-radius: 14px; backdrop-filter: blur(16px); padding: 16px 18px;
transition: transform .4s var(--ease-out), opacity .3s var(--ease-out);
box-shadow: 0 24px 60px -20px rgba(0, 0, 0, .45);
}
#detail.closed { transform: scale(.14); opacity: 0; pointer-events: none; }
#detail h3 { font-size: 14px; margin: 0 0 2px; color: var(--text); }
#detail .dsub { font-size: 10.5px; color: var(--faint); margin-bottom: 10px; letter-spacing: .04em; }
#detailClose {
position: absolute; right: 10px; top: 10px; width: 24px; height: 24px; border-radius: 8px;
border: 1px solid var(--line); background: transparent; color: var(--muted); cursor: pointer; font-size: 13px; line-height: 1;
}
#detail .dtag {
position: absolute; left: -7px; top: 26px; width: 14px; height: 14px; transform: rotate(45deg);
background: var(--glass); border-left: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
/* ---------- 滚动提示 ---------- */
#hint {
position: absolute; left: 50%; bottom: 100px; transform: translateX(-50%); z-index: 5;
font-size: 11px; letter-spacing: .3em; color: var(--faint); transition: opacity .5s var(--ease-out);
}
#hint.off { opacity: 0; }
/* 滚动章节占位:仅提供滚动行程,无可见内容 */
#track { position: relative; z-index: 1; pointer-events: none; }
#track section { height: 130vh; }
/* ---------- 危险操作 / 确认弹层,复用 dialog ---------- */
dialog { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--text); padding: 20px; }
/* ================================================================
减少动态效果(prefers-reduced-motion):舞台切换为六幕静态空间图 + 固定文字状态
信息与功能与动效版完全一致,只是去掉滚动镜头、旋转与闪烁。
================================================================ */
#staticShell { display: none; }
html.reduced #stageWrap, html.reduced #track, html.reduced #hint { display: none !important; }
html.reduced #staticShell { display: block; }
#staticNav {
display: flex; gap: 4px; padding: 8px var(--pad); border-bottom: 1px solid var(--line);
background: var(--surface); flex-wrap: wrap; position: sticky; top: 0; z-index: 3;
}
#staticNav button {
background: transparent; color: var(--muted); border: 0; padding: 7px 12px; border-radius: 8px; font-size: 13px;
}
#staticNav button.active { color: var(--action); font-weight: 600; background: var(--chip); }
.scene-static { padding: var(--pad); border-bottom: 1px solid var(--line); }
.scene-static .scene-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.scene-static .scene-head .eyebrow { font-size: 11px; letter-spacing: .18em; color: var(--cyan); }
.scene-static .diagram {
width: 100%; max-width: 620px; height: 190px; border-radius: 12px; border: 1px solid var(--line);
background: var(--chip); display: block; margin-bottom: 12px;
}
.scene-static .lamprow { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
.lampchip {
display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted);
border: 1px solid var(--line); border-radius: 999px; padding: 4px 10px; background: var(--chip);
}
.lampchip .lk, .lampchip .ac { width: 7px; height: 7px; border-radius: 99px; background: var(--faint); display: inline-block; }
.lampchip .lk.on { background: var(--cyan); box-shadow: 0 0 5px var(--cyan); }
.lampchip .ac.on { background: var(--amber); box-shadow: 0 0 6px var(--amber); }
.lampchip .ac.recent { outline: 1px solid var(--amber); transition: outline-color .8s var(--ease-out); }
/* ---------- 主内容区(main/reduced 内容容器统一样式,供动效版 detail 与静态版共用) ---------- */
main#page { padding: var(--pad); min-height: calc(100vh - 96px); background: var(--surface); }
/* ---------- 响应式:1440 / 1280 / 1024 三档桌面宽(须与 app.js cabinW 三档同步) ---------- */
@media (max-width: 1280px) {
#cabin { width: 260px; }
#detail { width: 320px; }
}
@media (max-width: 1024px) {
#cabin { width: 230px; padding: 13px 14px; }
#legend { display: none; }
}
/* ---------- 系统级兜底:即便 JS 未及时接管,也不留半成品动效 ---------- */
@media (prefers-reduced-motion: reduce) {
#stageWrap, #track, #hint { display: none !important; }
#staticShell { display: block !important; }
* { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}