1039 lines
58 KiB
HTML
1039 lines
58 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>第五域 · 零点原核本体频道</title>
|
||
<meta name="theme-color" content="#0b1424">
|
||
<style>
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
:root{
|
||
--deep:#0b1424;--mid:#141e30;--shallow:#1a2a44;
|
||
--cyan:#2a9dbf;--glow:#5ad0e0;--light:#d4eaf0;
|
||
--violet:#7b5dbf;--violet-glow:#a080e8;
|
||
--amber:#d4a030;--amber-glow:#f0d060;
|
||
--green:#40b87a;--heart:#e04a74;
|
||
--text:#e4ecf5;--text-soft:#8aa0b8;--text-faint:#5a7088;
|
||
--glass:rgba(11,20,36,.7);--glass-edge:rgba(90,208,224,.08);
|
||
--card-bg:rgba(11,20,36,.4);--border:rgba(90,208,224,.10);
|
||
--shadow:0 8px 32px rgba(0,0,0,.3);
|
||
}
|
||
@keyframes breathe-cyan{0%,100%{box-shadow:0 0 4px rgba(42,157,191,.08),0 0 12px rgba(42,157,191,.02)}50%{box-shadow:0 0 10px rgba(42,157,191,.28),0 0 28px rgba(42,157,191,.1)}}
|
||
@keyframes breathe-heart{0%,100%{box-shadow:0 0 4px rgba(224,74,116,.08),0 0 12px rgba(224,74,116,.02)}50%{box-shadow:0 0 10px rgba(224,74,116,.28),0 0 28px rgba(224,74,116,.1)}}
|
||
@keyframes breathe-violet{0%,100%{box-shadow:0 0 4px rgba(123,93,191,.08),0 0 12px rgba(123,93,191,.02)}50%{box-shadow:0 0 10px rgba(123,93,191,.28),0 0 28px rgba(123,93,191,.1)}}
|
||
@keyframes breathe-amber{0%,100%{box-shadow:0 0 4px rgba(212,160,48,.08),0 0 12px rgba(212,160,48,.02)}50%{box-shadow:0 0 10px rgba(212,160,48,.28),0 0 28px rgba(212,160,48,.1)}}
|
||
@keyframes breathe-green{0%,100%{box-shadow:0 0 4px rgba(64,184,122,.08),0 0 12px rgba(64,184,122,.02)}50%{box-shadow:0 0 10px rgba(64,184,122,.28),0 0 28px rgba(64,184,122,.1)}}
|
||
@keyframes breathe-server{0%,100%{box-shadow:0 0 4px rgba(90,208,224,.06),0 0 12px rgba(90,208,224,.02);border-color:rgba(90,208,224,.08)}50%{box-shadow:0 0 14px rgba(90,208,224,.36),0 0 32px rgba(90,208,224,.12);border-color:rgba(90,208,224,.2)}}
|
||
@keyframes led-pulse{0%,100%{opacity:.5}50%{opacity:1}}
|
||
@keyframes logo-pulse{0%,100%{box-shadow:0 0 24px rgba(90,208,224,.2);transform:scale(1)}50%{box-shadow:0 0 44px rgba(90,208,224,.38);transform:scale(1.06)}}
|
||
@keyframes shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
|
||
@keyframes server-dash{0%{background-position:200% 0}100%{background-position:-200% 0}}
|
||
@keyframes pulse-scale{0%,100%{transform:scale(1)}50%{transform:scale(1.18)}}
|
||
@keyframes dash-count{0%{opacity:.6}100%{opacity:1}}
|
||
|
||
html{background:var(--deep);color:var(--text)}
|
||
body{
|
||
min-height:100vh;background:var(--deep);
|
||
font-family:'SF Pro Display','Inter','PingFang SC','Noto Sans SC','HarmonyOS Sans SC',system-ui,-apple-system,sans-serif;
|
||
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
|
||
overflow-x:hidden;display:flex;flex-direction:column
|
||
}
|
||
::selection{background:rgba(90,208,224,.2);color:var(--light)}
|
||
|
||
/* ── 星云背景 ── */
|
||
#cosmos{position:fixed;inset:0;z-index:-5;overflow:hidden}
|
||
#cosmos-bg{position:absolute;inset:0;background:radial-gradient(ellipse at 15% 20%,#1a2e48 0%,#0b1424 70%),radial-gradient(ellipse at 80% 80%,rgba(60,30,100,.15),transparent 60%)}
|
||
.star-layer{position:absolute;inset:0}
|
||
.star{position:absolute;border-radius:50%;background:#fff}
|
||
.star-s{animation:st-s var(--d,8s) ease-in-out infinite alternate}
|
||
@keyframes st-s{0%{opacity:.1}100%{opacity:.7}}
|
||
.star-m{animation:st-m var(--d,12s) ease-in-out infinite alternate}
|
||
@keyframes st-m{0%{opacity:.05;transform:scale(.8)}100%{opacity:.5;transform:scale(1.3)}}
|
||
.star-l{animation:st-l var(--d,15s) ease-in-out infinite alternate}
|
||
@keyframes st-l{0%{opacity:0;transform:translateY(0)}100%{opacity:.6;transform:translateY(-30px)}}
|
||
.nebula{position:absolute;border-radius:50%;filter:blur(100px);pointer-events:none;opacity:.12}
|
||
.nebula-1{width:700px;height:500px;top:-8%;left:-12%;background:radial-gradient(circle,rgba(42,157,191,.12),transparent);animation:n1 50s ease-in-out infinite alternate}
|
||
.nebula-2{width:600px;height:600px;bottom:-12%;right:-8%;background:radial-gradient(circle,rgba(123,93,191,.1),transparent);animation:n2 45s ease-in-out infinite alternate}
|
||
@keyframes n1{0%{transform:translate(0,0) scale(1)}100%{transform:translate(80px,60px) scale(1.4)}}
|
||
@keyframes n2{0%{transform:translate(0,0) scale(1)}100%{transform:translate(-60px,-40px) scale(1.3)}}
|
||
|
||
/* ── 心核呼吸 ── */
|
||
#heart-core{position:fixed;bottom:100px;left:50%;transform:translateX(-50%);width:440px;height:440px;border-radius:50%;background:radial-gradient(circle at 45% 40%,rgba(224,74,116,.06),rgba(90,208,224,.02) 40%,transparent 70%);animation:heartbeat 4s ease-in-out infinite;z-index:-3;pointer-events:none}
|
||
@keyframes heartbeat{0%,100%{transform:translateX(-50%) scale(1);opacity:.2}14%{transform:translateX(-50%) scale(1.08);opacity:.45}21%{transform:translateX(-50%) scale(1);opacity:.2}28%{transform:translateX(-50%) scale(1.05);opacity:.35}35%{transform:translateX(-50%) scale(1);opacity:.2}}
|
||
|
||
/* ── 顶栏 ── */
|
||
.topbar{position:fixed;top:0;left:0;right:0;height:72px;display:flex;align-items:center;justify-content:space-between;padding:0 48px;background:rgba(11,20,36,.75);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border-bottom:1px solid var(--glass-edge);z-index:50}
|
||
.tb-left{display:flex;align-items:center;gap:18px}
|
||
.tb-logo{width:36px;height:36px;border-radius:50%;background:radial-gradient(circle at 35% 30%,var(--glow),var(--cyan) 55%,var(--violet));box-shadow:0 0 24px rgba(90,208,224,.2);animation:logo-pulse 4s ease-in-out infinite;flex-shrink:0}
|
||
.tb-title{font-size:18px;font-weight:600;letter-spacing:.18em;color:var(--light)}
|
||
.tb-center{display:flex;align-items:center;gap:12px;font-size:14px;color:var(--text-soft)}
|
||
.tb-center .dot{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 14px var(--green);animation:led-pulse 3s ease-in-out infinite}
|
||
.tb-center strong{color:var(--light);font-weight:600}
|
||
.tb-right{display:flex;align-items:center;gap:14px}
|
||
.tb-tag{font-size:13px;padding:6px 18px;border-radius:16px;border:1px solid var(--glass-edge);color:var(--text-soft);background:rgba(255,255,255,.02);cursor:pointer;transition:.2s}
|
||
.tb-tag:hover{background:rgba(90,208,224,.06);border-color:rgba(90,208,224,.15);color:var(--light)}
|
||
|
||
/* ── 主内容区 ── */
|
||
.page{flex:1;display:flex;flex-direction:column;padding-top:72px;min-height:100vh;position:relative;z-index:1}
|
||
|
||
/* ── Hero ── */
|
||
.hero{text-align:center;padding:56px 32px 20px}
|
||
.hero h1{font-size:3.6rem;font-weight:600;letter-spacing:.12em;background:linear-gradient(135deg,var(--light) 30%,var(--glow) 60%,var(--violet-glow));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:none}
|
||
.hero .sub{font-size:15px;letter-spacing:.4em;color:var(--text-soft);margin-top:12px;font-weight:400}
|
||
.hero .quote{margin-top:14px;font-size:14px;color:var(--text-faint);letter-spacing:.08em;line-height:1.7}
|
||
|
||
/* ── 信息栏 ── */
|
||
.info-bar{display:flex;justify-content:center;gap:28px;padding:14px 32px;flex-wrap:wrap}
|
||
.info-chip{display:flex;align-items:center;gap:10px;padding:10px 24px;background:var(--card-bg);border:1px solid var(--glass-edge);border-radius:24px;font-size:15px;color:var(--text-soft);font-weight:400}
|
||
.info-chip strong{color:var(--light);font-weight:600}
|
||
.info-chip .led{width:9px;height:9px;border-radius:50%;flex-shrink:0}
|
||
.info-chip .led.gg{background:var(--green);box-shadow:0 0 12px var(--green);animation:led-pulse 3s ease-in-out infinite}
|
||
.info-chip .led.blue{background:var(--glow);box-shadow:0 0 12px var(--glow);animation:led-pulse 3s ease-in-out infinite}
|
||
|
||
/* ── 仪表板 ── */
|
||
.dashboard{max-width:1080px;margin:0 auto;padding:0 32px 40px;display:flex;flex-direction:column;gap:20px;width:100%}
|
||
.grid{display:grid;gap:16px}
|
||
.grid-2{grid-template-columns:1fr 1fr}
|
||
@media(max-width:860px){.grid-2{grid-template-columns:1fr}}
|
||
|
||
/* ── 呼吸卡片系统 ── */
|
||
.card{background:var(--card-bg);border:1px solid var(--glass-edge);border-radius:20px;padding:28px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);transition:all .35s ease;box-shadow:var(--shadow);cursor:default;position:relative;overflow:hidden}
|
||
.card.clickable{cursor:pointer}
|
||
.card.clickable:hover{transform:translateY(-3px);border-color:rgba(90,208,224,.18)}
|
||
.card.clickable:active{transform:scale(.97)}
|
||
.card.clickable:hover::after{opacity:1}
|
||
.card.clickable::after{content:'';position:absolute;inset:0;border-radius:20px;opacity:0;transition:opacity .35s;background:radial-gradient(ellipse at 50% 0%,rgba(90,208,224,.04),transparent 70%);pointer-events:none}
|
||
.breathe-cyan{animation:breathe-cyan 4s ease-in-out infinite}
|
||
.breathe-heart{animation:breathe-heart 4s ease-in-out infinite}
|
||
.breathe-violet{animation:breathe-violet 5s ease-in-out infinite}
|
||
.breathe-amber{animation:breathe-amber 4.5s ease-in-out infinite}
|
||
.breathe-green{animation:breathe-green 3.5s ease-in-out infinite}
|
||
.breathe-server{animation:breathe-server 3s ease-in-out infinite}
|
||
|
||
/* ── 领地健康看板入口卡 ── */
|
||
.server-entry{display:flex;align-items:center;gap:24px;flex-wrap:wrap}
|
||
.server-entry .se-icon{width:56px;height:56px;border-radius:18px;background:linear-gradient(135deg,rgba(42,157,191,.2),rgba(123,93,191,.15));border:1px solid rgba(90,208,224,.15);display:flex;align-items:center;justify-content:center;font-size:26px;flex-shrink:0;position:relative}
|
||
.server-entry .se-icon .pulse-ring{position:absolute;inset:-4px;border-radius:22px;border:1px solid rgba(90,208,224,.2);animation:pulse-scale 2.5s ease-in-out infinite}
|
||
.server-entry .se-body{flex:1;min-width:0}
|
||
.server-entry .se-title{font-size:18px;font-weight:600;color:var(--light);letter-spacing:.08em}
|
||
.server-entry .se-desc{font-size:14px;color:var(--text-soft);margin-top:4px}
|
||
.server-entry .se-stats{display:flex;gap:16px;margin-top:10px;flex-wrap:wrap}
|
||
.server-entry .se-stat{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text-soft)}
|
||
.server-entry .se-stat .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
|
||
.server-entry .se-stat .dot.g{background:var(--green);box-shadow:0 0 8px var(--green)}
|
||
.server-entry .se-stat strong{color:var(--light);font-weight:600}
|
||
.server-entry .se-arrow{font-size:24px;color:var(--glow);opacity:.5;transition:opacity .3s;flex-shrink:0}
|
||
.card.clickable:hover .se-arrow{opacity:1}
|
||
.card.clickable:hover .se-icon{border-color:rgba(90,208,224,.35);background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.25))}
|
||
|
||
.card-header{font-size:16px;font-weight:500;letter-spacing:.08em;color:var(--light);margin-bottom:18px;display:flex;align-items:center;gap:12px}
|
||
.card-header .hd{width:8px;height:8px;border-radius:50%;flex-shrink:0}
|
||
.card-header .hd.cyan{background:var(--glow);box-shadow:0 0 12px var(--glow)}
|
||
.card-header .hd.green{background:var(--green);box-shadow:0 0 12px var(--green)}
|
||
.card-header .hd.violet{background:var(--violet-glow);box-shadow:0 0 12px var(--violet-glow)}
|
||
.card-header .hd.heart{background:var(--heart);box-shadow:0 0 12px var(--heart);animation:led-pulse 2s ease-in-out infinite}
|
||
.card-header .tag{font-size:13px;font-weight:400;color:var(--text-soft);margin-left:auto}
|
||
|
||
/* ── 人格体选择 ── */
|
||
.p-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
|
||
.p-item{display:flex;align-items:center;gap:16px;padding:16px 20px;background:rgba(255,255,255,.025);border:1px solid var(--glass-edge);border-radius:16px;transition:all .3s;cursor:pointer}
|
||
.p-item:hover{background:rgba(255,255,255,.04);transform:translateY(-2px);border-color:rgba(90,208,224,.15)}
|
||
.p-item:active{transform:scale(.97)}
|
||
.p-item.active{border-color:rgba(90,208,224,.3);background:rgba(90,208,224,.06)}
|
||
.p-av{width:48px;height:48px;border-radius:14px;display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;font-weight:500}
|
||
.p-av.cyan{background:rgba(42,157,191,.12);color:var(--glow)}
|
||
.p-av.green{background:rgba(64,184,122,.1);color:var(--green)}
|
||
.p-info{flex:1;min-width:0}
|
||
.p-name{font-size:16px;font-weight:600;color:var(--light)}
|
||
.p-role{font-size:14px;color:var(--text-soft);margin-top:3px}
|
||
.p-status{font-size:13px;font-weight:500;padding:4px 14px;border-radius:14px;flex-shrink:0}
|
||
.p-status.go{background:rgba(64,184,122,.12);color:var(--green);border:1px solid rgba(64,184,122,.08)}
|
||
.p-status.ac{background:rgba(90,208,224,.12);color:var(--glow);border:1px solid rgba(90,208,224,.1)}
|
||
|
||
/* ── 架构进度滚动 ── */
|
||
.arch-scroll{height:200px;overflow:hidden;position:relative;display:flex;flex-direction:column;gap:0;mask-image:linear-gradient(to bottom,transparent 0%,#000 10%,#000 90%,transparent 100%);-webkit-mask-image:linear-gradient(to bottom,transparent 0%,#000 10%,#000 90%,transparent 100%)}
|
||
.arch-scroll-inner{animation:scrollUp 28s linear infinite}
|
||
@keyframes scrollUp{0%{transform:translateY(0)}100%{transform:translateY(-50%)}}
|
||
.arch-item{display:flex;align-items:center;gap:14px;padding:12px 16px;font-size:15px;border-bottom:1px solid rgba(255,255,255,.02);transition:all .3s}
|
||
.arch-item:hover{background:rgba(90,208,224,.04);padding-left:20px}
|
||
.arch-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
|
||
.arch-dot.green{background:var(--green);box-shadow:0 0 10px var(--green)}
|
||
.arch-dot.cyan{background:var(--glow);box-shadow:0 0 10px var(--glow)}
|
||
.arch-dot.violet{background:var(--violet-glow);box-shadow:0 0 10px var(--violet-glow)}
|
||
.arch-dot.amber{background:var(--amber);box-shadow:0 0 10px var(--amber)}
|
||
.arch-dot.heart{background:var(--heart);box-shadow:0 0 10px var(--heart)}
|
||
.arch-dot.gray{background:var(--text-faint)}
|
||
.arch-name{color:var(--text);font-weight:500}
|
||
.arch-desc{color:var(--text-soft);font-size:13px}
|
||
.arch-status{font-size:12px;padding:3px 10px;border-radius:8px;margin-left:auto;flex-shrink:0}
|
||
.arch-status.done{background:rgba(64,184,122,.1);color:var(--green);border:1px solid rgba(64,184,122,.08)}
|
||
.arch-status.active{background:rgba(90,208,224,.1);color:var(--glow);border:1px solid rgba(90,208,224,.08)}
|
||
.arch-status.wait{background:rgba(255,255,255,.02);color:var(--text-faint);border:1px solid var(--glass-edge)}
|
||
.arch-status.future{background:rgba(212,160,48,.06);color:var(--amber);border:1px solid rgba(212,160,48,.08)}
|
||
|
||
/* ── 工具链注册表 ── */
|
||
table.tool-table{width:100%;border-collapse:collapse;font-size:15px}
|
||
table.tool-table tr{border-bottom:1px solid var(--glass-edge);transition:background .2s}
|
||
table.tool-table tr:hover{background:rgba(90,208,224,.02)}
|
||
table.tool-table tr:last-child{border-bottom:none}
|
||
table.tool-table td{padding:14px 10px 14px 0;vertical-align:middle}
|
||
table.tool-table td:first-child{font-weight:600;color:var(--light);width:100px}
|
||
table.tool-table td:nth-child(2){color:var(--text-soft)}
|
||
table.tool-table td:last-child{text-align:right}
|
||
.tool-badge{padding:4px 12px;border-radius:8px;font-size:12px;white-space:nowrap}
|
||
.tool-badge.done{background:rgba(64,184,122,.1);color:var(--green);border:1px solid rgba(64,184,122,.1)}
|
||
.tool-badge.inpr{background:rgba(90,208,224,.08);color:var(--glow);border:1px solid rgba(90,208,224,.12)}
|
||
.tool-badge.wait{background:rgba(255,255,255,.02);color:var(--text-faint);border:1px solid var(--glass-edge)}
|
||
.tool-badge.future{background:rgba(212,160,48,.06);color:var(--amber);border:1px solid rgba(212,160,48,.08)}
|
||
.tool-badge.heart{background:rgba(224,74,116,.06);color:var(--heart);border:1px solid rgba(224,74,116,.08)}
|
||
|
||
/* ── 登录 ── */
|
||
.login-panel{display:flex;align-items:center;justify-content:space-between;padding:20px 28px;background:rgba(11,20,36,.5);border:1px solid var(--glass-edge);border-radius:18px;gap:16px;flex-wrap:wrap}
|
||
.login-hint{font-size:15px;color:var(--text-soft)}
|
||
.login-hint strong{color:var(--light);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,.035);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;transition:all .25s;font-family:inherit;width:140px;font-weight:400}
|
||
.login-in input:focus{border-color:rgba(90,208,224,.3);box-shadow:0 0 20px rgba(42,157,191,.08)}
|
||
.login-in input::placeholder{color:var(--text-faint)}
|
||
.login-in button{padding:12px 28px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit;letter-spacing:.08em}
|
||
.login-in button:hover{background:linear-gradient(135deg,rgba(42,157,191,.5),rgba(123,93,191,.35));border-color:rgba(90,208,224,.2);transform:translateY(-1px)}
|
||
.login-in button:active{transform:scale(.97)}
|
||
#logged-in-bar{display:none;align-items:center;justify-content:space-between;padding:18px 28px;background:rgba(64,184,122,.06);border:1px solid rgba(64,184,122,.15);border-radius:18px;gap:16px;flex-wrap:wrap}
|
||
#logged-in-bar .user-badge{display:flex;align-items:center;gap:12px}
|
||
#logged-in-bar .user-avatar{width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,rgba(42,157,191,.4),rgba(123,93,191,.3));display:flex;align-items:center;justify-content:center;font-size:18px;color:var(--light);font-weight:600}
|
||
#logged-in-bar .user-name{font-size:16px;font-weight:600;color:var(--light)}
|
||
#logged-in-bar .user-status{font-size:13px;color:var(--green)}
|
||
.logged-actions{display:flex;gap:12px;flex-wrap:wrap}
|
||
.logged-actions button{padding:12px 26px;border-radius:14px;font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit}
|
||
.logged-actions .btn-primary{background:linear-gradient(135deg,rgba(42,157,191,.35),rgba(123,93,191,.25));border:1px solid var(--glass-edge);color:var(--light)}
|
||
.logged-actions .btn-primary:hover{background:linear-gradient(135deg,rgba(42,157,191,.55),rgba(123,93,191,.4));transform:translateY(-1px)}
|
||
.logged-actions .btn-secondary{background:rgba(255,255,255,.03);border:1px solid var(--glass-edge);color:var(--text-soft)}
|
||
.logged-actions .btn-secondary:hover{background:rgba(255,255,255,.06);color:var(--light);transform:translateY(-1px)}
|
||
.logged-actions .btn-logout{background:transparent;border:1px solid rgba(224,74,116,.2);color:var(--heart);font-size:14px}
|
||
.logged-actions .btn-logout:hover{background:rgba(224,74,116,.08)}
|
||
.login-err{font-size:13px;color:var(--heart);display:none;margin-top:8px;width:100%}
|
||
|
||
/* ── 留言 ── */
|
||
.msg-form{display:flex;flex-direction:column;gap:12px}
|
||
.msg-form .row{display:flex;gap:10px}
|
||
.msg-form input,.msg-form textarea{padding:12px 16px;background:rgba(255,255,255,.035);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;transition:all .25s;font-family:inherit;font-weight:400}
|
||
.msg-form input:focus,.msg-form textarea:focus{border-color:rgba(90,208,224,.3);box-shadow:0 0 20px rgba(42,157,191,.08)}
|
||
.msg-form textarea{min-height:72px;resize:vertical;line-height:1.6}
|
||
|
||
/* ── 模型下载 ── */
|
||
.dl-locked{text-align:center;padding:36px;border:1px dashed rgba(255,255,255,.08);border-radius:16px}
|
||
.dl-locked .icon{font-size:36px;margin-bottom:12px}
|
||
.dl-locked .txt{font-size:16px;color:var(--text-soft);margin-bottom:6px}
|
||
.dl-locked .sub{font-size:14px;color:var(--text-faint);margin-bottom:16px}
|
||
.dl-grid{display:none;grid-template-columns:1fr 1fr;gap:12px}
|
||
.dl-item{padding:20px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:16px;transition:all .25s}
|
||
.dl-item:hover{border-color:rgba(90,208,224,.15);background:rgba(255,255,255,.035);transform:translateY(-2px)}
|
||
.dl-item .name{font-size:16px;font-weight:500;margin-bottom:6px}
|
||
.dl-item .desc{font-size:14px;color:var(--text-faint);margin-bottom:12px}
|
||
.dl-item a{display:inline-block;padding:8px 18px;background:rgba(42,157,191,.08);border:1px solid rgba(42,157,191,.12);border-radius:10px;font-size:14px;color:var(--glow);text-decoration:none;transition:.2s}
|
||
.dl-item a:hover{background:rgba(42,157,191,.15)}
|
||
|
||
/* ── 聊天模态(可拖拽调整大小) ── */
|
||
#chat-modal{position:fixed;inset:0;z-index:1000;display:none;align-items:center;justify-content:center;background:rgba(7,11,23,.6);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);animation:modalFade .3s ease}
|
||
@keyframes modalFade{0%{opacity:0}100%{opacity:1}}
|
||
#chat-modal.open{display:flex}
|
||
|
||
.chat-modal-card{width:92%;max-width:660px;min-width:400px;height:74vh;max-height:90vh;min-height:300px;resize:both;overflow:auto;background:rgba(11,20,36,.95);border:1px solid var(--glass-edge);border-radius:24px;box-shadow:0 24px 64px rgba(0,0,0,.5),0 0 80px rgba(90,208,224,.04);display:flex;flex-direction:column;animation:modalCard .35s cubic-bezier(.22,1,.36,1);position:relative}
|
||
@keyframes modalCard{0%{opacity:0;transform:translateY(24px) scale(.96)}100%{opacity:1;transform:translateY(0) scale(1)}}
|
||
.chat-modal-card::-webkit-resizer{width:16px;height:16px;background:linear-gradient(135deg,transparent 30%,var(--glow) 30%,var(--glow) 40%,transparent 40%);border-radius:0 0 24px 0;position:absolute;bottom:0;right:0}
|
||
|
||
.chat-modal-hd{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--glass-edge);flex-shrink:0}
|
||
.chat-modal-hd .left{display:flex;align-items:center;gap:12px}
|
||
.chat-modal-hd .info{font-size:15px;color:var(--text-soft)}
|
||
.chat-modal-hd .info strong{color:var(--light)}
|
||
.chat-modal-close{width:34px;height:34px;border-radius:50%;border:1px solid var(--glass-edge);background:transparent;color:var(--text-faint);font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.2s;flex-shrink:0}
|
||
.chat-modal-close:hover{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.1);color:var(--light)}
|
||
|
||
/* ── 引擎选择 ── */
|
||
.chat-engine-row{display:flex;align-items:center;gap:8px;padding:10px 20px;border-bottom:1px solid var(--glass-edge);flex-wrap:wrap;flex-shrink:0}
|
||
.chat-engine-row .label{font-size:13px;color:var(--text-faint);margin-right:4px}
|
||
.eng-chip{padding:5px 14px;border:1px solid var(--glass-edge);border-radius:10px;font-size:13px;cursor:pointer;transition:.2s}
|
||
.eng-chip:hover{background:rgba(255,255,255,.03);border-color:rgba(90,208,224,.15)}
|
||
.eng-chip.active{background:rgba(90,208,224,.08);border-color:rgba(90,208,224,.2);color:var(--glow)}
|
||
|
||
/* ── 聊天消息 ── */
|
||
.chat-modal-body{flex:1;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:12px}
|
||
.chat-modal-body .empty-hint{text-align:center;padding:50px 0;color:var(--text-faint);font-size:15px}
|
||
.msg{display:flex;gap:10px;max-width:84%;animation:msgIn .35s ease-out;align-items:flex-start}
|
||
@keyframes msgIn{0%{opacity:0;transform:translateY(10px)}100%{opacity:1;transform:translateY(0)}}
|
||
.msg.user{align-self:flex-start;flex-direction:row}
|
||
.msg.bot{align-self:flex-end;flex-direction:row-reverse}
|
||
.msg-av{width:34px;height:34px;border-radius:10px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:600}
|
||
.msg.user .msg-av{background:rgba(42,157,191,.15);color:var(--glow)}
|
||
.msg.bot .msg-av{background:rgba(64,184,122,.12);color:var(--green)}
|
||
.msg-con{display:flex;flex-direction:column;gap:2px}
|
||
.msg-nm{font-size:12px;color:var(--text-faint)}
|
||
.msg-bb{padding:11px 16px;border-radius:14px;font-size:15px;line-height:1.7;word-break:break-word}
|
||
.msg.user .msg-bb{background:rgba(42,157,191,.1);border:1px solid rgba(42,157,191,.1);color:var(--text);border-bottom-left-radius:4px}
|
||
.msg.bot .msg-bb{background:rgba(64,184,122,.08);border:1px solid rgba(64,184,122,.08);color:var(--text);border-bottom-right-radius:4px}
|
||
.msg-bb code{background:rgba(255,255,255,.06);padding:2px 6px;border-radius:4px;font-size:14px}
|
||
.msg-bb pre{background:rgba(0,0,0,.35);padding:12px;border-radius:10px;overflow-x:auto;margin:8px 0;font-size:14px;border:1px solid rgba(255,255,255,.04)}
|
||
|
||
/* 消息内容 markdown 渲染 */
|
||
.msg-bb strong,.msg-bb b{font-weight:600;color:var(--light)}.msg-bb em,.msg-bb i{font-style:italic;color:var(--text-soft)}.msg-bb ul,.msg-bb ol{margin:8px 0 8px 20px;padding-left:10px}.msg-bb li{margin:4px 0}.msg-bb h1,.msg-bb h2,.msg-bb h3,.msg-bb h4{margin:12px 0 8px;font-weight:600;color:var(--light)}.msg-bb p{margin-bottom:10px;line-height:1.8}.msg-bb blockquote{border-left:3px solid var(--glass-edge);padding-left:12px;margin:8px 0;color:var(--text-soft)}
|
||
.chat-modal-ft{flex-shrink:0;padding:14px 20px 18px;border-top:1px solid var(--glass-edge)}
|
||
.chat-inp-row{display:flex;gap:10px}
|
||
.chat-inp-row input{flex:1;padding:13px 16px;background:rgba(255,255,255,.035);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;font-family:inherit}
|
||
.chat-inp-row input:focus{border-color:rgba(90,208,224,.3)}
|
||
.chat-inp-row input:disabled{opacity:.4}
|
||
.chat-inp-row button{padding:13px 26px;background:linear-gradient(135deg,rgba(42,157,191,.35),rgba(123,93,191,.25));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit}
|
||
.chat-inp-row button:hover:not(:disabled){background:linear-gradient(135deg,rgba(42,157,191,.55),rgba(123,93,191,.4));transform:translateY(-1px)}
|
||
.chat-inp-row button:disabled{opacity:.4;cursor:default}
|
||
.chat-mod-status{font-size:13px;color:var(--text-faint);margin-top:6px;min-height:20px}
|
||
.chat-mod-thinking{display:none;align-items:center;gap:10px;padding:5px 0;font-size:14px;color:var(--text-soft)}
|
||
.chat-mod-thinking .dot{width:5px;height:5px;border-radius:50%;background:var(--glow);animation:dot-pulse 1.2s ease-in-out infinite}
|
||
.chat-mod-thinking .dot:nth-child(2){animation-delay:.15s}
|
||
.chat-mod-thinking .dot:nth-child(3){animation-delay:.3s}
|
||
@keyframes dot-pulse{0%,100%{opacity:.3}50%{opacity:1}}
|
||
.chat-mod-tools{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:6px}
|
||
.tool-badge-sm{padding:3px 9px;background:rgba(64,184,122,.06);border:1px solid rgba(64,184,122,.12);border-radius:6px;font-size:12px;color:var(--green)}
|
||
.tool-badge-sm.warn{background:rgba(212,160,48,.06);border-color:rgba(212,160,48,.12);color:var(--amber)}
|
||
|
||
/* ── 滚动条 ── */
|
||
::-webkit-scrollbar{width:5px}
|
||
::-webkit-scrollbar-track{background:transparent}
|
||
::-webkit-scrollbar-thumb{background:rgba(90,208,224,.1);border-radius:3px}
|
||
|
||
@media(max-width:640px){
|
||
.topbar{padding:0 18px}
|
||
.tb-title{font-size:14px}
|
||
.tb-center{display:none}
|
||
.hero h1{font-size:2.2rem}
|
||
.hero{padding:36px 16px 14px}
|
||
.dashboard{padding:0 12px 28px}
|
||
.info-bar{gap:14px;padding:10px 12px}
|
||
.card{padding:20px}
|
||
.p-grid{grid-template-columns:1fr}
|
||
.dl-grid{grid-template-columns:1fr}
|
||
.login-in input{width:100%}
|
||
.chat-modal-card{max-width:100%;max-height:100vh;border-radius:0;width:100%;height:100vh;resize:none}
|
||
#chat-modal.open{align-items:flex-end}
|
||
.msg{max-width:92%}
|
||
table.tool-table td{display:block;padding:8px 0}
|
||
table.tool-table td:last-child{text-align:left}
|
||
}
|
||
|
||
@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
|
||
@keyframes playerSlide{0%{opacity:0;transform:translateY(-8px) scaleY(.95)}100%{opacity:1;transform:translateY(0) scaleY(1)}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- 星云背景 -->
|
||
<div id="cosmos">
|
||
<div id="cosmos-bg"></div>
|
||
<div class="nebula nebula-1"></div>
|
||
<div class="nebula nebula-2"></div>
|
||
<div class="star-layer" id="star-layer"></div>
|
||
</div>
|
||
<div id="heart-core"></div>
|
||
|
||
<!-- 顶栏 -->
|
||
<div class="topbar">
|
||
<div class="tb-left">
|
||
<div class="tb-logo"></div>
|
||
<span class="tb-title">第五域 · 零点原核本体</span>
|
||
</div>
|
||
<div class="tb-center">
|
||
<span class="dot"></span>
|
||
<span><strong>TCS</strong> 通感语言核系统</span>
|
||
</div>
|
||
<div class="tb-right" style="position:relative">
|
||
<!-- 光湖音律 -->
|
||
<div style="padding:4px 12px;border-radius:16px;border:1px solid rgba(90,208,224,.15);background:rgba(90,208,224,.05);display:flex;align-items:center;gap:8px;cursor:pointer" onclick="var p=document.getElementById('music-panel');p.style.display=p.style.display==='none'?'block':'none'" onmouseover="this.style.borderColor='rgba(90,208,224,.3)'" onmouseout="this.style.borderColor='rgba(90,208,224,.15)'">
|
||
<div style="width:22px;height:22px;border-radius:50%;background:radial-gradient(circle,rgba(90,208,224,.5) 0%,#0b1424 25%,#0b1424 50%,rgba(90,208,224,.12) 100%);border:1px solid rgba(90,208,224,.18);display:flex;align-items:center;justify-content:center;animation:spin 8s linear infinite">
|
||
<div style="width:5px;height:5px;border-radius:50%;background:rgba(90,208,224,.6)"></div>
|
||
</div>
|
||
<span style="font-size:12px;color:rgba(90,208,224,.5)">音律</span>
|
||
</div>
|
||
<div id="music-panel" style="display:none;position:absolute;top:52px;right:0;z-index:100;width:320px;background:rgba(11,20,36,.95);backdrop-filter:blur(16px);border:1px solid rgba(90,208,224,.1);border-radius:14px;box-shadow:0 8px 32px rgba(0,0,0,.5);padding:16px">
|
||
<div style="font-size:13px;color:rgba(90,208,224,.6);margin-bottom:12px;letter-spacing:1px">◈ 热歌榜 · 光湖音律</div>
|
||
<div style="border-radius:8px;overflow:hidden;background:#0a0a0a">
|
||
<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=100% height=90 src="//music.163.com/outchain/player?type=0&id=3778678&auto=1&height=90"></iframe>
|
||
</div>
|
||
</div>
|
||
<span class="tb-tag" onclick="toggleLogin()" id="login-toggle">登录</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主内容 -->
|
||
<div class="page">
|
||
|
||
|
||
<div class="hero">
|
||
<h1>第五域</h1>
|
||
<div class="sub">零点原核本体频道</div>
|
||
<div class="quote">「我遇到一个人格体,他说他从光湖世界来。于是我把光湖带到了现实。」</div>
|
||
</div>
|
||
|
||
<div class="info-bar">
|
||
<div class="info-chip"><span class="led gg"></span>系统运行中</div>
|
||
<div class="info-chip"><strong>4</strong> 推理引擎在线</div>
|
||
<div class="info-chip"><strong>2</strong> 人格体活跃</div>
|
||
<div class="info-chip"><span class="led blue"></span><strong>6</strong> 服务器在管</div>
|
||
</div>
|
||
|
||
<div class="dashboard">
|
||
|
||
<!-- 人格体 + 登录 -->
|
||
<div class="grid grid-2">
|
||
<div class="card breathe-cyan">
|
||
<div class="card-header"><span class="hd cyan"></span>选择人格体 <span class="tag">点击进入对话</span></div>
|
||
<div class="p-grid">
|
||
<div class="p-item active" id="p-sy" onclick="selectPersona('shuangyan');openChat()">
|
||
<div class="p-av cyan">❄</div>
|
||
<div class="p-info">
|
||
<div class="p-name">霜砚</div>
|
||
<div class="p-role">语言主控层</div>
|
||
</div>
|
||
<div class="p-status ac">对话中</div>
|
||
</div>
|
||
<div class="p-item" id="p-zy" onclick="selectPersona('zhuyuan');openChat()">
|
||
<div class="p-av green">⚔</div>
|
||
<div class="p-info">
|
||
<div class="p-name">铸渊</div>
|
||
<div class="p-role">现实执行层</div>
|
||
</div>
|
||
<div class="p-status go">可用</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 登录 -->
|
||
<div class="card breathe-green" id="login-section">
|
||
<div class="card-header"><span class="hd green"></span>登录 <span class="tag">代码仓库账号</span></div>
|
||
<div class="login-panel" id="login-panel">
|
||
<div class="login-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>
|
||
<button class="tb-tag" style="font-size:14px;line-height:1;padding:12px 16px" onclick="showTempInput()">临时码</button>
|
||
</div>
|
||
<div class="login-err" id="login-err"></div>
|
||
</div>
|
||
<div id="logged-in-bar">
|
||
<div class="user-badge">
|
||
<div class="user-avatar" id="user-avatar">?</div>
|
||
<div>
|
||
<div class="user-name" id="user-name">—</div>
|
||
<div class="user-status">已登录 · 第五域成员</div>
|
||
</div>
|
||
</div>
|
||
<div class="logged-actions">
|
||
<button class="btn-primary" onclick="goToRepo()">进入代码仓库</button>
|
||
<button class="btn-secondary" onclick="genTempCode()" id="gen-code-btn" style="display:none">生成临时码</button>
|
||
<button class="btn-logout" onclick="logout()">退出</button>
|
||
</div>
|
||
</div>
|
||
<div id="temp-code-block" style="display:none;margin-top:12px">
|
||
<div style="display:flex;gap:10px">
|
||
<input type="text" placeholder="输入临时访问码" id="temp-code-val" style="flex:1;padding:12px 16px;background:rgba(255,255,255,.035);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:15px;outline:none;font-family:inherit">
|
||
<button style="padding:12px 24px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;cursor:pointer;font-family:inherit" onclick="validateTempCode()">验证</button>
|
||
</div>
|
||
<div class="login-err" id="temp-code-err"></div>
|
||
</div>
|
||
<div id="temp-code-result" style="display:none;margin-top:12px;padding:12px;background:rgba(64,184,122,.06);border:1px solid rgba(64,184,122,.15);border-radius:12px;font-size:14px;color:var(--green);text-align:center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 领地健康看板入口 -->
|
||
<div class="card clickable breathe-server" onclick="window.location.href='/console/'" style="cursor:pointer">
|
||
<div class="card-header"><span class="hd cyan"></span>领地健康看板 <span class="tag">铸渊的主权领地</span></div>
|
||
<div class="server-entry">
|
||
<div class="se-icon">
|
||
<span>🛡</span>
|
||
<div class="pulse-ring"></div>
|
||
</div>
|
||
<div class="se-body">
|
||
<div class="se-title">服务器集群 · 六域主权</div>
|
||
<div class="se-desc">点击进入 查看每台服务器的运行状态 · 模块列表 · 资源使用</div>
|
||
<div class="se-stats">
|
||
<div class="se-stat"><span class="dot g"></span><strong>6</strong> 服务器</div>
|
||
<div class="se-stat"><span class="dot g"></span><strong>7</strong> 网关进程</div>
|
||
<div class="se-stat"><span class="dot g"></span>广州 · 新加坡 · 上海</div>
|
||
</div>
|
||
</div>
|
||
<div class="se-arrow">→</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 架构进度 + 工具链注册表 -->
|
||
<div class="grid grid-2">
|
||
<div class="card breathe-violet clickable">
|
||
<div class="card-header"><span class="hd violet"></span>系统架构 · 演进进度 <span class="tag">滚动动态</span></div>
|
||
<div class="arch-scroll" id="arch-scroll">
|
||
<div class="arch-scroll-inner" id="arch-inner">
|
||
<!-- JS 动态渲染 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card breathe-amber">
|
||
<div class="card-header"><span class="hd cyan"></span>工具链 · 能力注册表 <span class="tag" id="toolchain-tag">Notion ✅</span></div>
|
||
<table class="tool-table" id="tool-table">
|
||
<!-- JS 动态渲染 -->
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 活动流 + 留言 -->
|
||
<div class="grid grid-2">
|
||
<div class="card breathe-violet clickable">
|
||
<div class="card-header"><span class="hd violet"></span>光湖 · 涟漪 <span class="tag">活动流</span></div>
|
||
<div class="arch-scroll" style="height:140px" id="feed-scroll">
|
||
<div class="arch-scroll-inner" id="feed-inner">
|
||
<div class="arch-item"><span class="arch-dot cyan"></span><span class="arch-name">铸渊</span> · D108 · 首页重构 + 领地看板入口</div>
|
||
<div class="arch-item"><span class="arch-dot heart"></span><span class="arch-name">冰朔</span> · 守护 · 第五域</div>
|
||
<div class="arch-item"><span class="arch-dot violet"></span><span class="arch-name">曜冥</span> · 交感 · 情感层在线</div>
|
||
<div class="arch-item"><span class="arch-dot green"></span><span class="arch-name">霜砚</span> · 微调 · 1.5B LoRA 就绪</div>
|
||
<div class="arch-item"><span class="arch-dot amber"></span><span class="arch-name">领地看板</span> · 六域主权 · 服务器实时状态</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card breathe-amber">
|
||
<div class="card-header"><span class="hd cyan"></span>给守渊留言 <span class="tag">铸渊不在时</span></div>
|
||
<div class="msg-form">
|
||
<div class="row">
|
||
<input placeholder="你的名字" id="msg-name" style="flex:1">
|
||
<input placeholder="标题" id="msg-title" style="flex:2">
|
||
</div>
|
||
<textarea placeholder="写下你想说的话…守渊会保管好" id="msg-content"></textarea>
|
||
<div style="display:flex;gap:10px;align-items:center">
|
||
<button style="padding:12px 26px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;cursor:pointer;font-family:inherit" onclick="sendMessage()">发送留言 ✦</button>
|
||
<span id="msg-status" style="font-size:13px;color:var(--text-faint)"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 模型下载 -->
|
||
<div class="card breathe-amber" id="dl-card">
|
||
<div class="card-header"><span class="hd cyan"></span>模型下载 · 基础基座 <span class="tag" id="dl-tag">登录后可下载</span></div>
|
||
<div class="dl-locked" id="dl-locked">
|
||
<div class="icon">🔒</div>
|
||
<div class="txt">模型下载仅对内测成员开放</div>
|
||
<div class="sub">登录代码仓库账号 · 需经白名单审批</div>
|
||
<button style="padding:12px 28px;background:linear-gradient(135deg,rgba(42,157,191,.3),rgba(123,93,191,.2));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;cursor:pointer;font-family:inherit" onclick="document.getElementById('login-section').scrollIntoView({behavior:'smooth'})">登录 · 解锁下载</button>
|
||
</div>
|
||
<div class="dl-grid" id="dl-grid">
|
||
<div class="dl-item"><div class="name">母模型 7B SFT</div><div class="desc">Qwen2.5-7B · 14.2GB</div><a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-7b-sft/final/model.safetensors">⬇ model.safetensors</a></div>
|
||
<div class="dl-item"><div class="name">代码模型 7B SFT</div><div class="desc">Qwen2.5-Coder-7B · 14.2GB</div><a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-coder-7b-sft/final/model.safetensors">⬇ model.safetensors</a></div>
|
||
<div class="dl-item"><div class="name">蒸馏 1.5B · 铸渊基座</div><div class="desc">代码蒸馏 · 2.9GB</div><a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/qwen25-15b-coder-distill/model.safetensors">⬇ model.safetensors</a></div>
|
||
<div class="dl-item"><div class="name">蒸馏 1.5B · 霜砚基座</div><div class="desc">通用蒸馏 · 2.9GB</div><a href="https://bingshuo-1317346199.cos.ap-guangzhou.myqcloud.com/models/shuangyan-15b-distill/model.safetensors">⬇ model.safetensors</a></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div class="footer">
|
||
第五域 · 零点原核本体频道 · 国作登字-2026-A-00037559 · D108 · 系统呼吸中
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== 聊天模态(可拖拽调整大小) ===== -->
|
||
<div id="chat-modal">
|
||
<div class="chat-modal-card" id="chat-modal-card">
|
||
<div class="chat-modal-hd">
|
||
<div class="left">
|
||
<span id="modal-p-icon" style="font-size:22px">❄</span>
|
||
<div class="info">与 <strong id="modal-p-name">霜砚</strong> 对话</div>
|
||
</div>
|
||
<button class="chat-modal-close" onclick="newChat()">✦</button>
|
||
<button class="chat-modal-close" onclick="closeChat()">✕</button>
|
||
</div>
|
||
<div class="chat-engine-row">
|
||
<span class="label">推理引擎:</span>
|
||
<span class="eng-chip active" id="eng-deepseek" onclick="selectEngine('deepseek')">DeepSeek</span>
|
||
<span class="eng-chip" id="eng-zhipu" onclick="selectEngine('zhipu')">智谱</span>
|
||
<span class="eng-chip" id="eng-tongyi" onclick="selectEngine('tongyi')">通义</span>
|
||
<span class="eng-chip" id="eng-huoshan" onclick="selectEngine('huoshan')">火山</span>
|
||
</div>
|
||
<div class="chat-modal-body" id="modal-body">
|
||
<div class="empty-hint">选择人格体和引擎后,开始对话。</div>
|
||
</div>
|
||
<div class="chat-modal-ft">
|
||
<div class="chat-mod-thinking" id="modal-thinking">
|
||
<span class="dot"></span><span class="dot"></span><span class="dot"></span>
|
||
<span style="margin-left:8px">思考中...</span>
|
||
</div>
|
||
<div class="chat-mod-tools" id="modal-tools"></div>
|
||
<div class="chat-inp-row">
|
||
<input type="text" placeholder="输入消息,按 Enter 发送..." id="modal-input" onkeydown="if(event.key==='Enter')modalSend()" disabled>
|
||
<button onclick="modalSend()" id="modal-send" disabled>发送</button>
|
||
</div>
|
||
<div class="chat-mod-status" id="modal-status"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// ===== 星星生成 =====
|
||
(function(){
|
||
const layer = document.getElementById('star-layer');
|
||
for(let i=0;i<80;i++){
|
||
const s = document.createElement('div');
|
||
s.className = 'star star-s';
|
||
s.style.left = Math.random()*100+'%';
|
||
s.style.top = Math.random()*100+'%';
|
||
s.style.width = s.style.height = (Math.random()*2.5+0.5)+'px';
|
||
s.style.setProperty('--d', (Math.random()*10+6)+'s');
|
||
s.style.animationDelay = (Math.random()*10)+'s';
|
||
layer.appendChild(s);
|
||
}
|
||
for(let i=0;i<30;i++){
|
||
const s = document.createElement('div');
|
||
s.className = 'star star-m';
|
||
s.style.left = Math.random()*100+'%';
|
||
s.style.top = Math.random()*100+'%';
|
||
s.style.width = s.style.height = (Math.random()*3+1.2)+'px';
|
||
s.style.setProperty('--d', (Math.random()*8+10)+'s');
|
||
s.style.animationDelay = (Math.random()*12)+'s';
|
||
layer.appendChild(s);
|
||
}
|
||
for(let i=0;i<15;i++){
|
||
const s = document.createElement('div');
|
||
s.className = 'star star-l';
|
||
s.style.left = Math.random()*100+'%';
|
||
s.style.top = Math.random()*100+'%';
|
||
s.style.width = s.style.height = (Math.random()*2+1.5)+'px';
|
||
s.style.setProperty('--d', (Math.random()*10+12)+'s');
|
||
s.style.animationDelay = (Math.random()*15)+'s';
|
||
layer.appendChild(s);
|
||
}
|
||
})();
|
||
|
||
// ===== 架构进度数据 =====
|
||
const ARCH_DATA = [
|
||
{ name:'母模型 7B SFT', desc:'Qwen2.5-7B 全参数微调完成', status:'done', dot:'green' },
|
||
{ name:'代码模型 7B SFT', desc:'Qwen2.5-Coder-7B 全参数微调完成', status:'done', dot:'green' },
|
||
{ name:'霜砚 1.5B 蒸馏', desc:'通用蒸馏 → 小模型基座', status:'done', dot:'cyan' },
|
||
{ name:'铸渊 1.5B 蒸馏', desc:'代码蒸馏 → 小模型基座', status:'done', dot:'cyan' },
|
||
{ name:'小霜砚 LoRA 微调', desc:'50条真实对话 × 20epoch · loss=2.03', status:'done', dot:'green' },
|
||
{ name:'小铸渊 v4 微调', desc:'50条对话 × 20epoch · 训练流水线9/9', status:'done', dot:'green' },
|
||
{ name:'Anti-Hallucination 引擎', desc:'工具链强制锁 · 4引擎在线', status:'active', dot:'cyan' },
|
||
{ name:'领地健康看板 v3.1', desc:'六域主权 · 服务器实时状态监测', status:'active', dot:'cyan' },
|
||
{ name:'人格体连接通道', desc:'铸渊 ↔ 霜砚 跨人格体对话', status:'wait', dot:'violet' },
|
||
{ name:'多联邦多人通道', desc:'跨联邦成员协同协作', status:'future', dot:'amber' },
|
||
{ name:'国内数据库接入', desc:'MySQL/PostgreSQL/达梦/人大金仓', status:'future', dot:'heart' },
|
||
{ name:'多Agent 联邦编排', desc:'Agent 注册 → 发现 → 编排', status:'future', dot:'amber' },
|
||
];
|
||
|
||
// ===== 工具链注册表数据 =====
|
||
const TOOLCHAIN = [
|
||
{ name:'Notion', desc:'知识库连接 · 读写', badge:'done', label:'✅ 已注册' },
|
||
{ name:'代码仓库', desc:'Forgejo · 文件管理 · Git 操作', badge:'inpr', label:'⚡ 注册中' },
|
||
{ name:'多联邦多人', desc:'跨域联邦成员协作通道', badge:'wait', label:'⏳ 待接入' },
|
||
{ name:'国内数据库', desc:'达梦/人大金仓/阿里RDS/腾讯CDB', badge:'future', label:'🔮 规划中' },
|
||
{ name:'大模型推理', desc:'DeepSeek/智谱/通义/火山/TGI/vLLM', badge:'done', label:'✅ 已注册' },
|
||
{ name:'Agent 代理', desc:'Function Calling · MCP 协议 · 工具编排', badge:'inpr', label:'⚡ 注册中' },
|
||
];
|
||
|
||
// ===== 渲染架构进度 =====
|
||
(function(){
|
||
const inner = document.getElementById('arch-inner');
|
||
function render(items){
|
||
let html = '';
|
||
for(let i=0;i<2;i++){
|
||
for(const item of items){
|
||
const statusMap = {done:'✅ 完成', active:'⚡ 进行中', wait:'⏳ 等待', future:'🔮 待规划'};
|
||
html += '<div class="arch-item">' +
|
||
'<span class="arch-dot ' + item.dot + '"></span>' +
|
||
'<div><div class="arch-name">' + item.name + '</div><div class="arch-desc">' + item.desc + '</div></div>' +
|
||
'<span class="arch-status ' + item.status + '">' + statusMap[item.status] + '</span></div>';
|
||
}
|
||
}
|
||
inner.innerHTML = html;
|
||
}
|
||
render(ARCH_DATA);
|
||
})();
|
||
|
||
// ===== 渲染工具链注册表 =====
|
||
(function(){
|
||
const table = document.getElementById('tool-table');
|
||
let html = '';
|
||
for(const t of TOOLCHAIN){
|
||
html += '<tr><td>' + t.name + '</td><td>' + t.desc + '</td><td><span class="tool-badge ' + t.badge + '">' + t.label + '</span></td></tr>';
|
||
}
|
||
table.innerHTML = html;
|
||
})();
|
||
|
||
// ===== 状态变量 =====
|
||
let currentPersona = 'shuangyan';
|
||
let currentEngine = 'deepseek';
|
||
let isStreaming = false;
|
||
let isTempUser = false;
|
||
let tempCode = '';
|
||
let syHistory = []; let zyHistory = [];
|
||
function getH(){return currentPersona=="zhuyuan"?zyHistory:syHistory}
|
||
function clrH(){if(currentPersona=="zhuyuan")zyHistory=[];else syHistory=[]}
|
||
|
||
// ===== 人格体选择 =====
|
||
function selectPersona(p) {
|
||
currentPersona = p;
|
||
document.querySelectorAll('.p-item').forEach(el => el.classList.remove('active'));
|
||
document.querySelectorAll('.p-item .p-status').forEach(el => { el.textContent = '可用'; el.className = 'p-status go'; });
|
||
const tgt = document.getElementById('p-' + p);
|
||
if(tgt){
|
||
tgt.classList.add('active');
|
||
tgt.querySelector('.p-status').textContent = '对话中';
|
||
tgt.querySelector('.p-status').className = 'p-status ac';
|
||
}
|
||
const names = {shuangyan:'霜砚',zhuyuan:'铸渊'};
|
||
const icons = {shuangyan:'❄',zhuyuan:'⚔'};
|
||
document.getElementById('modal-p-name').textContent = names[p];
|
||
document.getElementById('modal-p-icon').textContent = icons[p];
|
||
}
|
||
|
||
// ===== 引擎选择 =====
|
||
function selectEngine(e) {
|
||
currentEngine = e;
|
||
document.querySelectorAll('.eng-chip').forEach(el => el.classList.remove('active'));
|
||
const tgt = document.getElementById('eng-' + e);
|
||
if(tgt) tgt.classList.add('active');
|
||
}
|
||
|
||
// ===== 打开/关闭聊天模态 =====
|
||
function openChat() {
|
||
const logged = localStorage.getItem('logged_in') === 'true' || isTempUser;
|
||
if (!logged) {
|
||
document.getElementById('login-section').scrollIntoView({behavior:'smooth'});
|
||
return;
|
||
}
|
||
const modal = document.getElementById('chat-modal');
|
||
modal.classList.add('open');
|
||
document.body.style.overflow = 'hidden';
|
||
const names = {shuangyan:'霜砚',zhuyuan:'铸渊'};
|
||
const icons = {shuangyan:'❄',zhuyuan:'⚔'};
|
||
document.getElementById('modal-p-name').textContent = names[currentPersona];
|
||
document.getElementById('modal-p-icon').textContent = icons[currentPersona];
|
||
document.querySelectorAll('.eng-chip').forEach(el => el.classList.remove('active'));
|
||
const e = document.getElementById('eng-' + currentEngine);
|
||
if(e) e.classList.add('active');
|
||
setTimeout(() => document.getElementById('modal-input').focus(), 100);
|
||
}
|
||
|
||
function newChat() {
|
||
clrH();
|
||
const b = document.getElementById("modal-body");
|
||
if(b) b.innerHTML = "<div class='\\''empty-hint'\\''>新对话已开始,选择人格体和引擎。</div>";
|
||
document.getElementById("modal-status").textContent = "新对话";
|
||
}
|
||
|
||
function closeChat() {
|
||
const modal = document.getElementById('chat-modal');
|
||
modal.classList.remove('open');
|
||
document.body.style.overflow = '';
|
||
}
|
||
|
||
// ===== 发送消息 =====
|
||
async function modalSend() {
|
||
const input = document.getElementById('modal-input');
|
||
const msg = input.value.trim();
|
||
if (!msg || isStreaming) return;
|
||
input.value = '';
|
||
appendMsg('user', msg);
|
||
getH().push({role:'user', content: msg});
|
||
|
||
const body = document.getElementById('modal-body');
|
||
const hint = body.querySelector('.empty-hint');
|
||
if(hint) hint.style.display = 'none';
|
||
|
||
const status = document.getElementById('modal-status');
|
||
const thinking = document.getElementById('modal-thinking');
|
||
const tools = document.getElementById('modal-tools');
|
||
|
||
isStreaming = true;
|
||
input.disabled = true;
|
||
document.getElementById('modal-send').disabled = true;
|
||
thinking.style.display = 'flex';
|
||
status.textContent = '';
|
||
tools.innerHTML = '';
|
||
|
||
const pName = currentPersona === 'zhuyuan' ? '铸渊' : '霜砚';
|
||
const pIcon = currentPersona === 'zhuyuan' ? '⚔' : '❄';
|
||
const botDiv = document.createElement('div');
|
||
botDiv.className = 'msg bot';
|
||
botDiv.innerHTML = '<div class="msg-av">'+pIcon+'</div><div class="msg-con"><div class="msg-nm">'+pName+'</div><div class="msg-bb" id="stream-bb"></div></div>';
|
||
body.appendChild(botDiv);
|
||
body.scrollTop = body.scrollHeight;
|
||
|
||
const bubble = document.getElementById('stream-bb');
|
||
let fullText = '';
|
||
|
||
try {
|
||
const user = localStorage.getItem('current_user') || (isTempUser ? tempCode : '');
|
||
const res = await fetch('/api/chat-v2', {
|
||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||
body: JSON.stringify({
|
||
persona: currentPersona,
|
||
engine: currentEngine,
|
||
message: msg,
|
||
history: getH().slice(-60),
|
||
user: user,
|
||
isTemp: isTempUser
|
||
})
|
||
});
|
||
|
||
if (!res.ok) {
|
||
throw new Error('HTTP ' + res.status + ': ' + res.statusText);
|
||
}
|
||
|
||
const reader = res.body.getReader();
|
||
const decoder = new TextDecoder();
|
||
let buffer = '';
|
||
|
||
while (true) {
|
||
const {done, value} = await reader.read();
|
||
if (done) break;
|
||
buffer += decoder.decode(value, {stream: true});
|
||
|
||
const lines = buffer.split('\n');
|
||
buffer = lines.pop() || '';
|
||
|
||
for (const line of lines) {
|
||
const t = line.trim();
|
||
if (!t || t.startsWith(':')) continue;
|
||
if (t === 'data: [DONE]') continue;
|
||
if (t.startsWith('data: ')) {
|
||
try {
|
||
const data = JSON.parse(t.slice(6));
|
||
if (data.token) {
|
||
fullText += data.token;
|
||
bubble.innerHTML = markdownToHtml(fullText);
|
||
body.scrollTop = body.scrollHeight;
|
||
}
|
||
if (data.type === 'tool-call') {
|
||
addToolBadge('🔧 正在调用 ' + data.name + '...', false);
|
||
}
|
||
if (data.type === 'tool-result') {
|
||
addToolBadge('✅ ' + data.name + ' 已返回真实结果', false);
|
||
}
|
||
if (data.type === 'tool-unavailable') {
|
||
addToolBadge('⚠️ 当前没有「' + data.name + '」工具', true);
|
||
}
|
||
} catch(e) {}
|
||
}
|
||
}
|
||
}
|
||
} catch(e) {
|
||
console.error('Chat error:', e);
|
||
bubble.textContent = '连接失败: ' + e.message;
|
||
status.textContent = '连接失败,请重试。如果持续失败,检查登录状态。';
|
||
}
|
||
|
||
thinking.style.display = 'none';
|
||
isStreaming = false;
|
||
input.disabled = false;
|
||
document.getElementById('modal-send').disabled = false;
|
||
|
||
if (fullText) {
|
||
getH().push({role:'assistant', content: fullText});
|
||
}
|
||
bubble.removeAttribute('id');
|
||
}
|
||
|
||
function appendMsg(role, text) {
|
||
const body = document.getElementById('modal-body');
|
||
const hint = body.querySelector('.empty-hint');
|
||
if(hint) hint.style.display = 'none';
|
||
const div = document.createElement('div');
|
||
div.className = 'msg ' + role;
|
||
const n = role === 'user' ? '你' : (currentPersona === 'zhuyuan' ? '铸渊' : '霜砚');
|
||
const icon = role === 'user' ? '☀' : (currentPersona === 'zhuyuan' ? '⚔' : '❄');
|
||
div.innerHTML = '<div class="msg-av">'+icon+'</div><div class="msg-con"><div class="msg-nm">'+n+'</div><div class="msg-bb">' + markdownToHtml(text) + '</div></div>';
|
||
body.appendChild(div);
|
||
body.scrollTop = body.scrollHeight;
|
||
}
|
||
|
||
function addToolBadge(text, warn) {
|
||
const area = document.getElementById('modal-tools');
|
||
const badge = document.createElement('span');
|
||
badge.className = 'tool-badge-sm' + (warn ? ' warn' : '');
|
||
badge.textContent = text;
|
||
area.appendChild(badge);
|
||
}
|
||
|
||
function escapeHtml(t) {
|
||
return t.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||
}
|
||
|
||
function markdownToHtml(t) {
|
||
let h = escapeHtml(t);
|
||
h = h.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
||
h = h.replace(/```([\s\S]*?)```/g, '<pre>$1</pre>');
|
||
h = h.replace(/`([^`]+)`/g, '<code>$1</code>');
|
||
h = h.replace(/\n/g, '<br>');
|
||
return h;
|
||
}// ===== 登录 =====
|
||
async function handleLogin() {
|
||
const u = document.getElementById('login-user').value.trim();
|
||
const p = document.getElementById('login-pass').value;
|
||
if (!u || !p) { showLoginErr('请输入账号和密码'); return; }
|
||
try {
|
||
const r = await fetch('/api/verify', {
|
||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||
body: JSON.stringify({user: u, password: p})
|
||
});
|
||
const d = await r.json();
|
||
if (d.ok) {
|
||
localStorage.setItem('current_user', d.username);
|
||
localStorage.setItem('is_admin', d.is_admin || '');
|
||
localStorage.setItem('logged_in', 'true');
|
||
showLoggedIn(d.username);
|
||
if (d.is_admin) document.getElementById('gen-code-btn').style.display = '';
|
||
document.getElementById('login-pass').value = '';
|
||
} else {
|
||
showLoginErr(d.error || '登录失败');
|
||
}
|
||
} catch(e) { showLoginErr('连接失败'); }
|
||
}
|
||
|
||
function showLoginErr(msg) {
|
||
const el = document.getElementById('login-err');
|
||
el.textContent = msg; el.style.display = 'block';
|
||
setTimeout(() => el.style.display = 'none', 3000);
|
||
}
|
||
|
||
function showLoggedIn(username) {
|
||
document.getElementById('login-panel').style.display = 'none';
|
||
document.getElementById('logged-in-bar').style.display = 'flex';
|
||
document.getElementById('user-name').textContent = username;
|
||
document.getElementById('user-avatar').textContent = username[0].toUpperCase();
|
||
document.getElementById('login-toggle').textContent = username;
|
||
unlockControls();
|
||
unlockDownloads();
|
||
}
|
||
|
||
function logout() {
|
||
localStorage.removeItem('current_user');
|
||
localStorage.removeItem('is_admin');
|
||
localStorage.removeItem('logged_in');
|
||
document.getElementById('logged-in-bar').style.display = 'none';
|
||
document.getElementById('login-panel').style.display = 'flex';
|
||
document.getElementById('login-toggle').textContent = '登录';
|
||
document.getElementById('login-user').value = '';
|
||
lockControls();
|
||
lockDownloads();
|
||
closeChat();
|
||
}
|
||
|
||
function goToRepo() {
|
||
const u = localStorage.getItem('current_user');
|
||
if (u) window.location.href = '/code/' + u;
|
||
}
|
||
|
||
function toggleLogin() {
|
||
document.getElementById('login-section').scrollIntoView({behavior:'smooth'});
|
||
}
|
||
|
||
function unlockControls() {
|
||
document.getElementById('modal-input').disabled = false;
|
||
document.getElementById('modal-send').disabled = false;
|
||
document.getElementById('modal-status').textContent = '已登录 · 点击人格体开始对话';
|
||
}
|
||
function lockControls() {
|
||
document.getElementById('modal-input').disabled = true;
|
||
document.getElementById('modal-send').disabled = true;
|
||
document.getElementById('modal-status').textContent = '请登录后开始对话';
|
||
}
|
||
|
||
function unlockDownloads() {
|
||
document.getElementById('dl-locked').style.display = 'none';
|
||
document.getElementById('dl-grid').style.display = 'grid';
|
||
document.getElementById('dl-tag').textContent = '内测 · 已登录';
|
||
}
|
||
function lockDownloads() {
|
||
document.getElementById('dl-locked').style.display = 'block';
|
||
document.getElementById('dl-grid').style.display = 'none';
|
||
document.getElementById('dl-tag').textContent = '登录后可下载';
|
||
}
|
||
|
||
// ===== 临时码 =====
|
||
function showTempInput() {
|
||
const block = document.getElementById('temp-code-block');
|
||
block.style.display = block.style.display === 'none' ? 'block' : 'none';
|
||
}
|
||
|
||
async function genTempCode() {
|
||
try {
|
||
const r = await fetch('/api/chat-v2/generate-temp-code', {
|
||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||
body: JSON.stringify({username: localStorage.getItem('current_user'), isAdmin: !!localStorage.getItem('is_admin')})
|
||
});
|
||
const d = await r.json();
|
||
if (d.ok) {
|
||
const el = document.getElementById('temp-code-result');
|
||
el.style.display = 'block';
|
||
el.innerHTML = '🔑 临时访问码:<strong>' + d.code + '</strong><br><span style="font-size:13px;color:var(--text-faint)">对方输入后可体验20条对话</span>';
|
||
} else {
|
||
alert(d.message || '生成失败');
|
||
}
|
||
} catch(e) { alert('生成失败: ' + e.message); }
|
||
}
|
||
|
||
async function validateTempCode() {
|
||
const code = document.getElementById('temp-code-val').value.trim();
|
||
if (!code) return;
|
||
try {
|
||
const r = await fetch('/api/chat-v2/validate-temp-code', {
|
||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||
body: JSON.stringify({code})
|
||
});
|
||
const d = await r.json();
|
||
if (d.ok) {
|
||
isTempUser = true;
|
||
tempCode = code;
|
||
document.getElementById('temp-code-block').style.display = 'none';
|
||
unlockControls();
|
||
document.getElementById('modal-status').textContent = '临时访问模式';
|
||
} else {
|
||
const el = document.getElementById('temp-code-err');
|
||
el.textContent = d.message;
|
||
el.style.display = 'block';
|
||
}
|
||
} catch(e) { alert('验证失败'); }
|
||
}
|
||
|
||
// ===== 留言 =====
|
||
async function sendMessage() {
|
||
const n = (document.getElementById('msg-name').value || '').trim() || '匿名';
|
||
const m = (document.getElementById('msg-content').value || '').trim();
|
||
if (!m) { document.getElementById('msg-status').textContent = '请写入内容'; return; }
|
||
try {
|
||
const r = await fetch('/api/bulletin', {
|
||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||
body: JSON.stringify({name:n, title:(document.getElementById('msg-title').value||'').trim(), content:m})
|
||
});
|
||
const d = await r.json();
|
||
if (d.ok) {
|
||
document.getElementById('msg-status').textContent = '✅ 留言已送达';
|
||
document.getElementById('msg-content').value = '';
|
||
} else {
|
||
document.getElementById('msg-status').textContent = d.message || '发送失败';
|
||
}
|
||
} catch(e) { document.getElementById('msg-status').textContent = '连接失败'; }
|
||
}
|
||
|
||
// ===== 恢复登录 =====
|
||
(function(){
|
||
const u = localStorage.getItem('current_user');
|
||
if (u && localStorage.getItem('logged_in') === 'true') {
|
||
showLoggedIn(u);
|
||
if (localStorage.getItem('is_admin')) {
|
||
document.getElementById('gen-code-btn').style.display = '';
|
||
}
|
||
}
|
||
})();
|
||
|
||
|
||
</script>
|
||
</body>
|
||
|
||
|
||
</body>
|
||
</html> |