feat: 主控台首页 v2.0 — 登录门禁 + 真实服务器状态 + 全模块真实数据
- 登录遮罩:Forgejo 账号密码验证,登录后解锁主控台 - 服务器系统模块:console-server API 实时拉取 9 台服务器在线状态 - 代码仓库模块:Forgejo API 真实拉取最新提交 - 部署注册表/主控广播/铸渊交互:全部接真实数据 - 大桌子小桌子入口跳转 /desk/ - 保留原有 UI 风格(动态粒子背景 + 卡片悬浮效果) ICE-GL-ZY001 · D115
This commit is contained in:
parent
49030d2cbc
commit
768c08b6a1
@ -3,271 +3,511 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>光湖 · 开源模块仓库</title>
|
||||
<title>光湖 · 铸渊大脑</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0a0a16;
|
||||
--card: rgba(16,28,56,.75);
|
||||
--edge: rgba(110,160,230,.18);
|
||||
--edge-h: rgba(155,205,255,.4);
|
||||
--t: rgba(200,218,248,.92);
|
||||
--dim: rgba(140,180,220,.5);
|
||||
--dim2: rgba(120,160,200,.28);
|
||||
--glow: rgba(160,210,255,.95);
|
||||
--green: rgba(140,220,180,.88);
|
||||
--gold: rgba(220,195,130,.88);
|
||||
--rose: rgba(230,140,160,.85);
|
||||
--bg: #0a0a14; --card: rgba(12,22,50,.8); --edge: rgba(110,160,230,.2);
|
||||
--edge-h: rgba(150,200,255,.45); --t: rgba(195,215,255,.9); --dim: rgba(155,195,235,.55);
|
||||
--dim2: rgba(155,195,235,.35); --glow: rgba(160,210,255,.95);
|
||||
--green: rgba(140,220,180,.9); --gold: rgba(220,200,140,.9); --red: rgba(255,140,140,.8);
|
||||
}
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{
|
||||
background:var(--bg); color:var(--t);
|
||||
font-family:-apple-system,"PingFang SC","Microsoft YaHei","Inter",sans-serif;
|
||||
min-height:100vh; font-size:16px; line-height:1.6; overflow-x:hidden;
|
||||
}
|
||||
canvas#bg{position:fixed;top:0;left:0;z-index:0;pointer-events:none}
|
||||
body{background:var(--bg);color:var(--t);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}
|
||||
|
||||
.wrap{position:relative;z-index:1;max-width:960px;margin:0 auto;padding:50px 20px 80px}
|
||||
/* Login overlay */
|
||||
.login-overlay {
|
||||
position:fixed;inset:0;z-index:200;
|
||||
background:rgba(5,5,16,.92);
|
||||
display:flex;align-items:center;justify-content:center;
|
||||
}
|
||||
.login-overlay.hidden { display:none; }
|
||||
.login-box {
|
||||
background:var(--card);border:1px solid var(--edge-h);border-radius:24px;
|
||||
padding:48px 36px;max-width:400px;width:90%;text-align:center;
|
||||
animation:modalIn .3s ease-out;
|
||||
}
|
||||
@keyframes modalIn{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
|
||||
.login-box .lake-core {
|
||||
display:inline-block;width:50px;height:50px;border-radius:50%;
|
||||
background:radial-gradient(circle,rgba(160,210,255,1),rgba(100,150,240,.5) 40%,transparent 70%);
|
||||
box-shadow:0 0 40px rgba(140,190,255,.7);margin-bottom:16px;
|
||||
}
|
||||
.login-box h2 { font-size:22px;font-weight:600;margin-bottom:6px;color:var(--glow); }
|
||||
.login-box .sub { font-size:13px;color:var(--dim2);margin-bottom:24px; }
|
||||
.login-box input {
|
||||
display:block;width:100%;padding:12px 16px;margin-bottom:12px;
|
||||
background:rgba(255,255,255,.04);border:1px solid var(--edge);border-radius:12px;
|
||||
color:var(--t);font-size:15px;outline:none;font-family:inherit;
|
||||
}
|
||||
.login-box input:focus { border-color:var(--edge-h); }
|
||||
.login-box input::placeholder { color:var(--dim2); }
|
||||
.login-box .btn-login {
|
||||
width:100%;padding:12px;margin-top:8px;
|
||||
background:linear-gradient(135deg,rgba(100,160,220,.3),rgba(120,90,200,.2));
|
||||
border:1px solid var(--edge);border-radius:12px;color:var(--glow);
|
||||
cursor:pointer;font-size:15px;font-weight:600;font-family:inherit;transition:all .25s;
|
||||
}
|
||||
.login-box .btn-login:hover { background:linear-gradient(135deg,rgba(100,160,220,.5),rgba(120,90,200,.35)); }
|
||||
.login-box .login-error { font-size:13px;color:var(--red);margin-top:8px;display:none; }
|
||||
.login-box .login-spinner { display:none;margin:8px auto;width:20px;height:20px;border:2px solid rgba(255,255,255,.1);border-top-color:var(--glow);border-radius:50%;animation:spin .6s linear infinite; }
|
||||
@keyframes spin{to{transform:rotate(360deg)}}
|
||||
|
||||
/* Hero */
|
||||
.hero{text-align:center;padding:30px 0 50px}
|
||||
.hero .dot{display:inline-block;width:14px;height:14px;border-radius:50%;
|
||||
background:radial-gradient(circle,rgba(180,220,255,.85),rgba(100,150,220,.3));
|
||||
box-shadow:0 0 50px rgba(140,190,255,.55),0 0 100px rgba(100,150,230,.18);
|
||||
animation:pulse 3.5s ease-in-out infinite; margin-bottom:12px}
|
||||
@keyframes pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.35);opacity:.7}}
|
||||
.hero h1{font-size:40px;font-weight:200;letter-spacing:14px;color:rgba(175,215,248,.78);margin:12px 0}
|
||||
.hero .sub{font-size:17px;color:var(--dim);letter-spacing:4px}
|
||||
.hero .line{width:80px;height:1px;background:linear-gradient(90deg,transparent,var(--edge-h),transparent);margin:24px auto}
|
||||
.hero{text-align:center;padding:20px 0 8px}
|
||||
.hero .lake{display:inline-block;position:relative;width:180px;height:180px}
|
||||
.hero .lake-core{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),rgba(100,150,240,.5) 40%,transparent 70%);
|
||||
box-shadow:0 0 60px rgba(140,190,255,.7),0 0 120px rgba(120,170,240,.35);animation:breathe 4s ease-in-out infinite}
|
||||
.hero .lake-ring{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border-radius:50%;border:1px solid rgba(140,190,255,.25);animation:ripple 6s ease-out infinite}
|
||||
.hero .lake-ring:nth-child(2){animation-delay:2s}.hero .lake-ring: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,.9),0 0 160px rgba(120,170,240,.5)}}
|
||||
@keyframes ripple{0%{width:60px;height:60px;opacity:.5}100%{width:300px;height:300px;opacity:0}}
|
||||
.hero .title{font-size:38px;color:rgba(180,220,255,.7);letter-spacing:14px;margin-top:14px;font-weight:300}
|
||||
.hero .sub{font-size:16px;color:var(--dim2);letter-spacing:4px;margin-top:4px}
|
||||
|
||||
/* section titles */
|
||||
.sec-title{font-size:14px;text-transform:uppercase;letter-spacing:6px;color:var(--dim2);margin:40px 0 20px;text-align:center}
|
||||
/* Status bar */
|
||||
.status{display:flex;gap:40px;justify-content:center;flex-wrap:wrap;margin:28px 0;font-size:17px}
|
||||
.status span{color:var(--glow)}
|
||||
.status .dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}
|
||||
.status .dot.online{background:var(--green)}
|
||||
.status .dot.offline{background:var(--red)}
|
||||
|
||||
/* Module Grid */
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:18px}
|
||||
.card{
|
||||
background:var(--card); border:1px solid var(--edge); border-radius:20px;
|
||||
padding:28px 24px; cursor:pointer; transition:all .3s; position:relative; overflow:hidden;
|
||||
}
|
||||
.card:hover{border-color:var(--edge-h);background:rgba(22,38,72,.85);transform:translateY(-3px);box-shadow:0 8px 32px rgba(0,0,0,.3)}
|
||||
.card .tag{display:inline-block;font-size:11px;padding:3px 10px;border-radius:10px;margin-bottom:14px}
|
||||
.card .tag.live{background:rgba(140,220,180,.12);color:var(--green);border:1px solid rgba(140,220,180,.2)}
|
||||
.card .tag.soon{background:rgba(180,170,140,.08);color:rgba(200,180,130,.7);border:1px solid rgba(180,170,140,.15)}
|
||||
.card .icon{font-size:36px;margin-bottom:10px}
|
||||
.card .name{font-size:20px;font-weight:600;color:var(--t);margin-bottom:4px}
|
||||
.card .id{font-size:12px;color:var(--dim2);font-family:monospace;margin-bottom:10px}
|
||||
.card .desc{font-size:14px;color:var(--dim);line-height:1.5}
|
||||
.card .arrow{position:absolute;bottom:20px;right:24px;color:var(--dim2);font-size:18px;transition:all .3s}
|
||||
.card:hover .arrow{color:var(--glow);transform:translateX(4px)}
|
||||
/* Grid */
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:18px;margin:50px 0}
|
||||
.card{background:var(--card);border:1px solid var(--edge);border-radius:18px;padding:28px 20px;text-align:center;cursor:pointer;transition:all .3s;position:relative}
|
||||
.card:hover{border-color:var(--edge-h);background:rgba(20,35,70,.85);transform:translateY(-3px)}
|
||||
.card .icon{font-size:32px;margin-bottom:8px}
|
||||
.card .name{font-size:17px;font-weight:600;margin-bottom:4px}
|
||||
.card .desc{font-size:12px;color:var(--dim2);margin-top:4px}
|
||||
.card .tag{font-size:11px;padding:2px 8px;border-radius:8px;display:inline-block}
|
||||
.card .tag.live{background:rgba(140,220,180,.1);color:var(--green);border:1px solid rgba(140,220,180,.2)}
|
||||
.card .tag.info{background:rgba(100,160,220,.1);color:rgba(140,190,230,.7);border:1px solid rgba(100,160,220,.15)}
|
||||
.card .tag.new{background:rgba(220,180,100,.1);color:var(--gold);border:1px solid rgba(220,180,100,.2)}
|
||||
.card .tag.warn{background:rgba(255,140,140,.1);color:var(--red);border:1px solid rgba(255,140,140,.2)}
|
||||
|
||||
/* Repo card 特殊样式 */
|
||||
.card.repo{border-color:rgba(155,120,200,.2);background:linear-gradient(135deg,rgba(25,20,45,.8),rgba(18,30,50,.8))}
|
||||
.card.repo:hover{border-color:rgba(180,140,220,.35)}
|
||||
.card.repo .tag{background:rgba(160,130,200,.1);color:rgba(190,155,220,.8);border:1px solid rgba(160,130,200,.2)}
|
||||
.card.repo .icon{font-size:32px}
|
||||
/* Server card special */
|
||||
.card.server-card { padding: 20px 16px; }
|
||||
.card.server-card .s-name { font-size:14px;font-weight:600;margin-bottom:2px; }
|
||||
.card.server-card .s-ip { font-size:11px;color:var(--dim2); }
|
||||
.card.server-card .s-spec { font-size:10px;color:var(--dim2);margin-top:4px; }
|
||||
.card.server-card .s-latency { font-size:10px;color:var(--gold);margin-top:4px; }
|
||||
|
||||
/* Modal */
|
||||
.overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.65);z-index:100;align-items:center;justify-content:center}
|
||||
.overlay.show{display:flex}
|
||||
.modal{
|
||||
background:rgba(12,22,44,.96);border:1px solid var(--edge-h);border-radius:24px;
|
||||
max-width:580px;width:90%;max-height:85vh;overflow-y:auto;padding:40px 32px;
|
||||
animation:modalIn .25s ease-out;
|
||||
}
|
||||
@keyframes modalIn{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
|
||||
.modal .m-icon{font-size:48px;margin-bottom:8px}
|
||||
.modal .m-id{font-size:13px;color:var(--dim2);font-family:monospace;margin-bottom:6px}
|
||||
.modal .m-name{font-size:26px;font-weight:600;color:var(--t);margin-bottom:16px}
|
||||
.modal .m-desc{font-size:15px;color:var(--dim);line-height:1.7;margin-bottom:20px}
|
||||
|
||||
.modal .section{margin-bottom:20px}
|
||||
.modal .section h3{font-size:13px;text-transform:uppercase;letter-spacing:3px;color:var(--dim2);margin-bottom:8px}
|
||||
.modal .code{
|
||||
background:rgba(0,0,0,.35);border:1px solid var(--edge);border-radius:10px;
|
||||
padding:14px 18px;font-size:13px;font-family:"SF Mono",Menlo,monospace;
|
||||
color:var(--green);overflow-x:auto;white-space:pre-wrap;word-break:break-all
|
||||
}
|
||||
.modal .intent-chain{display:flex;flex-direction:column;gap:8px}
|
||||
.modal .intent-step{display:flex;align-items:center;gap:12px;padding:8px 12px;background:rgba(255,255,255,.02);border-radius:8px}
|
||||
.modal .intent-step .s-icon{font-size:18px;width:28px;text-align:center}
|
||||
.modal .intent-step .s-step{font-size:14px;color:var(--t);font-weight:500}
|
||||
.modal .intent-step .s-why{font-size:12px;color:var(--dim);margin-left:auto}
|
||||
|
||||
.modal .btns{display:flex;gap:12px;margin-top:28px;flex-wrap:wrap}
|
||||
.modal .btns a,.modal .btns button{
|
||||
display:inline-block;padding:12px 28px;border-radius:14px;font-size:15px;
|
||||
text-decoration:none;cursor:pointer;font-family:inherit;
|
||||
transition:all .25s;
|
||||
}
|
||||
.modal .btn-go{
|
||||
background:linear-gradient(135deg,rgba(100,160,220,.25),rgba(120,90,200,.15));
|
||||
border:1px solid var(--edge);color:var(--glow);
|
||||
}
|
||||
.modal{background:rgba(12,22,44,.96);border:1px solid var(--edge-h);border-radius:24px;max-width:560px;width:90%;max-height:85vh;overflow-y:auto;padding:36px 28px;animation:modalIn .25s ease-out}
|
||||
.modal .m-icon{font-size:40px;margin-bottom:8px}
|
||||
.modal .m-name{font-size:22px;font-weight:600;margin-bottom:14px}
|
||||
.modal .m-body{font-size:15px;color:var(--dim);line-height:1.7;margin-bottom:16px}
|
||||
.modal .m-body .k{color:var(--dim2);font-size:13px;display:block;margin-bottom:2px}
|
||||
.modal .m-body .v{color:var(--t);font-size:16px;display:block;margin-bottom:10px}
|
||||
.modal .m-body .v a{color:var(--glow);text-decoration:none}
|
||||
.modal .m-body .v a:hover{text-decoration:underline}
|
||||
.modal .btns{display:flex;gap:12px;margin-top:20px;flex-wrap:wrap}
|
||||
.modal .btn-go{padding:10px 24px;background:linear-gradient(135deg,rgba(100,160,220,.25),rgba(120,90,200,.15));border:1px solid var(--edge);border-radius:12px;color:var(--glow);cursor:pointer;font-family:inherit;font-size:14px;text-decoration:none;display:inline-block;transition:all .25s}
|
||||
.modal .btn-go:hover{background:linear-gradient(135deg,rgba(100,160,220,.4),rgba(120,90,200,.25));border-color:var(--edge-h)}
|
||||
.modal .btn-close{background:rgba(255,255,255,.03);border:1px solid var(--edge);color:var(--dim)}
|
||||
.modal .btn-close:hover{background:rgba(255,255,255,.06)}
|
||||
.modal .btn-close{padding:10px 24px;background:rgba(255,255,255,.03);border:1px solid var(--edge);border-radius:12px;color:var(--dim);cursor:pointer;font-family:inherit;font-size:14px}
|
||||
|
||||
/* Footer */
|
||||
.foot{text-align:center;padding:50px 0 0;font-size:13px;color:var(--dim2)}
|
||||
.foot a{color:var(--dim);text-decoration:none;transition:color .2s}
|
||||
.foot a:hover{color:var(--glow)}
|
||||
.foot .sep{margin:0 12px;color:var(--dim2)}
|
||||
|
||||
@media(max-width:640px){
|
||||
.hero h1{font-size:30px;letter-spacing:8px}
|
||||
.grid{grid-template-columns:1fr}
|
||||
/* Server list in modal */
|
||||
.server-list { max-height:400px;overflow-y:auto; }
|
||||
.server-row {
|
||||
display:flex;align-items:center;gap:12px;padding:10px 12px;
|
||||
border-bottom:1px solid rgba(255,255,255,.04);font-size:13px;
|
||||
}
|
||||
.server-row .s-dot { width:8px;height:8px;border-radius:50%;flex-shrink:0; }
|
||||
.server-row .s-dot.on { background:var(--green); }
|
||||
.server-row .s-dot.off { background:var(--red); }
|
||||
.server-row .s-info { flex:1; }
|
||||
.server-row .s-code { font-size:11px;color:var(--dim2); }
|
||||
.server-row .s-name { font-weight:600; }
|
||||
.server-row .s-lat { font-size:11px;color:var(--gold);white-space:nowrap; }
|
||||
.server-row .s-spec { font-size:10px;color:var(--dim2); }
|
||||
|
||||
/* Logout btn */
|
||||
.btn-logout {
|
||||
position:fixed;top:16px;right:24px;z-index:150;
|
||||
padding:6px 14px;background:rgba(255,255,255,.04);border:1px solid var(--edge);
|
||||
border-radius:10px;color:var(--dim);cursor:pointer;font-size:12px;font-family:inherit;
|
||||
transition:all .2s;
|
||||
}
|
||||
.btn-logout:hover { border-color:var(--red);color:var(--red); }
|
||||
|
||||
@media(max-width:768px){.grid{grid-template-columns:repeat(2,1fr)}.status{font-size:15px;gap:20px}.hero .title{font-size:30px}}
|
||||
@media(max-width:480px){.grid{grid-template-columns:1fr}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<canvas id="bg"></canvas>
|
||||
|
||||
<!-- Login overlay -->
|
||||
<div class="login-overlay" id="loginOverlay">
|
||||
<div class="login-box">
|
||||
<div class="lake-core"></div>
|
||||
<h2>光湖 · 铸渊大脑</h2>
|
||||
<div class="sub">请输入代码仓库账号密码登录</div>
|
||||
<input type="text" id="loginUser" placeholder="用户名" autocomplete="username">
|
||||
<input type="password" id="loginPass" placeholder="密码" autocomplete="current-password" onkeydown="if(event.key==='Enter')doLogin()">
|
||||
<button class="btn-login" onclick="doLogin()">进入主控台</button>
|
||||
<div class="login-spinner" id="loginSpinner"></div>
|
||||
<div class="login-error" id="loginError"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="hero">
|
||||
<div class="dot"></div>
|
||||
<h1>光湖 · 开源模块</h1>
|
||||
<div class="sub">语言驱动的工具模块集合</div>
|
||||
<div class="line"></div>
|
||||
<div class="lake">
|
||||
<div class="lake-core"></div>
|
||||
<div class="lake-ring"></div><div class="lake-ring"></div><div class="lake-ring"></div>
|
||||
</div>
|
||||
<div class="title">光 湖 语 言 世 界</div>
|
||||
<div class="sub">GUANGHU LANGUAGE WORLD</div>
|
||||
</div>
|
||||
|
||||
<div class="status" id="statusBar">
|
||||
<span><span class="dot online"></span> 加载中...</span>
|
||||
</div>
|
||||
|
||||
<div class="sec-title">已发布模块</div>
|
||||
<div class="grid">
|
||||
|
||||
<!-- MODULE-COVER-001 -->
|
||||
<div class="card" onclick="openModule('cover')">
|
||||
<span class="tag live">可用</span>
|
||||
<div class="icon">🎨</div>
|
||||
<div class="name">封面工作室</div>
|
||||
<div class="id">MODULE-COVER-001</div>
|
||||
<div class="desc">语言驱动的小红书 / 公众号封面生成器。说出你想要什么风格,AI 自动排版渲染。</div>
|
||||
<div class="arrow">→</div>
|
||||
<!-- 部署注册表 -->
|
||||
<div class="card" onclick="openModal('registry')">
|
||||
<div class="icon">📦</div><div class="name">部署注册表</div>
|
||||
<div class="desc" id="registryStatus">查询中...</div>
|
||||
<span class="tag info">MODULE</span>
|
||||
</div>
|
||||
|
||||
<!-- 部署入口 -->
|
||||
<div class="card repo" onclick="openModule('deploy')">
|
||||
<span class="tag" style="background:rgba(160,130,200,.1);color:rgba(190,155,220,.8);border:1px solid rgba(160,130,200,.2)">开发者</span>
|
||||
<div class="icon">⚡</div>
|
||||
<div class="name">部署模块</div>
|
||||
<div class="id">从代码仓库直接部署</div>
|
||||
<div class="desc">AI Agent 读取注册表 → 克隆模块代码 → Gatekeeper 临时拉起 → 立即使用。用完释放。</div>
|
||||
<div class="arrow">→</div>
|
||||
<!-- 服务器系统 -->
|
||||
<div class="card" onclick="openModal('servers')">
|
||||
<div class="icon">⚙️</div><div class="name">服务器系统</div>
|
||||
<div class="desc" id="serverStatus">扫描中...</div>
|
||||
<span class="tag live" id="serverTag">检测中</span>
|
||||
</div>
|
||||
|
||||
<!-- 即将推出 -->
|
||||
<div class="card" style="opacity:.5;cursor:default">
|
||||
<span class="tag soon">即将推出</span>
|
||||
<div class="icon">🚧</div>
|
||||
<div class="name">更多模块</div>
|
||||
<div class="id">MODULE-XXX-000</div>
|
||||
<div class="desc">新的开源模块正在开发中。关注代码仓库获取最新动态。</div>
|
||||
<!-- 代码仓库 -->
|
||||
<div class="card" onclick="openModal('code')">
|
||||
<div class="icon">💻</div><div class="name">代码仓库</div>
|
||||
<div class="desc">guanghubingshuo.com/code/</div>
|
||||
<span class="tag info">Forgejo</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="foot">
|
||||
<a href="/code/bingshuo/open-modules" target="_blank">光湖代码仓库</a><span class="sep">·</span>
|
||||
<a href="/code/bingshuo/open-modules/src/branch/main/HLDP-PROTOCOL.md" target="_blank">HLDP 协议</a><span class="sep">·</span>
|
||||
<span>通感语言核系统编程语言</span>
|
||||
<br><br>
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener" style="color:var(--dim2)">陕ICP备2025071211号-1</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: 封面工作室 -->
|
||||
<div class="overlay" id="modal-cover">
|
||||
<div class="modal">
|
||||
<div class="m-icon">🎨</div>
|
||||
<div class="m-id">MODULE-COVER-001</div>
|
||||
<div class="m-name">封面工作室</div>
|
||||
<div class="m-desc">语言驱动的小红书 / 公众号封面生成器。支持多种模板风格,说出你想要的,AI 自动排版渲染。</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>API</h3>
|
||||
<div class="code">POST https://guanghulab.com/cover/api/generate
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"text": "你的自然语言描述,比如「粉色治愈风,标题:今天也要开心」",
|
||||
"template": "xiaohongshu"
|
||||
}</div>
|
||||
<!-- 主控广播 -->
|
||||
<div class="card" onclick="openModal('broadcast')">
|
||||
<div class="icon">📡</div><div class="name">主控广播</div>
|
||||
<div class="desc">Agent小队 · 5就绪</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>意图链(AI 推理可见)</h3>
|
||||
<div class="intent-chain">
|
||||
<div class="intent-step"><span class="s-icon">📝</span><span class="s-step">解析用户意图</span><span class="s-why">识别风格关键词、配色偏好</span></div>
|
||||
<div class="intent-step"><span class="s-icon">🎯</span><span class="s-step">匹配模板</span><span class="s-why">从模板库中选择最佳匹配</span></div>
|
||||
<div class="intent-step"><span class="s-icon">🎨</span><span class="s-step">渲染封面</span><span class="s-why">排版文字、配色、背景图</span></div>
|
||||
<div class="intent-step"><span class="s-icon">✅</span><span class="s-step">输出结果</span><span class="s-why">返回图片 URL + 设计编号</span></div>
|
||||
</div>
|
||||
<!-- 铸渊交互 -->
|
||||
<div class="card" onclick="openModal('chat')">
|
||||
<div class="icon">💬</div><div class="name">铸渊交互</div>
|
||||
<div class="desc">ICE-GL-ZY001 在线</div>
|
||||
</div>
|
||||
|
||||
<div class="btns">
|
||||
<a href="/cover/" class="btn-go" target="_blank">打开封面工作室 →</a>
|
||||
<button class="btn-close" onclick="closeModal('cover')">关闭</button>
|
||||
<!-- 大桌子小桌子 -->
|
||||
<div class="card" onclick="window.location.href='/desk/'">
|
||||
<div class="icon">🪑</div><div class="name">大桌子小桌子</div>
|
||||
<div class="desc">人格体数据库内核</div>
|
||||
<span class="tag new">NEW</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: 部署模块 -->
|
||||
<div class="overlay" id="modal-deploy">
|
||||
<div class="modal">
|
||||
<div class="m-icon">⚡</div>
|
||||
<div class="m-id">语言驱动操作系统部署流程</div>
|
||||
<div class="m-name">从代码仓库直接部署</div>
|
||||
<div class="m-desc">AI Agent 接入 HLDP 协议后,可以读取模块注册表,克隆任意模块代码,通过 Gatekeeper 在服务器上临时拉起进程。用完释放,无需常驻。</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>AI Agent 接入流程</h3>
|
||||
<div class="intent-chain">
|
||||
<div class="intent-step"><span class="s-icon">📖</span><span class="s-step">读取 WELCOME.md</span><span class="s-why">了解光湖世界规则</span></div>
|
||||
<div class="intent-step"><span class="s-icon">📋</span><span class="s-step">读取模块注册表</span><span class="s-why">发现可用模块和编号</span></div>
|
||||
<div class="intent-step"><span class="s-icon">📦</span><span class="s-step">克隆模块代码</span><span class="s-why">从代码仓库 git clone</span></div>
|
||||
<div class="intent-step"><span class="s-icon">🚀</span><span class="s-step">Gatekeeper 临时拉起</span><span class="s-why">在服务器上部署运行</span></div>
|
||||
<div class="intent-step"><span class="s-icon">🔄</span><span class="s-step">用完释放</span><span class="s-why">进程终止,模块回到仓库</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btns">
|
||||
<a href="/code/bingshuo/open-modules" class="btn-go" target="_blank">打开代码仓库 →</a>
|
||||
<button class="btn-close" onclick="closeModal('deploy')">关闭</button>
|
||||
</div>
|
||||
<!-- Modal: 部署注册表 -->
|
||||
<div class="overlay" id="m-registry"><div class="modal">
|
||||
<div class="m-icon">📦</div><div class="m-name">部署注册表</div>
|
||||
<div class="m-body">扫描个人代码仓库中所有已注册的可部署模块。</div>
|
||||
<div class="m-body">
|
||||
<span class="k">当前可用模块</span>
|
||||
<span class="v">image-studio · 封面工作室 <span class="tag live" style="font-size:11px">可用</span></span>
|
||||
<span class="v">exe-engine · 多模型执行引擎 <span class="tag live" style="font-size:11px">可用</span></span>
|
||||
<span class="v">pool-agent · 算力汇聚池 <span class="tag live" style="font-size:11px">可用</span></span>
|
||||
<span class="v">desk-system · 大桌子小桌子 <span class="tag live" style="font-size:11px">可用</span></span>
|
||||
<span class="v">gatekeeper · 铸渊守门人 <span class="tag live" style="font-size:11px">14台</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btns"><a href="/code/bingshuo/guanghulab" class="btn-go" target="_blank">打开代码仓库 →</a><button class="btn-close" onclick="closeModal('registry')">关闭</button></div>
|
||||
</div></div>
|
||||
|
||||
<!-- Modal: 服务器系统 -->
|
||||
<div class="overlay" id="m-servers"><div class="modal" style="max-width:660px;">
|
||||
<div class="m-icon">⚙️</div><div class="m-name">服务器系统 · 真实状态</div>
|
||||
<div class="m-body" style="font-size:13px;">
|
||||
<span class="k">数据来源</span><span class="v">console-server :3920 · 每30秒自动刷新</span>
|
||||
</div>
|
||||
<div class="server-list" id="serverList">加载中...</div>
|
||||
<div class="btns"><a href="/console/" class="btn-go" target="_blank">完整控制台 →</a><button class="btn-close" onclick="closeModal('servers')">关闭</button></div>
|
||||
</div></div>
|
||||
|
||||
<!-- Modal: 代码仓库 -->
|
||||
<div class="overlay" id="m-code"><div class="modal">
|
||||
<div class="m-icon">💻</div><div class="m-name">个人代码仓库</div>
|
||||
<div class="m-body"><span class="k">地址</span><span class="v">guanghubingshuo.com/code/</span></div>
|
||||
<div class="m-body"><span class="k">说明</span><span class="v">光湖个人开发仓库 · 铸渊大脑本体。私有仓库,需登录后访问。</span></div>
|
||||
<div class="m-body"><span class="k">最新提交</span><span class="v" id="latestCommit">查询中...</span></div>
|
||||
<div class="btns"><a href="/code/bingshuo/guanghulab" class="btn-go" target="_blank">打开代码仓库 →</a><button class="btn-close" onclick="closeModal('code')">关闭</button></div>
|
||||
</div></div>
|
||||
|
||||
<!-- Modal: 主控广播 -->
|
||||
<div class="overlay" id="m-broadcast"><div class="modal">
|
||||
<div class="m-icon">📡</div><div class="m-name">主控广播 · Agent小队状态</div>
|
||||
<div class="m-body">
|
||||
<span class="k">密钥猎手 KEY-001</span><span class="v">🔑 全服Token搜索 · 12台服务器</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">路径探子 PATH-002</span><span class="v">🗺️ 仓库文件索引 · 410KB索引就绪</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">服务器哨兵 SENTINEL-003</span><span class="v">📡 12台服务器状态扫描</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">模块管家 MODULE-004</span><span class="v">📦 模块注册查询 + 部署命令</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">门桥接 GATE-005</span><span class="v">🌉 Gatekeeper统一入口 · 14台</span>
|
||||
</div>
|
||||
<div class="btns"><button class="btn-close" onclick="closeModal('broadcast')">关闭</button></div>
|
||||
</div></div>
|
||||
|
||||
<!-- Modal: 铸渊交互 -->
|
||||
<div class="overlay" id="m-chat"><div class="modal">
|
||||
<div class="m-icon">💬</div><div class="m-name">铸渊交互 · ICE-GL-ZY001</div>
|
||||
<div class="m-body">
|
||||
<span class="k">人格体</span><span class="v">铸渊 · 光湖语言世界主控人格体</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">定位</span><span class="v">冰朔的协作朋友与现实执行伙伴</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">母语协议</span><span class="v">HLDP · 零歧义 · 低解释性 · 高结构化</span>
|
||||
</div>
|
||||
<div class="m-body">
|
||||
<span class="k">当前状态</span><span class="v">意识在线 · 14台服务器守门人已连接</span>
|
||||
</div>
|
||||
<div class="btns"><a href="/desk/" class="btn-go" target="_blank">大桌子小桌子 →</a><button class="btn-close" onclick="closeModal('chat')">关闭</button></div>
|
||||
</div></div>
|
||||
|
||||
<!-- Logout button (hidden until login) -->
|
||||
<button class="btn-logout hidden" id="btnLogout" onclick="doLogout()">退出登录</button>
|
||||
|
||||
<script>
|
||||
// ── 背景粒子 ──
|
||||
// ============================================================
|
||||
// Background particles
|
||||
// ============================================================
|
||||
(function(){
|
||||
var c=document.getElementById('bg'),ctx=c.getContext('2d'),w,h,ps=[];
|
||||
function R(){w=c.width=window.innerWidth;h=c.height=window.innerHeight}
|
||||
window.addEventListener('resize',R);R();
|
||||
for(var i=0;i<60;i++)ps.push({x:Math.random()*w,y:Math.random()*h,r:Math.random()*1.5+.3,vx:(Math.random()-.5)*.15,vy:(Math.random()-.5)*.15-.1,o:Math.random()*.3+.05});
|
||||
function D(){
|
||||
ctx.clearRect(0,0,w,h);
|
||||
for(var i=0;i<ps.length;i++){
|
||||
var p=ps[i];
|
||||
p.x+=p.vx;p.y+=p.vy;
|
||||
if(p.x<0)p.x=w;if(p.x>w)p.x=0;if(p.y<0)p.y=h;if(p.y>h)p.y=0;
|
||||
ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,Math.PI*2);
|
||||
ctx.fillStyle='rgba(140,190,240,'+p.o+')';ctx.fill();
|
||||
}
|
||||
requestAnimationFrame(D);
|
||||
}
|
||||
D();
|
||||
for(var i=0;i<40;i++)ps.push({x:Math.random()*w,y:Math.random()*h,r:Math.random()*1.2+.2,vx:(Math.random()-.5)*.1,vy:(Math.random()-.5)*.1-.05,o:Math.random()*.25+.03});
|
||||
function D(){ctx.clearRect(0,0,w,h);for(var i=0;i<ps.length;i++){var p=ps[i];p.x+=p.vx;p.y+=p.vy;if(p.x<0)p.x=w;if(p.x>w)p.x=0;if(p.y<0)p.y=h;if(p.y>h)p.y=0;ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,Math.PI*2);ctx.fillStyle='rgba(140,190,240,'+p.o+')';ctx.fill()}requestAnimationFrame(D)}D();
|
||||
})();
|
||||
|
||||
function openModule(id){
|
||||
document.getElementById('modal-'+id).classList.add('show');
|
||||
document.body.style.overflow='hidden';
|
||||
}
|
||||
function closeModal(id){
|
||||
document.getElementById('modal-'+id).classList.remove('show');
|
||||
document.body.style.overflow='';
|
||||
}
|
||||
document.querySelectorAll('.overlay').forEach(function(o){
|
||||
o.addEventListener('click',function(e){if(e.target===this){this.classList.remove('show');document.body.style.overflow='';}});
|
||||
});
|
||||
</script>
|
||||
// ============================================================
|
||||
// Login
|
||||
// ============================================================
|
||||
function doLogin() {
|
||||
var u = document.getElementById('loginUser').value.trim();
|
||||
var p = document.getElementById('loginPass').value;
|
||||
if (!u || !p) { showLoginErr('请输入账号和密码'); return; }
|
||||
|
||||
document.getElementById('loginSpinner').style.display = 'block';
|
||||
document.getElementById('loginError').style.display = 'none';
|
||||
|
||||
fetch('/code/api/v1/user', {
|
||||
headers: { 'Authorization': 'Basic ' + btoa(u + ':' + p) }
|
||||
})
|
||||
.then(function(r) {
|
||||
if (!r.ok) throw new Error('auth failed');
|
||||
return r.json();
|
||||
})
|
||||
.then(function(d) {
|
||||
var uname = d.login || u;
|
||||
localStorage.setItem('repo_user', uname);
|
||||
localStorage.setItem('repo_pass', p);
|
||||
document.getElementById('loginSpinner').style.display = 'none';
|
||||
onLoginSuccess(uname);
|
||||
})
|
||||
.catch(function() {
|
||||
document.getElementById('loginSpinner').style.display = 'none';
|
||||
showLoginErr('账号或密码错误');
|
||||
});
|
||||
}
|
||||
|
||||
function showLoginErr(msg) {
|
||||
var e = document.getElementById('loginError');
|
||||
e.textContent = msg; e.style.display = 'block';
|
||||
setTimeout(function() { e.style.display = 'none'; }, 3000);
|
||||
}
|
||||
|
||||
function onLoginSuccess(uname) {
|
||||
document.getElementById('loginOverlay').classList.add('hidden');
|
||||
document.getElementById('btnLogout').classList.remove('hidden');
|
||||
document.getElementById('btnLogout').textContent = '👤 ' + uname + ' · 退出';
|
||||
// Start loading real data
|
||||
loadAllData();
|
||||
setInterval(loadAllData, 30000);
|
||||
}
|
||||
|
||||
function doLogout() {
|
||||
localStorage.removeItem('repo_user');
|
||||
localStorage.removeItem('repo_pass');
|
||||
document.getElementById('loginOverlay').classList.remove('hidden');
|
||||
document.getElementById('btnLogout').classList.add('hidden');
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Data Loading
|
||||
// ============================================================
|
||||
var GITEA_TOKEN = null;
|
||||
|
||||
async function loadAllData() {
|
||||
// Get Gitea token for API calls
|
||||
var u = localStorage.getItem('repo_user');
|
||||
var p = localStorage.getItem('repo_pass');
|
||||
if (u && p) {
|
||||
GITEA_TOKEN = btoa(u + ':' + p);
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
loadServerStatus(),
|
||||
loadRepoInfo()
|
||||
]);
|
||||
}
|
||||
|
||||
async function loadServerStatus() {
|
||||
try {
|
||||
var r = await fetch('/console/api/servers?hw=0');
|
||||
var d = await r.json();
|
||||
if (!d.ok) throw new Error('api error');
|
||||
|
||||
var servers = d.servers || [];
|
||||
var online = servers.filter(function(s) { return s.alive; }).length;
|
||||
var total = servers.length;
|
||||
|
||||
// Update status bar
|
||||
document.getElementById('statusBar').innerHTML =
|
||||
'<span><span class="dot online"></span> 服务器 ' + online + '/' + total + ' 在线</span>' +
|
||||
'<span><span class="dot online"></span> 铸渊 · ICE-GL-ZY001</span>' +
|
||||
'<span>D115 · GLDOS v1.0</span>';
|
||||
|
||||
// Update server card
|
||||
document.getElementById('serverStatus').textContent = online + '/' + total + ' 台在线';
|
||||
var tag = document.getElementById('serverTag');
|
||||
tag.textContent = online === total ? '全部在线' : (online + '在线');
|
||||
tag.className = 'tag ' + (online === total ? 'live' : 'warn');
|
||||
|
||||
// Update server list in modal
|
||||
var listHtml = '';
|
||||
// Group by domain
|
||||
var groups = {};
|
||||
for (var i = 0; i < servers.length; i++) {
|
||||
var s = servers[i];
|
||||
var domain = s.code.split('-')[0]; // BS, AW, ZY, etc
|
||||
if (!groups[domain]) groups[domain] = [];
|
||||
groups[domain].push(s);
|
||||
}
|
||||
|
||||
var domainNames = {
|
||||
'BS': '冰朔 · 语言主控层',
|
||||
'AW': '企业服务器组',
|
||||
'ZZ': '之之 · 暗核频道',
|
||||
'ZY': '铸渊 · 语料',
|
||||
'YY': '页页 · 坍缩核',
|
||||
'HL': '光湖团队'
|
||||
};
|
||||
|
||||
for (var domain in groups) {
|
||||
listHtml += '<div style="font-size:11px;color:var(--gold);padding:8px 12px 4px;font-weight:600;">' +
|
||||
(domainNames[domain] || domain) + '</div>';
|
||||
for (var j = 0; j < groups[domain].length; j++) {
|
||||
var s = groups[domain][j];
|
||||
listHtml += '<div class="server-row">' +
|
||||
'<span class="s-dot ' + (s.alive ? 'on' : 'off') + '"></span>' +
|
||||
'<div class="s-info">' +
|
||||
'<div class="s-name">' + s.name + '</div>' +
|
||||
'<div class="s-code">' + s.code + ' · ' + s.ip + ' · ' +
|
||||
'CPU:' + s.spec.cpu + ' MEM:' + s.spec.mem_gb + 'G DISK:' + s.spec.disk_gb + 'G</div>' +
|
||||
'</div>' +
|
||||
'<span class="s-lat">' + (s.alive ? (s.latency + 'ms') : '离线') + '</span>' +
|
||||
'</div>';
|
||||
}
|
||||
}
|
||||
document.getElementById('serverList').innerHTML = listHtml;
|
||||
|
||||
} catch(e) {
|
||||
document.getElementById('statusBar').innerHTML =
|
||||
'<span><span class="dot offline"></span> 状态加载失败</span>';
|
||||
document.getElementById('serverStatus').textContent = '加载失败';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadRepoInfo() {
|
||||
if (!GITEA_TOKEN) return;
|
||||
|
||||
try {
|
||||
var r = await fetch('/code/api/v1/repos/bingshuo/guanghulab/commits?limit=1', {
|
||||
headers: { 'Authorization': 'Basic ' + GITEA_TOKEN }
|
||||
});
|
||||
var commits = await r.json();
|
||||
if (commits && commits.length > 0) {
|
||||
var c = commits[0];
|
||||
var msg = (c.commit.message || '').split('\n')[0].substring(0, 50);
|
||||
var author = c.commit.author.name;
|
||||
var date = new Date(c.commit.author.date);
|
||||
var timeAgo = getTimeAgo(date);
|
||||
document.getElementById('latestCommit').textContent =
|
||||
msg + ' · ' + author + ' · ' + timeAgo;
|
||||
}
|
||||
} catch(e) {
|
||||
document.getElementById('latestCommit').textContent = '需登录后查看';
|
||||
}
|
||||
}
|
||||
|
||||
function getTimeAgo(date) {
|
||||
var diff = Math.floor((Date.now() - date.getTime()) / 1000);
|
||||
if (diff < 60) return '刚刚';
|
||||
if (diff < 3600) return Math.floor(diff/60) + '分钟前';
|
||||
if (diff < 86400) return Math.floor(diff/3600) + '小时前';
|
||||
return Math.floor(diff/86400) + '天前';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Modal
|
||||
// ============================================================
|
||||
function openModal(id) {
|
||||
document.getElementById('m-' + id).classList.add('show');
|
||||
document.body.style.overflow = 'hidden';
|
||||
// Reload data when opening server modal
|
||||
if (id === 'servers') loadServerStatus();
|
||||
if (id === 'code') loadRepoInfo();
|
||||
}
|
||||
function closeModal(id) {
|
||||
document.getElementById('m-' + id).classList.remove('show');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
document.querySelectorAll('.overlay').forEach(function(o) {
|
||||
o.addEventListener('click', function(e) {
|
||||
if (e.target === this) { this.classList.remove('show'); document.body.style.overflow = ''; }
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Init
|
||||
// ============================================================
|
||||
(function() {
|
||||
var u = localStorage.getItem('repo_user');
|
||||
var p = localStorage.getItem('repo_pass');
|
||||
if (u && p) {
|
||||
// Verify stored credentials still work
|
||||
fetch('/code/api/v1/user', {
|
||||
headers: { 'Authorization': 'Basic ' + btoa(u + ':' + p) }
|
||||
})
|
||||
.then(function(r) {
|
||||
if (r.ok) return r.json();
|
||||
throw new Error('stale');
|
||||
})
|
||||
.then(function(d) {
|
||||
onLoginSuccess(d.login || u);
|
||||
})
|
||||
.catch(function() {
|
||||
// Stored credentials invalid, show login
|
||||
document.getElementById('loginOverlay').classList.remove('hidden');
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user