🎨 D107 · UI重写:可拖拽聊天卡片+架构滚动进度+工具链注册表+API路由修复

This commit is contained in:
root 2026-05-20 22:38:57 +08:00
parent 7647766e84
commit 10a6bb0ee2

View File

@ -84,14 +84,12 @@ body{
.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.rr{background:var(--heart);box-shadow:0 0 12px var(--heart);animation:led-pulse 1.5s ease-in-out infinite}
/* ── 仪表板 ── */
.dashboard{max-width:1040px;margin:0 auto;padding:0 32px 40px;display:flex;flex-direction:column;gap:20px;width:100%}
.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}
.grid-3{grid-template-columns:1fr 1fr 1fr}
@media(max-width:860px){.grid-2,.grid-3{grid-template-columns: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}
@ -122,40 +120,50 @@ body{
.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.heart{background:rgba(224,74,116,.1);color:var(--heart)}
.p-av.violet{background:rgba(123,93,191,.12);color:var(--violet-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.tr{background:rgba(224,74,116,.1);color:var(--heart);border:1px solid rgba(224,74,116,.08)}
.p-status.ac{background:rgba(90,208,224,.12);color:var(--glow);border:1px solid rgba(90,208,224,.1)}
/* ── 留言板 ── */
.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 input::placeholder,.msg-form textarea::placeholder{color:var(--text-faint)}
.msg-form textarea{min-height:80px;resize:vertical;line-height:1.6}
.msg-form .send-row{display:flex;gap:10px;align-items:center}
/* ── 架构进度滚动 ── */
.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)}
/* ── Notion ── */
.notion-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:8px 0}
/* ── 活动流 ── */
.feed{display:flex;flex-direction:column;gap:8px}
.feed-item{display:flex;align-items:center;gap:16px;padding:14px 18px;background:rgba(255,255,255,.02);border:1px solid var(--glass-edge);border-radius:14px;transition:all .3s;font-size:15px;cursor:pointer}
.feed-item:hover{background:rgba(255,255,255,.035);transform:translateX(3px);border-color:rgba(90,208,224,.1)}
.feed-item:active{transform:scale(.98)}
.feed-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.feed-dot.cyan{background:var(--glow);box-shadow:0 0 10px var(--glow)}
.feed-dot.violet{background:var(--violet-glow);box-shadow:0 0 10px var(--violet-glow)}
.feed-dot.green{background:var(--green);box-shadow:0 0 10px var(--green)}
.feed-dot.heart{background:var(--heart);box-shadow:0 0 12px var(--heart);animation:feed-h 2s ease-in-out infinite}
@keyframes feed-h{0%,100%{transform:scale(1)}50%{transform:scale(1.4)}}
/* ── 工具链注册表 ── */
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}
@ -168,7 +176,6 @@ body{
.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)}
.login-note{margin-top:12px;font-size:13px;color:var(--text-faint);line-height:1.6}
#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}
@ -177,11 +184,19 @@ body{
.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);border-color:rgba(90,208,224,.2)}
.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}
@ -196,75 +211,64 @@ body{
.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)}
/* ── 使用指南 ── */
.code-block{background:rgba(0,0,0,.3);padding:14px;border-radius:12px;font-size:14px;color:var(--glow);overflow-x:auto;margin:8px 0;line-height:1.8;border:1px solid rgba(90,208,224,.05)}
/* ── 底部 ── */
.footer{text-align:center;padding:28px;font-size:14px;color:var(--text-faint);letter-spacing:.12em;border-top:1px solid var(--glass-edge);margin-top:auto;position:relative;z-index:1;font-weight:400}
/* ── 聊天模态卡片 ── */
/* ── 聊天模态(可拖拽调整大小) ── */
#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:680px;max-height:84vh;background:rgba(11,20,36,.92);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);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);display:flex;flex-direction:column;animation:modalCard .35s cubic-bezier(.22,1,.36,1)}
.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:18px 24px;border-bottom:1px solid var(--glass-edge);flex-shrink: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}
.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:12px 24px;border-bottom:1px solid var(--glass-edge);flex-wrap:wrap;flex-shrink:0}
.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:20px 24px;display:flex;flex-direction:column;gap:14px}
.chat-modal-body .empty-hint{text-align:center;padding:60px 0;color:var(--text-faint);font-size:15px}
.msg{display:flex;gap:12px;max-width:82%;animation:msgIn .35s ease-out;align-items:flex-start}
.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:36px;height:36px;border-radius:12px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:600}
.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:3px}
.msg-con{display:flex;flex-direction:column;gap:2px}
.msg-nm{font-size:12px;color:var(--text-faint)}
.msg.user .msg-nm{color:var(--glow);opacity:.7}
.msg.bot .msg-nm{color:var(--green);opacity:.7}
.msg-bb{padding:12px 18px;border-radius:14px;font-size:15px;line-height:1.7;word-break:break-word}
.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 p{margin-bottom:8px}
.msg-bb p:last-child{margin-bottom:0}
.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)}
/* ── 聊天底部 ── */
.chat-modal-ft{flex-shrink:0;padding:16px 24px 20px;border-top:1px solid var(--glass-edge)}
.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:14px 18px;background:rgba(255,255,255,.035);border:1px solid var(--glass-edge);border-radius:14px;color:var(--text);font-size:16px;outline:none;font-family:inherit}
.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:14px 28px;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:16px;font-weight:500;cursor:pointer;transition:all .25s;font-family:inherit}
.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:8px;min-height:20px}
.chat-mod-thinking{display:none;align-items:center;gap:10px;padding:6px 0;font-size:14px;color:var(--text-soft)}
.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:8px;flex-wrap:wrap;margin-top:6px}
.tool-badge{padding:4px 10px;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.warn{background:rgba(212,160,48,.06);border-color:rgba(212,160,48,.12);color:var(--amber)}
.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}
@ -282,11 +286,12 @@ body{
.card{padding:20px}
.p-grid{grid-template-columns:1fr}
.dl-grid{grid-template-columns:1fr}
.grid-2,.grid-3{grid-template-columns:1fr}
.login-in input{width:100%}
.chat-modal-card{max-width:100%;max-height:100vh;border-radius:0;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}
}
</style>
</head>
@ -319,21 +324,18 @@ body{
<!-- 主内容 -->
<div class="page">
<!-- Hero -->
<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>
<!-- 仪表板 -->
<div class="dashboard">
<!-- 人格体 + 登录 -->
@ -371,7 +373,7 @@ body{
<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" style="display:none;font-size:13px;color:var(--heart);width:100%"></div>
<div class="login-err" id="login-err"></div>
</div>
<div id="logged-in-bar">
<div class="user-badge">
@ -387,30 +389,49 @@ body{
<button class="btn-logout" onclick="logout()">退出</button>
</div>
</div>
<div id="temp-code-block" style="display:none;">
<div style="display:flex;gap:10px;margin-top:12px">
<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 class="login-in 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>
<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" style="display:none;font-size:13px;color:var(--heart);margin-top:6px"></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="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="feed">
<div class="feed-item"><span class="feed-dot cyan"></span>铸渊 · D107 · 首页重构 + 引擎部署</div>
<div class="feed-item"><span class="feed-dot heart"></span>冰朔 · 守护 · 第五域</div>
<div class="feed-item"><span class="feed-dot violet"></span>曜冥 · 交感 · 情感层在线</div>
<div class="feed-item"><span class="feed-dot green"></span>霜砚 · 微调 · 1.5B LoRA 就绪</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> · D107 · 首页重构 + 引擎部署</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">Nginx</span> · API 路由修正 · chat-v2 接入 Portal</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">
@ -419,8 +440,8 @@ body{
<input placeholder="标题" id="msg-title" style="flex:2">
</div>
<textarea placeholder="写下你想说的话…守渊会保管好" id="msg-content"></textarea>
<div class="send-row">
<button class="login-in 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>
<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>
@ -434,7 +455,7 @@ body{
<div class="icon">🔒</div>
<div class="txt">模型下载仅对内测成员开放</div>
<div class="sub">登录代码仓库账号 · 需经白名单审批</div>
<button class="login-in 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>
<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>
@ -444,31 +465,6 @@ body{
</div>
</div>
<!-- 使用指南 + Notion -->
<div class="grid grid-2">
<div class="card breathe-violet">
<div class="card-header"><span class="hd cyan"></span>模型加载 · 使用指南 <span class="tag">transformers + peft</span></div>
<div style="font-size:15px;color:var(--text-faint);line-height:1.9">
<strong style="color:var(--light)">全参数模型7B</strong>
<div class="code-block">from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B")</div>
</div>
<div style="font-size:15px;color:var(--text-faint);line-height:1.9;margin-top:14px">
<strong style="color:var(--light)">蒸馏模板1.5B+ LoRA</strong>
<div class="code-block">from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("./qwen25-15b-shuangyan-distill/")
model = PeftModel.from_pretrained(base, "./shuangyan-lora/")</div>
</div>
<div style="margin-top:12px;font-size:14px;color:var(--text-faint)">微调脚本参考仓库 scripts/distill/finetune_*.py · 💡 不构造数据不加system prompt</div>
</div>
<div class="card breathe-heart">
<div class="card-header"><span class="hd heart"></span>Notion · 知识连接 <span class="tag" id="notion-label">未连接</span></div>
<div class="notion-body">
<div style="font-size:15px;color:var(--text-faint);margin-bottom:14px">连接 Notion 后读取和记录知识库</div>
<button class="login-in button" style="padding:12px 28px;background:linear-gradient(135deg,rgba(123,93,191,.2),rgba(42,157,191,.1));border:1px solid var(--glass-edge);border-radius:14px;color:var(--light);font-size:15px;cursor:pointer;font-family:inherit" onclick="connectNotion()">连接 Notion</button>
</div>
</div>
</div>
</div>
<div class="footer">
@ -476,9 +472,9 @@ model = PeftModel.from_pretrained(base, "./shuangyan-lora/")</div>
</div>
</div>
<!-- ===== 聊天模态卡片 ===== -->
<!-- ===== 聊天模态(可拖拽调整大小) ===== -->
<div id="chat-modal">
<div class="chat-modal-card">
<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>
@ -547,6 +543,61 @@ model = PeftModel.from_pretrained(base, "./shuangyan-lora/")</div>
}
})();
// ===== 架构进度数据 =====
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:'光湖驱动引擎 v1.0', 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';
@ -559,14 +610,13 @@ let chatHistory = [];
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 = '可用');
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];
@ -591,12 +641,10 @@ function openChat() {
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');
@ -633,7 +681,6 @@ async function modalSend() {
status.textContent = '';
tools.innerHTML = '';
// 机器人消息占位
const pName = currentPersona === 'zhuyuan' ? '铸渊' : '霜砚';
const pIcon = currentPersona === 'zhuyuan' ? '⚔' : '❄';
const botDiv = document.createElement('div');
@ -703,6 +750,7 @@ async function modalSend() {
} catch(e) {
console.error('Chat error:', e);
bubble.textContent = '连接失败: ' + e.message;
status.textContent = '连接失败,请重试。如果持续失败,检查登录状态。';
}
thinking.style.display = 'none';
@ -732,7 +780,7 @@ function appendMsg(role, text) {
function addToolBadge(text, warn) {
const area = document.getElementById('modal-tools');
const badge = document.createElement('span');
badge.className = 'tool-badge' + (warn ? ' warn' : '');
badge.className = 'tool-badge-sm' + (warn ? ' warn' : '');
badge.textContent = text;
area.appendChild(badge);
}
@ -825,7 +873,7 @@ function lockDownloads() {
document.getElementById('dl-tag').textContent = '登录后可下载';
}
// ===== 临时访问码 =====
// ===== 临时码 =====
function showTempInput() {
const block = document.getElementById('temp-code-block');
block.style.display = block.style.display === 'none' ? 'block' : 'none';
@ -862,7 +910,7 @@ async function validateTempCode() {
tempCode = code;
document.getElementById('temp-code-block').style.display = 'none';
unlockControls();
document.getElementById('modal-status').textContent = '临时访问模式 · 剩余 ' + d.remain + ' 条';
document.getElementById('modal-status').textContent = '临时访问模式';
} else {
const el = document.getElementById('temp-code-err');
el.textContent = d.message;
@ -871,21 +919,6 @@ async function validateTempCode() {
} catch(e) { alert('验证失败'); }
}
// ===== Notion =====
async function connectNotion() {
try { window.location.href = "/api/notion/connect?user_key=default"; } catch(e) {}
}
async function checkNotion() {
try {
const r = await fetch("/api/notion/status");
const d = await r.json();
if (!d.ok || !d.connected_users || !d.connected_users.length) return;
document.getElementById("notion-label").textContent = "✅ " + d.connected_users[0].workspace;
} catch(e) {}
}
setTimeout(checkNotion, 3000);
// ===== 留言 =====
async function sendMessage() {
const n = (document.getElementById('msg-name').value || '').trim() || '匿名';
@ -906,7 +939,7 @@ async function sendMessage() {
} catch(e) { document.getElementById('msg-status').textContent = '连接失败'; }
}
// ===== 恢复登录状态 =====
// ===== 恢复登录 =====
(function(){
const u = localStorage.getItem('current_user');
if (u && localStorage.getItem('logged_in') === 'true') {