按已通过样图(HEL-527,白栖知“按照这个试试吧”)重做 xiaobai-datahub
管理后台(8766/admin/),仅改 admin/index.html、admin/styles.css、
admin/app.js 三个文件,零新依赖、不改构建流程、不触碰 datahub/ 后端、
Docker/Compose、8765 主站与冻结区“问天”。
核心实现:
- 单个 76vh sticky 空间舞台(#stageWrap,position: sticky 钉在视口),
#track 六段 130vh 透明占位撑高文档、驱动滚动进度,舞台本体在滚动期间
保持不动,直到六幕滚完才随之离场。
- 一枚持续旋转的 3D 数据机芯(canvas 2D 手工透视投影,无 WebGL/新依赖),
六幕分别对应总览/数据源/调度任务/盘后发布/数据集/审计,切换幕时机芯
换面/爆炸展开/合拢,4 条数据流通道持续汇入机芯。
- A2 路由式 LINK/ACT 双灯:LINK 是稳态真实连通性(取自 /admin/api/sources
健康探测结果,仅 tushare/eastmoney/tencent/ifind 四路可流动,ths/xgb/
akshare 属永久预留源,不参与流动动画);ACT 严格由真实事件驱动——
tushare 靠 recent_calls 增量 diff,其余三源靠健康探测“探测动作本身
就是一次真实网络调用”,手动“探测一次”按钮同样触发真实后端请求
(已用真实浏览器验证会打到 /admin/api/sources/<provider>/probe)。
同源事件簇最多闪 3 次,全站闪烁令牌桶限流 ≤3 簇/秒,各源不共享时钟。
- 动效令牌统一:进出用强 ease-out,屏内位移用强 ease-in-out,持续流动用
linear;全文件禁止 ease-in、禁止 transition: all。
- prefers-reduced-motion:静态六幕面板(StaticShell)与动效版共用同一套
cabin/detail/bind 渲染函数,信息与交互完全对等,媒体查询变化时可不
刷新页面实时切换;系统级 CSS 兜底同样生效。
- 页面隐藏 / 断网即暂停所有轮询与 rAF 循环、清空未播闪烁队列,恢复时
只静默重建基线、不补播错过的事件。
- 保留原有登录/改密/登出、数据源探测、任务重跑、盘后发布二次确认
(密码+确认词)、回滚/补数等全部后端接口调用与危险操作确认流程。
自测(均在本地临时环境完成,未连接生产库/生产网络):
- `python -m unittest discover -s xiaobai-datahub/tests -v`:133 项全过。
- `node --check xiaobai-datahub/admin/app.js`:语法通过。
- `git diff --check`:无空白/换行问题;`git status`:仅上述 3 个文件改动。
- 起本地 datahub 服务 + Playwright 真实无头浏览器,22 项端到端断言全过:
画面渲染、六幕滚动到底/导航跳转、日夜切换、机芯点击开合详情、后台
切换(RAF 真停)、断网/恢复、reduced-motion 实时切换、探测按钮触发
真实后端调用等。过程中定位并修复两处真实缺陷:
1) #stageWrap 原为 position: relative,未真正钉住舞台,滚动时机芯会
随页面滚走——已改为 sticky,现验证滚动任意距离机芯位置不变。
2) 点击机芯打开详情硬编码成“数据源”,已改为按当前所在幕动态选择。
另外补上了此前遗漏的 #phase 幕序指示(如“3 / 6”),静态版切幕同步
更新顶部 crumb/phase。
未覆盖:未在 1440/1280/1024 三档做像素级视觉走查(仅验证 1024 无横向
溢出),未做真实弱网/高延迟环境下的手动观察,只做了断网模拟。
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
79 lines
3.1 KiB
HTML
79 lines
3.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>xiaobai-datahub 管理后台 · 数据中枢</title>
|
||
<link rel="stylesheet" href="/admin/styles.css" />
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
<section id="login-view" class="panel auth-panel">
|
||
<span class="badge-sim">内网 · 8766</span>
|
||
<h1>数据中枢</h1>
|
||
<p class="muted">四路来源持续汇流、调度、发布与审计的运转空间。</p>
|
||
<form id="login-form">
|
||
<label>账号 <input name="username" value="hub_admin" autocomplete="username" /></label>
|
||
<label>密码 <input name="password" type="password" autocomplete="current-password" /></label>
|
||
<button type="submit">登录</button>
|
||
<p id="login-error" class="error" hidden></p>
|
||
</form>
|
||
</section>
|
||
|
||
<section id="change-view" class="panel auth-panel" hidden>
|
||
<h1>修改初始密码</h1>
|
||
<form id="change-form">
|
||
<label>当前密码 <input name="current" type="password" /></label>
|
||
<label>新密码(至少 8 位) <input name="new_password" type="password" /></label>
|
||
<button type="submit">保存并继续</button>
|
||
<p id="change-error" class="error" hidden></p>
|
||
</form>
|
||
</section>
|
||
|
||
<section id="shell" hidden>
|
||
<header id="topbar">
|
||
<div class="logo">小白复盘 <em>·</em> 数据中枢</div>
|
||
<span class="crumb" id="crumb">8766 · 四源汇流 · 持续运转</span>
|
||
<span id="phase" class="pill"></span>
|
||
<span class="spacer"></span>
|
||
<span id="who" class="muted who"></span>
|
||
<button type="button" id="theme-btn" class="ghost">夜间</button>
|
||
<button type="button" id="logout-btn" class="ghost">退出</button>
|
||
</header>
|
||
|
||
<!-- 动效版:一台连续空间舞台,六幕滚动切换,同一核心与流道贯穿始终 -->
|
||
<div id="stageWrap">
|
||
<canvas id="scene"></canvas>
|
||
<div id="cabin"></div>
|
||
<div id="legend">
|
||
<span class="lampico li-link"></span>LINK 链路常亮(低亮)<br>
|
||
<span class="lampico li-act"></span>ACT 活动灯 · 事件成簇短闪
|
||
</div>
|
||
<div id="rail"></div>
|
||
<div id="hint">滚 动 推 进 镜 头</div>
|
||
<div id="detail" class="closed">
|
||
<div class="dtag"></div>
|
||
<button id="detailClose" type="button" aria-label="关闭详情">×</button>
|
||
<div id="detailBody"></div>
|
||
</div>
|
||
</div>
|
||
<div id="track" aria-hidden="true">
|
||
<section data-scene="0"></section>
|
||
<section data-scene="1"></section>
|
||
<section data-scene="2"></section>
|
||
<section data-scene="3"></section>
|
||
<section data-scene="4"></section>
|
||
<section data-scene="5"></section>
|
||
</div>
|
||
|
||
<!-- 减少动态效果版:六幕静态空间图 + 固定文字状态,信息与功能完全等价 -->
|
||
<main id="staticShell" hidden>
|
||
<nav id="staticNav"></nav>
|
||
<div id="staticScenes"></div>
|
||
</main>
|
||
</section>
|
||
</div>
|
||
<script src="/admin/app.js"></script>
|
||
</body>
|
||
</html>
|