Files
xiaobai-review/xiaobai-datahub/admin/layouts/flowline.css
T
011ecc0d1a feat(HEL-546): 数据中枢 A/B/C 三方向落地为可用页面
- 基于第七版稳定基线(be647bb)重构 admin 前端为模块化架构:
  tokens.css(设计token唯一来源) + shared.css(公共组件) + core.js(状态/API/事件总线/轮询/路由)
  + main.js(入口) + layouts/{flowline,ledger,strata}.{css,js}(三方向独立布局)
  + layouts/shared.js(三方向共用数据视图与操作绑定)
- 三个页面(A装配线/B值班台账/C地层剖面)通过 ?layout= 查询参数独立可达、可刷新、可前进后退导航,
  共享登录态、真实后端数据(overview/sources/jobs/batches/datasets/audit)、错误处理与主题
- 六大板块(总览/数据源/调度任务/盘后发布/数据集/审计)在三个方向均可查看与操作(探测/触发/回滚/补数)
- 修正健康状态语义:CircuitBreaker closed/half_open/open 与适配器 ok/error/empty/unconfigured/unknown
  统一归一化为 ok/warn/error/unconfigured/unknown 供三方向一致展示
- 事件驱动动效:A 水平接力光梭、B 行级高亮+实时调用跑马灯、C 纵向贯穿光点+分层标记;
  统一使用 transform/opacity/WAAPI,避免 transition:all,支持 prefers-reduced-motion 静态降级
- 修复响应式布局在 1024/1280 断点因 CSS Grid 默认 min-width:auto 被内部宽表格撑爆轨道的问题
- 修复布局切换/前进后退时残留 setTimeout 回调在 unmount 后访问 null root 导致的报错(mounted 标志位+
  safeTimeout+统一清理定时器)
- 自测:Playwright 全断点(1440/1280/1024)x 双主题矩阵截图、90 次连续布局切换+前进后退压力测试无报错、
  探测/触发/回滚danger操作流程验证、reduced-motion 验证;后端 pytest 全量 133 用例通过,无回归
- 未改动:登录/鉴权契约、后端 API、'问天'冻结区、生产数据/权限

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-09-13 16:28:50 +08:00

98 lines
5.7 KiB
CSS

