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='

API 对接

'+tabs+'
'+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('已更新','新密钥已生效'); }