From 45f08e553b3b9629d35a997b68f1c08494e96a3a Mon Sep 17 00:00:00 2001 From: Catie Date: Wed, 23 Sep 2026 09:49:10 +0800 Subject: [PATCH] feat: promote Antigravity to a standalone sidebar page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give Antigravity its own top-level sidebar entry instead of a button on the 绘图 page. DrawingView gains a `variant` prop so the same account-pool UI serves both pages: the antigravity variant lists only provider=antigravity channels with an Antigravity-oriented import guide and create button, while the drawing page now excludes antigravity channels entirely. Rebuild the frontend bundle (index-B276P45A.js). Co-Authored-By: Claude Opus 4.8 (1M context) --- dist/assets/index-B276P45A.js | 43 ++++++++++++++++++++++++ dist/assets/index-B9-tgVyd.js | 43 ------------------------ dist/index.html | 2 +- src/App.tsx | 61 ++++++++++++++++++++++++++--------- 4 files changed, 89 insertions(+), 60 deletions(-) create mode 100644 dist/assets/index-B276P45A.js delete mode 100644 dist/assets/index-B9-tgVyd.js diff --git a/dist/assets/index-B276P45A.js b/dist/assets/index-B276P45A.js new file mode 100644 index 0000000..6fecadf --- /dev/null +++ b/dist/assets/index-B276P45A.js @@ -0,0 +1,43 @@ +(function(){const f=document.createElement("link").relList;if(f&&f.supports&&f.supports("modulepreload"))return;for(const A of document.querySelectorAll('link[rel="modulepreload"]'))r(A);new MutationObserver(A=>{for(const T of A)if(T.type==="childList")for(const L of T.addedNodes)L.tagName==="LINK"&&L.rel==="modulepreload"&&r(L)}).observe(document,{childList:!0,subtree:!0});function p(A){const T={};return A.integrity&&(T.integrity=A.integrity),A.referrerPolicy&&(T.referrerPolicy=A.referrerPolicy),A.crossOrigin==="use-credentials"?T.credentials="include":A.crossOrigin==="anonymous"?T.credentials="omit":T.credentials="same-origin",T}function r(A){if(A.ep)return;A.ep=!0;const T=p(A);fetch(A.href,T)}})();function q0(u){return u&&u.__esModule&&Object.prototype.hasOwnProperty.call(u,"default")?u.default:u}var Qc={exports:{}},is={};var tm;function G0(){if(tm)return is;tm=1;var u=Symbol.for("react.transitional.element"),f=Symbol.for("react.fragment");function p(r,A,T){var L=null;if(T!==void 0&&(L=""+T),A.key!==void 0&&(L=""+A.key),"key"in A){T={};for(var $ in A)$!=="key"&&(T[$]=A[$])}else T=A;return A=T.ref,{$$typeof:u,type:r,key:L,ref:A!==void 0?A:null,props:T}}return is.Fragment=f,is.jsx=p,is.jsxs=p,is}var lm;function Y0(){return lm||(lm=1,Qc.exports=G0()),Qc.exports}var n=Y0(),Xc={exports:{}},Ae={};var am;function L0(){if(am)return Ae;am=1;var u=Symbol.for("react.transitional.element"),f=Symbol.for("react.portal"),p=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),A=Symbol.for("react.profiler"),T=Symbol.for("react.consumer"),L=Symbol.for("react.context"),$=Symbol.for("react.forward_ref"),C=Symbol.for("react.suspense"),g=Symbol.for("react.memo"),G=Symbol.for("react.lazy"),z=Symbol.for("react.activity"),V=Symbol.iterator;function W(m){return m===null||typeof m!="object"?null:(m=V&&m[V]||m["@@iterator"],typeof m=="function"?m:null)}var fe={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},te=Object.assign,ae={};function ie(m,h,M){this.props=m,this.context=h,this.refs=ae,this.updater=M||fe}ie.prototype.isReactComponent={},ie.prototype.setState=function(m,h){if(typeof m!="object"&&typeof m!="function"&&m!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,m,h,"setState")},ie.prototype.forceUpdate=function(m){this.updater.enqueueForceUpdate(this,m,"forceUpdate")};function be(){}be.prototype=ie.prototype;function Y(m,h,M){this.props=m,this.context=h,this.refs=ae,this.updater=M||fe}var xe=Y.prototype=new be;xe.constructor=Y,te(xe,ie.prototype),xe.isPureReactComponent=!0;var P=Array.isArray;function he(){}var _={H:null,A:null,T:null,S:null},ne=Object.prototype.hasOwnProperty;function me(m,h,M){var Q=M.ref;return{$$typeof:u,type:m,key:h,ref:Q!==void 0?Q:null,props:M}}function Ce(m,h){return me(m.type,h,m.props)}function Me(m){return typeof m=="object"&&m!==null&&m.$$typeof===u}function ue(m){var h={"=":"=0",":":"=2"};return"$"+m.replace(/[=:]/g,function(M){return h[M]})}var K=/\/+/g;function de(m,h){return typeof m=="object"&&m!==null&&m.key!=null?ue(""+m.key):h.toString(36)}function J(m){switch(m.status){case"fulfilled":return m.value;case"rejected":throw m.reason;default:switch(typeof m.status=="string"?m.then(he,he):(m.status="pending",m.then(function(h){m.status==="pending"&&(m.status="fulfilled",m.value=h)},function(h){m.status==="pending"&&(m.status="rejected",m.reason=h)})),m.status){case"fulfilled":return m.value;case"rejected":throw m.reason}}throw m}function N(m,h,M,Q,ee){var Ne=typeof m;(Ne==="undefined"||Ne==="boolean")&&(m=null);var O=!1;if(m===null)O=!0;else switch(Ne){case"bigint":case"string":case"number":O=!0;break;case"object":switch(m.$$typeof){case u:case f:O=!0;break;case G:return O=m._init,N(O(m._payload),h,M,Q,ee)}}if(O)return ee=ee(m),O=Q===""?"."+de(m,0):Q,P(ee)?(M="",O!=null&&(M=O.replace(K,"$&/")+"/"),N(ee,h,M,"",function(St){return St})):ee!=null&&(Me(ee)&&(ee=Ce(ee,M+(ee.key==null||m&&m.key===ee.key?"":(""+ee.key).replace(K,"$&/")+"/")+O)),h.push(ee)),1;O=0;var ye=Q===""?".":Q+":";if(P(m))for(var ce=0;ce>>1,se=N[X];if(0>>1;XA(M,H))QA(ee,M)?(N[X]=ee,N[Q]=H,X=Q):(N[X]=M,N[h]=H,X=h);else if(QA(ee,H))N[X]=ee,N[Q]=H,X=Q;else break e}}return k}function A(N,k){var H=N.sortIndex-k.sortIndex;return H!==0?H:N.id-k.id}if(u.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var T=performance;u.unstable_now=function(){return T.now()}}else{var L=Date,$=L.now();u.unstable_now=function(){return L.now()-$}}var C=[],g=[],G=1,z=null,V=3,W=!1,fe=!1,te=!1,ae=!1,ie=typeof setTimeout=="function"?setTimeout:null,be=typeof clearTimeout=="function"?clearTimeout:null,Y=typeof setImmediate<"u"?setImmediate:null;function xe(N){for(var k=p(g);k!==null;){if(k.callback===null)r(g);else if(k.startTime<=N)r(g),k.sortIndex=k.expirationTime,f(C,k);else break;k=p(g)}}function P(N){if(te=!1,xe(N),!fe)if(p(C)!==null)fe=!0,he||(he=!0,ue());else{var k=p(g);k!==null&&J(P,k.startTime-N)}}var he=!1,_=-1,ne=5,me=-1;function Ce(){return ae?!0:!(u.unstable_now()-meN&&Ce());){var X=z.callback;if(typeof X=="function"){z.callback=null,V=z.priorityLevel;var se=X(z.expirationTime<=N);if(N=u.unstable_now(),typeof se=="function"){z.callback=se,xe(N),k=!0;break t}z===p(C)&&r(C),xe(N)}else r(C);z=p(C)}if(z!==null)k=!0;else{var m=p(g);m!==null&&J(P,m.startTime-N),k=!1}}break e}finally{z=null,V=H,W=!1}k=void 0}}finally{k?ue():he=!1}}}var ue;if(typeof Y=="function")ue=function(){Y(Me)};else if(typeof MessageChannel<"u"){var K=new MessageChannel,de=K.port2;K.port1.onmessage=Me,ue=function(){de.postMessage(null)}}else ue=function(){ie(Me,0)};function J(N,k){_=ie(function(){N(u.unstable_now())},k)}u.unstable_IdlePriority=5,u.unstable_ImmediatePriority=1,u.unstable_LowPriority=4,u.unstable_NormalPriority=3,u.unstable_Profiling=null,u.unstable_UserBlockingPriority=2,u.unstable_cancelCallback=function(N){N.callback=null},u.unstable_forceFrameRate=function(N){0>N||125X?(N.sortIndex=H,f(g,N),p(C)===null&&N===p(g)&&(te?(be(_),_=-1):te=!0,J(P,H-X))):(N.sortIndex=se,f(C,N),fe||W||(fe=!0,he||(he=!0,ue()))),N},u.unstable_shouldYield=Ce,u.unstable_wrapCallback=function(N){var k=V;return function(){var H=V;V=k;try{return N.apply(this,arguments)}finally{V=H}}}})(Vc)),Vc}var im;function X0(){return im||(im=1,Zc.exports=Q0()),Zc.exports}var Jc={exports:{}},gt={};var um;function K0(){if(um)return gt;um=1;var u=eo();function f(C){var g="https://react.dev/errors/"+C;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(u)}catch(f){console.error(f)}}return u(),Jc.exports=K0(),Jc.exports}var om;function V0(){if(om)return us;om=1;var u=X0(),f=eo(),p=Z0();function r(e){var t="https://react.dev/errors/"+e;if(1se||(e.current=X[se],X[se]=null,se--)}function M(e,t){se++,X[se]=e.current,e.current=t}var Q=m(null),ee=m(null),Ne=m(null),O=m(null);function ye(e,t){switch(M(Ne,t),M(ee,e),M(Q,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Af(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Af(t),e=Cf(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}h(Q),M(Q,e)}function ce(){h(Q),h(ee),h(Ne)}function St(e){e.memoizedState!==null&&M(O,e);var t=Q.current,l=Cf(t,e.type);t!==l&&(M(ee,e),M(Q,l))}function F(e){ee.current===e&&(h(Q),h(ee)),O.current===e&&(h(O),ls._currentValue=H)}var $e,rt;function We(e){if($e===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);$e=t&&t[1]||"",rt=-1)":-1s||d[a]!==j[s]){var D=` +`+d[a].replace(" at new "," at ");return e.displayName&&D.includes("")&&(D=D.replace("",e.displayName)),D}while(1<=a&&0<=s);break}}}finally{bt=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?We(l):""}function tl(e,t){switch(e.tag){case 26:case 27:case 5:return We(e.type);case 16:return We("Lazy");case 13:return e.child!==t&&t!==null?We("Suspense Fallback"):We("Suspense");case 19:return We("SuspenseList");case 0:case 15:return Ut(e.type,!1);case 11:return Ut(e.type.render,!1);case 1:return Ut(e.type,!0);case 31:return We("Activity");default:return""}}function ll(e){try{var t="",l=null;do t+=tl(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var U=Object.prototype.hasOwnProperty,B=u.unstable_scheduleCallback,Be=u.unstable_cancelCallback,Fe=u.unstable_shouldYield,nt=u.unstable_requestPaint,et=u.unstable_now,zi=u.unstable_getCurrentPriorityLevel,hn=u.unstable_ImmediatePriority,ia=u.unstable_UserBlockingPriority,ua=u.unstable_NormalPriority,Oi=u.unstable_LowPriority,R=u.unstable_IdlePriority,Z=u.log,le=u.unstable_setDisableYieldValue,I=null,ge=null;function qe(e){if(typeof Z=="function"&&le(e),ge&&typeof ge.setStrictMode=="function")try{ge.setStrictMode(I,e)}catch{}}var Ke=Math.clz32?Math.clz32:ca,Rt=Math.log,Rl=Math.LN2;function ca(e){return e>>>=0,e===0?32:31-(Rt(e)/Rl|0)|0}var Ea=256,Ma=262144,wl=4194304;function hl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function os(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var s=0,i=e.suspendedLanes,c=e.pingedLanes;e=e.warmLanes;var o=a&134217727;return o!==0?(a=o&~i,a!==0?s=hl(a):(c&=o,c!==0?s=hl(c):l||(l=o&~e,l!==0&&(s=hl(l))))):(o=a&~i,o!==0?s=hl(o):c!==0?s=hl(c):l||(l=a&~e,l!==0&&(s=hl(l)))),s===0?0:t!==0&&t!==s&&(t&i)===0&&(i=s&-s,l=t&-t,i>=l||i===32&&(l&4194048)!==0)?t:s}function pn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Cm(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ao(){var e=wl;return wl<<=1,(wl&62914560)===0&&(wl=4194304),e}function _i(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function vn(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Tm(e,t,l,a,s,i){var c=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var o=e.entanglements,d=e.expirationTimes,j=e.hiddenUpdates;for(l=c&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Dm=/[\n"\\]/g;function Xt(e){return e.replace(Dm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Bi(e,t,l,a,s,i,c,o){e.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?e.type=c:e.removeAttribute("type"),t!=null?c==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+Qt(t)):e.value!==""+Qt(t)&&(e.value=""+Qt(t)):c!=="submit"&&c!=="reset"||e.removeAttribute("value"),t!=null?qi(e,c,Qt(t)):l!=null?qi(e,c,Qt(l)):a!=null&&e.removeAttribute("value"),s==null&&i!=null&&(e.defaultChecked=!!i),s!=null&&(e.checked=s&&typeof s!="function"&&typeof s!="symbol"),o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?e.name=""+Qt(o):e.removeAttribute("name")}function yo(e,t,l,a,s,i,c,o){if(i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(e.type=i),t!=null||l!=null){if(!(i!=="submit"&&i!=="reset"||t!=null)){Hi(e);return}l=l!=null?""+Qt(l):"",t=t!=null?""+Qt(t):l,o||t===e.value||(e.value=t),e.defaultValue=t}a=a??s,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=o?e.checked:!!a,e.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.name=c),Hi(e)}function qi(e,t,l){t==="number"&&fs(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ra(e,t,l,a){if(e=e.options,t){t={};for(var s=0;s"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Qi=!1;if(yl)try{var xn={};Object.defineProperty(xn,"passive",{get:function(){Qi=!0}}),window.addEventListener("test",xn,xn),window.removeEventListener("test",xn,xn)}catch{Qi=!1}var Bl=null,Xi=null,hs=null;function Ao(){if(hs)return hs;var e,t=Xi,l=t.length,a,s="value"in Bl?Bl.value:Bl.textContent,i=s.length;for(e=0;e=Nn),Oo=" ",_o=!1;function Do(e,t){switch(e){case"keyup":return ih.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Uo(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var qa=!1;function ch(e,t){switch(e){case"compositionend":return Uo(t);case"keypress":return t.which!==32?null:(_o=!0,Oo);case"textInput":return e=t.data,e===Oo&&_o?null:e;default:return null}}function oh(e,t){if(qa)return e==="compositionend"||!$i&&Do(e,t)?(e=Ao(),hs=Xi=Bl=null,qa=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Lo(l)}}function Qo(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Qo(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Xo(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=fs(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=fs(e.document)}return t}function Ii(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var yh=yl&&"documentMode"in document&&11>=document.documentMode,Ga=null,Pi=null,En=null,eu=!1;function Ko(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;eu||Ga==null||Ga!==fs(a)||(a=Ga,"selectionStart"in a&&Ii(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),En&&Tn(En,a)||(En=a,a=ui(Pi,"onSelect"),0>=c,s-=c,ol=1<<32-Ke(t)+s|l<Ee?(De=re,re=null):De=re.sibling;var we=S(y,re,x[Ee],w);if(we===null){re===null&&(re=De);break}e&&re&&we.alternate===null&&t(y,re),v=i(we,v,Ee),Re===null?pe=we:Re.sibling=we,Re=we,re=De}if(Ee===x.length)return l(y,re),Ue&&bl(y,Ee),pe;if(re===null){for(;EeEe?(De=re,re=null):De=re.sibling;var sa=S(y,re,we.value,w);if(sa===null){re===null&&(re=De);break}e&&re&&sa.alternate===null&&t(y,re),v=i(sa,v,Ee),Re===null?pe=sa:Re.sibling=sa,Re=sa,re=De}if(we.done)return l(y,re),Ue&&bl(y,Ee),pe;if(re===null){for(;!we.done;Ee++,we=x.next())we=q(y,we.value,w),we!==null&&(v=i(we,v,Ee),Re===null?pe=we:Re.sibling=we,Re=we);return Ue&&bl(y,Ee),pe}for(re=a(re);!we.done;Ee++,we=x.next())we=E(re,y,Ee,we.value,w),we!==null&&(e&&we.alternate!==null&&re.delete(we.key===null?Ee:we.key),v=i(we,v,Ee),Re===null?pe=we:Re.sibling=we,Re=we);return e&&re.forEach(function(B0){return t(y,B0)}),Ue&&bl(y,Ee),pe}function Qe(y,v,x,w){if(typeof x=="object"&&x!==null&&x.type===te&&x.key===null&&(x=x.props.children),typeof x=="object"&&x!==null){switch(x.$$typeof){case W:e:{for(var pe=x.key;v!==null;){if(v.key===pe){if(pe=x.type,pe===te){if(v.tag===7){l(y,v.sibling),w=s(v,x.props.children),w.return=y,y=w;break e}}else if(v.elementType===pe||typeof pe=="object"&&pe!==null&&pe.$$typeof===ne&&ba(pe)===v.type){l(y,v.sibling),w=s(v,x.props),Un(w,x),w.return=y,y=w;break e}l(y,v);break}else t(y,v);v=v.sibling}x.type===te?(w=ha(x.props.children,y.mode,w,x.key),w.return=y,y=w):(w=As(x.type,x.key,x.props,null,y.mode,w),Un(w,x),w.return=y,y=w)}return c(y);case fe:e:{for(pe=x.key;v!==null;){if(v.key===pe)if(v.tag===4&&v.stateNode.containerInfo===x.containerInfo&&v.stateNode.implementation===x.implementation){l(y,v.sibling),w=s(v,x.children||[]),w.return=y,y=w;break e}else{l(y,v);break}else t(y,v);v=v.sibling}w=uu(x,y.mode,w),w.return=y,y=w}return c(y);case ne:return x=ba(x),Qe(y,v,x,w)}if(J(x))return oe(y,v,x,w);if(ue(x)){if(pe=ue(x),typeof pe!="function")throw Error(r(150));return x=pe.call(x),Se(y,v,x,w)}if(typeof x.then=="function")return Qe(y,v,_s(x),w);if(x.$$typeof===Y)return Qe(y,v,Es(y,x),w);Ds(y,x)}return typeof x=="string"&&x!==""||typeof x=="number"||typeof x=="bigint"?(x=""+x,v!==null&&v.tag===6?(l(y,v.sibling),w=s(v,x),w.return=y,y=w):(l(y,v),w=iu(x,y.mode,w),w.return=y,y=w),c(y)):l(y,v)}return function(y,v,x,w){try{Dn=0;var pe=Qe(y,v,x,w);return Wa=null,pe}catch(re){if(re===$a||re===zs)throw re;var Re=Ht(29,re,null,y.mode);return Re.lanes=w,Re.return=y,Re}}}var ja=hr(!0),pr=hr(!1),kl=!1;function bu(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xu(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ql(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Xl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(He&2)!==0){var s=a.pending;return s===null?t.next=t:(t.next=s.next,s.next=t),a.pending=t,t=Ns(e),Io(e,null,l),t}return Ss(e,a,t,l),Ns(e)}function Rn(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,so(e,l)}}function ju(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var s=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};i===null?s=i=c:i=i.next=c,l=l.next}while(l!==null);i===null?s=i=t:i=i.next=t}else s=i=t;l={baseState:a.baseState,firstBaseUpdate:s,lastBaseUpdate:i,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Su=!1;function wn(){if(Su){var e=Ja;if(e!==null)throw e}}function Hn(e,t,l,a){Su=!1;var s=e.updateQueue;kl=!1;var i=s.firstBaseUpdate,c=s.lastBaseUpdate,o=s.shared.pending;if(o!==null){s.shared.pending=null;var d=o,j=d.next;d.next=null,c===null?i=j:c.next=j,c=d;var D=e.alternate;D!==null&&(D=D.updateQueue,o=D.lastBaseUpdate,o!==c&&(o===null?D.firstBaseUpdate=j:o.next=j,D.lastBaseUpdate=d))}if(i!==null){var q=s.baseState;c=0,D=j=d=null,o=i;do{var S=o.lane&-536870913,E=S!==o.lane;if(E?(_e&S)===S:(a&S)===S){S!==0&&S===Va&&(Su=!0),D!==null&&(D=D.next={lane:0,tag:o.tag,payload:o.payload,callback:null,next:null});e:{var oe=e,Se=o;S=t;var Qe=l;switch(Se.tag){case 1:if(oe=Se.payload,typeof oe=="function"){q=oe.call(Qe,q,S);break e}q=oe;break e;case 3:oe.flags=oe.flags&-65537|128;case 0:if(oe=Se.payload,S=typeof oe=="function"?oe.call(Qe,q,S):oe,S==null)break e;q=z({},q,S);break e;case 2:kl=!0}}S=o.callback,S!==null&&(e.flags|=64,E&&(e.flags|=8192),E=s.callbacks,E===null?s.callbacks=[S]:E.push(S))}else E={lane:S,tag:o.tag,payload:o.payload,callback:o.callback,next:null},D===null?(j=D=E,d=q):D=D.next=E,c|=S;if(o=o.next,o===null){if(o=s.shared.pending,o===null)break;E=o,o=E.next,E.next=null,s.lastBaseUpdate=E,s.shared.pending=null}}while(!0);D===null&&(d=q),s.baseState=d,s.firstBaseUpdate=j,s.lastBaseUpdate=D,i===null&&(s.shared.lanes=0),$l|=c,e.lanes=c,e.memoizedState=q}}function vr(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function yr(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ei?i:8;var c=N.T,o={};N.T=o,Lu(e,!1,t,l);try{var d=s(),j=N.S;if(j!==null&&j(o,d),d!==null&&typeof d=="object"&&typeof d.then=="function"){var D=Th(d,a);Gn(e,t,D,Lt(e))}else Gn(e,t,a,Lt(e))}catch(q){Gn(e,t,{then:function(){},status:"rejected",reason:q},Lt())}finally{k.p=i,c!==null&&o.types!==null&&(c.types=o.types),N.T=c}}function Dh(){}function Gu(e,t,l,a){if(e.tag!==5)throw Error(r(476));var s=$r(e).queue;Jr(e,s,t,H,l===null?Dh:function(){return Wr(e),l(a)})}function $r(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:H,baseState:H,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Nl,lastRenderedState:H},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Nl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Wr(e){var t=$r(e);t.next===null&&(t=e.alternate.memoizedState),Gn(e,t.next.queue,{},Lt())}function Yu(){return pt(ls)}function Fr(){return lt().memoizedState}function Ir(){return lt().memoizedState}function Uh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Lt();e=Ql(l);var a=Xl(t,e,l);a!==null&&(zt(a,t,l),Rn(a,t,l)),t={cache:pu()},e.payload=t;return}t=t.return}}function Rh(e,t,l){var a=Lt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},ks(e)?ed(t,l):(l=nu(e,t,l,a),l!==null&&(zt(l,e,a),td(l,t,a)))}function Pr(e,t,l){var a=Lt();Gn(e,t,l,a)}function Gn(e,t,l,a){var s={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(ks(e))ed(t,s);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var c=t.lastRenderedState,o=i(c,l);if(s.hasEagerState=!0,s.eagerState=o,wt(o,c))return Ss(e,t,s,0),Xe===null&&js(),!1}catch{}if(l=nu(e,t,s,a),l!==null)return zt(l,e,a),td(l,t,a),!0}return!1}function Lu(e,t,l,a){if(a={lane:2,revertLane:bc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},ks(e)){if(t)throw Error(r(479))}else t=nu(e,l,a,2),t!==null&&zt(t,e,2)}function ks(e){var t=e.alternate;return e===Te||t!==null&&t===Te}function ed(e,t){Ia=ws=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function td(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,so(e,l)}}var Yn={readContext:pt,use:qs,useCallback:Ie,useContext:Ie,useEffect:Ie,useImperativeHandle:Ie,useLayoutEffect:Ie,useInsertionEffect:Ie,useMemo:Ie,useReducer:Ie,useRef:Ie,useState:Ie,useDebugValue:Ie,useDeferredValue:Ie,useTransition:Ie,useSyncExternalStore:Ie,useId:Ie,useHostTransitionStatus:Ie,useFormState:Ie,useActionState:Ie,useOptimistic:Ie,useMemoCache:Ie,useCacheRefresh:Ie};Yn.useEffectEvent=Ie;var ld={readContext:pt,use:qs,useCallback:function(e,t){return xt().memoizedState=[e,t===void 0?null:t],e},useContext:pt,useEffect:Gr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Ys(4194308,4,Qr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Ys(4194308,4,e,t)},useInsertionEffect:function(e,t){Ys(4,2,e,t)},useMemo:function(e,t){var l=xt();t=t===void 0?null:t;var a=e();if(Sa){qe(!0);try{e()}finally{qe(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=xt();if(l!==void 0){var s=l(t);if(Sa){qe(!0);try{l(t)}finally{qe(!1)}}}else s=t;return a.memoizedState=a.baseState=s,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:s},a.queue=e,e=e.dispatch=Rh.bind(null,Te,e),[a.memoizedState,e]},useRef:function(e){var t=xt();return e={current:e},t.memoizedState=e},useState:function(e){e=Ru(e);var t=e.queue,l=Pr.bind(null,Te,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Bu,useDeferredValue:function(e,t){var l=xt();return qu(l,e,t)},useTransition:function(){var e=Ru(!1);return e=Jr.bind(null,Te,e.queue,!0,!1),xt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=Te,s=xt();if(Ue){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Xe===null)throw Error(r(349));(_e&127)!==0||Nr(a,t,l)}s.memoizedState=l;var i={value:l,getSnapshot:t};return s.queue=i,Gr(Cr.bind(null,a,i,e),[e]),a.flags|=2048,en(9,{destroy:void 0},Ar.bind(null,a,i,l,t),null),l},useId:function(){var e=xt(),t=Xe.identifierPrefix;if(Ue){var l=rl,a=ol;l=(a&~(1<<32-Ke(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Hs++,0<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?i.multiple=!0:a.size&&(i.size=a.size);break;default:i=typeof a.is=="string"?c.createElement(s,{is:a.is}):c.createElement(s)}}i[mt]=t,i[Nt]=a;e:for(c=t.child;c!==null;){if(c.tag===5||c.tag===6)i.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===t)break e;for(;c.sibling===null;){if(c.return===null||c.return===t)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}t.stateNode=i;e:switch(yt(i,s,a),s){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&Cl(t)}}return Ve(t),tc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Cl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=Ne.current,Ka(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,s=ht,s!==null)switch(s.tag){case 27:case 5:a=s.memoizedProps}e[mt]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||Sf(e.nodeValue,l)),e||Yl(t,!0)}else e=ci(e).createTextNode(a),e[mt]=t,t.stateNode=e}return Ve(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=Ka(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[mt]=t}else pa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ve(t),e=!1}else l=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(qt(t),t):(qt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Ve(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(s=Ka(t),a!==null&&a.dehydrated!==null){if(e===null){if(!s)throw Error(r(318));if(s=t.memoizedState,s=s!==null?s.dehydrated:null,!s)throw Error(r(317));s[mt]=t}else pa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ve(t),s=!1}else s=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=s),s=!0;if(!s)return t.flags&256?(qt(t),t):(qt(t),null)}return qt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,s=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(s=a.alternate.memoizedState.cachePool.pool),i=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(i=a.memoizedState.cachePool.pool),i!==s&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Vs(t,t.updateQueue),Ve(t),null);case 4:return ce(),e===null&&Nc(t.stateNode.containerInfo),Ve(t),null;case 10:return jl(t.type),Ve(t),null;case 19:if(h(tt),a=t.memoizedState,a===null)return Ve(t),null;if(s=(t.flags&128)!==0,i=a.rendering,i===null)if(s)kn(a,!1);else{if(Pe!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(i=Rs(e),i!==null){for(t.flags|=128,kn(a,!1),e=i.updateQueue,t.updateQueue=e,Vs(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Po(l,e),l=l.sibling;return M(tt,tt.current&1|2),Ue&&bl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&et()>Is&&(t.flags|=128,s=!0,kn(a,!1),t.lanes=4194304)}else{if(!s)if(e=Rs(i),e!==null){if(t.flags|=128,s=!0,e=e.updateQueue,t.updateQueue=e,Vs(t,e),kn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!Ue)return Ve(t),null}else 2*et()-a.renderingStartTime>Is&&l!==536870912&&(t.flags|=128,s=!0,kn(a,!1),t.lanes=4194304);a.isBackwards?(i.sibling=t.child,t.child=i):(e=a.last,e!==null?e.sibling=i:t.child=i,a.last=i)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=et(),e.sibling=null,l=tt.current,M(tt,s?l&1|2:l&1),Ue&&bl(t,a.treeForkCount),e):(Ve(t),null);case 22:case 23:return qt(t),Au(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Ve(t),t.subtreeFlags&6&&(t.flags|=8192)):Ve(t),l=t.updateQueue,l!==null&&Vs(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&h(ga),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),jl(st),Ve(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Gh(e,t){switch(ou(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return jl(st),ce(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return F(t),null;case 31:if(t.memoizedState!==null){if(qt(t),t.alternate===null)throw Error(r(340));pa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(qt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));pa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return h(tt),null;case 4:return ce(),null;case 10:return jl(t.type),null;case 22:case 23:return qt(t),Au(),e!==null&&h(ga),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return jl(st),null;case 25:return null;default:return null}}function Td(e,t){switch(ou(t),t.tag){case 3:jl(st),ce();break;case 26:case 27:case 5:F(t);break;case 4:ce();break;case 31:t.memoizedState!==null&&qt(t);break;case 13:qt(t);break;case 19:h(tt);break;case 10:jl(t.type);break;case 22:case 23:qt(t),Au(),e!==null&&h(ga);break;case 24:jl(st)}}function Qn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var s=a.next;l=s;do{if((l.tag&e)===e){a=void 0;var i=l.create,c=l.inst;a=i(),c.destroy=a}l=l.next}while(l!==s)}}catch(o){Ye(t,t.return,o)}}function Vl(e,t,l){try{var a=t.updateQueue,s=a!==null?a.lastEffect:null;if(s!==null){var i=s.next;a=i;do{if((a.tag&e)===e){var c=a.inst,o=c.destroy;if(o!==void 0){c.destroy=void 0,s=t;var d=l,j=o;try{j()}catch(D){Ye(s,d,D)}}}a=a.next}while(a!==i)}}catch(D){Ye(t,t.return,D)}}function Ed(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{yr(t,l)}catch(a){Ye(e,e.return,a)}}}function Md(e,t,l){l.props=Na(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){Ye(e,t,a)}}function Xn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(s){Ye(e,t,s)}}function dl(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(s){Ye(e,t,s)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(s){Ye(e,t,s)}else l.current=null}function zd(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(s){Ye(e,e.return,s)}}function lc(e,t,l){try{var a=e.stateNode;u0(a,e.type,l,t),a[Nt]=t}catch(s){Ye(e,e.return,s)}}function Od(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&ea(e.type)||e.tag===4}function ac(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Od(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&ea(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function nc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=vl));else if(a!==4&&(a===27&&ea(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(nc(e,t,l),e=e.sibling;e!==null;)nc(e,t,l),e=e.sibling}function Js(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&ea(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Js(e,t,l),e=e.sibling;e!==null;)Js(e,t,l),e=e.sibling}function _d(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,s=t.attributes;s.length;)t.removeAttributeNode(s[0]);yt(t,a,l),t[mt]=e,t[Nt]=l}catch(i){Ye(e,e.return,i)}}var Tl=!1,ct=!1,sc=!1,Dd=typeof WeakSet=="function"?WeakSet:Set,ft=null;function Yh(e,t){if(e=e.containerInfo,Tc=pi,e=Xo(e),Ii(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var s=a.anchorOffset,i=a.focusNode;a=a.focusOffset;try{l.nodeType,i.nodeType}catch{l=null;break e}var c=0,o=-1,d=-1,j=0,D=0,q=e,S=null;t:for(;;){for(var E;q!==l||s!==0&&q.nodeType!==3||(o=c+s),q!==i||a!==0&&q.nodeType!==3||(d=c+a),q.nodeType===3&&(c+=q.nodeValue.length),(E=q.firstChild)!==null;)S=q,q=E;for(;;){if(q===e)break t;if(S===l&&++j===s&&(o=c),S===i&&++D===a&&(d=c),(E=q.nextSibling)!==null)break;q=S,S=q.parentNode}q=E}l=o===-1||d===-1?null:{start:o,end:d}}else l=null}l=l||{start:0,end:0}}else l=null;for(Ec={focusedElem:e,selectionRange:l},pi=!1,ft=t;ft!==null;)if(t=ft,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ft=e;else for(;ft!==null;){switch(t=ft,i=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),yt(i,a,l),i[mt]=e,dt(i),a=i;break e;case"link":var c=Gf("link","href",s).get(a+(l.href||""));if(c){for(var o=0;oQe&&(c=Qe,Qe=Se,Se=c);var y=ko(o,Se),v=ko(o,Qe);if(y&&v&&(E.rangeCount!==1||E.anchorNode!==y.node||E.anchorOffset!==y.offset||E.focusNode!==v.node||E.focusOffset!==v.offset)){var x=q.createRange();x.setStart(y.node,y.offset),E.removeAllRanges(),Se>Qe?(E.addRange(x),E.extend(v.node,v.offset)):(x.setEnd(v.node,v.offset),E.addRange(x))}}}}for(q=[],E=o;E=E.parentNode;)E.nodeType===1&&q.push({element:E,left:E.scrollLeft,top:E.scrollTop});for(typeof o.focus=="function"&&o.focus(),o=0;ol?32:l,N.T=null,l=fc,fc=null;var i=Fl,c=_l;if(ot=0,sn=Fl=null,_l=0,(He&6)!==0)throw Error(r(331));var o=He;if(He|=4,Qd(i.current),Yd(i,i.current,c,l),He=o,Wn(0,!1),ge&&typeof ge.onPostCommitFiberRoot=="function")try{ge.onPostCommitFiberRoot(I,i)}catch{}return!0}finally{k.p=s,N.T=a,cf(e,t)}}function rf(e,t,l){t=Zt(l,t),t=Ku(e.stateNode,t,2),e=Xl(e,t,2),e!==null&&(vn(e,2),fl(e))}function Ye(e,t,l){if(e.tag===3)rf(e,e,l);else for(;t!==null;){if(t.tag===3){rf(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Wl===null||!Wl.has(a))){e=Zt(l,e),l=rd(2),a=Xl(t,l,2),a!==null&&(dd(l,a,t,e),vn(a,2),fl(a));break}}t=t.return}}function vc(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Qh;var s=new Set;a.set(t,s)}else s=a.get(t),s===void 0&&(s=new Set,a.set(t,s));s.has(l)||(cc=!0,s.add(l),e=Jh.bind(null,e,t,l),t.then(e,e))}function Jh(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Xe===e&&(_e&l)===l&&(Pe===4||Pe===3&&(_e&62914560)===_e&&300>et()-Fs?(He&2)===0&&un(e,0):oc|=l,nn===_e&&(nn=0)),fl(e)}function df(e,t){t===0&&(t=ao()),e=ma(e,t),e!==null&&(vn(e,t),fl(e))}function $h(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),df(e,l)}function Wh(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,s=e.memoizedState;s!==null&&(l=s.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),df(e,l)}function Fh(e,t){return B(e,t)}var ni=null,on=null,yc=!1,si=!1,gc=!1,Pl=0;function fl(e){e!==on&&e.next===null&&(on===null?ni=on=e:on=on.next=e),si=!0,yc||(yc=!0,Ph())}function Wn(e,t){if(!gc&&si){gc=!0;do for(var l=!1,a=ni;a!==null;){if(e!==0){var s=a.pendingLanes;if(s===0)var i=0;else{var c=a.suspendedLanes,o=a.pingedLanes;i=(1<<31-Ke(42|e)+1)-1,i&=s&~(c&~o),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(l=!0,pf(a,i))}else i=_e,i=os(a,a===Xe?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||pn(a,i)||(l=!0,pf(a,i));a=a.next}while(l);gc=!1}}function Ih(){ff()}function ff(){si=yc=!1;var e=0;Pl!==0&&o0()&&(e=Pl);for(var t=et(),l=null,a=ni;a!==null;){var s=a.next,i=mf(a,t);i===0?(a.next=null,l===null?ni=s:l.next=s,s===null&&(on=l)):(l=a,(e!==0||(i&3)!==0)&&(si=!0)),a=s}ot!==0&&ot!==5||Wn(e),Pl!==0&&(Pl=0)}function mf(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,s=e.expirationTimes,i=e.pendingLanes&-62914561;0o)break;var D=d.transferSize,q=d.initiatorType;D&&Nf(q)&&(d=d.responseEnd,c+=D*(d"u"?null:document;function wf(e,t,l){var a=rn;if(a&&typeof t=="string"&&t){var s=Xt(t);s='link[rel="'+e+'"][href="'+s+'"]',typeof l=="string"&&(s+='[crossorigin="'+l+'"]'),Rf.has(s)||(Rf.add(s),e={rel:e,crossOrigin:l,href:t},a.querySelector(s)===null&&(t=a.createElement("link"),yt(t,"link",e),dt(t),a.head.appendChild(t)))}}function g0(e){Dl.D(e),wf("dns-prefetch",e,null)}function b0(e,t){Dl.C(e,t),wf("preconnect",e,t)}function x0(e,t,l){Dl.L(e,t,l);var a=rn;if(a&&e&&t){var s='link[rel="preload"][as="'+Xt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(s+='[imagesrcset="'+Xt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(s+='[imagesizes="'+Xt(l.imageSizes)+'"]')):s+='[href="'+Xt(e)+'"]';var i=s;switch(t){case"style":i=dn(e);break;case"script":i=fn(e)}It.has(i)||(e=z({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),It.set(i,e),a.querySelector(s)!==null||t==="style"&&a.querySelector(es(i))||t==="script"&&a.querySelector(ts(i))||(t=a.createElement("link"),yt(t,"link",e),dt(t),a.head.appendChild(t)))}}function j0(e,t){Dl.m(e,t);var l=rn;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",s='link[rel="modulepreload"][as="'+Xt(a)+'"][href="'+Xt(e)+'"]',i=s;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=fn(e)}if(!It.has(i)&&(e=z({rel:"modulepreload",href:e},t),It.set(i,e),l.querySelector(s)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(ts(i)))return}a=l.createElement("link"),yt(a,"link",e),dt(a),l.head.appendChild(a)}}}function S0(e,t,l){Dl.S(e,t,l);var a=rn;if(a&&e){var s=Da(a).hoistableStyles,i=dn(e);t=t||"default";var c=s.get(i);if(!c){var o={loading:0,preload:null};if(c=a.querySelector(es(i)))o.loading=5;else{e=z({rel:"stylesheet",href:e,"data-precedence":t},l),(l=It.get(i))&&Rc(e,l);var d=c=a.createElement("link");dt(d),yt(d,"link",e),d._p=new Promise(function(j,D){d.onload=j,d.onerror=D}),d.addEventListener("load",function(){o.loading|=1}),d.addEventListener("error",function(){o.loading|=2}),o.loading|=4,ri(c,t,a)}c={type:"stylesheet",instance:c,count:1,state:o},s.set(i,c)}}}function N0(e,t){Dl.X(e,t);var l=rn;if(l&&e){var a=Da(l).hoistableScripts,s=fn(e),i=a.get(s);i||(i=l.querySelector(ts(s)),i||(e=z({src:e,async:!0},t),(t=It.get(s))&&wc(e,t),i=l.createElement("script"),dt(i),yt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(s,i))}}function A0(e,t){Dl.M(e,t);var l=rn;if(l&&e){var a=Da(l).hoistableScripts,s=fn(e),i=a.get(s);i||(i=l.querySelector(ts(s)),i||(e=z({src:e,async:!0,type:"module"},t),(t=It.get(s))&&wc(e,t),i=l.createElement("script"),dt(i),yt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(s,i))}}function Hf(e,t,l,a){var s=(s=Ne.current)?oi(s):null;if(!s)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=dn(l.href),l=Da(s).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=dn(l.href);var i=Da(s).hoistableStyles,c=i.get(e);if(c||(s=s.ownerDocument||s,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},i.set(e,c),(i=s.querySelector(es(e)))&&!i._p&&(c.instance=i,c.state.loading=5),It.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},It.set(e,l),i||C0(s,e,l,c.state))),t&&a===null)throw Error(r(528,""));return c}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=fn(l),l=Da(s).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function dn(e){return'href="'+Xt(e)+'"'}function es(e){return'link[rel="stylesheet"]['+e+"]"}function Bf(e){return z({},e,{"data-precedence":e.precedence,precedence:null})}function C0(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),yt(t,"link",l),dt(t),e.head.appendChild(t))}function fn(e){return'[src="'+Xt(e)+'"]'}function ts(e){return"script[async]"+e}function qf(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Xt(l.href)+'"]');if(a)return t.instance=a,dt(a),a;var s=z({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),dt(a),yt(a,"style",s),ri(a,l.precedence,e),t.instance=a;case"stylesheet":s=dn(l.href);var i=e.querySelector(es(s));if(i)return t.state.loading|=4,t.instance=i,dt(i),i;a=Bf(l),(s=It.get(s))&&Rc(a,s),i=(e.ownerDocument||e).createElement("link"),dt(i);var c=i;return c._p=new Promise(function(o,d){c.onload=o,c.onerror=d}),yt(i,"link",a),t.state.loading|=4,ri(i,l.precedence,e),t.instance=i;case"script":return i=fn(l.src),(s=e.querySelector(ts(i)))?(t.instance=s,dt(s),s):(a=l,(s=It.get(i))&&(a=z({},l),wc(a,s)),e=e.ownerDocument||e,s=e.createElement("script"),dt(s),yt(s,"link",a),e.head.appendChild(s),t.instance=s);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,ri(a,l.precedence,e));return t.instance}function ri(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),s=a.length?a[a.length-1]:null,i=s,c=0;c title"):null)}function T0(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Lf(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function E0(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var s=dn(a.href),i=t.querySelector(es(s));if(i){t=i._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=fi.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=i,dt(i);return}i=t.ownerDocument||t,a=Bf(a),(s=It.get(s))&&Rc(a,s),i=i.createElement("link"),dt(i);var c=i;c._p=new Promise(function(o,d){c.onload=o,c.onerror=d}),yt(i,"link",a),l.instance=i}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=fi.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Hc=0;function M0(e,t){return e.stylesheets&&e.count===0&&hi(e,e.stylesheets),0Hc?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(s)}}:null}function fi(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)hi(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var mi=null;function hi(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,mi=new Map,t.forEach(z0,e),mi=null,fi.call(e))}function z0(e,t){if(!(t.state.loading&4)){var l=mi.get(e);if(l)var a=l.get(null);else{l=new Map,mi.set(e,l);for(var s=e.querySelectorAll("link[data-precedence],style[data-precedence]"),i=0;i"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(u)}catch(f){console.error(f)}}return u(),Kc.exports=V0(),Kc.exports}var $0=J0();function je(u){return Array.isArray(u)?u:[]}function ym(u){const f=new Set;return u.map(p=>p.trim()).filter(p=>{const r=p.toLowerCase();return!p||f.has(r)?!1:(f.add(r),!0)})}function il(u){const f=Ni.some(p=>p.value===u.streamMode)?u.streamMode:"auto";return{...u,streamMode:f,models:je(u.models),allowedGroupIds:je(u.allowedGroupIds),openaiAccounts:je(u.openaiAccounts),kiroAccounts:je(u.kiroAccounts)}}function cs(u){return{...u,aliases:je(u.aliases)}}function W0(u){return{...u,apiKeys:je(u.apiKeys),logs:je(u.logs)}}class Ci extends Error{status;payload;constructor(f,p,r){super(p),this.status=f,this.payload=r}}const F0={home:"M3 10.5 12 3l9 7.5V21a1 1 0 0 1-1 1h-5v-7H9v7H4a1 1 0 0 1-1-1z",users:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75",key:"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78ZM14 8l7-7M21 8h-5V3",models:"M12 2 4 6v12l8 4 8-4V6zM4 6l8 4 8-4M12 10v12",image:"M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2ZM8.5 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM21 16l-5-5L5 21",route:"M4 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM20 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM7 16h3a4 4 0 0 0 4-4V8h3",logs:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6M8 13h8M8 17h6",orbit:"M12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10ZM3 12a9 3 0 1 0 18 0 9 3 0 1 0-18 0Z",settings:"M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 8.92 4a1.65 1.65 0 0 0 1-1.51V2a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.31.39.57.71.71.23.1.49.18.8.2H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z",search:"M21 21l-4.35-4.35M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z",copy:"M8 8h11a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1ZM4 16H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v1",ban:"M4.93 4.93 19.07 19.07M22 12A10 10 0 1 1 2 12a10 10 0 0 1 20 0Z",check:"M20 6 9 17l-5-5",moon:"M21 12.8A8.5 8.5 0 1 1 11.2 3 6.5 6.5 0 0 0 21 12.8Z",sun:"M12 4V2M12 22v-2M4.93 4.93 3.52 3.52M20.48 20.48l-1.41-1.41M4 12H2M22 12h-2M4.93 19.07l-1.41 1.41M20.48 3.52l-1.41 1.41M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z",plus:"M12 5v14M5 12h14"};function Ot({name:u}){return n.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",className:"icon",children:n.jsx("path",{d:F0[u]})})}async function ve(u,f){const p=new Headers(f?.headers);p.set("Content-Type","application/json");const r=window.sessionStorage.getItem("capi-admin-token");r&&p.set("Authorization",`Bearer ${r}`);const A=await fetch(u,{credentials:"include",...f,headers:p});if(!A.ok){const T=await A.json().catch(()=>null);throw new Ci(A.status,T?.error?.message||`Request failed: ${A.status}`,T)}return A.json()}async function I0(u,f){const p=new Headers,r=window.sessionStorage.getItem("capi-admin-token");r&&p.set("Authorization",`Bearer ${r}`);const A=await fetch(u,{credentials:"include",method:"POST",headers:p,body:f});if(!A.ok){const T=await A.json().catch(()=>null);throw new Ci(A.status,T?.error?.message||`Request failed: ${A.status}`,T)}return A.json()}const dm=[{id:"overview",label:"概览",icon:"home"},{id:"users",label:"用户",icon:"users"},{id:"groups",label:"分组",icon:"users"},{id:"keys",label:"密钥",icon:"key"},{id:"models",label:"模型",icon:"models"},{id:"drawing",label:"绘图",icon:"image"},{id:"antigravity",label:"Antigravity",icon:"orbit"},{id:"channels",label:"渠道",icon:"route"},{id:"logs",label:"日志",icon:"logs"},{id:"settings",label:"设置",icon:"settings"}],to=[{value:"kiro",label:"Kiro / Amazon Q"},{value:"codex",label:"Codex / ChatGPT OAuth"},{value:"antigravity",label:"Antigravity / Google"},{value:"cpa",label:"CPA / CLIProxyAPI"},{value:"openai",label:"OpenAI"},{value:"anthropic",label:"Anthropic / Claude"},{value:"google",label:"Google Gemini"},{value:"deepseek",label:"DeepSeek"},{value:"openrouter",label:"OpenRouter"},{value:"groq",label:"Groq"},{value:"siliconflow",label:"SiliconFlow"},{value:"moonshot",label:"Moonshot"},{value:"compatible",label:"OpenAI 兼容接口"}],gm="https://api.openai.com/v1",Ti="https://chatgpt.com/backend-api",bm="http://localhost:8317/v1",xm="https://codewhisperer.us-east-1.amazonaws.com",jm="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2, gpt-image-1",P0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2",ep="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, claude-sonnet-4, gemini-3.1-pro",tp="claude-sonnet-4.5, claude-sonnet-4, claude-haiku-4.5, claude-opus-4.5",Sm="https://daily-cloudcode-pa.googleapis.com",lp="claude-opus-4-6-thinking, claude-sonnet-4-6, gemini-3.8-flash-high, gemini-3.7-flash-high, gemini-3.6-flash-high, gemini-3-flash, gemini-pro-agent, gemini-3.1-pro-low, gpt-oss-120b-medium, gemini-3.1-flash-lite, gemini-3.5-flash-lite, gemini-3.1-flash-image",Fc=[{provider:"kiro",label:"Kiro / Amazon Q",name:"Kiro 账号池",baseUrl:xm,models:tp.split(",").map(u=>u.trim())},{provider:"openai",label:"OpenAI",name:"OpenAI 主线路",baseUrl:gm,models:P0.split(",").map(u=>u.trim())},{provider:"codex",label:"Codex 账号池",name:"Codex 账号池",baseUrl:Ti,models:jm.split(",").map(u=>u.trim())},{provider:"antigravity",label:"Antigravity 账号池",name:"Antigravity 账号池",baseUrl:Sm,models:lp.split(",").map(u=>u.trim())},{provider:"cpa",label:"CPA / CLIProxyAPI",name:"CPA 本地代理",baseUrl:bm,models:ep.split(",").map(u=>u.trim())},{provider:"compatible",label:"OpenAI 兼容接口",name:"兼容渠道",baseUrl:"",models:[]},{provider:"openrouter",label:"OpenRouter",name:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",models:[]},{provider:"google",label:"Google Gemini",name:"Gemini",baseUrl:"",models:[]},{provider:"anthropic",label:"Anthropic / Claude",name:"Claude",baseUrl:"",models:[]}];function Ta(u){return Fc.find(f=>f.provider===u)||Fc[2]}function Ic(u){const f=Ta(u);return{name:f.name,provider:f.provider,baseUrl:f.baseUrl,models:[...f.models],streamMode:"auto"}}function ap(u){const f=u?.trim().toLowerCase();return f&&({free:"Free",plus:"Plus",pro:"Pro",team:"Team",enterprise:"Enterprise"}[f]||u)||"套餐未知"}function fm(u){return u?{upstream_token_invalidated:"Token 已失效",upstream_invalid_api_key:"API Key 无效",upstream_account_error:"账号错误",upstream_accounts_unavailable:"账号池不可用",upstream_error:"上游错误"}[u]||u:""}function Ei(u){return u==="openai"?gm:u==="codex"?Ti:u==="antigravity"?Sm:u==="cpa"||u==="cliproxyapi"?bm:u==="kiro"?xm:""}function Pc(u){return ym(u.split(/[\s,;,;]+/))}function np(u){return ym(u.split(/[\n,;,;]+/).map(f=>f.trim()))}function Nm(u){const f=np(u);return f.length===0?{}:f.length===1?{upstreamApiKey:f[0]}:{upstreamApiKeys:f}}const Ni=[{value:"auto",label:"自动",description:"按请求参数处理"},{value:"real",label:"真流",description:"直连上游 SSE"},{value:"fake",label:"假流",description:"非流转 SSE"},{value:"disabled",label:"禁用流",description:"流式请求跳过"}];function el(u){if(!u)return"未使用";const f=new Date(u);return Number.isNaN(f.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(f)}function mm(u){if(!u)return"";const f=new Date(u);if(Number.isNaN(f.getTime()))return"";const p=f.getTimezoneOffset()*6e4;return new Date(f.getTime()-p).toISOString().slice(0,16)}function sp(u){if(!u)return"";const f=new Date(u);return Number.isNaN(f.getTime())?"":f.toISOString()}function ip(u){if(!u)return"-";const f=new Date(u);return Number.isNaN(f.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).format(f)}function _t(u){return{active:"正常",disabled:"禁用",limited:"受限",overdue:"欠费",healthy:"正常",standby:"备用",available:"Available",success:"成功",failed:"失败"}[u]||u}function jt(u,f=2){const p=Number(u||0);return new Intl.NumberFormat("zh-CN",{minimumFractionDigits:f,maximumFractionDigits:f}).format(p)}function ml(u){return new Intl.NumberFormat("zh-CN").format(Math.max(0,Math.round(Number(u||0))))}function lo(u){return u.model?u.model:u.errorCode==="invalid_api_key"?"密钥无效":u.errorCode==="model_not_available"?"模型不可用":u.errorCode==="insufficient_quota"?"额度不足":u.errorCode==="rate_limit_exceeded"?"请求过快":u.errorCode||"请求失败"}function up(u){return u.model||(u.errorCode?`错误:${u.errorCode}`:"-")}function cp(u){return u.channel||(u.apiKeyPrefix?`Key ${u.apiKeyPrefix}`:"-")}function op(u){const f=je(u);if(f.length===0)return"未绑定模型";const p=f.slice(0,2).join(", ");return f.length>2?`${p} · 其余 ${f.length-2} 个`:p}function ul(u){return u==="cliproxyapi"||u==="cli-proxy-api"?"CPA / CLIProxyAPI":to.find(f=>f.value===u)?.label||u||"Custom"}function $c(u){const f=`${u.vendor} ${u.id} ${u.name}`.toLowerCase();return f.includes("cliproxyapi")||/\bcpa\b/.test(f)?"cpa":f.includes("openai")||/\bgpt[-_/]/.test(f)||f.includes("o1-")||f.includes("o3-")?"openai":f.includes("anthropic")||f.includes("claude")?"anthropic":f.includes("google")||f.includes("gemini")||f.includes("gcli-")?"google":f.includes("deepseek")?"deepseek":f.includes("openrouter")?"openrouter":f.includes("groq")?"groq":f.includes("siliconflow")?"siliconflow":f.includes("moonshot")||f.includes("kimi")?"moonshot":u.vendor&&u.vendor.toLowerCase()!=="custom"?u.vendor.toLowerCase():"compatible"}function hm({provider:u}){if(u==="deepseek")return n.jsx("span",{className:"provider-icon provider-icon-deepseek","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("path",{transform:"translate(2.4 4.4)",d:"M26.517 3.395c-.282-.138-.403.125-.568.258-.057.044-.105.1-.152.152-.413.44-.895.73-1.524.695-.92-.052-1.705.237-2.4.941-.147-.868-.638-1.386-1.384-1.718-.39-.173-.786-.346-1.06-.721-.19-.268-.243-.566-.338-.86-.061-.176-.121-.357-.325-.388-.222-.034-.309.151-.396.307-.347.635-.481 1.334-.468 2.042.03 1.594.703 2.863 2.04 3.765.152.104.191.207.143.359-.091.31-.2.613-.295.924-.06.198-.151.242-.364.155-.734-.306-1.367-.76-1.927-1.308-.951-.92-1.81-1.934-2.882-2.729-.252-.185-.504-.358-.764-.522-1.094-1.062.143-1.935.43-2.038.3-.108.104-.48-.864-.475-.968.004-1.853.328-2.982.76-.165.065-.339.112-.516.151-1.024-.194-2.088-.237-3.199-.112-2.092.233-3.763 1.222-4.991 2.91C.254 7.972-.093 10.278.332 12.682c.446 2.535 1.74 4.633 3.728 6.274 2.062 1.7 4.436 2.534 7.145 2.375 1.645-.095 3.476-.316 5.542-2.064.521.259 1.068.363 1.975.44.699.065 1.371-.034 1.892-.142.816-.173.76-.929.465-1.067-2.392-1.114-1.866-.661-2.344-1.027 1.215-1.438 3.071-3.993 3.644-7.473.056-.384.128-.925.12-1.236-.005-.19.038-.263.255-.285.6-.069 1.18-.233 1.715-.527 1.55-.846 2.175-2.237 2.322-3.903.022-.255-.005-.518-.274-.652ZM13.014 18.395c-2.318-1.823-3.442-2.423-3.906-2.397-.434.026-.356.523-.26.847.1.32.23.54.412.82.126.186.213.462-.126.67-.746.461-2.044-.156-2.105-.186-1.51-.89-2.773-2.064-3.664-3.67-.86-1.545-1.358-3.204-1.44-4.974-.022-.427.104-.578.529-.656.56-.103 1.137-.125 1.697-.043 2.366.346 4.379 1.403 6.068 3.079.963.954 1.692 2.094 2.443 3.208.799 1.183 1.658 2.31 2.752 3.234.387.324.695.57.99.751-.89.1-2.374.121-3.39-.683Zm1.111-7.146c0-.19.152-.341.343-.341.043 0 .082.009.117.021.048.018.092.044.126.083.061.06.096.146.096.237a.341.341 0 0 1-.343.341.34.34 0 0 1-.339-.341Zm3.451 1.77c-.222.09-.443.168-.656.177-.33.017-.69-.117-.885-.281-.304-.255-.521-.397-.612-.842-.039-.19-.017-.483.017-.652.078-.362-.009-.595-.265-.807-.208-.172-.473-.22-.764-.22-.108 0-.208-.048-.282-.086-.121-.061-.221-.212-.126-.398.031-.06.178-.207.213-.233.395-.225.85-.151 1.272.018.39.16.686.453 1.111.867.434.501.512.639.759 1.015.196.294.373.596.495.942.073.215-.022.392-.277.5Z"})]})});if(u==="openai")return n.jsx("span",{className:"provider-icon provider-icon-openai","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("g",{transform:"translate(7 7.5) scale(0.065)",fill:"currentColor",stroke:"none",children:n.jsx("path",{d:"M267.06 111.34a71.78 71.78 0 0 0-6.17-58.91c-14.5-25.15-43.55-38.09-71.9-32.03A71.78 71.78 0 0 0 135.1.5C106 .43 80.21 19.16 71.29 46.85a71.79 71.79 0 0 0-47.98 34.8c-14.6 25.1-11.28 56.75 8.22 78.3a71.78 71.78 0 0 0 6.16 58.9c14.5 25.16 43.56 38.1 71.91 32.04a71.76 71.76 0 0 0 53.89 24.02c29.12.02 54.92-18.72 63.84-46.44a71.79 71.79 0 0 0 47.98-34.8c14.58-25.1 11.25-56.72-8.24-78.27zm-107.9 150.77a53.15 53.15 0 0 1-34.15-12.35c.43-.24 1.2-.66 1.7-.96l56.68-32.73a9.22 9.22 0 0 0 4.66-8.06v-79.9l23.95 13.83a.85.85 0 0 1 .47.66v66.16a53.42 53.42 0 0 1-53.3 53.35zM44.6 213.16a53.13 53.13 0 0 1-6.36-35.75c.42.25 1.15.7 1.68 1l56.68 32.73a9.24 9.24 0 0 0 9.31 0l69.2-39.95v27.66a.87.87 0 0 1-.34.74l-57.29 33.07a53.42 53.42 0 0 1-72.88-19.5zM29.7 90.05a53.1 53.1 0 0 1 27.76-23.36c0 .49-.03 1.36-.03 1.96v65.46a9.22 9.22 0 0 0 4.65 8.05l69.2 39.95-23.95 13.83a.86.86 0 0 1-.81.07L49.2 162.9A53.42 53.42 0 0 1 29.7 90.05zm196.8 45.8L157.3 95.9l23.95-13.82a.86.86 0 0 1 .81-.07l57.3 33.08a53.37 53.37 0 0 1-8.24 96.29v-65.46a9.2 9.2 0 0 0-4.62-8.06zm23.84-35.89c-.42-.26-1.15-.7-1.68-1.01l-56.68-32.73a9.25 9.25 0 0 0-9.31 0l-69.2 39.95V78.5a.87.87 0 0 1 .35-.74l57.28-33.05a53.35 53.35 0 0 1 79.24 55.25zM100.11 149.24l-23.96-13.83a.85.85 0 0 1-.46-.66V68.6a53.37 53.37 0 0 1 87.52-40.95c-.42.24-1.19.66-1.7.96l-56.68 32.73a9.22 9.22 0 0 0-4.66 8.06l-.04 79.85zm13.01-28.05L144 103.3l30.88 17.83v35.68L144 174.63l-30.88-17.82v-35.62z"})})]})});const f=u==="codex"?"C":u==="antigravity"?"G":u==="cpa"||u==="cliproxyapi"?"CPA":u==="anthropic"?"A":u==="google"?"✦":u==="openrouter"?"↗":u==="groq"?"G":u==="siliconflow"?"S":u==="moonshot"?"M":"◇";return n.jsx("span",{className:`provider-icon provider-icon-${u}`,"aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("text",{x:"16",y:"21",textAnchor:"middle",children:f})]})})}async function Ai(u){if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(u);return}const f=document.createElement("textarea");f.value=u,f.setAttribute("readonly","true"),f.style.position="fixed",f.style.opacity="0",document.body.appendChild(f),f.select(),document.execCommand("copy"),document.body.removeChild(f)}function Ul(){return window.location.origin}function rp(){return`${Ul()}/api/auth/discord/callback`}function dp(){return`${Ul()}/`}function Wc(u){return{...u,redirectUri:u.redirectUri&&!u.redirectUri.includes("localhost")?u.redirectUri:rp(),authSuccessUrl:u.authSuccessUrl&&!u.authSuccessUrl.includes("localhost")?u.authSuccessUrl:dp(),blockedGuildIds:je(u.blockedGuildIds),sessionTtlHours:u.sessionTtlHours||168}}function Mi(u){return u==="email"||u==="discord"?u:"username"}function fp(u){const p=(u.split("@")[0]||"user").toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^[-_]+|[-_]+$/g,"");return(p.length>=3?p:"user").slice(0,24)}function mp(){const[u,f]=b.useState("home"),[p,r]=b.useState("login"),[A,T]=b.useState(null),[L,$]=b.useState("overview"),[C,g]=b.useState(()=>{const R=window.localStorage.getItem("capi-theme");return R==="light"||R==="dark"?R:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}),[G,z]=b.useState("comfortable"),[V,W]=b.useState(null),[fe,te]=b.useState([]),[ae,ie]=b.useState([]),[be,Y]=b.useState([]),[xe,P]=b.useState([]),[he,_]=b.useState([]),[ne,me]=b.useState(""),[Ce,Me]=b.useState(""),[ue,K]=b.useState(null),[de,J]=b.useState(""),[N,k]=b.useState(""),[H,X]=b.useState(!1),se=b.useMemo(()=>{const R=ne.trim().toLowerCase();return R?fe.filter(Z=>`${Z.id} ${Z.name} ${Z.email}`.toLowerCase().includes(R)):fe},[ne,fe]);async function m(){const R=new Date().getTimezoneOffset(),[Z,le,I,ge,qe,Ke]=await Promise.all([ve(`/api/overview?timezoneOffset=${R}`),ve("/api/users"),ve("/api/channels"),ve("/api/models"),ve("/api/logs"),ve("/api/groups")]),Rt=je(le.users),Rl=je(I.channels).map(il),ca=je(ge.models).map(cs),Ea=je(qe.logs),Ma=je(Ke.groups);W(Z),te(Rt),ie(Rl),Y(Ma),P(ca),_(Ea),Me(wl=>wl&&Rt.some(hl=>hl.id===wl)?wl:Rt[0]?.id||""),Rt.length===0&&K(null),X(!0)}async function h(R){const Z=await ve(`/api/users/${R}`);K(W0(Z))}async function M(R,Z){const le=await ve(`/api/users/${R}`,{method:"PATCH",body:JSON.stringify(Z)});te(I=>I.map(ge=>ge.id===R?le.user:ge)),K(I=>I?.user.id===R?{...I,user:le.user}:I),J("已更新用户"),window.setTimeout(()=>J(""),1800)}async function Q(R,Z,le={}){const I=await ve("/api/users/bulk",{method:"POST",body:JSON.stringify({userIds:R,action:Z,...le})}),ge=new Map(je(I.users).map(qe=>[qe.id,qe]));te(qe=>qe.map(Ke=>ge.get(Ke.id)||Ke)),K(qe=>{if(!qe)return qe;const Ke=ge.get(qe.user.id);return Ke?{...qe,user:Ke}:qe}),J(`已处理 ${I.updated} 个用户`),window.setTimeout(()=>J(""),1800)}async function ee(R){const Z=await ve(`/api/users/${R}/api-keys`,{method:"POST",body:JSON.stringify({name:"Console Key"})});ue?.user.id===R&&K({...ue,apiKeys:[...ue.apiKeys,Z.apiKey]}),k(Z.secret),await Ai(Z.secret),J("新 Key 已创建并复制,请立即保存"),window.setTimeout(()=>J(""),2400)}async function Ne(R){window.confirm("删除这个 Key?删除后使用它的请求会立即失效。")&&(await ve(`/api/api-keys/${R}`,{method:"DELETE"}),K(Z=>Z&&{...Z,apiKeys:Z.apiKeys.filter(le=>le.id!==R)}),J("Key 已删除"),window.setTimeout(()=>J(""),1800))}async function O(R,Z){const le=await ve(`/api/api-keys/${R}`,{method:"PATCH",body:JSON.stringify(Z)});K(I=>I&&{...I,apiKeys:I.apiKeys.map(ge=>ge.id===R?le.apiKey:ge)}),J("Key 已更新"),window.setTimeout(()=>J(""),1800)}async function ye(R,Z){const le=await ve(`/api/channels/${R}`,{method:"PATCH",body:JSON.stringify(Z)});ie(I=>I.map(ge=>ge.id===R?il(le.channel):ge)),We(le.removedModels),J("渠道已更新"),window.setTimeout(()=>J(""),1800)}async function ce(R){const Z=ae.find(I=>I.id===R);if(!window.confirm(`删除渠道「${Z?.name||R}」?`))return;const le=await ve(`/api/channels/${R}`,{method:"DELETE"});ie(I=>I.filter(ge=>ge.id!==R)),We(le.removedModels),J("渠道已删除"),window.setTimeout(()=>J(""),1800)}async function St(R){const Z=await ve("/api/groups",{method:"POST",body:JSON.stringify(R)});Y(le=>[...le,Z.group]),J("分组已创建"),window.setTimeout(()=>J(""),1800)}async function F(R,Z){const le=await ve(`/api/groups/${R}`,{method:"PATCH",body:JSON.stringify(Z)});Y(I=>I.map(ge=>ge.id===R?le.group:ge)),J("分组已更新"),window.setTimeout(()=>J(""),1800)}async function $e(R){const Z=be.find(le=>le.id===R);window.confirm(`删除分组「${Z?.name||R}」?删除后渠道的可见范围会移除该分组。`)&&(await ve(`/api/groups/${R}`,{method:"DELETE"}),Y(le=>le.filter(I=>I.id!==R)),ie(le=>le.map(I=>({...I,allowedGroupIds:I.allowedGroupIds.filter(ge=>ge!==R)}))),J("分组已删除"),window.setTimeout(()=>J(""),1800))}async function rt(R,Z){const le=je(Z).map(Rt=>Rt.trim()).filter(Boolean),I=await ve(`/api/channels/${R}/sync-models`,{method:"POST",body:JSON.stringify(le.length?{models:le}:{})}),ge=il(I.channel),qe=je(I.addedModels).map(cs),Ke=je(I.models);ie(Rt=>Rt.map(Rl=>Rl.id===R?ge:Rl)),qe.length>0&&P(Rt=>{const Rl=new Set(Rt.map(ca=>ca.id.toLowerCase()));return[...Rt,...qe.filter(ca=>!Rl.has(ca.id.toLowerCase()))]}),We(I.removedModels),J(le.length?`已保存 ${Ke.length} 个模型`:Ke.length?`已拉取 ${Ke.length} 个模型`:"上游没有返回模型"),window.setTimeout(()=>J(""),2200)}function We(R){const Z=new Set(je(R).map(le=>le.toLowerCase()));Z.size!==0&&(P(le=>le.filter(I=>!Z.has(I.id.toLowerCase()))),K(le=>le&&{...le,apiKeys:le.apiKeys.map(I=>({...I,allowedModels:I.allowedModels.filter(ge=>!Z.has(ge.toLowerCase()))}))}))}async function bt(R){try{const Z=await ve(`/api/channels/${R}/check`,{method:"POST",body:JSON.stringify({})});ie(le=>le.map(I=>I.id===R?il(Z.channel):I)),J(Z.ok?`渠道可用,检测到 ${je(Z.models).length} 个模型`:"渠道检测失败")}catch(Z){const le=Z instanceof Ci?Z.payload?.channel:null;le&&ie(I=>I.map(ge=>ge.id===R?il(le):ge)),J(Z instanceof Error?Z.message:"渠道检测失败")}window.setTimeout(()=>J(""),2400)}async function Ut(R=Ic("codex")){const Z=await ve("/api/channels",{method:"POST",body:JSON.stringify(R)});ie(le=>[...le,il(Z.channel)]),J("渠道已创建,可继续拉取模型或检测渠道"),window.setTimeout(()=>J(""),2400)}async function tl(R,Z){const le=new FormData;le.append("file",Z);const I=await I0(`/api/channels/${encodeURIComponent(R)}/import-openai-accounts`,le);ie(ge=>ge.map(qe=>qe.id===I.channel.id?il(I.channel):qe)),J(`新增 ${I.created??I.imported} 个账号${I.updated?`,更新 ${I.updated} 个已有账号`:""}${I.skipped?`,跳过 ${I.skipped} 个`:""}`),window.setTimeout(()=>J(""),2600)}async function ll(R,Z=!1,le=""){const I=await ve(`/api/channels/${encodeURIComponent(R)}/openai-accounts/check`,{method:"POST",body:JSON.stringify({onlyInvalid:Z,accountId:le})});ie(ge=>ge.map(qe=>qe.id===I.channel.id?il(I.channel):qe)),J(`${Z?"无效账号复检":"账号测活"}完成:${I.healthy}/${I.checked} 可用${I.failed?`,无效 ${I.failed}`:""}`),window.setTimeout(()=>J(""),3e3)}async function U(R){const Z=await ve(`/api/channels/${encodeURIComponent(R)}/openai-accounts/deduplicate`,{method:"POST",body:JSON.stringify({})});ie(le=>le.map(I=>I.id===Z.channel.id?il(Z.channel):I)),J(Z.removed?`已合并 ${Z.removed} 个重复账号`:"未发现可识别的重复账号"),window.setTimeout(()=>J(""),2600)}async function B(R,Z){const le=await ve(`/api/channels/${encodeURIComponent(R)}/openai-accounts/${encodeURIComponent(Z)}`,{method:"DELETE"});ie(I=>I.map(ge=>ge.id===le.channel.id?il(le.channel):ge)),J("账号已删除"),window.setTimeout(()=>J(""),1800)}async function Be(R){return ve(`/api/channels/${encodeURIComponent(R)}/openai-oauth/start`,{method:"POST",body:JSON.stringify({})})}async function Fe(R,Z){const le=await ve(`/api/channels/${encodeURIComponent(R)}/openai-oauth/complete`,{method:"POST",body:JSON.stringify(Z)});return ie(I=>I.map(ge=>ge.id===le.channel.id?il(le.channel):ge)),J("已通过 OAuth 添加账号"),window.setTimeout(()=>J(""),2400),le}async function nt(R){const Z=await ve("/api/models",{method:"POST",body:JSON.stringify(R)});P(le=>[...le,cs(Z.model)]),J("模型已添加"),window.setTimeout(()=>J(""),1800)}async function et(R,Z){const le=await ve(`/api/models/${encodeURIComponent(R)}`,{method:"PATCH",body:JSON.stringify(Z)});P(I=>I.map(ge=>ge.id===R?cs(le.model):ge)),J("模型已更新"),window.setTimeout(()=>J(""),1600)}async function zi(R){window.confirm(`删除模型 ${R}?渠道和 Key 中的引用也会一起清理。`)&&(await ve(`/api/models/${encodeURIComponent(R)}`,{method:"DELETE"}),P(Z=>Z.filter(le=>le.id!==R)),ie(Z=>Z.map(le=>({...le,models:le.models.filter(I=>I!==R)}))),K(Z=>Z&&{...Z,apiKeys:Z.apiKeys.map(le=>({...le,allowedModels:le.allowedModels.filter(I=>I!==R)}))}),J("模型已删除"),window.setTimeout(()=>J(""),1800))}async function hn(R,Z="已复制"){await Ai(R),J(Z),window.setTimeout(()=>J(""),1600)}function ia(R,Z){if(R instanceof Ci&&R.status===401){X(!1),r("login"),f("auth");return}J(Z)}async function ua(){try{const R=await ve("/api/auth/status");if(T(R),!R.initialized){r("setup"),f("auth");return}if(!R.authenticated){r("login"),f("auth");return}f(R.session?.role==="admin"?"console":"account")}catch(R){ia(R,"认证状态加载失败")}}async function Oi(){await ve("/api/auth/logout",{method:"POST"}),window.sessionStorage.removeItem("capi-admin-token"),T(null),f("home")}return b.useEffect(()=>{let R=!1;return ve("/api/auth/status").then(Z=>{R||(T(Z),Z.authenticated&&Z.session&&f(Z.session.role==="admin"?"console":"account"))}).catch(()=>{}),()=>{R=!0}},[]),b.useEffect(()=>{u==="console"&&(X(!1),m().catch(R=>ia(R,"加载数据失败")))},[u]),b.useEffect(()=>{u!=="console"||!H||h(Ce).catch(R=>ia(R,"加载用户详情失败"))},[Ce,u,H]),b.useEffect(()=>{window.localStorage.setItem("capi-theme",C)},[C]),b.useEffect(()=>{window.scrollTo({top:0,left:0})},[u,L]),u==="home"?n.jsx(xp,{theme:C,setTheme:g,enterConsole:ua}):u==="auth"?n.jsx(hp,{theme:C,mode:p,status:A,setTheme:g,setMode:r,goHome:()=>f("home"),onAuthenticated:R=>{T(Z=>Z?{...Z,authenticated:!0,initialized:!0,session:R}:null),f(R.role==="admin"?"console":"account")}}):u==="account"?n.jsx(bp,{theme:C,setTheme:g,goHome:()=>f("home"),openLogin:ua}):n.jsxs("div",{className:"app-shell","data-theme":C,"data-density":G,children:[n.jsxs("aside",{className:"sidebar",children:[n.jsxs("div",{className:"ios-window-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsxs("div",{className:"brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"聚合网关"})]})]}),n.jsx("nav",{children:dm.map(R=>n.jsxs("button",{className:L===R.id?"nav-item active":"nav-item",onClick:()=>$(R.id),children:[n.jsx(Ot,{name:R.icon}),n.jsx("span",{className:"nav-label",children:R.label})]},R.id))}),n.jsxs("div",{className:"sidebar-footer",children:[n.jsx("span",{children:"Gateway"}),n.jsxs("strong",{children:[n.jsx("span",{className:"pulse-dot"}),"Online"]})]})]}),n.jsxs("main",{className:"content",children:[n.jsxs("header",{className:"topbar",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Admin Console"}),n.jsx("h1",{children:dm.find(R=>R.id===L)?.label})]}),n.jsxs("div",{className:"topbar-actions",children:[n.jsx(Vp,{value:G,options:[{value:"comfortable",label:"舒适"},{value:"compact",label:"紧凑"}],onChange:R=>z(R)}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>g(C==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:C==="dark"?"sun":"moon"}),n.jsx("span",{children:C==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:()=>m().catch(R=>ia(R,"刷新失败")),children:"刷新"}),n.jsx("button",{className:"secondary-button home-link",onClick:()=>f("home"),children:"首页"}),n.jsx("button",{className:"secondary-button",onClick:Oi,children:"退出"})]})]}),L==="overview"&&n.jsx(jp,{overview:V,channels:ae,logs:he,onNavigate:R=>{$(R),R==="channels"&&ae.length===0&&J("渠道页可以创建第一个上游"),R==="logs"&&he.length===0&&J("暂无异常日志"),window.setTimeout(()=>J(""),1800)}}),L==="users"&&n.jsx(Np,{users:se,query:ne,selectedUser:ue,onQuery:me,onSelect:Me,onUpdate:M,onBulkUpdate:Q,onCreateKey:ee,groups:be,onOpenRegistration:()=>{$("settings"),J("在账号与注册里开放注册,用户即可自助创建账号"),window.setTimeout(()=>J(""),2400)}}),L==="groups"&&n.jsx(Kp,{groups:be,onCreate:St,onUpdate:F,onDelete:$e}),L==="keys"&&n.jsx(Ap,{selectedUser:ue,onCreateKey:ee,onUpdateKey:O,onDeleteKey:Ne}),L==="models"&&n.jsx(Tp,{models:xe,onCopy:hn,onCreate:nt,onUpdate:et,onDelete:zi}),L==="drawing"&&n.jsx(vm,{variant:"drawing",channels:ae,onCreate:Ut,onImport:tl,onCheckAccounts:ll,onDeduplicateAccounts:U,onDeleteAccount:B,onUpdate:ye,onStartOAuth:Be,onCompleteOAuth:Fe}),L==="antigravity"&&n.jsx(vm,{variant:"antigravity",channels:ae,onCreate:Ut,onImport:tl,onCheckAccounts:ll,onDeduplicateAccounts:U,onDeleteAccount:B,onUpdate:ye,onStartOAuth:Be,onCompleteOAuth:Fe}),L==="channels"&&n.jsx(Yp,{channels:ae,groups:be,onUpdate:ye,onCreate:Ut,onImport:tl,onDelete:ce,onSyncModels:rt,onCheck:bt}),L==="logs"&&n.jsx(kp,{logs:he,onCopy:hn}),L==="settings"&&n.jsx(Xp,{models:xe,channels:ae,groups:be})]}),N&&n.jsx("div",{className:"secret-dialog-backdrop",role:"presentation",children:n.jsxs("section",{className:"secret-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"secret-dialog-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"One-time secret"}),n.jsx("h2",{id:"secret-dialog-title",children:"完整 API Key"})]}),n.jsx("p",{children:"完整密钥只显示这一次。列表中的星号内容只是识别前缀,不能用于 API 调用。"}),n.jsx("code",{children:N}),n.jsxs("div",{className:"secret-dialog-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>{Ai(N),J("完整 Key 已复制"),window.setTimeout(()=>J(""),1800)},children:"复制"}),n.jsx("button",{className:"primary-button",onClick:()=>k(""),children:"完成"})]})]})}),de&&n.jsx("div",{className:"toast",children:de})]})}function hp({theme:u,mode:f,status:p,setTheme:r,setMode:A,goHome:T,onAuthenticated:L}){const[$,C]=b.useState(""),[g,G]=b.useState(""),[z,V]=b.useState(""),[W,fe]=b.useState(""),[te,ae]=b.useState(""),[ie,be]=b.useState(""),[Y,xe]=b.useState(!1),[P,he]=b.useState("username"),[_,ne]=b.useState("0"),[me,Ce]=b.useState(""),[Me,ue]=b.useState(!1),K=f==="setup",de=f==="register",J=Mi(p?.registrationMode),N=de&&J==="email",k=de&&J==="discord";async function H(){if(!k){if((K||de)&&te!==ie){Ce("两次输入的密码不一致");return}ue(!0),Ce("");try{const X=K?"/api/auth/setup":de?"/api/auth/register":"/api/auth/login",se=N?fp(z):$,m=f==="login"?{identifier:$,password:te}:{username:se,password:te,displayName:g,email:z,discordUserId:K?W:"",registrationEnabled:K?Y:void 0,registrationMode:K?P:void 0,defaultBalance:K?Number(_||0):void 0},h=await ve(X,{method:"POST",body:JSON.stringify(m)});L(h.session)}catch(X){Ce(X instanceof Error?X.message:"操作失败")}finally{ue(!1)}}}return n.jsxs("main",{className:"auth-page","data-theme":u,children:[n.jsxs("header",{className:"auth-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:T,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>r(u==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:u==="dark"?"sun":"moon"}),n.jsx("span",{children:u==="dark"?"浅色":"暗色"})]})]}),n.jsxs("section",{className:"auth-stage",children:[n.jsxs("div",{className:"auth-intro",children:[n.jsx("span",{children:K?"First Run":"Welcome Back"}),n.jsx("h1",{children:K?"初始化 CAPI":de?"创建账号":"登录"}),n.jsx("p",{children:K?"创建第一个管理员账号,完成后即可进入控制台。":"使用你的 CAPI 账号继续。"})]}),n.jsxs("form",{className:"auth-form",onSubmit:X=>{X.preventDefault(),H()},children:[k?n.jsxs("div",{className:"auth-discord-register",children:[n.jsx("strong",{children:"使用 Discord 创建账号"}),n.jsx("span",{children:"继续后会按站点设置校验服务器和身份组。"}),p?.discordEnabled?n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"继续使用 Discord"}):n.jsx("div",{className:"auth-message",children:"管理员还没有启用 Discord 登录"})]}):n.jsxs(n.Fragment,{children:[f!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:g,onChange:X=>G(X.target.value),autoComplete:"name",placeholder:"CAPI"})]}),!N&&n.jsxs("label",{children:[n.jsx("span",{children:f==="login"?"账号或邮箱":"账号"}),n.jsx("input",{value:$,onChange:X=>C(X.target.value),autoComplete:"username",placeholder:f==="login"?"输入账号或邮箱":"3-32 位字母、数字、_ 或 -"})]}),(K||N)&&n.jsxs("label",{children:[n.jsx("span",{children:N?"邮箱":"邮箱(可选)"}),n.jsx("input",{type:"email",value:z,onChange:X=>V(X.target.value),autoComplete:"email",placeholder:"name@example.com"})]}),K&&n.jsxs(n.Fragment,{children:[n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:W,onChange:X=>fe(X.target.value),placeholder:"绑定管理员 Discord 账号"})]}),n.jsxs("div",{className:"setup-options",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放注册"}),n.jsx("button",{type:"button",className:Y?"ios-switch is-on":"ios-switch","aria-pressed":Y,onClick:()=>xe(X=>!X),children:n.jsx("span",{})})]}),n.jsxs("label",{children:[n.jsx("span",{children:"注册方式"}),n.jsxs("select",{value:P,onChange:X=>he(Mi(X.target.value)),children:[n.jsx("option",{value:"username",children:"账号密码"}),n.jsx("option",{value:"email",children:"邮箱"}),n.jsx("option",{value:"discord",children:"Discord"})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新用户初始额度"}),n.jsx("input",{type:"number",min:"0",step:"0.01",value:_,onChange:X=>ne(X.target.value)})]})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"密码"}),n.jsx("input",{type:"password",value:te,onChange:X=>ae(X.target.value),autoComplete:f==="login"?"current-password":"new-password",placeholder:"至少 8 个字符"})]}),f!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"确认密码"}),n.jsx("input",{type:"password",value:ie,onChange:X=>be(X.target.value),autoComplete:"new-password",placeholder:"再次输入密码"})]}),n.jsx("div",{className:"auth-message",role:"status",children:me}),n.jsx("button",{className:"primary-button auth-submit",type:"submit",disabled:Me,children:Me?"请稍候":K?"创建管理员":de?"注册":"登录"})]}),!K&&!k&&p?.discordEnabled&&n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"使用 Discord 登录"}),!K&&n.jsx("div",{className:"auth-switch",children:f==="login"&&p?.registrationEnabled?n.jsx("button",{type:"button",onClick:()=>A("register"),children:"创建账号"}):n.jsx("button",{type:"button",onClick:()=>A("login"),children:"返回登录"})})]})]})]})}const pp=[1,1.5,2,2.5,3,4,5,6,8,10];function vp(u){if(!(u>0))return 1;const f=Math.floor(Math.log10(u)),p=Math.pow(10,f),r=u/p;return(pp.find(T=>r<=T)??10)*p}const pm=88;function yp(u){const f=u.split("-");return f.length===3?`${f[1]}/${f[2]}`:u}function gp(){const[u,f]=b.useState(14),[p,r]=b.useState(null),[A,T]=b.useState(!0),[L,$]=b.useState(!1),[C,g]=b.useState("");b.useEffect(()=>{let Y=!1;return T(!0),ve(`/api/account/usage?days=${u}&timezoneOffset=${new Date().getTimezoneOffset()}`).then(xe=>{Y||(r({...xe.usage,daily:je(xe.usage?.daily),models:je(xe.usage?.models)}),$(!1))}).catch(()=>{Y||$(!0)}).finally(()=>{Y||T(!1)}),()=>{Y=!0}},[u]);const G=p?.daily??[],z=p?.models??[],V=vp(Math.max(0,...G.map(Y=>Y.cost))),W=Math.max(0,...z.map(Y=>Y.cost)),fe=G.reduce((Y,xe)=>!Y||xe.cost>Y.cost?xe:Y,null),te=Math.max(1,Math.ceil(G.length/5)),ae=G.find(Y=>Y.day===C)||null,ie=ae?G.indexOf(ae):-1,be=p?p.today.cost-p.yesterday.cost:0;return n.jsxs("section",{className:"account-section usage-section",children:[n.jsx("div",{className:"account-section-title",children:n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Usage"}),n.jsx("h2",{children:"用量概览"})]})}),!p&&A&&n.jsx("p",{className:"usage-placeholder",children:"正在统计用量…"}),!p&&!A&&L&&n.jsx("p",{className:"usage-placeholder",children:"用量加载失败,请稍后重试"}),p&&n.jsxs("div",{className:A?"usage-body is-refreshing":"usage-body",children:[n.jsxs("div",{className:"usage-kpi",children:[n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"今日消费"}),n.jsx("strong",{children:jt(p.today.cost)}),n.jsxs("small",{children:["较昨日 ",be>=0?"+":"−",jt(Math.abs(be))]})]}),n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"本月消费"}),n.jsx("strong",{children:jt(p.month.cost)}),n.jsxs("small",{children:[ml(p.month.requests)," 次请求"]})]}),n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"今日请求"}),n.jsx("strong",{children:ml(p.today.requests)}),n.jsxs("small",{children:["成功率 ",p.today.successRate,"%"]})]}),n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"累计消费"}),n.jsx("strong",{children:jt(p.total.cost)}),n.jsxs("small",{children:[ml(p.total.requests)," 次请求"]})]})]}),n.jsx("div",{className:"usage-range",role:"group","aria-label":"统计范围",children:[7,14,30].map(Y=>n.jsxs("button",{type:"button",className:u===Y?"selected":"","aria-pressed":u===Y,onClick:()=>f(Y),children:["近 ",Y," 天"]},Y))}),n.jsxs("div",{className:"usage-block",children:[n.jsxs("div",{className:"usage-block-head",children:[n.jsx("strong",{children:"每日消费"}),n.jsxs("span",{children:["近 ",p.rangeDays," 天"]})]}),G.length===0||V<=0?n.jsx("p",{className:"usage-placeholder",children:"这段时间还没有消费记录"}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"usage-plot",children:[n.jsx("div",{className:"usage-grid","aria-hidden":"true",children:[1,.5,0].map(Y=>n.jsx("div",{className:"usage-gridline",style:{bottom:`${Y*pm}%`},children:n.jsx("span",{children:jt(V*Y)})},Y))}),n.jsxs("div",{className:"usage-columns",children:[G.map((Y,xe)=>{const P=V>0?Y.cost/V*pm:0,he=Y.cost>0,_=he&&fe!==null&&Y.day===fe.day,ne=xe%te===0||xe===G.length-1;return n.jsxs("div",{className:"usage-column",children:[n.jsxs("button",{type:"button",className:C===Y.day?"usage-column-hit is-hovered":"usage-column-hit",onMouseEnter:()=>g(Y.day),onMouseLeave:()=>g(""),onFocus:()=>g(Y.day),onBlur:()=>g(""),"aria-label":`${Y.day} 消费 ${jt(Y.cost)},${Y.requests} 次请求`,children:[he&&n.jsx("span",{className:"usage-column-bar",style:{height:`${P}%`}}),_&&n.jsx("span",{className:"usage-column-peak",style:{bottom:`calc(${P}% + 6px)`},children:jt(Y.cost)})]}),n.jsx("span",{className:"usage-column-tick",children:ne?yp(Y.day):""})]},Y.day)}),ae&&n.jsxs("div",{className:"usage-tooltip",style:{left:`${(ie+.5)/G.length*100}%`},role:"status",children:[n.jsx("strong",{children:jt(ae.cost)}),n.jsx("span",{children:ae.day}),n.jsxs("span",{children:[ae.requests," 次请求"]})]})]})]}),n.jsxs("details",{className:"usage-table-toggle",children:[n.jsx("summary",{children:"查看数据表"}),n.jsxs("div",{className:"usage-table",children:[n.jsxs("div",{className:"usage-table-head",children:[n.jsx("span",{children:"日期"}),n.jsx("span",{children:"请求"}),n.jsx("span",{children:"消费"})]}),G.slice().reverse().map(Y=>n.jsxs("div",{className:"usage-table-row",children:[n.jsx("span",{children:Y.day}),n.jsx("span",{children:Y.requests}),n.jsx("span",{children:jt(Y.cost)})]},Y.day))]})]})]})]}),n.jsxs("div",{className:"usage-block",children:[n.jsxs("div",{className:"usage-block-head",children:[n.jsx("strong",{children:"按模型拆分"}),n.jsxs("span",{children:["近 ",p.rangeDays," 天消费"]})]}),z.length===0?n.jsx("p",{className:"usage-placeholder",children:"这段时间还没有调用记录"}):n.jsx("div",{className:"usage-models",children:z.map(Y=>n.jsxs("div",{className:"usage-model-row",children:[n.jsx("span",{className:"usage-model-name",title:Y.model,children:Y.model}),n.jsx("span",{className:"usage-model-track",children:n.jsx("span",{className:"usage-model-bar",style:{width:`${W>0?Y.cost/W*100:0}%`}})}),n.jsx("span",{className:"usage-model-value",children:jt(Y.cost)})]},Y.model))})]})]})]})}function bp({theme:u,setTheme:f,goHome:p,openLogin:r}){const[A,T]=b.useState(null),[L,$]=b.useState([]),[C,g]=b.useState(null),[G,z]=b.useState(!1),[V,W]=b.useState(""),[fe,te]=b.useState(""),[ae,ie]=b.useState("");async function be(){try{const[_,ne,me]=await Promise.all([ve("/api/account/me"),ve("/api/catalog/models"),ve("/api/account/check-in")]);T({..._,apiKeys:je(_.apiKeys)}),$(je(ne.models).map(cs)),g(me.checkIn)}catch{r()}}b.useEffect(()=>{be()},[]);async function Y(){if(!(!C?.enabled||C.claimed||G)){z(!0),W("");try{const _=await ve("/api/account/check-in",{method:"POST",body:JSON.stringify({})});T(ne=>ne&&{...ne,user:_.user}),g(_.checkIn),W(`签到成功,获得 ${_.reward.toFixed(2)} 额度`)}catch(_){W(_ instanceof Error?_.message:"签到失败,请稍后重试")}finally{z(!1)}}}async function xe(){try{const _=await ve("/api/account/api-keys",{method:"POST",body:JSON.stringify({name:"My API Key"})});te(_.secret),ie("新密钥只显示这一次"),await be()}catch(_){ie(_ instanceof Error?_.message:"创建密钥失败")}}async function P(_){if(window.confirm("删除这个 API Key?使用它的请求会立即失效。"))try{await ve(`/api/account/api-keys/${_}`,{method:"DELETE"}),T(ne=>ne&&{...ne,apiKeys:ne.apiKeys.filter(me=>me.id!==_)}),ie("密钥已删除")}catch(ne){ie(ne instanceof Error?ne.message:"删除密钥失败")}}async function he(){await ve("/api/auth/logout",{method:"POST"}),p()}return n.jsxs("main",{className:"account-page","data-theme":u,children:[n.jsxs("header",{className:"account-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:p,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("div",{className:"account-actions",children:[n.jsx("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>f(u==="dark"?"light":"dark"),children:n.jsx(Ot,{name:u==="dark"?"sun":"moon"})}),n.jsx("button",{className:"secondary-button",onClick:he,children:"退出"})]})]}),n.jsxs("section",{className:"account-content",children:[n.jsxs("div",{className:"account-heading",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"My CAPI"}),n.jsx("h1",{children:A?.user.name||"账户"})]}),n.jsxs("div",{className:"account-balance",children:[n.jsx("span",{children:"余额"}),n.jsx("strong",{children:A?A.user.balance.toFixed(2):"-"})]})]}),n.jsx(gp,{}),n.jsxs("section",{className:"account-section check-in-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Daily Reward"}),n.jsx("h2",{children:"每日签到"})]}),n.jsx("button",{className:"primary-button",disabled:!C?.enabled||!!C?.claimed||G,onClick:Y,children:G?"领取中":C?.claimed?"今日已签到":C?.enabled?"签到领额度":"暂未开放"})]}),n.jsxs("div",{className:"check-in-summary",children:[n.jsxs("div",{children:[n.jsx("span",{children:"今日状态"}),n.jsx("strong",{children:C?.claimed?`已领取 ${C.reward.toFixed(2)}`:C?.enabled?"等待签到":"活动关闭"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"随机奖励"}),n.jsx("strong",{children:C?`${C.minReward.toFixed(2)} - ${C.maxReward.toFixed(2)}`:"-"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"结算日期"}),n.jsx("strong",{children:C?.day||"北京时间"})]})]}),n.jsx("p",{className:"check-in-note",children:"每天按北京时间 00:00 刷新,奖励领取后直接计入账户余额。"}),V&&n.jsx("p",{className:"account-message check-in-message",role:"status",children:V})]}),n.jsxs("section",{className:"account-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"API Keys"}),n.jsx("h2",{children:"API 密钥"})]}),n.jsx("button",{className:"primary-button",onClick:xe,children:"创建密钥"})]}),fe&&n.jsx("code",{className:"one-time-secret",children:fe}),ae&&n.jsx("p",{className:"account-message",children:ae}),n.jsxs("div",{className:"account-key-list",children:[A?.apiKeys?.map(_=>n.jsxs("div",{className:"account-key-item",children:[n.jsx("span",{className:"account-key-mark","aria-hidden":"true",children:n.jsx(Ot,{name:"key"})}),n.jsxs("div",{className:"account-key-info",children:[n.jsx("strong",{children:_.name}),n.jsxs("code",{children:[_.prefix,"…"]})]}),n.jsx(Dt,{tone:_.status,children:_t(_.status)}),n.jsx("button",{className:"icon-button","aria-label":`删除 ${_.name}`,title:"删除密钥",onClick:()=>P(_.id),children:n.jsx(Ot,{name:"ban"})})]},_.id)),je(A?.apiKeys).length===0&&n.jsx("div",{className:"empty",children:"还没有 API 密钥"})]})]}),n.jsxs("section",{className:"account-section",children:[n.jsx("div",{className:"account-section-title",children:n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Models"}),n.jsx("h2",{children:"可用模型"})]})}),n.jsxs("div",{className:"account-model-grid",children:[L.map(_=>n.jsxs("article",{children:[n.jsx("span",{children:_.vendor}),n.jsx("strong",{children:_.name}),n.jsx("p",{children:_.description}),n.jsx("code",{children:_.id})]},_.id)),L.length===0&&n.jsx("div",{className:"account-model-empty",children:"暂无可用模型,管理员配置渠道后将在此展示"})]})]})]})]})}function xp({theme:u,setTheme:f,enterConsole:p}){return n.jsxs("main",{className:"public-home","data-theme":u,children:[n.jsxs("header",{className:"home-topbar",children:[n.jsxs("div",{className:"home-brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"AI 聚合网关"})]})]}),n.jsxs("div",{className:"home-actions",children:[n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>f(u==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:u==="dark"?"sun":"moon"}),n.jsx("span",{children:u==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:p,children:"控制台"})]})]}),n.jsxs("section",{className:"home-hero",children:[n.jsxs("div",{className:"home-copy",children:[n.jsx("span",{className:"home-kicker",children:"兼容 OpenAI 格式的网关"}),n.jsxs("h1",{children:["CAPI",n.jsx("span",{children:"轻量 AI 聚合网关"})]}),n.jsx("p",{children:"面向个人用户和团队的模型接入层。把 API Key、额度、模型渠道和调用日志放在一个清爽控制台里,保持轻量,也便于排障。"}),n.jsx("div",{className:"home-cta",children:n.jsx("button",{className:"primary-button",onClick:p,children:"进入控制台"})}),n.jsxs("div",{className:"integration-row","aria-label":"网关能力概览",children:[n.jsx("span",{children:"网关能力"}),n.jsxs("div",{children:[n.jsx("span",{children:"OpenAI 兼容接口"}),n.jsx("span",{children:"额度控制"}),n.jsx("span",{children:"调用审计"})]})]})]}),n.jsxs("div",{className:"gateway-terminal","aria-label":"CAPI 终端请求示意",children:[n.jsxs("div",{className:"terminal-titlebar",children:[n.jsxs("div",{className:"terminal-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsx("strong",{children:"CAPI Terminal"}),n.jsxs("div",{className:"terminal-status",children:[n.jsx("span",{className:"pulse-dot"}),n.jsx("strong",{children:"Online"})]})]}),n.jsxs("div",{className:"terminal-endpoint",children:[n.jsx("span",{children:"POST"}),n.jsx("strong",{children:"/v1/chat/completions"})]}),n.jsxs("div",{className:"terminal-body",children:[n.jsxs("div",{className:"terminal-block",children:[n.jsx("span",{children:"REQUEST"}),n.jsx("pre",{children:`curl https://api.capi.local/v1/chat/completions \\ + -H "Authorization: Bearer cat_..." \\ + -d '{ + "model": "capi-fast", + "messages": [{ "role": "user", "content": "ping" }] + }'`})]}),n.jsxs("div",{className:"terminal-route",children:[n.jsxs("div",{children:[n.jsx("span",{children:"auth"}),n.jsx("strong",{children:"pass"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"quota"}),n.jsx("strong",{children:"ok"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"route"}),n.jsx("strong",{children:"capi-fast"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"latency"}),n.jsx("strong",{children:"186ms"})]})]}),n.jsxs("div",{className:"terminal-block response",children:[n.jsx("span",{children:"RESPONSE"}),n.jsxs("pre",{children:[`{ + "status": 200, + "model": "capi-fast", + "usage": { "total_tokens": 27 }, + "message": "request routed" +}`,n.jsx("span",{className:"terminal-caret","aria-hidden":"true"})]})]})]})]})]})]})}function jp({overview:u,channels:f,logs:p,onNavigate:r}){const A=p.filter(T=>T.status!=="success");return n.jsxs("section",{className:"page-stack",children:[n.jsxs("div",{className:"hero-strip",children:[n.jsxs("div",{children:[n.jsx("span",{children:"Live Gateway"}),n.jsxs("strong",{children:["CAPI 网关正在服务 ",u?.activeUsers??"-"," 个活跃用户"]}),n.jsx("p",{children:"请求进入 CAPI 后,会按额度、模型和渠道状态自动选择最合适的上游。"})]}),n.jsxs("div",{className:"live-island",children:[n.jsx("div",{className:"pulse-dot"}),n.jsx("span",{children:"在线"})]})]}),n.jsxs("div",{className:"quick-actions","aria-label":"快捷操作",children:[n.jsx(Si,{icon:"key",label:"创建 Key",onClick:()=>r("keys")}),n.jsx(Si,{icon:"route",label:"配置渠道",onClick:()=>r("channels")}),n.jsx(Si,{icon:"users",label:"调整额度",onClick:()=>r("users")}),n.jsx(Si,{icon:"logs",label:"查看异常",onClick:()=>r("logs")})]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(cl,{label:"活跃用户",value:u?ml(u.activeUsers):"-"}),n.jsx(cl,{label:"今日请求",value:u?ml(u.requestsToday):"-"}),n.jsx(cl,{label:"今日输入",value:u?ml(u.todayInputTokens):"-"}),n.jsx(cl,{label:"今日输出",value:u?ml(u.todayOutputTokens):"-"}),n.jsx(cl,{label:"今日扣费",value:u?jt(u.todayCost,4):"-"}),n.jsx(cl,{label:"账户余额",value:u?jt(u.totalBalance):"-"}),n.jsx(cl,{label:"成功率",value:u?`${u.successRate}%`:"-"})]}),n.jsx(Sp,{}),n.jsxs("div",{className:"split-grid",children:[n.jsx(at,{title:"渠道状态",children:f.length?f.map(T=>n.jsxs("div",{className:"list-row overview-channel-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:T.name}),n.jsx("span",{title:je(T.models).join(", "),children:op(T.models)})]}),n.jsx(Dt,{tone:T.status,children:_t(T.status)})]},T.id)):n.jsx(kt,{text:"暂无渠道"})}),n.jsx(at,{title:"最近请求",children:p.length?p.slice(0,4).map(T=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:lo(T)}),n.jsxs("span",{children:[T.id," · ",T.errorCode||el(T.createdAt)]})]}),n.jsx(Dt,{tone:T.status,children:_t(T.status)})]},T.id)):n.jsx(kt,{text:A.length?"暂无最近请求":"暂无请求"})})]})]})}function Si({icon:u,label:f,onClick:p}){return n.jsxs("button",{className:"quick-action",onClick:p,children:[n.jsx(Ot,{name:u}),n.jsx("span",{children:f})]})}function Sp(){const u=[{label:"认证",detail:"校验 API Key"},{label:"额度",detail:"检查余额"},{label:"路由",detail:"选择渠道"},{label:"响应",detail:"返回结果"}];return n.jsxs("section",{className:"flow-panel","aria-label":"网关流转",children:[n.jsxs("div",{className:"flow-copy",children:[n.jsx("span",{children:"Request Flow"}),n.jsx("strong",{children:"请求处理流程"})]}),n.jsx("div",{className:"flow-steps",children:u.map((f,p)=>n.jsxs("div",{className:"flow-step",children:[n.jsx("div",{className:"flow-index",children:p+1}),n.jsx("strong",{children:f.label}),n.jsx("span",{children:f.detail})]},f.label))})]})}function Np({users:u,query:f,selectedUser:p,onQuery:r,onSelect:A,onUpdate:T,onBulkUpdate:L,onCreateKey:$,groups:C,onOpenRegistration:g}){const[z,V]=b.useState(1),[W,fe]=b.useState("all"),[te,ae]=b.useState(new Set),[ie,be]=b.useState("10"),[Y,xe]=b.useState(""),[P,he]=b.useState(""),[_,ne]=b.useState(!1),[me,Ce]=b.useState("10"),[Me,ue]=b.useState(""),[K,de]=b.useState(""),[J,N]=b.useState(!1),k=W==="all"?u:u.filter(O=>O.status===W),H=k.filter(O=>O.role!=="admin"),X=Math.max(1,Math.ceil(k.length/25)),se=Math.min(z,X),m=k.slice((se-1)*25,se*25),h=H.length>0&&H.every(O=>te.has(O.id));b.useEffect(()=>{V(1)},[f,W]),b.useEffect(()=>{const O=new Set(u.map(ye=>ye.id));ae(ye=>new Set([...ye].filter(ce=>O.has(ce))))},[u]),b.useEffect(()=>{Ce("10"),ue(""),de("")},[p?.user.id]);function M(O){ae(ye=>{const ce=new Set(ye);return ce.has(O)?ce.delete(O):ce.add(O),ce})}function Q(){ae(O=>{const ye=new Set(O);return h?H.forEach(ce=>ye.delete(ce.id)):H.forEach(ce=>ye.add(ce.id)),ye})}async function ee(O,ye){if(te.size!==0){ne(!0);try{await L([...te],O,ye),ae(new Set),xe("")}finally{ne(!1)}}}async function Ne(O){if(!p)return;const ye=Math.abs(Number(me));if(!Number.isFinite(ye)||ye<=0){de("请输入大于 0 的金额");return}N(!0),de("");try{await L([p.user.id],"adjust_balance",{amount:Number((ye*O).toFixed(4)),reason:Me.trim()||(O>0?"管理员增加额度":"管理员扣减额度")}),de(O>0?"额度已增加":"额度已扣减"),ue("")}catch(ce){de(ce instanceof Error?ce.message:"额度调整失败")}finally{N(!1)}}return n.jsxs("section",{className:"users-layout",children:[n.jsxs(at,{title:"用户管理",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Ot,{name:"search"}),n.jsx("input",{value:f,onChange:O=>r(O.target.value),placeholder:"搜索 ID、姓名或邮箱"})]}),n.jsx("button",{className:"icon-button",title:"开放注册",onClick:g,children:n.jsx(Ot,{name:"plus"})})]}),n.jsxs("div",{className:"user-summary-strip",children:[n.jsxs("span",{children:[n.jsx("strong",{children:u.length})," 匹配用户"]}),n.jsxs("span",{children:[n.jsx("strong",{children:u.filter(O=>O.status==="active").length})," 正常"]}),n.jsxs("span",{children:[n.jsx("strong",{children:u.filter(O=>O.status==="disabled").length})," 禁用"]}),n.jsxs("span",{children:[n.jsx("strong",{children:u.reduce((O,ye)=>O+ye.requestsToday,0)})," 今日请求"]})]}),n.jsx("div",{className:"user-filter-row",role:"group","aria-label":"用户状态筛选",children:[{value:"all",label:"全部"},{value:"active",label:"正常"},{value:"limited",label:"受限"},{value:"disabled",label:"禁用"}].map(O=>n.jsx("button",{type:"button",className:W===O.value?"selected":"",onClick:()=>fe(O.value),children:O.label},O.value))}),n.jsx("button",{type:"button",className:"secondary-button mobile-bulk-select",onClick:Q,children:h?"取消全选":`全选结果(${H.length})`}),te.size>0&&n.jsxs("div",{className:"bulk-action-bar",children:[n.jsxs("strong",{children:["已选 ",te.size," 人"]}),n.jsx("input",{type:"number",step:"0.01",value:ie,onChange:O=>be(O.target.value),"aria-label":"额度调整值"}),n.jsx("input",{value:Y,onChange:O=>xe(O.target.value),placeholder:"原因,例如:活动赠送","aria-label":"调整原因"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:_||!Number(ie),onClick:()=>ee("adjust_balance",{amount:Number(ie),reason:Y}),children:"调整额度"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:_,onClick:()=>ee("set_status",{value:"active"}),children:"启用"}),n.jsx("button",{type:"button",className:"danger-button",disabled:_,onClick:()=>ee("set_status",{value:"disabled"}),children:"禁用"}),n.jsxs("select",{className:"bulk-group-select",value:P,disabled:_,"aria-label":"批量设置分组",onChange:O=>he(O.target.value),children:[n.jsx("option",{value:"",children:"未分组"}),C.map(O=>n.jsx("option",{value:O.id,children:O.name},O.id))]}),n.jsx("button",{type:"button",className:"secondary-button",disabled:_,onClick:()=>ee("set_group",{value:P}),children:"设为分组"})]}),n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head users-table",children:[n.jsx("input",{type:"checkbox",checked:h,onChange:Q,"aria-label":"选择当前筛选结果"}),n.jsx("span",{children:"用户"}),n.jsx("span",{children:"状态"}),n.jsx("span",{children:"余额"}),n.jsx("span",{children:"今日"})]}),m.map(O=>n.jsxs("div",{className:p?.user.id===O.id?"table-row users-table selected":"table-row users-table",role:"button",tabIndex:0,onClick:()=>A(O.id),onKeyDown:ye=>{(ye.key==="Enter"||ye.key===" ")&&A(O.id)},children:[n.jsx("input",{type:"checkbox",checked:te.has(O.id),disabled:O.role==="admin",onChange:()=>M(O.id),onClick:ye=>ye.stopPropagation(),"aria-label":O.role==="admin"?`${O.name} 是管理员,不参与批量操作`:`选择 ${O.name}`}),n.jsxs("span",{children:[n.jsx("strong",{children:O.name}),n.jsxs("small",{children:[O.id," · ",O.email||"未绑定邮箱"]})]}),n.jsx(Dt,{tone:O.status,children:_t(O.status)}),n.jsx("span",{children:jt(O.balance)}),n.jsx("span",{children:O.requestsToday})]},O.id)),k.length===0&&n.jsx(kt,{text:"暂无匹配用户"})]}),k.length>25&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:se<=1,onClick:()=>V(O=>Math.max(1,O-1)),children:"上一页"}),n.jsxs("span",{children:[se," / ",X]}),n.jsx("button",{className:"secondary-button",disabled:se>=X,onClick:()=>V(O=>Math.min(X,O+1)),children:"下一页"})]})]}),n.jsx(at,{title:"用户详情",children:p?n.jsxs("div",{className:"detail-stack",children:[n.jsxs("div",{className:"user-hero",children:[n.jsx("div",{className:"avatar",children:p.user.name.slice(0,1)}),n.jsxs("div",{children:[n.jsx("h2",{children:p.user.name}),n.jsx("p",{children:p.user.email})]}),n.jsx(Dt,{tone:p.user.status,children:_t(p.user.status)})]}),n.jsxs("div",{className:"settings-group",children:[n.jsx(Pt,{label:"角色",value:p.user.role==="admin"?"管理员":"用户"}),n.jsx(Pt,{label:"余额",value:jt(p.user.balance)}),n.jsx(Pt,{label:"总请求",value:String(p.user.totalRequests)}),n.jsx(Pt,{label:"最后登录",value:el(p.user.lastLoginAt)}),n.jsx(Pt,{label:"API 调用",value:p.user.status==="disabled"?"关闭":"允许",switchOn:p.user.status!=="disabled"})]}),n.jsxs("div",{className:"group-assign-row",children:[n.jsxs("label",{children:[n.jsx("span",{children:"所属分组"}),n.jsxs("select",{value:p.user.groupId||"",onChange:O=>T(p.user.id,{groupId:O.target.value}),children:[n.jsx("option",{value:"",children:"未分组"}),C.map(O=>n.jsx("option",{value:O.id,children:O.name},O.id))]})]}),n.jsx("small",{children:"分组决定该用户可路由到哪些渠道;未分组用户只能使用未限制分组的渠道。"})]}),n.jsxs("div",{className:"balance-adjuster",children:[n.jsxs("div",{className:"balance-adjuster-title",children:[n.jsx("strong",{children:"调整余额"}),n.jsxs("span",{children:["当前 ",jt(p.user.balance)]})]}),n.jsxs("div",{className:"balance-adjuster-fields",children:[n.jsxs("label",{children:[n.jsx("span",{children:"金额"}),n.jsx("input",{type:"number",min:"0.0001",step:"0.01",value:me,onChange:O=>Ce(O.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"备注"}),n.jsx("input",{value:Me,onChange:O=>ue(O.target.value),placeholder:"可选,会记录到流水"})]})]}),n.jsxs("div",{className:"balance-adjuster-actions",children:[n.jsx("button",{className:"secondary-button",disabled:J,onClick:()=>Ne(1),children:"增加"}),n.jsx("button",{className:"danger-button",disabled:J,onClick:()=>Ne(-1),children:"扣减"}),n.jsx("span",{role:"status",children:K})]})]}),n.jsxs("div",{className:"action-row",children:[n.jsx("button",{className:"secondary-button",onClick:()=>$(p.user.id),children:"创建 Key"}),n.jsx("button",{className:"secondary-button",disabled:p.user.role==="admin",onClick:()=>T(p.user.id,{status:p.user.status==="disabled"?"active":"disabled"}),children:p.user.role==="admin"?"管理员保护":p.user.status==="disabled"?"解封":"禁用"})]}),n.jsxs("div",{children:[n.jsx("h3",{children:"API Key"}),p.apiKeys.map(O=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:O.name}),n.jsxs("span",{children:[O.prefix,"*** · ",O.requestCount," 次"]})]}),n.jsx(Dt,{tone:O.status,children:_t(O.status)})]},O.id)),p.apiKeys.length===0&&n.jsx(kt,{text:"暂无 API Key"})]})]}):n.jsx(kt,{text:"请选择一个用户"})})]})}function Ap({selectedUser:u,onCreateKey:f,onUpdateKey:p,onDeleteKey:r}){return n.jsx(at,{title:"密钥管理",children:u?n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("span",{className:"muted-inline",children:[u.user.name," · 完整 Key 只在创建时显示,丢失请重新创建"]}),n.jsx("button",{className:"primary-button",onClick:()=>f(u.user.id),children:"创建 Key"})]}),u.apiKeys.length?u.apiKeys.map(A=>n.jsx(Cp,{apiKey:A,onSave:p,onDelete:r},A.id)):n.jsx(kt,{text:"暂无密钥"})]}):n.jsx(kt,{text:"请选择一个用户"})})}function Cp({apiKey:u,onSave:f,onDelete:p}){const[r,A]=b.useState(u.name),[T,L]=b.useState(je(u.allowedModels).join(", ")),[$,C]=b.useState(mm(u.expiresAt||"")),[g,G]=b.useState(String(u.rateLimitPerMinute||"")),[z,V]=b.useState(!1),W=je(u.allowedModels).length?je(u.allowedModels).join(", "):"全部模型";b.useEffect(()=>{A(u.name),L(je(u.allowedModels).join(", ")),C(mm(u.expiresAt||"")),G(String(u.rateLimitPerMinute||""))},[u]);async function fe(){V(!0);try{await f(u.id,{name:r.trim()||"API Key",allowedModels:Pc(T),expiresAt:sp($),rateLimitPerMinute:Number(g||0)})}finally{V(!1)}}return n.jsxs("details",{className:"key-editor key-editor-collapsible",children:[n.jsxs("summary",{className:"key-editor-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:u.name}),n.jsxs("span",{children:[u.prefix,"*** · ",W," · 最后使用 ",el(u.lastUsedAt)]})]}),n.jsxs("div",{className:"row-actions",children:[n.jsx(Dt,{tone:u.status,children:_t(u.status)}),n.jsx("span",{className:"key-expand-hint",children:"管理"})]})]}),n.jsxs("div",{className:"key-editor-body",children:[n.jsxs("div",{className:"key-editor-grid",children:[n.jsxs("label",{children:["名称",n.jsx("input",{value:r,onChange:te=>A(te.target.value)})]}),n.jsxs("label",{children:["允许模型",n.jsx("input",{value:T,onChange:te=>L(te.target.value),placeholder:"留空表示全部模型,多个用逗号分隔"})]}),n.jsxs("label",{children:["过期时间",n.jsx("input",{type:"datetime-local",value:$,onChange:te=>C(te.target.value)})]}),n.jsxs("label",{children:["每分钟限制",n.jsx("input",{type:"number",min:"0",value:g,onChange:te=>G(te.target.value),placeholder:"0 使用全局限制"})]})]}),n.jsxs("div",{className:"key-editor-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>f(u.id,{status:u.status==="active"?"disabled":"active"}),children:u.status==="active"?"停用密钥":"启用密钥"}),n.jsx("button",{className:"danger-button",onClick:()=>p(u.id),children:"删除密钥"}),n.jsx("button",{className:"primary-button",disabled:z,onClick:fe,children:z?"保存中":"保存设置"})]})]})]})}function Tp({models:u,onCopy:f,onCreate:p,onUpdate:r,onDelete:A}){const T=u.filter(H=>H.recommended),[L,$]=b.useState(""),[C,g]=b.useState("all"),[G,z]=b.useState("all"),[V,W]=b.useState(1),[fe,te]=b.useState(""),[ae,ie]=b.useState(""),[be,Y]=b.useState(""),[xe,P]=b.useState(""),[he,_]=b.useState(""),[ne,me]=b.useState(""),Ce=60,Me=b.useMemo(()=>{const H=new Map;return u.forEach(X=>{const se=$c(X);H.set(se,(H.get(se)||0)+1)}),Array.from(H.entries()).sort((X,se)=>se[1]-X[1]||ul(X[0]).localeCompare(ul(se[0]))).map(([X,se])=>({provider:X,count:se}))},[u]),ue=b.useMemo(()=>{const H=L.trim().toLowerCase();return u.filter(X=>C!=="all"&&$c(X)!==C||G!=="all"&&X.status!==G?!1:H?[X.id,X.name,X.vendor,X.category,X.description,...je(X.aliases)].join(" ").toLowerCase().includes(H):!0)},[u,L,C,G]),K=b.useMemo(()=>{const H=new Map;ue.forEach(M=>{const Q=$c(M);H.set(Q,[...H.get(Q)||[],M])});const X=[];let se=[],m=0;const h=Array.from(H.entries()).sort((M,Q)=>ul(M[0]).localeCompare(ul(Q[0])));for(const M of h)se.length>0&&m+M[1].length>Ce&&(X.push(se),se=[],m=0),se.push(M),m+=M[1].length;return se.length>0&&X.push(se),X},[ue]),de=Math.max(1,K.length),J=Math.min(V,de),N=K[J-1]||[];b.useEffect(()=>{W(1)},[L,C,G,u.length]);async function k(H){H.preventDefault();const X=fe.trim();if(X){me("");try{await p({id:X,name:ae.trim()||X,vendor:be.trim()||"Custom",aliases:xe.split(",").map(se=>se.trim()).filter(Boolean),category:"通用",description:he.trim(),price:"自定义",context:"未配置上下文"}),te(""),ie(""),Y(""),P(""),_("")}catch(se){me(se instanceof Error?se.message:"模型添加失败")}}}return n.jsxs("section",{className:"models-page",children:[n.jsx("div",{className:"model-hero",children:n.jsxs("div",{children:[n.jsx("span",{children:"Model Catalog"}),n.jsx("strong",{children:"Models"})]})}),n.jsx(at,{title:"新增模型",children:n.jsxs("form",{className:"model-create-form",onSubmit:k,children:[n.jsx("input",{value:fe,onChange:H=>te(H.target.value),placeholder:"模型 ID,例如 openai/gpt-4.1"}),n.jsx("input",{value:ae,onChange:H=>ie(H.target.value),placeholder:"显示名称(可选)"}),n.jsx("input",{value:be,onChange:H=>Y(H.target.value),placeholder:"供应商(可选)"}),n.jsx("input",{value:xe,onChange:H=>P(H.target.value),placeholder:"代称,多个用逗号分隔(可选)"}),n.jsx("input",{className:"model-create-wide",value:he,onChange:H=>_(H.target.value),placeholder:"描述(可选)"}),n.jsx("button",{className:"primary-button",type:"submit",children:"新增模型"}),n.jsx("div",{className:"model-create-message",role:"status",children:ne})]})}),T.length>0&&n.jsx(at,{title:"推荐模型",children:n.jsx("div",{className:"model-grid",children:T.map(H=>n.jsx(Mp,{model:H,featured:!0,onCopy:f,onUpdate:r},H.id))})}),n.jsxs(at,{title:"全部模型",children:[n.jsxs("div",{className:"panel-toolbar model-list-toolbar",children:[n.jsx("input",{value:L,onChange:H=>$(H.target.value),placeholder:"搜索模型 ID、名称、供应商或代称"}),n.jsx("div",{className:"model-filter-actions",children:[{value:"all",label:"全部"},{value:"available",label:"可用"},{value:"disabled",label:"禁用"}].map(H=>n.jsx("button",{type:"button",className:G===H.value?"selected":"",onClick:()=>z(H.value),children:H.label},H.value))})]}),n.jsxs("div",{className:"model-provider-filter","aria-label":"按供应商筛选模型",children:[n.jsxs("button",{type:"button",className:C==="all"?"selected":"",onClick:()=>g("all"),children:[n.jsx("span",{className:"provider-icon provider-icon-all","aria-hidden":"true",children:"All"}),n.jsx("strong",{children:"全部"}),n.jsx("small",{children:u.length})]}),Me.map(H=>n.jsxs("button",{type:"button",className:C===H.provider?"selected":"",onClick:()=>g(H.provider),children:[n.jsx(hm,{provider:H.provider}),n.jsx("strong",{children:ul(H.provider)}),n.jsx("small",{children:H.count})]},H.provider))]}),n.jsxs("div",{className:"model-list-summary",children:[n.jsx("span",{children:C==="all"?"全部供应商":ul(C)}),n.jsx("strong",{children:ue.length}),n.jsx("span",{children:"个模型"})]}),ue.length>0?n.jsxs(n.Fragment,{children:[n.jsx("div",{className:"model-provider-groups",children:N.map(([H,X])=>n.jsxs("section",{className:"model-provider-group",children:[n.jsxs("header",{children:[n.jsx(hm,{provider:H}),n.jsxs("div",{children:[n.jsx("strong",{children:ul(H)}),n.jsxs("span",{children:[X.length," 个模型"]})]})]}),n.jsx("div",{className:"model-compact-grid",children:X.map(se=>n.jsx(Ep,{model:se,onCopy:f,onUpdate:r,onDelete:A},se.id))})]},H))}),de>1&&n.jsxs("div",{className:"pager",children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>W(H=>Math.max(1,H-1)),disabled:J<=1,children:"上一页"}),n.jsxs("span",{children:[J," / ",de]}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>W(H=>Math.min(de,H+1)),disabled:J>=de,children:"下一页"})]})]}):n.jsx(kt,{text:u.length?"没有匹配的模型":"暂无模型,请先添加你要开放给用户调用的模型 ID"})]})]})}function Ep({model:u,onCopy:f,onUpdate:p,onDelete:r}){const A=je(u.aliases).slice(0,3),T=u.status==="disabled";return n.jsxs("article",{className:"model-compact-row",children:[n.jsxs("div",{className:"model-compact-main",children:[n.jsx("strong",{children:u.name}),n.jsx("small",{children:u.id}),A.length>0&&n.jsx("span",{children:A.map(L=>n.jsx("em",{children:L},L))})]}),n.jsxs("div",{className:"model-row-actions",children:[n.jsx(Dt,{tone:u.status,children:_t(u.status)}),u.recommended&&n.jsx("span",{className:"model-recommended-mark",children:"推荐"}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>f(u.id,"模型 ID 已复制"),children:n.jsx(Ot,{name:"copy"})}),n.jsxs("details",{className:"model-row-menu",children:[n.jsx("summary",{"aria-label":"模型操作",children:"•••"}),n.jsxs("div",{children:[n.jsx("button",{type:"button",onClick:()=>p(u.id,{recommended:!u.recommended}),children:u.recommended?"取消推荐":"设为推荐"}),n.jsx("button",{type:"button",onClick:()=>p(u.id,{status:T?"available":"disabled"}),children:T?"启用模型":"停用模型"}),n.jsx("button",{className:"is-danger",type:"button",onClick:()=>r(u.id),children:"删除模型"})]})]})]})]})}function Mp({model:u,featured:f=!1,onCopy:p,onUpdate:r}){return n.jsxs("article",{className:f?"model-card featured":"model-card",children:[n.jsxs("div",{className:"model-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:u.name}),n.jsxs("span",{children:[u.vendor," · ",u.category]})]}),n.jsx(Dt,{tone:u.status,children:_t(u.status)})]}),n.jsx("p",{children:u.description}),n.jsx("div",{className:"alias-row",children:je(u.aliases).map(A=>n.jsx("span",{children:A},A))}),n.jsxs("div",{className:"model-meta",children:[n.jsxs("span",{children:["价格:",u.price]}),n.jsx("span",{children:u.context})]}),n.jsxs("div",{className:"model-id",children:[n.jsx("code",{children:u.id}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>p(u.id,"模型 ID 已复制"),children:n.jsx(Ot,{name:"copy"})})]}),r&&n.jsxs("div",{className:"model-card-actions",children:[n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(u.id,{recommended:!1}),children:"取消推荐"}),n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(u.id,{status:u.status==="disabled"?"available":"disabled"}),children:u.status==="disabled"?"启用":"停用"})]})]})}function vm({channels:u,onCreate:f,onImport:p,onCheckAccounts:r,onDeduplicateAccounts:A,onDeleteAccount:T,onUpdate:L,onStartOAuth:$,onCompleteOAuth:C,variant:g="drawing"}){const G=g==="antigravity",z=u.filter(h=>G?h.provider==="antigravity":h.provider!=="antigravity"&&(h.provider==="codex"||h.provider==="openai"||je(h.models).some(M=>M.includes("image")))),[V,W]=b.useState(""),[fe,te]=b.useState({}),[ae,ie]=b.useState({}),[be,Y]=b.useState({}),[xe,P]=b.useState({}),[he,_]=b.useState(""),[ne,me]=b.useState(""),[Ce,Me]=b.useState(""),[ue,K]=b.useState(""),de=24,J=48;async function N(h,M){W(`import:${h}`);try{await p(h,M)}finally{W("")}}async function k(h,M=!1,Q=""){W(Q?`check-account:${Q}`:`${M?"retry":"check"}:${h}`);try{await r(h,M,Q)}finally{W("")}}async function H(h){W(`dedupe:${h}`);try{await A(h)}finally{W("")}}function X(h){const M=je(h.openaiAccounts).map(ce=>[ce.email||ce.name||ce.accountId||ce.id,ce.accountId||"",ce.status||"unchecked",ce.credentialMode||"access-token",ce.planType||"",ce.expiresAt||"",ce.lastCheckedAt||"",ce.lastUsedAt||"",String(ce.requestCount||0),ce.lastErrorCode||"",ce.lastError||""]),Q=ce=>`"${ce.replace(/"/g,'""')}"`,ee=[["账号","Account ID","状态","凭据方式","套餐","到期时间","最近检测","最近调用","调用次数","错误码","最后错误"],...M].map(ce=>ce.map(Q).join(",")).join(`\r +`),Ne=new Blob(["\uFEFF"+ee],{type:"text/csv;charset=utf-8"}),O=URL.createObjectURL(Ne),ye=document.createElement("a");ye.href=O,ye.download=`${h.name||"account-pool"}-health-report.csv`,ye.click(),URL.revokeObjectURL(O)}async function se(h){W(`status:${h.id}`);try{await L(h.id,{status:h.status==="disabled"?"healthy":"disabled",baseUrl:h.baseUrl||Ei(h.provider)||Ti,provider:h.provider||"codex",models:je(h.models).length?h.models:jm.split(",").map(M=>M.trim())})}finally{W("")}}async function m(h,M){const Q=M.email||M.name||M.accountId||M.id;if(window.confirm(`删除账号「${Q}」?`)){W(`delete-account:${M.id}`);try{await T(h.id,M.id)}finally{W("")}}}return n.jsxs(at,{title:G?"Antigravity 账号池":"账号池",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:G?"导入 Google OAuth JSON 或 refresh token 即可入池。":"账号有两种来源,任选其一即可。"}),G?n.jsx("button",{className:"primary-button",onClick:()=>f(Ic("antigravity")),children:"新增 Antigravity 账号池"}):n.jsx("button",{className:"primary-button",onClick:()=>f(Ic("codex")),children:"新增账号池渠道"})]}),n.jsx("div",{className:"source-guide",children:G?n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"Antigravity 导入(推荐)"}),n.jsx("span",{children:"粘贴 Google OAuth 凭据 JSON 或 refresh token,调用前自动换取 accessToken。"})]}),n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"批量导入"}),n.jsx("span",{children:"支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 refresh token。"})]})]}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"网页会话(推荐)"}),n.jsx("span",{children:"支持完整 auth/session JSON 或浏览器 Session Cookie,并在调用前重新获取 accessToken。"})]}),n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"批量导入"}),n.jsx("span",{children:"支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 access token。"})]})]})}),n.jsxs("div",{className:"channels-stack",children:[z.map(h=>{const M=je(h.openaiAccounts),Q=M.filter(B=>B.status==="healthy").length,ee=M.filter(B=>B.status==="invalid").length,Ne=M.filter(B=>!!B.lastErrorCode).length,O=Math.max(0,M.length-Q-ee),ye=M.filter(B=>B.credentialMode==="refreshable").length,ce=M.filter(B=>B.credentialMode==="browser-session").length,St=Math.max(0,M.length-ye-ce),F=ae[h.id]||"all",$e=(be[h.id]||"").trim().toLowerCase(),rt=M.filter(B=>{const Be=F==="all"||F==="attention"&&Gp(B)||F==="invalid"&&B.status==="invalid"||F==="error"&&!!B.lastErrorCode||F==="refreshable"&&B.credentialMode==="refreshable",Fe=`${B.email||""} ${B.name||""} ${B.accountId||""} ${B.userId||""} ${B.lastError||""}`.toLowerCase();return Be&&(!$e||Fe.includes($e))}),We=xe[h.id]||"pool",bt=[...rt].sort((B,Be)=>{if(We==="pool")return 0;const Fe=We==="expiry"?B.expiresAt||"9999-12-31":B.lastUsedAt||"",nt=We==="expiry"?Be.expiresAt||"9999-12-31":Be.lastUsedAt||"";return We==="recent"?nt.localeCompare(Fe):Fe.localeCompare(nt)}),Ut=Math.min(bt.length,fe[h.id]||de),tl=bt.slice(0,Ut),ll=Math.max(0,bt.length-tl.length),U=ll===0;return n.jsxs("div",{className:"channel-card",children:[n.jsxs("div",{className:"channel-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:h.name}),n.jsx("span",{children:h.baseUrl||Ei(h.provider)||Ti}),n.jsxs("small",{children:["账号 ",M.length," 个,可用 ",Q,",无效 ",ee,",未验证 ",O]}),n.jsxs("small",{children:["可续期 ",ye," · 网页会话 ",ce," · 仅 Token ",St]}),n.jsxs("small",{children:["自动检测 ",h.lastCheckedAt?el(h.lastCheckedAt):"等待首次检测"]})]}),n.jsxs("div",{className:"channel-card-head-actions",children:[n.jsx(Dt,{tone:h.status,children:_t(h.status)}),n.jsx("button",{className:"primary-button compact-button",onClick:()=>K(h.id),disabled:V!=="",children:"添加账号"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>k(h.id),disabled:V!==""||M.length===0,children:V===`check:${h.id}`?"检测中":"批量检测"}),ee>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>k(h.id,!0),disabled:V!=="",children:V===`retry:${h.id}`?"复检中":`复检无效 ${ee}`}),M.length>1&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>H(h.id),disabled:V!=="",children:V===`dedupe:${h.id}`?"去重中":"账号去重"}),M.length>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>X(h),disabled:V!=="",children:"导出报告"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>se(h),disabled:V!=="",children:h.status==="disabled"?"启用渠道":"停用渠道"})]})]}),n.jsxs("div",{className:"account-filter-bar",role:"group","aria-label":"账号筛选",children:[n.jsx("input",{value:be[h.id]||"",onChange:B=>Y(Be=>({...Be,[h.id]:B.target.value})),placeholder:"搜索账号或错误","aria-label":"搜索账号"}),n.jsxs("select",{value:We,onChange:B=>P(Be=>({...Be,[h.id]:B.target.value})),"aria-label":"账号排序",children:[n.jsx("option",{value:"pool",children:"账号池顺序"}),n.jsx("option",{value:"oldest",children:"最久未用优先"}),n.jsx("option",{value:"recent",children:"最近使用优先"}),n.jsx("option",{value:"expiry",children:"最早到期优先"})]}),[["all",`全部 ${M.length}`],["attention","需关注"],["invalid",`无效 ${ee}`],["error",`有错误 ${Ne}`],["refreshable",`可续期 ${ye}`]].map(([B,Be])=>n.jsx("button",{type:"button",className:F===B?"selected":"",onClick:()=>ie(Fe=>({...Fe,[h.id]:B})),children:Be},B))]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(cl,{label:"账号总数",value:M.length}),n.jsx(cl,{label:"可用账号",value:Q}),n.jsx(cl,{label:"无效账号",value:ee}),n.jsx(cl,{label:"未验证账号",value:O})]}),n.jsx("div",{className:"drawing-channel-models",children:je(h.models).length?je(h.models).map(B=>n.jsx("span",{children:B},B)):n.jsx("span",{children:"未绑定绘图模型"})}),M.length>0&&n.jsxs("div",{className:"account-pool-list",children:[tl.map(B=>n.jsxs("div",{className:"account-pool-row",children:[n.jsxs("div",{className:"account-pool-main",children:[n.jsxs("div",{children:[n.jsxs("div",{className:"account-pool-title",children:[n.jsx("strong",{title:B.email||B.name||B.accountId||B.id,children:B.email||B.name||B.accountId||B.id}),n.jsx("span",{className:`source-tag source-tag-${B.source==="web-login"?"web":"manual"}`,children:B.source==="web-login"?"网页登录":B.source==="web-oauth"?"网页 OAuth":B.source==="oauth"?"Codex OAuth":B.source==="antigravity"||B.source==="agy"||B.source==="google-antigravity"?"Antigravity":"导入"})]}),n.jsx("span",{children:B.lastError?`${fm(B.lastErrorCode)}${fm(B.lastErrorCode)?" · ":""}${B.lastError}`:B.lastCheckedAt?`上次检测 ${el(B.lastCheckedAt)}`:"未检测"}),n.jsxs("span",{children:[B.credentialMode==="refreshable"?"可自动续期":B.credentialMode==="browser-session"?"依赖网页会话":"仅 access token",B.expiresAt?` · 到期 ${el(B.expiresAt)}`:""]}),n.jsxs("span",{children:["套餐 ",ap(B.planType)]}),B.lastUsedAt&&n.jsxs("span",{children:["最近调用 ",el(B.lastUsedAt)," · ",B.requestCount||0," 次"]})]}),n.jsx(wp,{limits:B.quotaLimits})]}),n.jsxs("div",{className:"account-pool-meta",children:[n.jsx(Dt,{tone:B.status==="healthy"?"healthy":B.status==="invalid"?"disabled":"standby",children:B.status==="healthy"?"可用":B.status==="invalid"?"无效":"未验证"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",disabled:V!=="",onClick:()=>k(h.id,!1,B.id),children:V===`check-account:${B.id}`?"检测中":"检测"}),n.jsx("button",{type:"button",className:"danger-button compact-button",disabled:V!=="",onClick:()=>m(h,B),children:V===`delete-account:${B.id}`?"删除中":"删除"})]})]},B.id)),rt.length===0&&n.jsx(kt,{text:"没有匹配的账号"}),bt.length>de&&n.jsxs("div",{className:"account-pool-more",children:[n.jsx("span",{className:"muted-inline",children:U?`已显示全部 ${bt.length} 个账号`:`已显示 ${tl.length} 个,还有 ${ll} 个`}),n.jsxs("div",{className:"account-pool-more-actions",children:[!U&&n.jsxs("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(B=>({...B,[h.id]:Math.min(bt.length,Ut+J)})),children:["再显示 ",Math.min(J,ll)," 个"]}),!U&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(B=>({...B,[h.id]:bt.length})),children:"全部显示"}),Ut>de&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(B=>({...B,[h.id]:de})),children:"收起"})]})]})]})]},h.id)}),z.length===0&&n.jsx(kt,{text:G?"暂无 Antigravity 渠道,先新增一个 Antigravity 账号池":"暂无绘图渠道,先新增一个 OpenAI 账号池渠道"})]}),he&&n.jsx(Rp,{channelId:he,onStart:$,onComplete:C,onClose:()=>_("")}),ue&&n.jsx(zp,{busy:V!=="",onAuthSession:()=>{me(ue),K("")},onAntigravity:()=>{Me(ue),K("")},onImport:async h=>{await N(ue,h),K("")},onClose:()=>K("")}),ne&&n.jsx(_p,{onImport:async h=>{await N(ne,new File([JSON.stringify(Op(h))],"authsession.json",{type:"application/json"}))},onClose:()=>me("")}),Ce&&n.jsx(Up,{onImport:async h=>{await N(Ce,new File([JSON.stringify(Dp(h))],"antigravity.json",{type:"application/json"}))},onClose:()=>Me("")})]})}function zp({busy:u,onAuthSession:f,onAntigravity:p,onImport:r,onClose:A}){return n.jsx("div",{className:"modal-backdrop",onClick:A,children:n.jsxs("div",{className:"modal-card account-add-modal",onClick:T=>T.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"添加账号"}),n.jsx("span",{children:"选择一种账号接入方式"})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:A,children:"×"})]}),n.jsxs("div",{className:"account-add-options",children:[n.jsxs("button",{type:"button",className:"account-add-option recommended",onClick:f,disabled:u,children:[n.jsx("span",{className:"account-add-icon",children:"A"}),n.jsx("strong",{children:"导入网页会话"}),n.jsx("small",{children:"粘贴完整 authsession JSON,保留 sessionToken"})]}),n.jsxs("button",{type:"button",className:"account-add-option",onClick:p,disabled:u,children:[n.jsx("span",{className:"account-add-icon",children:"G"}),n.jsx("strong",{children:"导入 Antigravity"}),n.jsx("small",{children:"粘贴 Google OAuth JSON 或 refresh token"})]}),n.jsxs("label",{className:`account-add-option${u?" disabled":""}`,children:[n.jsx("span",{className:"account-add-icon",children:"J"}),n.jsx("strong",{children:u?"导入中":"导入 JSON / ZIP / TXT"}),n.jsx("small",{children:"批量导入已有账号文件"}),n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:u,onChange:T=>{const L=T.target.files?.[0];L&&r(L),T.target.value=""}})]})]}),n.jsx("div",{className:"modal-actions",children:n.jsx("button",{type:"button",className:"secondary-button",onClick:A,children:"取消"})})]})})}function Op(u){const f=u.trim(),p=f.match(/(?:^|[;\s])(__Secure-(?:next-auth|authjs)\.session-token)=([^;\s]+)/);if(p)return{sessionToken:p[2],source:"web-login"};try{const r=JSON.parse(f),A=r.tokens&&typeof r.tokens=="object"?r.tokens:{},T=G=>typeof r[G]=="string"?r[G]:typeof A[G]=="string"?A[G]:"",L=T("accessToken")||T("access_token"),$=T("refreshToken")||T("refresh_token"),C=T("sessionToken")||T("session_token"),g=r.user&&typeof r.user=="object"?r.user:{};if(L||$||C)return{accessToken:L||void 0,refreshToken:$||void 0,sessionToken:C||void 0,email:typeof g.email=="string"?g.email:void 0,name:typeof g.name=="string"?g.name:void 0,source:"web-login"}}catch{}return{sessionToken:f,source:"web-login"}}function _p({onImport:u,onClose:f}){const[p,r]=b.useState(""),[A,T]=b.useState(!1),[L,$]=b.useState(""),[C,g]=b.useState("");async function G(){if(!p.trim()){$("请粘贴 authsession");return}T(!0),$(""),g("");try{await u(p.trim()),r(""),g("已导入,继续粘贴下一条即可")}catch(z){$(z instanceof Error?z.message:"导入失败")}finally{T(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:f,children:n.jsxs("div",{className:"modal-card",onClick:z=>z.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"添加网页会话"}),n.jsx("button",{type:"button",className:"icon-button",onClick:f,children:"×"})]}),n.jsxs("p",{className:"muted-inline",children:["可直接粘贴 chatgpt.com/api/auth/session 的完整 JSON;也支持浏览器 ",n.jsx("code",{children:"__Secure-next-auth.session-token"})," 的值或完整 Cookie 字符串。"]}),n.jsxs("label",{className:"authsession-field",children:[n.jsx("span",{children:"authsession"}),n.jsx("textarea",{autoFocus:!0,value:p,onChange:z=>r(z.target.value),placeholder:"eyJhbGci..."})]}),L&&n.jsx("div",{className:"form-error",children:L}),C&&n.jsx("div",{className:"form-success",children:C}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:f,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:A,onClick:G,children:A?"导入中":"导入账号"})]})]})})}function Dp(u){const f=u.trim();try{const p=JSON.parse(f),r=p.tokens&&typeof p.tokens=="object"?p.tokens:{},A=(...g)=>{for(const G of g){if(typeof p[G]=="string"&&p[G])return p[G];if(typeof r[G]=="string"&&r[G])return r[G]}return""},T=A("access_token","accessToken"),L=A("refresh_token","refreshToken"),$=A("email"),C=A("expired","expires_at","expiresAt","expiry");if(T||L)return{accessToken:T||void 0,refreshToken:L||void 0,email:$||void 0,expired:C||void 0,source:"antigravity"}}catch{}return{refreshToken:f,source:"antigravity"}}function Up({onImport:u,onClose:f}){const[p,r]=b.useState(""),[A,T]=b.useState(!1),[L,$]=b.useState(""),[C,g]=b.useState("");async function G(){if(!p.trim()){$("请粘贴 Antigravity OAuth JSON 或 refresh token");return}T(!0),$(""),g("");try{await u(p.trim()),r(""),g("已导入,继续粘贴下一条即可")}catch(z){$(z instanceof Error?z.message:"导入失败")}finally{T(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:f,children:n.jsxs("div",{className:"modal-card",onClick:z=>z.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"导入 Antigravity 账号"}),n.jsx("button",{type:"button",className:"icon-button",onClick:f,children:"×"})]}),n.jsxs("p",{className:"muted-inline",children:["粘贴 Antigravity 的 Google OAuth 凭证 JSON(含 ",n.jsx("code",{children:"access_token"})," / ",n.jsx("code",{children:"refresh_token"}),"),或直接粘贴 refresh token。导入后会自动刷新并加入账号池。"]}),n.jsxs("label",{className:"authsession-field",children:[n.jsx("span",{children:"OAuth JSON / refresh token"}),n.jsx("textarea",{autoFocus:!0,value:p,onChange:z=>r(z.target.value),placeholder:'{"access_token":"ya29...","refresh_token":"1//..."}'})]}),L&&n.jsx("div",{className:"form-error",children:L}),C&&n.jsx("div",{className:"form-success",children:C}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:f,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:A,onClick:G,children:A?"导入中":"导入账号"})]})]})})}function Rp({channelId:u,onStart:f,onComplete:p,onClose:r}){const[A,T]=b.useState(""),[L,$]=b.useState(""),[C,g]=b.useState(""),[G,z]=b.useState(!1),[V,W]=b.useState("");async function fe(){z(!0),W("");try{const ae=await f(u);T(ae.authorizeUrl),$(ae.state),window.open(ae.authorizeUrl,"_blank","noopener")}catch(ae){W(ae instanceof Error?ae.message:"发起授权失败")}finally{z(!1)}}async function te(){if(!C.trim()){W("请粘贴授权完成后浏览器跳转的回调地址");return}z(!0),W("");try{await p(u,{callbackUrl:C.trim(),state:L}),r()}catch(ae){W(ae instanceof Error?ae.message:"完成授权失败")}finally{z(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:r,children:n.jsxs("div",{className:"modal-card",onClick:ae=>ae.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"OAuth 授权添加网页账号"}),n.jsx("button",{type:"button",className:"icon-button",onClick:r,children:"×"})]}),n.jsx("p",{className:"muted-inline",children:"使用 ChatGPT 网页兼容的 OAuth 客户端获取 refresh_token,只调用网页 backend-api,不会走 Codex 接口。"}),n.jsxs("ol",{className:"oauth-steps",children:[n.jsxs("li",{children:[n.jsx("button",{type:"button",className:"primary-button",onClick:fe,disabled:G,children:A?"重新生成授权链接":"① 生成授权链接并打开"}),A&&n.jsxs("div",{className:"oauth-link",children:[n.jsx("input",{readOnly:!0,value:A,onFocus:ae=>ae.target.select()}),n.jsx("span",{className:"muted-inline",children:"若未自动打开,复制到浏览器手动访问,用要添加的 ChatGPT 账号登录授权。"})]})]}),n.jsxs("li",{children:[n.jsx("label",{children:"② 粘贴授权后浏览器跳转的完整回调地址"}),n.jsx("input",{value:C,placeholder:"https://platform.openai.com/auth/callback?code=...&state=...",onChange:ae=>g(ae.target.value),disabled:!A||G})]})]}),V&&n.jsx("p",{className:"form-error",children:V}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:r,disabled:G,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",onClick:te,disabled:!A||G,children:G?"处理中":"完成授权"})]})]})})}function wp({limits:u}){const f=je(u).filter(p=>p.label||p.name).slice(0,3);return f.length?n.jsx("div",{className:"quota-bars",children:f.map(p=>{const r=Hp(p);return n.jsxs("div",{className:"quota-bar",children:[n.jsxs("div",{className:"quota-bar-label",children:[n.jsx("strong",{children:p.label||p.name}),n.jsx("span",{children:Bp(p,r)})]}),n.jsx("div",{className:"quota-bar-track",children:n.jsx("span",{style:{width:`${r}%`}})})]},`${p.label||p.name}-${p.resetAt||""}`)})}):null}function Hp(u){return typeof u.percentRemaining=="number"&&Number.isFinite(u.percentRemaining)?Math.max(0,Math.min(100,u.percentRemaining)):typeof u.remaining=="number"&&typeof u.limit=="number"&&u.limit>0?Math.max(0,Math.min(100,u.remaining/u.limit*100)):typeof u.used=="number"&&typeof u.limit=="number"&&u.limit>0?Math.max(0,Math.min(100,(u.limit-u.used)/u.limit*100)):0}function Bp(u,f){const p=u.resetAt?` · ${el(u.resetAt)}`:"";return typeof u.remaining=="number"?`${Math.round(f)}% 剩余${p}`:`${Math.round(f)}%${p}`}function qp(u){const f=je(u.models).join(" ").toLowerCase(),p=["对话"];u.streamMode!=="disabled"&&p.push("流式"),/(image|dall-e|gpt-image)/.test(f)&&p.push("图片"),(u.openaiAccountCount??u.openaiAccounts?.length??0)>0&&p.push("账号池");const r=u.upstreamKeyCount??0;return r>1&&p.push(`${r} Key 轮询`),p}function Gp(u){if(u.status==="invalid"||u.credentialMode==="browser-session")return!0;if(!u.expiresAt)return!1;const f=new Date(u.expiresAt).getTime();return Number.isFinite(f)&&f-Date.now()<=1440*60*1e3}function Yp({channels:u,groups:f,onUpdate:p,onCreate:r,onImport:A,onDelete:T,onSyncModels:L,onCheck:$}){const C=Ta("openai"),[g,G]=b.useState(!1),[z,V]=b.useState(C.provider),[W,fe]=b.useState(C.name),[te,ae]=b.useState(C.baseUrl),[ie,be]=b.useState(C.models.join(", ")),[Y,xe]=b.useState(""),[P,he]=b.useState(""),[_,ne]=b.useState(!1),[me,Ce]=b.useState(!1);function Me(K){const de=Ta(K);V(de.provider),fe(de.name),ae(de.baseUrl),be(de.models.join(", ")),he("")}async function ue(K){K.preventDefault(),ne(!0),he("");try{await r({name:W.trim()||Ta(z).name,provider:z,baseUrl:te.trim(),...Nm(Y),models:Pc(ie),streamMode:"auto"}),G(!1),xe(""),Me(z)}catch(de){he(de instanceof Error?de.message:"渠道创建失败")}finally{ne(!1)}}return n.jsxs(at,{title:"渠道",children:[n.jsxs("div",{className:"channel-page-intro",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"管理上游服务"}),n.jsx("span",{children:"每个渠道对应一个 API 上游。先添加渠道,再检测连通性并同步可用模型。"})]}),n.jsxs("div",{className:"channel-page-summary",children:[n.jsxs("span",{children:[n.jsx("b",{children:u.length})," 个渠道"]}),n.jsxs("span",{children:[n.jsx("b",{children:u.filter(K=>K.status!=="disabled").length})," 个已启用"]})]})]}),n.jsxs("div",{className:"panel-toolbar channel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"列表显示当前状态;点击任一渠道可修改连接、模型和计费设置。"}),n.jsx("button",{className:"primary-button",onClick:()=>G(K=>!K),children:g?"取消新增":"+ 新增渠道"})]}),g&&n.jsxs("form",{className:"channel-card channel-create-form",onSubmit:ue,children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"选择渠道类型"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:Ta(z).label}),n.jsx("small",{children:"选择后自动填入建议配置"})]}),n.jsx("div",{role:"listbox","aria-label":"选择渠道类型",children:Fc.map(K=>n.jsxs("button",{type:"button",className:z===K.provider?"selected":"",onClick:de=>{Me(K.provider),de.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:K.label}),n.jsx("span",{children:"使用推荐的名称和地址"})]},K.provider))})]})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:W,onChange:K=>fe(K.target.value),placeholder:"例如 OpenAI 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:ul(z),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:te,onChange:K=>ae(K.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"上游 Key"}),n.jsx("textarea",{className:"channel-key-input",value:Y,onChange:K=>xe(K.target.value),placeholder:z==="codex"?"账号池导入后使用":z==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发",autoComplete:"off",rows:3})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsx("button",{type:"button",className:"model-pull-button",onClick:()=>{if(z!=="codex"&&!te.trim()){he("请先填写 Base URL 再获取模型");return}he(""),Ce(!0)},children:"从上游获取模型"})]}),n.jsx("textarea",{value:ie,onChange:K=>be(K.target.value),placeholder:"多个模型用逗号分隔,或点上方『从上游获取模型』拉取后多选"})]})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("span",{className:"model-create-message",role:"status",children:P}),n.jsx("button",{className:"secondary-button",type:"button",onClick:()=>Me(z),disabled:_,children:"填入模板"}),n.jsx("button",{className:"primary-button",type:"submit",disabled:_,children:_?"创建中":"创建渠道"})]})]}),g&&me&&n.jsx(Am,{subtitle:`${W.trim()||Ta(z).name} · 勾选需要接入的模型`,current:Pc(ie),loadModels:async()=>{const K=await ve("/api/channel-model-preview",{method:"POST",body:JSON.stringify({provider:z,baseUrl:te.trim(),upstreamApiKey:Y})});return je(K.models)},onConfirm:async K=>{be(K.join(", "))},onClose:()=>Ce(!1)}),n.jsxs("div",{className:"channels-stack",children:[u.map(K=>n.jsx(Lp,{channel:K,groups:f,onUpdate:p,onImport:A,onDelete:T,onSyncModels:L,onCheck:$},K.id)),u.length===0&&n.jsx(kt,{text:"暂无渠道,先在后端添加渠道接口或导入配置"})]})]})}function Lp({channel:u,groups:f,onUpdate:p,onImport:r,onDelete:A,onSyncModels:T,onCheck:L}){const[$,C]=b.useState(u.name),[g,G]=b.useState(u.provider),[z,V]=b.useState(u.streamMode||"auto"),[W,fe]=b.useState(u.baseUrl),[te,ae]=b.useState(je(u.allowedGroupIds)),[ie,be]=b.useState(je(u.models).join(", ")),[Y,xe]=b.useState("saved"),[P,he]=b.useState(String(u.inputPricePer1K||0)),[_,ne]=b.useState(String(u.outputPricePer1K||0)),[me,Ce]=b.useState(!!u.webEndpoint),[Me,ue]=b.useState(""),[K,de]=b.useState(""),[J,N]=b.useState(!1),k=u.openaiAccountCount??u.openaiAccounts?.length??0,H=je(u.models).length,X=qp(u),se=u.status==="disabled",m={saved:"已保存",template:"模板",manual:"手动",synced:"上游同步"}[Y],h=Ni.find(F=>F.value===z)||Ni[0],M={auto:"自动处理(推荐)",real:"强制流式",fake:"兼容流式",disabled:"关闭流式"};b.useEffect(()=>{C(u.name),G(u.provider),V(u.streamMode||"auto"),fe(u.baseUrl),ae(je(u.allowedGroupIds)),be(je(u.models).join(", ")),xe("saved"),he(String(u.inputPricePer1K||0)),ne(String(u.outputPricePer1K||0)),Ce(!!u.webEndpoint),ue("")},[u.id,u.name,u.provider,u.streamMode,u.baseUrl,u.models,u.inputPricePer1K,u.outputPricePer1K,u.webEndpoint]);async function Q(){const F=ee();de("save");try{await p(u.id,F),ue("")}finally{de("")}}function ee(){const F=Ei(g),$e=!/^https?:\/\//i.test(W.trim())&&F?F:W,rt={name:$.trim()||u.name,provider:g,streamMode:z,baseUrl:$e,inputPricePer1K:Number(P)||0,outputPricePer1K:Number(_)||0,webEndpoint:me,models:ie.split(",").map(We=>We.trim()).filter(Boolean),allowedGroupIds:te};return Object.assign(rt,Nm(Me)),rt}async function Ne(){const F=u.status==="disabled"?"healthy":"disabled";de("status");try{await p(u.id,{...ee(),status:F}),ue("")}finally{de("")}}async function O(){de("sync");try{await p(u.id,ee()),ue(""),N(!0)}finally{de("")}}function ye(){const F=Ta(g);be(F.models.join(", ")),xe("template"),F.baseUrl&&!/^https?:\/\//i.test(W.trim())&&fe(F.baseUrl)}async function ce(){de("check");try{await Q(),await L(u.id)}finally{de("")}}async function St(F){de("import");try{await r(u.id,F)}finally{de("")}}return n.jsxs(n.Fragment,{children:[n.jsxs("details",{className:"channel-card channel-card-collapsible",children:[n.jsxs("summary",{className:"channel-card-head channel-list-row",children:[n.jsxs("div",{className:"channel-identity",children:[n.jsx("strong",{children:u.name}),n.jsx("span",{children:ul(g)}),n.jsx("small",{children:u.baseUrl||"尚未配置上游地址"}),n.jsx("div",{className:"channel-capability-tags",children:X.map(F=>n.jsx("span",{children:F},F))})]}),n.jsxs("div",{className:"channel-list-meta",children:[n.jsxs("span",{children:[n.jsx("b",{children:H})," 个模型"]}),k>0&&n.jsxs("span",{children:[n.jsx("b",{children:k})," 个账号"]})]}),n.jsxs("div",{className:"channel-check-result",children:[n.jsx("span",{children:"连通性"}),n.jsx("b",{className:u.lastError?"is-error":u.lastCheckedAt?"is-ok":"",children:u.lastError?"检测失败":u.lastCheckedAt?`已检测 ${el(u.lastCheckedAt)}`:"尚未检测"})]}),n.jsxs("div",{className:"channel-list-status",children:[n.jsx(Dt,{tone:u.status,children:se?"已停用":_t(u.status)}),n.jsx("span",{className:"channel-expand-hint",children:"配置"})]})]}),n.jsxs("div",{className:"channel-editor-controls",children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"供应商"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:ul(g)}),n.jsx("small",{children:"修改上游协议类型"})]}),n.jsx("div",{role:"listbox","aria-label":"供应商",children:to.map(F=>n.jsxs("button",{type:"button",className:g===F.value?"selected":"",onClick:$e=>{G(F.value);const rt=Ei(F.value);rt&&!/^https?:\/\//i.test(W.trim())&&fe(rt),$e.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:F.label}),n.jsx("span",{children:F.value==="compatible"?"适用于兼容 OpenAI 格式的服务":"选择对应的上游协议"})]},F.value))})]})]}),n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"响应方式"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:M[h.value]}),n.jsx("small",{children:h.description})]}),n.jsx("div",{role:"listbox","aria-label":"响应方式",children:Ni.map(F=>n.jsxs("button",{type:"button",className:z===F.value?"selected":"",onClick:$e=>{V(F.value),$e.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:M[F.value]}),n.jsx("span",{children:F.description})]},F.value))})]})]})]}),(g==="codex"||k>0)&&n.jsxs("div",{className:"setting",children:[n.jsxs("div",{children:[n.jsx("span",{children:"网页对话接口"}),n.jsx("small",{children:"开启后走 ChatGPT 网页对话接口,把 Plus 订阅账号包装成 API"})]}),n.jsx("div",{className:"setting-value",children:n.jsx("button",{type:"button",className:me?"ios-switch is-on":"ios-switch","aria-label":me?"关闭网页对话接口":"开启网页对话接口","aria-pressed":me,onClick:()=>Ce(F=>!F),children:n.jsx("span",{})})})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:$,onChange:F=>C(F.target.value),placeholder:"例如 Gemini 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:ul(g),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:W,onChange:F=>fe(F.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"优先级"}),n.jsx("input",{value:u.priority,readOnly:!0})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsxs("small",{children:["来源:",m]})]}),n.jsx("textarea",{value:ie,onChange:F=>{be(F.target.value),xe("manual")},placeholder:"优先拉取上游模型,也可以手动补充,多个用逗号分隔"}),n.jsxs("div",{className:"channel-model-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:ye,disabled:K!=="",children:"填入模板"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:O,disabled:K!=="",children:K==="sync"?"拉取中":"获取上游模型"})]})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsxs("span",{children:["上游 Key",(u.upstreamKeyCount??0)>0?` (已配置 ${u.upstreamKeyCount} 个)`:u.upstreamKeySet?" (已配置)":""]}),n.jsx("textarea",{className:"channel-key-input",value:Me,onChange:F=>ue(F.target.value),placeholder:g==="codex"?"Codex 账号池不需要上游 Key":g==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发;留空不修改",autoComplete:"off",rows:3})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输入单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:P,onChange:F=>he(F.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输出单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:_,onChange:F=>ne(F.target.value)})]}),n.jsx("span",{className:"channel-billing-note",children:"定价可先留空;接入是否可用优先看渠道检测和模型同步结果。"})]}),n.jsxs("div",{className:"channel-group-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"可见分组"}),n.jsx("small",{children:te.length?`已选择 ${te.length} 个分组`:"全部用户可用"})]}),f.length===0?n.jsx("p",{className:"channel-group-empty",children:"还没有用户分组。去「分组」页创建后,可在这里把渠道限制为只对特定分组开放。"}):n.jsx("div",{className:"channel-group-options",children:f.map(F=>{const $e=te.includes(F.id);return n.jsxs("button",{type:"button",className:$e?"selected":"","aria-pressed":$e,onClick:()=>ae(rt=>$e?rt.filter(We=>We!==F.id):[...rt,F.id]),children:[n.jsx("span",{children:F.name}),F.description&&n.jsx("small",{children:F.description})]},F.id)})})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("button",{className:"secondary-button",onClick:ce,disabled:K!=="",children:K==="check"?"检测中":"检测渠道"}),n.jsx("button",{className:"primary-button",onClick:Q,disabled:K!=="",children:K==="save"?"保存中":"保存"}),n.jsxs("details",{className:"channel-more-actions",children:[n.jsx("summary",{children:"更多操作"}),n.jsxs("div",{children:[n.jsxs("label",{className:"secondary-button",children:[K==="import"?"导入中":"导入账号 JSON",n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:K!=="",onChange:F=>{const $e=F.target.files?.[0];$e&&St($e),F.target.value=""}})]}),n.jsx("button",{className:"secondary-button",onClick:Ne,disabled:K!=="",children:u.status==="disabled"?"启用渠道":"停用渠道"}),n.jsx("button",{className:"danger-button",onClick:()=>A(u.id),disabled:K!=="",children:"删除渠道"})]})]})]})]}),J&&n.jsx(Am,{subtitle:`${u.name} · 勾选需要接入的模型`,current:ie.split(",").map(F=>F.trim()).filter(Boolean),loadModels:async()=>{const F=await ve(`/api/channels/${u.id}/upstream-models`,{method:"POST",body:JSON.stringify({})});return je(F.models)},onConfirm:async F=>{await T(u.id,F)},onClose:()=>N(!1)})]})}function Am({subtitle:u,current:f,loadModels:p,onConfirm:r,onClose:A}){const[T,L]=b.useState(!0),[$,C]=b.useState(""),[g,G]=b.useState([]),[z,V]=b.useState(new Set),[W,fe]=b.useState(""),[te,ae]=b.useState(!1);b.useEffect(()=>{let _=!1;return(async()=>{L(!0),C("");try{const ne=await p();if(_)return;const me=new Set,Ce=je(ne).map(ue=>ue.trim()).filter(ue=>{if(!ue)return!1;const K=ue.toLowerCase();return me.has(K)?!1:(me.add(K),!0)}),Me=new Set(f.map(ue=>ue.toLowerCase()));G(Ce),V(new Set(Ce.filter(ue=>Me.has(ue.toLowerCase()))))}catch(ne){_||C(ne instanceof Error?ne.message:"获取上游模型失败")}finally{_||L(!1)}})(),()=>{_=!0}},[]);const ie=W.trim().toLowerCase(),be=ie?g.filter(_=>_.toLowerCase().includes(ie)):g,Y=be.length>0&&be.every(_=>z.has(_));function xe(_){V(ne=>{const me=new Set(ne);return me.has(_)?me.delete(_):me.add(_),me})}function P(){V(_=>{const ne=new Set(_);return Y?be.forEach(me=>ne.delete(me)):be.forEach(me=>ne.add(me)),ne})}async function he(){const _=new Set(g.map(ue=>ue.toLowerCase())),ne=f.filter(ue=>!_.has(ue.toLowerCase())),me=g.filter(ue=>z.has(ue)),Ce=new Set,Me=[...ne,...me].filter(ue=>{const K=ue.toLowerCase();return Ce.has(K)?!1:(Ce.add(K),!0)});ae(!0);try{await r(Me),A()}catch{ae(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:A,children:n.jsxs("div",{className:"modal-card model-picker-modal",onClick:_=>_.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"选择上游模型"}),n.jsx("span",{children:u})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:A,children:"×"})]}),T?n.jsx("div",{className:"model-picker-status",children:"正在获取上游模型…"}):$?n.jsx("div",{className:"model-picker-status model-picker-error",children:$}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"model-picker-toolbar",children:[n.jsx("input",{className:"model-picker-search",value:W,onChange:_=>fe(_.target.value),placeholder:"搜索模型名称",autoFocus:!0}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:P,disabled:be.length===0,children:Y?"取消全选":"全选"})]}),n.jsxs("div",{className:"model-picker-count",children:["共 ",g.length," 个 · 已选 ",z.size," 个",ie?` · 匹配 ${be.length} 个`:""]}),n.jsxs("div",{className:"model-picker-list",children:[be.map(_=>{const ne=z.has(_),me=f.some(Ce=>Ce.toLowerCase()===_.toLowerCase());return n.jsxs("label",{className:`model-picker-row${ne?" checked":""}`,children:[n.jsx("input",{type:"checkbox",checked:ne,onChange:()=>xe(_)}),n.jsx("span",{className:"model-picker-name",children:_}),me&&n.jsx("span",{className:"model-picker-tag",children:"已接入"})]},_)}),be.length===0&&n.jsx("div",{className:"model-picker-status",children:"没有匹配的模型"})]})]}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:A,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:T||!!$||te,onClick:he,children:te?"保存中":`导入所选 (${z.size})`})]})]})})}function kp({logs:u,onCopy:f}){const[p,r]=b.useState(u),[A,T]=b.useState(u.length),[L,$]=b.useState(1),[C,g]=b.useState(""),[G,z]=b.useState("all"),[V,W]=b.useState(null),[fe,te]=b.useState(!1),[ae,ie]=b.useState(!1),be=25,Y=Math.max(1,Math.ceil(A/be));b.useEffect(()=>{$(1)},[C,G]),b.useEffect(()=>{L>Y&&$(Y)},[L,Y]),b.useEffect(()=>{const P=new AbortController,he=window.setTimeout(async()=>{te(!0);try{const _=new URLSearchParams({page:String(L),pageSize:String(be),status:G,q:C.trim()}),ne=await ve(`/api/logs?${_}`,{signal:P.signal}),me=je(ne.logs);r(me),T(ne.total||0),W(Ce=>Ce&&me.some(Me=>Me.id===Ce.id)?Ce:null)}catch(_){_ instanceof DOMException&&_.name==="AbortError"||(r([]),T(0))}finally{P.signal.aborted||te(!1)}},C?250:0);return()=>{window.clearTimeout(he),P.abort()}},[L,C,G]);async function xe(P){if(V?.id===P.id){W(null);return}W(P),ie(!0);try{const he=await ve(`/api/logs/${encodeURIComponent(P.id)}`);W(he.log)}catch{W(P)}finally{ie(!1)}}return n.jsxs(at,{title:"调用日志",children:[n.jsxs("div",{className:"logs-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Ot,{name:"search"}),n.jsx("input",{value:C,onChange:P=>g(P.target.value),placeholder:"搜索请求 ID、用户、Key、模型、渠道或错误码"})]}),n.jsx("div",{className:"log-status-filter",role:"group","aria-label":"日志状态筛选",children:[{value:"all",label:"全部"},{value:"success",label:"成功"},{value:"failed",label:"失败"}].map(P=>n.jsx("button",{type:"button",className:G===P.value?"selected":"",onClick:()=>z(P.value),children:P.label},P.value))}),n.jsx("span",{className:"muted-inline",children:fe?"加载中":`共 ${A} 条`})]}),n.jsxs("div",{className:V?"logs-layout has-detail":"logs-layout",children:[n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head logs-table",children:[n.jsx("span",{children:"请求"}),n.jsx("span",{children:"模型"}),n.jsx("span",{children:"渠道"}),n.jsx("span",{children:"状态"})]}),p.map(P=>n.jsx("div",{className:"log-entry",children:n.jsxs("div",{className:V?.id===P.id?"table-row logs-table selected":"table-row logs-table",role:"button",tabIndex:0,onClick:()=>xe(P),onKeyDown:he=>{(he.key==="Enter"||he.key===" ")&&xe(P)},children:[n.jsxs("span",{children:[n.jsx("strong",{children:lo(P)}),n.jsxs("small",{children:[P.id," · ",el(P.createdAt)," · ",P.latencyMs,"ms"]})]}),n.jsx("span",{children:up(P)}),n.jsx("span",{children:cp(P)}),n.jsx(Dt,{tone:P.status,children:_t(P.status)})]})},P.id)),!fe&&p.length===0&&n.jsx(kt,{text:C||G!=="all"?"没有匹配的日志":"暂无调用日志"})]}),V&&n.jsx(Qp,{log:V,loading:ae,onCopy:f})]}),Y>1&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:L<=1||fe,onClick:()=>$(P=>Math.max(1,P-1)),children:"上一页"}),n.jsxs("span",{children:[L," / ",Y]}),n.jsx("button",{className:"secondary-button",disabled:L>=Y||fe,onClick:()=>$(P=>Math.min(Y,P+1)),children:"下一页"})]})]})}function Qp({log:u,loading:f,onCopy:p}){if(!u)return n.jsx("aside",{className:"log-inspector empty-inspector",children:n.jsx("span",{children:"选择一条日志查看详情"})});const r=Number(u.inputTokens||0),A=Number(u.outputTokens||0),T=typeof u.attempts=="number"?Math.max(0,u.attempts):null,L=[["请求 ID",u.id],["状态",_t(u.status)],["时间",ip(u.createdAt)],["用户 ID",u.userId||"未识别"],["API Key",u.apiKeyPrefix?`${u.apiKeyPrefix}***`:"未识别"],["模型",u.model||"未提供"],["渠道",u.channel||"未选择"],["实际账号",u.account||"未记录"],["响应耗时",`${u.latencyMs} ms`],["尝试次数",T===null?"未记录":String(T)],["是否重试",T===null?"未记录":T>1?"是":"否"],["输入 Tokens",ml(r)],["输出 Tokens",ml(A)],["总 Tokens",ml(r+A)],["扣费",u.cost.toFixed(4)],["错误码",u.errorCode||"无"]];return n.jsxs("aside",{className:"log-inspector",children:[n.jsxs("header",{children:[n.jsxs("div",{children:[n.jsx("span",{children:f?"加载中":"日志详情"}),n.jsx("strong",{children:lo(u)})]}),n.jsx(Dt,{tone:u.status,children:_t(u.status)})]}),n.jsx("div",{className:"log-detail",children:L.map(([$,C])=>n.jsxs("div",{children:[n.jsx("span",{children:$}),n.jsx("strong",{title:C,children:C})]},$))}),n.jsxs("div",{className:"log-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>p(u.id,"请求 ID 已复制"),children:"复制请求 ID"}),u.errorCode&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>p(u.errorCode||"","错误码已复制"),children:"复制错误码"})]})]})}function Xp({models:u,channels:f,groups:p}){const[r,A]=b.useState(null),[T,L]=b.useState(null),[$,C]=b.useState("username"),[g,G]=b.useState("0"),[z,V]=b.useState(""),[W,fe]=b.useState({enabled:!0,minReward:.1,maxReward:1}),[te,ae]=b.useState({logRetentionDays:30,maxLogs:1e4,maxQuotaEntries:2e4}),[ie,be]=b.useState(null),[Y,xe]=b.useState(null),[P,he]=b.useState(""),[_,ne]=b.useState(""),[me,Ce]=b.useState(""),[Me,ue]=b.useState(""),[K,de]=b.useState(""),[J,N]=b.useState(""),[k,H]=b.useState(""),[X,se]=b.useState(""),[m,h]=b.useState(""),[M,Q]=b.useState(!1),[ee,Ne]=b.useState("system"),O=u.find(U=>U.recommended&&U.status==="available")?.id||u.find(U=>U.status==="available")?.id||"未配置",ye=f.filter(U=>U.status!=="disabled").length,ce=[{value:"system",label:"系统",description:"运行概况"},{value:"cli",label:"CLI 接入",description:"一键配置"},{value:"auth",label:"注册",description:"开放方式"},{value:"check-in",label:"签到",description:"奖励范围"},{value:"admin",label:"管理员",description:"账号绑定"},{value:"discord",label:"Discord",description:"登录限制"},{value:"maintenance",label:"维护",description:"日志保留"},{value:"backup",label:"备份",description:"导出恢复"}],St=ce.find(U=>U.value===ee)||ce[0];b.useEffect(()=>{Promise.all([ve("/api/settings/discord"),ve("/api/settings/auth"),ve("/api/settings/check-in"),ve("/api/account/me"),ve("/api/settings/maintenance"),ve("/api/health")]).then(([U,B,Be,Fe,nt,et])=>{A(Wc(U.discord)),se(je(U.discord.blockedGuildIds).join(` +`)),L(B.auth.registrationEnabled),C(Mi(B.auth.registrationMode)),G(String(B.auth.defaultBalance||0)),V(B.auth.defaultGroupId||""),fe(Be.checkIn),xe(Fe.account),he(Fe.account?.username||""),ne(Fe.user.name||""),Ce(Fe.account?.email||""),ue(Fe.account?.discordUserId||""),ae(nt.maintenance),be(et)}).catch(()=>h("设置加载失败"))},[]);async function F(U=T,B=$,Be=Number(g),Fe=z){if(U!==null)try{const nt=await ve("/api/settings/auth",{method:"PATCH",body:JSON.stringify({registrationEnabled:U,registrationMode:B,defaultBalance:Be,defaultGroupId:Fe})});L(nt.auth.registrationEnabled),C(Mi(nt.auth.registrationMode)),G(String(nt.auth.defaultBalance||0)),V(nt.auth.defaultGroupId||""),h(nt.auth.registrationEnabled?"注册设置已保存":"已关闭用户注册")}catch(nt){h(nt instanceof Error?nt.message:"注册设置保存失败")}}async function $e(){T!==null&&F(!T,$)}async function rt(){Q(!0),h("");try{const U=await ve("/api/settings/check-in",{method:"PATCH",body:JSON.stringify(W)});fe(U.checkIn),h(U.checkIn.enabled?"签到奖励设置已保存":"已关闭每日签到")}catch(U){h(U instanceof Error?U.message:"签到设置保存失败")}finally{Q(!1)}}async function We(){if(r){Q(!0),h("");try{const U=Wc(r),B=X.split(/[\s,]+/).map(Fe=>Fe.trim()).filter(Boolean),Be=await ve("/api/settings/discord",{method:"PATCH",body:JSON.stringify({...U,blockedGuildIds:B,clientSecret:k})});A(Wc(Be.discord)),se(je(Be.discord.blockedGuildIds).join(` +`)),H(""),h("Discord 配置已保存")}catch(U){h(U instanceof Error?U.message:"保存失败,请检查填写内容")}finally{Q(!1)}}}async function bt(){try{const U=await ve("/api/account/profile",{method:"PATCH",body:JSON.stringify({username:P,displayName:_,email:me,discordUserId:Me,currentPassword:K,newPassword:J})});xe(U.account),he(U.account.username),Ce(U.account.email||""),ue(U.account.discordUserId||""),de(""),N(""),h("管理员账号已保存")}catch(U){h(U instanceof Error?U.message:"账号设置保存失败")}}async function Ut(){Q(!0),h("");try{const U=await ve("/api/settings/maintenance",{method:"PATCH",body:JSON.stringify(te)});ae(U.maintenance),h("维护设置已保存,历史数据已按新规则清理")}catch(U){h(U instanceof Error?U.message:"维护设置保存失败")}finally{Q(!1)}}async function tl(){Q(!0),h("");try{const U=await fetch("/api/backup",{credentials:"include"});if(!U.ok)throw new Error("备份导出失败");const B=await U.blob(),Fe=(U.headers.get("Content-Disposition")||"").match(/filename="([^"]+)"/)?.[1]||"capi-backup.json",nt=URL.createObjectURL(B),et=document.createElement("a");et.href=nt,et.download=Fe,et.click(),URL.revokeObjectURL(nt),h("备份已导出,请妥善保管")}catch(U){h(U instanceof Error?U.message:"备份导出失败")}finally{Q(!1)}}async function ll(U){if(window.confirm("恢复会覆盖当前全部数据,并退出现有登录会话。确定继续?")){Q(!0),h("");try{const B=await fetch("/api/restore",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:U}),Be=await B.json().catch(()=>null);if(!B.ok)throw new Error(Be?.error?.message||"备份恢复失败");h(`已恢复 ${Be.users} 个用户、${Be.channels} 条渠道和 ${Be.models} 个模型,请重新登录`)}catch(B){h(B instanceof Error?B.message:"备份恢复失败")}finally{Q(!1)}}}return n.jsxs("div",{className:"settings-layout",children:[n.jsx("div",{className:"settings-tabs",children:ce.map(U=>n.jsxs("button",{type:"button",className:ee===U.value?"selected":"",onClick:()=>Ne(U.value),children:[n.jsx("strong",{children:U.label}),n.jsx("small",{children:U.description})]},U.value))}),n.jsxs("div",{className:"settings-tab-note",children:[n.jsx("strong",{children:St.label}),n.jsx("span",{children:St.description})]}),ee==="system"&&n.jsx(at,{title:"系统设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsx(Pt,{label:"接口兼容",value:"OpenAI API"}),n.jsx(Pt,{label:"当前默认模型",value:O}),n.jsx(Pt,{label:"已配置渠道",value:`${f.length} 个,${ye} 个启用`}),n.jsx(Pt,{label:"可选供应商",value:`${to.length} 种`}),n.jsx(Pt,{label:"运行版本",value:`${ie?.version||"未知"} · ${ie?.commit||"未知"}`}),n.jsx(Pt,{label:"构建时间",value:ie?.buildTime?el(ie.buildTime):"本地构建"}),n.jsx(Pt,{label:"账号自动检测",value:"每 15 分钟自动检测一次"})]})}),ee==="cli"&&n.jsxs(at,{title:"CLI 工具接入",children:[n.jsx("p",{className:"cli-intro",children:"CAPI 兼容 OpenAI 和 Anthropic 协议,常见 AI 命令行工具可直接接入。"}),n.jsxs("div",{className:"cli-credentials",children:[n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"Base URL"}),n.jsx("code",{children:Ul()}),n.jsx("button",{type:"button",className:"copy-button","aria-label":"复制",onClick:()=>{Ai(Ul()),h("已复制 Base URL")},children:n.jsx(Ot,{name:"copy"})})]}),n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"API Key"}),n.jsx("code",{children:"cat_你的_api_key"})]})]}),n.jsxs("div",{className:"cli-tools",children:[n.jsxs("details",{className:"cli-tool",open:!0,children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Claude Code"}),n.jsx("span",{children:"Anthropic Messages 协议"})]}),n.jsx("pre",{children:`export ANTHROPIC_BASE_URL="${Ul()}" +export ANTHROPIC_AUTH_TOKEN="cat_你的_api_key" +export ANTHROPIC_MODEL="${O}" +claude`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Codex CLI"}),n.jsx("span",{children:"OpenAI Chat 协议"})]}),n.jsxs("p",{children:["编辑 ",n.jsx("code",{children:"~/.codex/config.toml"}),":"]}),n.jsx("pre",{children:`model = "${O}" +model_provider = "capi" + +[model_providers.capi] +name = "CAPI" +base_url = "${Ul()}/v1" +env_key = "CAPI_KEY" +wire_api = "chat"`}),n.jsx("p",{children:"然后设置环境变量并运行:"}),n.jsx("pre",{children:`export CAPI_KEY="cat_你的_api_key" +codex`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Aider"}),n.jsx("span",{children:"OpenAI 兼容"})]}),n.jsx("pre",{children:`export OPENAI_API_BASE="${Ul()}" +export OPENAI_API_KEY="cat_你的_api_key" +aider --model openai/${O}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Cline / Roo Code / Kilo Code"}),n.jsx("span",{children:"VS Code 插件"})]}),n.jsxs("p",{children:["在插件设置中选择 ",n.jsx("strong",{children:"OpenAI Compatible"}),":"]}),n.jsx("pre",{children:`Base URL: ${Ul()}/v1 +API Key: cat_你的_api_key +Model ID: ${O}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"通用 OpenAI SDK"}),n.jsx("span",{children:"Python / Node.js"})]}),n.jsx("pre",{children:`export OPENAI_BASE_URL="${Ul()}" +export OPENAI_API_KEY="cat_你的_api_key"`}),n.jsx("pre",{children:`from openai import OpenAI +client = OpenAI() +response = client.chat.completions.create( + model="${O}", + messages=[{"role": "user", "content": "hello"}] +)`})]})]}),m&&n.jsx("p",{className:"cli-message",role:"status",children:m})]}),ee==="maintenance"&&n.jsx(at,{title:"维护设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志保留天数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"1",max:"3650",value:te.logRetentionDays,onChange:U=>ae(B=>({...B,logRetentionDays:Number(U.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"1000000",step:"100",value:te.maxLogs,onChange:U=>ae(B=>({...B,maxLogs:Number(U.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"额度流水最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"2000000",step:"100",value:te.maxQuotaEntries,onChange:U=>ae(B=>({...B,maxQuotaEntries:Number(U.target.value)}))})})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:m}),n.jsx("button",{type:"button",className:"primary-button",disabled:M,onClick:Ut,children:M?"保存中":"保存维护设置"})]})]})}),ee==="backup"&&n.jsx(at,{title:"备份与恢复",children:n.jsx("div",{className:"settings-group",children:n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["备份与恢复",n.jsx("small",{children:"包含账号哈希和加密后的上游密钥,恢复时需要相同的 SECRET_KEY"})]}),n.jsxs("div",{className:"setting-value backup-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",disabled:M,onClick:tl,children:"导出备份"}),n.jsxs("label",{className:"secondary-button",children:["恢复备份",n.jsx("input",{type:"file",accept:"application/json,.json",disabled:M,onChange:U=>{const B=U.target.files?.[0];B&&ll(B),U.target.value=""}})]})]})]})})}),ee==="auth"&&n.jsx(at,{title:"账号与注册",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放用户注册"}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:T?"启用":"关闭"}),n.jsx("button",{type:"button",className:T?"ios-switch is-on":"ios-switch","aria-label":T?"关闭用户注册":"开放用户注册","aria-pressed":!!T,onClick:$e,children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"注册方式"}),n.jsx("div",{className:"registration-mode-control",role:"group","aria-label":"注册方式",children:[{value:"username",label:"账号密码"},{value:"email",label:"邮箱"},{value:"discord",label:"Discord"}].map(U=>n.jsx("button",{type:"button",className:$===U.value?"selected":"",onClick:()=>F(T??!0,U.value),children:U.label},U.value))})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["新用户初始额度",n.jsx("small",{children:"注册完成后自动发放,仅影响之后的新用户"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsx("input",{type:"number",min:"0",step:"0.01",value:g,onChange:U=>G(U.target.value),"aria-label":"新用户初始额度"}),n.jsx("button",{type:"button",className:"secondary-button",onClick:()=>F(T,$,Number(g)),children:"保存"})]})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["默认注册分组",n.jsx("small",{children:"新注册用户自动归入该分组,决定他们能用哪些渠道"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsxs("select",{value:z,onChange:U=>V(U.target.value),"aria-label":"默认注册分组",children:[p.map(U=>n.jsx("option",{value:U.id,children:U.name},U.id)),p.length===0&&n.jsx("option",{value:"",children:"暂无分组"})]}),n.jsx("button",{type:"button",className:"secondary-button",disabled:p.length===0,onClick:()=>F(T,$,Number(g),z),children:"保存"})]})]})]})}),ee==="check-in"&&n.jsx(at,{title:"每日签到奖励",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["开放每日签到",n.jsx("small",{children:"用户每天可领取一次随机额度,按北京时间刷新"})]}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:W.enabled?"启用":"关闭"}),n.jsx("button",{type:"button",className:W.enabled?"ios-switch is-on":"ios-switch","aria-label":W.enabled?"关闭每日签到":"开放每日签到","aria-pressed":W.enabled,onClick:()=>fe(U=>({...U,enabled:!U.enabled})),children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting check-in-settings-row",children:[n.jsxs("span",{children:["随机奖励范围",n.jsx("small",{children:"领取金额精确到 0.01,直接计入用户余额和额度流水"})]}),n.jsxs("div",{className:"check-in-reward-inputs",children:[n.jsxs("label",{children:[n.jsx("span",{children:"最低"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:W.minReward,onChange:U=>fe(B=>({...B,minReward:Number(U.target.value)}))})]}),n.jsxs("label",{children:[n.jsx("span",{children:"最高"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:W.maxReward,onChange:U=>fe(B=>({...B,maxReward:Number(U.target.value)}))})]})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:m}),n.jsx("button",{type:"button",className:"primary-button",disabled:M,onClick:rt,children:M?"保存中":"保存签到设置"})]})]})}),ee==="admin"&&n.jsx(at,{title:"管理员账号",children:n.jsxs("form",{className:"discord-settings",onSubmit:U=>{U.preventDefault(),bt()},children:[n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"登录账号"}),n.jsx("input",{value:P,onChange:U=>he(U.target.value),autoComplete:"username"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:_,onChange:U=>ne(U.target.value),autoComplete:"name"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"邮箱"}),n.jsx("input",{type:"email",value:me,onChange:U=>Ce(U.target.value),autoComplete:"email"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:Me,onChange:U=>ue(U.target.value),placeholder:Y?.discordUserId?"已绑定":"输入管理员的 Discord 用户 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"当前密码"}),n.jsx("input",{type:"password",value:K,onChange:U=>de(U.target.value),autoComplete:"current-password",placeholder:"修改密码时填写"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新密码"}),n.jsx("input",{type:"password",value:J,onChange:U=>N(U.target.value),autoComplete:"new-password",placeholder:"留空表示不修改"})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:m}),n.jsx("button",{className:"primary-button",type:"submit",children:"保存账号"})]})]})}),ee==="discord"&&n.jsx(at,{title:"Discord 登录",children:r?n.jsxs("form",{className:"discord-settings",autoComplete:"off",onSubmit:U=>{U.preventDefault(),We()},children:[n.jsxs("div",{className:"discord-toggle-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"Discord 登录"}),n.jsx("span",{children:r.enabled?"已启用":"未启用"})]}),n.jsx("button",{type:"button",className:r.enabled?"ios-switch is-on":"ios-switch","aria-label":r.enabled?"停用 Discord 登录":"启用 Discord 登录","aria-pressed":r.enabled,onClick:()=>A({...r,enabled:!r.enabled}),children:n.jsx("span",{})})]}),n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"Client ID"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:r.clientId,onChange:U=>A({...r,clientId:U.target.value}),placeholder:"100000000000000001"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Client Secret"}),n.jsx("input",{type:"password",autoComplete:"new-password",value:k,onChange:U=>H(U.target.value),placeholder:r.clientSecretSet?"已设置,留空表示不修改":"粘贴 Discord Client Secret"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"回调地址"}),n.jsx("input",{type:"url",value:r.redirectUri,onChange:U=>A({...r,redirectUri:U.target.value}),placeholder:"https://你的域名/api/auth/discord/callback"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"服务器 ID"}),n.jsx("input",{inputMode:"numeric",value:r.allowedGuildId,onChange:U=>A({...r,allowedGuildId:U.target.value}),placeholder:"允许登录的服务器 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"身份组 ID"}),n.jsx("input",{inputMode:"numeric",value:r.allowedRoleId,onChange:U=>A({...r,allowedRoleId:U.target.value}),placeholder:"允许登录的身份组 ID"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"拉黑服务器 ID"}),n.jsx("textarea",{value:X,onChange:U=>se(U.target.value),placeholder:"每行一个服务器 ID;命中的用户禁止注册 / 登录",rows:3}),n.jsx("small",{children:"用户若加入了这些 Discord 服务器中的任意一个,将无法注册或登录(优先于上面的允许规则)。"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"登录成功跳转地址"}),n.jsx("input",{type:"url",value:r.authSuccessUrl,onChange:U=>A({...r,authSuccessUrl:U.target.value}),placeholder:"https://你的域名/"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"登录有效期(小时)"}),n.jsx("input",{type:"number",min:"1",max:"8760",value:r.sessionTtlHours,onChange:U=>A({...r,sessionTtlHours:Number(U.target.value)})})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:m}),n.jsx("button",{className:"primary-button",type:"submit",disabled:M,children:M?"保存中":"保存配置"})]})]}):n.jsx("div",{className:"empty",children:"正在读取配置"})})]})}function cl({label:u,value:f}){return n.jsxs("div",{className:"metric",children:[n.jsx("span",{children:u}),n.jsx("strong",{children:f})]})}function Kp({groups:u,onCreate:f,onUpdate:p,onDelete:r}){const[A,T]=b.useState(""),[L,$]=b.useState(""),[C,g]=b.useState(!1);async function G(z){if(z.preventDefault(),!!A.trim()){g(!0);try{await f({name:A.trim(),description:L.trim()}),T(""),$("")}finally{g(!1)}}}return n.jsxs("section",{className:"models-page",children:[n.jsxs(at,{title:"用户分组",children:[n.jsxs("form",{className:"channel-create-form",onSubmit:G,children:[n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"分组名称"}),n.jsx("input",{value:A,onChange:z=>T(z.target.value),placeholder:"例如 尊享用户 / 试用用户"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"说明"}),n.jsx("input",{value:L,onChange:z=>$(z.target.value),placeholder:"可选"})]})]}),n.jsx("div",{className:"channel-card-actions",children:n.jsx("button",{className:"primary-button",type:"submit",disabled:C||!A.trim(),children:C?"创建中":"创建分组"})})]}),n.jsx("p",{className:"muted-inline",children:"分组用于控制渠道对用户的可见范围:把用户归入分组,并在渠道上勾选「可见分组」即可限制访问。未分组的用户只能使用未限制分组的渠道。"})]}),n.jsx(at,{title:"全部分组",children:u.length===0?n.jsx(kt,{text:"还没有分组"}):n.jsx("div",{className:"channels-stack",children:u.map(z=>n.jsx(Zp,{group:z,onUpdate:p,onDelete:r},z.id))})})]})}function Zp({group:u,onUpdate:f,onDelete:p}){const[r,A]=b.useState(!1),[T,L]=b.useState(u.name),[$,C]=b.useState(u.description),[g,G]=b.useState(!1);async function z(){G(!0);try{await f(u.id,{name:T.trim(),description:$.trim()}),A(!1)}finally{G(!1)}}return n.jsx("div",{className:"channel-card",children:n.jsxs("div",{className:"channel-card-head",children:[n.jsx("div",{children:r?n.jsxs("div",{className:"group-edit-fields",children:[n.jsx("input",{value:T,onChange:V=>L(V.target.value),placeholder:"分组名称"}),n.jsx("input",{value:$,onChange:V=>C(V.target.value),placeholder:"说明"})]}):n.jsxs(n.Fragment,{children:[n.jsx("strong",{children:u.name}),u.description&&n.jsx("span",{children:u.description}),n.jsxs("small",{children:["创建于 ",el(u.createdAt)]})]})}),n.jsx("div",{className:"channel-card-head-actions",children:r?n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"primary-button compact-button",onClick:z,disabled:g||!T.trim(),children:g?"保存中":"保存"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>{L(u.name),C(u.description),A(!1)},children:"取消"})]}):n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>A(!0),children:"重命名"}),n.jsx("button",{className:"danger-button compact-button",onClick:()=>p(u.id),children:"删除"})]})})]})})}function at({title:u,children:f}){return n.jsxs("section",{className:"panel",children:[n.jsx("div",{className:"panel-title",children:n.jsx("h2",{children:u})}),f]})}function Dt({tone:u,children:f}){return n.jsx("span",{className:`badge tone-${u}`,children:f})}function Pt({label:u,value:f,switchOn:p}){return n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:u}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:f}),typeof p=="boolean"&&n.jsx("div",{className:p?"ios-switch is-on":"ios-switch","aria-hidden":"true",children:n.jsx("span",{})})]})]})}function Vp({value:u,options:f,onChange:p}){return n.jsx("div",{className:"segmented-control",children:f.map(r=>n.jsx("button",{className:u===r.value?"selected":"",onClick:()=>p(r.value),children:r.label},r.value))})}function kt({text:u}){return n.jsx("div",{className:"empty",children:u})}$0.createRoot(document.getElementById("root")).render(n.jsx(k0.StrictMode,{children:n.jsx(mp,{})})); diff --git a/dist/assets/index-B9-tgVyd.js b/dist/assets/index-B9-tgVyd.js deleted file mode 100644 index ccd44ce..0000000 --- a/dist/assets/index-B9-tgVyd.js +++ /dev/null @@ -1,43 +0,0 @@ -(function(){const m=document.createElement("link").relList;if(m&&m.supports&&m.supports("modulepreload"))return;for(const A of document.querySelectorAll('link[rel="modulepreload"]'))r(A);new MutationObserver(A=>{for(const E of A)if(E.type==="childList")for(const L of E.addedNodes)L.tagName==="LINK"&&L.rel==="modulepreload"&&r(L)}).observe(document,{childList:!0,subtree:!0});function h(A){const E={};return A.integrity&&(E.integrity=A.integrity),A.referrerPolicy&&(E.referrerPolicy=A.referrerPolicy),A.crossOrigin==="use-credentials"?E.credentials="include":A.crossOrigin==="anonymous"?E.credentials="omit":E.credentials="same-origin",E}function r(A){if(A.ep)return;A.ep=!0;const E=h(A);fetch(A.href,E)}})();function B0(u){return u&&u.__esModule&&Object.prototype.hasOwnProperty.call(u,"default")?u.default:u}var Qc={exports:{}},is={};var tm;function q0(){if(tm)return is;tm=1;var u=Symbol.for("react.transitional.element"),m=Symbol.for("react.fragment");function h(r,A,E){var L=null;if(E!==void 0&&(L=""+E),A.key!==void 0&&(L=""+A.key),"key"in A){E={};for(var $ in A)$!=="key"&&(E[$]=A[$])}else E=A;return A=E.ref,{$$typeof:u,type:r,key:L,ref:A!==void 0?A:null,props:E}}return is.Fragment=m,is.jsx=h,is.jsxs=h,is}var lm;function G0(){return lm||(lm=1,Qc.exports=q0()),Qc.exports}var n=G0(),Xc={exports:{}},Ce={};var am;function Y0(){if(am)return Ce;am=1;var u=Symbol.for("react.transitional.element"),m=Symbol.for("react.portal"),h=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),A=Symbol.for("react.profiler"),E=Symbol.for("react.consumer"),L=Symbol.for("react.context"),$=Symbol.for("react.forward_ref"),C=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),R=Symbol.for("react.lazy"),z=Symbol.for("react.activity"),P=Symbol.iterator;function ee(d){return d===null||typeof d!="object"?null:(d=P&&d[P]||d["@@iterator"],typeof d=="function"?d:null)}var de={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},ne=Object.assign,le={};function ie(d,x,G){this.props=d,this.context=x,this.refs=le,this.updater=G||de}ie.prototype.isReactComponent={},ie.prototype.setState=function(d,x){if(typeof d!="object"&&typeof d!="function"&&d!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,d,x,"setState")},ie.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function xe(){}xe.prototype=ie.prototype;function Y(d,x,G){this.props=d,this.context=x,this.refs=le,this.updater=G||de}var ge=Y.prototype=new xe;ge.constructor=Y,ne(ge,ie.prototype),ge.isPureReactComponent=!0;var F=Array.isArray;function me(){}var D={H:null,A:null,T:null,S:null},ae=Object.prototype.hasOwnProperty;function fe(d,x,G){var X=G.ref;return{$$typeof:u,type:d,key:x,ref:X!==void 0?X:null,props:G}}function Ae(d,x){return fe(d.type,x,d.props)}function Te(d){return typeof d=="object"&&d!==null&&d.$$typeof===u}function ue(d){var x={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(G){return x[G]})}var Z=/\/+/g;function re(d,x){return typeof d=="object"&&d!==null&&d.key!=null?ue(""+d.key):x.toString(36)}function J(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(me,me):(d.status="pending",d.then(function(x){d.status==="pending"&&(d.status="fulfilled",d.value=x)},function(x){d.status==="pending"&&(d.status="rejected",d.reason=x)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function T(d,x,G,X,se){var ve=typeof d;(ve==="undefined"||ve==="boolean")&&(d=null);var N=!1;if(d===null)N=!0;else switch(ve){case"bigint":case"string":case"number":N=!0;break;case"object":switch(d.$$typeof){case u:case m:N=!0;break;case R:return N=d._init,T(N(d._payload),x,G,X,se)}}if(N)return se=se(d),N=X===""?"."+re(d,0):X,F(se)?(G="",N!=null&&(G=N.replace(Z,"$&/")+"/"),T(se,x,G,"",function(bt){return bt})):se!=null&&(Te(se)&&(se=Ae(se,G+(se.key==null||d&&d.key===se.key?"":(""+se.key).replace(Z,"$&/")+"/")+N)),x.push(se)),1;N=0;var Ne=X===""?".":X+":";if(F(d))for(var Se=0;Se>>1,O=T[Q];if(0>>1;QA(G,B))XA(se,G)?(T[Q]=se,T[X]=B,Q=X):(T[Q]=G,T[x]=B,Q=x);else if(XA(se,B))T[Q]=se,T[X]=B,Q=X;else break e}}return k}function A(T,k){var B=T.sortIndex-k.sortIndex;return B!==0?B:T.id-k.id}if(u.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var E=performance;u.unstable_now=function(){return E.now()}}else{var L=Date,$=L.now();u.unstable_now=function(){return L.now()-$}}var C=[],y=[],R=1,z=null,P=3,ee=!1,de=!1,ne=!1,le=!1,ie=typeof setTimeout=="function"?setTimeout:null,xe=typeof clearTimeout=="function"?clearTimeout:null,Y=typeof setImmediate<"u"?setImmediate:null;function ge(T){for(var k=h(y);k!==null;){if(k.callback===null)r(y);else if(k.startTime<=T)r(y),k.sortIndex=k.expirationTime,m(C,k);else break;k=h(y)}}function F(T){if(ne=!1,ge(T),!de)if(h(C)!==null)de=!0,me||(me=!0,ue());else{var k=h(y);k!==null&&J(F,k.startTime-T)}}var me=!1,D=-1,ae=5,fe=-1;function Ae(){return le?!0:!(u.unstable_now()-feT&&Ae());){var Q=z.callback;if(typeof Q=="function"){z.callback=null,P=z.priorityLevel;var O=Q(z.expirationTime<=T);if(T=u.unstable_now(),typeof O=="function"){z.callback=O,ge(T),k=!0;break t}z===h(C)&&r(C),ge(T)}else r(C);z=h(C)}if(z!==null)k=!0;else{var d=h(y);d!==null&&J(F,d.startTime-T),k=!1}}break e}finally{z=null,P=B,ee=!1}k=void 0}}finally{k?ue():me=!1}}}var ue;if(typeof Y=="function")ue=function(){Y(Te)};else if(typeof MessageChannel<"u"){var Z=new MessageChannel,re=Z.port2;Z.port1.onmessage=Te,ue=function(){re.postMessage(null)}}else ue=function(){ie(Te,0)};function J(T,k){D=ie(function(){T(u.unstable_now())},k)}u.unstable_IdlePriority=5,u.unstable_ImmediatePriority=1,u.unstable_LowPriority=4,u.unstable_NormalPriority=3,u.unstable_Profiling=null,u.unstable_UserBlockingPriority=2,u.unstable_cancelCallback=function(T){T.callback=null},u.unstable_forceFrameRate=function(T){0>T||125Q?(T.sortIndex=B,m(y,T),h(C)===null&&T===h(y)&&(ne?(xe(D),D=-1):ne=!0,J(F,B-Q))):(T.sortIndex=O,m(C,T),de||ee||(de=!0,me||(me=!0,ue()))),T},u.unstable_shouldYield=Ae,u.unstable_wrapCallback=function(T){var k=P;return function(){var B=P;P=k;try{return T.apply(this,arguments)}finally{P=B}}}})(Vc)),Vc}var im;function Q0(){return im||(im=1,Zc.exports=k0()),Zc.exports}var Jc={exports:{}},gt={};var um;function X0(){if(um)return gt;um=1;var u=eo();function m(C){var y="https://react.dev/errors/"+C;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(u)}catch(m){console.error(m)}}return u(),Jc.exports=X0(),Jc.exports}var om;function Z0(){if(om)return us;om=1;var u=Q0(),m=eo(),h=K0();function r(e){var t="https://react.dev/errors/"+e;if(1O||(e.current=Q[O],Q[O]=null,O--)}function G(e,t){O++,Q[O]=e.current,e.current=t}var X=d(null),se=d(null),ve=d(null),N=d(null);function Ne(e,t){switch(G(ve,t),G(se,e),G(X,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Af(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Af(t),e=Cf(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}x(X),G(X,e)}function Se(){x(X),x(se),x(ve)}function bt(e){e.memoizedState!==null&&G(N,e);var t=X.current,l=Cf(t,e.type);t!==l&&(G(se,e),G(X,l))}function I(e){se.current===e&&(x(X),x(se)),N.current===e&&(x(N),ls._currentValue=B)}var Ke,We;function Pe(e){if(Ke===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);Ke=t&&t[1]||"",We=-1)":-1s||f[a]!==j[s]){var U=` -`+f[a].replace(" at new "," at ");return e.displayName&&U.includes("")&&(U=U.replace("",e.displayName)),U}while(1<=a&&0<=s);break}}}finally{tl=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Pe(l):""}function cl(e,t){switch(e.tag){case 26:case 27:case 5:return Pe(e.type);case 16:return Pe("Lazy");case 13:return e.child!==t&&t!==null?Pe("Suspense Fallback"):Pe("Suspense");case 19:return Pe("SuspenseList");case 0:case 15:return kt(e.type,!1);case 11:return kt(e.type.render,!1);case 1:return kt(e.type,!0);case 31:return Pe("Activity");default:return""}}function V(e){try{var t="",l=null;do t+=cl(e,l),l=e,e=e.return;while(e);return t}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var _=Object.prototype.hasOwnProperty,Ee=u.unstable_scheduleCallback,et=u.unstable_cancelCallback,xt=u.unstable_shouldYield,ft=u.unstable_requestPaint,tt=u.unstable_now,zi=u.unstable_getCurrentPriorityLevel,hn=u.unstable_ImmediatePriority,ia=u.unstable_UserBlockingPriority,ua=u.unstable_NormalPriority,Oi=u.unstable_LowPriority,w=u.unstable_IdlePriority,K=u.log,te=u.unstable_setDisableYieldValue,W=null,ye=null;function qe(e){if(typeof K=="function"&&te(e),ye&&typeof ye.setStrictMode=="function")try{ye.setStrictMode(W,e)}catch{}}var Ze=Math.clz32?Math.clz32:ca,Ut=Math.log,Rl=Math.LN2;function ca(e){return e>>>=0,e===0?32:31-(Ut(e)/Rl|0)|0}var Ea=256,Ma=262144,wl=4194304;function hl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function os(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var s=0,i=e.suspendedLanes,c=e.pingedLanes;e=e.warmLanes;var o=a&134217727;return o!==0?(a=o&~i,a!==0?s=hl(a):(c&=o,c!==0?s=hl(c):l||(l=o&~e,l!==0&&(s=hl(l))))):(o=a&~i,o!==0?s=hl(o):c!==0?s=hl(c):l||(l=a&~e,l!==0&&(s=hl(l)))),s===0?0:t!==0&&t!==s&&(t&i)===0&&(i=s&-s,l=t&-t,i>=l||i===32&&(l&4194048)!==0)?t:s}function pn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Am(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ao(){var e=wl;return wl<<=1,(wl&62914560)===0&&(wl=4194304),e}function _i(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function vn(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Cm(e,t,l,a,s,i){var c=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var o=e.entanglements,f=e.expirationTimes,j=e.hiddenUpdates;for(l=c&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var _m=/[\n"\\]/g;function Xt(e){return e.replace(_m,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Bi(e,t,l,a,s,i,c,o){e.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?e.type=c:e.removeAttribute("type"),t!=null?c==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+Qt(t)):e.value!==""+Qt(t)&&(e.value=""+Qt(t)):c!=="submit"&&c!=="reset"||e.removeAttribute("value"),t!=null?qi(e,c,Qt(t)):l!=null?qi(e,c,Qt(l)):a!=null&&e.removeAttribute("value"),s==null&&i!=null&&(e.defaultChecked=!!i),s!=null&&(e.checked=s&&typeof s!="function"&&typeof s!="symbol"),o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?e.name=""+Qt(o):e.removeAttribute("name")}function yo(e,t,l,a,s,i,c,o){if(i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(e.type=i),t!=null||l!=null){if(!(i!=="submit"&&i!=="reset"||t!=null)){Hi(e);return}l=l!=null?""+Qt(l):"",t=t!=null?""+Qt(t):l,o||t===e.value||(e.value=t),e.defaultValue=t}a=a??s,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=o?e.checked:!!a,e.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.name=c),Hi(e)}function qi(e,t,l){t==="number"&&fs(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ra(e,t,l,a){if(e=e.options,t){t={};for(var s=0;s"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Qi=!1;if(yl)try{var xn={};Object.defineProperty(xn,"passive",{get:function(){Qi=!0}}),window.addEventListener("test",xn,xn),window.removeEventListener("test",xn,xn)}catch{Qi=!1}var Bl=null,Xi=null,hs=null;function Ao(){if(hs)return hs;var e,t=Xi,l=t.length,a,s="value"in Bl?Bl.value:Bl.textContent,i=s.length;for(e=0;e=Nn),Oo=" ",_o=!1;function Do(e,t){switch(e){case"keyup":return sh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Uo(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var qa=!1;function uh(e,t){switch(e){case"compositionend":return Uo(t);case"keypress":return t.which!==32?null:(_o=!0,Oo);case"textInput":return e=t.data,e===Oo&&_o?null:e;default:return null}}function ch(e,t){if(qa)return e==="compositionend"||!$i&&Do(e,t)?(e=Ao(),hs=Xi=Bl=null,qa=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Lo(l)}}function Qo(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Qo(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Xo(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=fs(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=fs(e.document)}return t}function Ii(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var vh=yl&&"documentMode"in document&&11>=document.documentMode,Ga=null,Pi=null,En=null,eu=!1;function Ko(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;eu||Ga==null||Ga!==fs(a)||(a=Ga,"selectionStart"in a&&Ii(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),En&&Tn(En,a)||(En=a,a=ui(Pi,"onSelect"),0>=c,s-=c,ol=1<<32-Ze(t)+s|l<ze?(Ue=oe,oe=null):Ue=oe.sibling;var He=S(v,oe,b[ze],H);if(He===null){oe===null&&(oe=Ue);break}e&&oe&&He.alternate===null&&t(v,oe),p=i(He,p,ze),we===null?he=He:we.sibling=He,we=He,oe=Ue}if(ze===b.length)return l(v,oe),Re&&bl(v,ze),he;if(oe===null){for(;zeze?(Ue=oe,oe=null):Ue=oe.sibling;var sa=S(v,oe,He.value,H);if(sa===null){oe===null&&(oe=Ue);break}e&&oe&&sa.alternate===null&&t(v,oe),p=i(sa,p,ze),we===null?he=sa:we.sibling=sa,we=sa,oe=Ue}if(He.done)return l(v,oe),Re&&bl(v,ze),he;if(oe===null){for(;!He.done;ze++,He=b.next())He=q(v,He.value,H),He!==null&&(p=i(He,p,ze),we===null?he=He:we.sibling=He,we=He);return Re&&bl(v,ze),he}for(oe=a(oe);!He.done;ze++,He=b.next())He=M(oe,v,ze,He.value,H),He!==null&&(e&&He.alternate!==null&&oe.delete(He.key===null?ze:He.key),p=i(He,p,ze),we===null?he=He:we.sibling=He,we=He);return e&&oe.forEach(function(H0){return t(v,H0)}),Re&&bl(v,ze),he}function Qe(v,p,b,H){if(typeof b=="object"&&b!==null&&b.type===ne&&b.key===null&&(b=b.props.children),typeof b=="object"&&b!==null){switch(b.$$typeof){case ee:e:{for(var he=b.key;p!==null;){if(p.key===he){if(he=b.type,he===ne){if(p.tag===7){l(v,p.sibling),H=s(p,b.props.children),H.return=v,v=H;break e}}else if(p.elementType===he||typeof he=="object"&&he!==null&&he.$$typeof===ae&&ba(he)===p.type){l(v,p.sibling),H=s(p,b.props),Un(H,b),H.return=v,v=H;break e}l(v,p);break}else t(v,p);p=p.sibling}b.type===ne?(H=ha(b.props.children,v.mode,H,b.key),H.return=v,v=H):(H=As(b.type,b.key,b.props,null,v.mode,H),Un(H,b),H.return=v,v=H)}return c(v);case de:e:{for(he=b.key;p!==null;){if(p.key===he)if(p.tag===4&&p.stateNode.containerInfo===b.containerInfo&&p.stateNode.implementation===b.implementation){l(v,p.sibling),H=s(p,b.children||[]),H.return=v,v=H;break e}else{l(v,p);break}else t(v,p);p=p.sibling}H=uu(b,v.mode,H),H.return=v,v=H}return c(v);case ae:return b=ba(b),Qe(v,p,b,H)}if(J(b))return ce(v,p,b,H);if(ue(b)){if(he=ue(b),typeof he!="function")throw Error(r(150));return b=he.call(b),je(v,p,b,H)}if(typeof b.then=="function")return Qe(v,p,_s(b),H);if(b.$$typeof===Y)return Qe(v,p,Es(v,b),H);Ds(v,b)}return typeof b=="string"&&b!==""||typeof b=="number"||typeof b=="bigint"?(b=""+b,p!==null&&p.tag===6?(l(v,p.sibling),H=s(p,b),H.return=v,v=H):(l(v,p),H=iu(b,v.mode,H),H.return=v,v=H),c(v)):l(v,p)}return function(v,p,b,H){try{Dn=0;var he=Qe(v,p,b,H);return Wa=null,he}catch(oe){if(oe===$a||oe===zs)throw oe;var we=wt(29,oe,null,v.mode);return we.lanes=H,we.return=v,we}}}var ja=hr(!0),pr=hr(!1),kl=!1;function bu(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xu(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ql(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Xl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(Be&2)!==0){var s=a.pending;return s===null?t.next=t:(t.next=s.next,s.next=t),a.pending=t,t=Ns(e),Io(e,null,l),t}return Ss(e,a,t,l),Ns(e)}function Rn(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,so(e,l)}}function ju(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var s=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};i===null?s=i=c:i=i.next=c,l=l.next}while(l!==null);i===null?s=i=t:i=i.next=t}else s=i=t;l={baseState:a.baseState,firstBaseUpdate:s,lastBaseUpdate:i,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Su=!1;function wn(){if(Su){var e=Ja;if(e!==null)throw e}}function Hn(e,t,l,a){Su=!1;var s=e.updateQueue;kl=!1;var i=s.firstBaseUpdate,c=s.lastBaseUpdate,o=s.shared.pending;if(o!==null){s.shared.pending=null;var f=o,j=f.next;f.next=null,c===null?i=j:c.next=j,c=f;var U=e.alternate;U!==null&&(U=U.updateQueue,o=U.lastBaseUpdate,o!==c&&(o===null?U.firstBaseUpdate=j:o.next=j,U.lastBaseUpdate=f))}if(i!==null){var q=s.baseState;c=0,U=j=f=null,o=i;do{var S=o.lane&-536870913,M=S!==o.lane;if(M?(De&S)===S:(a&S)===S){S!==0&&S===Va&&(Su=!0),U!==null&&(U=U.next={lane:0,tag:o.tag,payload:o.payload,callback:null,next:null});e:{var ce=e,je=o;S=t;var Qe=l;switch(je.tag){case 1:if(ce=je.payload,typeof ce=="function"){q=ce.call(Qe,q,S);break e}q=ce;break e;case 3:ce.flags=ce.flags&-65537|128;case 0:if(ce=je.payload,S=typeof ce=="function"?ce.call(Qe,q,S):ce,S==null)break e;q=z({},q,S);break e;case 2:kl=!0}}S=o.callback,S!==null&&(e.flags|=64,M&&(e.flags|=8192),M=s.callbacks,M===null?s.callbacks=[S]:M.push(S))}else M={lane:S,tag:o.tag,payload:o.payload,callback:o.callback,next:null},U===null?(j=U=M,f=q):U=U.next=M,c|=S;if(o=o.next,o===null){if(o=s.shared.pending,o===null)break;M=o,o=M.next,M.next=null,s.lastBaseUpdate=M,s.shared.pending=null}}while(!0);U===null&&(f=q),s.baseState=f,s.firstBaseUpdate=j,s.lastBaseUpdate=U,i===null&&(s.shared.lanes=0),$l|=c,e.lanes=c,e.memoizedState=q}}function vr(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function yr(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ei?i:8;var c=T.T,o={};T.T=o,Lu(e,!1,t,l);try{var f=s(),j=T.S;if(j!==null&&j(o,f),f!==null&&typeof f=="object"&&typeof f.then=="function"){var U=Ch(f,a);Gn(e,t,U,Yt(e))}else Gn(e,t,a,Yt(e))}catch(q){Gn(e,t,{then:function(){},status:"rejected",reason:q},Yt())}finally{k.p=i,c!==null&&o.types!==null&&(c.types=o.types),T.T=c}}function _h(){}function Gu(e,t,l,a){if(e.tag!==5)throw Error(r(476));var s=$r(e).queue;Jr(e,s,t,B,l===null?_h:function(){return Wr(e),l(a)})}function $r(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:B,baseState:B,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Nl,lastRenderedState:B},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Nl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Wr(e){var t=$r(e);t.next===null&&(t=e.alternate.memoizedState),Gn(e,t.next.queue,{},Yt())}function Yu(){return pt(ls)}function Fr(){return at().memoizedState}function Ir(){return at().memoizedState}function Dh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Yt();e=Ql(l);var a=Xl(t,e,l);a!==null&&(zt(a,t,l),Rn(a,t,l)),t={cache:pu()},e.payload=t;return}t=t.return}}function Uh(e,t,l){var a=Yt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},ks(e)?ed(t,l):(l=nu(e,t,l,a),l!==null&&(zt(l,e,a),td(l,t,a)))}function Pr(e,t,l){var a=Yt();Gn(e,t,l,a)}function Gn(e,t,l,a){var s={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(ks(e))ed(t,s);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var c=t.lastRenderedState,o=i(c,l);if(s.hasEagerState=!0,s.eagerState=o,Rt(o,c))return Ss(e,t,s,0),Xe===null&&js(),!1}catch{}if(l=nu(e,t,s,a),l!==null)return zt(l,e,a),td(l,t,a),!0}return!1}function Lu(e,t,l,a){if(a={lane:2,revertLane:bc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},ks(e)){if(t)throw Error(r(479))}else t=nu(e,l,a,2),t!==null&&zt(t,e,2)}function ks(e){var t=e.alternate;return e===Me||t!==null&&t===Me}function ed(e,t){Ia=ws=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function td(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,so(e,l)}}var Yn={readContext:pt,use:qs,useCallback:Fe,useContext:Fe,useEffect:Fe,useImperativeHandle:Fe,useLayoutEffect:Fe,useInsertionEffect:Fe,useMemo:Fe,useReducer:Fe,useRef:Fe,useState:Fe,useDebugValue:Fe,useDeferredValue:Fe,useTransition:Fe,useSyncExternalStore:Fe,useId:Fe,useHostTransitionStatus:Fe,useFormState:Fe,useActionState:Fe,useOptimistic:Fe,useMemoCache:Fe,useCacheRefresh:Fe};Yn.useEffectEvent=Fe;var ld={readContext:pt,use:qs,useCallback:function(e,t){return jt().memoizedState=[e,t===void 0?null:t],e},useContext:pt,useEffect:Gr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Ys(4194308,4,Qr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Ys(4194308,4,e,t)},useInsertionEffect:function(e,t){Ys(4,2,e,t)},useMemo:function(e,t){var l=jt();t=t===void 0?null:t;var a=e();if(Sa){qe(!0);try{e()}finally{qe(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=jt();if(l!==void 0){var s=l(t);if(Sa){qe(!0);try{l(t)}finally{qe(!1)}}}else s=t;return a.memoizedState=a.baseState=s,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:s},a.queue=e,e=e.dispatch=Uh.bind(null,Me,e),[a.memoizedState,e]},useRef:function(e){var t=jt();return e={current:e},t.memoizedState=e},useState:function(e){e=Ru(e);var t=e.queue,l=Pr.bind(null,Me,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Bu,useDeferredValue:function(e,t){var l=jt();return qu(l,e,t)},useTransition:function(){var e=Ru(!1);return e=Jr.bind(null,Me,e.queue,!0,!1),jt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=Me,s=jt();if(Re){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Xe===null)throw Error(r(349));(De&127)!==0||Nr(a,t,l)}s.memoizedState=l;var i={value:l,getSnapshot:t};return s.queue=i,Gr(Cr.bind(null,a,i,e),[e]),a.flags|=2048,en(9,{destroy:void 0},Ar.bind(null,a,i,l,t),null),l},useId:function(){var e=jt(),t=Xe.identifierPrefix;if(Re){var l=rl,a=ol;l=(a&~(1<<32-Ze(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Hs++,0<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?i.multiple=!0:a.size&&(i.size=a.size);break;default:i=typeof a.is=="string"?c.createElement(s,{is:a.is}):c.createElement(s)}}i[mt]=t,i[Nt]=a;e:for(c=t.child;c!==null;){if(c.tag===5||c.tag===6)i.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===t)break e;for(;c.sibling===null;){if(c.return===null||c.return===t)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}t.stateNode=i;e:switch(yt(i,s,a),s){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&Cl(t)}}return Je(t),tc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Cl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=ve.current,Ka(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,s=ht,s!==null)switch(s.tag){case 27:case 5:a=s.memoizedProps}e[mt]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||Sf(e.nodeValue,l)),e||Yl(t,!0)}else e=ci(e).createTextNode(a),e[mt]=t,t.stateNode=e}return Je(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=Ka(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[mt]=t}else pa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Je(t),e=!1}else l=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Bt(t),t):(Bt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Je(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(s=Ka(t),a!==null&&a.dehydrated!==null){if(e===null){if(!s)throw Error(r(318));if(s=t.memoizedState,s=s!==null?s.dehydrated:null,!s)throw Error(r(317));s[mt]=t}else pa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Je(t),s=!1}else s=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=s),s=!0;if(!s)return t.flags&256?(Bt(t),t):(Bt(t),null)}return Bt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,s=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(s=a.alternate.memoizedState.cachePool.pool),i=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(i=a.memoizedState.cachePool.pool),i!==s&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Vs(t,t.updateQueue),Je(t),null);case 4:return Se(),e===null&&Nc(t.stateNode.containerInfo),Je(t),null;case 10:return jl(t.type),Je(t),null;case 19:if(x(lt),a=t.memoizedState,a===null)return Je(t),null;if(s=(t.flags&128)!==0,i=a.rendering,i===null)if(s)kn(a,!1);else{if(Ie!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(i=Rs(e),i!==null){for(t.flags|=128,kn(a,!1),e=i.updateQueue,t.updateQueue=e,Vs(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Po(l,e),l=l.sibling;return G(lt,lt.current&1|2),Re&&bl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&tt()>Is&&(t.flags|=128,s=!0,kn(a,!1),t.lanes=4194304)}else{if(!s)if(e=Rs(i),e!==null){if(t.flags|=128,s=!0,e=e.updateQueue,t.updateQueue=e,Vs(t,e),kn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!Re)return Je(t),null}else 2*tt()-a.renderingStartTime>Is&&l!==536870912&&(t.flags|=128,s=!0,kn(a,!1),t.lanes=4194304);a.isBackwards?(i.sibling=t.child,t.child=i):(e=a.last,e!==null?e.sibling=i:t.child=i,a.last=i)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=tt(),e.sibling=null,l=lt.current,G(lt,s?l&1|2:l&1),Re&&bl(t,a.treeForkCount),e):(Je(t),null);case 22:case 23:return Bt(t),Au(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Je(t),t.subtreeFlags&6&&(t.flags|=8192)):Je(t),l=t.updateQueue,l!==null&&Vs(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&x(ga),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),jl(st),Je(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function qh(e,t){switch(ou(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return jl(st),Se(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return I(t),null;case 31:if(t.memoizedState!==null){if(Bt(t),t.alternate===null)throw Error(r(340));pa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Bt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));pa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return x(lt),null;case 4:return Se(),null;case 10:return jl(t.type),null;case 22:case 23:return Bt(t),Au(),e!==null&&x(ga),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return jl(st),null;case 25:return null;default:return null}}function Td(e,t){switch(ou(t),t.tag){case 3:jl(st),Se();break;case 26:case 27:case 5:I(t);break;case 4:Se();break;case 31:t.memoizedState!==null&&Bt(t);break;case 13:Bt(t);break;case 19:x(lt);break;case 10:jl(t.type);break;case 22:case 23:Bt(t),Au(),e!==null&&x(ga);break;case 24:jl(st)}}function Qn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var s=a.next;l=s;do{if((l.tag&e)===e){a=void 0;var i=l.create,c=l.inst;a=i(),c.destroy=a}l=l.next}while(l!==s)}}catch(o){Ye(t,t.return,o)}}function Vl(e,t,l){try{var a=t.updateQueue,s=a!==null?a.lastEffect:null;if(s!==null){var i=s.next;a=i;do{if((a.tag&e)===e){var c=a.inst,o=c.destroy;if(o!==void 0){c.destroy=void 0,s=t;var f=l,j=o;try{j()}catch(U){Ye(s,f,U)}}}a=a.next}while(a!==i)}}catch(U){Ye(t,t.return,U)}}function Ed(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{yr(t,l)}catch(a){Ye(e,e.return,a)}}}function Md(e,t,l){l.props=Na(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){Ye(e,t,a)}}function Xn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(s){Ye(e,t,s)}}function dl(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(s){Ye(e,t,s)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(s){Ye(e,t,s)}else l.current=null}function zd(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(s){Ye(e,e.return,s)}}function lc(e,t,l){try{var a=e.stateNode;i0(a,e.type,l,t),a[Nt]=t}catch(s){Ye(e,e.return,s)}}function Od(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&ea(e.type)||e.tag===4}function ac(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Od(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&ea(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function nc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=vl));else if(a!==4&&(a===27&&ea(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(nc(e,t,l),e=e.sibling;e!==null;)nc(e,t,l),e=e.sibling}function Js(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&ea(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Js(e,t,l),e=e.sibling;e!==null;)Js(e,t,l),e=e.sibling}function _d(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,s=t.attributes;s.length;)t.removeAttributeNode(s[0]);yt(t,a,l),t[mt]=e,t[Nt]=l}catch(i){Ye(e,e.return,i)}}var Tl=!1,ct=!1,sc=!1,Dd=typeof WeakSet=="function"?WeakSet:Set,dt=null;function Gh(e,t){if(e=e.containerInfo,Tc=pi,e=Xo(e),Ii(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var s=a.anchorOffset,i=a.focusNode;a=a.focusOffset;try{l.nodeType,i.nodeType}catch{l=null;break e}var c=0,o=-1,f=-1,j=0,U=0,q=e,S=null;t:for(;;){for(var M;q!==l||s!==0&&q.nodeType!==3||(o=c+s),q!==i||a!==0&&q.nodeType!==3||(f=c+a),q.nodeType===3&&(c+=q.nodeValue.length),(M=q.firstChild)!==null;)S=q,q=M;for(;;){if(q===e)break t;if(S===l&&++j===s&&(o=c),S===i&&++U===a&&(f=c),(M=q.nextSibling)!==null)break;q=S,S=q.parentNode}q=M}l=o===-1||f===-1?null:{start:o,end:f}}else l=null}l=l||{start:0,end:0}}else l=null;for(Ec={focusedElem:e,selectionRange:l},pi=!1,dt=t;dt!==null;)if(t=dt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,dt=e;else for(;dt!==null;){switch(t=dt,i=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),yt(i,a,l),i[mt]=e,rt(i),a=i;break e;case"link":var c=Gf("link","href",s).get(a+(l.href||""));if(c){for(var o=0;oQe&&(c=Qe,Qe=je,je=c);var v=ko(o,je),p=ko(o,Qe);if(v&&p&&(M.rangeCount!==1||M.anchorNode!==v.node||M.anchorOffset!==v.offset||M.focusNode!==p.node||M.focusOffset!==p.offset)){var b=q.createRange();b.setStart(v.node,v.offset),M.removeAllRanges(),je>Qe?(M.addRange(b),M.extend(p.node,p.offset)):(b.setEnd(p.node,p.offset),M.addRange(b))}}}}for(q=[],M=o;M=M.parentNode;)M.nodeType===1&&q.push({element:M,left:M.scrollLeft,top:M.scrollTop});for(typeof o.focus=="function"&&o.focus(),o=0;ol?32:l,T.T=null,l=fc,fc=null;var i=Fl,c=_l;if(ot=0,sn=Fl=null,_l=0,(Be&6)!==0)throw Error(r(331));var o=Be;if(Be|=4,Qd(i.current),Yd(i,i.current,c,l),Be=o,Wn(0,!1),ye&&typeof ye.onPostCommitFiberRoot=="function")try{ye.onPostCommitFiberRoot(W,i)}catch{}return!0}finally{k.p=s,T.T=a,cf(e,t)}}function rf(e,t,l){t=Zt(l,t),t=Ku(e.stateNode,t,2),e=Xl(e,t,2),e!==null&&(vn(e,2),fl(e))}function Ye(e,t,l){if(e.tag===3)rf(e,e,l);else for(;t!==null;){if(t.tag===3){rf(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Wl===null||!Wl.has(a))){e=Zt(l,e),l=rd(2),a=Xl(t,l,2),a!==null&&(dd(l,a,t,e),vn(a,2),fl(a));break}}t=t.return}}function vc(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new kh;var s=new Set;a.set(t,s)}else s=a.get(t),s===void 0&&(s=new Set,a.set(t,s));s.has(l)||(cc=!0,s.add(l),e=Vh.bind(null,e,t,l),t.then(e,e))}function Vh(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Xe===e&&(De&l)===l&&(Ie===4||Ie===3&&(De&62914560)===De&&300>tt()-Fs?(Be&2)===0&&un(e,0):oc|=l,nn===De&&(nn=0)),fl(e)}function df(e,t){t===0&&(t=ao()),e=ma(e,t),e!==null&&(vn(e,t),fl(e))}function Jh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),df(e,l)}function $h(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,s=e.memoizedState;s!==null&&(l=s.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),df(e,l)}function Wh(e,t){return Ee(e,t)}var ni=null,on=null,yc=!1,si=!1,gc=!1,Pl=0;function fl(e){e!==on&&e.next===null&&(on===null?ni=on=e:on=on.next=e),si=!0,yc||(yc=!0,Ih())}function Wn(e,t){if(!gc&&si){gc=!0;do for(var l=!1,a=ni;a!==null;){if(e!==0){var s=a.pendingLanes;if(s===0)var i=0;else{var c=a.suspendedLanes,o=a.pingedLanes;i=(1<<31-Ze(42|e)+1)-1,i&=s&~(c&~o),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(l=!0,pf(a,i))}else i=De,i=os(a,a===Xe?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||pn(a,i)||(l=!0,pf(a,i));a=a.next}while(l);gc=!1}}function Fh(){ff()}function ff(){si=yc=!1;var e=0;Pl!==0&&c0()&&(e=Pl);for(var t=tt(),l=null,a=ni;a!==null;){var s=a.next,i=mf(a,t);i===0?(a.next=null,l===null?ni=s:l.next=s,s===null&&(on=l)):(l=a,(e!==0||(i&3)!==0)&&(si=!0)),a=s}ot!==0&&ot!==5||Wn(e),Pl!==0&&(Pl=0)}function mf(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,s=e.expirationTimes,i=e.pendingLanes&-62914561;0o)break;var U=f.transferSize,q=f.initiatorType;U&&Nf(q)&&(f=f.responseEnd,c+=U*(f"u"?null:document;function wf(e,t,l){var a=rn;if(a&&typeof t=="string"&&t){var s=Xt(t);s='link[rel="'+e+'"][href="'+s+'"]',typeof l=="string"&&(s+='[crossorigin="'+l+'"]'),Rf.has(s)||(Rf.add(s),e={rel:e,crossOrigin:l,href:t},a.querySelector(s)===null&&(t=a.createElement("link"),yt(t,"link",e),rt(t),a.head.appendChild(t)))}}function y0(e){Dl.D(e),wf("dns-prefetch",e,null)}function g0(e,t){Dl.C(e,t),wf("preconnect",e,t)}function b0(e,t,l){Dl.L(e,t,l);var a=rn;if(a&&e&&t){var s='link[rel="preload"][as="'+Xt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(s+='[imagesrcset="'+Xt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(s+='[imagesizes="'+Xt(l.imageSizes)+'"]')):s+='[href="'+Xt(e)+'"]';var i=s;switch(t){case"style":i=dn(e);break;case"script":i=fn(e)}It.has(i)||(e=z({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),It.set(i,e),a.querySelector(s)!==null||t==="style"&&a.querySelector(es(i))||t==="script"&&a.querySelector(ts(i))||(t=a.createElement("link"),yt(t,"link",e),rt(t),a.head.appendChild(t)))}}function x0(e,t){Dl.m(e,t);var l=rn;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",s='link[rel="modulepreload"][as="'+Xt(a)+'"][href="'+Xt(e)+'"]',i=s;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=fn(e)}if(!It.has(i)&&(e=z({rel:"modulepreload",href:e},t),It.set(i,e),l.querySelector(s)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(ts(i)))return}a=l.createElement("link"),yt(a,"link",e),rt(a),l.head.appendChild(a)}}}function j0(e,t,l){Dl.S(e,t,l);var a=rn;if(a&&e){var s=Da(a).hoistableStyles,i=dn(e);t=t||"default";var c=s.get(i);if(!c){var o={loading:0,preload:null};if(c=a.querySelector(es(i)))o.loading=5;else{e=z({rel:"stylesheet",href:e,"data-precedence":t},l),(l=It.get(i))&&Rc(e,l);var f=c=a.createElement("link");rt(f),yt(f,"link",e),f._p=new Promise(function(j,U){f.onload=j,f.onerror=U}),f.addEventListener("load",function(){o.loading|=1}),f.addEventListener("error",function(){o.loading|=2}),o.loading|=4,ri(c,t,a)}c={type:"stylesheet",instance:c,count:1,state:o},s.set(i,c)}}}function S0(e,t){Dl.X(e,t);var l=rn;if(l&&e){var a=Da(l).hoistableScripts,s=fn(e),i=a.get(s);i||(i=l.querySelector(ts(s)),i||(e=z({src:e,async:!0},t),(t=It.get(s))&&wc(e,t),i=l.createElement("script"),rt(i),yt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(s,i))}}function N0(e,t){Dl.M(e,t);var l=rn;if(l&&e){var a=Da(l).hoistableScripts,s=fn(e),i=a.get(s);i||(i=l.querySelector(ts(s)),i||(e=z({src:e,async:!0,type:"module"},t),(t=It.get(s))&&wc(e,t),i=l.createElement("script"),rt(i),yt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(s,i))}}function Hf(e,t,l,a){var s=(s=ve.current)?oi(s):null;if(!s)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=dn(l.href),l=Da(s).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=dn(l.href);var i=Da(s).hoistableStyles,c=i.get(e);if(c||(s=s.ownerDocument||s,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},i.set(e,c),(i=s.querySelector(es(e)))&&!i._p&&(c.instance=i,c.state.loading=5),It.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},It.set(e,l),i||A0(s,e,l,c.state))),t&&a===null)throw Error(r(528,""));return c}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=fn(l),l=Da(s).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function dn(e){return'href="'+Xt(e)+'"'}function es(e){return'link[rel="stylesheet"]['+e+"]"}function Bf(e){return z({},e,{"data-precedence":e.precedence,precedence:null})}function A0(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),yt(t,"link",l),rt(t),e.head.appendChild(t))}function fn(e){return'[src="'+Xt(e)+'"]'}function ts(e){return"script[async]"+e}function qf(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Xt(l.href)+'"]');if(a)return t.instance=a,rt(a),a;var s=z({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),rt(a),yt(a,"style",s),ri(a,l.precedence,e),t.instance=a;case"stylesheet":s=dn(l.href);var i=e.querySelector(es(s));if(i)return t.state.loading|=4,t.instance=i,rt(i),i;a=Bf(l),(s=It.get(s))&&Rc(a,s),i=(e.ownerDocument||e).createElement("link"),rt(i);var c=i;return c._p=new Promise(function(o,f){c.onload=o,c.onerror=f}),yt(i,"link",a),t.state.loading|=4,ri(i,l.precedence,e),t.instance=i;case"script":return i=fn(l.src),(s=e.querySelector(ts(i)))?(t.instance=s,rt(s),s):(a=l,(s=It.get(i))&&(a=z({},l),wc(a,s)),e=e.ownerDocument||e,s=e.createElement("script"),rt(s),yt(s,"link",a),e.head.appendChild(s),t.instance=s);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,ri(a,l.precedence,e));return t.instance}function ri(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),s=a.length?a[a.length-1]:null,i=s,c=0;c title"):null)}function C0(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Lf(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function T0(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var s=dn(a.href),i=t.querySelector(es(s));if(i){t=i._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=fi.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=i,rt(i);return}i=t.ownerDocument||t,a=Bf(a),(s=It.get(s))&&Rc(a,s),i=i.createElement("link"),rt(i);var c=i;c._p=new Promise(function(o,f){c.onload=o,c.onerror=f}),yt(i,"link",a),l.instance=i}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=fi.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Hc=0;function E0(e,t){return e.stylesheets&&e.count===0&&hi(e,e.stylesheets),0Hc?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(s)}}:null}function fi(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)hi(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var mi=null;function hi(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,mi=new Map,t.forEach(M0,e),mi=null,fi.call(e))}function M0(e,t){if(!(t.state.loading&4)){var l=mi.get(e);if(l)var a=l.get(null);else{l=new Map,mi.set(e,l);for(var s=e.querySelectorAll("link[data-precedence],style[data-precedence]"),i=0;i"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(u)}catch(m){console.error(m)}}return u(),Kc.exports=Z0(),Kc.exports}var J0=V0();function be(u){return Array.isArray(u)?u:[]}function vm(u){const m=new Set;return u.map(h=>h.trim()).filter(h=>{const r=h.toLowerCase();return!h||m.has(r)?!1:(m.add(r),!0)})}function sl(u){const m=Ni.some(h=>h.value===u.streamMode)?u.streamMode:"auto";return{...u,streamMode:m,models:be(u.models),allowedGroupIds:be(u.allowedGroupIds),openaiAccounts:be(u.openaiAccounts),kiroAccounts:be(u.kiroAccounts)}}function cs(u){return{...u,aliases:be(u.aliases)}}function $0(u){return{...u,apiKeys:be(u.apiKeys),logs:be(u.logs)}}class Ci extends Error{status;payload;constructor(m,h,r){super(h),this.status=m,this.payload=r}}const W0={home:"M3 10.5 12 3l9 7.5V21a1 1 0 0 1-1 1h-5v-7H9v7H4a1 1 0 0 1-1-1z",users:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75",key:"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78ZM14 8l7-7M21 8h-5V3",models:"M12 2 4 6v12l8 4 8-4V6zM4 6l8 4 8-4M12 10v12",image:"M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2ZM8.5 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM21 16l-5-5L5 21",route:"M4 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM20 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM7 16h3a4 4 0 0 0 4-4V8h3",logs:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6M8 13h8M8 17h6",settings:"M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 8.92 4a1.65 1.65 0 0 0 1-1.51V2a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.31.39.57.71.71.23.1.49.18.8.2H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z",search:"M21 21l-4.35-4.35M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z",copy:"M8 8h11a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1ZM4 16H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v1",ban:"M4.93 4.93 19.07 19.07M22 12A10 10 0 1 1 2 12a10 10 0 0 1 20 0Z",check:"M20 6 9 17l-5-5",moon:"M21 12.8A8.5 8.5 0 1 1 11.2 3 6.5 6.5 0 0 0 21 12.8Z",sun:"M12 4V2M12 22v-2M4.93 4.93 3.52 3.52M20.48 20.48l-1.41-1.41M4 12H2M22 12h-2M4.93 19.07l-1.41 1.41M20.48 3.52l-1.41 1.41M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z",plus:"M12 5v14M5 12h14"};function Ot({name:u}){return n.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",className:"icon",children:n.jsx("path",{d:W0[u]})})}async function pe(u,m){const h=new Headers(m?.headers);h.set("Content-Type","application/json");const r=window.sessionStorage.getItem("capi-admin-token");r&&h.set("Authorization",`Bearer ${r}`);const A=await fetch(u,{credentials:"include",...m,headers:h});if(!A.ok){const E=await A.json().catch(()=>null);throw new Ci(A.status,E?.error?.message||`Request failed: ${A.status}`,E)}return A.json()}async function F0(u,m){const h=new Headers,r=window.sessionStorage.getItem("capi-admin-token");r&&h.set("Authorization",`Bearer ${r}`);const A=await fetch(u,{credentials:"include",method:"POST",headers:h,body:m});if(!A.ok){const E=await A.json().catch(()=>null);throw new Ci(A.status,E?.error?.message||`Request failed: ${A.status}`,E)}return A.json()}const dm=[{id:"overview",label:"概览",icon:"home"},{id:"users",label:"用户",icon:"users"},{id:"groups",label:"分组",icon:"users"},{id:"keys",label:"密钥",icon:"key"},{id:"models",label:"模型",icon:"models"},{id:"drawing",label:"绘图",icon:"image"},{id:"channels",label:"渠道",icon:"route"},{id:"logs",label:"日志",icon:"logs"},{id:"settings",label:"设置",icon:"settings"}],to=[{value:"kiro",label:"Kiro / Amazon Q"},{value:"codex",label:"Codex / ChatGPT OAuth"},{value:"antigravity",label:"Antigravity / Google"},{value:"cpa",label:"CPA / CLIProxyAPI"},{value:"openai",label:"OpenAI"},{value:"anthropic",label:"Anthropic / Claude"},{value:"google",label:"Google Gemini"},{value:"deepseek",label:"DeepSeek"},{value:"openrouter",label:"OpenRouter"},{value:"groq",label:"Groq"},{value:"siliconflow",label:"SiliconFlow"},{value:"moonshot",label:"Moonshot"},{value:"compatible",label:"OpenAI 兼容接口"}],ym="https://api.openai.com/v1",Ti="https://chatgpt.com/backend-api",gm="http://localhost:8317/v1",bm="https://codewhisperer.us-east-1.amazonaws.com",xm="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2, gpt-image-1",I0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2",P0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, claude-sonnet-4, gemini-3.1-pro",ep="claude-sonnet-4.5, claude-sonnet-4, claude-haiku-4.5, claude-opus-4.5",jm="https://daily-cloudcode-pa.googleapis.com",tp="claude-opus-4-6-thinking, claude-sonnet-4-6, gemini-3.8-flash-high, gemini-3.7-flash-high, gemini-3.6-flash-high, gemini-3-flash, gemini-pro-agent, gemini-3.1-pro-low, gpt-oss-120b-medium, gemini-3.1-flash-lite, gemini-3.5-flash-lite, gemini-3.1-flash-image",Fc=[{provider:"kiro",label:"Kiro / Amazon Q",name:"Kiro 账号池",baseUrl:bm,models:ep.split(",").map(u=>u.trim())},{provider:"openai",label:"OpenAI",name:"OpenAI 主线路",baseUrl:ym,models:I0.split(",").map(u=>u.trim())},{provider:"codex",label:"Codex 账号池",name:"Codex 账号池",baseUrl:Ti,models:xm.split(",").map(u=>u.trim())},{provider:"antigravity",label:"Antigravity 账号池",name:"Antigravity 账号池",baseUrl:jm,models:tp.split(",").map(u=>u.trim())},{provider:"cpa",label:"CPA / CLIProxyAPI",name:"CPA 本地代理",baseUrl:gm,models:P0.split(",").map(u=>u.trim())},{provider:"compatible",label:"OpenAI 兼容接口",name:"兼容渠道",baseUrl:"",models:[]},{provider:"openrouter",label:"OpenRouter",name:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",models:[]},{provider:"google",label:"Google Gemini",name:"Gemini",baseUrl:"",models:[]},{provider:"anthropic",label:"Anthropic / Claude",name:"Claude",baseUrl:"",models:[]}];function Ta(u){return Fc.find(m=>m.provider===u)||Fc[2]}function Ic(u){const m=Ta(u);return{name:m.name,provider:m.provider,baseUrl:m.baseUrl,models:[...m.models],streamMode:"auto"}}function lp(u){const m=u?.trim().toLowerCase();return m&&({free:"Free",plus:"Plus",pro:"Pro",team:"Team",enterprise:"Enterprise"}[m]||u)||"套餐未知"}function fm(u){return u?{upstream_token_invalidated:"Token 已失效",upstream_invalid_api_key:"API Key 无效",upstream_account_error:"账号错误",upstream_accounts_unavailable:"账号池不可用",upstream_error:"上游错误"}[u]||u:""}function Ei(u){return u==="openai"?ym:u==="codex"?Ti:u==="antigravity"?jm:u==="cpa"||u==="cliproxyapi"?gm:u==="kiro"?bm:""}function Pc(u){return vm(u.split(/[\s,;,;]+/))}function ap(u){return vm(u.split(/[\n,;,;]+/).map(m=>m.trim()))}function Sm(u){const m=ap(u);return m.length===0?{}:m.length===1?{upstreamApiKey:m[0]}:{upstreamApiKeys:m}}const Ni=[{value:"auto",label:"自动",description:"按请求参数处理"},{value:"real",label:"真流",description:"直连上游 SSE"},{value:"fake",label:"假流",description:"非流转 SSE"},{value:"disabled",label:"禁用流",description:"流式请求跳过"}];function el(u){if(!u)return"未使用";const m=new Date(u);return Number.isNaN(m.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(m)}function mm(u){if(!u)return"";const m=new Date(u);if(Number.isNaN(m.getTime()))return"";const h=m.getTimezoneOffset()*6e4;return new Date(m.getTime()-h).toISOString().slice(0,16)}function np(u){if(!u)return"";const m=new Date(u);return Number.isNaN(m.getTime())?"":m.toISOString()}function sp(u){if(!u)return"-";const m=new Date(u);return Number.isNaN(m.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).format(m)}function _t(u){return{active:"正常",disabled:"禁用",limited:"受限",overdue:"欠费",healthy:"正常",standby:"备用",available:"Available",success:"成功",failed:"失败"}[u]||u}function St(u,m=2){const h=Number(u||0);return new Intl.NumberFormat("zh-CN",{minimumFractionDigits:m,maximumFractionDigits:m}).format(h)}function ml(u){return new Intl.NumberFormat("zh-CN").format(Math.max(0,Math.round(Number(u||0))))}function lo(u){return u.model?u.model:u.errorCode==="invalid_api_key"?"密钥无效":u.errorCode==="model_not_available"?"模型不可用":u.errorCode==="insufficient_quota"?"额度不足":u.errorCode==="rate_limit_exceeded"?"请求过快":u.errorCode||"请求失败"}function ip(u){return u.model||(u.errorCode?`错误:${u.errorCode}`:"-")}function up(u){return u.channel||(u.apiKeyPrefix?`Key ${u.apiKeyPrefix}`:"-")}function cp(u){const m=be(u);if(m.length===0)return"未绑定模型";const h=m.slice(0,2).join(", ");return m.length>2?`${h} · 其余 ${m.length-2} 个`:h}function il(u){return u==="cliproxyapi"||u==="cli-proxy-api"?"CPA / CLIProxyAPI":to.find(m=>m.value===u)?.label||u||"Custom"}function $c(u){const m=`${u.vendor} ${u.id} ${u.name}`.toLowerCase();return m.includes("cliproxyapi")||/\bcpa\b/.test(m)?"cpa":m.includes("openai")||/\bgpt[-_/]/.test(m)||m.includes("o1-")||m.includes("o3-")?"openai":m.includes("anthropic")||m.includes("claude")?"anthropic":m.includes("google")||m.includes("gemini")||m.includes("gcli-")?"google":m.includes("deepseek")?"deepseek":m.includes("openrouter")?"openrouter":m.includes("groq")?"groq":m.includes("siliconflow")?"siliconflow":m.includes("moonshot")||m.includes("kimi")?"moonshot":u.vendor&&u.vendor.toLowerCase()!=="custom"?u.vendor.toLowerCase():"compatible"}function hm({provider:u}){if(u==="deepseek")return n.jsx("span",{className:"provider-icon provider-icon-deepseek","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("path",{transform:"translate(2.4 4.4)",d:"M26.517 3.395c-.282-.138-.403.125-.568.258-.057.044-.105.1-.152.152-.413.44-.895.73-1.524.695-.92-.052-1.705.237-2.4.941-.147-.868-.638-1.386-1.384-1.718-.39-.173-.786-.346-1.06-.721-.19-.268-.243-.566-.338-.86-.061-.176-.121-.357-.325-.388-.222-.034-.309.151-.396.307-.347.635-.481 1.334-.468 2.042.03 1.594.703 2.863 2.04 3.765.152.104.191.207.143.359-.091.31-.2.613-.295.924-.06.198-.151.242-.364.155-.734-.306-1.367-.76-1.927-1.308-.951-.92-1.81-1.934-2.882-2.729-.252-.185-.504-.358-.764-.522-1.094-1.062.143-1.935.43-2.038.3-.108.104-.48-.864-.475-.968.004-1.853.328-2.982.76-.165.065-.339.112-.516.151-1.024-.194-2.088-.237-3.199-.112-2.092.233-3.763 1.222-4.991 2.91C.254 7.972-.093 10.278.332 12.682c.446 2.535 1.74 4.633 3.728 6.274 2.062 1.7 4.436 2.534 7.145 2.375 1.645-.095 3.476-.316 5.542-2.064.521.259 1.068.363 1.975.44.699.065 1.371-.034 1.892-.142.816-.173.76-.929.465-1.067-2.392-1.114-1.866-.661-2.344-1.027 1.215-1.438 3.071-3.993 3.644-7.473.056-.384.128-.925.12-1.236-.005-.19.038-.263.255-.285.6-.069 1.18-.233 1.715-.527 1.55-.846 2.175-2.237 2.322-3.903.022-.255-.005-.518-.274-.652ZM13.014 18.395c-2.318-1.823-3.442-2.423-3.906-2.397-.434.026-.356.523-.26.847.1.32.23.54.412.82.126.186.213.462-.126.67-.746.461-2.044-.156-2.105-.186-1.51-.89-2.773-2.064-3.664-3.67-.86-1.545-1.358-3.204-1.44-4.974-.022-.427.104-.578.529-.656.56-.103 1.137-.125 1.697-.043 2.366.346 4.379 1.403 6.068 3.079.963.954 1.692 2.094 2.443 3.208.799 1.183 1.658 2.31 2.752 3.234.387.324.695.57.99.751-.89.1-2.374.121-3.39-.683Zm1.111-7.146c0-.19.152-.341.343-.341.043 0 .082.009.117.021.048.018.092.044.126.083.061.06.096.146.096.237a.341.341 0 0 1-.343.341.34.34 0 0 1-.339-.341Zm3.451 1.77c-.222.09-.443.168-.656.177-.33.017-.69-.117-.885-.281-.304-.255-.521-.397-.612-.842-.039-.19-.017-.483.017-.652.078-.362-.009-.595-.265-.807-.208-.172-.473-.22-.764-.22-.108 0-.208-.048-.282-.086-.121-.061-.221-.212-.126-.398.031-.06.178-.207.213-.233.395-.225.85-.151 1.272.018.39.16.686.453 1.111.867.434.501.512.639.759 1.015.196.294.373.596.495.942.073.215-.022.392-.277.5Z"})]})});if(u==="openai")return n.jsx("span",{className:"provider-icon provider-icon-openai","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("g",{transform:"translate(7 7.5) scale(0.065)",fill:"currentColor",stroke:"none",children:n.jsx("path",{d:"M267.06 111.34a71.78 71.78 0 0 0-6.17-58.91c-14.5-25.15-43.55-38.09-71.9-32.03A71.78 71.78 0 0 0 135.1.5C106 .43 80.21 19.16 71.29 46.85a71.79 71.79 0 0 0-47.98 34.8c-14.6 25.1-11.28 56.75 8.22 78.3a71.78 71.78 0 0 0 6.16 58.9c14.5 25.16 43.56 38.1 71.91 32.04a71.76 71.76 0 0 0 53.89 24.02c29.12.02 54.92-18.72 63.84-46.44a71.79 71.79 0 0 0 47.98-34.8c14.58-25.1 11.25-56.72-8.24-78.27zm-107.9 150.77a53.15 53.15 0 0 1-34.15-12.35c.43-.24 1.2-.66 1.7-.96l56.68-32.73a9.22 9.22 0 0 0 4.66-8.06v-79.9l23.95 13.83a.85.85 0 0 1 .47.66v66.16a53.42 53.42 0 0 1-53.3 53.35zM44.6 213.16a53.13 53.13 0 0 1-6.36-35.75c.42.25 1.15.7 1.68 1l56.68 32.73a9.24 9.24 0 0 0 9.31 0l69.2-39.95v27.66a.87.87 0 0 1-.34.74l-57.29 33.07a53.42 53.42 0 0 1-72.88-19.5zM29.7 90.05a53.1 53.1 0 0 1 27.76-23.36c0 .49-.03 1.36-.03 1.96v65.46a9.22 9.22 0 0 0 4.65 8.05l69.2 39.95-23.95 13.83a.86.86 0 0 1-.81.07L49.2 162.9A53.42 53.42 0 0 1 29.7 90.05zm196.8 45.8L157.3 95.9l23.95-13.82a.86.86 0 0 1 .81-.07l57.3 33.08a53.37 53.37 0 0 1-8.24 96.29v-65.46a9.2 9.2 0 0 0-4.62-8.06zm23.84-35.89c-.42-.26-1.15-.7-1.68-1.01l-56.68-32.73a9.25 9.25 0 0 0-9.31 0l-69.2 39.95V78.5a.87.87 0 0 1 .35-.74l57.28-33.05a53.35 53.35 0 0 1 79.24 55.25zM100.11 149.24l-23.96-13.83a.85.85 0 0 1-.46-.66V68.6a53.37 53.37 0 0 1 87.52-40.95c-.42.24-1.19.66-1.7.96l-56.68 32.73a9.22 9.22 0 0 0-4.66 8.06l-.04 79.85zm13.01-28.05L144 103.3l30.88 17.83v35.68L144 174.63l-30.88-17.82v-35.62z"})})]})});const m=u==="codex"?"C":u==="antigravity"?"G":u==="cpa"||u==="cliproxyapi"?"CPA":u==="anthropic"?"A":u==="google"?"✦":u==="openrouter"?"↗":u==="groq"?"G":u==="siliconflow"?"S":u==="moonshot"?"M":"◇";return n.jsx("span",{className:`provider-icon provider-icon-${u}`,"aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("text",{x:"16",y:"21",textAnchor:"middle",children:m})]})})}async function Ai(u){if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(u);return}const m=document.createElement("textarea");m.value=u,m.setAttribute("readonly","true"),m.style.position="fixed",m.style.opacity="0",document.body.appendChild(m),m.select(),document.execCommand("copy"),document.body.removeChild(m)}function Ul(){return window.location.origin}function op(){return`${Ul()}/api/auth/discord/callback`}function rp(){return`${Ul()}/`}function Wc(u){return{...u,redirectUri:u.redirectUri&&!u.redirectUri.includes("localhost")?u.redirectUri:op(),authSuccessUrl:u.authSuccessUrl&&!u.authSuccessUrl.includes("localhost")?u.authSuccessUrl:rp(),blockedGuildIds:be(u.blockedGuildIds),sessionTtlHours:u.sessionTtlHours||168}}function Mi(u){return u==="email"||u==="discord"?u:"username"}function dp(u){const h=(u.split("@")[0]||"user").toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^[-_]+|[-_]+$/g,"");return(h.length>=3?h:"user").slice(0,24)}function fp(){const[u,m]=g.useState("home"),[h,r]=g.useState("login"),[A,E]=g.useState(null),[L,$]=g.useState("overview"),[C,y]=g.useState(()=>{const w=window.localStorage.getItem("capi-theme");return w==="light"||w==="dark"?w:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}),[R,z]=g.useState("comfortable"),[P,ee]=g.useState(null),[de,ne]=g.useState([]),[le,ie]=g.useState([]),[xe,Y]=g.useState([]),[ge,F]=g.useState([]),[me,D]=g.useState([]),[ae,fe]=g.useState(""),[Ae,Te]=g.useState(""),[ue,Z]=g.useState(null),[re,J]=g.useState(""),[T,k]=g.useState(""),[B,Q]=g.useState(!1),O=g.useMemo(()=>{const w=ae.trim().toLowerCase();return w?de.filter(K=>`${K.id} ${K.name} ${K.email}`.toLowerCase().includes(w)):de},[ae,de]);async function d(){const w=new Date().getTimezoneOffset(),[K,te,W,ye,qe,Ze]=await Promise.all([pe(`/api/overview?timezoneOffset=${w}`),pe("/api/users"),pe("/api/channels"),pe("/api/models"),pe("/api/logs"),pe("/api/groups")]),Ut=be(te.users),Rl=be(W.channels).map(sl),ca=be(ye.models).map(cs),Ea=be(qe.logs),Ma=be(Ze.groups);ee(K),ne(Ut),ie(Rl),Y(Ma),F(ca),D(Ea),Te(wl=>wl&&Ut.some(hl=>hl.id===wl)?wl:Ut[0]?.id||""),Ut.length===0&&Z(null),Q(!0)}async function x(w){const K=await pe(`/api/users/${w}`);Z($0(K))}async function G(w,K){const te=await pe(`/api/users/${w}`,{method:"PATCH",body:JSON.stringify(K)});ne(W=>W.map(ye=>ye.id===w?te.user:ye)),Z(W=>W?.user.id===w?{...W,user:te.user}:W),J("已更新用户"),window.setTimeout(()=>J(""),1800)}async function X(w,K,te={}){const W=await pe("/api/users/bulk",{method:"POST",body:JSON.stringify({userIds:w,action:K,...te})}),ye=new Map(be(W.users).map(qe=>[qe.id,qe]));ne(qe=>qe.map(Ze=>ye.get(Ze.id)||Ze)),Z(qe=>{if(!qe)return qe;const Ze=ye.get(qe.user.id);return Ze?{...qe,user:Ze}:qe}),J(`已处理 ${W.updated} 个用户`),window.setTimeout(()=>J(""),1800)}async function se(w){const K=await pe(`/api/users/${w}/api-keys`,{method:"POST",body:JSON.stringify({name:"Console Key"})});ue?.user.id===w&&Z({...ue,apiKeys:[...ue.apiKeys,K.apiKey]}),k(K.secret),await Ai(K.secret),J("新 Key 已创建并复制,请立即保存"),window.setTimeout(()=>J(""),2400)}async function ve(w){window.confirm("删除这个 Key?删除后使用它的请求会立即失效。")&&(await pe(`/api/api-keys/${w}`,{method:"DELETE"}),Z(K=>K&&{...K,apiKeys:K.apiKeys.filter(te=>te.id!==w)}),J("Key 已删除"),window.setTimeout(()=>J(""),1800))}async function N(w,K){const te=await pe(`/api/api-keys/${w}`,{method:"PATCH",body:JSON.stringify(K)});Z(W=>W&&{...W,apiKeys:W.apiKeys.map(ye=>ye.id===w?te.apiKey:ye)}),J("Key 已更新"),window.setTimeout(()=>J(""),1800)}async function Ne(w,K){const te=await pe(`/api/channels/${w}`,{method:"PATCH",body:JSON.stringify(K)});ie(W=>W.map(ye=>ye.id===w?sl(te.channel):ye)),Pe(te.removedModels),J("渠道已更新"),window.setTimeout(()=>J(""),1800)}async function Se(w){const K=le.find(W=>W.id===w);if(!window.confirm(`删除渠道「${K?.name||w}」?`))return;const te=await pe(`/api/channels/${w}`,{method:"DELETE"});ie(W=>W.filter(ye=>ye.id!==w)),Pe(te.removedModels),J("渠道已删除"),window.setTimeout(()=>J(""),1800)}async function bt(w){const K=await pe("/api/groups",{method:"POST",body:JSON.stringify(w)});Y(te=>[...te,K.group]),J("分组已创建"),window.setTimeout(()=>J(""),1800)}async function I(w,K){const te=await pe(`/api/groups/${w}`,{method:"PATCH",body:JSON.stringify(K)});Y(W=>W.map(ye=>ye.id===w?te.group:ye)),J("分组已更新"),window.setTimeout(()=>J(""),1800)}async function Ke(w){const K=xe.find(te=>te.id===w);window.confirm(`删除分组「${K?.name||w}」?删除后渠道的可见范围会移除该分组。`)&&(await pe(`/api/groups/${w}`,{method:"DELETE"}),Y(te=>te.filter(W=>W.id!==w)),ie(te=>te.map(W=>({...W,allowedGroupIds:W.allowedGroupIds.filter(ye=>ye!==w)}))),J("分组已删除"),window.setTimeout(()=>J(""),1800))}async function We(w,K){const te=be(K).map(Ut=>Ut.trim()).filter(Boolean),W=await pe(`/api/channels/${w}/sync-models`,{method:"POST",body:JSON.stringify(te.length?{models:te}:{})}),ye=sl(W.channel),qe=be(W.addedModels).map(cs),Ze=be(W.models);ie(Ut=>Ut.map(Rl=>Rl.id===w?ye:Rl)),qe.length>0&&F(Ut=>{const Rl=new Set(Ut.map(ca=>ca.id.toLowerCase()));return[...Ut,...qe.filter(ca=>!Rl.has(ca.id.toLowerCase()))]}),Pe(W.removedModels),J(te.length?`已保存 ${Ze.length} 个模型`:Ze.length?`已拉取 ${Ze.length} 个模型`:"上游没有返回模型"),window.setTimeout(()=>J(""),2200)}function Pe(w){const K=new Set(be(w).map(te=>te.toLowerCase()));K.size!==0&&(F(te=>te.filter(W=>!K.has(W.id.toLowerCase()))),Z(te=>te&&{...te,apiKeys:te.apiKeys.map(W=>({...W,allowedModels:W.allowedModels.filter(ye=>!K.has(ye.toLowerCase()))}))}))}async function tl(w){try{const K=await pe(`/api/channels/${w}/check`,{method:"POST",body:JSON.stringify({})});ie(te=>te.map(W=>W.id===w?sl(K.channel):W)),J(K.ok?`渠道可用,检测到 ${be(K.models).length} 个模型`:"渠道检测失败")}catch(K){const te=K instanceof Ci?K.payload?.channel:null;te&&ie(W=>W.map(ye=>ye.id===w?sl(te):ye)),J(K instanceof Error?K.message:"渠道检测失败")}window.setTimeout(()=>J(""),2400)}async function kt(w=Ic("codex")){const K=await pe("/api/channels",{method:"POST",body:JSON.stringify(w)});ie(te=>[...te,sl(K.channel)]),J("渠道已创建,可继续拉取模型或检测渠道"),window.setTimeout(()=>J(""),2400)}async function cl(w,K){const te=new FormData;te.append("file",K);const W=await F0(`/api/channels/${encodeURIComponent(w)}/import-openai-accounts`,te);ie(ye=>ye.map(qe=>qe.id===W.channel.id?sl(W.channel):qe)),J(`新增 ${W.created??W.imported} 个账号${W.updated?`,更新 ${W.updated} 个已有账号`:""}${W.skipped?`,跳过 ${W.skipped} 个`:""}`),window.setTimeout(()=>J(""),2600)}async function V(w,K=!1,te=""){const W=await pe(`/api/channels/${encodeURIComponent(w)}/openai-accounts/check`,{method:"POST",body:JSON.stringify({onlyInvalid:K,accountId:te})});ie(ye=>ye.map(qe=>qe.id===W.channel.id?sl(W.channel):qe)),J(`${K?"无效账号复检":"账号测活"}完成:${W.healthy}/${W.checked} 可用${W.failed?`,无效 ${W.failed}`:""}`),window.setTimeout(()=>J(""),3e3)}async function _(w){const K=await pe(`/api/channels/${encodeURIComponent(w)}/openai-accounts/deduplicate`,{method:"POST",body:JSON.stringify({})});ie(te=>te.map(W=>W.id===K.channel.id?sl(K.channel):W)),J(K.removed?`已合并 ${K.removed} 个重复账号`:"未发现可识别的重复账号"),window.setTimeout(()=>J(""),2600)}async function Ee(w,K){const te=await pe(`/api/channels/${encodeURIComponent(w)}/openai-accounts/${encodeURIComponent(K)}`,{method:"DELETE"});ie(W=>W.map(ye=>ye.id===te.channel.id?sl(te.channel):ye)),J("账号已删除"),window.setTimeout(()=>J(""),1800)}async function et(w){return pe(`/api/channels/${encodeURIComponent(w)}/openai-oauth/start`,{method:"POST",body:JSON.stringify({})})}async function xt(w,K){const te=await pe(`/api/channels/${encodeURIComponent(w)}/openai-oauth/complete`,{method:"POST",body:JSON.stringify(K)});return ie(W=>W.map(ye=>ye.id===te.channel.id?sl(te.channel):ye)),J("已通过 OAuth 添加账号"),window.setTimeout(()=>J(""),2400),te}async function ft(w){const K=await pe("/api/models",{method:"POST",body:JSON.stringify(w)});F(te=>[...te,cs(K.model)]),J("模型已添加"),window.setTimeout(()=>J(""),1800)}async function tt(w,K){const te=await pe(`/api/models/${encodeURIComponent(w)}`,{method:"PATCH",body:JSON.stringify(K)});F(W=>W.map(ye=>ye.id===w?cs(te.model):ye)),J("模型已更新"),window.setTimeout(()=>J(""),1600)}async function zi(w){window.confirm(`删除模型 ${w}?渠道和 Key 中的引用也会一起清理。`)&&(await pe(`/api/models/${encodeURIComponent(w)}`,{method:"DELETE"}),F(K=>K.filter(te=>te.id!==w)),ie(K=>K.map(te=>({...te,models:te.models.filter(W=>W!==w)}))),Z(K=>K&&{...K,apiKeys:K.apiKeys.map(te=>({...te,allowedModels:te.allowedModels.filter(W=>W!==w)}))}),J("模型已删除"),window.setTimeout(()=>J(""),1800))}async function hn(w,K="已复制"){await Ai(w),J(K),window.setTimeout(()=>J(""),1600)}function ia(w,K){if(w instanceof Ci&&w.status===401){Q(!1),r("login"),m("auth");return}J(K)}async function ua(){try{const w=await pe("/api/auth/status");if(E(w),!w.initialized){r("setup"),m("auth");return}if(!w.authenticated){r("login"),m("auth");return}m(w.session?.role==="admin"?"console":"account")}catch(w){ia(w,"认证状态加载失败")}}async function Oi(){await pe("/api/auth/logout",{method:"POST"}),window.sessionStorage.removeItem("capi-admin-token"),E(null),m("home")}return g.useEffect(()=>{let w=!1;return pe("/api/auth/status").then(K=>{w||(E(K),K.authenticated&&K.session&&m(K.session.role==="admin"?"console":"account"))}).catch(()=>{}),()=>{w=!0}},[]),g.useEffect(()=>{u==="console"&&(Q(!1),d().catch(w=>ia(w,"加载数据失败")))},[u]),g.useEffect(()=>{u!=="console"||!B||x(Ae).catch(w=>ia(w,"加载用户详情失败"))},[Ae,u,B]),g.useEffect(()=>{window.localStorage.setItem("capi-theme",C)},[C]),g.useEffect(()=>{window.scrollTo({top:0,left:0})},[u,L]),u==="home"?n.jsx(bp,{theme:C,setTheme:y,enterConsole:ua}):u==="auth"?n.jsx(mp,{theme:C,mode:h,status:A,setTheme:y,setMode:r,goHome:()=>m("home"),onAuthenticated:w=>{E(K=>K?{...K,authenticated:!0,initialized:!0,session:w}:null),m(w.role==="admin"?"console":"account")}}):u==="account"?n.jsx(gp,{theme:C,setTheme:y,goHome:()=>m("home"),openLogin:ua}):n.jsxs("div",{className:"app-shell","data-theme":C,"data-density":R,children:[n.jsxs("aside",{className:"sidebar",children:[n.jsxs("div",{className:"ios-window-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsxs("div",{className:"brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"聚合网关"})]})]}),n.jsx("nav",{children:dm.map(w=>n.jsxs("button",{className:L===w.id?"nav-item active":"nav-item",onClick:()=>$(w.id),children:[n.jsx(Ot,{name:w.icon}),n.jsx("span",{className:"nav-label",children:w.label})]},w.id))}),n.jsxs("div",{className:"sidebar-footer",children:[n.jsx("span",{children:"Gateway"}),n.jsxs("strong",{children:[n.jsx("span",{className:"pulse-dot"}),"Online"]})]})]}),n.jsxs("main",{className:"content",children:[n.jsxs("header",{className:"topbar",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Admin Console"}),n.jsx("h1",{children:dm.find(w=>w.id===L)?.label})]}),n.jsxs("div",{className:"topbar-actions",children:[n.jsx(Vp,{value:R,options:[{value:"comfortable",label:"舒适"},{value:"compact",label:"紧凑"}],onChange:w=>z(w)}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>y(C==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:C==="dark"?"sun":"moon"}),n.jsx("span",{children:C==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:()=>d().catch(w=>ia(w,"刷新失败")),children:"刷新"}),n.jsx("button",{className:"secondary-button home-link",onClick:()=>m("home"),children:"首页"}),n.jsx("button",{className:"secondary-button",onClick:Oi,children:"退出"})]})]}),L==="overview"&&n.jsx(xp,{overview:P,channels:le,logs:me,onNavigate:w=>{$(w),w==="channels"&&le.length===0&&J("渠道页可以创建第一个上游"),w==="logs"&&me.length===0&&J("暂无异常日志"),window.setTimeout(()=>J(""),1800)}}),L==="users"&&n.jsx(Sp,{users:O,query:ae,selectedUser:ue,onQuery:fe,onSelect:Te,onUpdate:G,onBulkUpdate:X,onCreateKey:se,groups:xe,onOpenRegistration:()=>{$("settings"),J("在账号与注册里开放注册,用户即可自助创建账号"),window.setTimeout(()=>J(""),2400)}}),L==="groups"&&n.jsx(Kp,{groups:xe,onCreate:bt,onUpdate:I,onDelete:Ke}),L==="keys"&&n.jsx(Np,{selectedUser:ue,onCreateKey:se,onUpdateKey:N,onDeleteKey:ve}),L==="models"&&n.jsx(Cp,{models:ge,onCopy:hn,onCreate:ft,onUpdate:tt,onDelete:zi}),L==="drawing"&&n.jsx(Mp,{channels:le,onCreate:kt,onImport:cl,onCheckAccounts:V,onDeduplicateAccounts:_,onDeleteAccount:Ee,onUpdate:Ne,onStartOAuth:et,onCompleteOAuth:xt}),L==="channels"&&n.jsx(Yp,{channels:le,groups:xe,onUpdate:Ne,onCreate:kt,onImport:cl,onDelete:Se,onSyncModels:We,onCheck:tl}),L==="logs"&&n.jsx(kp,{logs:me,onCopy:hn}),L==="settings"&&n.jsx(Xp,{models:ge,channels:le,groups:xe})]}),T&&n.jsx("div",{className:"secret-dialog-backdrop",role:"presentation",children:n.jsxs("section",{className:"secret-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"secret-dialog-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"One-time secret"}),n.jsx("h2",{id:"secret-dialog-title",children:"完整 API Key"})]}),n.jsx("p",{children:"完整密钥只显示这一次。列表中的星号内容只是识别前缀,不能用于 API 调用。"}),n.jsx("code",{children:T}),n.jsxs("div",{className:"secret-dialog-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>{Ai(T),J("完整 Key 已复制"),window.setTimeout(()=>J(""),1800)},children:"复制"}),n.jsx("button",{className:"primary-button",onClick:()=>k(""),children:"完成"})]})]})}),re&&n.jsx("div",{className:"toast",children:re})]})}function mp({theme:u,mode:m,status:h,setTheme:r,setMode:A,goHome:E,onAuthenticated:L}){const[$,C]=g.useState(""),[y,R]=g.useState(""),[z,P]=g.useState(""),[ee,de]=g.useState(""),[ne,le]=g.useState(""),[ie,xe]=g.useState(""),[Y,ge]=g.useState(!1),[F,me]=g.useState("username"),[D,ae]=g.useState("0"),[fe,Ae]=g.useState(""),[Te,ue]=g.useState(!1),Z=m==="setup",re=m==="register",J=Mi(h?.registrationMode),T=re&&J==="email",k=re&&J==="discord";async function B(){if(!k){if((Z||re)&&ne!==ie){Ae("两次输入的密码不一致");return}ue(!0),Ae("");try{const Q=Z?"/api/auth/setup":re?"/api/auth/register":"/api/auth/login",O=T?dp(z):$,d=m==="login"?{identifier:$,password:ne}:{username:O,password:ne,displayName:y,email:z,discordUserId:Z?ee:"",registrationEnabled:Z?Y:void 0,registrationMode:Z?F:void 0,defaultBalance:Z?Number(D||0):void 0},x=await pe(Q,{method:"POST",body:JSON.stringify(d)});L(x.session)}catch(Q){Ae(Q instanceof Error?Q.message:"操作失败")}finally{ue(!1)}}}return n.jsxs("main",{className:"auth-page","data-theme":u,children:[n.jsxs("header",{className:"auth-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:E,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>r(u==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:u==="dark"?"sun":"moon"}),n.jsx("span",{children:u==="dark"?"浅色":"暗色"})]})]}),n.jsxs("section",{className:"auth-stage",children:[n.jsxs("div",{className:"auth-intro",children:[n.jsx("span",{children:Z?"First Run":"Welcome Back"}),n.jsx("h1",{children:Z?"初始化 CAPI":re?"创建账号":"登录"}),n.jsx("p",{children:Z?"创建第一个管理员账号,完成后即可进入控制台。":"使用你的 CAPI 账号继续。"})]}),n.jsxs("form",{className:"auth-form",onSubmit:Q=>{Q.preventDefault(),B()},children:[k?n.jsxs("div",{className:"auth-discord-register",children:[n.jsx("strong",{children:"使用 Discord 创建账号"}),n.jsx("span",{children:"继续后会按站点设置校验服务器和身份组。"}),h?.discordEnabled?n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"继续使用 Discord"}):n.jsx("div",{className:"auth-message",children:"管理员还没有启用 Discord 登录"})]}):n.jsxs(n.Fragment,{children:[m!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:y,onChange:Q=>R(Q.target.value),autoComplete:"name",placeholder:"CAPI"})]}),!T&&n.jsxs("label",{children:[n.jsx("span",{children:m==="login"?"账号或邮箱":"账号"}),n.jsx("input",{value:$,onChange:Q=>C(Q.target.value),autoComplete:"username",placeholder:m==="login"?"输入账号或邮箱":"3-32 位字母、数字、_ 或 -"})]}),(Z||T)&&n.jsxs("label",{children:[n.jsx("span",{children:T?"邮箱":"邮箱(可选)"}),n.jsx("input",{type:"email",value:z,onChange:Q=>P(Q.target.value),autoComplete:"email",placeholder:"name@example.com"})]}),Z&&n.jsxs(n.Fragment,{children:[n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:ee,onChange:Q=>de(Q.target.value),placeholder:"绑定管理员 Discord 账号"})]}),n.jsxs("div",{className:"setup-options",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放注册"}),n.jsx("button",{type:"button",className:Y?"ios-switch is-on":"ios-switch","aria-pressed":Y,onClick:()=>ge(Q=>!Q),children:n.jsx("span",{})})]}),n.jsxs("label",{children:[n.jsx("span",{children:"注册方式"}),n.jsxs("select",{value:F,onChange:Q=>me(Mi(Q.target.value)),children:[n.jsx("option",{value:"username",children:"账号密码"}),n.jsx("option",{value:"email",children:"邮箱"}),n.jsx("option",{value:"discord",children:"Discord"})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新用户初始额度"}),n.jsx("input",{type:"number",min:"0",step:"0.01",value:D,onChange:Q=>ae(Q.target.value)})]})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"密码"}),n.jsx("input",{type:"password",value:ne,onChange:Q=>le(Q.target.value),autoComplete:m==="login"?"current-password":"new-password",placeholder:"至少 8 个字符"})]}),m!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"确认密码"}),n.jsx("input",{type:"password",value:ie,onChange:Q=>xe(Q.target.value),autoComplete:"new-password",placeholder:"再次输入密码"})]}),n.jsx("div",{className:"auth-message",role:"status",children:fe}),n.jsx("button",{className:"primary-button auth-submit",type:"submit",disabled:Te,children:Te?"请稍候":Z?"创建管理员":re?"注册":"登录"})]}),!Z&&!k&&h?.discordEnabled&&n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"使用 Discord 登录"}),!Z&&n.jsx("div",{className:"auth-switch",children:m==="login"&&h?.registrationEnabled?n.jsx("button",{type:"button",onClick:()=>A("register"),children:"创建账号"}):n.jsx("button",{type:"button",onClick:()=>A("login"),children:"返回登录"})})]})]})]})}const hp=[1,1.5,2,2.5,3,4,5,6,8,10];function pp(u){if(!(u>0))return 1;const m=Math.floor(Math.log10(u)),h=Math.pow(10,m),r=u/h;return(hp.find(E=>r<=E)??10)*h}const pm=88;function vp(u){const m=u.split("-");return m.length===3?`${m[1]}/${m[2]}`:u}function yp(){const[u,m]=g.useState(14),[h,r]=g.useState(null),[A,E]=g.useState(!0),[L,$]=g.useState(!1),[C,y]=g.useState("");g.useEffect(()=>{let Y=!1;return E(!0),pe(`/api/account/usage?days=${u}&timezoneOffset=${new Date().getTimezoneOffset()}`).then(ge=>{Y||(r({...ge.usage,daily:be(ge.usage?.daily),models:be(ge.usage?.models)}),$(!1))}).catch(()=>{Y||$(!0)}).finally(()=>{Y||E(!1)}),()=>{Y=!0}},[u]);const R=h?.daily??[],z=h?.models??[],P=pp(Math.max(0,...R.map(Y=>Y.cost))),ee=Math.max(0,...z.map(Y=>Y.cost)),de=R.reduce((Y,ge)=>!Y||ge.cost>Y.cost?ge:Y,null),ne=Math.max(1,Math.ceil(R.length/5)),le=R.find(Y=>Y.day===C)||null,ie=le?R.indexOf(le):-1,xe=h?h.today.cost-h.yesterday.cost:0;return n.jsxs("section",{className:"account-section usage-section",children:[n.jsx("div",{className:"account-section-title",children:n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Usage"}),n.jsx("h2",{children:"用量概览"})]})}),!h&&A&&n.jsx("p",{className:"usage-placeholder",children:"正在统计用量…"}),!h&&!A&&L&&n.jsx("p",{className:"usage-placeholder",children:"用量加载失败,请稍后重试"}),h&&n.jsxs("div",{className:A?"usage-body is-refreshing":"usage-body",children:[n.jsxs("div",{className:"usage-kpi",children:[n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"今日消费"}),n.jsx("strong",{children:St(h.today.cost)}),n.jsxs("small",{children:["较昨日 ",xe>=0?"+":"−",St(Math.abs(xe))]})]}),n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"本月消费"}),n.jsx("strong",{children:St(h.month.cost)}),n.jsxs("small",{children:[ml(h.month.requests)," 次请求"]})]}),n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"今日请求"}),n.jsx("strong",{children:ml(h.today.requests)}),n.jsxs("small",{children:["成功率 ",h.today.successRate,"%"]})]}),n.jsxs("div",{className:"usage-tile",children:[n.jsx("span",{children:"累计消费"}),n.jsx("strong",{children:St(h.total.cost)}),n.jsxs("small",{children:[ml(h.total.requests)," 次请求"]})]})]}),n.jsx("div",{className:"usage-range",role:"group","aria-label":"统计范围",children:[7,14,30].map(Y=>n.jsxs("button",{type:"button",className:u===Y?"selected":"","aria-pressed":u===Y,onClick:()=>m(Y),children:["近 ",Y," 天"]},Y))}),n.jsxs("div",{className:"usage-block",children:[n.jsxs("div",{className:"usage-block-head",children:[n.jsx("strong",{children:"每日消费"}),n.jsxs("span",{children:["近 ",h.rangeDays," 天"]})]}),R.length===0||P<=0?n.jsx("p",{className:"usage-placeholder",children:"这段时间还没有消费记录"}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"usage-plot",children:[n.jsx("div",{className:"usage-grid","aria-hidden":"true",children:[1,.5,0].map(Y=>n.jsx("div",{className:"usage-gridline",style:{bottom:`${Y*pm}%`},children:n.jsx("span",{children:St(P*Y)})},Y))}),n.jsxs("div",{className:"usage-columns",children:[R.map((Y,ge)=>{const F=P>0?Y.cost/P*pm:0,me=Y.cost>0,D=me&&de!==null&&Y.day===de.day,ae=ge%ne===0||ge===R.length-1;return n.jsxs("div",{className:"usage-column",children:[n.jsxs("button",{type:"button",className:C===Y.day?"usage-column-hit is-hovered":"usage-column-hit",onMouseEnter:()=>y(Y.day),onMouseLeave:()=>y(""),onFocus:()=>y(Y.day),onBlur:()=>y(""),"aria-label":`${Y.day} 消费 ${St(Y.cost)},${Y.requests} 次请求`,children:[me&&n.jsx("span",{className:"usage-column-bar",style:{height:`${F}%`}}),D&&n.jsx("span",{className:"usage-column-peak",style:{bottom:`calc(${F}% + 6px)`},children:St(Y.cost)})]}),n.jsx("span",{className:"usage-column-tick",children:ae?vp(Y.day):""})]},Y.day)}),le&&n.jsxs("div",{className:"usage-tooltip",style:{left:`${(ie+.5)/R.length*100}%`},role:"status",children:[n.jsx("strong",{children:St(le.cost)}),n.jsx("span",{children:le.day}),n.jsxs("span",{children:[le.requests," 次请求"]})]})]})]}),n.jsxs("details",{className:"usage-table-toggle",children:[n.jsx("summary",{children:"查看数据表"}),n.jsxs("div",{className:"usage-table",children:[n.jsxs("div",{className:"usage-table-head",children:[n.jsx("span",{children:"日期"}),n.jsx("span",{children:"请求"}),n.jsx("span",{children:"消费"})]}),R.slice().reverse().map(Y=>n.jsxs("div",{className:"usage-table-row",children:[n.jsx("span",{children:Y.day}),n.jsx("span",{children:Y.requests}),n.jsx("span",{children:St(Y.cost)})]},Y.day))]})]})]})]}),n.jsxs("div",{className:"usage-block",children:[n.jsxs("div",{className:"usage-block-head",children:[n.jsx("strong",{children:"按模型拆分"}),n.jsxs("span",{children:["近 ",h.rangeDays," 天消费"]})]}),z.length===0?n.jsx("p",{className:"usage-placeholder",children:"这段时间还没有调用记录"}):n.jsx("div",{className:"usage-models",children:z.map(Y=>n.jsxs("div",{className:"usage-model-row",children:[n.jsx("span",{className:"usage-model-name",title:Y.model,children:Y.model}),n.jsx("span",{className:"usage-model-track",children:n.jsx("span",{className:"usage-model-bar",style:{width:`${ee>0?Y.cost/ee*100:0}%`}})}),n.jsx("span",{className:"usage-model-value",children:St(Y.cost)})]},Y.model))})]})]})]})}function gp({theme:u,setTheme:m,goHome:h,openLogin:r}){const[A,E]=g.useState(null),[L,$]=g.useState([]),[C,y]=g.useState(null),[R,z]=g.useState(!1),[P,ee]=g.useState(""),[de,ne]=g.useState(""),[le,ie]=g.useState("");async function xe(){try{const[D,ae,fe]=await Promise.all([pe("/api/account/me"),pe("/api/catalog/models"),pe("/api/account/check-in")]);E({...D,apiKeys:be(D.apiKeys)}),$(be(ae.models).map(cs)),y(fe.checkIn)}catch{r()}}g.useEffect(()=>{xe()},[]);async function Y(){if(!(!C?.enabled||C.claimed||R)){z(!0),ee("");try{const D=await pe("/api/account/check-in",{method:"POST",body:JSON.stringify({})});E(ae=>ae&&{...ae,user:D.user}),y(D.checkIn),ee(`签到成功,获得 ${D.reward.toFixed(2)} 额度`)}catch(D){ee(D instanceof Error?D.message:"签到失败,请稍后重试")}finally{z(!1)}}}async function ge(){try{const D=await pe("/api/account/api-keys",{method:"POST",body:JSON.stringify({name:"My API Key"})});ne(D.secret),ie("新密钥只显示这一次"),await xe()}catch(D){ie(D instanceof Error?D.message:"创建密钥失败")}}async function F(D){if(window.confirm("删除这个 API Key?使用它的请求会立即失效。"))try{await pe(`/api/account/api-keys/${D}`,{method:"DELETE"}),E(ae=>ae&&{...ae,apiKeys:ae.apiKeys.filter(fe=>fe.id!==D)}),ie("密钥已删除")}catch(ae){ie(ae instanceof Error?ae.message:"删除密钥失败")}}async function me(){await pe("/api/auth/logout",{method:"POST"}),h()}return n.jsxs("main",{className:"account-page","data-theme":u,children:[n.jsxs("header",{className:"account-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:h,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("div",{className:"account-actions",children:[n.jsx("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>m(u==="dark"?"light":"dark"),children:n.jsx(Ot,{name:u==="dark"?"sun":"moon"})}),n.jsx("button",{className:"secondary-button",onClick:me,children:"退出"})]})]}),n.jsxs("section",{className:"account-content",children:[n.jsxs("div",{className:"account-heading",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"My CAPI"}),n.jsx("h1",{children:A?.user.name||"账户"})]}),n.jsxs("div",{className:"account-balance",children:[n.jsx("span",{children:"余额"}),n.jsx("strong",{children:A?A.user.balance.toFixed(2):"-"})]})]}),n.jsx(yp,{}),n.jsxs("section",{className:"account-section check-in-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Daily Reward"}),n.jsx("h2",{children:"每日签到"})]}),n.jsx("button",{className:"primary-button",disabled:!C?.enabled||!!C?.claimed||R,onClick:Y,children:R?"领取中":C?.claimed?"今日已签到":C?.enabled?"签到领额度":"暂未开放"})]}),n.jsxs("div",{className:"check-in-summary",children:[n.jsxs("div",{children:[n.jsx("span",{children:"今日状态"}),n.jsx("strong",{children:C?.claimed?`已领取 ${C.reward.toFixed(2)}`:C?.enabled?"等待签到":"活动关闭"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"随机奖励"}),n.jsx("strong",{children:C?`${C.minReward.toFixed(2)} - ${C.maxReward.toFixed(2)}`:"-"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"结算日期"}),n.jsx("strong",{children:C?.day||"北京时间"})]})]}),n.jsx("p",{className:"check-in-note",children:"每天按北京时间 00:00 刷新,奖励领取后直接计入账户余额。"}),P&&n.jsx("p",{className:"account-message check-in-message",role:"status",children:P})]}),n.jsxs("section",{className:"account-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"API Keys"}),n.jsx("h2",{children:"API 密钥"})]}),n.jsx("button",{className:"primary-button",onClick:ge,children:"创建密钥"})]}),de&&n.jsx("code",{className:"one-time-secret",children:de}),le&&n.jsx("p",{className:"account-message",children:le}),n.jsxs("div",{className:"account-key-list",children:[A?.apiKeys?.map(D=>n.jsxs("div",{className:"account-key-item",children:[n.jsx("span",{className:"account-key-mark","aria-hidden":"true",children:n.jsx(Ot,{name:"key"})}),n.jsxs("div",{className:"account-key-info",children:[n.jsx("strong",{children:D.name}),n.jsxs("code",{children:[D.prefix,"…"]})]}),n.jsx(Dt,{tone:D.status,children:_t(D.status)}),n.jsx("button",{className:"icon-button","aria-label":`删除 ${D.name}`,title:"删除密钥",onClick:()=>F(D.id),children:n.jsx(Ot,{name:"ban"})})]},D.id)),be(A?.apiKeys).length===0&&n.jsx("div",{className:"empty",children:"还没有 API 密钥"})]})]}),n.jsxs("section",{className:"account-section",children:[n.jsx("div",{className:"account-section-title",children:n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Models"}),n.jsx("h2",{children:"可用模型"})]})}),n.jsxs("div",{className:"account-model-grid",children:[L.map(D=>n.jsxs("article",{children:[n.jsx("span",{children:D.vendor}),n.jsx("strong",{children:D.name}),n.jsx("p",{children:D.description}),n.jsx("code",{children:D.id})]},D.id)),L.length===0&&n.jsx("div",{className:"account-model-empty",children:"暂无可用模型,管理员配置渠道后将在此展示"})]})]})]})]})}function bp({theme:u,setTheme:m,enterConsole:h}){return n.jsxs("main",{className:"public-home","data-theme":u,children:[n.jsxs("header",{className:"home-topbar",children:[n.jsxs("div",{className:"home-brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"AI 聚合网关"})]})]}),n.jsxs("div",{className:"home-actions",children:[n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>m(u==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:u==="dark"?"sun":"moon"}),n.jsx("span",{children:u==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:h,children:"控制台"})]})]}),n.jsxs("section",{className:"home-hero",children:[n.jsxs("div",{className:"home-copy",children:[n.jsx("span",{className:"home-kicker",children:"兼容 OpenAI 格式的网关"}),n.jsxs("h1",{children:["CAPI",n.jsx("span",{children:"轻量 AI 聚合网关"})]}),n.jsx("p",{children:"面向个人用户和团队的模型接入层。把 API Key、额度、模型渠道和调用日志放在一个清爽控制台里,保持轻量,也便于排障。"}),n.jsx("div",{className:"home-cta",children:n.jsx("button",{className:"primary-button",onClick:h,children:"进入控制台"})}),n.jsxs("div",{className:"integration-row","aria-label":"网关能力概览",children:[n.jsx("span",{children:"网关能力"}),n.jsxs("div",{children:[n.jsx("span",{children:"OpenAI 兼容接口"}),n.jsx("span",{children:"额度控制"}),n.jsx("span",{children:"调用审计"})]})]})]}),n.jsxs("div",{className:"gateway-terminal","aria-label":"CAPI 终端请求示意",children:[n.jsxs("div",{className:"terminal-titlebar",children:[n.jsxs("div",{className:"terminal-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsx("strong",{children:"CAPI Terminal"}),n.jsxs("div",{className:"terminal-status",children:[n.jsx("span",{className:"pulse-dot"}),n.jsx("strong",{children:"Online"})]})]}),n.jsxs("div",{className:"terminal-endpoint",children:[n.jsx("span",{children:"POST"}),n.jsx("strong",{children:"/v1/chat/completions"})]}),n.jsxs("div",{className:"terminal-body",children:[n.jsxs("div",{className:"terminal-block",children:[n.jsx("span",{children:"REQUEST"}),n.jsx("pre",{children:`curl https://api.capi.local/v1/chat/completions \\ - -H "Authorization: Bearer cat_..." \\ - -d '{ - "model": "capi-fast", - "messages": [{ "role": "user", "content": "ping" }] - }'`})]}),n.jsxs("div",{className:"terminal-route",children:[n.jsxs("div",{children:[n.jsx("span",{children:"auth"}),n.jsx("strong",{children:"pass"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"quota"}),n.jsx("strong",{children:"ok"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"route"}),n.jsx("strong",{children:"capi-fast"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"latency"}),n.jsx("strong",{children:"186ms"})]})]}),n.jsxs("div",{className:"terminal-block response",children:[n.jsx("span",{children:"RESPONSE"}),n.jsxs("pre",{children:[`{ - "status": 200, - "model": "capi-fast", - "usage": { "total_tokens": 27 }, - "message": "request routed" -}`,n.jsx("span",{className:"terminal-caret","aria-hidden":"true"})]})]})]})]})]})]})}function xp({overview:u,channels:m,logs:h,onNavigate:r}){const A=h.filter(E=>E.status!=="success");return n.jsxs("section",{className:"page-stack",children:[n.jsxs("div",{className:"hero-strip",children:[n.jsxs("div",{children:[n.jsx("span",{children:"Live Gateway"}),n.jsxs("strong",{children:["CAPI 网关正在服务 ",u?.activeUsers??"-"," 个活跃用户"]}),n.jsx("p",{children:"请求进入 CAPI 后,会按额度、模型和渠道状态自动选择最合适的上游。"})]}),n.jsxs("div",{className:"live-island",children:[n.jsx("div",{className:"pulse-dot"}),n.jsx("span",{children:"在线"})]})]}),n.jsxs("div",{className:"quick-actions","aria-label":"快捷操作",children:[n.jsx(Si,{icon:"key",label:"创建 Key",onClick:()=>r("keys")}),n.jsx(Si,{icon:"route",label:"配置渠道",onClick:()=>r("channels")}),n.jsx(Si,{icon:"users",label:"调整额度",onClick:()=>r("users")}),n.jsx(Si,{icon:"logs",label:"查看异常",onClick:()=>r("logs")})]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(ul,{label:"活跃用户",value:u?ml(u.activeUsers):"-"}),n.jsx(ul,{label:"今日请求",value:u?ml(u.requestsToday):"-"}),n.jsx(ul,{label:"今日输入",value:u?ml(u.todayInputTokens):"-"}),n.jsx(ul,{label:"今日输出",value:u?ml(u.todayOutputTokens):"-"}),n.jsx(ul,{label:"今日扣费",value:u?St(u.todayCost,4):"-"}),n.jsx(ul,{label:"账户余额",value:u?St(u.totalBalance):"-"}),n.jsx(ul,{label:"成功率",value:u?`${u.successRate}%`:"-"})]}),n.jsx(jp,{}),n.jsxs("div",{className:"split-grid",children:[n.jsx(nt,{title:"渠道状态",children:m.length?m.map(E=>n.jsxs("div",{className:"list-row overview-channel-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:E.name}),n.jsx("span",{title:be(E.models).join(", "),children:cp(E.models)})]}),n.jsx(Dt,{tone:E.status,children:_t(E.status)})]},E.id)):n.jsx(Lt,{text:"暂无渠道"})}),n.jsx(nt,{title:"最近请求",children:h.length?h.slice(0,4).map(E=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:lo(E)}),n.jsxs("span",{children:[E.id," · ",E.errorCode||el(E.createdAt)]})]}),n.jsx(Dt,{tone:E.status,children:_t(E.status)})]},E.id)):n.jsx(Lt,{text:A.length?"暂无最近请求":"暂无请求"})})]})]})}function Si({icon:u,label:m,onClick:h}){return n.jsxs("button",{className:"quick-action",onClick:h,children:[n.jsx(Ot,{name:u}),n.jsx("span",{children:m})]})}function jp(){const u=[{label:"认证",detail:"校验 API Key"},{label:"额度",detail:"检查余额"},{label:"路由",detail:"选择渠道"},{label:"响应",detail:"返回结果"}];return n.jsxs("section",{className:"flow-panel","aria-label":"网关流转",children:[n.jsxs("div",{className:"flow-copy",children:[n.jsx("span",{children:"Request Flow"}),n.jsx("strong",{children:"请求处理流程"})]}),n.jsx("div",{className:"flow-steps",children:u.map((m,h)=>n.jsxs("div",{className:"flow-step",children:[n.jsx("div",{className:"flow-index",children:h+1}),n.jsx("strong",{children:m.label}),n.jsx("span",{children:m.detail})]},m.label))})]})}function Sp({users:u,query:m,selectedUser:h,onQuery:r,onSelect:A,onUpdate:E,onBulkUpdate:L,onCreateKey:$,groups:C,onOpenRegistration:y}){const[z,P]=g.useState(1),[ee,de]=g.useState("all"),[ne,le]=g.useState(new Set),[ie,xe]=g.useState("10"),[Y,ge]=g.useState(""),[F,me]=g.useState(""),[D,ae]=g.useState(!1),[fe,Ae]=g.useState("10"),[Te,ue]=g.useState(""),[Z,re]=g.useState(""),[J,T]=g.useState(!1),k=ee==="all"?u:u.filter(N=>N.status===ee),B=k.filter(N=>N.role!=="admin"),Q=Math.max(1,Math.ceil(k.length/25)),O=Math.min(z,Q),d=k.slice((O-1)*25,O*25),x=B.length>0&&B.every(N=>ne.has(N.id));g.useEffect(()=>{P(1)},[m,ee]),g.useEffect(()=>{const N=new Set(u.map(Ne=>Ne.id));le(Ne=>new Set([...Ne].filter(Se=>N.has(Se))))},[u]),g.useEffect(()=>{Ae("10"),ue(""),re("")},[h?.user.id]);function G(N){le(Ne=>{const Se=new Set(Ne);return Se.has(N)?Se.delete(N):Se.add(N),Se})}function X(){le(N=>{const Ne=new Set(N);return x?B.forEach(Se=>Ne.delete(Se.id)):B.forEach(Se=>Ne.add(Se.id)),Ne})}async function se(N,Ne){if(ne.size!==0){ae(!0);try{await L([...ne],N,Ne),le(new Set),ge("")}finally{ae(!1)}}}async function ve(N){if(!h)return;const Ne=Math.abs(Number(fe));if(!Number.isFinite(Ne)||Ne<=0){re("请输入大于 0 的金额");return}T(!0),re("");try{await L([h.user.id],"adjust_balance",{amount:Number((Ne*N).toFixed(4)),reason:Te.trim()||(N>0?"管理员增加额度":"管理员扣减额度")}),re(N>0?"额度已增加":"额度已扣减"),ue("")}catch(Se){re(Se instanceof Error?Se.message:"额度调整失败")}finally{T(!1)}}return n.jsxs("section",{className:"users-layout",children:[n.jsxs(nt,{title:"用户管理",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Ot,{name:"search"}),n.jsx("input",{value:m,onChange:N=>r(N.target.value),placeholder:"搜索 ID、姓名或邮箱"})]}),n.jsx("button",{className:"icon-button",title:"开放注册",onClick:y,children:n.jsx(Ot,{name:"plus"})})]}),n.jsxs("div",{className:"user-summary-strip",children:[n.jsxs("span",{children:[n.jsx("strong",{children:u.length})," 匹配用户"]}),n.jsxs("span",{children:[n.jsx("strong",{children:u.filter(N=>N.status==="active").length})," 正常"]}),n.jsxs("span",{children:[n.jsx("strong",{children:u.filter(N=>N.status==="disabled").length})," 禁用"]}),n.jsxs("span",{children:[n.jsx("strong",{children:u.reduce((N,Ne)=>N+Ne.requestsToday,0)})," 今日请求"]})]}),n.jsx("div",{className:"user-filter-row",role:"group","aria-label":"用户状态筛选",children:[{value:"all",label:"全部"},{value:"active",label:"正常"},{value:"limited",label:"受限"},{value:"disabled",label:"禁用"}].map(N=>n.jsx("button",{type:"button",className:ee===N.value?"selected":"",onClick:()=>de(N.value),children:N.label},N.value))}),n.jsx("button",{type:"button",className:"secondary-button mobile-bulk-select",onClick:X,children:x?"取消全选":`全选结果(${B.length})`}),ne.size>0&&n.jsxs("div",{className:"bulk-action-bar",children:[n.jsxs("strong",{children:["已选 ",ne.size," 人"]}),n.jsx("input",{type:"number",step:"0.01",value:ie,onChange:N=>xe(N.target.value),"aria-label":"额度调整值"}),n.jsx("input",{value:Y,onChange:N=>ge(N.target.value),placeholder:"原因,例如:活动赠送","aria-label":"调整原因"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:D||!Number(ie),onClick:()=>se("adjust_balance",{amount:Number(ie),reason:Y}),children:"调整额度"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:D,onClick:()=>se("set_status",{value:"active"}),children:"启用"}),n.jsx("button",{type:"button",className:"danger-button",disabled:D,onClick:()=>se("set_status",{value:"disabled"}),children:"禁用"}),n.jsxs("select",{className:"bulk-group-select",value:F,disabled:D,"aria-label":"批量设置分组",onChange:N=>me(N.target.value),children:[n.jsx("option",{value:"",children:"未分组"}),C.map(N=>n.jsx("option",{value:N.id,children:N.name},N.id))]}),n.jsx("button",{type:"button",className:"secondary-button",disabled:D,onClick:()=>se("set_group",{value:F}),children:"设为分组"})]}),n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head users-table",children:[n.jsx("input",{type:"checkbox",checked:x,onChange:X,"aria-label":"选择当前筛选结果"}),n.jsx("span",{children:"用户"}),n.jsx("span",{children:"状态"}),n.jsx("span",{children:"余额"}),n.jsx("span",{children:"今日"})]}),d.map(N=>n.jsxs("div",{className:h?.user.id===N.id?"table-row users-table selected":"table-row users-table",role:"button",tabIndex:0,onClick:()=>A(N.id),onKeyDown:Ne=>{(Ne.key==="Enter"||Ne.key===" ")&&A(N.id)},children:[n.jsx("input",{type:"checkbox",checked:ne.has(N.id),disabled:N.role==="admin",onChange:()=>G(N.id),onClick:Ne=>Ne.stopPropagation(),"aria-label":N.role==="admin"?`${N.name} 是管理员,不参与批量操作`:`选择 ${N.name}`}),n.jsxs("span",{children:[n.jsx("strong",{children:N.name}),n.jsxs("small",{children:[N.id," · ",N.email||"未绑定邮箱"]})]}),n.jsx(Dt,{tone:N.status,children:_t(N.status)}),n.jsx("span",{children:St(N.balance)}),n.jsx("span",{children:N.requestsToday})]},N.id)),k.length===0&&n.jsx(Lt,{text:"暂无匹配用户"})]}),k.length>25&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:O<=1,onClick:()=>P(N=>Math.max(1,N-1)),children:"上一页"}),n.jsxs("span",{children:[O," / ",Q]}),n.jsx("button",{className:"secondary-button",disabled:O>=Q,onClick:()=>P(N=>Math.min(Q,N+1)),children:"下一页"})]})]}),n.jsx(nt,{title:"用户详情",children:h?n.jsxs("div",{className:"detail-stack",children:[n.jsxs("div",{className:"user-hero",children:[n.jsx("div",{className:"avatar",children:h.user.name.slice(0,1)}),n.jsxs("div",{children:[n.jsx("h2",{children:h.user.name}),n.jsx("p",{children:h.user.email})]}),n.jsx(Dt,{tone:h.user.status,children:_t(h.user.status)})]}),n.jsxs("div",{className:"settings-group",children:[n.jsx(Pt,{label:"角色",value:h.user.role==="admin"?"管理员":"用户"}),n.jsx(Pt,{label:"余额",value:St(h.user.balance)}),n.jsx(Pt,{label:"总请求",value:String(h.user.totalRequests)}),n.jsx(Pt,{label:"最后登录",value:el(h.user.lastLoginAt)}),n.jsx(Pt,{label:"API 调用",value:h.user.status==="disabled"?"关闭":"允许",switchOn:h.user.status!=="disabled"})]}),n.jsxs("div",{className:"group-assign-row",children:[n.jsxs("label",{children:[n.jsx("span",{children:"所属分组"}),n.jsxs("select",{value:h.user.groupId||"",onChange:N=>E(h.user.id,{groupId:N.target.value}),children:[n.jsx("option",{value:"",children:"未分组"}),C.map(N=>n.jsx("option",{value:N.id,children:N.name},N.id))]})]}),n.jsx("small",{children:"分组决定该用户可路由到哪些渠道;未分组用户只能使用未限制分组的渠道。"})]}),n.jsxs("div",{className:"balance-adjuster",children:[n.jsxs("div",{className:"balance-adjuster-title",children:[n.jsx("strong",{children:"调整余额"}),n.jsxs("span",{children:["当前 ",St(h.user.balance)]})]}),n.jsxs("div",{className:"balance-adjuster-fields",children:[n.jsxs("label",{children:[n.jsx("span",{children:"金额"}),n.jsx("input",{type:"number",min:"0.0001",step:"0.01",value:fe,onChange:N=>Ae(N.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"备注"}),n.jsx("input",{value:Te,onChange:N=>ue(N.target.value),placeholder:"可选,会记录到流水"})]})]}),n.jsxs("div",{className:"balance-adjuster-actions",children:[n.jsx("button",{className:"secondary-button",disabled:J,onClick:()=>ve(1),children:"增加"}),n.jsx("button",{className:"danger-button",disabled:J,onClick:()=>ve(-1),children:"扣减"}),n.jsx("span",{role:"status",children:Z})]})]}),n.jsxs("div",{className:"action-row",children:[n.jsx("button",{className:"secondary-button",onClick:()=>$(h.user.id),children:"创建 Key"}),n.jsx("button",{className:"secondary-button",disabled:h.user.role==="admin",onClick:()=>E(h.user.id,{status:h.user.status==="disabled"?"active":"disabled"}),children:h.user.role==="admin"?"管理员保护":h.user.status==="disabled"?"解封":"禁用"})]}),n.jsxs("div",{children:[n.jsx("h3",{children:"API Key"}),h.apiKeys.map(N=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:N.name}),n.jsxs("span",{children:[N.prefix,"*** · ",N.requestCount," 次"]})]}),n.jsx(Dt,{tone:N.status,children:_t(N.status)})]},N.id)),h.apiKeys.length===0&&n.jsx(Lt,{text:"暂无 API Key"})]})]}):n.jsx(Lt,{text:"请选择一个用户"})})]})}function Np({selectedUser:u,onCreateKey:m,onUpdateKey:h,onDeleteKey:r}){return n.jsx(nt,{title:"密钥管理",children:u?n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("span",{className:"muted-inline",children:[u.user.name," · 完整 Key 只在创建时显示,丢失请重新创建"]}),n.jsx("button",{className:"primary-button",onClick:()=>m(u.user.id),children:"创建 Key"})]}),u.apiKeys.length?u.apiKeys.map(A=>n.jsx(Ap,{apiKey:A,onSave:h,onDelete:r},A.id)):n.jsx(Lt,{text:"暂无密钥"})]}):n.jsx(Lt,{text:"请选择一个用户"})})}function Ap({apiKey:u,onSave:m,onDelete:h}){const[r,A]=g.useState(u.name),[E,L]=g.useState(be(u.allowedModels).join(", ")),[$,C]=g.useState(mm(u.expiresAt||"")),[y,R]=g.useState(String(u.rateLimitPerMinute||"")),[z,P]=g.useState(!1),ee=be(u.allowedModels).length?be(u.allowedModels).join(", "):"全部模型";g.useEffect(()=>{A(u.name),L(be(u.allowedModels).join(", ")),C(mm(u.expiresAt||"")),R(String(u.rateLimitPerMinute||""))},[u]);async function de(){P(!0);try{await m(u.id,{name:r.trim()||"API Key",allowedModels:Pc(E),expiresAt:np($),rateLimitPerMinute:Number(y||0)})}finally{P(!1)}}return n.jsxs("details",{className:"key-editor key-editor-collapsible",children:[n.jsxs("summary",{className:"key-editor-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:u.name}),n.jsxs("span",{children:[u.prefix,"*** · ",ee," · 最后使用 ",el(u.lastUsedAt)]})]}),n.jsxs("div",{className:"row-actions",children:[n.jsx(Dt,{tone:u.status,children:_t(u.status)}),n.jsx("span",{className:"key-expand-hint",children:"管理"})]})]}),n.jsxs("div",{className:"key-editor-body",children:[n.jsxs("div",{className:"key-editor-grid",children:[n.jsxs("label",{children:["名称",n.jsx("input",{value:r,onChange:ne=>A(ne.target.value)})]}),n.jsxs("label",{children:["允许模型",n.jsx("input",{value:E,onChange:ne=>L(ne.target.value),placeholder:"留空表示全部模型,多个用逗号分隔"})]}),n.jsxs("label",{children:["过期时间",n.jsx("input",{type:"datetime-local",value:$,onChange:ne=>C(ne.target.value)})]}),n.jsxs("label",{children:["每分钟限制",n.jsx("input",{type:"number",min:"0",value:y,onChange:ne=>R(ne.target.value),placeholder:"0 使用全局限制"})]})]}),n.jsxs("div",{className:"key-editor-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>m(u.id,{status:u.status==="active"?"disabled":"active"}),children:u.status==="active"?"停用密钥":"启用密钥"}),n.jsx("button",{className:"danger-button",onClick:()=>h(u.id),children:"删除密钥"}),n.jsx("button",{className:"primary-button",disabled:z,onClick:de,children:z?"保存中":"保存设置"})]})]})]})}function Cp({models:u,onCopy:m,onCreate:h,onUpdate:r,onDelete:A}){const E=u.filter(B=>B.recommended),[L,$]=g.useState(""),[C,y]=g.useState("all"),[R,z]=g.useState("all"),[P,ee]=g.useState(1),[de,ne]=g.useState(""),[le,ie]=g.useState(""),[xe,Y]=g.useState(""),[ge,F]=g.useState(""),[me,D]=g.useState(""),[ae,fe]=g.useState(""),Ae=60,Te=g.useMemo(()=>{const B=new Map;return u.forEach(Q=>{const O=$c(Q);B.set(O,(B.get(O)||0)+1)}),Array.from(B.entries()).sort((Q,O)=>O[1]-Q[1]||il(Q[0]).localeCompare(il(O[0]))).map(([Q,O])=>({provider:Q,count:O}))},[u]),ue=g.useMemo(()=>{const B=L.trim().toLowerCase();return u.filter(Q=>C!=="all"&&$c(Q)!==C||R!=="all"&&Q.status!==R?!1:B?[Q.id,Q.name,Q.vendor,Q.category,Q.description,...be(Q.aliases)].join(" ").toLowerCase().includes(B):!0)},[u,L,C,R]),Z=g.useMemo(()=>{const B=new Map;ue.forEach(G=>{const X=$c(G);B.set(X,[...B.get(X)||[],G])});const Q=[];let O=[],d=0;const x=Array.from(B.entries()).sort((G,X)=>il(G[0]).localeCompare(il(X[0])));for(const G of x)O.length>0&&d+G[1].length>Ae&&(Q.push(O),O=[],d=0),O.push(G),d+=G[1].length;return O.length>0&&Q.push(O),Q},[ue]),re=Math.max(1,Z.length),J=Math.min(P,re),T=Z[J-1]||[];g.useEffect(()=>{ee(1)},[L,C,R,u.length]);async function k(B){B.preventDefault();const Q=de.trim();if(Q){fe("");try{await h({id:Q,name:le.trim()||Q,vendor:xe.trim()||"Custom",aliases:ge.split(",").map(O=>O.trim()).filter(Boolean),category:"通用",description:me.trim(),price:"自定义",context:"未配置上下文"}),ne(""),ie(""),Y(""),F(""),D("")}catch(O){fe(O instanceof Error?O.message:"模型添加失败")}}}return n.jsxs("section",{className:"models-page",children:[n.jsx("div",{className:"model-hero",children:n.jsxs("div",{children:[n.jsx("span",{children:"Model Catalog"}),n.jsx("strong",{children:"Models"})]})}),n.jsx(nt,{title:"新增模型",children:n.jsxs("form",{className:"model-create-form",onSubmit:k,children:[n.jsx("input",{value:de,onChange:B=>ne(B.target.value),placeholder:"模型 ID,例如 openai/gpt-4.1"}),n.jsx("input",{value:le,onChange:B=>ie(B.target.value),placeholder:"显示名称(可选)"}),n.jsx("input",{value:xe,onChange:B=>Y(B.target.value),placeholder:"供应商(可选)"}),n.jsx("input",{value:ge,onChange:B=>F(B.target.value),placeholder:"代称,多个用逗号分隔(可选)"}),n.jsx("input",{className:"model-create-wide",value:me,onChange:B=>D(B.target.value),placeholder:"描述(可选)"}),n.jsx("button",{className:"primary-button",type:"submit",children:"新增模型"}),n.jsx("div",{className:"model-create-message",role:"status",children:ae})]})}),E.length>0&&n.jsx(nt,{title:"推荐模型",children:n.jsx("div",{className:"model-grid",children:E.map(B=>n.jsx(Ep,{model:B,featured:!0,onCopy:m,onUpdate:r},B.id))})}),n.jsxs(nt,{title:"全部模型",children:[n.jsxs("div",{className:"panel-toolbar model-list-toolbar",children:[n.jsx("input",{value:L,onChange:B=>$(B.target.value),placeholder:"搜索模型 ID、名称、供应商或代称"}),n.jsx("div",{className:"model-filter-actions",children:[{value:"all",label:"全部"},{value:"available",label:"可用"},{value:"disabled",label:"禁用"}].map(B=>n.jsx("button",{type:"button",className:R===B.value?"selected":"",onClick:()=>z(B.value),children:B.label},B.value))})]}),n.jsxs("div",{className:"model-provider-filter","aria-label":"按供应商筛选模型",children:[n.jsxs("button",{type:"button",className:C==="all"?"selected":"",onClick:()=>y("all"),children:[n.jsx("span",{className:"provider-icon provider-icon-all","aria-hidden":"true",children:"All"}),n.jsx("strong",{children:"全部"}),n.jsx("small",{children:u.length})]}),Te.map(B=>n.jsxs("button",{type:"button",className:C===B.provider?"selected":"",onClick:()=>y(B.provider),children:[n.jsx(hm,{provider:B.provider}),n.jsx("strong",{children:il(B.provider)}),n.jsx("small",{children:B.count})]},B.provider))]}),n.jsxs("div",{className:"model-list-summary",children:[n.jsx("span",{children:C==="all"?"全部供应商":il(C)}),n.jsx("strong",{children:ue.length}),n.jsx("span",{children:"个模型"})]}),ue.length>0?n.jsxs(n.Fragment,{children:[n.jsx("div",{className:"model-provider-groups",children:T.map(([B,Q])=>n.jsxs("section",{className:"model-provider-group",children:[n.jsxs("header",{children:[n.jsx(hm,{provider:B}),n.jsxs("div",{children:[n.jsx("strong",{children:il(B)}),n.jsxs("span",{children:[Q.length," 个模型"]})]})]}),n.jsx("div",{className:"model-compact-grid",children:Q.map(O=>n.jsx(Tp,{model:O,onCopy:m,onUpdate:r,onDelete:A},O.id))})]},B))}),re>1&&n.jsxs("div",{className:"pager",children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>ee(B=>Math.max(1,B-1)),disabled:J<=1,children:"上一页"}),n.jsxs("span",{children:[J," / ",re]}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>ee(B=>Math.min(re,B+1)),disabled:J>=re,children:"下一页"})]})]}):n.jsx(Lt,{text:u.length?"没有匹配的模型":"暂无模型,请先添加你要开放给用户调用的模型 ID"})]})]})}function Tp({model:u,onCopy:m,onUpdate:h,onDelete:r}){const A=be(u.aliases).slice(0,3),E=u.status==="disabled";return n.jsxs("article",{className:"model-compact-row",children:[n.jsxs("div",{className:"model-compact-main",children:[n.jsx("strong",{children:u.name}),n.jsx("small",{children:u.id}),A.length>0&&n.jsx("span",{children:A.map(L=>n.jsx("em",{children:L},L))})]}),n.jsxs("div",{className:"model-row-actions",children:[n.jsx(Dt,{tone:u.status,children:_t(u.status)}),u.recommended&&n.jsx("span",{className:"model-recommended-mark",children:"推荐"}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>m(u.id,"模型 ID 已复制"),children:n.jsx(Ot,{name:"copy"})}),n.jsxs("details",{className:"model-row-menu",children:[n.jsx("summary",{"aria-label":"模型操作",children:"•••"}),n.jsxs("div",{children:[n.jsx("button",{type:"button",onClick:()=>h(u.id,{recommended:!u.recommended}),children:u.recommended?"取消推荐":"设为推荐"}),n.jsx("button",{type:"button",onClick:()=>h(u.id,{status:E?"available":"disabled"}),children:E?"启用模型":"停用模型"}),n.jsx("button",{className:"is-danger",type:"button",onClick:()=>r(u.id),children:"删除模型"})]})]})]})]})}function Ep({model:u,featured:m=!1,onCopy:h,onUpdate:r}){return n.jsxs("article",{className:m?"model-card featured":"model-card",children:[n.jsxs("div",{className:"model-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:u.name}),n.jsxs("span",{children:[u.vendor," · ",u.category]})]}),n.jsx(Dt,{tone:u.status,children:_t(u.status)})]}),n.jsx("p",{children:u.description}),n.jsx("div",{className:"alias-row",children:be(u.aliases).map(A=>n.jsx("span",{children:A},A))}),n.jsxs("div",{className:"model-meta",children:[n.jsxs("span",{children:["价格:",u.price]}),n.jsx("span",{children:u.context})]}),n.jsxs("div",{className:"model-id",children:[n.jsx("code",{children:u.id}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>h(u.id,"模型 ID 已复制"),children:n.jsx(Ot,{name:"copy"})})]}),r&&n.jsxs("div",{className:"model-card-actions",children:[n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(u.id,{recommended:!1}),children:"取消推荐"}),n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(u.id,{status:u.status==="disabled"?"available":"disabled"}),children:u.status==="disabled"?"启用":"停用"})]})]})}function Mp({channels:u,onCreate:m,onImport:h,onCheckAccounts:r,onDeduplicateAccounts:A,onDeleteAccount:E,onUpdate:L,onStartOAuth:$,onCompleteOAuth:C}){const y=u.filter(O=>O.provider==="codex"||O.provider==="antigravity"||O.provider==="openai"||be(O.models).some(d=>d.includes("image"))),[R,z]=g.useState(""),[P,ee]=g.useState({}),[de,ne]=g.useState({}),[le,ie]=g.useState({}),[xe,Y]=g.useState({}),[ge,F]=g.useState(""),[me,D]=g.useState(""),[ae,fe]=g.useState(""),[Ae,Te]=g.useState(""),ue=24,Z=48;async function re(O,d){z(`import:${O}`);try{await h(O,d)}finally{z("")}}async function J(O,d=!1,x=""){z(x?`check-account:${x}`:`${d?"retry":"check"}:${O}`);try{await r(O,d,x)}finally{z("")}}async function T(O){z(`dedupe:${O}`);try{await A(O)}finally{z("")}}function k(O){const d=be(O.openaiAccounts).map(N=>[N.email||N.name||N.accountId||N.id,N.accountId||"",N.status||"unchecked",N.credentialMode||"access-token",N.planType||"",N.expiresAt||"",N.lastCheckedAt||"",N.lastUsedAt||"",String(N.requestCount||0),N.lastErrorCode||"",N.lastError||""]),x=N=>`"${N.replace(/"/g,'""')}"`,G=[["账号","Account ID","状态","凭据方式","套餐","到期时间","最近检测","最近调用","调用次数","错误码","最后错误"],...d].map(N=>N.map(x).join(",")).join(`\r -`),X=new Blob(["\uFEFF"+G],{type:"text/csv;charset=utf-8"}),se=URL.createObjectURL(X),ve=document.createElement("a");ve.href=se,ve.download=`${O.name||"account-pool"}-health-report.csv`,ve.click(),URL.revokeObjectURL(se)}async function B(O){z(`status:${O.id}`);try{await L(O.id,{status:O.status==="disabled"?"healthy":"disabled",baseUrl:O.baseUrl||Ei(O.provider)||Ti,provider:O.provider||"codex",models:be(O.models).length?O.models:xm.split(",").map(d=>d.trim())})}finally{z("")}}async function Q(O,d){const x=d.email||d.name||d.accountId||d.id;if(window.confirm(`删除账号「${x}」?`)){z(`delete-account:${d.id}`);try{await E(O.id,d.id)}finally{z("")}}}return n.jsxs(nt,{title:"账号池",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"账号有两种来源,任选其一即可。"}),n.jsx("button",{className:"primary-button",onClick:()=>m(Ic("codex")),children:"新增账号池渠道"}),n.jsx("button",{className:"secondary-button",onClick:()=>m(Ic("antigravity")),children:"新增 Antigravity 账号池"})]}),n.jsxs("div",{className:"source-guide",children:[n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"网页会话(推荐)"}),n.jsx("span",{children:"支持完整 auth/session JSON 或浏览器 Session Cookie,并在调用前重新获取 accessToken。"})]}),n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"批量导入"}),n.jsx("span",{children:"支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 access token。"})]})]}),n.jsxs("div",{className:"channels-stack",children:[y.map(O=>{const d=be(O.openaiAccounts),x=d.filter(V=>V.status==="healthy").length,G=d.filter(V=>V.status==="invalid").length,X=d.filter(V=>!!V.lastErrorCode).length,se=Math.max(0,d.length-x-G),ve=d.filter(V=>V.credentialMode==="refreshable").length,N=d.filter(V=>V.credentialMode==="browser-session").length,Ne=Math.max(0,d.length-ve-N),Se=de[O.id]||"all",bt=(le[O.id]||"").trim().toLowerCase(),I=d.filter(V=>{const _=Se==="all"||Se==="attention"&&Gp(V)||Se==="invalid"&&V.status==="invalid"||Se==="error"&&!!V.lastErrorCode||Se==="refreshable"&&V.credentialMode==="refreshable",Ee=`${V.email||""} ${V.name||""} ${V.accountId||""} ${V.userId||""} ${V.lastError||""}`.toLowerCase();return _&&(!bt||Ee.includes(bt))}),Ke=xe[O.id]||"pool",We=[...I].sort((V,_)=>{if(Ke==="pool")return 0;const Ee=Ke==="expiry"?V.expiresAt||"9999-12-31":V.lastUsedAt||"",et=Ke==="expiry"?_.expiresAt||"9999-12-31":_.lastUsedAt||"";return Ke==="recent"?et.localeCompare(Ee):Ee.localeCompare(et)}),Pe=Math.min(We.length,P[O.id]||ue),tl=We.slice(0,Pe),kt=Math.max(0,We.length-tl.length),cl=kt===0;return n.jsxs("div",{className:"channel-card",children:[n.jsxs("div",{className:"channel-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:O.name}),n.jsx("span",{children:O.baseUrl||Ei(O.provider)||Ti}),n.jsxs("small",{children:["账号 ",d.length," 个,可用 ",x,",无效 ",G,",未验证 ",se]}),n.jsxs("small",{children:["可续期 ",ve," · 网页会话 ",N," · 仅 Token ",Ne]}),n.jsxs("small",{children:["自动检测 ",O.lastCheckedAt?el(O.lastCheckedAt):"等待首次检测"]})]}),n.jsxs("div",{className:"channel-card-head-actions",children:[n.jsx(Dt,{tone:O.status,children:_t(O.status)}),n.jsx("button",{className:"primary-button compact-button",onClick:()=>Te(O.id),disabled:R!=="",children:"添加账号"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>J(O.id),disabled:R!==""||d.length===0,children:R===`check:${O.id}`?"检测中":"批量检测"}),G>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>J(O.id,!0),disabled:R!=="",children:R===`retry:${O.id}`?"复检中":`复检无效 ${G}`}),d.length>1&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>T(O.id),disabled:R!=="",children:R===`dedupe:${O.id}`?"去重中":"账号去重"}),d.length>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>k(O),disabled:R!=="",children:"导出报告"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>B(O),disabled:R!=="",children:O.status==="disabled"?"启用渠道":"停用渠道"})]})]}),n.jsxs("div",{className:"account-filter-bar",role:"group","aria-label":"账号筛选",children:[n.jsx("input",{value:le[O.id]||"",onChange:V=>ie(_=>({..._,[O.id]:V.target.value})),placeholder:"搜索账号或错误","aria-label":"搜索账号"}),n.jsxs("select",{value:Ke,onChange:V=>Y(_=>({..._,[O.id]:V.target.value})),"aria-label":"账号排序",children:[n.jsx("option",{value:"pool",children:"账号池顺序"}),n.jsx("option",{value:"oldest",children:"最久未用优先"}),n.jsx("option",{value:"recent",children:"最近使用优先"}),n.jsx("option",{value:"expiry",children:"最早到期优先"})]}),[["all",`全部 ${d.length}`],["attention","需关注"],["invalid",`无效 ${G}`],["error",`有错误 ${X}`],["refreshable",`可续期 ${ve}`]].map(([V,_])=>n.jsx("button",{type:"button",className:Se===V?"selected":"",onClick:()=>ne(Ee=>({...Ee,[O.id]:V})),children:_},V))]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(ul,{label:"账号总数",value:d.length}),n.jsx(ul,{label:"可用账号",value:x}),n.jsx(ul,{label:"无效账号",value:G}),n.jsx(ul,{label:"未验证账号",value:se})]}),n.jsx("div",{className:"drawing-channel-models",children:be(O.models).length?be(O.models).map(V=>n.jsx("span",{children:V},V)):n.jsx("span",{children:"未绑定绘图模型"})}),d.length>0&&n.jsxs("div",{className:"account-pool-list",children:[tl.map(V=>n.jsxs("div",{className:"account-pool-row",children:[n.jsxs("div",{className:"account-pool-main",children:[n.jsxs("div",{children:[n.jsxs("div",{className:"account-pool-title",children:[n.jsx("strong",{title:V.email||V.name||V.accountId||V.id,children:V.email||V.name||V.accountId||V.id}),n.jsx("span",{className:`source-tag source-tag-${V.source==="web-login"?"web":"manual"}`,children:V.source==="web-login"?"网页登录":V.source==="web-oauth"?"网页 OAuth":V.source==="oauth"?"Codex OAuth":V.source==="antigravity"||V.source==="agy"||V.source==="google-antigravity"?"Antigravity":"导入"})]}),n.jsx("span",{children:V.lastError?`${fm(V.lastErrorCode)}${fm(V.lastErrorCode)?" · ":""}${V.lastError}`:V.lastCheckedAt?`上次检测 ${el(V.lastCheckedAt)}`:"未检测"}),n.jsxs("span",{children:[V.credentialMode==="refreshable"?"可自动续期":V.credentialMode==="browser-session"?"依赖网页会话":"仅 access token",V.expiresAt?` · 到期 ${el(V.expiresAt)}`:""]}),n.jsxs("span",{children:["套餐 ",lp(V.planType)]}),V.lastUsedAt&&n.jsxs("span",{children:["最近调用 ",el(V.lastUsedAt)," · ",V.requestCount||0," 次"]})]}),n.jsx(wp,{limits:V.quotaLimits})]}),n.jsxs("div",{className:"account-pool-meta",children:[n.jsx(Dt,{tone:V.status==="healthy"?"healthy":V.status==="invalid"?"disabled":"standby",children:V.status==="healthy"?"可用":V.status==="invalid"?"无效":"未验证"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",disabled:R!=="",onClick:()=>J(O.id,!1,V.id),children:R===`check-account:${V.id}`?"检测中":"检测"}),n.jsx("button",{type:"button",className:"danger-button compact-button",disabled:R!=="",onClick:()=>Q(O,V),children:R===`delete-account:${V.id}`?"删除中":"删除"})]})]},V.id)),I.length===0&&n.jsx(Lt,{text:"没有匹配的账号"}),We.length>ue&&n.jsxs("div",{className:"account-pool-more",children:[n.jsx("span",{className:"muted-inline",children:cl?`已显示全部 ${We.length} 个账号`:`已显示 ${tl.length} 个,还有 ${kt} 个`}),n.jsxs("div",{className:"account-pool-more-actions",children:[!cl&&n.jsxs("button",{type:"button",className:"secondary-button compact-button",onClick:()=>ee(V=>({...V,[O.id]:Math.min(We.length,Pe+Z)})),children:["再显示 ",Math.min(Z,kt)," 个"]}),!cl&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>ee(V=>({...V,[O.id]:We.length})),children:"全部显示"}),Pe>ue&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>ee(V=>({...V,[O.id]:ue})),children:"收起"})]})]})]})]},O.id)}),y.length===0&&n.jsx(Lt,{text:"暂无绘图渠道,先新增一个 OpenAI 账号池渠道"})]}),ge&&n.jsx(Rp,{channelId:ge,onStart:$,onComplete:C,onClose:()=>F("")}),Ae&&n.jsx(zp,{busy:R!=="",onAuthSession:()=>{D(Ae),Te("")},onAntigravity:()=>{fe(Ae),Te("")},onImport:async O=>{await re(Ae,O),Te("")},onClose:()=>Te("")}),me&&n.jsx(_p,{onImport:async O=>{await re(me,new File([JSON.stringify(Op(O))],"authsession.json",{type:"application/json"}))},onClose:()=>D("")}),ae&&n.jsx(Up,{onImport:async O=>{await re(ae,new File([JSON.stringify(Dp(O))],"antigravity.json",{type:"application/json"}))},onClose:()=>fe("")})]})}function zp({busy:u,onAuthSession:m,onAntigravity:h,onImport:r,onClose:A}){return n.jsx("div",{className:"modal-backdrop",onClick:A,children:n.jsxs("div",{className:"modal-card account-add-modal",onClick:E=>E.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"添加账号"}),n.jsx("span",{children:"选择一种账号接入方式"})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:A,children:"×"})]}),n.jsxs("div",{className:"account-add-options",children:[n.jsxs("button",{type:"button",className:"account-add-option recommended",onClick:m,disabled:u,children:[n.jsx("span",{className:"account-add-icon",children:"A"}),n.jsx("strong",{children:"导入网页会话"}),n.jsx("small",{children:"粘贴完整 authsession JSON,保留 sessionToken"})]}),n.jsxs("button",{type:"button",className:"account-add-option",onClick:h,disabled:u,children:[n.jsx("span",{className:"account-add-icon",children:"G"}),n.jsx("strong",{children:"导入 Antigravity"}),n.jsx("small",{children:"粘贴 Google OAuth JSON 或 refresh token"})]}),n.jsxs("label",{className:`account-add-option${u?" disabled":""}`,children:[n.jsx("span",{className:"account-add-icon",children:"J"}),n.jsx("strong",{children:u?"导入中":"导入 JSON / ZIP / TXT"}),n.jsx("small",{children:"批量导入已有账号文件"}),n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:u,onChange:E=>{const L=E.target.files?.[0];L&&r(L),E.target.value=""}})]})]}),n.jsx("div",{className:"modal-actions",children:n.jsx("button",{type:"button",className:"secondary-button",onClick:A,children:"取消"})})]})})}function Op(u){const m=u.trim(),h=m.match(/(?:^|[;\s])(__Secure-(?:next-auth|authjs)\.session-token)=([^;\s]+)/);if(h)return{sessionToken:h[2],source:"web-login"};try{const r=JSON.parse(m),A=r.tokens&&typeof r.tokens=="object"?r.tokens:{},E=R=>typeof r[R]=="string"?r[R]:typeof A[R]=="string"?A[R]:"",L=E("accessToken")||E("access_token"),$=E("refreshToken")||E("refresh_token"),C=E("sessionToken")||E("session_token"),y=r.user&&typeof r.user=="object"?r.user:{};if(L||$||C)return{accessToken:L||void 0,refreshToken:$||void 0,sessionToken:C||void 0,email:typeof y.email=="string"?y.email:void 0,name:typeof y.name=="string"?y.name:void 0,source:"web-login"}}catch{}return{sessionToken:m,source:"web-login"}}function _p({onImport:u,onClose:m}){const[h,r]=g.useState(""),[A,E]=g.useState(!1),[L,$]=g.useState(""),[C,y]=g.useState("");async function R(){if(!h.trim()){$("请粘贴 authsession");return}E(!0),$(""),y("");try{await u(h.trim()),r(""),y("已导入,继续粘贴下一条即可")}catch(z){$(z instanceof Error?z.message:"导入失败")}finally{E(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:m,children:n.jsxs("div",{className:"modal-card",onClick:z=>z.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"添加网页会话"}),n.jsx("button",{type:"button",className:"icon-button",onClick:m,children:"×"})]}),n.jsxs("p",{className:"muted-inline",children:["可直接粘贴 chatgpt.com/api/auth/session 的完整 JSON;也支持浏览器 ",n.jsx("code",{children:"__Secure-next-auth.session-token"})," 的值或完整 Cookie 字符串。"]}),n.jsxs("label",{className:"authsession-field",children:[n.jsx("span",{children:"authsession"}),n.jsx("textarea",{autoFocus:!0,value:h,onChange:z=>r(z.target.value),placeholder:"eyJhbGci..."})]}),L&&n.jsx("div",{className:"form-error",children:L}),C&&n.jsx("div",{className:"form-success",children:C}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:m,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:A,onClick:R,children:A?"导入中":"导入账号"})]})]})})}function Dp(u){const m=u.trim();try{const h=JSON.parse(m),r=h.tokens&&typeof h.tokens=="object"?h.tokens:{},A=(...y)=>{for(const R of y){if(typeof h[R]=="string"&&h[R])return h[R];if(typeof r[R]=="string"&&r[R])return r[R]}return""},E=A("access_token","accessToken"),L=A("refresh_token","refreshToken"),$=A("email"),C=A("expired","expires_at","expiresAt","expiry");if(E||L)return{accessToken:E||void 0,refreshToken:L||void 0,email:$||void 0,expired:C||void 0,source:"antigravity"}}catch{}return{refreshToken:m,source:"antigravity"}}function Up({onImport:u,onClose:m}){const[h,r]=g.useState(""),[A,E]=g.useState(!1),[L,$]=g.useState(""),[C,y]=g.useState("");async function R(){if(!h.trim()){$("请粘贴 Antigravity OAuth JSON 或 refresh token");return}E(!0),$(""),y("");try{await u(h.trim()),r(""),y("已导入,继续粘贴下一条即可")}catch(z){$(z instanceof Error?z.message:"导入失败")}finally{E(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:m,children:n.jsxs("div",{className:"modal-card",onClick:z=>z.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"导入 Antigravity 账号"}),n.jsx("button",{type:"button",className:"icon-button",onClick:m,children:"×"})]}),n.jsxs("p",{className:"muted-inline",children:["粘贴 Antigravity 的 Google OAuth 凭证 JSON(含 ",n.jsx("code",{children:"access_token"})," / ",n.jsx("code",{children:"refresh_token"}),"),或直接粘贴 refresh token。导入后会自动刷新并加入账号池。"]}),n.jsxs("label",{className:"authsession-field",children:[n.jsx("span",{children:"OAuth JSON / refresh token"}),n.jsx("textarea",{autoFocus:!0,value:h,onChange:z=>r(z.target.value),placeholder:'{"access_token":"ya29...","refresh_token":"1//..."}'})]}),L&&n.jsx("div",{className:"form-error",children:L}),C&&n.jsx("div",{className:"form-success",children:C}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:m,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:A,onClick:R,children:A?"导入中":"导入账号"})]})]})})}function Rp({channelId:u,onStart:m,onComplete:h,onClose:r}){const[A,E]=g.useState(""),[L,$]=g.useState(""),[C,y]=g.useState(""),[R,z]=g.useState(!1),[P,ee]=g.useState("");async function de(){z(!0),ee("");try{const le=await m(u);E(le.authorizeUrl),$(le.state),window.open(le.authorizeUrl,"_blank","noopener")}catch(le){ee(le instanceof Error?le.message:"发起授权失败")}finally{z(!1)}}async function ne(){if(!C.trim()){ee("请粘贴授权完成后浏览器跳转的回调地址");return}z(!0),ee("");try{await h(u,{callbackUrl:C.trim(),state:L}),r()}catch(le){ee(le instanceof Error?le.message:"完成授权失败")}finally{z(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:r,children:n.jsxs("div",{className:"modal-card",onClick:le=>le.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"OAuth 授权添加网页账号"}),n.jsx("button",{type:"button",className:"icon-button",onClick:r,children:"×"})]}),n.jsx("p",{className:"muted-inline",children:"使用 ChatGPT 网页兼容的 OAuth 客户端获取 refresh_token,只调用网页 backend-api,不会走 Codex 接口。"}),n.jsxs("ol",{className:"oauth-steps",children:[n.jsxs("li",{children:[n.jsx("button",{type:"button",className:"primary-button",onClick:de,disabled:R,children:A?"重新生成授权链接":"① 生成授权链接并打开"}),A&&n.jsxs("div",{className:"oauth-link",children:[n.jsx("input",{readOnly:!0,value:A,onFocus:le=>le.target.select()}),n.jsx("span",{className:"muted-inline",children:"若未自动打开,复制到浏览器手动访问,用要添加的 ChatGPT 账号登录授权。"})]})]}),n.jsxs("li",{children:[n.jsx("label",{children:"② 粘贴授权后浏览器跳转的完整回调地址"}),n.jsx("input",{value:C,placeholder:"https://platform.openai.com/auth/callback?code=...&state=...",onChange:le=>y(le.target.value),disabled:!A||R})]})]}),P&&n.jsx("p",{className:"form-error",children:P}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:r,disabled:R,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",onClick:ne,disabled:!A||R,children:R?"处理中":"完成授权"})]})]})})}function wp({limits:u}){const m=be(u).filter(h=>h.label||h.name).slice(0,3);return m.length?n.jsx("div",{className:"quota-bars",children:m.map(h=>{const r=Hp(h);return n.jsxs("div",{className:"quota-bar",children:[n.jsxs("div",{className:"quota-bar-label",children:[n.jsx("strong",{children:h.label||h.name}),n.jsx("span",{children:Bp(h,r)})]}),n.jsx("div",{className:"quota-bar-track",children:n.jsx("span",{style:{width:`${r}%`}})})]},`${h.label||h.name}-${h.resetAt||""}`)})}):null}function Hp(u){return typeof u.percentRemaining=="number"&&Number.isFinite(u.percentRemaining)?Math.max(0,Math.min(100,u.percentRemaining)):typeof u.remaining=="number"&&typeof u.limit=="number"&&u.limit>0?Math.max(0,Math.min(100,u.remaining/u.limit*100)):typeof u.used=="number"&&typeof u.limit=="number"&&u.limit>0?Math.max(0,Math.min(100,(u.limit-u.used)/u.limit*100)):0}function Bp(u,m){const h=u.resetAt?` · ${el(u.resetAt)}`:"";return typeof u.remaining=="number"?`${Math.round(m)}% 剩余${h}`:`${Math.round(m)}%${h}`}function qp(u){const m=be(u.models).join(" ").toLowerCase(),h=["对话"];u.streamMode!=="disabled"&&h.push("流式"),/(image|dall-e|gpt-image)/.test(m)&&h.push("图片"),(u.openaiAccountCount??u.openaiAccounts?.length??0)>0&&h.push("账号池");const r=u.upstreamKeyCount??0;return r>1&&h.push(`${r} Key 轮询`),h}function Gp(u){if(u.status==="invalid"||u.credentialMode==="browser-session")return!0;if(!u.expiresAt)return!1;const m=new Date(u.expiresAt).getTime();return Number.isFinite(m)&&m-Date.now()<=1440*60*1e3}function Yp({channels:u,groups:m,onUpdate:h,onCreate:r,onImport:A,onDelete:E,onSyncModels:L,onCheck:$}){const C=Ta("openai"),[y,R]=g.useState(!1),[z,P]=g.useState(C.provider),[ee,de]=g.useState(C.name),[ne,le]=g.useState(C.baseUrl),[ie,xe]=g.useState(C.models.join(", ")),[Y,ge]=g.useState(""),[F,me]=g.useState(""),[D,ae]=g.useState(!1),[fe,Ae]=g.useState(!1);function Te(Z){const re=Ta(Z);P(re.provider),de(re.name),le(re.baseUrl),xe(re.models.join(", ")),me("")}async function ue(Z){Z.preventDefault(),ae(!0),me("");try{await r({name:ee.trim()||Ta(z).name,provider:z,baseUrl:ne.trim(),...Sm(Y),models:Pc(ie),streamMode:"auto"}),R(!1),ge(""),Te(z)}catch(re){me(re instanceof Error?re.message:"渠道创建失败")}finally{ae(!1)}}return n.jsxs(nt,{title:"渠道",children:[n.jsxs("div",{className:"channel-page-intro",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"管理上游服务"}),n.jsx("span",{children:"每个渠道对应一个 API 上游。先添加渠道,再检测连通性并同步可用模型。"})]}),n.jsxs("div",{className:"channel-page-summary",children:[n.jsxs("span",{children:[n.jsx("b",{children:u.length})," 个渠道"]}),n.jsxs("span",{children:[n.jsx("b",{children:u.filter(Z=>Z.status!=="disabled").length})," 个已启用"]})]})]}),n.jsxs("div",{className:"panel-toolbar channel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"列表显示当前状态;点击任一渠道可修改连接、模型和计费设置。"}),n.jsx("button",{className:"primary-button",onClick:()=>R(Z=>!Z),children:y?"取消新增":"+ 新增渠道"})]}),y&&n.jsxs("form",{className:"channel-card channel-create-form",onSubmit:ue,children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"选择渠道类型"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:Ta(z).label}),n.jsx("small",{children:"选择后自动填入建议配置"})]}),n.jsx("div",{role:"listbox","aria-label":"选择渠道类型",children:Fc.map(Z=>n.jsxs("button",{type:"button",className:z===Z.provider?"selected":"",onClick:re=>{Te(Z.provider),re.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:Z.label}),n.jsx("span",{children:"使用推荐的名称和地址"})]},Z.provider))})]})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:ee,onChange:Z=>de(Z.target.value),placeholder:"例如 OpenAI 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:il(z),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:ne,onChange:Z=>le(Z.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"上游 Key"}),n.jsx("textarea",{className:"channel-key-input",value:Y,onChange:Z=>ge(Z.target.value),placeholder:z==="codex"?"账号池导入后使用":z==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发",autoComplete:"off",rows:3})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsx("button",{type:"button",className:"model-pull-button",onClick:()=>{if(z!=="codex"&&!ne.trim()){me("请先填写 Base URL 再获取模型");return}me(""),Ae(!0)},children:"从上游获取模型"})]}),n.jsx("textarea",{value:ie,onChange:Z=>xe(Z.target.value),placeholder:"多个模型用逗号分隔,或点上方『从上游获取模型』拉取后多选"})]})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("span",{className:"model-create-message",role:"status",children:F}),n.jsx("button",{className:"secondary-button",type:"button",onClick:()=>Te(z),disabled:D,children:"填入模板"}),n.jsx("button",{className:"primary-button",type:"submit",disabled:D,children:D?"创建中":"创建渠道"})]})]}),y&&fe&&n.jsx(Nm,{subtitle:`${ee.trim()||Ta(z).name} · 勾选需要接入的模型`,current:Pc(ie),loadModels:async()=>{const Z=await pe("/api/channel-model-preview",{method:"POST",body:JSON.stringify({provider:z,baseUrl:ne.trim(),upstreamApiKey:Y})});return be(Z.models)},onConfirm:async Z=>{xe(Z.join(", "))},onClose:()=>Ae(!1)}),n.jsxs("div",{className:"channels-stack",children:[u.map(Z=>n.jsx(Lp,{channel:Z,groups:m,onUpdate:h,onImport:A,onDelete:E,onSyncModels:L,onCheck:$},Z.id)),u.length===0&&n.jsx(Lt,{text:"暂无渠道,先在后端添加渠道接口或导入配置"})]})]})}function Lp({channel:u,groups:m,onUpdate:h,onImport:r,onDelete:A,onSyncModels:E,onCheck:L}){const[$,C]=g.useState(u.name),[y,R]=g.useState(u.provider),[z,P]=g.useState(u.streamMode||"auto"),[ee,de]=g.useState(u.baseUrl),[ne,le]=g.useState(be(u.allowedGroupIds)),[ie,xe]=g.useState(be(u.models).join(", ")),[Y,ge]=g.useState("saved"),[F,me]=g.useState(String(u.inputPricePer1K||0)),[D,ae]=g.useState(String(u.outputPricePer1K||0)),[fe,Ae]=g.useState(!!u.webEndpoint),[Te,ue]=g.useState(""),[Z,re]=g.useState(""),[J,T]=g.useState(!1),k=u.openaiAccountCount??u.openaiAccounts?.length??0,B=be(u.models).length,Q=qp(u),O=u.status==="disabled",d={saved:"已保存",template:"模板",manual:"手动",synced:"上游同步"}[Y],x=Ni.find(I=>I.value===z)||Ni[0],G={auto:"自动处理(推荐)",real:"强制流式",fake:"兼容流式",disabled:"关闭流式"};g.useEffect(()=>{C(u.name),R(u.provider),P(u.streamMode||"auto"),de(u.baseUrl),le(be(u.allowedGroupIds)),xe(be(u.models).join(", ")),ge("saved"),me(String(u.inputPricePer1K||0)),ae(String(u.outputPricePer1K||0)),Ae(!!u.webEndpoint),ue("")},[u.id,u.name,u.provider,u.streamMode,u.baseUrl,u.models,u.inputPricePer1K,u.outputPricePer1K,u.webEndpoint]);async function X(){const I=se();re("save");try{await h(u.id,I),ue("")}finally{re("")}}function se(){const I=Ei(y),Ke=!/^https?:\/\//i.test(ee.trim())&&I?I:ee,We={name:$.trim()||u.name,provider:y,streamMode:z,baseUrl:Ke,inputPricePer1K:Number(F)||0,outputPricePer1K:Number(D)||0,webEndpoint:fe,models:ie.split(",").map(Pe=>Pe.trim()).filter(Boolean),allowedGroupIds:ne};return Object.assign(We,Sm(Te)),We}async function ve(){const I=u.status==="disabled"?"healthy":"disabled";re("status");try{await h(u.id,{...se(),status:I}),ue("")}finally{re("")}}async function N(){re("sync");try{await h(u.id,se()),ue(""),T(!0)}finally{re("")}}function Ne(){const I=Ta(y);xe(I.models.join(", ")),ge("template"),I.baseUrl&&!/^https?:\/\//i.test(ee.trim())&&de(I.baseUrl)}async function Se(){re("check");try{await X(),await L(u.id)}finally{re("")}}async function bt(I){re("import");try{await r(u.id,I)}finally{re("")}}return n.jsxs(n.Fragment,{children:[n.jsxs("details",{className:"channel-card channel-card-collapsible",children:[n.jsxs("summary",{className:"channel-card-head channel-list-row",children:[n.jsxs("div",{className:"channel-identity",children:[n.jsx("strong",{children:u.name}),n.jsx("span",{children:il(y)}),n.jsx("small",{children:u.baseUrl||"尚未配置上游地址"}),n.jsx("div",{className:"channel-capability-tags",children:Q.map(I=>n.jsx("span",{children:I},I))})]}),n.jsxs("div",{className:"channel-list-meta",children:[n.jsxs("span",{children:[n.jsx("b",{children:B})," 个模型"]}),k>0&&n.jsxs("span",{children:[n.jsx("b",{children:k})," 个账号"]})]}),n.jsxs("div",{className:"channel-check-result",children:[n.jsx("span",{children:"连通性"}),n.jsx("b",{className:u.lastError?"is-error":u.lastCheckedAt?"is-ok":"",children:u.lastError?"检测失败":u.lastCheckedAt?`已检测 ${el(u.lastCheckedAt)}`:"尚未检测"})]}),n.jsxs("div",{className:"channel-list-status",children:[n.jsx(Dt,{tone:u.status,children:O?"已停用":_t(u.status)}),n.jsx("span",{className:"channel-expand-hint",children:"配置"})]})]}),n.jsxs("div",{className:"channel-editor-controls",children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"供应商"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:il(y)}),n.jsx("small",{children:"修改上游协议类型"})]}),n.jsx("div",{role:"listbox","aria-label":"供应商",children:to.map(I=>n.jsxs("button",{type:"button",className:y===I.value?"selected":"",onClick:Ke=>{R(I.value);const We=Ei(I.value);We&&!/^https?:\/\//i.test(ee.trim())&&de(We),Ke.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:I.label}),n.jsx("span",{children:I.value==="compatible"?"适用于兼容 OpenAI 格式的服务":"选择对应的上游协议"})]},I.value))})]})]}),n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"响应方式"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:G[x.value]}),n.jsx("small",{children:x.description})]}),n.jsx("div",{role:"listbox","aria-label":"响应方式",children:Ni.map(I=>n.jsxs("button",{type:"button",className:z===I.value?"selected":"",onClick:Ke=>{P(I.value),Ke.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:G[I.value]}),n.jsx("span",{children:I.description})]},I.value))})]})]})]}),(y==="codex"||k>0)&&n.jsxs("div",{className:"setting",children:[n.jsxs("div",{children:[n.jsx("span",{children:"网页对话接口"}),n.jsx("small",{children:"开启后走 ChatGPT 网页对话接口,把 Plus 订阅账号包装成 API"})]}),n.jsx("div",{className:"setting-value",children:n.jsx("button",{type:"button",className:fe?"ios-switch is-on":"ios-switch","aria-label":fe?"关闭网页对话接口":"开启网页对话接口","aria-pressed":fe,onClick:()=>Ae(I=>!I),children:n.jsx("span",{})})})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:$,onChange:I=>C(I.target.value),placeholder:"例如 Gemini 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:il(y),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:ee,onChange:I=>de(I.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"优先级"}),n.jsx("input",{value:u.priority,readOnly:!0})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsxs("small",{children:["来源:",d]})]}),n.jsx("textarea",{value:ie,onChange:I=>{xe(I.target.value),ge("manual")},placeholder:"优先拉取上游模型,也可以手动补充,多个用逗号分隔"}),n.jsxs("div",{className:"channel-model-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:Ne,disabled:Z!=="",children:"填入模板"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:N,disabled:Z!=="",children:Z==="sync"?"拉取中":"获取上游模型"})]})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsxs("span",{children:["上游 Key",(u.upstreamKeyCount??0)>0?` (已配置 ${u.upstreamKeyCount} 个)`:u.upstreamKeySet?" (已配置)":""]}),n.jsx("textarea",{className:"channel-key-input",value:Te,onChange:I=>ue(I.target.value),placeholder:y==="codex"?"Codex 账号池不需要上游 Key":y==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发;留空不修改",autoComplete:"off",rows:3})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输入单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:F,onChange:I=>me(I.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输出单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:D,onChange:I=>ae(I.target.value)})]}),n.jsx("span",{className:"channel-billing-note",children:"定价可先留空;接入是否可用优先看渠道检测和模型同步结果。"})]}),n.jsxs("div",{className:"channel-group-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"可见分组"}),n.jsx("small",{children:ne.length?`已选择 ${ne.length} 个分组`:"全部用户可用"})]}),m.length===0?n.jsx("p",{className:"channel-group-empty",children:"还没有用户分组。去「分组」页创建后,可在这里把渠道限制为只对特定分组开放。"}):n.jsx("div",{className:"channel-group-options",children:m.map(I=>{const Ke=ne.includes(I.id);return n.jsxs("button",{type:"button",className:Ke?"selected":"","aria-pressed":Ke,onClick:()=>le(We=>Ke?We.filter(Pe=>Pe!==I.id):[...We,I.id]),children:[n.jsx("span",{children:I.name}),I.description&&n.jsx("small",{children:I.description})]},I.id)})})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("button",{className:"secondary-button",onClick:Se,disabled:Z!=="",children:Z==="check"?"检测中":"检测渠道"}),n.jsx("button",{className:"primary-button",onClick:X,disabled:Z!=="",children:Z==="save"?"保存中":"保存"}),n.jsxs("details",{className:"channel-more-actions",children:[n.jsx("summary",{children:"更多操作"}),n.jsxs("div",{children:[n.jsxs("label",{className:"secondary-button",children:[Z==="import"?"导入中":"导入账号 JSON",n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:Z!=="",onChange:I=>{const Ke=I.target.files?.[0];Ke&&bt(Ke),I.target.value=""}})]}),n.jsx("button",{className:"secondary-button",onClick:ve,disabled:Z!=="",children:u.status==="disabled"?"启用渠道":"停用渠道"}),n.jsx("button",{className:"danger-button",onClick:()=>A(u.id),disabled:Z!=="",children:"删除渠道"})]})]})]})]}),J&&n.jsx(Nm,{subtitle:`${u.name} · 勾选需要接入的模型`,current:ie.split(",").map(I=>I.trim()).filter(Boolean),loadModels:async()=>{const I=await pe(`/api/channels/${u.id}/upstream-models`,{method:"POST",body:JSON.stringify({})});return be(I.models)},onConfirm:async I=>{await E(u.id,I)},onClose:()=>T(!1)})]})}function Nm({subtitle:u,current:m,loadModels:h,onConfirm:r,onClose:A}){const[E,L]=g.useState(!0),[$,C]=g.useState(""),[y,R]=g.useState([]),[z,P]=g.useState(new Set),[ee,de]=g.useState(""),[ne,le]=g.useState(!1);g.useEffect(()=>{let D=!1;return(async()=>{L(!0),C("");try{const ae=await h();if(D)return;const fe=new Set,Ae=be(ae).map(ue=>ue.trim()).filter(ue=>{if(!ue)return!1;const Z=ue.toLowerCase();return fe.has(Z)?!1:(fe.add(Z),!0)}),Te=new Set(m.map(ue=>ue.toLowerCase()));R(Ae),P(new Set(Ae.filter(ue=>Te.has(ue.toLowerCase()))))}catch(ae){D||C(ae instanceof Error?ae.message:"获取上游模型失败")}finally{D||L(!1)}})(),()=>{D=!0}},[]);const ie=ee.trim().toLowerCase(),xe=ie?y.filter(D=>D.toLowerCase().includes(ie)):y,Y=xe.length>0&&xe.every(D=>z.has(D));function ge(D){P(ae=>{const fe=new Set(ae);return fe.has(D)?fe.delete(D):fe.add(D),fe})}function F(){P(D=>{const ae=new Set(D);return Y?xe.forEach(fe=>ae.delete(fe)):xe.forEach(fe=>ae.add(fe)),ae})}async function me(){const D=new Set(y.map(ue=>ue.toLowerCase())),ae=m.filter(ue=>!D.has(ue.toLowerCase())),fe=y.filter(ue=>z.has(ue)),Ae=new Set,Te=[...ae,...fe].filter(ue=>{const Z=ue.toLowerCase();return Ae.has(Z)?!1:(Ae.add(Z),!0)});le(!0);try{await r(Te),A()}catch{le(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:A,children:n.jsxs("div",{className:"modal-card model-picker-modal",onClick:D=>D.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"选择上游模型"}),n.jsx("span",{children:u})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:A,children:"×"})]}),E?n.jsx("div",{className:"model-picker-status",children:"正在获取上游模型…"}):$?n.jsx("div",{className:"model-picker-status model-picker-error",children:$}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"model-picker-toolbar",children:[n.jsx("input",{className:"model-picker-search",value:ee,onChange:D=>de(D.target.value),placeholder:"搜索模型名称",autoFocus:!0}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:F,disabled:xe.length===0,children:Y?"取消全选":"全选"})]}),n.jsxs("div",{className:"model-picker-count",children:["共 ",y.length," 个 · 已选 ",z.size," 个",ie?` · 匹配 ${xe.length} 个`:""]}),n.jsxs("div",{className:"model-picker-list",children:[xe.map(D=>{const ae=z.has(D),fe=m.some(Ae=>Ae.toLowerCase()===D.toLowerCase());return n.jsxs("label",{className:`model-picker-row${ae?" checked":""}`,children:[n.jsx("input",{type:"checkbox",checked:ae,onChange:()=>ge(D)}),n.jsx("span",{className:"model-picker-name",children:D}),fe&&n.jsx("span",{className:"model-picker-tag",children:"已接入"})]},D)}),xe.length===0&&n.jsx("div",{className:"model-picker-status",children:"没有匹配的模型"})]})]}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:A,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:E||!!$||ne,onClick:me,children:ne?"保存中":`导入所选 (${z.size})`})]})]})})}function kp({logs:u,onCopy:m}){const[h,r]=g.useState(u),[A,E]=g.useState(u.length),[L,$]=g.useState(1),[C,y]=g.useState(""),[R,z]=g.useState("all"),[P,ee]=g.useState(null),[de,ne]=g.useState(!1),[le,ie]=g.useState(!1),xe=25,Y=Math.max(1,Math.ceil(A/xe));g.useEffect(()=>{$(1)},[C,R]),g.useEffect(()=>{L>Y&&$(Y)},[L,Y]),g.useEffect(()=>{const F=new AbortController,me=window.setTimeout(async()=>{ne(!0);try{const D=new URLSearchParams({page:String(L),pageSize:String(xe),status:R,q:C.trim()}),ae=await pe(`/api/logs?${D}`,{signal:F.signal}),fe=be(ae.logs);r(fe),E(ae.total||0),ee(Ae=>Ae&&fe.some(Te=>Te.id===Ae.id)?Ae:null)}catch(D){D instanceof DOMException&&D.name==="AbortError"||(r([]),E(0))}finally{F.signal.aborted||ne(!1)}},C?250:0);return()=>{window.clearTimeout(me),F.abort()}},[L,C,R]);async function ge(F){if(P?.id===F.id){ee(null);return}ee(F),ie(!0);try{const me=await pe(`/api/logs/${encodeURIComponent(F.id)}`);ee(me.log)}catch{ee(F)}finally{ie(!1)}}return n.jsxs(nt,{title:"调用日志",children:[n.jsxs("div",{className:"logs-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Ot,{name:"search"}),n.jsx("input",{value:C,onChange:F=>y(F.target.value),placeholder:"搜索请求 ID、用户、Key、模型、渠道或错误码"})]}),n.jsx("div",{className:"log-status-filter",role:"group","aria-label":"日志状态筛选",children:[{value:"all",label:"全部"},{value:"success",label:"成功"},{value:"failed",label:"失败"}].map(F=>n.jsx("button",{type:"button",className:R===F.value?"selected":"",onClick:()=>z(F.value),children:F.label},F.value))}),n.jsx("span",{className:"muted-inline",children:de?"加载中":`共 ${A} 条`})]}),n.jsxs("div",{className:P?"logs-layout has-detail":"logs-layout",children:[n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head logs-table",children:[n.jsx("span",{children:"请求"}),n.jsx("span",{children:"模型"}),n.jsx("span",{children:"渠道"}),n.jsx("span",{children:"状态"})]}),h.map(F=>n.jsx("div",{className:"log-entry",children:n.jsxs("div",{className:P?.id===F.id?"table-row logs-table selected":"table-row logs-table",role:"button",tabIndex:0,onClick:()=>ge(F),onKeyDown:me=>{(me.key==="Enter"||me.key===" ")&&ge(F)},children:[n.jsxs("span",{children:[n.jsx("strong",{children:lo(F)}),n.jsxs("small",{children:[F.id," · ",el(F.createdAt)," · ",F.latencyMs,"ms"]})]}),n.jsx("span",{children:ip(F)}),n.jsx("span",{children:up(F)}),n.jsx(Dt,{tone:F.status,children:_t(F.status)})]})},F.id)),!de&&h.length===0&&n.jsx(Lt,{text:C||R!=="all"?"没有匹配的日志":"暂无调用日志"})]}),P&&n.jsx(Qp,{log:P,loading:le,onCopy:m})]}),Y>1&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:L<=1||de,onClick:()=>$(F=>Math.max(1,F-1)),children:"上一页"}),n.jsxs("span",{children:[L," / ",Y]}),n.jsx("button",{className:"secondary-button",disabled:L>=Y||de,onClick:()=>$(F=>Math.min(Y,F+1)),children:"下一页"})]})]})}function Qp({log:u,loading:m,onCopy:h}){if(!u)return n.jsx("aside",{className:"log-inspector empty-inspector",children:n.jsx("span",{children:"选择一条日志查看详情"})});const r=Number(u.inputTokens||0),A=Number(u.outputTokens||0),E=typeof u.attempts=="number"?Math.max(0,u.attempts):null,L=[["请求 ID",u.id],["状态",_t(u.status)],["时间",sp(u.createdAt)],["用户 ID",u.userId||"未识别"],["API Key",u.apiKeyPrefix?`${u.apiKeyPrefix}***`:"未识别"],["模型",u.model||"未提供"],["渠道",u.channel||"未选择"],["实际账号",u.account||"未记录"],["响应耗时",`${u.latencyMs} ms`],["尝试次数",E===null?"未记录":String(E)],["是否重试",E===null?"未记录":E>1?"是":"否"],["输入 Tokens",ml(r)],["输出 Tokens",ml(A)],["总 Tokens",ml(r+A)],["扣费",u.cost.toFixed(4)],["错误码",u.errorCode||"无"]];return n.jsxs("aside",{className:"log-inspector",children:[n.jsxs("header",{children:[n.jsxs("div",{children:[n.jsx("span",{children:m?"加载中":"日志详情"}),n.jsx("strong",{children:lo(u)})]}),n.jsx(Dt,{tone:u.status,children:_t(u.status)})]}),n.jsx("div",{className:"log-detail",children:L.map(([$,C])=>n.jsxs("div",{children:[n.jsx("span",{children:$}),n.jsx("strong",{title:C,children:C})]},$))}),n.jsxs("div",{className:"log-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>h(u.id,"请求 ID 已复制"),children:"复制请求 ID"}),u.errorCode&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>h(u.errorCode||"","错误码已复制"),children:"复制错误码"})]})]})}function Xp({models:u,channels:m,groups:h}){const[r,A]=g.useState(null),[E,L]=g.useState(null),[$,C]=g.useState("username"),[y,R]=g.useState("0"),[z,P]=g.useState(""),[ee,de]=g.useState({enabled:!0,minReward:.1,maxReward:1}),[ne,le]=g.useState({logRetentionDays:30,maxLogs:1e4,maxQuotaEntries:2e4}),[ie,xe]=g.useState(null),[Y,ge]=g.useState(null),[F,me]=g.useState(""),[D,ae]=g.useState(""),[fe,Ae]=g.useState(""),[Te,ue]=g.useState(""),[Z,re]=g.useState(""),[J,T]=g.useState(""),[k,B]=g.useState(""),[Q,O]=g.useState(""),[d,x]=g.useState(""),[G,X]=g.useState(!1),[se,ve]=g.useState("system"),N=u.find(_=>_.recommended&&_.status==="available")?.id||u.find(_=>_.status==="available")?.id||"未配置",Ne=m.filter(_=>_.status!=="disabled").length,Se=[{value:"system",label:"系统",description:"运行概况"},{value:"cli",label:"CLI 接入",description:"一键配置"},{value:"auth",label:"注册",description:"开放方式"},{value:"check-in",label:"签到",description:"奖励范围"},{value:"admin",label:"管理员",description:"账号绑定"},{value:"discord",label:"Discord",description:"登录限制"},{value:"maintenance",label:"维护",description:"日志保留"},{value:"backup",label:"备份",description:"导出恢复"}],bt=Se.find(_=>_.value===se)||Se[0];g.useEffect(()=>{Promise.all([pe("/api/settings/discord"),pe("/api/settings/auth"),pe("/api/settings/check-in"),pe("/api/account/me"),pe("/api/settings/maintenance"),pe("/api/health")]).then(([_,Ee,et,xt,ft,tt])=>{A(Wc(_.discord)),O(be(_.discord.blockedGuildIds).join(` -`)),L(Ee.auth.registrationEnabled),C(Mi(Ee.auth.registrationMode)),R(String(Ee.auth.defaultBalance||0)),P(Ee.auth.defaultGroupId||""),de(et.checkIn),ge(xt.account),me(xt.account?.username||""),ae(xt.user.name||""),Ae(xt.account?.email||""),ue(xt.account?.discordUserId||""),le(ft.maintenance),xe(tt)}).catch(()=>x("设置加载失败"))},[]);async function I(_=E,Ee=$,et=Number(y),xt=z){if(_!==null)try{const ft=await pe("/api/settings/auth",{method:"PATCH",body:JSON.stringify({registrationEnabled:_,registrationMode:Ee,defaultBalance:et,defaultGroupId:xt})});L(ft.auth.registrationEnabled),C(Mi(ft.auth.registrationMode)),R(String(ft.auth.defaultBalance||0)),P(ft.auth.defaultGroupId||""),x(ft.auth.registrationEnabled?"注册设置已保存":"已关闭用户注册")}catch(ft){x(ft instanceof Error?ft.message:"注册设置保存失败")}}async function Ke(){E!==null&&I(!E,$)}async function We(){X(!0),x("");try{const _=await pe("/api/settings/check-in",{method:"PATCH",body:JSON.stringify(ee)});de(_.checkIn),x(_.checkIn.enabled?"签到奖励设置已保存":"已关闭每日签到")}catch(_){x(_ instanceof Error?_.message:"签到设置保存失败")}finally{X(!1)}}async function Pe(){if(r){X(!0),x("");try{const _=Wc(r),Ee=Q.split(/[\s,]+/).map(xt=>xt.trim()).filter(Boolean),et=await pe("/api/settings/discord",{method:"PATCH",body:JSON.stringify({..._,blockedGuildIds:Ee,clientSecret:k})});A(Wc(et.discord)),O(be(et.discord.blockedGuildIds).join(` -`)),B(""),x("Discord 配置已保存")}catch(_){x(_ instanceof Error?_.message:"保存失败,请检查填写内容")}finally{X(!1)}}}async function tl(){try{const _=await pe("/api/account/profile",{method:"PATCH",body:JSON.stringify({username:F,displayName:D,email:fe,discordUserId:Te,currentPassword:Z,newPassword:J})});ge(_.account),me(_.account.username),Ae(_.account.email||""),ue(_.account.discordUserId||""),re(""),T(""),x("管理员账号已保存")}catch(_){x(_ instanceof Error?_.message:"账号设置保存失败")}}async function kt(){X(!0),x("");try{const _=await pe("/api/settings/maintenance",{method:"PATCH",body:JSON.stringify(ne)});le(_.maintenance),x("维护设置已保存,历史数据已按新规则清理")}catch(_){x(_ instanceof Error?_.message:"维护设置保存失败")}finally{X(!1)}}async function cl(){X(!0),x("");try{const _=await fetch("/api/backup",{credentials:"include"});if(!_.ok)throw new Error("备份导出失败");const Ee=await _.blob(),xt=(_.headers.get("Content-Disposition")||"").match(/filename="([^"]+)"/)?.[1]||"capi-backup.json",ft=URL.createObjectURL(Ee),tt=document.createElement("a");tt.href=ft,tt.download=xt,tt.click(),URL.revokeObjectURL(ft),x("备份已导出,请妥善保管")}catch(_){x(_ instanceof Error?_.message:"备份导出失败")}finally{X(!1)}}async function V(_){if(window.confirm("恢复会覆盖当前全部数据,并退出现有登录会话。确定继续?")){X(!0),x("");try{const Ee=await fetch("/api/restore",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:_}),et=await Ee.json().catch(()=>null);if(!Ee.ok)throw new Error(et?.error?.message||"备份恢复失败");x(`已恢复 ${et.users} 个用户、${et.channels} 条渠道和 ${et.models} 个模型,请重新登录`)}catch(Ee){x(Ee instanceof Error?Ee.message:"备份恢复失败")}finally{X(!1)}}}return n.jsxs("div",{className:"settings-layout",children:[n.jsx("div",{className:"settings-tabs",children:Se.map(_=>n.jsxs("button",{type:"button",className:se===_.value?"selected":"",onClick:()=>ve(_.value),children:[n.jsx("strong",{children:_.label}),n.jsx("small",{children:_.description})]},_.value))}),n.jsxs("div",{className:"settings-tab-note",children:[n.jsx("strong",{children:bt.label}),n.jsx("span",{children:bt.description})]}),se==="system"&&n.jsx(nt,{title:"系统设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsx(Pt,{label:"接口兼容",value:"OpenAI API"}),n.jsx(Pt,{label:"当前默认模型",value:N}),n.jsx(Pt,{label:"已配置渠道",value:`${m.length} 个,${Ne} 个启用`}),n.jsx(Pt,{label:"可选供应商",value:`${to.length} 种`}),n.jsx(Pt,{label:"运行版本",value:`${ie?.version||"未知"} · ${ie?.commit||"未知"}`}),n.jsx(Pt,{label:"构建时间",value:ie?.buildTime?el(ie.buildTime):"本地构建"}),n.jsx(Pt,{label:"账号自动检测",value:"每 15 分钟自动检测一次"})]})}),se==="cli"&&n.jsxs(nt,{title:"CLI 工具接入",children:[n.jsx("p",{className:"cli-intro",children:"CAPI 兼容 OpenAI 和 Anthropic 协议,常见 AI 命令行工具可直接接入。"}),n.jsxs("div",{className:"cli-credentials",children:[n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"Base URL"}),n.jsx("code",{children:Ul()}),n.jsx("button",{type:"button",className:"copy-button","aria-label":"复制",onClick:()=>{Ai(Ul()),x("已复制 Base URL")},children:n.jsx(Ot,{name:"copy"})})]}),n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"API Key"}),n.jsx("code",{children:"cat_你的_api_key"})]})]}),n.jsxs("div",{className:"cli-tools",children:[n.jsxs("details",{className:"cli-tool",open:!0,children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Claude Code"}),n.jsx("span",{children:"Anthropic Messages 协议"})]}),n.jsx("pre",{children:`export ANTHROPIC_BASE_URL="${Ul()}" -export ANTHROPIC_AUTH_TOKEN="cat_你的_api_key" -export ANTHROPIC_MODEL="${N}" -claude`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Codex CLI"}),n.jsx("span",{children:"OpenAI Chat 协议"})]}),n.jsxs("p",{children:["编辑 ",n.jsx("code",{children:"~/.codex/config.toml"}),":"]}),n.jsx("pre",{children:`model = "${N}" -model_provider = "capi" - -[model_providers.capi] -name = "CAPI" -base_url = "${Ul()}/v1" -env_key = "CAPI_KEY" -wire_api = "chat"`}),n.jsx("p",{children:"然后设置环境变量并运行:"}),n.jsx("pre",{children:`export CAPI_KEY="cat_你的_api_key" -codex`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Aider"}),n.jsx("span",{children:"OpenAI 兼容"})]}),n.jsx("pre",{children:`export OPENAI_API_BASE="${Ul()}" -export OPENAI_API_KEY="cat_你的_api_key" -aider --model openai/${N}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Cline / Roo Code / Kilo Code"}),n.jsx("span",{children:"VS Code 插件"})]}),n.jsxs("p",{children:["在插件设置中选择 ",n.jsx("strong",{children:"OpenAI Compatible"}),":"]}),n.jsx("pre",{children:`Base URL: ${Ul()}/v1 -API Key: cat_你的_api_key -Model ID: ${N}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"通用 OpenAI SDK"}),n.jsx("span",{children:"Python / Node.js"})]}),n.jsx("pre",{children:`export OPENAI_BASE_URL="${Ul()}" -export OPENAI_API_KEY="cat_你的_api_key"`}),n.jsx("pre",{children:`from openai import OpenAI -client = OpenAI() -response = client.chat.completions.create( - model="${N}", - messages=[{"role": "user", "content": "hello"}] -)`})]})]}),d&&n.jsx("p",{className:"cli-message",role:"status",children:d})]}),se==="maintenance"&&n.jsx(nt,{title:"维护设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志保留天数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"1",max:"3650",value:ne.logRetentionDays,onChange:_=>le(Ee=>({...Ee,logRetentionDays:Number(_.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"1000000",step:"100",value:ne.maxLogs,onChange:_=>le(Ee=>({...Ee,maxLogs:Number(_.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"额度流水最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"2000000",step:"100",value:ne.maxQuotaEntries,onChange:_=>le(Ee=>({...Ee,maxQuotaEntries:Number(_.target.value)}))})})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:d}),n.jsx("button",{type:"button",className:"primary-button",disabled:G,onClick:kt,children:G?"保存中":"保存维护设置"})]})]})}),se==="backup"&&n.jsx(nt,{title:"备份与恢复",children:n.jsx("div",{className:"settings-group",children:n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["备份与恢复",n.jsx("small",{children:"包含账号哈希和加密后的上游密钥,恢复时需要相同的 SECRET_KEY"})]}),n.jsxs("div",{className:"setting-value backup-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",disabled:G,onClick:cl,children:"导出备份"}),n.jsxs("label",{className:"secondary-button",children:["恢复备份",n.jsx("input",{type:"file",accept:"application/json,.json",disabled:G,onChange:_=>{const Ee=_.target.files?.[0];Ee&&V(Ee),_.target.value=""}})]})]})]})})}),se==="auth"&&n.jsx(nt,{title:"账号与注册",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放用户注册"}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:E?"启用":"关闭"}),n.jsx("button",{type:"button",className:E?"ios-switch is-on":"ios-switch","aria-label":E?"关闭用户注册":"开放用户注册","aria-pressed":!!E,onClick:Ke,children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"注册方式"}),n.jsx("div",{className:"registration-mode-control",role:"group","aria-label":"注册方式",children:[{value:"username",label:"账号密码"},{value:"email",label:"邮箱"},{value:"discord",label:"Discord"}].map(_=>n.jsx("button",{type:"button",className:$===_.value?"selected":"",onClick:()=>I(E??!0,_.value),children:_.label},_.value))})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["新用户初始额度",n.jsx("small",{children:"注册完成后自动发放,仅影响之后的新用户"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsx("input",{type:"number",min:"0",step:"0.01",value:y,onChange:_=>R(_.target.value),"aria-label":"新用户初始额度"}),n.jsx("button",{type:"button",className:"secondary-button",onClick:()=>I(E,$,Number(y)),children:"保存"})]})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["默认注册分组",n.jsx("small",{children:"新注册用户自动归入该分组,决定他们能用哪些渠道"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsxs("select",{value:z,onChange:_=>P(_.target.value),"aria-label":"默认注册分组",children:[h.map(_=>n.jsx("option",{value:_.id,children:_.name},_.id)),h.length===0&&n.jsx("option",{value:"",children:"暂无分组"})]}),n.jsx("button",{type:"button",className:"secondary-button",disabled:h.length===0,onClick:()=>I(E,$,Number(y),z),children:"保存"})]})]})]})}),se==="check-in"&&n.jsx(nt,{title:"每日签到奖励",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["开放每日签到",n.jsx("small",{children:"用户每天可领取一次随机额度,按北京时间刷新"})]}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:ee.enabled?"启用":"关闭"}),n.jsx("button",{type:"button",className:ee.enabled?"ios-switch is-on":"ios-switch","aria-label":ee.enabled?"关闭每日签到":"开放每日签到","aria-pressed":ee.enabled,onClick:()=>de(_=>({..._,enabled:!_.enabled})),children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting check-in-settings-row",children:[n.jsxs("span",{children:["随机奖励范围",n.jsx("small",{children:"领取金额精确到 0.01,直接计入用户余额和额度流水"})]}),n.jsxs("div",{className:"check-in-reward-inputs",children:[n.jsxs("label",{children:[n.jsx("span",{children:"最低"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:ee.minReward,onChange:_=>de(Ee=>({...Ee,minReward:Number(_.target.value)}))})]}),n.jsxs("label",{children:[n.jsx("span",{children:"最高"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:ee.maxReward,onChange:_=>de(Ee=>({...Ee,maxReward:Number(_.target.value)}))})]})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:d}),n.jsx("button",{type:"button",className:"primary-button",disabled:G,onClick:We,children:G?"保存中":"保存签到设置"})]})]})}),se==="admin"&&n.jsx(nt,{title:"管理员账号",children:n.jsxs("form",{className:"discord-settings",onSubmit:_=>{_.preventDefault(),tl()},children:[n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"登录账号"}),n.jsx("input",{value:F,onChange:_=>me(_.target.value),autoComplete:"username"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:D,onChange:_=>ae(_.target.value),autoComplete:"name"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"邮箱"}),n.jsx("input",{type:"email",value:fe,onChange:_=>Ae(_.target.value),autoComplete:"email"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:Te,onChange:_=>ue(_.target.value),placeholder:Y?.discordUserId?"已绑定":"输入管理员的 Discord 用户 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"当前密码"}),n.jsx("input",{type:"password",value:Z,onChange:_=>re(_.target.value),autoComplete:"current-password",placeholder:"修改密码时填写"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新密码"}),n.jsx("input",{type:"password",value:J,onChange:_=>T(_.target.value),autoComplete:"new-password",placeholder:"留空表示不修改"})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:d}),n.jsx("button",{className:"primary-button",type:"submit",children:"保存账号"})]})]})}),se==="discord"&&n.jsx(nt,{title:"Discord 登录",children:r?n.jsxs("form",{className:"discord-settings",autoComplete:"off",onSubmit:_=>{_.preventDefault(),Pe()},children:[n.jsxs("div",{className:"discord-toggle-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"Discord 登录"}),n.jsx("span",{children:r.enabled?"已启用":"未启用"})]}),n.jsx("button",{type:"button",className:r.enabled?"ios-switch is-on":"ios-switch","aria-label":r.enabled?"停用 Discord 登录":"启用 Discord 登录","aria-pressed":r.enabled,onClick:()=>A({...r,enabled:!r.enabled}),children:n.jsx("span",{})})]}),n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"Client ID"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:r.clientId,onChange:_=>A({...r,clientId:_.target.value}),placeholder:"100000000000000001"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Client Secret"}),n.jsx("input",{type:"password",autoComplete:"new-password",value:k,onChange:_=>B(_.target.value),placeholder:r.clientSecretSet?"已设置,留空表示不修改":"粘贴 Discord Client Secret"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"回调地址"}),n.jsx("input",{type:"url",value:r.redirectUri,onChange:_=>A({...r,redirectUri:_.target.value}),placeholder:"https://你的域名/api/auth/discord/callback"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"服务器 ID"}),n.jsx("input",{inputMode:"numeric",value:r.allowedGuildId,onChange:_=>A({...r,allowedGuildId:_.target.value}),placeholder:"允许登录的服务器 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"身份组 ID"}),n.jsx("input",{inputMode:"numeric",value:r.allowedRoleId,onChange:_=>A({...r,allowedRoleId:_.target.value}),placeholder:"允许登录的身份组 ID"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"拉黑服务器 ID"}),n.jsx("textarea",{value:Q,onChange:_=>O(_.target.value),placeholder:"每行一个服务器 ID;命中的用户禁止注册 / 登录",rows:3}),n.jsx("small",{children:"用户若加入了这些 Discord 服务器中的任意一个,将无法注册或登录(优先于上面的允许规则)。"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"登录成功跳转地址"}),n.jsx("input",{type:"url",value:r.authSuccessUrl,onChange:_=>A({...r,authSuccessUrl:_.target.value}),placeholder:"https://你的域名/"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"登录有效期(小时)"}),n.jsx("input",{type:"number",min:"1",max:"8760",value:r.sessionTtlHours,onChange:_=>A({...r,sessionTtlHours:Number(_.target.value)})})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:d}),n.jsx("button",{className:"primary-button",type:"submit",disabled:G,children:G?"保存中":"保存配置"})]})]}):n.jsx("div",{className:"empty",children:"正在读取配置"})})]})}function ul({label:u,value:m}){return n.jsxs("div",{className:"metric",children:[n.jsx("span",{children:u}),n.jsx("strong",{children:m})]})}function Kp({groups:u,onCreate:m,onUpdate:h,onDelete:r}){const[A,E]=g.useState(""),[L,$]=g.useState(""),[C,y]=g.useState(!1);async function R(z){if(z.preventDefault(),!!A.trim()){y(!0);try{await m({name:A.trim(),description:L.trim()}),E(""),$("")}finally{y(!1)}}}return n.jsxs("section",{className:"models-page",children:[n.jsxs(nt,{title:"用户分组",children:[n.jsxs("form",{className:"channel-create-form",onSubmit:R,children:[n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"分组名称"}),n.jsx("input",{value:A,onChange:z=>E(z.target.value),placeholder:"例如 尊享用户 / 试用用户"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"说明"}),n.jsx("input",{value:L,onChange:z=>$(z.target.value),placeholder:"可选"})]})]}),n.jsx("div",{className:"channel-card-actions",children:n.jsx("button",{className:"primary-button",type:"submit",disabled:C||!A.trim(),children:C?"创建中":"创建分组"})})]}),n.jsx("p",{className:"muted-inline",children:"分组用于控制渠道对用户的可见范围:把用户归入分组,并在渠道上勾选「可见分组」即可限制访问。未分组的用户只能使用未限制分组的渠道。"})]}),n.jsx(nt,{title:"全部分组",children:u.length===0?n.jsx(Lt,{text:"还没有分组"}):n.jsx("div",{className:"channels-stack",children:u.map(z=>n.jsx(Zp,{group:z,onUpdate:h,onDelete:r},z.id))})})]})}function Zp({group:u,onUpdate:m,onDelete:h}){const[r,A]=g.useState(!1),[E,L]=g.useState(u.name),[$,C]=g.useState(u.description),[y,R]=g.useState(!1);async function z(){R(!0);try{await m(u.id,{name:E.trim(),description:$.trim()}),A(!1)}finally{R(!1)}}return n.jsx("div",{className:"channel-card",children:n.jsxs("div",{className:"channel-card-head",children:[n.jsx("div",{children:r?n.jsxs("div",{className:"group-edit-fields",children:[n.jsx("input",{value:E,onChange:P=>L(P.target.value),placeholder:"分组名称"}),n.jsx("input",{value:$,onChange:P=>C(P.target.value),placeholder:"说明"})]}):n.jsxs(n.Fragment,{children:[n.jsx("strong",{children:u.name}),u.description&&n.jsx("span",{children:u.description}),n.jsxs("small",{children:["创建于 ",el(u.createdAt)]})]})}),n.jsx("div",{className:"channel-card-head-actions",children:r?n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"primary-button compact-button",onClick:z,disabled:y||!E.trim(),children:y?"保存中":"保存"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>{L(u.name),C(u.description),A(!1)},children:"取消"})]}):n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>A(!0),children:"重命名"}),n.jsx("button",{className:"danger-button compact-button",onClick:()=>h(u.id),children:"删除"})]})})]})})}function nt({title:u,children:m}){return n.jsxs("section",{className:"panel",children:[n.jsx("div",{className:"panel-title",children:n.jsx("h2",{children:u})}),m]})}function Dt({tone:u,children:m}){return n.jsx("span",{className:`badge tone-${u}`,children:m})}function Pt({label:u,value:m,switchOn:h}){return n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:u}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:m}),typeof h=="boolean"&&n.jsx("div",{className:h?"ios-switch is-on":"ios-switch","aria-hidden":"true",children:n.jsx("span",{})})]})]})}function Vp({value:u,options:m,onChange:h}){return n.jsx("div",{className:"segmented-control",children:m.map(r=>n.jsx("button",{className:u===r.value?"selected":"",onClick:()=>h(r.value),children:r.label},r.value))})}function Lt({text:u}){return n.jsx("div",{className:"empty",children:u})}J0.createRoot(document.getElementById("root")).render(n.jsx(L0.StrictMode,{children:n.jsx(fp,{})})); diff --git a/dist/index.html b/dist/index.html index 7db8b92..05a0788 100644 --- a/dist/index.html +++ b/dist/index.html @@ -5,7 +5,7 @@ CAPI - + diff --git a/src/App.tsx b/src/App.tsx index f1a2b51..4d850ef 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -363,6 +363,7 @@ type IconName = | "route" | "logs" | "settings" + | "orbit" | "search" | "copy" | "ban" @@ -379,6 +380,7 @@ const iconPaths: Record = { image: "M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2ZM8.5 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM21 16l-5-5L5 21", route: "M4 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM20 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM7 16h3a4 4 0 0 0 4-4V8h3", logs: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6M8 13h8M8 17h6", + orbit: "M12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10ZM3 12a9 3 0 1 0 18 0 9 3 0 1 0-18 0Z", settings: "M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 8.92 4a1.65 1.65 0 0 0 1-1.51V2a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.31.39.57.71.71.23.1.49.18.8.2H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z", search: "M21 21l-4.35-4.35M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z", copy: "M8 8h11a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1ZM4 16H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v1", @@ -438,6 +440,7 @@ const navItems = [ { id: "keys", label: "密钥", icon: "key" }, { id: "models", label: "模型", icon: "models" }, { id: "drawing", label: "绘图", icon: "image" }, + { id: "antigravity", label: "Antigravity", icon: "orbit" }, { id: "channels", label: "渠道", icon: "route" }, { id: "logs", label: "日志", icon: "logs" }, { id: "settings", label: "设置", icon: "settings" } @@ -1342,7 +1345,8 @@ function App() { {active === "groups" && } {active === "keys" && } {active === "models" && } - {active === "drawing" && } + {active === "drawing" && } + {active === "antigravity" && } {active === "channels" && } {active === "logs" && } {active === "settings" && } @@ -3054,7 +3058,8 @@ function DrawingView({ onDeleteAccount, onUpdate, onStartOAuth, - onCompleteOAuth + onCompleteOAuth, + variant = "drawing" }: { channels: Channel[]; onCreate: (channel?: ChannelCreate) => Promise; @@ -3065,8 +3070,14 @@ function DrawingView({ onUpdate: (id: string, patch: ChannelPatch) => Promise; onStartOAuth: (channelId: string) => Promise<{ authorizeUrl: string; state: string; redirectUri: string }>; onCompleteOAuth: (channelId: string, payload: { callbackUrl?: string; code?: string; state?: string }) => Promise; + variant?: "drawing" | "antigravity"; }) { - const drawingChannels = channels.filter((channel) => channel.provider === "codex" || channel.provider === "antigravity" || channel.provider === "openai" || arrayOf(channel.models).some((model) => model.includes("image"))); + const isAntigravity = variant === "antigravity"; + const drawingChannels = channels.filter((channel) => + isAntigravity + ? channel.provider === "antigravity" + : channel.provider !== "antigravity" && (channel.provider === "codex" || channel.provider === "openai" || arrayOf(channel.models).some((model) => model.includes("image"))) + ); const [busy, setBusy] = useState(""); const [accountVisibleCounts, setAccountVisibleCounts] = useState>({}); const [accountFilters, setAccountFilters] = useState>({}); @@ -3159,21 +3170,39 @@ function DrawingView({ } return ( - +
- 账号有两种来源,任选其一即可。 - - + {isAntigravity ? "导入 Google OAuth JSON 或 refresh token 即可入池。" : "账号有两种来源,任选其一即可。"} + {isAntigravity ? ( + + ) : ( + + )}
-
- 网页会话(推荐) - 支持完整 auth/session JSON 或浏览器 Session Cookie,并在调用前重新获取 accessToken。 -
-
- 批量导入 - 支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 access token。 -
+ {isAntigravity ? ( + <> +
+ Antigravity 导入(推荐) + 粘贴 Google OAuth 凭据 JSON 或 refresh token,调用前自动换取 accessToken。 +
+
+ 批量导入 + 支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 refresh token。 +
+ + ) : ( + <> +
+ 网页会话(推荐) + 支持完整 auth/session JSON 或浏览器 Session Cookie,并在调用前重新获取 accessToken。 +
+
+ 批量导入 + 支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 access token。 +
+ + )}
{drawingChannels.map((channel) => { @@ -3345,7 +3374,7 @@ function DrawingView({
); })} - {drawingChannels.length === 0 && } + {drawingChannels.length === 0 && } {oauthChannelId && (