213 lines
20 KiB
HTML
213 lines
20 KiB
HTML
<!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>
|
||
:root {
|
||
--bg: #0a0a14;
|
||
--glass: rgba(12, 22, 50, 0.8);
|
||
--edge: rgba(110, 160, 230, 0.2);
|
||
--edge-h: rgba(150, 200, 255, 0.45);
|
||
--text: rgba(195, 215, 255, 0.9);
|
||
--soft: rgba(155, 195, 235, 0.55);
|
||
--faint: rgba(155, 195, 235, 0.35);
|
||
--glow: rgba(160, 210, 255, 0.95);
|
||
--green: rgba(140, 220, 180, 0.9);
|
||
--gold: rgba(220, 200, 140, 0.9);
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body { background: var(--bg); color: var(--text); 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 8px; }
|
||
.badge .d { font-size: 18px; color: var(--faint); letter-spacing: 4px; }
|
||
.badge .c { font-size: 15px; color: rgba(155, 195, 235, 0.28); letter-spacing: 2px; margin-top: 4px; }
|
||
|
||
.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; }
|
||
|
||
/* 登录栏 */
|
||
.login-bar { display: flex; align-items: center; justify-content: space-between; padding: 22px 28px; background: var(--glass); border: 1px solid var(--edge); border-radius: 18px; gap: 16px; flex-wrap: wrap; margin: 28px 0; }
|
||
.login-bar .hint { font-size: 16px; color: var(--soft); }
|
||
.login-bar .hint strong { color: var(--glow); font-weight: 600; }
|
||
.login-in { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
|
||
.login-in input { padding: 12px 18px; background: rgba(255,255,255,0.04); border: 1px solid var(--edge); border-radius: 14px; color: var(--text); font-size: 16px; outline: none; width: 150px; font-family: inherit; }
|
||
.login-in input:focus { border-color: rgba(160,210,255,0.35); }
|
||
.login-in input::placeholder { color: var(--faint); }
|
||
.login-in button { padding: 12px 28px; background: linear-gradient(135deg, rgba(100,160,220,0.3), rgba(130,100,200,0.2)); border: 1px solid var(--edge); border-radius: 14px; color: var(--glow); font-size: 16px; cursor: pointer; font-family: inherit; letter-spacing: 1px; transition: all 0.25s; }
|
||
.login-in button:hover { background: linear-gradient(135deg, rgba(100,160,220,0.5), rgba(130,100,200,0.35)); border-color: var(--edge-h); }
|
||
.logged-in { display: none; align-items: center; justify-content: space-between; padding: 20px 28px; background: rgba(140,220,180,0.06); border: 1px solid rgba(140,220,180,0.15); border-radius: 18px; gap: 16px; flex-wrap: wrap; margin: 28px 0; }
|
||
.logged-in .user { display: flex; align-items: center; gap: 14px; }
|
||
.logged-in .avatar { width: 44px; height: 44px; border-radius: 50%; background: linear-gradient(135deg, rgba(100,160,220,0.4), rgba(130,100,200,0.3)); display: flex; align-items: center; justify-content: center; font-size: 20px; color: var(--glow); font-weight: 600; }
|
||
.logged-in .uname { font-size: 18px; color: var(--glow); font-weight: 600; }
|
||
.logged-in .ustatus { font-size: 14px; color: var(--green); }
|
||
.logged-in .btns { display: flex; gap: 10px; }
|
||
.logged-in .btns button { padding: 12px 24px; border-radius: 14px; font-size: 15px; cursor: pointer; font-family: inherit; transition: all 0.25s; }
|
||
.btn-go { background: linear-gradient(135deg, rgba(100,160,220,0.3), rgba(130,100,200,0.2)); border: 1px solid var(--edge); color: var(--glow); }
|
||
.btn-go:hover { background: linear-gradient(135deg, rgba(100,160,220,0.5), rgba(130,100,200,0.35)); }
|
||
.btn-out { background: rgba(255,255,255,0.03); border: 1px solid var(--edge); color: var(--soft); }
|
||
.login-error { font-size: 14px; color: rgba(255, 140, 140, 0.8); display: none; text-align: center; margin-top: 8px; }
|
||
|
||
/* 状态条 */
|
||
.status { display: flex; gap: 40px; justify-content: center; flex-wrap: wrap; margin: 28px 0; font-size: 19px; }
|
||
.status span { color: var(--glow); }
|
||
|
||
/* 模块 */
|
||
.modules { display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px; margin: 50px 0; }
|
||
.mod { background: var(--glass); border: 1px solid var(--edge); border-radius: 18px; padding: 32px 20px; text-align: center; cursor: pointer; transition: all 0.3s; }
|
||
.mod:hover { border-color: var(--edge-h); 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.new { border-color: rgba(140,220,180,0.4); }
|
||
.mod .icon { font-size: 42px; margin-bottom: 12px; }
|
||
.mod .name { font-size: 19px; color: var(--glow); letter-spacing: 2px; }
|
||
.mod .tag { display: inline-block; font-size: 11px; color: var(--green); background: rgba(140,220,180,0.12); padding: 2px 10px; border-radius: 10px; margin-top: 8px; letter-spacing: 1px; }
|
||
|
||
.panel { background: var(--glass); border: 1px solid var(--edge); 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: var(--glow); 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: var(--green); 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: var(--faint); 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 .ticon { font-size: 22px; width: 32px; }
|
||
.ticket .name { flex: 1; }
|
||
.ticket .tag { font-size: 14px; padding: 4px 14px; border-radius: 14px; }
|
||
.ticket .tag.done { color: var(--green); background: rgba(140,220,180,0.12); }
|
||
.ticket .tag.progress { color: var(--gold); background: rgba(220,200,140,0.12); }
|
||
|
||
.bcast { font-size: 17px; color: var(--soft); 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: var(--soft); margin-bottom: 4px; }
|
||
.chat-msg .who.zhu { color: var(--glow); }
|
||
.chat-input { display: flex; gap: 12px; }
|
||
.chat-input input { flex: 1; background: rgba(12,20,45,0.7); border: 1px solid var(--edge); border-radius: 14px; padding: 18px 20px; color: var(--text); font-size: 18px; outline: none; }
|
||
.chat-input input::placeholder { color: var(--faint); }
|
||
.chat-input button { background: linear-gradient(135deg, rgba(100,160,220,0.25), rgba(130,100,200,0.15)); border: 1px solid var(--edge-h); border-radius: 14px; padding: 18px 32px; color: var(--glow); font-size: 17px; cursor: pointer; font-family: inherit; }
|
||
|
||
.footer { text-align: center; padding: 60px 0; font-size: 15px; color: var(--faint); letter-spacing: 3px; }
|
||
|
||
@media(max-width:768px){.modules{grid-template-columns:repeat(2,1fr)}.status{font-size:17px;gap:24px}.lake-title{font-size:32px}.login-bar{flex-direction:column;text-align:center}}
|
||
</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="login-bar" id="login-bar">
|
||
<div class="hint">登录你的<strong>光湖开发节点库</strong> · 使用全部功能</div>
|
||
<div class="login-in">
|
||
<input type="text" placeholder="账号" id="login-user" onkeydown="if(event.key==='Enter')handleLogin()">
|
||
<input type="password" placeholder="密码" id="login-pass" onkeydown="if(event.key==='Enter')handleLogin()">
|
||
<button onclick="handleLogin()">登录 · 进入联邦</button>
|
||
</div>
|
||
</div>
|
||
<div class="login-error" id="login-error"></div>
|
||
|
||
<div class="logged-in" id="logged-in">
|
||
<div class="user"><div class="avatar" id="avatar">?</div><div><div class="uname" id="uname">—</div><div class="ustatus">已登录 · 光湖联邦成员</div></div></div>
|
||
<div class="btns"><button class="btn-go" onclick="goRepo()">→ 进入光湖开发节点库</button><button class="btn-out" onclick="logout()">退出</button></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:var(--green)">9/10</span></div>
|
||
</div>
|
||
|
||
<div class="modules">
|
||
<div class="mod new" onclick="window.open('/modules/','_blank')">
|
||
<div class="icon">🎨</div>
|
||
<div class="name">开源模块</div>
|
||
<div class="tag">NEW</div>
|
||
</div>
|
||
<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:var(--soft);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:var(--soft);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="ticon">⏳</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>📨 频道仪表盘 v5 已发布</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+.2,o:Math.random(),s:Math.random()*.0025+.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)*.5+.5,a=s.o*(.25+b*.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 p=document.getElementById('p-'+id),c=document.getElementById('m-'+id),isOpen=p.classList.contains('show');var ap=document.getElementsByClassName('panel');for(var i=0;i<ap.length;i++)ap[i].classList.remove('show');var ac=document.getElementsByClassName('mod');for(var j=0;j<ac.length;j++)ac[j].classList.remove('active');if(isOpen){cur=null;return}p.classList.add('show');c.classList.add('active');cur=id;if(id==='chat')document.getElementById('inp').focus();if(id==='server'){renderSrv();fetchLog()}resize();mkStars()}
|
||
|
||
function handleLogin(){var u=document.getElementById('login-user').value.trim(),p=document.getElementById('login-pass').value;if(!u||!p){var e=document.getElementById('login-error');e.textContent='请输入账号和密码';e.style.display='block';setTimeout(function(){e.style.display='none'},3000);return}fetch('/api/verify',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({user:u,password:p})}).then(function(r){return r.json()}).then(function(d){if(d.ok){localStorage.setItem('current_user',d.username);localStorage.setItem('is_admin',d.is_admin);localStorage.setItem('logged_in','true');loggedIn(d.username);document.getElementById('login-pass').value=''}else{var e=document.getElementById('login-error');e.textContent=d.error||'登录失败';e.style.display='block';setTimeout(function(){e.style.display='none'},3000)}}).catch(function(){var e=document.getElementById('login-error');e.textContent='连接失败';e.style.display='block';setTimeout(function(){e.style.display='none'},3000)})}
|
||
function loggedIn(u){document.getElementById('login-bar').style.display='none';document.getElementById('logged-in').style.display='flex';document.getElementById('uname').textContent=u;document.getElementById('avatar').textContent=u[0].toUpperCase()}
|
||
function goRepo(){var u=localStorage.getItem('current_user');window.location.href='/code/'+u}
|
||
function logout(){localStorage.removeItem('current_user');localStorage.removeItem('is_admin');localStorage.removeItem('logged_in');document.getElementById('logged-in').style.display='none';document.getElementById('login-bar').style.display='flex';document.getElementById('login-user').value=''}
|
||
|
||
var hb=document.getElementById('hb'),beats=['▮▮▮','▮ ▮ ▮','▮▮▮','▮ ▮ ▮'],idxB=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 b=document.getElementById('srv-list');if(!data||!data.server){b.innerHTML='<div class="server-item"><span class="server-dot on"></span>等待数据…</div>';return}var on=data.server.services||[],off=data.server.stopped||[],h='';for(var i=0;i<on.length;i++){var n=names[on[i]]||on[i].replace(/^guanghulab-/,'').replace(/-/g,' ');h+='<div class="server-item"><span class="server-dot on"></span>'+n+'</div>'}for(var j=0;j<off.length;j++){var m=names[off[j]]||off[j].replace(/^guanghulab-/,'').replace(/-/g,' ');h+='<div class="server-item"><span class="server-dot off"></span><span style="opacity:.6">'+m+'</span></div>'}b.innerHTML=h||'<div class="server-item">暂无服务</div>'}
|
||
function fetchLog(){fetch('/api/brain',{cache:'no-store'}).then(function(r){return r.json()}).then(function(d){var b=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>';b.innerHTML=h}else{b.innerHTML='<div style="color:var(--faint)">日志未接入</div>'}}).catch(function(){document.getElementById('log-box').innerHTML='<div style="color:var(--faint)">加载失败</div>'})}
|
||
function renderTk(){var b=document.getElementById('tk-list');if(!data||!data.mothers){b.innerHTML='<div class="ticket"><span class="ticon">⏳</span><span class="name">等待数据…</span></div>';return}var h='';for(var i=0;i<data.mothers.length;i++){var m=data.mothers[i];h+='<div style="font-size:15px;color:var(--soft);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',icon=done?'✅':prog?'🔄':'⏳',tag=done?'done':prog?'progress':'',label=done?'完成':prog?'进行中':'待办';h+='<div class="ticket"><span class="ticon">'+icon+'</span><span class="name">'+p.name+'</span><span class="tag '+tag+'">'+label+'</span></div>'}}b.innerHTML=h}
|
||
|
||
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[idxB];idxB=(idxB+1)%beats.length;lastB=t}if(t-lastF>3000){fetchData();lastF=t}requestAnimationFrame(loop)}
|
||
|
||
(function(){var u=localStorage.getItem('current_user');if(u&&localStorage.getItem('logged_in')==='true')loggedIn(u)})();
|
||
|
||
fetchData();requestAnimationFrame(loop);
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|