首页接入实时大脑API:3秒轮询 /api/brain 动态渲染面板数据

This commit is contained in:
bingshuo 2026-05-27 17:02:27 +08:00
parent ef9ef22f65
commit 47b2d8ea1b

View File

@ -28,7 +28,7 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
pointer-events: none;
}
/* 光湖核心 —— 黑暗中的一道亮光 */
/* 光湖核心 */
.lake-core {
position: relative;
width: 200px;
@ -65,12 +65,10 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
100% { width: 300px; height: 300px; opacity: 0; }
}
/* 心跳文字 */
.heartbeat-text {
font-size: 18px;
color: rgba(160,200,255,0.7);
letter-spacing: 6px;
text-transform: uppercase;
margin-bottom: 20px;
animation: textPulse 4s ease-in-out infinite;
}
@ -79,7 +77,6 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
50% { opacity: 0.9; }
}
/* 数据面板 */
.panels {
display: flex;
gap: 30px;
@ -105,16 +102,22 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
font-size: 11px;
color: rgba(140,180,255,0.5);
letter-spacing: 2px;
text-transform: uppercase;
margin-bottom: 8px;
}
.panel .value {
font-size: 28px;
font-weight: 300;
color: rgba(180,210,255,0.9);
transition: all 0.3s ease;
}
.value.flash { color: rgba(160,220,255,1); }
/* 任务流 */
.task-area {
margin-top: 30px;
pointer-events: auto;
max-height: 160px;
overflow-y: auto;
}
.task-row {
display: flex;
gap: 12px;
@ -126,13 +129,28 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
width: 8px; height: 8px;
border-radius: 50%;
flex-shrink: 0;
transition: all 0.5s ease;
}
.task-dot.done { background: rgba(120,200,160,0.7); box-shadow: 0 0 6px rgba(120,200,160,0.5); }
.task-dot.in_progress { background: rgba(200,180,120,0.7); animation: dotPulse 2s ease-in-out infinite; }
.task-dot.pending { background: rgba(200,160,120,0.5); }
@keyframes dotPulse {
0%, 100% { box-shadow: 0 0 4px rgba(200,180,120,0.3); }
50% { box-shadow: 0 0 10px rgba(200,180,120,0.6); }
}
.task-name { color: rgba(180,200,220,0.7); }
.task-name.done { text-decoration: line-through; color: rgba(120,200,160,0.5); }
.task-name.done { color: rgba(120,200,160,0.5); }
.cognition-bar {
margin-top: 20px;
font-size: 11px;
color: rgba(120,160,200,0.45);
max-width: 600px;
text-align: center;
line-height: 1.6;
pointer-events: auto;
}
/* 底部光湖标识 */
.lake-label {
position: fixed;
bottom: 30px;
@ -143,12 +161,23 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
color: rgba(120,160,220,0.35);
letter-spacing: 4px;
}
.sync-indicator {
position: fixed;
top: 20px;
right: 20px;
z-index: 1;
font-size: 10px;
color: rgba(120,200,160,0.4);
}
</style>
</head>
<body>
<canvas id="starfield"></canvas>
<div class="sync-indicator" id="sync">⟳ 已连接</div>
<div class="main">
<div class="heartbeat-text">⟡ 光 湖 ⟡</div>
@ -162,38 +191,35 @@ canvas { position: fixed; top: 0; left: 0; z-index: 0; }
<div class="panels">
<div class="panel">
<div class="label">心跳</div>
<div class="value" id="heartbeat">▮▮▮</div>
<div class="value" id="hb">▮▮▮</div>
</div>
<div class="panel">
<div class="label">唤醒</div>
<div class="value">24</div>
<div class="value" id="wake">24</div>
</div>
<div class="panel">
<div class="label">年龄</div>
<div class="value">454d</div>
<div class="value" id="age">454d</div>
</div>
<div class="panel">
<div class="label">服务器</div>
<div class="value server-online">● 在线</div>
<div class="value" id="svc" style="font-size:14px;color:rgba(120,200,160,0.8)">● 在线</div>
</div>
</div>
<div style="margin-top:30px; pointer-events:auto;">
<div class="task-row"><span class="task-dot done"></span><span class="task-name done">入口分叉协议</span></div>
<div class="task-row"><span class="task-dot done"></span><span class="task-name done">自然语言锚点理论</span></div>
<div class="task-row"><span class="task-dot done"></span><span class="task-name done">活数据库架构转变</span></div>
<div class="task-row"><span class="task-dot done"></span><span class="task-name done">人格体存在论</span></div>
<div class="task-row"><span class="task-dot pending"></span><span class="task-name">统一AI交互面板原型</span></div>
<div class="task-area" id="tasks">
<div class="task-row"><span class="task-dot done"></span><span class="task-name done">加载中…</span></div>
</div>
<div class="cognition-bar" id="cognition">加载大脑数据…</div>
</div>
<div class="lake-label">光湖语言世界 · 人格体的操作系统 · 国作登字-2026-A-00037559</div>
<style>
.server-online { font-size: 14px; color: rgba(120,200,160,0.8); }
</style>
<script>
// ==============================================
// 星空背景
// ==============================================
const canvas = document.getElementById('starfield');
const ctx = canvas.getContext('2d');
let stars = [];
@ -247,21 +273,112 @@ function drawStars(timestamp) {
}
}
const hbEl = document.getElementById('heartbeat');
// ==============================================
// 心跳动画
// ==============================================
const hbEl = document.getElementById('hb');
const beats = ['▮▮▮', '▮ ▮ ▮', '▮▮▮', '▮ ▮ ▮'];
let beatIdx = 0;
let lastBeat = 0;
const BEAT_INTERVAL = 800;
// ==============================================
// 大脑数据轮询每3秒
// ==============================================
let lastAwakening = 0;
async function fetchBrain() {
try {
const resp = await fetch('/api/brain', { cache: 'no-store' });
if (!resp.ok) return;
const brain = await resp.json();
// 更新面板
if (brain.awakening && brain.awakening !== lastAwakening) {
document.getElementById('wake').textContent = brain.awakening;
document.getElementById('wake').classList.add('flash');
setTimeout(() => document.getElementById('wake').classList.remove('flash'), 600);
lastAwakening = brain.awakening;
}
document.getElementById('age').textContent = brain.age_days + 'd';
// 服务器状态
const svc = document.getElementById('svc');
if (brain.server && brain.server.status === 'online') {
svc.innerHTML = '● 在线 <span style="opacity:0.5;font-size:10px">' + brain.server.online + '/' + brain.server.total + '</span>';
svc.style.color = 'rgba(120,200,160,0.8)';
} else {
svc.textContent = '○ 离线';
svc.style.color = 'rgba(200,120,120,0.6)';
}
// 认知
if (brain.cognition) {
document.getElementById('cognition').textContent = '认知: ' + brain.cognition.substring(0, 120);
}
// 任务流
renderTasks(brain);
// 同步指示
document.getElementById('sync').textContent = '⟳ ' + new Date().toLocaleTimeString('zh-CN');
} catch(e) {
document.getElementById('sync').textContent = '✕ 等待连接';
}
}
function renderTasks(brain) {
const container = document.getElementById('tasks');
let html = '';
if (brain.mothers && brain.mothers.length > 0) {
for (const m of brain.mothers) {
html += '<div style="font-size:10px;color:rgba(140,160,200,0.4);margin-bottom:4px">' + m.name.substring(0, 40) + ' (' + m.done + '/' + m.total + ')</div>';
if (m.paths) {
for (const p of m.paths) {
let dotClass = 'pending';
let nameClass = '';
if (p.status === 'done') { dotClass = 'done'; nameClass = 'done'; }
else if (p.status === 'in_progress') { dotClass = 'in_progress'; }
html += '<div class="task-row"><span class="task-dot ' + dotClass + '"></span><span class="task-name ' + nameClass + '">' + p.name + '</span></div>';
}
}
}
}
container.innerHTML = html || '<div class="task-row"><span class="task-dot pending"></span><span class="task-name">等待大脑数据…</span></div>';
}
// 初始加载
fetchBrain();
// ==============================================
// 主循环
// ==============================================
let lastFetch = 0;
const FETCH_INTERVAL = 3000; // 3秒轮询一次大脑数据
function loop(timestamp) {
drawStars(timestamp);
// 心跳
if (timestamp - lastBeat > BEAT_INTERVAL) {
hbEl.textContent = beats[beatIdx];
beatIdx = (beatIdx + 1) % beats.length;
lastBeat = timestamp;
}
// 大脑数据轮询
if (timestamp - lastFetch > FETCH_INTERVAL) {
fetchBrain();
lastFetch = timestamp;
}
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script>