/* A · 装配线 Flowline —— 来源→加工→发布→审计 四工位水平因果链
只写这个布局独有的排布;颜色/组件规则一律来自 tokens.css + shared.css。 */
#fl-root { padding: var(--sp4); max-width: 1584px; margin: 0 auto; }
#fl-band { position: relative; padding: 14px 16px 18px; margin-bottom: 14px; overflow: hidden; }
#fl-band .lane-labels { display: flex; }
#fl-band .lane-labels span { flex: 1; }
#fl-wire { position: relative; height: 1px; background: var(--line); margin: 22px 0 18px; }
#fl-wire .chev { position: absolute; top: -8px; font-size: 13px; color: var(--t3); font-family: var(--font-mono); transform: translateX(-50%); }
#fl-lanes { display: grid; grid-template-columns: 2fr 1.15fr 1.05fr 0.85fr; gap: 14px; align-items: start; }
/* 防止内部宽表格用 min-width:auto 撑爆 1fr 轨道,参见 ledger.css 同类注释。 */
#fl-lanes > *, #fl-cols > * { min-width: 0; }
#fl-srcCards { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.fl-src-card { position: relative; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; overflow: hidden; }
.fl-src-card .row { display: flex; align-items: center; gap: 8px; }
.fl-src-card .name { font-size: 14px; font-weight: 600; color: var(--t1); }
.fl-src-card .role { font-size: 11px; color: var(--t3); }
.fl-src-card .grow { flex: 1; }
.fl-src-card .lat { font-size: 12px; color: var(--t2); }
.fl-src-card .cred { font-size: 11px; color: var(--t3); }
.fl-src-card .lamps { display: flex; align-items: center; gap: 4px; }
.fl-src-card .edge {
position: absolute; left: 0; top: 6px; bottom: 6px; width: 2px; background: var(--act);
border-radius: 2px; opacity: 0; transition: opacity var(--dur-ui) var(--ease-out);
}
.fl-src-card .edge.err { background: var(--error); }
.fl-station { padding: 12px 14px; min-height: 150px; position: relative; transition: box-shadow var(--dur-ui) var(--ease-out); }
.fl-station.pulse { box-shadow: 0 0 0 2px var(--action-soft) inset; }
.fl-station .hd { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.fl-station .hd .nm { font-size: 13px; font-weight: 600; color: var(--t1); }
.fl-station .hd .grow { flex: 1; }
.fl-station .task { font-size: 12px; color: var(--t2); margin-bottom: 8px; }
.fl-station .task b { color: var(--t1); font-weight: 600; }
.fl-pbar { position: relative; height: 4px; border-radius: 2px; background: var(--bg2); overflow: hidden; margin-bottom: 6px; }
.fl-pbar > i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--action); border-radius: 2px; transition: width var(--dur-ui) var(--ease-out); }
.fl-station .queue { font-size: 12px; color: var(--t2); margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.fl-miniruns { border-top: 1px solid var(--line-soft); padding-top: 6px; }
.fl-miniruns .mr { display: flex; gap: 8px; font-size: 11px; line-height: 1.7; }
.fl-miniruns .mr .id { color: var(--t3); width: 34px; }
.fl-miniruns .mr .why { color: var(--error); }
.fl-gate .bignum { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.fl-gate .bignum .n { font-size: var(--fs-hero); font-weight: 600; color: var(--t1); display: inline-block; transition: transform var(--dur-ui) var(--ease-out); }
.fl-gate .bignum .cap { font-size: 12px; color: var(--t3); }
.fl-gate .latest { font-size: 12px; color: var(--t2); margin-bottom: 10px; }
.fl-gate .valrow { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--t2); }
.fl-audit .al { font-size: 11px; line-height: 1.75; color: var(--t2); white-space: normal; word-break: break-all; }
.fl-audit .al .dim { color: var(--t3); }
.fl-audit .adiv { border-top: 1px solid var(--line-soft); margin: 6px 0; }
#fl-packet {
position: absolute; width: 34px; height: 3px; border-radius: 2px; background: var(--packet);
opacity: 0; pointer-events: none; z-index: 5; top: 0; left: 0;
}
#fl-cols { display: grid; grid-template-columns: 1.15fr 1.1fr 1fr; gap: 14px; }
.fl-col { padding: 12px 14px; }
.fl-col .sec-label { display: block; margin-bottom: 8px; }
.fl-col .sub-label { display: block; margin: 12px 0 4px; }
#fl-callsTable td.res-ok { color: var(--t2); }
#fl-callsTable td.res-err { color: var(--error); }
#fl-callsFoot { margin-top: 8px; font-size: 11px; color: var(--t3); border-top: 1px solid var(--line-soft); padding-top: 8px; }
.fl-newrow { transition: background var(--dur-ui) var(--ease-out); }
.fl-newrow.flashin { background: var(--alive-soft); }
.fl-jobrow { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line-soft); }
.fl-jobrow .jid { font-size: 12px; color: var(--t1); }
.fl-jobrow .jti { font-size: 12px; color: var(--t2); }
.fl-jobrow .jat { font-size: 11px; color: var(--t3); }
.fl-jobrow .grow { flex: 1; }
#fl-col3 .toolrow { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
#fl-col3 .toolrow input {
font-family: var(--font-mono); font-size: 12px; color: var(--t1); background: var(--bg2);
border: 1px solid var(--line); border-radius: var(--r-chip); padding: 5px 8px; width: 96px; outline: none;
}
.fl-anom { margin-top: 10px; }
tr.fl-rowflash td { transition: background var(--dur-ui) var(--ease-out); }
tr.fl-rowflash.on td { background: var(--alive-soft); }
/* ---------------- 1280 ---------------- */
@media (max-width: 1280px) {
#fl-lanes { grid-template-columns: 1fr; }
#fl-srcCards { grid-template-columns: 1fr 1fr; }
#fl-cols { grid-template-columns: 1fr 1fr; }
#fl-col3 { grid-column: 1 / -1; }
}
/* ---------------- 1024 ---------------- */
@media (max-width: 1100px) {
#fl-root { padding: var(--sp3); }
#fl-srcCards { grid-template-columns: 1fr; }
#fl-cols { grid-template-columns: 1fr; }
.fl-src-card .role, .fl-src-card .cred { display: none; }
}