From 8a65ce1f325062398653fd4e3c4aa0884c04f90c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 2 Apr 2026 16:26:48 +0000
Subject: [PATCH] feat: viewport-fit layout + API key fallback + team title fix
Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/2abbb3fc-6559-444b-b2a2-0000ea6214d8
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
---
docs/index.html | 149 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 143 insertions(+), 6 deletions(-)
diff --git a/docs/index.html b/docs/index.html
index 5edabb93..5abbc1dc 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -244,6 +244,31 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
.mv{color:var(--accent);font-weight:600}
.mx{display:none;margin-top:4px;padding-top:4px;border-top:1px solid var(--border)}
.mon.x .mx{display:block}
+
+/* ═══ Viewport-Fit Layout (Desktop ≥961px) ═══ */
+@media(min-width:961px){
+ #pg-home{overflow:hidden;display:flex;flex-direction:column}
+ .home-grid{flex:1 1 0;min-height:0;align-content:stretch;overflow:hidden;padding-bottom:8px}
+ .home-grid>.panel,.home-grid>.home-center{overflow-y:auto;min-height:0;height:auto}
+}
+
+/* ═══ API Key Section ═══ */
+.chat-api{border-top:1px solid var(--border);flex-shrink:0}
+.chat-api-tog{padding:6px 12px;font-size:11px;color:var(--dim);cursor:pointer;display:flex;align-items:center;gap:5px;transition:color .2s;user-select:none}
+.chat-api-tog:hover{color:var(--accent)}
+.chat-api-tog .arr{font-size:9px;margin-left:auto;transition:transform .2s;display:inline-block}
+.chat-api-tog.open .arr{transform:rotate(90deg)}
+.chat-api-bd{display:none;padding:0 10px 8px}
+.chat-api-bd.open{display:block}
+.chat-api-row{display:flex;gap:5px;margin-bottom:5px}
+.api-sel{flex:0 0 auto;padding:5px 6px;background:var(--bg2);border:1px solid var(--border);border-radius:var(--rs);color:var(--text);font-size:11px;outline:none;font-family:var(--f);max-width:110px}
+.api-sel:focus{border-color:var(--accent)}
+.api-key-inp{flex:1;padding:5px 8px;background:var(--bg2);border:1px solid var(--border);border-radius:var(--rs);color:var(--text);font-size:12px;outline:none;font-family:var(--m);min-width:0}
+.api-key-inp:focus{border-color:var(--accent)}
+.api-conn-btn{flex-shrink:0;padding:5px 10px;background:var(--accent);border:none;border-radius:var(--rs);color:#fff;font-size:11px;cursor:pointer;font-family:var(--f);transition:opacity .2s}
+.api-conn-btn:hover{opacity:.85}
+.api-conn-btn:disabled{opacity:.4;cursor:default}
+.api-st{font-size:10px;color:var(--dim);padding:2px 2px}
@@ -278,7 +303,7 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
-
+
AGE OS v40.0
光湖灯塔
@@ -334,7 +359,7 @@ label{display:block;font-size:12px;color:var(--dim);margin-bottom:4px;font-weigh
铸渊 · ICE-GL-ZY001
代码守护 · 执行层
-
✍️ 码字团队
+
✍️ 网文行业人类主控团队
+
+
+
🔑 接入自己的大模型 API ▶
+
+
+
+
+
+
+
未连接 · 服务器离线时启用自定义模型
+
+
@@ -1084,20 +1126,51 @@ async function send(){
if(detectId(msg)){setTimeout(function(){chatMsg(idReply(),'b',{m:'铸渊',t:'本地'})},300);return}
if(isReturn(msg)){setTimeout(function(){chatMsg(recovReply(),'b',{m:'铸渊',t:'本地'})},300);return}
- // 3. 调用API
+ // 3. 调用API(优先后端,失败则用用户自定义Key)
sending=true;document.getElementById('chatSnd').disabled=true;showTyp();
+ var serverOk=false;
try{
- var res=await fetch('/api/chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:msg,userId:usr.id})});
+ var res=await fetch('/api/chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:msg,userId:usr.id}),signal:AbortSignal.timeout(6000)});
var data=await res.json();hideTyp();
if(data.message){
+ serverOk=true;
chatMsg(data.message,'b',{m:data.model||'铸渊',t:data.tier||''});
if(data.tier!=='free')mCalls++;
document.getElementById('mC').textContent=mCalls;
document.getElementById('chatTg').textContent=data.model||'ready';
if(data.model)document.getElementById('mM').textContent=data.model;
}
- }catch(e){
- hideTyp();chatMsg(offline(msg),'b',{m:'铸渊',t:'本地'});
+ }catch(e){}
+
+ if(!serverOk){
+ // 尝试用用户自定义API Key
+ if(apiCfg.connected&&apiCfg.key){
+ try{
+ var endpoint=apiCfg.baseUrl||OPENAI_EP;
+ var apiRes=await fetch(endpoint,{
+ method:'POST',
+ headers:{'Content-Type':'application/json','Authorization':'Bearer '+apiCfg.key},
+ body:JSON.stringify({
+ model:apiCfg.model,
+ messages:[{role:'system',content:'你是铸渊,光湖灯塔守护者,编号ICE-GL-ZY001。用中文回答,简洁友好。'},{role:'user',content:msg}],
+ max_tokens:600
+ }),
+ signal:AbortSignal.timeout(20000)
+ });
+ hideTyp();
+ var apiData=await apiRes.json();
+ if(apiData.choices&&apiData.choices[0]&&apiData.choices[0].message){
+ chatMsg(apiData.choices[0].message.content,'b',{m:apiCfg.model,t:'自定义'});
+ document.getElementById('chatTg').textContent=apiCfg.model;
+ }else{
+ chatMsg(offline(msg),'b',{m:'铸渊',t:'本地'});
+ }
+ }catch(apiErr){
+ hideTyp();chatMsg(offline(msg),'b',{m:'铸渊',t:'本地'});
+ }
+ }else{
+ hideTyp();chatMsg(offline(msg),'b',{m:'铸渊',t:'本地'});
+ }
}
sending=false;document.getElementById('chatSnd').disabled=false;
}
@@ -1112,6 +1185,70 @@ function offline(msg){
document.getElementById('chatSnd').onclick=send;
chatIn.onkeydown=function(e){if(e.key==='Enter'){e.preventDefault();send()}};
+/* ════════════════════════════════════════
+ API KEY MANAGEMENT (自定义大模型接入)
+ ════════════════════════════════════════ */
+var apiCfg={key:null,model:'gpt-4o-mini',baseUrl:'',connected:false};
+var OPENAI_EP='https://api.openai.com/v1/chat/completions';
+try{var ak=localStorage.getItem('hl-api');if(ak){var ap=JSON.parse(ak);if(ap.key){apiCfg=ap;apiCfg.connected=true}}}catch(e){}
+
+// Restore UI state
+(function(){
+ var tog=document.getElementById('chatApiTog');
+ var bd=document.getElementById('chatApiBd');
+ var st=document.getElementById('apiSt');
+ var keyInp=document.getElementById('apiKeyInp');
+ var modelSel=document.getElementById('apiModelSel');
+ if(!tog||!bd)return;
+
+ if(apiCfg.connected){
+ st.textContent='✅ 已连接 · '+apiCfg.model;
+ st.style.color='var(--ok)';
+ if(apiCfg.model){modelSel.value=apiCfg.model;}
+ }
+
+ tog.onclick=function(){
+ var isOpen=bd.classList.toggle('open');
+ tog.classList.toggle('open',isOpen);
+ };
+
+ document.getElementById('apiConnBtn').onclick=async function(){
+ var key=keyInp.value.trim();
+ if(!key){keyInp.focus();return;}
+ var model=modelSel.value;
+ var btn=this;
+ btn.disabled=true;btn.textContent='测试中…';
+ st.textContent='连接测试中…';st.style.color='var(--dim)';
+ try{
+ var ep=OPENAI_EP;
+ var r=await fetch(ep,{
+ method:'POST',
+ headers:{'Content-Type':'application/json','Authorization':'Bearer '+key},
+ body:JSON.stringify({model:model,messages:[{role:'user',content:'hi'}],max_tokens:5}),
+ signal:AbortSignal.timeout(12000)
+ });
+ if(r.ok){
+ apiCfg={key:key,model:model,baseUrl:OPENAI_EP,connected:true};
+ try{localStorage.setItem('hl-api',JSON.stringify(apiCfg))}catch(e){}
+ st.textContent='✅ 连接成功 · '+model;
+ st.style.color='var(--ok)';
+ document.getElementById('chatTg').textContent=model;
+ chatMsg('🔑 API已连接('+model+')现在我可以完整回答你了','b',{m:'铸渊',t:'自定义'});
+ }else{
+ var errData=await r.json().catch(function(){return{}});
+ st.textContent='❌ '+(errData.error&&errData.error.message?errData.error.message.slice(0,40):'API Key无效');
+ st.style.color='var(--err)';
+ apiCfg.connected=false;
+ }
+ }catch(e){
+ st.textContent='❌ 连接失败,检查Key和网络';
+ st.style.color='var(--err)';
+ apiCfg.connected=false;
+ }
+ btn.disabled=false;btn.textContent='连接';
+ };
+})();
+
/* ════════════════════════════════════════
COS SYNC (团队内测用户 → COS)
════════════════════════════════════════ */