let apiDocTab='ingest';
async function viewAPIDocs(){
const doc=await api('/api/admin/api-docs');
if(doc.error){ $('#app').innerHTML='
'+esc(doc.error)+'
'; return; }
const groups=doc.groups||[];
if(!groups.some(g=>g.id===apiDocTab)) apiDocTab=(groups[0]&&groups[0].id)||'';
const tabs=groups.map(g=>'').join('');
const g=groups.find(x=>x.id===apiDocTab)||groups[0]||{endpoints:[]};
const key=g.key?'固定密钥
'+esc(g.key)+'
':'';
const eps=(g.endpoints||[]).map(ep=>{
const body=ep.body?'请求体
'+esc(JSON.stringify(ep.body,null,2))+'
':'';
return ''+esc(ep.method)+''+esc(ep.path)+'
'+esc(ep.summary||'')+'
'+body+'
示例
'+esc(ep.curl||'')+'
';
}).join('');
$('#app').innerHTML=''+esc(g.auth||'')+'
基址 '+esc(doc.base||'')+'
'+key+eps;
}
function copyText(text){
const done=()=>notice('已复制','');
if(navigator.clipboard && navigator.clipboard.writeText){ navigator.clipboard.writeText(text).then(done).catch(()=>fallbackCopy(text)); return; }
fallbackCopy(text);
}
function fallbackCopy(text){
const ta=document.createElement('textarea');
ta.value=text; document.body.appendChild(ta); ta.select();
try{ document.execCommand('copy'); notice('已复制',''); }catch(e){ fail('无法复制', text); }
ta.remove();
}
function copyIngestKey(){
const el=document.getElementById('ingestKey');
copyText(el?el.textContent:'');
}
async function rotateIngestKey(){
const ok=await modal({title:'更新上报密钥', message:'旧密钥会立即失效,正在使用的上报方需要换成新密钥。', okText:'更新'});
if(!ok) return;
const res=await api('/api/admin/ingest-key',{method:'POST',body:'{}'});
if(res.error) return fail('无法更新', res.error);
const el=document.getElementById('ingestKey');
if(el && res.key) el.textContent=res.key;
notice('已更新','新密钥已生效');
}