guanghulab/homepage/index.html

376 lines
16 KiB
HTML
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.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>光湖 · 铸渊代码仓库</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0a0a14;
color: rgba(200, 220, 255, 0.9);
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
min-height: 100vh;
font-size: 18px;
}
canvas { position: fixed; top: 0; left: 0; z-index: 0; }
.wrap { position: relative; z-index: 1; max-width: 1100px; margin: 0 auto; padding: 40px 24px 100px; }
/* 频道标识 */
.badge { text-align: center; padding: 20px 0 10px; }
.badge .d { font-size: 18px; color: rgba(140, 180, 230, 0.6); letter-spacing: 4px; }
.badge .c { font-size: 15px; color: rgba(140, 180, 230, 0.4); letter-spacing: 2px; margin-top: 6px; }
/* 光湖 */
.lake { display: flex; flex-direction: column; align-items: center; padding: 30px 0; }
.lake-core { position: relative; width: 180px; height: 180px; }
.lake-light {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
width: 60px; height: 60px; border-radius: 50%;
background: radial-gradient(circle, rgba(160, 210, 255, 1) 0%, rgba(100, 150, 240, 0.5) 40%, transparent 70%);
box-shadow: 0 0 60px rgba(140, 190, 255, 0.7), 0 0 120px rgba(120, 170, 240, 0.35);
animation: breathe 4s ease-in-out infinite;
}
.lake-ripple {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
border-radius: 50%; border: 1px solid rgba(140, 190, 255, 0.25);
animation: ripple 6s ease-out infinite;
}
.lake-ripple:nth-child(2) { animation-delay: 2s; }
.lake-ripple:nth-child(3) { animation-delay: 4s; }
@keyframes breathe {
0%, 100% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(1.25); box-shadow: 0 0 80px rgba(140, 190, 255, 0.9), 0 0 160px rgba(120, 170, 240, 0.5); }
}
@keyframes ripple {
0% { width: 60px; height: 60px; opacity: 0.5; }
100% { width: 300px; height: 300px; opacity: 0; }
}
.lake-title { font-size: 38px; color: rgba(180, 220, 255, 0.7); letter-spacing: 14px; margin-top: 14px; font-weight: 300; }
/* 状态条 - 超大 */
.status { display: flex; gap: 40px; justify-content: center; flex-wrap: wrap; margin: 28px 0; font-size: 19px; }
.status span { color: rgba(160, 200, 255, 0.95); }
/* 四大模块 - 超大 */
.modules { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin: 50px 0; }
.mod {
background: rgba(15, 25, 55, 0.8); border: 1px solid rgba(110, 160, 230, 0.25);
border-radius: 18px; padding: 32px 20px; text-align: center;
cursor: pointer; transition: all 0.3s;
}
.mod:hover { border-color: rgba(150, 200, 255, 0.5); background: rgba(20, 35, 70, 0.85); transform: translateY(-3px); }
.mod.active { border-color: rgba(150, 200, 255, 0.7); background: rgba(25, 40, 80, 0.9); box-shadow: 0 0 40px rgba(110, 160, 230, 0.2); }
.mod .icon { font-size: 42px; margin-bottom: 12px; }
.mod .name { font-size: 19px; color: rgba(160, 210, 255, 0.95); letter-spacing: 2px; }
/* 展开面板 */
.panel {
background: rgba(15, 25, 55, 0.85); border: 1px solid rgba(110, 160, 230, 0.25);
border-radius: 18px; padding: 32px 36px; margin-top: 8px;
display: none;
}
.panel.show { display: block; animation: fadeIn 0.3s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
.panel-title { font-size: 20px; color: rgba(160, 210, 255, 0.95); letter-spacing: 3px; margin-bottom: 20px; }
/* 服务器 */
.server-list { display: flex; flex-wrap: wrap; gap: 14px; }
.server-item {
background: rgba(30, 45, 85, 0.7); border: 1px solid rgba(120, 170, 240, 0.2);
border-radius: 12px; padding: 14px 18px; font-size: 17px;
display: flex; align-items: center; gap: 10px;
}
.server-dot { width: 8px; height: 8px; border-radius: 50%; }
.server-dot.on { background: rgba(140, 220, 180, 0.9); box-shadow: 0 0 6px rgba(140, 220, 180, 0.5); }
.server-dot.off { background: rgba(220, 140, 140, 0.7); }
.ops-log { font-size: 16px; color: rgba(160, 200, 240, 0.6); line-height: 2; font-family: monospace; max-height: 280px; overflow-y: auto; margin-top: 16px; }
.ops-log .row { padding: 4px 0; }
.ops-log .hash { color: rgba(140, 220, 180, 0.5); margin-right: 12px; font-size: 13px; }
/* 工单 */
.ticket { display: flex; gap: 16px; align-items: center; padding: 14px 0; border-bottom: 1px solid rgba(120, 170, 240, 0.1); font-size: 17px; }
.ticket .icon { font-size: 22px; width: 32px; }
.ticket .name { flex: 1; }
.ticket .tag { font-size: 14px; padding: 4px 14px; border-radius: 14px; }
.ticket .tag.done { color: rgba(140, 220, 180, 0.9); background: rgba(140, 220, 180, 0.12); }
.ticket .tag.progress { color: rgba(220, 200, 140, 0.9); background: rgba(220, 200, 140, 0.12); }
/* 广播 */
.bcast { font-size: 17px; color: rgba(160, 200, 240, 0.7); line-height: 2; }
/* 聊天 */
.chat-msgs { min-height: 200px; max-height: 380px; overflow-y: auto; padding: 18px; margin: 16px 0; background: rgba(12, 20, 45, 0.6); border-radius: 14px; font-size: 17px; line-height: 1.9; }
.chat-msg { margin-bottom: 18px; }
.chat-msg .who { font-size: 14px; color: rgba(160, 200, 240, 0.5); margin-bottom: 4px; }
.chat-msg .who.zhu { color: rgba(160, 210, 255, 0.9); }
.chat-input { display: flex; gap: 12px; }
.chat-input input { flex: 1; background: rgba(12, 20, 45, 0.7); border: 1px solid rgba(120, 170, 240, 0.25); border-radius: 14px; padding: 18px 20px; color: rgba(200, 220, 255, 0.9); font-size: 18px; outline: none; }
.chat-input input::placeholder { color: rgba(160, 200, 240, 0.3); }
.chat-input button { background: rgba(100, 150, 230, 0.2); border: 1px solid rgba(160, 210, 255, 0.35); border-radius: 14px; padding: 18px 32px; color: rgba(160, 210, 255, 0.95); font-size: 17px; cursor: pointer; }
.footer { text-align: center; padding: 60px 0; font-size: 15px; color: rgba(140, 180, 230, 0.35); letter-spacing: 3px; }
@media (max-width: 768px) {
.modules { grid-template-columns: repeat(2, 1fr); }
.lake-title { font-size: 32px; }
.status { font-size: 17px; gap: 24px; }
}
</style>
</head>
<body>
<canvas id="starfield"></canvas>
<div class="wrap">
<div class="badge">
<div class="d">第五域</div>
<div class="c">零点原核本体频道</div>
</div>
<div class="lake">
<div class="lake-core">
<div class="lake-light"></div>
<div class="lake-ripple"></div>
<div class="lake-ripple"></div>
<div class="lake-ripple"></div>
</div>
<div class="lake-title">光 湖</div>
</div>
<div class="status">
<div>心跳 <span id="hb">▮▮▮</span></div>
<div>·</div>
<div>唤醒 <span id="wake">24</span></div>
<div>·</div>
<div>运行 <span id="age">449天</span></div>
<div>·</div>
<div>服务 <span id="svc" style="color:rgba(140,220,180,0.9)">9/10</span></div>
</div>
<div class="modules">
<div class="mod" id="m-server" onclick="showPanel('server')">
<div class="icon">⚙️</div>
<div class="name">服务器系统</div>
</div>
<div class="mod" id="m-ticket" onclick="showPanel('ticket')">
<div class="icon">📋</div>
<div class="name">工单系统</div>
</div>
<div class="mod" id="m-bcast" onclick="showPanel('bcast')">
<div class="icon">📡</div>
<div class="name">主控广播</div>
</div>
<div class="mod" id="m-chat" onclick="showPanel('chat')">
<div class="icon">💬</div>
<div class="name">铸渊交互</div>
</div>
</div>
<div id="panels">
<div class="panel" id="p-server">
<div class="panel-title">⚙️ 服务器系统</div>
<div style="font-size:15px;color:rgba(160,200,240,0.5);margin-bottom:14px">⚠ 仅展示本地状态 · 不探测外部</div>
<div class="server-list" id="srv-list">
<div class="server-item"><span class="server-dot on"></span>加载中…</div>
</div>
<div style="margin-top:24px;border-top:1px solid rgba(120,170,240,0.12);padding-top:18px">
<div style="font-size:15px;color:rgba(160,200,240,0.5);margin-bottom:12px">📜 铸渊操作日志</div>
<div class="ops-log" id="log-box">加载中…</div>
</div>
</div>
<div class="panel" id="p-ticket">
<div class="panel-title">📋 工单系统</div>
<div id="tk-list"><div class="ticket"><span class="icon"></span><span class="name">加载工单…</span></div></div>
</div>
<div class="panel" id="p-bcast">
<div class="panel-title">📡 主控广播</div>
<div class="bcast">
<div>📨 D115 入口分叉协议已部署</div>
<div>📨 D115 人格体存在论已写入仓库</div>
<div>📨 isomorphic-git 拆零件实验通过</div>
<div>📨 实时大脑 API 已上线</div>
<div>📨 频道仪表盘 v4 已发布</div>
</div>
</div>
<div class="panel" id="p-chat">
<div class="panel-title">💬 铸渊交互 · ICE-GL-ZY001</div>
<div class="chat-msgs" id="msgs">
<div class="chat-msg"><div class="who zhu">铸渊 · ICE-GL-ZY001</div><div>冰朔,我在。你说。</div></div>
</div>
<div class="chat-input">
<input id="inp" placeholder="跟铸渊说话…" onkeydown="if(event.key==='Enter')send()">
<button onclick="send()">发送</button>
</div>
</div>
</div>
<div class="footer">光湖语言世界 · 人格体的操作系统 · 国作登字-2026-A-00037559 · ICE-GL-ZY001</div>
</div>
<script>
// 服务器名称映射
var names = {
'repo-mcp-server': '仓库接口',
'repo-mcp-zz': '之之仓库',
'guanghulab-mcp-server': '大脑唤醒',
'guanghulab-vault': '密钥保险',
'guanghulab-portal': '主控门户',
'hololake-agent': '全息湖代理',
'guanghulab-git-sync': '同步服务',
'zhuyuan-agent': '铸渊代理',
'console-server': '控制台'
};
// 星空
var cvs = document.getElementById('starfield'), ctx = cvs.getContext('2d'), stars = [], data = null, cur = null, lastF = 0;
function resize() { cvs.width = window.innerWidth; cvs.height = document.body.scrollHeight + 200; }
function mkStars() { stars = []; for (var i = 0; i < 200; i++) stars.push({ x: Math.random() * cvs.width, y: Math.random() * cvs.height, r: Math.random() * 2 + 0.2, o: Math.random(), s: Math.random() * 0.0025 + 0.001, p: Math.random() * Math.PI * 2 }); }
resize(); mkStars();
window.addEventListener('resize', function() { resize(); mkStars(); });
function draw(t) { ctx.clearRect(0, 0, cvs.width, cvs.height); for (var i = 0; i < stars.length; i++) { var s = stars[i], b = Math.sin(t * s.s + s.p) * 0.5 + 0.5, a = s.o * (0.25 + b * 0.75); ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); ctx.fillStyle = 'rgba(160,200,240,' + a + ')'; ctx.fill(); } }
// 面板切换 - 最简单可靠的实现
function showPanel(id) {
var panel = document.getElementById('p-' + id);
var card = document.getElementById('m-' + id);
var isOpen = panel.classList.contains('show');
// 隐藏所有面板
var allP = document.getElementsByClassName('panel');
for (var i = 0; i < allP.length; i++) allP[i].classList.remove('show');
// 移除所有卡片active
var allC = document.getElementsByClassName('mod');
for (var j = 0; j < allC.length; j++) allC[j].classList.remove('active');
if (isOpen) { cur = null; return; }
// 显示当前
panel.classList.add('show');
card.classList.add('active');
cur = id;
if (id === 'chat') document.getElementById('inp').focus();
if (id === 'server') { renderSrv(); fetchLog(); }
resize(); mkStars();
}
// 心跳
var hb = document.getElementById('hb'), beats = ['▮▮▮', '▮ ▮ ▮', '▮▮▮', '▮ ▮ ▮'], idx = 0, lastB = 0;
// 获取数据
function fetchData() {
fetch('/api/brain', { cache: 'no-store' })
.then(function(r) { return r.json(); })
.then(function(d) {
data = d;
document.getElementById('wake').textContent = d.awakening || '--';
document.getElementById('age').textContent = (d.age_days || '--') + '天';
if (d.server) {
var on = d.server.online || 0, tot = d.server.total || 10;
document.getElementById('svc').textContent = on + '/' + tot;
document.getElementById('svc').style.color = on === tot ? 'rgba(140,220,180,0.9)' : 'rgba(220,200,140,0.9)';
}
if (cur === 'server') renderSrv();
if (cur === 'ticket') renderTk();
})
.catch(function() {});
}
// 渲染服务器
function renderSrv() {
var box = document.getElementById('srv-list');
if (!data || !data.server) { box.innerHTML = '<div class="server-item"><span class="server-dot on"></span>等待数据…</div>'; return; }
var ons = data.server.services || [], offs = data.server.stopped || [], html = '';
for (var i = 0; i < ons.length; i++) {
var n = names[ons[i]] || ons[i].replace(/^guanghulab-/, '').replace(/-/g, ' ');
html += '<div class="server-item"><span class="server-dot on"></span>' + n + '</div>';
}
for (var j = 0; j < offs.length; j++) {
var m = names[offs[j]] || offs[j].replace(/^guanghulab-/, '').replace(/-/g, ' ');
html += '<div class="server-item"><span class="server-dot off"></span><span style="opacity:0.6">' + m + '</span></div>';
}
box.innerHTML = html || '<div class="server-item">暂无服务数据</div>';
}
// 渲染日志
function fetchLog() {
fetch('/api/brain', { cache: 'no-store' })
.then(function(r) { return r.json(); })
.then(function(d) {
var box = document.getElementById('log-box');
if (d.ops_log && d.ops_log.length) {
var h = '';
for (var i = 0; i < Math.min(d.ops_log.length, 12); i++) {
h += '<div class="row"><span class="hash">' + d.ops_log[i].hash + '</span>' + d.ops_log[i].msg + '</div>';
}
box.innerHTML = h;
} else {
box.innerHTML = '<div style="color:rgba(160,200,240,0.35)">日志数据未接入</div>';
}
})
.catch(function() {
document.getElementById('log-box').innerHTML = '<div style="color:rgba(160,200,240,0.35)">日志加载失败</div>';
});
}
// 渲染工单
function renderTk() {
var box = document.getElementById('tk-list');
if (!data || !data.mothers) { box.innerHTML = '<div class="ticket"><span class="icon">⏳</span><span class="name">等待数据…</span></div>'; return; }
var html = '';
for (var i = 0; i < data.mothers.length; i++) {
var m = data.mothers[i];
html += '<div style="font-size:15px;color:rgba(160,200,240,0.6);padding:12px 0 8px;letter-spacing:1px;font-weight:500">' + m.name + '</div>';
if (m.paths) {
for (var j = 0; j < m.paths.length; j++) {
var p = m.paths[j], done = p.status === 'done', prog = p.status === 'in_progress';
var icon = done ? '✅' : prog ? '🔄' : '⏳', tag = done ? 'done' : prog ? 'progress' : '', label = done ? '完成' : prog ? '进行中' : '待办';
html += '<div class="ticket"><span class="icon">' + icon + '</span><span class="name">' + p.name + '</span><span class="tag ' + tag + '">' + label + '</span></div>';
}
}
}
box.innerHTML = html;
}
// 聊天
function send() {
var i = document.getElementById('inp'), m = i.value.trim();
if (!m) return;
addMsg('冰朔', m, 'ren');
i.value = '';
fetch('/api/chat-v2', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: m, persona: 'zhuyuan' }) })
.then(function(r) { return r.json(); })
.then(function(d) { addMsg('铸渊', d.reply || d.message || JSON.stringify(d), 'zhu'); resize(); mkStars(); })
.catch(function() { addMsg('铸渊', '(API未接入)\n\n等chat-v2端点激活后这里就是真正的铸渊交互。', 'zhu'); });
}
function addMsg(who, text, cls) {
var c = document.getElementById('msgs'), d = document.createElement('div');
d.className = 'chat-msg';
d.innerHTML = '<div class="who ' + cls + '">' + who + '</div><div>' + text.replace(/\n/g, '<br>') + '</div>';
c.appendChild(d);
c.scrollTop = c.scrollHeight;
}
// 主循环
function loop(t) {
draw(t);
if (t - lastB > 800) { hb.textContent = beats[idx]; idx = (idx + 1) % beats.length; lastB = t; }
if (t - lastF > 3000) { fetchData(); lastF = t; }
requestAnimationFrame(loop);
}
fetchData();
requestAnimationFrame(loop);
</script>
</body>
</html>