mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 17:38:10 +00:00
2 lines
7.6 KiB
HTML
2 lines
7.6 KiB
HTML
function renderOneSettings(){let prefix=state.selectedSection+'.';let allKeys=Object.keys(state.settings||{});let filtered=allKeys.filter(k=>k===prefix.slice(0,-1)||k.startsWith(prefix));filtered.sort();let hideTopLlms=['core.llm.base_url','core.llm.model','core.llm.api_key','core.llm.adapter','core.llm.adapter_path','core.llm.thinking_enabled'];let sourceKeys=filtered.filter(k=>k.startsWith('core.llm.sources.'));let sourceMap={};sourceKeys.forEach(k=>{let parts=k.split('.');let srcName=parts[3];if(!sourceMap[srcName])sourceMap[srcName]={};sourceMap[srcName][k]=true});let mcpServerKeys=filtered.filter(k=>k.startsWith('plugin.mcp.servers.')&&k.split('.').length>=5);let mcpServerMap={};mcpServerKeys.forEach(k=>{let parts=k.split('.');let srvName=parts[3];if(!mcpServerMap[srvName])mcpServerMap[srvName]={};mcpServerMap[srvName][k]=true});let regularKeys=filtered.filter(k=>!k.startsWith('core.llm.sources.')&&hideTopLlms.indexOf(k)===-1&&!k.startsWith('plugin.mcp.servers.')&&k!=='plugin.mcp.servers');let html='<div class="settings-layout"><div class="settings-sidebar"></div><div class="settings-content">';if(regularKeys.length===0&&Object.keys(sourceMap).length===0&&Object.keys(mcpServerMap).length===0&&state.selectedSection!=='plugin.mcp'){html+='<div class="card"><h2>'+escHtml(state.selectedSection)+'</h2><p style="color:var(--text-muted)">æš‚æ— è®¾ç½®é¡?/p></div>'}else{regularKeys.forEach(k=>{let v=state.settings[k];let sv=typeof v==='object'?JSON.stringify(v):String(v);let m=state.meta?.[k];let label=m?.display_name||'å€?;let desc=m?.description||'';let typ=m?.type||'string';let ph=m?.placeholder||'';let opts=m?.options||[];let inpId='inp-'+k.replace(/\./g,'_');let inp='';if(typ==='bool'){let chk=sv==='true'?'checked':'';inp='<label style="display:flex;align-items:center;gap:8px;cursor:pointer"><input type="checkbox" id="'+inpId+'" '+chk+' onchange="markDirty(\''+k+'\')" style="width:auto;margin:0"> '+label+'</label>'}else if(typ==='password'){inp='<label>'+label+'</label><input type="password" id="'+inpId+'" value="'+escHtml(sv)+'" placeholder="'+escHtml(ph)+'" onchange="markDirty(\''+k+'\')">'}else if(typ==='text'){inp='<label>'+label+'</label><textarea id="'+inpId+'" onchange="markDirty(\''+k+'\')">'+escHtml(sv)+'</textarea>'}else if(typ==='select'&&opts.length>0){let sel='<label>'+label+'</label><select id="'+inpId+'" onchange="markDirty(\''+k+'\')">';opts.forEach(o=>{sel+='<option value="'+escHtml(o)+'"'+(sv===o?' selected':'')+'>'+escHtml(o)+'</option>'});sel+='</select>';inp=sel}else if(typ==='int'){inp='<label>'+label+'</label><input type="number" id="'+inpId+'" value="'+escHtml(sv)+'" placeholder="'+escHtml(ph)+'" onchange="markDirty(\''+k+'\')">'}else{inp='<label>'+label+'</label><input id="'+inpId+'" value="'+escHtml(sv)+'" placeholder="'+escHtml(ph)+'" onchange="markDirty(\''+k+'\')">'}html+='<div class="card"><button class="btn btn-primary btn-sm save-btn" onclick="saveSetting(\''+k+'\')" style="float:right;margin-top:-4px">ä¿<EFBFBD>å˜</button><div class="settings-key">'+escHtml(k)+'</div>'+inp;if(desc){html+='<p style="color:var(--text-muted);font-size:11px;margin-top:-6px">'+escHtml(desc)+'</p>'}html+='</div>'})}if(state.selectedSection==='core'){let srcNames=Object.keys(sourceMap).sort();srcNames.forEach(sn=>{let baseKey='core.llm.sources.'+sn;let srcHtml='<div class="card" style="border-left:3px solid var(--accent)"><h2 style="display:flex;justify-content:space-between;align-items:center"><span>🌐 '+escHtml(sn)+'</span><button class="btn btn-danger btn-sm" onclick="deleteSource(\''+sn+'\')" style="font-size:10px">åˆ é™¤</button></h2>';let fields=[{key:'adapter',label:'适é…<C3A9>å™?},{key:'base_url',label:'API 地å<C2B0>€'},{key:'model',label:'模型'},{key:'api_key',label:'API 密钥',typ:'password'},{key:'thinking_enabled',label:'深度æ€<C3A6>è€?,typ:'bool'}];fields.forEach(f=>{let fk=baseKey+'.'+f.key;let fv=state.settings[fk];let fsv=typeof fv==='object'?JSON.stringify(fv):String(fv||'');let fm=state.meta?.[fk];let ftyp=f.typ||fm?.type||'string';let finpId='inp-'+(baseKey+'.'+f.key).replace(/\./g,'_');let finp='';if(ftyp==='bool'){let chk=fsv==='true'?'checked':'';finp='<label style="display:flex;align-items:center;gap:8px;cursor:pointer;margin-bottom:6px"><input type="checkbox" id="'+finpId+'" '+chk+' onchange="markDirty(\''+baseKey+'.'+f.key+'\')" style="width:auto;margin:0"> '+f.label+'</label>'}else if(ftyp==='password'){finp='<label style="font-size:11px;color:var(--text-secondary)">'+f.label+'</label><input type="password" id="'+finpId+'" value="'+escHtml(fsv)+'" placeholder="留空则使用全局密钥" onchange="markDirty(\''+baseKey+'.'+f.key+'\')" style="margin-bottom:6px">'}else if(f.key==='adapter'&&window._adapters&&window._adapters.length){let sel='<label style="font-size:11px;color:var(--text-secondary)">'+f.label+'</label><select id="'+finpId+'" onchange="markDirty(\''+baseKey+'.'+f.key+'\')" style="margin-bottom:6px">';window._adapters.forEach(a=>{sel+='<option value="'+escHtml(a.name)+'" '+(a.name===fsv?'selected':'')+'>'+escHtml(a.name)+'</option>'});sel+='</select>';finp=sel}else{finp='<label style="font-size:11px;color:var(--text-secondary)">'+f.label+'</label><input id="'+finpId+'" value="'+escHtml(fsv)+'" placeholder="输入'+f.label+'" onchange="markDirty(\''+baseKey+'.'+f.key+'\')" style="margin-bottom:6px">'}srcHtml+=finp});srcHtml+='<button class="btn btn-primary btn-sm" onclick="saveSetting(\''+baseKey+'.adapter\');saveSetting(\''+baseKey+'.base_url\');saveSetting(\''+baseKey+'.model\');saveSetting(\''+baseKey+'.api_key\');if(document.getElementById(\''+('inp-'+baseKey+'.thinking_enabled').replace(/\./g,'_')+'\'))saveSetting(\''+baseKey+'.thinking_enabled\');toast(\'æº?\\\''+sn+'\\\' å·²ä¿<C3A4>å˜\')" style="margin-top:6px">ä¿<EFBFBD>å˜æº?/button></div>';html+=srcHtml});html+='<div style="margin-top:16px;text-align:center"><button class="btn btn-primary" onclick="showAddSourceDialog()" style="min-width:160px">+ æ·»åŠ æ–?LLM æº?/button></div>'};if(state.selectedSection==='plugin.mcp'){Object.keys(mcpServerMap).sort().forEach(sn=>{let baseKey='plugin.mcp.servers.'+sn;let cmd=state.settings[baseKey+'.command'],url=state.settings[baseKey+'.url'];if((!cmd||cmd==='<nil>')&&(!url||url==='<nil>'))return;let html2='<div class="card" style="border-left:3px solid var(--accent);margin-top:12px"><h2 style="display:flex;justify-content:space-between;align-items:center"><span>⚙ '+escHtml(sn)+'</span><button class="btn btn-danger btn-sm" onclick="deleteMCPServer(\''+sn+'\')" style="font-size:10px">åˆ é™¤</button></h2>';let fields=[{key:'command',label:'命令'},{key:'url',label:'URL'},{key:'args',label:'å<>‚æ•°(JSON)'},{key:'env',label:'环境å<C692>˜é‡<C3A9>(JSON)'}];fields.forEach(f=>{let fk=baseKey+'.'+f.key;let fv=state.settings[fk];let fsv=typeof fv==='object'?JSON.stringify(fv):String(fv||'');let finpId='inp-'+fk.replace(/\./g,'_');let finp='';if(f.key==='args'||f.key==='env'){finp='<label style="font-size:11px;color:var(--text-secondary)">'+f.label+'</label><textarea id="'+finpId+'" onchange="markDirty(\''+fk+'\')" style="margin-bottom:6px">'+escHtml(fsv)+'</textarea>'}else{finp='<label style="font-size:11px;color:var(--text-secondary)">'+f.label+'</label><input id="'+finpId+'" value="'+escHtml(fsv)+'" placeholder="输入'+f.label+'" onchange="markDirty(\''+fk+'\')" style="margin-bottom:6px">'}html2+=finp});html2+='<button class="btn btn-primary btn-sm" onclick="saveSetting(\''+baseKey+'.command\');saveSetting(\''+baseKey+'.url\');saveSetting(\''+baseKey+'.args\');saveSetting(\''+baseKey+'.env\')" style="margin-top:6px">ä¿<EFBFBD>å˜</button></div>';html+=html2});html+='<div style="margin-top:16px;text-align:center"><button class="btn btn-primary" onclick="addMCPSource()" style="min-width:160px">+ æ·»åŠ MCP æœ<C3A6>务å™?/button></div>'}}html+='</div></div>'
|