diff --git a/VERSION b/VERSION
index 0041a435..470abefa 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.66
+1.1.67
diff --git a/web/admin-spa/dist/assets/AccountsView-tVq-jcj7.js b/web/admin-spa/dist/assets/AccountsView-DHI8l47P.js
similarity index 69%
rename from web/admin-spa/dist/assets/AccountsView-tVq-jcj7.js
rename to web/admin-spa/dist/assets/AccountsView-DHI8l47P.js
index 63ba71b8..f94a1aff 100644
--- a/web/admin-spa/dist/assets/AccountsView-tVq-jcj7.js
+++ b/web/admin-spa/dist/assets/AccountsView-DHI8l47P.js
@@ -1,15 +1,15 @@
-import{r as b,aR as ze,o as E,V as Ee,x as n,y as a,z as e,L as y,K as g,al as _e,aY as me,aX as ce,aq as _,aZ as Oe,C as R,O as C,c as ne,P as f,I as le,a5 as Ae,q as Ke,an as X,Q as re,ac as ie,R as Ce,u as Y,Y as We,B as Te}from"./vue-vendor-CKToUHZx.js";import{s as h}from"./toast-BvwA7Mwb.js";import{a as V,_ as qe}from"./index-D3bIJLrk.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const $e=b(!1),Me=b({title:"",message:"",confirmText:"继续",cancelText:"取消"}),se=b(null);function Le(){return{showConfirmModal:$e,confirmOptions:Me,showConfirm:($,i,M="继续",I="取消")=>new Promise(T=>{Me.value={title:$,message:i,confirmText:M,cancelText:I},se.value=T,$e.value=!0}),handleConfirm:()=>{$e.value=!1,se.value&&(se.value(!0),se.value=null)},handleCancel:()=>{$e.value=!1,se.value&&(se.value(!1),se.value=null)}}}const Pe=ze("accounts",()=>{const P=b([]),O=b([]),d=b([]),$=b(!1),i=b(null),M=b(""),I=b("asc"),T=async()=>{$.value=!0,i.value=null;try{const c=await V.get("/admin/claude-accounts");if(c.success)P.value=c.data||[];else throw new Error(c.message||"获取Claude账户失败")}catch(c){throw i.value=c.message,c}finally{$.value=!1}},w=async()=>{$.value=!0,i.value=null;try{const c=await V.get("/admin/claude-console-accounts");if(c.success)O.value=c.data||[];else throw new Error(c.message||"获取Claude Console账户失败")}catch(c){throw i.value=c.message,c}finally{$.value=!1}},v=async()=>{$.value=!0,i.value=null;try{const c=await V.get("/admin/gemini-accounts");if(c.success)d.value=c.data||[];else throw new Error(c.message||"获取Gemini账户失败")}catch(c){throw i.value=c.message,c}finally{$.value=!1}};return{claudeAccounts:P,claudeConsoleAccounts:O,geminiAccounts:d,loading:$,error:i,sortBy:M,sortOrder:I,fetchClaudeAccounts:T,fetchClaudeConsoleAccounts:w,fetchGeminiAccounts:v,fetchAllAccounts:async()=>{$.value=!0,i.value=null;try{await Promise.all([T(),w(),v()])}catch(c){throw i.value=c.message,c}finally{$.value=!1}},createClaudeAccount:async c=>{$.value=!0,i.value=null;try{const p=await V.post("/admin/claude-accounts",c);if(p.success)return await T(),p.data;throw new Error(p.message||"创建Claude账户失败")}catch(p){throw i.value=p.message,p}finally{$.value=!1}},createClaudeConsoleAccount:async c=>{$.value=!0,i.value=null;try{const p=await V.post("/admin/claude-console-accounts",c);if(p.success)return await w(),p.data;throw new Error(p.message||"创建Claude Console账户失败")}catch(p){throw i.value=p.message,p}finally{$.value=!1}},createGeminiAccount:async c=>{$.value=!0,i.value=null;try{const p=await V.post("/admin/gemini-accounts",c);if(p.success)return await v(),p.data;throw new Error(p.message||"创建Gemini账户失败")}catch(p){throw i.value=p.message,p}finally{$.value=!1}},updateClaudeAccount:async(c,p)=>{$.value=!0,i.value=null;try{const U=await V.put(`/admin/claude-accounts/${c}`,p);if(U.success)return await T(),U;throw new Error(U.message||"更新Claude账户失败")}catch(U){throw i.value=U.message,U}finally{$.value=!1}},updateClaudeConsoleAccount:async(c,p)=>{$.value=!0,i.value=null;try{const U=await V.put(`/admin/claude-console-accounts/${c}`,p);if(U.success)return await w(),U;throw new Error(U.message||"更新Claude Console账户失败")}catch(U){throw i.value=U.message,U}finally{$.value=!1}},updateGeminiAccount:async(c,p)=>{$.value=!0,i.value=null;try{const U=await V.put(`/admin/gemini-accounts/${c}`,p);if(U.success)return await v(),U;throw new Error(U.message||"更新Gemini账户失败")}catch(U){throw i.value=U.message,U}finally{$.value=!1}},toggleAccount:async(c,p)=>{$.value=!0,i.value=null;try{let U;c==="claude"?U=`/admin/claude-accounts/${p}/toggle`:c==="claude-console"?U=`/admin/claude-console-accounts/${p}/toggle`:U=`/admin/gemini-accounts/${p}/toggle`;const B=await V.put(U);if(B.success)return c==="claude"?await T():c==="claude-console"?await w():await v(),B;throw new Error(B.message||"切换状态失败")}catch(U){throw i.value=U.message,U}finally{$.value=!1}},deleteAccount:async(c,p)=>{$.value=!0,i.value=null;try{let U;c==="claude"?U=`/admin/claude-accounts/${p}`:c==="claude-console"?U=`/admin/claude-console-accounts/${p}`:U=`/admin/gemini-accounts/${p}`;const B=await V.delete(U);if(B.success)return c==="claude"?await T():c==="claude-console"?await w():await v(),B;throw new Error(B.message||"删除失败")}catch(U){throw i.value=U.message,U}finally{$.value=!1}},refreshClaudeToken:async c=>{$.value=!0,i.value=null;try{const p=await V.post(`/admin/claude-accounts/${c}/refresh`);if(p.success)return await T(),p;throw new Error(p.message||"Token刷新失败")}catch(p){throw i.value=p.message,p}finally{$.value=!1}},generateClaudeAuthUrl:async c=>{try{const p=await V.post("/admin/claude-accounts/generate-auth-url",c);if(p.success)return p.data;throw new Error(p.message||"生成授权URL失败")}catch(p){throw i.value=p.message,p}},exchangeClaudeCode:async c=>{try{const p=await V.post("/admin/claude-accounts/exchange-code",c);if(p.success)return p.data;throw new Error(p.message||"交换授权码失败")}catch(p){throw i.value=p.message,p}},generateGeminiAuthUrl:async c=>{try{const p=await V.post("/admin/gemini-accounts/generate-auth-url",c);if(p.success)return p.data;throw new Error(p.message||"生成授权URL失败")}catch(p){throw i.value=p.message,p}},exchangeGeminiCode:async c=>{try{const p=await V.post("/admin/gemini-accounts/exchange-code",c);if(p.success)return p.data;throw new Error(p.message||"交换授权码失败")}catch(p){throw i.value=p.message,p}},sortAccounts:c=>{M.value===c?I.value=I.value==="asc"?"desc":"asc":(M.value=c,I.value="asc")},reset:()=>{P.value=[],O.value=[],d.value=[],$.value=!1,i.value=null,M.value="",I.value="asc"}}}),Fe={class:"space-y-4"},Be={class:"flex items-center justify-between"},Ne={class:"flex items-center cursor-pointer"},He={key:0,class:"bg-gray-50 p-4 rounded-lg border border-gray-200 space-y-4"},Je={class:"grid grid-cols-2 gap-4"},Ye={class:"space-y-4"},Qe={class:"flex items-center"},Xe={key:0,class:"grid grid-cols-2 gap-4"},Ze={class:"relative"},et=["type"],Ge={__name:"ProxyConfig",props:{modelValue:{type:Object,default:()=>({enabled:!1,type:"socks5",host:"",port:"",username:"",password:""})}},emits:["update:modelValue"],setup(P,{emit:O}){const d=P,$=O,i=b({...d.modelValue}),M=b(!!(i.value.username||i.value.password)),I=b(!1);E(()=>d.modelValue,v=>{JSON.stringify(v)!==JSON.stringify(i.value)&&(i.value={...v},M.value=!!(v.username||v.password))},{deep:!0}),E(()=>i.value.enabled,v=>{w()}),E(()=>i.value.type,v=>{w()}),E(()=>i.value.host,v=>{w()}),E(()=>i.value.port,v=>{w()}),E(()=>i.value.username,v=>{w()}),E(()=>i.value.password,v=>{w()}),E(M,v=>{v||(i.value.username="",i.value.password="",w())});let T=null;function w(){T&&clearTimeout(T),T=setTimeout(()=>{const v={...i.value};M.value||(v.username="",v.password=""),$("update:modelValue",v)},100)}return Ee(()=>{T&&clearTimeout(T)}),(v,m)=>(a(),n("div",Fe,[e("div",Be,[m[9]||(m[9]=e("h4",{class:"text-sm font-semibold text-gray-700"}," 代理设置 (可选) ",-1)),e("label",Ne,[g(e("input",{"onUpdate:modelValue":m[0]||(m[0]=G=>i.value.enabled=G),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[_e,i.value.enabled]]),m[8]||(m[8]=e("span",{class:"ml-2 text-sm text-gray-700"},"启用代理",-1))])]),i.value.enabled?(a(),n("div",He,[m[17]||(m[17]=me('
配置代理以访问受限的网络资源。支持 SOCKS5 和 HTTP 代理。
请确保代理服务器稳定可用,否则会影响账户的正常使用。
',1)),e("div",null,[m[11]||(m[11]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"代理类型",-1)),g(e("select",{"onUpdate:modelValue":m[1]||(m[1]=G=>i.value.type=G),class:"form-input w-full"},m[10]||(m[10]=[e("option",{value:"socks5"}," SOCKS5 ",-1),e("option",{value:"http"}," HTTP ",-1),e("option",{value:"https"}," HTTPS ",-1)]),512),[[ce,i.value.type]])]),e("div",Je,[e("div",null,[m[12]||(m[12]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"主机地址",-1)),g(e("input",{"onUpdate:modelValue":m[2]||(m[2]=G=>i.value.host=G),type:"text",placeholder:"例如: 192.168.1.100",class:"form-input w-full"},null,512),[[_,i.value.host]])]),e("div",null,[m[13]||(m[13]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"端口",-1)),g(e("input",{"onUpdate:modelValue":m[3]||(m[3]=G=>i.value.port=G),type:"number",placeholder:"例如: 1080",class:"form-input w-full"},null,512),[[_,i.value.port]])])]),e("div",Ye,[e("div",Qe,[g(e("input",{id:"proxyAuth","onUpdate:modelValue":m[4]||(m[4]=G=>M.value=G),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[_e,M.value]]),m[14]||(m[14]=e("label",{for:"proxyAuth",class:"ml-2 text-sm text-gray-700 cursor-pointer"}," 需要身份验证 ",-1))]),M.value?(a(),n("div",Xe,[e("div",null,[m[15]||(m[15]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"用户名",-1)),g(e("input",{"onUpdate:modelValue":m[5]||(m[5]=G=>i.value.username=G),type:"text",placeholder:"代理用户名",class:"form-input w-full"},null,512),[[_,i.value.username]])]),e("div",null,[m[16]||(m[16]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"密码",-1)),e("div",Ze,[g(e("input",{"onUpdate:modelValue":m[6]||(m[6]=G=>i.value.password=G),type:I.value?"text":"password",placeholder:"代理密码",class:"form-input w-full pr-10"},null,8,et),[[Oe,i.value.password]]),e("button",{type:"button",class:"absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600",onClick:m[7]||(m[7]=G=>I.value=!I.value)},[e("i",{class:R(I.value?"fas fa-eye-slash":"fas fa-eye")},null,2)])])])])):y("",!0)]),m[18]||(m[18]=e("div",{class:"bg-blue-50 p-3 rounded-lg border border-blue-200"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),e("strong",null,"提示:"),C("代理设置将用于所有与此账户相关的API请求。请确保代理服务器支持HTTPS流量转发。 ")])],-1))])):y("",!0)]))}},tt={class:"space-y-6"},st={key:0},lt={class:"bg-blue-50 p-6 rounded-lg border border-blue-200"},ot={class:"flex items-start gap-4"},at={class:"flex-1"},nt={class:"space-y-4"},rt={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},it={class:"flex items-start gap-3"},ut={class:"flex-1"},dt=["disabled"],pt={key:0,class:"fas fa-link mr-2"},mt={key:1,class:"loading-spinner mr-2"},ct={key:1,class:"space-y-3"},ft={class:"flex items-center gap-2"},xt=["value"],vt={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},gt={class:"flex items-start gap-3"},yt={class:"flex-1"},bt={class:"space-y-3"},wt={key:1},kt={class:"bg-green-50 p-6 rounded-lg border border-green-200"},ht={class:"flex items-start gap-4"},$t={class:"flex-1"},Ct={class:"space-y-4"},Tt={class:"bg-white/80 rounded-lg p-4 border border-green-300"},At={class:"flex items-start gap-3"},Ut={class:"flex-1"},It=["disabled"],Vt={key:0,class:"fas fa-link mr-2"},jt={key:1,class:"loading-spinner mr-2"},St={key:1,class:"space-y-3"},_t={class:"flex items-center gap-2"},Mt=["value"],Gt={class:"bg-white/80 rounded-lg p-4 border border-green-300"},Rt={class:"flex items-start gap-3"},Kt={class:"flex-1"},Lt={class:"space-y-3"},Pt={class:"flex gap-3 pt-4"},Dt=["disabled"],zt={key:0,class:"loading-spinner mr-2"},Et={__name:"OAuthFlow",props:{platform:{type:String,required:!0},proxy:{type:Object,default:null}},emits:["success","back"],setup(P,{emit:O}){const d=P,$=O,i=Pe(),M=b(!1),I=b(!1),T=b(""),w=b(""),v=b(!1),m=b(""),G=ne(()=>T.value&&w.value.trim());E(w,x=>{if(!x||typeof x!="string")return;const r=x.trim();if(!r)return;if(r.startsWith("http://")||r.startsWith("https://"))if(r.startsWith("http://localhost:45462"))try{const W=new URL(r).searchParams.get("code");W?(w.value=W,h("成功提取授权码!","success"),console.log("Successfully extracted authorization code from URL")):h("URL 中未找到授权码参数,请检查链接是否正确","error")}catch(F){console.error("Failed to parse URL:",F),h("链接格式错误,请检查是否为完整的 URL","error")}else if(d.platform==="gemini")try{const W=new URL(r).searchParams.get("code");W&&(w.value=W,h("成功提取授权码!","success"))}catch{}else h("请粘贴以 http://localhost:45462 开头的链接","error")});const S=async()=>{var x;M.value=!0;try{const r=(x=d.proxy)!=null&&x.enabled?{proxy:{type:d.proxy.type,host:d.proxy.host,port:parseInt(d.proxy.port),username:d.proxy.username||null,password:d.proxy.password||null}}:{};if(d.platform==="claude"){const L=await i.generateClaudeAuthUrl(r);T.value=L.authUrl,m.value=L.sessionId}else if(d.platform==="gemini"){const L=await i.generateGeminiAuthUrl(r);T.value=L.authUrl,m.value=L.sessionId}}catch(r){h(r.message||"生成授权链接失败","error")}finally{M.value=!1}},K=()=>{T.value="",w.value="",S()},q=async()=>{try{await navigator.clipboard.writeText(T.value),v.value=!0,h("链接已复制","success"),setTimeout(()=>{v.value=!1},2e3)}catch{const r=document.createElement("input");r.value=T.value,document.body.appendChild(r),r.select(),document.execCommand("copy"),document.body.removeChild(r),v.value=!0,h("链接已复制","success"),setTimeout(()=>{v.value=!1},2e3)}},l=async()=>{var x;if(G.value){I.value=!0;try{let r={};d.platform==="claude"?r={sessionId:m.value,callbackUrl:w.value.trim()}:d.platform==="gemini"&&(r={code:w.value.trim(),sessionId:m.value}),(x=d.proxy)!=null&&x.enabled&&(r.proxy={type:d.proxy.type,host:d.proxy.host,port:parseInt(d.proxy.port),username:d.proxy.username||null,password:d.proxy.password||null});let L;d.platform==="claude"?L=await i.exchangeClaudeCode(r):d.platform==="gemini"&&(L=await i.exchangeGeminiCode(r)),$("success",L)}catch(r){h(r.message||"授权失败,请检查授权码是否正确","error")}finally{I.value=!1}}};return(x,r)=>(a(),n("div",tt,[P.platform==="claude"?(a(),n("div",st,[e("div",lt,[e("div",ot,[r[14]||(r[14]=e("div",{class:"w-10 h-10 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-link text-white"})],-1)),e("div",at,[r[12]||(r[12]=e("h4",{class:"font-semibold text-blue-900 mb-3"}," Claude 账户授权 ",-1)),r[13]||(r[13]=e("p",{class:"text-sm text-blue-800 mb-4"}," 请按照以下步骤完成 Claude 账户的授权: ",-1)),e("div",nt,[e("div",rt,[e("div",it,[r[5]||(r[5]=e("div",{class:"w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 1 ",-1)),e("div",ut,[r[4]||(r[4]=e("p",{class:"font-medium text-blue-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(a(),n("div",ct,[e("div",ft,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,xt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:q},[e("i",{class:R(v.value?"fas fa-check text-green-500":"fas fa-copy")},null,2)])]),e("button",{class:"text-xs text-blue-600 hover:text-blue-700",onClick:K},r[3]||(r[3]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),C("重新生成 ",-1)]))])):(a(),n("button",{key:0,disabled:M.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:S},[M.value?(a(),n("div",mt)):(a(),n("i",pt)),C(" "+f(M.value?"生成中...":"生成授权链接"),1)],8,dt))])])]),r[11]||(r[11]=me(' 2
在浏览器中打开链接并完成授权
请在新标签页中打开授权链接,登录您的 Claude 账户并授权。
注意:如果您设置了代理,请确保浏览器也使用相同的代理访问授权页面。
',1)),e("div",vt,[e("div",gt,[r[10]||(r[10]=e("div",{class:"w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 3 ",-1)),e("div",yt,[r[8]||(r[8]=e("p",{class:"font-medium text-blue-900 mb-2"}," 输入 Authorization Code ",-1)),r[9]||(r[9]=e("p",{class:"text-sm text-blue-700 mb-3"},[C(" 授权完成后,页面会显示一个 "),e("strong",null,"Authorization Code"),C(",请将其复制并粘贴到下方输入框: ")],-1)),e("div",bt,[e("div",null,[r[6]||(r[6]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[e("i",{class:"fas fa-key text-blue-500 mr-2"}),C("Authorization Code ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[0]||(r[0]=L=>w.value=L),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴从Claude页面获取的Authorization Code..."},null,512),[[_,w.value]])]),r[7]||(r[7]=e("p",{class:"text-xs text-gray-500 mt-2"},[e("i",{class:"fas fa-info-circle mr-1"}),C(" 请粘贴从Claude页面复制的Authorization Code ")],-1))])])])])])])])])])):P.platform==="gemini"?(a(),n("div",wt,[e("div",kt,[e("div",ht,[r[26]||(r[26]=e("div",{class:"w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-robot text-white"})],-1)),e("div",$t,[r[24]||(r[24]=e("h4",{class:"font-semibold text-green-900 mb-3"}," Gemini 账户授权 ",-1)),r[25]||(r[25]=e("p",{class:"text-sm text-green-800 mb-4"}," 请按照以下步骤完成 Gemini 账户的授权: ",-1)),e("div",Ct,[e("div",Tt,[e("div",At,[r[17]||(r[17]=e("div",{class:"w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 1 ",-1)),e("div",Ut,[r[16]||(r[16]=e("p",{class:"font-medium text-green-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(a(),n("div",St,[e("div",_t,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,Mt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:q},[e("i",{class:R(v.value?"fas fa-check text-green-500":"fas fa-copy")},null,2)])]),e("button",{class:"text-xs text-green-600 hover:text-green-700",onClick:K},r[15]||(r[15]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),C("重新生成 ",-1)]))])):(a(),n("button",{key:0,disabled:M.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:S},[M.value?(a(),n("div",jt)):(a(),n("i",Vt)),C(" "+f(M.value?"生成中...":"生成授权链接"),1)],8,It))])])]),r[23]||(r[23]=me(' 2
在浏览器中打开链接并完成授权
- 点击上方的授权链接,在新页面中完成Google账号登录
- 点击“登录”按钮后可能会加载很慢(这是正常的)
- 如果超过1分钟还在加载,请按 F5 刷新页面
- 授权完成后会跳转到 http://localhost:45462 (可能显示无法访问)
提示:如果页面一直无法跳转,可以打开浏览器开发者工具(F12),F5刷新一下授权页再点击页面的登录按钮,在“网络”标签中找到以 localhost:45462 开头的请求,复制其完整URL。
',1)),e("div",Gt,[e("div",Rt,[r[22]||(r[22]=e("div",{class:"w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 3 ",-1)),e("div",Kt,[r[20]||(r[20]=e("p",{class:"font-medium text-green-900 mb-2"}," 复制oauth后的链接 ",-1)),r[21]||(r[21]=e("p",{class:"text-sm text-green-700 mb-3"}," 复制浏览器地址栏的完整链接并粘贴到下方输入框: ",-1)),e("div",Lt,[e("div",null,[r[18]||(r[18]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[e("i",{class:"fas fa-key text-green-500 mr-2"}),C("复制oauth后的链接 ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[1]||(r[1]=L=>w.value=L),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴以 http://localhost:45462 开头的完整链接..."},null,512),[[_,w.value]])]),r[19]||(r[19]=me(' 支持粘贴完整链接,系统会自动提取授权码
也可以直接粘贴授权码(code参数的值)
',1))])])])])])])])])])):y("",!0),e("div",Pt,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:r[2]||(r[2]=L=>x.$emit("back"))}," 上一步 "),e("button",{type:"button",disabled:!G.value||I.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:l},[I.value?(a(),n("div",zt)):y("",!0),C(" "+f(I.value?"验证中...":"完成授权"),1)],8,Dt)])]))}},Ot={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Wt={class:"modal-content w-full max-w-md p-6 mx-auto"},qt={class:"flex items-start gap-4 mb-6"},Ft={class:"flex-1"},Bt={class:"text-lg font-bold text-gray-900 mb-2"},Nt={class:"text-gray-600 text-sm leading-relaxed whitespace-pre-line"},Ht={class:"flex gap-3"},De={__name:"ConfirmModal",props:{show:{type:Boolean,required:!0},title:{type:String,default:""},message:{type:String,default:""},confirmText:{type:String,default:"继续"},cancelText:{type:String,default:"取消"}},emits:["confirm","cancel"],setup(P){return(O,d)=>(a(),le(Ae,{to:"body"},[P.show?(a(),n("div",Ot,[e("div",Wt,[e("div",qt,[d[2]||(d[2]=e("div",{class:"w-12 h-12 bg-gradient-to-br from-yellow-400 to-yellow-500 rounded-full flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-exclamation text-white text-xl"})],-1)),e("div",Ft,[e("h3",Bt,f(P.title),1),e("p",Nt,f(P.message),1)])]),e("div",Ht,[e("button",{class:"flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-xl font-medium hover:bg-gray-200 transition-colors",onClick:d[0]||(d[0]=$=>O.$emit("cancel"))},f(P.cancelText),1),e("button",{class:"flex-1 px-4 py-2.5 bg-gradient-to-r from-yellow-500 to-orange-500 text-white rounded-xl font-medium hover:from-yellow-600 hover:to-orange-600 transition-colors shadow-sm",onClick:d[1]||(d[1]=$=>O.$emit("confirm"))},f(P.confirmText),1)])])])):y("",!0)]))}},Jt={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},Yt={class:"modal-content w-full max-w-4xl p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Qt={class:"flex items-center justify-between mb-4 sm:mb-6"},Xt={class:"mb-6"},Zt={key:0,class:"mb-6 p-4 bg-blue-50 rounded-lg border border-blue-200"},es={class:"space-y-4"},ts={class:"flex gap-4"},ss={class:"flex items-center cursor-pointer"},ls={class:"flex items-center cursor-pointer"},os={class:"flex gap-3"},as=["disabled"],ns={key:0,class:"loading-spinner mr-2"},rs={class:"space-y-4"},is={key:0,class:"text-center py-8"},us={key:1,class:"text-center py-8 bg-gray-50 rounded-lg"},ds={key:2,class:"grid gap-4 grid-cols-1 md:grid-cols-2"},ps={class:"flex items-start justify-between mb-3"},ms={class:"flex-1"},cs={class:"font-semibold text-gray-900"},fs={class:"text-sm text-gray-500 mt-1"},xs={class:"flex items-center gap-2 ml-4"},vs={class:"flex items-center justify-between text-sm text-gray-600"},gs={class:"flex items-center gap-4"},ys={class:"flex items-center gap-2"},bs=["onClick"],ws=["disabled","onClick"],ks={key:1,class:"fixed inset-0 modal z-60 flex items-center justify-center p-3 sm:p-4"},hs={class:"modal-content w-full max-w-lg p-4 sm:p-6"},$s={class:"space-y-4"},Cs={class:"px-3 py-2 bg-gray-100 rounded-lg text-sm text-gray-600"},Ts={class:"flex gap-3 pt-4"},As=["disabled"],Us={key:0,class:"loading-spinner mr-2"},Is={__name:"GroupManagementModal",emits:["close","refresh"],setup(P,{emit:O}){const d=O,$=b(!0),i=b(!1),M=b([]),I=b(!1),T=b(!1),w=b({name:"",platform:"claude",description:""}),v=b(!1),m=b(!1),G=b(null),S=b({name:"",platform:"",description:""}),K=j=>j?new Date(j).toLocaleDateString("zh-CN"):"-",q=async()=>{i.value=!0;try{const j=await V.get("/admin/account-groups");M.value=j.data||[]}catch{h("加载分组列表失败","error")}finally{i.value=!1}},l=async()=>{var j,u;if(!w.value.name||!w.value.platform){h("请填写必填项","error");return}T.value=!0;try{await V.post("/admin/account-groups",{name:w.value.name,platform:w.value.platform,description:w.value.description}),h("分组创建成功","success"),x(),await q(),d("refresh")}catch(A){h(((u=(j=A.response)==null?void 0:j.data)==null?void 0:u.error)||"创建分组失败","error")}finally{T.value=!1}},x=()=>{I.value=!1,w.value={name:"",platform:"claude",description:""}},r=j=>{G.value=j,S.value={name:j.name,platform:j.platform,description:j.description||""},v.value=!0},L=async()=>{var j,u;if(!S.value.name){h("请填写分组名称","error");return}m.value=!0;try{await V.put(`/admin/account-groups/${G.value.id}`,{name:S.value.name,description:S.value.description}),h("分组更新成功","success"),F(),await q(),d("refresh")}catch(A){h(((u=(j=A.response)==null?void 0:j.data)==null?void 0:u.error)||"更新分组失败","error")}finally{m.value=!1}},F=()=>{v.value=!1,G.value=null,S.value={name:"",platform:"",description:""}},W=async j=>{var u,A;if(j.memberCount>0){h("分组内还有成员,无法删除","error");return}if(confirm(`确定要删除分组 "${j.name}" 吗?`))try{await V.delete(`/admin/account-groups/${j.id}`),h("分组删除成功","success"),await q(),d("refresh")}catch(Z){h(((A=(u=Z.response)==null?void 0:u.data)==null?void 0:A.error)||"删除分组失败","error")}};return Ke(()=>{q()}),(j,u)=>(a(),le(Ae,{to:"body"},[$.value?(a(),n("div",Jt,[e("div",Yt,[e("div",Qt,[u[9]||(u[9]=e("div",{class:"flex items-center gap-2 sm:gap-3"},[e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-purple-500 to-purple-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-layer-group text-white text-sm sm:text-base"})]),e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 账户分组管理 ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:u[0]||(u[0]=A=>j.$emit("close"))},u[8]||(u[8]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),e("div",Xt,[e("button",{class:"btn btn-primary px-4 py-2",onClick:u[1]||(u[1]=A=>I.value=!0)},u[10]||(u[10]=[e("i",{class:"fas fa-plus mr-2"},null,-1),C(" 创建新分组 ",-1)]))]),I.value?(a(),n("div",Zt,[u[16]||(u[16]=e("h4",{class:"text-lg font-semibold text-gray-900 mb-4"},"创建新分组",-1)),e("div",es,[e("div",null,[u[11]||(u[11]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"分组名称 *",-1)),g(e("input",{"onUpdate:modelValue":u[2]||(u[2]=A=>w.value.name=A),type:"text",class:"form-input w-full",placeholder:"输入分组名称"},null,512),[[_,w.value.name]])]),e("div",null,[u[14]||(u[14]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"平台类型 *",-1)),e("div",ts,[e("label",ss,[g(e("input",{"onUpdate:modelValue":u[3]||(u[3]=A=>w.value.platform=A),type:"radio",value:"claude",class:"mr-2"},null,512),[[X,w.value.platform]]),u[12]||(u[12]=e("span",{class:"text-sm text-gray-700"},"Claude",-1))]),e("label",ls,[g(e("input",{"onUpdate:modelValue":u[4]||(u[4]=A=>w.value.platform=A),type:"radio",value:"gemini",class:"mr-2"},null,512),[[X,w.value.platform]]),u[13]||(u[13]=e("span",{class:"text-sm text-gray-700"},"Gemini",-1))])])]),e("div",null,[u[15]||(u[15]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":u[5]||(u[5]=A=>w.value.description=A),rows:"2",class:"form-input w-full resize-none",placeholder:"分组描述..."},null,512),[[_,w.value.description]])]),e("div",os,[e("button",{class:"btn btn-primary px-4 py-2",disabled:!w.value.name||!w.value.platform||T.value,onClick:l},[T.value?(a(),n("div",ns)):y("",!0),C(" "+f(T.value?"创建中...":"创建"),1)],8,as),e("button",{class:"btn btn-secondary px-4 py-2",onClick:x}," 取消 ")])])])):y("",!0),e("div",rs,[i.value?(a(),n("div",is,u[17]||(u[17]=[e("div",{class:"loading-spinner-lg mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"},"加载中...",-1)]))):M.value.length===0?(a(),n("div",us,u[18]||(u[18]=[e("i",{class:"fas fa-layer-group text-4xl text-gray-300 mb-4"},null,-1),e("p",{class:"text-gray-500"},"暂无分组",-1)]))):(a(),n("div",ds,[(a(!0),n(re,null,ie(M.value,A=>(a(),n("div",{key:A.id,class:"bg-white rounded-lg border p-4 hover:shadow-md transition-shadow"},[e("div",ps,[e("div",ms,[e("h4",cs,f(A.name),1),e("p",fs,f(A.description||"暂无描述"),1)]),e("div",xs,[e("span",{class:R(["px-2 py-1 text-xs font-medium rounded-full",A.platform==="claude"?"bg-purple-100 text-purple-700":"bg-blue-100 text-blue-700"])},f(A.platform==="claude"?"Claude":"Gemini"),3)])]),e("div",vs,[e("div",gs,[e("span",null,[u[19]||(u[19]=e("i",{class:"fas fa-users mr-1"},null,-1)),C(" "+f(A.memberCount||0)+" 个成员 ",1)]),e("span",null,[u[20]||(u[20]=e("i",{class:"fas fa-clock mr-1"},null,-1)),C(" "+f(K(A.createdAt)),1)])]),e("div",ys,[e("button",{class:"text-blue-600 hover:text-blue-800 transition-colors",title:"编辑",onClick:Z=>r(A)},u[21]||(u[21]=[e("i",{class:"fas fa-edit"},null,-1)]),8,bs),e("button",{class:"text-red-600 hover:text-red-800 transition-colors",title:"删除",disabled:A.memberCount>0,onClick:Z=>W(A)},u[22]||(u[22]=[e("i",{class:"fas fa-trash"},null,-1)]),8,ws)])])]))),128))]))])])])):y("",!0),v.value?(a(),n("div",ks,[e("div",hs,[e("div",{class:"flex items-center justify-between mb-4"},[u[24]||(u[24]=e("h3",{class:"text-lg font-bold text-gray-900"},"编辑分组",-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:F},u[23]||(u[23]=[e("i",{class:"fas fa-times"},null,-1)]))]),e("div",$s,[e("div",null,[u[25]||(u[25]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"分组名称 *",-1)),g(e("input",{"onUpdate:modelValue":u[6]||(u[6]=A=>S.value.name=A),type:"text",class:"form-input w-full",placeholder:"输入分组名称"},null,512),[[_,S.value.name]])]),e("div",null,[u[27]||(u[27]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"平台类型",-1)),e("div",Cs,[C(f(S.value.platform==="claude"?"Claude":"Gemini")+" ",1),u[26]||(u[26]=e("span",{class:"text-xs text-gray-500 ml-2"},"(不可修改)",-1))])]),e("div",null,[u[28]||(u[28]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":u[7]||(u[7]=A=>S.value.description=A),rows:"2",class:"form-input w-full resize-none",placeholder:"分组描述..."},null,512),[[_,S.value.description]])]),e("div",Ts,[e("button",{class:"btn btn-primary px-4 py-2 flex-1",disabled:!S.value.name||m.value,onClick:L},[m.value?(a(),n("div",Us)):y("",!0),C(" "+f(m.value?"更新中...":"更新"),1)],8,As),e("button",{class:"btn btn-secondary px-4 py-2 flex-1",onClick:F}," 取消 ")])])])])):y("",!0)]))}},Vs={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},js={class:"modal-content w-full max-w-2xl p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Ss={class:"flex items-center justify-between mb-4 sm:mb-6"},_s={class:"flex items-center gap-2 sm:gap-3"},Ms={class:"text-lg sm:text-xl font-bold text-gray-900"},Gs={key:0,class:"flex items-center justify-center mb-4 sm:mb-8"},Rs={class:"flex items-center space-x-2 sm:space-x-4"},Ks={class:"flex items-center"},Ls={class:"flex items-center"},Ps={key:1},Ds={class:"space-y-6"},zs={key:0},Es={class:"flex gap-4"},Os={class:"flex items-center cursor-pointer"},Ws={class:"flex items-center cursor-pointer"},qs={class:"flex items-center cursor-pointer"},Fs={key:1},Bs={class:"flex gap-4"},Ns={class:"flex items-center cursor-pointer"},Hs={class:"flex items-center cursor-pointer"},Js={key:0,class:"text-red-500 text-xs mt-1"},Ys={class:"flex gap-4"},Qs={class:"flex items-center cursor-pointer"},Xs={class:"flex items-center cursor-pointer"},Zs={class:"flex items-center cursor-pointer"},el={key:2},tl={class:"flex gap-2"},sl=["value"],ll={key:3},ol={key:4,class:"space-y-4"},al={key:0,class:"text-red-500 text-xs mt-1"},nl={key:0,class:"text-red-500 text-xs mt-1"},rl={class:"mb-2 flex gap-2"},il={key:5},ul={key:6,class:"space-y-4 bg-blue-50 p-4 rounded-lg border border-blue-200"},dl={class:"flex items-start gap-3 mb-4"},pl={key:0,class:"text-sm text-blue-800 mb-2"},ml={key:1,class:"text-sm text-blue-800 mb-2"},cl={class:"bg-white/80 rounded-lg p-3 mt-2 mb-2 border border-blue-300"},fl={key:0,class:"text-xs text-blue-800"},xl={key:1,class:"text-xs text-blue-800"},vl={key:0,class:"text-red-500 text-xs mt-1"},gl={class:"flex gap-3 pt-4"},yl=["disabled"],bl=["disabled"],wl={key:0,class:"loading-spinner mr-2"},kl={key:3,class:"space-y-6"},hl={class:"flex gap-4"},$l={class:"flex items-center cursor-pointer"},Cl={class:"flex items-center cursor-pointer"},Tl={class:"flex items-center cursor-pointer"},Al={key:0},Ul={class:"flex gap-2"},Il=["value"],Vl={key:1},jl={key:2},Sl={key:3,class:"space-y-4"},_l={class:"mb-2 flex gap-2"},Ml={key:4,class:"bg-amber-50 p-4 rounded-lg border border-amber-200"},Gl={class:"space-y-4"},Rl={class:"flex gap-3 pt-4"},Kl=["disabled"],Ll={key:0,class:"loading-spinner mr-2"},Re={__name:"AccountForm",props:{account:{type:Object,default:null}},emits:["close","success"],setup(P,{emit:O}){var ue,de,fe,pe,xe,ve,ge,ye,be,we,ke,he;const d=P,$=O,i=Pe(),{showConfirmModal:M,confirmOptions:I,showConfirm:T,handleConfirm:w,handleCancel:v}=Le(),m=ne(()=>!!d.account),G=b(!0),S=b(1),K=b(!1),q=()=>{var o;return(o=d.account)!=null&&o.proxy&&d.account.proxy.host&&d.account.proxy.port?{enabled:!0,type:d.account.proxy.type||"socks5",host:d.account.proxy.host,port:d.account.proxy.port,username:d.account.proxy.username||"",password:d.account.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""}},l=b({platform:((ue=d.account)==null?void 0:ue.platform)||"claude",addType:"oauth",name:((de=d.account)==null?void 0:de.name)||"",description:((fe=d.account)==null?void 0:fe.description)||"",accountType:((pe=d.account)==null?void 0:pe.accountType)||"shared",groupId:"",projectId:((xe=d.account)==null?void 0:xe.projectId)||"",accessToken:"",refreshToken:"",proxy:q(),apiUrl:((ve=d.account)==null?void 0:ve.apiUrl)||"",apiKey:((ge=d.account)==null?void 0:ge.apiKey)||"",priority:((ye=d.account)==null?void 0:ye.priority)||50,supportedModels:((we=(be=d.account)==null?void 0:be.supportedModels)==null?void 0:we.join(`
-`))||"",userAgent:((ke=d.account)==null?void 0:ke.userAgent)||"",rateLimitDuration:((he=d.account)==null?void 0:he.rateLimitDuration)||60}),x=b({name:"",accessToken:"",apiUrl:"",apiKey:""}),r=ne(()=>{var o;return((o=l.value.name)==null?void 0:o.trim())&&l.value.platform});ne(()=>{var o,t,s;return l.value.addType==="manual"?((o=l.value.name)==null?void 0:o.trim())&&((t=l.value.accessToken)==null?void 0:t.trim()):(s=l.value.name)==null?void 0:s.trim()});const L=async()=>{if(x.value.name="",!r.value){(!l.value.name||l.value.name.trim()==="")&&(x.value.name="请填写账户名称");return}if(l.value.accountType==="group"&&(!l.value.groupId||l.value.groupId.trim()==="")){h("请选择一个分组","error");return}l.value.platform==="gemini"&&S.value===1&&l.value.addType==="oauth"&&(!l.value.projectId||l.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。
+import{r as b,aR as ze,o as E,V as Ee,x as n,y as a,z as e,L as y,K as g,al as _e,aY as Ce,aX as me,aq as _,aZ as Oe,C as K,O as $,c as ne,P as f,I as le,a5 as Ae,q as Re,an as X,Q as re,ac as ie,R as $e,u as Y,Y as We,B as Te}from"./vue-vendor-CKToUHZx.js";import{s as h}from"./toast-BvwA7Mwb.js";import{a as V,_ as qe}from"./index-D1PUfDNP.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const he=b(!1),Me=b({title:"",message:"",confirmText:"继续",cancelText:"取消"}),se=b(null);function Le(){return{showConfirmModal:he,confirmOptions:Me,showConfirm:(C,i,M="继续",I="取消")=>new Promise(T=>{Me.value={title:C,message:i,confirmText:M,cancelText:I},se.value=T,he.value=!0}),handleConfirm:()=>{he.value=!1,se.value&&(se.value(!0),se.value=null)},handleCancel:()=>{he.value=!1,se.value&&(se.value(!1),se.value=null)}}}const Pe=ze("accounts",()=>{const P=b([]),O=b([]),d=b([]),C=b(!1),i=b(null),M=b(""),I=b("asc"),T=async()=>{C.value=!0,i.value=null;try{const c=await V.get("/admin/claude-accounts");if(c.success)P.value=c.data||[];else throw new Error(c.message||"获取Claude账户失败")}catch(c){throw i.value=c.message,c}finally{C.value=!1}},w=async()=>{C.value=!0,i.value=null;try{const c=await V.get("/admin/claude-console-accounts");if(c.success)O.value=c.data||[];else throw new Error(c.message||"获取Claude Console账户失败")}catch(c){throw i.value=c.message,c}finally{C.value=!1}},v=async()=>{C.value=!0,i.value=null;try{const c=await V.get("/admin/gemini-accounts");if(c.success)d.value=c.data||[];else throw new Error(c.message||"获取Gemini账户失败")}catch(c){throw i.value=c.message,c}finally{C.value=!1}};return{claudeAccounts:P,claudeConsoleAccounts:O,geminiAccounts:d,loading:C,error:i,sortBy:M,sortOrder:I,fetchClaudeAccounts:T,fetchClaudeConsoleAccounts:w,fetchGeminiAccounts:v,fetchAllAccounts:async()=>{C.value=!0,i.value=null;try{await Promise.all([T(),w(),v()])}catch(c){throw i.value=c.message,c}finally{C.value=!1}},createClaudeAccount:async c=>{C.value=!0,i.value=null;try{const p=await V.post("/admin/claude-accounts",c);if(p.success)return await T(),p.data;throw new Error(p.message||"创建Claude账户失败")}catch(p){throw i.value=p.message,p}finally{C.value=!1}},createClaudeConsoleAccount:async c=>{C.value=!0,i.value=null;try{const p=await V.post("/admin/claude-console-accounts",c);if(p.success)return await w(),p.data;throw new Error(p.message||"创建Claude Console账户失败")}catch(p){throw i.value=p.message,p}finally{C.value=!1}},createGeminiAccount:async c=>{C.value=!0,i.value=null;try{const p=await V.post("/admin/gemini-accounts",c);if(p.success)return await v(),p.data;throw new Error(p.message||"创建Gemini账户失败")}catch(p){throw i.value=p.message,p}finally{C.value=!1}},updateClaudeAccount:async(c,p)=>{C.value=!0,i.value=null;try{const U=await V.put(`/admin/claude-accounts/${c}`,p);if(U.success)return await T(),U;throw new Error(U.message||"更新Claude账户失败")}catch(U){throw i.value=U.message,U}finally{C.value=!1}},updateClaudeConsoleAccount:async(c,p)=>{C.value=!0,i.value=null;try{const U=await V.put(`/admin/claude-console-accounts/${c}`,p);if(U.success)return await w(),U;throw new Error(U.message||"更新Claude Console账户失败")}catch(U){throw i.value=U.message,U}finally{C.value=!1}},updateGeminiAccount:async(c,p)=>{C.value=!0,i.value=null;try{const U=await V.put(`/admin/gemini-accounts/${c}`,p);if(U.success)return await v(),U;throw new Error(U.message||"更新Gemini账户失败")}catch(U){throw i.value=U.message,U}finally{C.value=!1}},toggleAccount:async(c,p)=>{C.value=!0,i.value=null;try{let U;c==="claude"?U=`/admin/claude-accounts/${p}/toggle`:c==="claude-console"?U=`/admin/claude-console-accounts/${p}/toggle`:U=`/admin/gemini-accounts/${p}/toggle`;const F=await V.put(U);if(F.success)return c==="claude"?await T():c==="claude-console"?await w():await v(),F;throw new Error(F.message||"切换状态失败")}catch(U){throw i.value=U.message,U}finally{C.value=!1}},deleteAccount:async(c,p)=>{C.value=!0,i.value=null;try{let U;c==="claude"?U=`/admin/claude-accounts/${p}`:c==="claude-console"?U=`/admin/claude-console-accounts/${p}`:U=`/admin/gemini-accounts/${p}`;const F=await V.delete(U);if(F.success)return c==="claude"?await T():c==="claude-console"?await w():await v(),F;throw new Error(F.message||"删除失败")}catch(U){throw i.value=U.message,U}finally{C.value=!1}},refreshClaudeToken:async c=>{C.value=!0,i.value=null;try{const p=await V.post(`/admin/claude-accounts/${c}/refresh`);if(p.success)return await T(),p;throw new Error(p.message||"Token刷新失败")}catch(p){throw i.value=p.message,p}finally{C.value=!1}},generateClaudeAuthUrl:async c=>{try{const p=await V.post("/admin/claude-accounts/generate-auth-url",c);if(p.success)return p.data;throw new Error(p.message||"生成授权URL失败")}catch(p){throw i.value=p.message,p}},exchangeClaudeCode:async c=>{try{const p=await V.post("/admin/claude-accounts/exchange-code",c);if(p.success)return p.data;throw new Error(p.message||"交换授权码失败")}catch(p){throw i.value=p.message,p}},generateGeminiAuthUrl:async c=>{try{const p=await V.post("/admin/gemini-accounts/generate-auth-url",c);if(p.success)return p.data;throw new Error(p.message||"生成授权URL失败")}catch(p){throw i.value=p.message,p}},exchangeGeminiCode:async c=>{try{const p=await V.post("/admin/gemini-accounts/exchange-code",c);if(p.success)return p.data;throw new Error(p.message||"交换授权码失败")}catch(p){throw i.value=p.message,p}},sortAccounts:c=>{M.value===c?I.value=I.value==="asc"?"desc":"asc":(M.value=c,I.value="asc")},reset:()=>{P.value=[],O.value=[],d.value=[],C.value=!1,i.value=null,M.value="",I.value="asc"}}}),Be={class:"space-y-4"},Fe={class:"flex items-center justify-between"},Ne={class:"flex items-center cursor-pointer"},He={key:0,class:"bg-gray-50 p-4 rounded-lg border border-gray-200 space-y-4"},Je={class:"grid grid-cols-2 gap-4"},Ye={class:"space-y-4"},Qe={class:"flex items-center"},Xe={key:0,class:"grid grid-cols-2 gap-4"},Ze={class:"relative"},et=["type"],Ge={__name:"ProxyConfig",props:{modelValue:{type:Object,default:()=>({enabled:!1,type:"socks5",host:"",port:"",username:"",password:""})}},emits:["update:modelValue"],setup(P,{emit:O}){const d=P,C=O,i=b({...d.modelValue}),M=b(!!(i.value.username||i.value.password)),I=b(!1);E(()=>d.modelValue,v=>{JSON.stringify(v)!==JSON.stringify(i.value)&&(i.value={...v},M.value=!!(v.username||v.password))},{deep:!0}),E(()=>i.value.enabled,v=>{w()}),E(()=>i.value.type,v=>{w()}),E(()=>i.value.host,v=>{w()}),E(()=>i.value.port,v=>{w()}),E(()=>i.value.username,v=>{w()}),E(()=>i.value.password,v=>{w()}),E(M,v=>{v||(i.value.username="",i.value.password="",w())});let T=null;function w(){T&&clearTimeout(T),T=setTimeout(()=>{const v={...i.value};M.value||(v.username="",v.password=""),C("update:modelValue",v)},100)}return Ee(()=>{T&&clearTimeout(T)}),(v,m)=>(a(),n("div",Be,[e("div",Fe,[m[9]||(m[9]=e("h4",{class:"text-sm font-semibold text-gray-700"}," 代理设置 (可选) ",-1)),e("label",Ne,[g(e("input",{"onUpdate:modelValue":m[0]||(m[0]=G=>i.value.enabled=G),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[_e,i.value.enabled]]),m[8]||(m[8]=e("span",{class:"ml-2 text-sm text-gray-700"},"启用代理",-1))])]),i.value.enabled?(a(),n("div",He,[m[17]||(m[17]=Ce('
配置代理以访问受限的网络资源。支持 SOCKS5 和 HTTP 代理。
请确保代理服务器稳定可用,否则会影响账户的正常使用。
',1)),e("div",null,[m[11]||(m[11]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"代理类型",-1)),g(e("select",{"onUpdate:modelValue":m[1]||(m[1]=G=>i.value.type=G),class:"form-input w-full"},m[10]||(m[10]=[e("option",{value:"socks5"}," SOCKS5 ",-1),e("option",{value:"http"}," HTTP ",-1),e("option",{value:"https"}," HTTPS ",-1)]),512),[[me,i.value.type]])]),e("div",Je,[e("div",null,[m[12]||(m[12]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"主机地址",-1)),g(e("input",{"onUpdate:modelValue":m[2]||(m[2]=G=>i.value.host=G),type:"text",placeholder:"例如: 192.168.1.100",class:"form-input w-full"},null,512),[[_,i.value.host]])]),e("div",null,[m[13]||(m[13]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"端口",-1)),g(e("input",{"onUpdate:modelValue":m[3]||(m[3]=G=>i.value.port=G),type:"number",placeholder:"例如: 1080",class:"form-input w-full"},null,512),[[_,i.value.port]])])]),e("div",Ye,[e("div",Qe,[g(e("input",{id:"proxyAuth","onUpdate:modelValue":m[4]||(m[4]=G=>M.value=G),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[_e,M.value]]),m[14]||(m[14]=e("label",{for:"proxyAuth",class:"ml-2 text-sm text-gray-700 cursor-pointer"}," 需要身份验证 ",-1))]),M.value?(a(),n("div",Xe,[e("div",null,[m[15]||(m[15]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"用户名",-1)),g(e("input",{"onUpdate:modelValue":m[5]||(m[5]=G=>i.value.username=G),type:"text",placeholder:"代理用户名",class:"form-input w-full"},null,512),[[_,i.value.username]])]),e("div",null,[m[16]||(m[16]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"密码",-1)),e("div",Ze,[g(e("input",{"onUpdate:modelValue":m[6]||(m[6]=G=>i.value.password=G),type:I.value?"text":"password",placeholder:"代理密码",class:"form-input w-full pr-10"},null,8,et),[[Oe,i.value.password]]),e("button",{type:"button",class:"absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600",onClick:m[7]||(m[7]=G=>I.value=!I.value)},[e("i",{class:K(I.value?"fas fa-eye-slash":"fas fa-eye")},null,2)])])])])):y("",!0)]),m[18]||(m[18]=e("div",{class:"bg-blue-50 p-3 rounded-lg border border-blue-200"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),e("strong",null,"提示:"),$("代理设置将用于所有与此账户相关的API请求。请确保代理服务器支持HTTPS流量转发。 ")])],-1))])):y("",!0)]))}},tt={class:"space-y-6"},st={key:0},lt={class:"bg-blue-50 p-6 rounded-lg border border-blue-200"},ot={class:"flex items-start gap-4"},at={class:"flex-1"},nt={class:"space-y-4"},rt={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},it={class:"flex items-start gap-3"},ut={class:"flex-1"},dt=["disabled"],pt={key:0,class:"fas fa-link mr-2"},mt={key:1,class:"loading-spinner mr-2"},ct={key:1,class:"space-y-3"},ft={class:"flex items-center gap-2"},xt=["value"],vt={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},gt={class:"flex items-start gap-3"},yt={class:"flex-1"},bt={class:"space-y-3"},wt={key:1},kt={class:"bg-green-50 p-6 rounded-lg border border-green-200"},ht={class:"flex items-start gap-4"},$t={class:"flex-1"},Ct={class:"space-y-4"},Tt={class:"bg-white/80 rounded-lg p-4 border border-green-300"},At={class:"flex items-start gap-3"},Ut={class:"flex-1"},It=["disabled"],Vt={key:0,class:"fas fa-link mr-2"},jt={key:1,class:"loading-spinner mr-2"},St={key:1,class:"space-y-3"},_t={class:"flex items-center gap-2"},Mt=["value"],Gt={class:"bg-white/80 rounded-lg p-4 border border-green-300"},Kt={class:"flex items-start gap-3"},Rt={class:"flex-1"},Lt={class:"space-y-3"},Pt={class:"flex gap-3 pt-4"},Dt=["disabled"],zt={key:0,class:"loading-spinner mr-2"},Et={__name:"OAuthFlow",props:{platform:{type:String,required:!0},proxy:{type:Object,default:null}},emits:["success","back"],setup(P,{emit:O}){const d=P,C=O,i=Pe(),M=b(!1),I=b(!1),T=b(""),w=b(""),v=b(!1),m=b(""),G=ne(()=>T.value&&w.value.trim());E(w,x=>{if(!x||typeof x!="string")return;const r=x.trim();if(!r)return;if(r.startsWith("http://")||r.startsWith("https://"))if(r.startsWith("http://localhost:45462"))try{const W=new URL(r).searchParams.get("code");W?(w.value=W,h("成功提取授权码!","success"),console.log("Successfully extracted authorization code from URL")):h("URL 中未找到授权码参数,请检查链接是否正确","error")}catch(B){console.error("Failed to parse URL:",B),h("链接格式错误,请检查是否为完整的 URL","error")}else if(d.platform==="gemini")try{const W=new URL(r).searchParams.get("code");W&&(w.value=W,h("成功提取授权码!","success"))}catch{}else h("请粘贴以 http://localhost:45462 开头的链接","error")});const S=async()=>{var x;M.value=!0;try{const r=(x=d.proxy)!=null&&x.enabled?{proxy:{type:d.proxy.type,host:d.proxy.host,port:parseInt(d.proxy.port),username:d.proxy.username||null,password:d.proxy.password||null}}:{};if(d.platform==="claude"){const L=await i.generateClaudeAuthUrl(r);T.value=L.authUrl,m.value=L.sessionId}else if(d.platform==="gemini"){const L=await i.generateGeminiAuthUrl(r);T.value=L.authUrl,m.value=L.sessionId}}catch(r){h(r.message||"生成授权链接失败","error")}finally{M.value=!1}},R=()=>{T.value="",w.value="",S()},q=async()=>{try{await navigator.clipboard.writeText(T.value),v.value=!0,h("链接已复制","success"),setTimeout(()=>{v.value=!1},2e3)}catch{const r=document.createElement("input");r.value=T.value,document.body.appendChild(r),r.select(),document.execCommand("copy"),document.body.removeChild(r),v.value=!0,h("链接已复制","success"),setTimeout(()=>{v.value=!1},2e3)}},l=async()=>{var x;if(G.value){I.value=!0;try{let r={};d.platform==="claude"?r={sessionId:m.value,callbackUrl:w.value.trim()}:d.platform==="gemini"&&(r={code:w.value.trim(),sessionId:m.value}),(x=d.proxy)!=null&&x.enabled&&(r.proxy={type:d.proxy.type,host:d.proxy.host,port:parseInt(d.proxy.port),username:d.proxy.username||null,password:d.proxy.password||null});let L;d.platform==="claude"?L=await i.exchangeClaudeCode(r):d.platform==="gemini"&&(L=await i.exchangeGeminiCode(r)),C("success",L)}catch(r){h(r.message||"授权失败,请检查授权码是否正确","error")}finally{I.value=!1}}};return(x,r)=>(a(),n("div",tt,[P.platform==="claude"?(a(),n("div",st,[e("div",lt,[e("div",ot,[r[14]||(r[14]=e("div",{class:"w-10 h-10 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-link text-white"})],-1)),e("div",at,[r[12]||(r[12]=e("h4",{class:"font-semibold text-blue-900 mb-3"}," Claude 账户授权 ",-1)),r[13]||(r[13]=e("p",{class:"text-sm text-blue-800 mb-4"}," 请按照以下步骤完成 Claude 账户的授权: ",-1)),e("div",nt,[e("div",rt,[e("div",it,[r[5]||(r[5]=e("div",{class:"w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 1 ",-1)),e("div",ut,[r[4]||(r[4]=e("p",{class:"font-medium text-blue-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(a(),n("div",ct,[e("div",ft,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,xt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:q},[e("i",{class:K(v.value?"fas fa-check text-green-500":"fas fa-copy")},null,2)])]),e("button",{class:"text-xs text-blue-600 hover:text-blue-700",onClick:R},r[3]||(r[3]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),$("重新生成 ",-1)]))])):(a(),n("button",{key:0,disabled:M.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:S},[M.value?(a(),n("div",mt)):(a(),n("i",pt)),$(" "+f(M.value?"生成中...":"生成授权链接"),1)],8,dt))])])]),r[11]||(r[11]=Ce(' 2
在浏览器中打开链接并完成授权
请在新标签页中打开授权链接,登录您的 Claude 账户并授权。
注意:如果您设置了代理,请确保浏览器也使用相同的代理访问授权页面。
',1)),e("div",vt,[e("div",gt,[r[10]||(r[10]=e("div",{class:"w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 3 ",-1)),e("div",yt,[r[8]||(r[8]=e("p",{class:"font-medium text-blue-900 mb-2"}," 输入 Authorization Code ",-1)),r[9]||(r[9]=e("p",{class:"text-sm text-blue-700 mb-3"},[$(" 授权完成后,页面会显示一个 "),e("strong",null,"Authorization Code"),$(",请将其复制并粘贴到下方输入框: ")],-1)),e("div",bt,[e("div",null,[r[6]||(r[6]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[e("i",{class:"fas fa-key text-blue-500 mr-2"}),$("Authorization Code ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[0]||(r[0]=L=>w.value=L),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴从Claude页面获取的Authorization Code..."},null,512),[[_,w.value]])]),r[7]||(r[7]=e("p",{class:"text-xs text-gray-500 mt-2"},[e("i",{class:"fas fa-info-circle mr-1"}),$(" 请粘贴从Claude页面复制的Authorization Code ")],-1))])])])])])])])])])):P.platform==="gemini"?(a(),n("div",wt,[e("div",kt,[e("div",ht,[r[26]||(r[26]=e("div",{class:"w-10 h-10 bg-green-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-robot text-white"})],-1)),e("div",$t,[r[24]||(r[24]=e("h4",{class:"font-semibold text-green-900 mb-3"}," Gemini 账户授权 ",-1)),r[25]||(r[25]=e("p",{class:"text-sm text-green-800 mb-4"}," 请按照以下步骤完成 Gemini 账户的授权: ",-1)),e("div",Ct,[e("div",Tt,[e("div",At,[r[17]||(r[17]=e("div",{class:"w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 1 ",-1)),e("div",Ut,[r[16]||(r[16]=e("p",{class:"font-medium text-green-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(a(),n("div",St,[e("div",_t,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,Mt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:q},[e("i",{class:K(v.value?"fas fa-check text-green-500":"fas fa-copy")},null,2)])]),e("button",{class:"text-xs text-green-600 hover:text-green-700",onClick:R},r[15]||(r[15]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),$("重新生成 ",-1)]))])):(a(),n("button",{key:0,disabled:M.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:S},[M.value?(a(),n("div",jt)):(a(),n("i",Vt)),$(" "+f(M.value?"生成中...":"生成授权链接"),1)],8,It))])])]),r[23]||(r[23]=Ce(' 2
在浏览器中打开链接并完成授权
请在新标签页中打开授权链接,登录您的 Gemini 账户并授权。
注意:如果您设置了代理,请确保浏览器也使用相同的代理访问授权页面。
',1)),e("div",Gt,[e("div",Kt,[r[22]||(r[22]=e("div",{class:"w-6 h-6 bg-green-600 text-white rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0"}," 3 ",-1)),e("div",Rt,[r[20]||(r[20]=e("p",{class:"font-medium text-green-900 mb-2"}," 输入 Authorization Code ",-1)),r[21]||(r[21]=e("p",{class:"text-sm text-green-700 mb-3"}," 授权完成后,页面会显示一个 Authorization Code,请将其复制并粘贴到下方输入框: ",-1)),e("div",Lt,[e("div",null,[r[18]||(r[18]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},[e("i",{class:"fas fa-key text-green-500 mr-2"}),$("Authorization Code ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[1]||(r[1]=L=>w.value=L),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴从Gemini页面获取的Authorization Code..."},null,512),[[_,w.value]])]),r[19]||(r[19]=e("div",{class:"mt-2 space-y-1"},[e("p",{class:"text-xs text-gray-600"},[e("i",{class:"fas fa-check-circle text-green-500 mr-1"}),$(" 请粘贴从Gemini页面复制的Authorization Code ")])],-1))])])])])])])])])])):y("",!0),e("div",Pt,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:r[2]||(r[2]=L=>x.$emit("back"))}," 上一步 "),e("button",{type:"button",disabled:!G.value||I.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:l},[I.value?(a(),n("div",zt)):y("",!0),$(" "+f(I.value?"验证中...":"完成授权"),1)],8,Dt)])]))}},Ot={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Wt={class:"modal-content w-full max-w-md p-6 mx-auto"},qt={class:"flex items-start gap-4 mb-6"},Bt={class:"flex-1"},Ft={class:"text-lg font-bold text-gray-900 mb-2"},Nt={class:"text-gray-600 text-sm leading-relaxed whitespace-pre-line"},Ht={class:"flex gap-3"},De={__name:"ConfirmModal",props:{show:{type:Boolean,required:!0},title:{type:String,default:""},message:{type:String,default:""},confirmText:{type:String,default:"继续"},cancelText:{type:String,default:"取消"}},emits:["confirm","cancel"],setup(P){return(O,d)=>(a(),le(Ae,{to:"body"},[P.show?(a(),n("div",Ot,[e("div",Wt,[e("div",qt,[d[2]||(d[2]=e("div",{class:"w-12 h-12 bg-gradient-to-br from-yellow-400 to-yellow-500 rounded-full flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-exclamation text-white text-xl"})],-1)),e("div",Bt,[e("h3",Ft,f(P.title),1),e("p",Nt,f(P.message),1)])]),e("div",Ht,[e("button",{class:"flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-xl font-medium hover:bg-gray-200 transition-colors",onClick:d[0]||(d[0]=C=>O.$emit("cancel"))},f(P.cancelText),1),e("button",{class:"flex-1 px-4 py-2.5 bg-gradient-to-r from-yellow-500 to-orange-500 text-white rounded-xl font-medium hover:from-yellow-600 hover:to-orange-600 transition-colors shadow-sm",onClick:d[1]||(d[1]=C=>O.$emit("confirm"))},f(P.confirmText),1)])])])):y("",!0)]))}},Jt={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},Yt={class:"modal-content w-full max-w-4xl p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Qt={class:"flex items-center justify-between mb-4 sm:mb-6"},Xt={class:"mb-6"},Zt={key:0,class:"mb-6 p-4 bg-blue-50 rounded-lg border border-blue-200"},es={class:"space-y-4"},ts={class:"flex gap-4"},ss={class:"flex items-center cursor-pointer"},ls={class:"flex items-center cursor-pointer"},os={class:"flex gap-3"},as=["disabled"],ns={key:0,class:"loading-spinner mr-2"},rs={class:"space-y-4"},is={key:0,class:"text-center py-8"},us={key:1,class:"text-center py-8 bg-gray-50 rounded-lg"},ds={key:2,class:"grid gap-4 grid-cols-1 md:grid-cols-2"},ps={class:"flex items-start justify-between mb-3"},ms={class:"flex-1"},cs={class:"font-semibold text-gray-900"},fs={class:"text-sm text-gray-500 mt-1"},xs={class:"flex items-center gap-2 ml-4"},vs={class:"flex items-center justify-between text-sm text-gray-600"},gs={class:"flex items-center gap-4"},ys={class:"flex items-center gap-2"},bs=["onClick"],ws=["disabled","onClick"],ks={key:1,class:"fixed inset-0 modal z-60 flex items-center justify-center p-3 sm:p-4"},hs={class:"modal-content w-full max-w-lg p-4 sm:p-6"},$s={class:"space-y-4"},Cs={class:"px-3 py-2 bg-gray-100 rounded-lg text-sm text-gray-600"},Ts={class:"flex gap-3 pt-4"},As=["disabled"],Us={key:0,class:"loading-spinner mr-2"},Is={__name:"GroupManagementModal",emits:["close","refresh"],setup(P,{emit:O}){const d=O,C=b(!0),i=b(!1),M=b([]),I=b(!1),T=b(!1),w=b({name:"",platform:"claude",description:""}),v=b(!1),m=b(!1),G=b(null),S=b({name:"",platform:"",description:""}),R=j=>j?new Date(j).toLocaleDateString("zh-CN"):"-",q=async()=>{i.value=!0;try{const j=await V.get("/admin/account-groups");M.value=j.data||[]}catch{h("加载分组列表失败","error")}finally{i.value=!1}},l=async()=>{var j,u;if(!w.value.name||!w.value.platform){h("请填写必填项","error");return}T.value=!0;try{await V.post("/admin/account-groups",{name:w.value.name,platform:w.value.platform,description:w.value.description}),h("分组创建成功","success"),x(),await q(),d("refresh")}catch(A){h(((u=(j=A.response)==null?void 0:j.data)==null?void 0:u.error)||"创建分组失败","error")}finally{T.value=!1}},x=()=>{I.value=!1,w.value={name:"",platform:"claude",description:""}},r=j=>{G.value=j,S.value={name:j.name,platform:j.platform,description:j.description||""},v.value=!0},L=async()=>{var j,u;if(!S.value.name){h("请填写分组名称","error");return}m.value=!0;try{await V.put(`/admin/account-groups/${G.value.id}`,{name:S.value.name,description:S.value.description}),h("分组更新成功","success"),B(),await q(),d("refresh")}catch(A){h(((u=(j=A.response)==null?void 0:j.data)==null?void 0:u.error)||"更新分组失败","error")}finally{m.value=!1}},B=()=>{v.value=!1,G.value=null,S.value={name:"",platform:"",description:""}},W=async j=>{var u,A;if(j.memberCount>0){h("分组内还有成员,无法删除","error");return}if(confirm(`确定要删除分组 "${j.name}" 吗?`))try{await V.delete(`/admin/account-groups/${j.id}`),h("分组删除成功","success"),await q(),d("refresh")}catch(Z){h(((A=(u=Z.response)==null?void 0:u.data)==null?void 0:A.error)||"删除分组失败","error")}};return Re(()=>{q()}),(j,u)=>(a(),le(Ae,{to:"body"},[C.value?(a(),n("div",Jt,[e("div",Yt,[e("div",Qt,[u[9]||(u[9]=e("div",{class:"flex items-center gap-2 sm:gap-3"},[e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-purple-500 to-purple-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-layer-group text-white text-sm sm:text-base"})]),e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 账户分组管理 ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:u[0]||(u[0]=A=>j.$emit("close"))},u[8]||(u[8]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),e("div",Xt,[e("button",{class:"btn btn-primary px-4 py-2",onClick:u[1]||(u[1]=A=>I.value=!0)},u[10]||(u[10]=[e("i",{class:"fas fa-plus mr-2"},null,-1),$(" 创建新分组 ",-1)]))]),I.value?(a(),n("div",Zt,[u[16]||(u[16]=e("h4",{class:"text-lg font-semibold text-gray-900 mb-4"},"创建新分组",-1)),e("div",es,[e("div",null,[u[11]||(u[11]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"分组名称 *",-1)),g(e("input",{"onUpdate:modelValue":u[2]||(u[2]=A=>w.value.name=A),type:"text",class:"form-input w-full",placeholder:"输入分组名称"},null,512),[[_,w.value.name]])]),e("div",null,[u[14]||(u[14]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"平台类型 *",-1)),e("div",ts,[e("label",ss,[g(e("input",{"onUpdate:modelValue":u[3]||(u[3]=A=>w.value.platform=A),type:"radio",value:"claude",class:"mr-2"},null,512),[[X,w.value.platform]]),u[12]||(u[12]=e("span",{class:"text-sm text-gray-700"},"Claude",-1))]),e("label",ls,[g(e("input",{"onUpdate:modelValue":u[4]||(u[4]=A=>w.value.platform=A),type:"radio",value:"gemini",class:"mr-2"},null,512),[[X,w.value.platform]]),u[13]||(u[13]=e("span",{class:"text-sm text-gray-700"},"Gemini",-1))])])]),e("div",null,[u[15]||(u[15]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":u[5]||(u[5]=A=>w.value.description=A),rows:"2",class:"form-input w-full resize-none",placeholder:"分组描述..."},null,512),[[_,w.value.description]])]),e("div",os,[e("button",{class:"btn btn-primary px-4 py-2",disabled:!w.value.name||!w.value.platform||T.value,onClick:l},[T.value?(a(),n("div",ns)):y("",!0),$(" "+f(T.value?"创建中...":"创建"),1)],8,as),e("button",{class:"btn btn-secondary px-4 py-2",onClick:x}," 取消 ")])])])):y("",!0),e("div",rs,[i.value?(a(),n("div",is,u[17]||(u[17]=[e("div",{class:"loading-spinner-lg mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"},"加载中...",-1)]))):M.value.length===0?(a(),n("div",us,u[18]||(u[18]=[e("i",{class:"fas fa-layer-group text-4xl text-gray-300 mb-4"},null,-1),e("p",{class:"text-gray-500"},"暂无分组",-1)]))):(a(),n("div",ds,[(a(!0),n(re,null,ie(M.value,A=>(a(),n("div",{key:A.id,class:"bg-white rounded-lg border p-4 hover:shadow-md transition-shadow"},[e("div",ps,[e("div",ms,[e("h4",cs,f(A.name),1),e("p",fs,f(A.description||"暂无描述"),1)]),e("div",xs,[e("span",{class:K(["px-2 py-1 text-xs font-medium rounded-full",A.platform==="claude"?"bg-purple-100 text-purple-700":"bg-blue-100 text-blue-700"])},f(A.platform==="claude"?"Claude":"Gemini"),3)])]),e("div",vs,[e("div",gs,[e("span",null,[u[19]||(u[19]=e("i",{class:"fas fa-users mr-1"},null,-1)),$(" "+f(A.memberCount||0)+" 个成员 ",1)]),e("span",null,[u[20]||(u[20]=e("i",{class:"fas fa-clock mr-1"},null,-1)),$(" "+f(R(A.createdAt)),1)])]),e("div",ys,[e("button",{class:"text-blue-600 hover:text-blue-800 transition-colors",title:"编辑",onClick:Z=>r(A)},u[21]||(u[21]=[e("i",{class:"fas fa-edit"},null,-1)]),8,bs),e("button",{class:"text-red-600 hover:text-red-800 transition-colors",title:"删除",disabled:A.memberCount>0,onClick:Z=>W(A)},u[22]||(u[22]=[e("i",{class:"fas fa-trash"},null,-1)]),8,ws)])])]))),128))]))])])])):y("",!0),v.value?(a(),n("div",ks,[e("div",hs,[e("div",{class:"flex items-center justify-between mb-4"},[u[24]||(u[24]=e("h3",{class:"text-lg font-bold text-gray-900"},"编辑分组",-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:B},u[23]||(u[23]=[e("i",{class:"fas fa-times"},null,-1)]))]),e("div",$s,[e("div",null,[u[25]||(u[25]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"分组名称 *",-1)),g(e("input",{"onUpdate:modelValue":u[6]||(u[6]=A=>S.value.name=A),type:"text",class:"form-input w-full",placeholder:"输入分组名称"},null,512),[[_,S.value.name]])]),e("div",null,[u[27]||(u[27]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"平台类型",-1)),e("div",Cs,[$(f(S.value.platform==="claude"?"Claude":"Gemini")+" ",1),u[26]||(u[26]=e("span",{class:"text-xs text-gray-500 ml-2"},"(不可修改)",-1))])]),e("div",null,[u[28]||(u[28]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":u[7]||(u[7]=A=>S.value.description=A),rows:"2",class:"form-input w-full resize-none",placeholder:"分组描述..."},null,512),[[_,S.value.description]])]),e("div",Ts,[e("button",{class:"btn btn-primary px-4 py-2 flex-1",disabled:!S.value.name||m.value,onClick:L},[m.value?(a(),n("div",Us)):y("",!0),$(" "+f(m.value?"更新中...":"更新"),1)],8,As),e("button",{class:"btn btn-secondary px-4 py-2 flex-1",onClick:B}," 取消 ")])])])])):y("",!0)]))}},Vs={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},js={class:"modal-content w-full max-w-2xl p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Ss={class:"flex items-center justify-between mb-4 sm:mb-6"},_s={class:"flex items-center gap-2 sm:gap-3"},Ms={class:"text-lg sm:text-xl font-bold text-gray-900"},Gs={key:0,class:"flex items-center justify-center mb-4 sm:mb-8"},Ks={class:"flex items-center space-x-2 sm:space-x-4"},Rs={class:"flex items-center"},Ls={class:"flex items-center"},Ps={key:1},Ds={class:"space-y-6"},zs={key:0},Es={class:"flex gap-4"},Os={class:"flex items-center cursor-pointer"},Ws={class:"flex items-center cursor-pointer"},qs={class:"flex items-center cursor-pointer"},Bs={key:1},Fs={class:"flex gap-4"},Ns={class:"flex items-center cursor-pointer"},Hs={class:"flex items-center cursor-pointer"},Js={key:0,class:"text-red-500 text-xs mt-1"},Ys={class:"flex gap-4"},Qs={class:"flex items-center cursor-pointer"},Xs={class:"flex items-center cursor-pointer"},Zs={class:"flex items-center cursor-pointer"},el={key:2},tl={class:"flex gap-2"},sl=["value"],ll={key:3},ol={key:4,class:"space-y-4"},al={key:0,class:"text-red-500 text-xs mt-1"},nl={key:0,class:"text-red-500 text-xs mt-1"},rl={class:"mb-2 flex gap-2"},il={key:5},ul={key:6,class:"space-y-4 bg-blue-50 p-4 rounded-lg border border-blue-200"},dl={class:"flex items-start gap-3 mb-4"},pl={key:0,class:"text-sm text-blue-800 mb-2"},ml={key:1,class:"text-sm text-blue-800 mb-2"},cl={class:"bg-white/80 rounded-lg p-3 mt-2 mb-2 border border-blue-300"},fl={key:0,class:"text-xs text-blue-800"},xl={key:1,class:"text-xs text-blue-800"},vl={key:0,class:"text-red-500 text-xs mt-1"},gl={class:"flex gap-3 pt-4"},yl=["disabled"],bl=["disabled"],wl={key:0,class:"loading-spinner mr-2"},kl={key:3,class:"space-y-6"},hl={class:"flex gap-4"},$l={class:"flex items-center cursor-pointer"},Cl={class:"flex items-center cursor-pointer"},Tl={class:"flex items-center cursor-pointer"},Al={key:0},Ul={class:"flex gap-2"},Il=["value"],Vl={key:1},jl={key:2},Sl={key:3,class:"space-y-4"},_l={class:"mb-2 flex gap-2"},Ml={key:4,class:"bg-amber-50 p-4 rounded-lg border border-amber-200"},Gl={class:"space-y-4"},Kl={class:"flex gap-3 pt-4"},Rl=["disabled"],Ll={key:0,class:"loading-spinner mr-2"},Ke={__name:"AccountForm",props:{account:{type:Object,default:null}},emits:["close","success"],setup(P,{emit:O}){var ue,de,ce,pe,fe,xe,ve,ge,ye,be,we,ke;const d=P,C=O,i=Pe(),{showConfirmModal:M,confirmOptions:I,showConfirm:T,handleConfirm:w,handleCancel:v}=Le(),m=ne(()=>!!d.account),G=b(!0),S=b(1),R=b(!1),q=()=>{var o;return(o=d.account)!=null&&o.proxy&&d.account.proxy.host&&d.account.proxy.port?{enabled:!0,type:d.account.proxy.type||"socks5",host:d.account.proxy.host,port:d.account.proxy.port,username:d.account.proxy.username||"",password:d.account.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""}},l=b({platform:((ue=d.account)==null?void 0:ue.platform)||"claude",addType:"oauth",name:((de=d.account)==null?void 0:de.name)||"",description:((ce=d.account)==null?void 0:ce.description)||"",accountType:((pe=d.account)==null?void 0:pe.accountType)||"shared",groupId:"",projectId:((fe=d.account)==null?void 0:fe.projectId)||"",accessToken:"",refreshToken:"",proxy:q(),apiUrl:((xe=d.account)==null?void 0:xe.apiUrl)||"",apiKey:((ve=d.account)==null?void 0:ve.apiKey)||"",priority:((ge=d.account)==null?void 0:ge.priority)||50,supportedModels:((be=(ye=d.account)==null?void 0:ye.supportedModels)==null?void 0:be.join(`
+`))||"",userAgent:((we=d.account)==null?void 0:we.userAgent)||"",rateLimitDuration:((ke=d.account)==null?void 0:ke.rateLimitDuration)||60}),x=b({name:"",accessToken:"",apiUrl:"",apiKey:""}),r=ne(()=>{var o;return((o=l.value.name)==null?void 0:o.trim())&&l.value.platform});ne(()=>{var o,t,s;return l.value.addType==="manual"?((o=l.value.name)==null?void 0:o.trim())&&((t=l.value.accessToken)==null?void 0:t.trim()):(s=l.value.name)==null?void 0:s.trim()});const L=async()=>{if(x.value.name="",!r.value){(!l.value.name||l.value.name.trim()==="")&&(x.value.name="请填写账户名称");return}if(l.value.accountType==="group"&&(!l.value.groupId||l.value.groupId.trim()==="")){h("请选择一个分组","error");return}l.value.platform==="gemini"&&S.value===1&&l.value.addType==="oauth"&&(!l.value.projectId||l.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。
如果您的Google账号绑定了Google Cloud或被识别为Workspace账号,需要提供项目编号。
-如果您使用的是普通个人账号,可以继续不填写。`,"继续","返回填写")||(S.value=2)},F=async o=>{K.value=!0;try{const t={name:l.value.name,description:l.value.description,accountType:l.value.accountType,groupId:l.value.accountType==="group"?l.value.groupId:void 0,proxy:l.value.proxy.enabled?{type:l.value.proxy.type,host:l.value.proxy.host,port:parseInt(l.value.proxy.port),username:l.value.proxy.username||null,password:l.value.proxy.password||null}:null};l.value.platform==="claude"?(t.claudeAiOauth=o.claudeAiOauth||o,t.priority=l.value.priority||50):l.value.platform==="gemini"&&(t.geminiOauth=o.tokens||o,l.value.projectId&&(t.projectId=l.value.projectId));let s;l.value.platform==="claude"?s=await i.createClaudeAccount(t):s=await i.createGeminiAccount(t),$("success",s)}catch(t){h(t.message||"账户创建失败","error")}finally{K.value=!1}},W=async()=>{x.value.name="",x.value.accessToken="",x.value.apiUrl="",x.value.apiKey="";let o=!1;if((!l.value.name||l.value.name.trim()==="")&&(x.value.name="请填写账户名称",o=!0),l.value.platform==="claude-console"?((!l.value.apiUrl||l.value.apiUrl.trim()==="")&&(x.value.apiUrl="请填写 API URL",o=!0),(!l.value.apiKey||l.value.apiKey.trim()==="")&&(x.value.apiKey="请填写 API Key",o=!0)):l.value.addType==="manual"&&(!l.value.accessToken||l.value.accessToken.trim()==="")&&(x.value.accessToken="请填写 Access Token",o=!0),l.value.accountType==="group"&&(!l.value.groupId||l.value.groupId.trim()==="")&&(h("请选择一个分组","error"),o=!0),!o){K.value=!0;try{const t={name:l.value.name,description:l.value.description,accountType:l.value.accountType,groupId:l.value.accountType==="group"?l.value.groupId:void 0,proxy:l.value.proxy.enabled?{type:l.value.proxy.type,host:l.value.proxy.host,port:parseInt(l.value.proxy.port),username:l.value.proxy.username||null,password:l.value.proxy.password||null}:null};if(l.value.platform==="claude"){const k=l.value.refreshToken?6e5:31536e6;t.claudeAiOauth={accessToken:l.value.accessToken,refreshToken:l.value.refreshToken||"",expiresAt:Date.now()+k,scopes:["user:inference"]},t.priority=l.value.priority||50}else if(l.value.platform==="gemini"){const k=l.value.refreshToken?6e5:31536e6;t.geminiOauth={access_token:l.value.accessToken,refresh_token:l.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+k},l.value.projectId&&(t.projectId=l.value.projectId)}else l.value.platform==="claude-console"&&(t.apiUrl=l.value.apiUrl,t.apiKey=l.value.apiKey,t.priority=l.value.priority||50,t.supportedModels=l.value.supportedModels?l.value.supportedModels.split(`
-`).filter(k=>k.trim()):[],t.userAgent=l.value.userAgent||null,t.rateLimitDuration=l.value.rateLimitDuration||60);let s;l.value.platform==="claude"?s=await i.createClaudeAccount(t):l.value.platform==="claude-console"?s=await i.createClaudeConsoleAccount(t):s=await i.createGeminiAccount(t),$("success",s)}catch(t){h(t.message||"账户创建失败","error")}finally{K.value=!1}}},j=async()=>{if(x.value.name="",!l.value.name||l.value.name.trim()===""){x.value.name="请填写账户名称";return}if(l.value.accountType==="group"&&(!l.value.groupId||l.value.groupId.trim()==="")){h("请选择一个分组","error");return}if(!(l.value.platform==="gemini"&&(!l.value.projectId||l.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。
+如果您使用的是普通个人账号,可以继续不填写。`,"继续","返回填写")||(S.value=2)},B=async o=>{R.value=!0;try{const t={name:l.value.name,description:l.value.description,accountType:l.value.accountType,groupId:l.value.accountType==="group"?l.value.groupId:void 0,proxy:l.value.proxy.enabled?{type:l.value.proxy.type,host:l.value.proxy.host,port:parseInt(l.value.proxy.port),username:l.value.proxy.username||null,password:l.value.proxy.password||null}:null};l.value.platform==="claude"?(t.claudeAiOauth=o.claudeAiOauth||o,t.priority=l.value.priority||50):l.value.platform==="gemini"&&(t.geminiOauth=o.tokens||o,l.value.projectId&&(t.projectId=l.value.projectId));let s;l.value.platform==="claude"?s=await i.createClaudeAccount(t):s=await i.createGeminiAccount(t),C("success",s)}catch(t){h(t.message||"账户创建失败","error")}finally{R.value=!1}},W=async()=>{x.value.name="",x.value.accessToken="",x.value.apiUrl="",x.value.apiKey="";let o=!1;if((!l.value.name||l.value.name.trim()==="")&&(x.value.name="请填写账户名称",o=!0),l.value.platform==="claude-console"?((!l.value.apiUrl||l.value.apiUrl.trim()==="")&&(x.value.apiUrl="请填写 API URL",o=!0),(!l.value.apiKey||l.value.apiKey.trim()==="")&&(x.value.apiKey="请填写 API Key",o=!0)):l.value.addType==="manual"&&(!l.value.accessToken||l.value.accessToken.trim()==="")&&(x.value.accessToken="请填写 Access Token",o=!0),l.value.accountType==="group"&&(!l.value.groupId||l.value.groupId.trim()==="")&&(h("请选择一个分组","error"),o=!0),!o){R.value=!0;try{const t={name:l.value.name,description:l.value.description,accountType:l.value.accountType,groupId:l.value.accountType==="group"?l.value.groupId:void 0,proxy:l.value.proxy.enabled?{type:l.value.proxy.type,host:l.value.proxy.host,port:parseInt(l.value.proxy.port),username:l.value.proxy.username||null,password:l.value.proxy.password||null}:null};if(l.value.platform==="claude"){const k=l.value.refreshToken?6e5:31536e6;t.claudeAiOauth={accessToken:l.value.accessToken,refreshToken:l.value.refreshToken||"",expiresAt:Date.now()+k,scopes:["user:inference"]},t.priority=l.value.priority||50}else if(l.value.platform==="gemini"){const k=l.value.refreshToken?6e5:31536e6;t.geminiOauth={access_token:l.value.accessToken,refresh_token:l.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+k},l.value.projectId&&(t.projectId=l.value.projectId)}else l.value.platform==="claude-console"&&(t.apiUrl=l.value.apiUrl,t.apiKey=l.value.apiKey,t.priority=l.value.priority||50,t.supportedModels=l.value.supportedModels?l.value.supportedModels.split(`
+`).filter(k=>k.trim()):[],t.userAgent=l.value.userAgent||null,t.rateLimitDuration=l.value.rateLimitDuration||60);let s;l.value.platform==="claude"?s=await i.createClaudeAccount(t):l.value.platform==="claude-console"?s=await i.createClaudeConsoleAccount(t):s=await i.createGeminiAccount(t),C("success",s)}catch(t){h(t.message||"账户创建失败","error")}finally{R.value=!1}}},j=async()=>{if(x.value.name="",!l.value.name||l.value.name.trim()===""){x.value.name="请填写账户名称";return}if(l.value.accountType==="group"&&(!l.value.groupId||l.value.groupId.trim()==="")){h("请选择一个分组","error");return}if(!(l.value.platform==="gemini"&&(!l.value.projectId||l.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。
如果您的Google账号绑定了Google Cloud或被识别为Workspace账号,需要提供项目编号。
-如果您使用的是普通个人账号,可以继续不填写。`,"继续保存","返回填写"))){K.value=!0;try{const o={name:l.value.name,description:l.value.description,accountType:l.value.accountType,groupId:l.value.accountType==="group"?l.value.groupId:void 0,proxy:l.value.proxy.enabled?{type:l.value.proxy.type,host:l.value.proxy.host,port:parseInt(l.value.proxy.port),username:l.value.proxy.username||null,password:l.value.proxy.password||null}:null};if(l.value.accessToken||l.value.refreshToken){if(d.account.platform==="claude"){const t=l.value.refreshToken?6e5:31536e6;o.claudeAiOauth={accessToken:l.value.accessToken||"",refreshToken:l.value.refreshToken||"",expiresAt:Date.now()+t,scopes:["user:inference"]}}else if(d.account.platform==="gemini"){const t=l.value.refreshToken?6e5:31536e6;o.geminiOauth={access_token:l.value.accessToken||"",refresh_token:l.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+t}}}d.account.platform==="gemini"&&l.value.projectId&&(o.projectId=l.value.projectId),d.account.platform==="claude"&&(o.priority=l.value.priority||50),d.account.platform==="claude-console"&&(o.apiUrl=l.value.apiUrl,l.value.apiKey&&(o.apiKey=l.value.apiKey),o.priority=l.value.priority||50,o.supportedModels=l.value.supportedModels?l.value.supportedModels.split(`
-`).filter(t=>t.trim()):[],o.userAgent=l.value.userAgent||null,o.rateLimitDuration=l.value.rateLimitDuration||60),d.account.platform==="claude"?await i.updateClaudeAccount(d.account.id,o):d.account.platform==="claude-console"?await i.updateClaudeConsoleAccount(d.account.id,o):await i.updateGeminiAccount(d.account.id,o),$("success")}catch(o){h(o.message||"账户更新失败","error")}finally{K.value=!1}}};E(()=>l.value.name,()=>{var o;x.value.name&&((o=l.value.name)!=null&&o.trim())&&(x.value.name="")}),E(()=>l.value.accessToken,()=>{var o;x.value.accessToken&&((o=l.value.accessToken)!=null&&o.trim())&&(x.value.accessToken="")}),E(()=>l.value.apiUrl,()=>{var o;x.value.apiUrl&&((o=l.value.apiUrl)!=null&&o.trim())&&(x.value.apiUrl="")}),E(()=>l.value.apiKey,()=>{var o;x.value.apiKey&&((o=l.value.apiKey)!=null&&o.trim())&&(x.value.apiKey="")});const u=b([]),A=b(!1),Z=b(!1),oe=ne(()=>{const o=l.value.platform==="claude-console"?"claude":l.value.platform;return u.value.filter(t=>t.platform===o)}),c=async()=>{A.value=!0;try{const o=await V.get("/admin/account-groups");u.value=o.data||[]}catch{h("加载分组列表失败","error"),u.value=[]}finally{A.value=!1}},p=async()=>{await c(),h("分组列表已刷新","success")},U=async()=>{await c()};E(()=>l.value.platform,o=>{o==="claude-console"&&(l.value.addType="manual"),l.value.accountType==="group"&&(l.value.groupId="")}),E(()=>l.value.accountType,o=>{o==="group"&&u.value.length===0&&c()}),E(()=>l.value.groupId,o=>{o==="__new__"&&(l.value.groupId="",Z.value=!0)});const B=o=>{const t=l.value.supportedModels?l.value.supportedModels.split(`
+如果您使用的是普通个人账号,可以继续不填写。`,"继续保存","返回填写"))){R.value=!0;try{const o={name:l.value.name,description:l.value.description,accountType:l.value.accountType,groupId:l.value.accountType==="group"?l.value.groupId:void 0,proxy:l.value.proxy.enabled?{type:l.value.proxy.type,host:l.value.proxy.host,port:parseInt(l.value.proxy.port),username:l.value.proxy.username||null,password:l.value.proxy.password||null}:null};if(l.value.accessToken||l.value.refreshToken){if(d.account.platform==="claude"){const t=l.value.refreshToken?6e5:31536e6;o.claudeAiOauth={accessToken:l.value.accessToken||"",refreshToken:l.value.refreshToken||"",expiresAt:Date.now()+t,scopes:["user:inference"]}}else if(d.account.platform==="gemini"){const t=l.value.refreshToken?6e5:31536e6;o.geminiOauth={access_token:l.value.accessToken||"",refresh_token:l.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+t}}}d.account.platform==="gemini"&&l.value.projectId&&(o.projectId=l.value.projectId),d.account.platform==="claude"&&(o.priority=l.value.priority||50),d.account.platform==="claude-console"&&(o.apiUrl=l.value.apiUrl,l.value.apiKey&&(o.apiKey=l.value.apiKey),o.priority=l.value.priority||50,o.supportedModels=l.value.supportedModels?l.value.supportedModels.split(`
+`).filter(t=>t.trim()):[],o.userAgent=l.value.userAgent||null,o.rateLimitDuration=l.value.rateLimitDuration||60),d.account.platform==="claude"?await i.updateClaudeAccount(d.account.id,o):d.account.platform==="claude-console"?await i.updateClaudeConsoleAccount(d.account.id,o):await i.updateGeminiAccount(d.account.id,o),C("success")}catch(o){h(o.message||"账户更新失败","error")}finally{R.value=!1}}};E(()=>l.value.name,()=>{var o;x.value.name&&((o=l.value.name)!=null&&o.trim())&&(x.value.name="")}),E(()=>l.value.accessToken,()=>{var o;x.value.accessToken&&((o=l.value.accessToken)!=null&&o.trim())&&(x.value.accessToken="")}),E(()=>l.value.apiUrl,()=>{var o;x.value.apiUrl&&((o=l.value.apiUrl)!=null&&o.trim())&&(x.value.apiUrl="")}),E(()=>l.value.apiKey,()=>{var o;x.value.apiKey&&((o=l.value.apiKey)!=null&&o.trim())&&(x.value.apiKey="")});const u=b([]),A=b(!1),Z=b(!1),oe=ne(()=>{const o=l.value.platform==="claude-console"?"claude":l.value.platform;return u.value.filter(t=>t.platform===o)}),c=async()=>{A.value=!0;try{const o=await V.get("/admin/account-groups");u.value=o.data||[]}catch{h("加载分组列表失败","error"),u.value=[]}finally{A.value=!1}},p=async()=>{await c(),h("分组列表已刷新","success")},U=async()=>{await c()};E(()=>l.value.platform,o=>{o==="claude-console"&&(l.value.addType="manual"),l.value.accountType==="group"&&(l.value.groupId="")}),E(()=>l.value.accountType,o=>{o==="group"&&u.value.length===0&&c()}),E(()=>l.value.groupId,o=>{o==="__new__"&&(l.value.groupId="",Z.value=!0)});const F=o=>{const t=l.value.supportedModels?l.value.supportedModels.split(`
`).filter(s=>s.trim()):[];if(t.includes(o)){h(`模型 ${o} 已存在`,"info");return}t.push(o),l.value.supportedModels=t.join(`
`),h(`已添加模型 ${o}`,"success")};return E(()=>d.account,o=>{var t;if(o){const s=o.proxy&&o.proxy.host&&o.proxy.port?{enabled:!0,type:o.proxy.type||"socks5",host:o.proxy.host,port:o.proxy.port,username:o.proxy.username||"",password:o.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""};l.value={platform:o.platform,addType:"oauth",name:o.name,description:o.description||"",accountType:o.accountType||"shared",groupId:"",projectId:o.projectId||"",accessToken:"",refreshToken:"",proxy:s,apiUrl:o.apiUrl||"",apiKey:"",priority:o.priority||50,supportedModels:((t=o.supportedModels)==null?void 0:t.join(`
-`))||"",userAgent:o.userAgent||"",rateLimitDuration:o.rateLimitDuration||60},o.accountType==="group"&&c().then(()=>{u.value.forEach(k=>{V.get(`/admin/account-groups/${k.id}/members`).then(D=>{(D.data||[]).some(H=>H.id===o.id)&&(l.value.groupId=k.id)}).catch(()=>{})})})}},{immediate:!0}),(o,t)=>(a(),le(Ae,{to:"body"},[G.value?(a(),n("div",Vs,[e("div",js,[e("div",Ss,[e("div",_s,[t[48]||(t[48]=e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-user-circle text-white text-sm sm:text-base"})],-1)),e("h3",Ms,f(m.value?"编辑账户":"添加账户"),1)]),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:t[0]||(t[0]=s=>o.$emit("close"))},t[49]||(t[49]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),!m.value&&l.value.addType==="oauth"?(a(),n("div",Gs,[e("div",Rs,[e("div",Ks,[e("div",{class:R(["w-6 h-6 sm:w-8 sm:h-8 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold",S.value>=1?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 1 ",2),t[50]||(t[50]=e("span",{class:"ml-1.5 sm:ml-2 text-xs sm:text-sm font-medium text-gray-700"},"基本信息",-1))]),t[52]||(t[52]=e("div",{class:"w-4 sm:w-8 h-0.5 bg-gray-300"},null,-1)),e("div",Ls,[e("div",{class:R(["w-6 h-6 sm:w-8 sm:h-8 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold",S.value>=2?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 2 ",2),t[51]||(t[51]=e("span",{class:"ml-1.5 sm:ml-2 text-xs sm:text-sm font-medium text-gray-700"},"授权认证",-1))])])])):y("",!0),S.value===1&&!m.value?(a(),n("div",Ps,[e("div",Ds,[m.value?y("",!0):(a(),n("div",zs,[t[56]||(t[56]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"平台",-1)),e("div",Es,[e("label",Os,[g(e("input",{"onUpdate:modelValue":t[1]||(t[1]=s=>l.value.platform=s),type:"radio",value:"claude",class:"mr-2"},null,512),[[X,l.value.platform]]),t[53]||(t[53]=e("span",{class:"text-sm text-gray-700"},"Claude",-1))]),e("label",Ws,[g(e("input",{"onUpdate:modelValue":t[2]||(t[2]=s=>l.value.platform=s),type:"radio",value:"claude-console",class:"mr-2"},null,512),[[X,l.value.platform]]),t[54]||(t[54]=e("span",{class:"text-sm text-gray-700"},"Claude Console",-1))]),e("label",qs,[g(e("input",{"onUpdate:modelValue":t[3]||(t[3]=s=>l.value.platform=s),type:"radio",value:"gemini",class:"mr-2"},null,512),[[X,l.value.platform]]),t[55]||(t[55]=e("span",{class:"text-sm text-gray-700"},"Gemini",-1))])])])),!m.value&&l.value.platform!=="claude-console"?(a(),n("div",Fs,[t[59]||(t[59]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"添加方式",-1)),e("div",Bs,[e("label",Ns,[g(e("input",{"onUpdate:modelValue":t[4]||(t[4]=s=>l.value.addType=s),type:"radio",value:"oauth",class:"mr-2"},null,512),[[X,l.value.addType]]),t[57]||(t[57]=e("span",{class:"text-sm text-gray-700"},"OAuth 授权 (推荐)",-1))]),e("label",Hs,[g(e("input",{"onUpdate:modelValue":t[5]||(t[5]=s=>l.value.addType=s),type:"radio",value:"manual",class:"mr-2"},null,512),[[X,l.value.addType]]),t[58]||(t[58]=e("span",{class:"text-sm text-gray-700"},"手动输入 Access Token",-1))])])])):y("",!0),e("div",null,[t[60]||(t[60]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[6]||(t[6]=s=>l.value.name=s),type:"text",required:"",class:R(["form-input w-full",{"border-red-500":x.value.name}]),placeholder:"为账户设置一个易识别的名称"},null,2),[[_,l.value.name]]),x.value.name?(a(),n("p",Js,f(x.value.name),1)):y("",!0)]),e("div",null,[t[61]||(t[61]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[7]||(t[7]=s=>l.value.description=s),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[_,l.value.description]])]),e("div",null,[t[65]||(t[65]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",Ys,[e("label",Qs,[g(e("input",{"onUpdate:modelValue":t[8]||(t[8]=s=>l.value.accountType=s),type:"radio",value:"shared",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[62]||(t[62]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",Xs,[g(e("input",{"onUpdate:modelValue":t[9]||(t[9]=s=>l.value.accountType=s),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[63]||(t[63]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))]),e("label",Zs,[g(e("input",{"onUpdate:modelValue":t[10]||(t[10]=s=>l.value.accountType=s),type:"radio",value:"group",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[64]||(t[64]=e("span",{class:"text-sm text-gray-700"},"分组调度",-1))])]),t[66]||(t[66]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用;分组调度:加入分组供分组内调度 ",-1))]),l.value.accountType==="group"?(a(),n("div",el,[t[69]||(t[69]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"选择分组 *",-1)),e("div",tl,[g(e("select",{"onUpdate:modelValue":t[11]||(t[11]=s=>l.value.groupId=s),class:"form-input flex-1",required:""},[t[67]||(t[67]=e("option",{value:""},"请选择分组",-1)),(a(!0),n(re,null,ie(oe.value,s=>(a(),n("option",{key:s.id,value:s.id},f(s.name)+" ("+f(s.memberCount||0)+" 个成员) ",9,sl))),128)),t[68]||(t[68]=e("option",{value:"__new__"},"+ 新建分组",-1))],512),[[ce,l.value.groupId]]),e("button",{type:"button",class:"px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",onClick:p},[e("i",{class:R(["fas fa-sync-alt",{"animate-spin":A.value}])},null,2)])])])):y("",!0),l.value.platform==="gemini"?(a(),n("div",ll,[t[70]||(t[70]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[12]||(t[12]=s=>l.value.projectId=s),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[_,l.value.projectId]]),t[71]||(t[71]=e("div",{class:"mt-2 p-3 bg-yellow-50 border border-yellow-200 rounded-lg"},[e("div",{class:"flex items-start gap-2"},[e("i",{class:"fas fa-info-circle text-yellow-600 mt-0.5"}),e("div",{class:"text-xs text-yellow-700"},[e("p",{class:"font-medium mb-1"}," Google Cloud/Workspace 账号需要提供项目编号 "),e("p",null,"某些 Google 账号(特别是绑定了 Google Cloud 的账号)会被识别为 Workspace 账号,需要提供额外的项目编号。"),e("div",{class:"mt-2 p-2 bg-white rounded border border-yellow-300"},[e("p",{class:"font-medium mb-1"}," 如何获取项目编号: "),e("ol",{class:"list-decimal list-inside space-y-1 ml-2"},[e("li",null,[C(" 访问 "),e("a",{href:"https://console.cloud.google.com/welcome",target:"_blank",class:"text-blue-600 hover:underline font-medium"},"Google Cloud Console")]),e("li",null,[C("复制"),e("span",{class:"font-semibold text-red-600"},"项目编号(Project Number)"),C(",通常是12位纯数字")]),e("li",{class:"text-red-600"}," ⚠️ 注意:不要复制项目ID(Project ID),要复制项目编号! ")])]),e("p",{class:"mt-2"},[e("strong",null,"提示:"),C("如果您的账号是普通个人账号(未绑定 Google Cloud),请留空此字段。 ")])])])],-1))])):y("",!0),l.value.platform==="claude-console"&&!m.value?(a(),n("div",ol,[e("div",null,[t[72]||(t[72]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL *",-1)),g(e("input",{"onUpdate:modelValue":t[13]||(t[13]=s=>l.value.apiUrl=s),type:"text",required:"",class:R(["form-input w-full",{"border-red-500":x.value.apiUrl}]),placeholder:"例如:https://api.example.com"},null,2),[[_,l.value.apiUrl]]),x.value.apiUrl?(a(),n("p",al,f(x.value.apiUrl),1)):y("",!0)]),e("div",null,[t[73]||(t[73]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key *",-1)),g(e("input",{"onUpdate:modelValue":t[14]||(t[14]=s=>l.value.apiKey=s),type:"password",required:"",class:R(["form-input w-full",{"border-red-500":x.value.apiKey}]),placeholder:"请输入API Key"},null,2),[[_,l.value.apiKey]]),x.value.apiKey?(a(),n("p",nl,f(x.value.apiKey),1)):y("",!0)]),e("div",null,[t[74]||(t[74]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"支持的模型 (可选)--注意,ClaudeCode必须加上hiku模型!",-1)),e("div",rl,[e("button",{type:"button",class:"px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors",onClick:t[15]||(t[15]=s=>B("claude-sonnet-4-20250514"))}," + claude-sonnet-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[16]||(t[16]=s=>B("claude-opus-4-20250514"))}," + claude-opus-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[17]||(t[17]=s=>B("claude-3-5-haiku-20241022"))}," + claude-3-5-haiku-20241022 ")]),g(e("textarea",{"onUpdate:modelValue":t[18]||(t[18]=s=>l.value.supportedModels=s),rows:"3",class:"form-input w-full resize-none",placeholder:"每行一个模型,留空表示支持所有模型。特别注意,ClaudeCode必须加上hiku模型!"},null,512),[[_,l.value.supportedModels]]),t[75]||(t[75]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示支持所有模型。如果指定模型,请求中的模型不在列表内将不会调度到此账号 ",-1))]),e("div",null,[t[76]||(t[76]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[19]||(t[19]=s=>l.value.userAgent=s),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[_,l.value.userAgent]])]),e("div",null,[t[77]||(t[77]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[20]||(t[20]=s=>l.value.rateLimitDuration=s),type:"number",min:"1",class:"form-input w-full",placeholder:"默认60分钟"},null,512),[[_,l.value.rateLimitDuration,void 0,{number:!0}]]),t[78]||(t[78]=e("p",{class:"text-xs text-gray-500 mt-1"}," 当账号返回429错误时,暂停调度的时间(分钟) ",-1))])])):y("",!0),l.value.platform==="claude"||l.value.platform==="claude-console"?(a(),n("div",il,[t[79]||(t[79]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[21]||(t[21]=s=>l.value.priority=s),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高,默认50"},null,512),[[_,l.value.priority,void 0,{number:!0}]]),t[80]||(t[80]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):y("",!0),l.value.addType==="manual"&&l.value.platform!=="claude-console"?(a(),n("div",ul,[e("div",dl,[t[86]||(t[86]=e("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"},[e("i",{class:"fas fa-info text-white text-sm"})],-1)),e("div",null,[t[84]||(t[84]=e("h5",{class:"font-semibold text-blue-900 mb-2"}," 手动输入 Token ",-1)),l.value.platform==="claude"?(a(),n("p",pl," 请输入有效的 Claude Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):l.value.platform==="gemini"?(a(),n("p",ml," 请输入有效的 Gemini Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):y("",!0),e("div",cl,[t[83]||(t[83]=e("p",{class:"text-sm text-blue-900 font-medium mb-1"},[e("i",{class:"fas fa-folder-open mr-1"}),C(" 获取 Access Token 的方法: ")],-1)),l.value.platform==="claude"?(a(),n("p",fl,t[81]||(t[81]=[C(" 请从已登录 Claude Code 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.claude/.credentials.json",-1),C(" 文件中的凭证, 请勿使用 Claude 官网 API Keys 页面的密钥。 ",-1)]))):l.value.platform==="gemini"?(a(),n("p",xl,t[82]||(t[82]=[C(" 请从已登录 Gemini CLI 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.config/gemini/credentials.json",-1),C(" 文件中的凭证。 ",-1)]))):y("",!0)]),t[85]||(t[85]=e("p",{class:"text-xs text-blue-600"}," 💡 如果未填写 Refresh Token,Token 过期后需要手动更新。 ",-1))])]),e("div",null,[t[87]||(t[87]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Access Token *",-1)),g(e("textarea",{"onUpdate:modelValue":t[22]||(t[22]=s=>l.value.accessToken=s),rows:"4",required:"",class:R(["form-input w-full resize-none font-mono text-xs",{"border-red-500":x.value.accessToken}]),placeholder:"请输入 Access Token..."},null,2),[[_,l.value.accessToken]]),x.value.accessToken?(a(),n("p",vl,f(x.value.accessToken),1)):y("",!0)]),e("div",null,[t[88]||(t[88]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Refresh Token (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[23]||(t[23]=s=>l.value.refreshToken=s),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"请输入 Refresh Token..."},null,512),[[_,l.value.refreshToken]])])])):y("",!0),Ce(Ge,{modelValue:l.value.proxy,"onUpdate:modelValue":t[24]||(t[24]=s=>l.value.proxy=s)},null,8,["modelValue"]),e("div",gl,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:t[25]||(t[25]=s=>o.$emit("close"))}," 取消 "),l.value.addType==="oauth"&&l.value.platform!=="claude-console"?(a(),n("button",{key:0,type:"button",disabled:K.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:L}," 下一步 ",8,yl)):(a(),n("button",{key:1,type:"button",disabled:K.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:W},[K.value?(a(),n("div",wl)):y("",!0),C(" "+f(K.value?"创建中...":"创建"),1)],8,bl))])])])):y("",!0),S.value===2&&l.value.addType==="oauth"?(a(),le(Et,{key:2,platform:l.value.platform,proxy:l.value.proxy,onSuccess:F,onBack:t[26]||(t[26]=s=>S.value=1)},null,8,["platform","proxy"])):y("",!0),m.value?(a(),n("div",kl,[e("div",null,[t[89]||(t[89]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[27]||(t[27]=s=>l.value.name=s),type:"text",required:"",class:"form-input w-full",placeholder:"为账户设置一个易识别的名称"},null,512),[[_,l.value.name]])]),e("div",null,[t[90]||(t[90]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[28]||(t[28]=s=>l.value.description=s),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[_,l.value.description]])]),e("div",null,[t[94]||(t[94]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",hl,[e("label",$l,[g(e("input",{"onUpdate:modelValue":t[29]||(t[29]=s=>l.value.accountType=s),type:"radio",value:"shared",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[91]||(t[91]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",Cl,[g(e("input",{"onUpdate:modelValue":t[30]||(t[30]=s=>l.value.accountType=s),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[92]||(t[92]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))]),e("label",Tl,[g(e("input",{"onUpdate:modelValue":t[31]||(t[31]=s=>l.value.accountType=s),type:"radio",value:"group",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[93]||(t[93]=e("span",{class:"text-sm text-gray-700"},"分组调度",-1))])]),t[95]||(t[95]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用;分组调度:加入分组供分组内调度 ",-1))]),l.value.accountType==="group"?(a(),n("div",Al,[t[98]||(t[98]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"选择分组 *",-1)),e("div",Ul,[g(e("select",{"onUpdate:modelValue":t[32]||(t[32]=s=>l.value.groupId=s),class:"form-input flex-1",required:""},[t[96]||(t[96]=e("option",{value:""},"请选择分组",-1)),(a(!0),n(re,null,ie(oe.value,s=>(a(),n("option",{key:s.id,value:s.id},f(s.name)+" ("+f(s.memberCount||0)+" 个成员) ",9,Il))),128)),t[97]||(t[97]=e("option",{value:"__new__"},"+ 新建分组",-1))],512),[[ce,l.value.groupId]]),e("button",{type:"button",class:"px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",onClick:p},[e("i",{class:R(["fas fa-sync-alt",{"animate-spin":A.value}])},null,2)])])])):y("",!0),l.value.platform==="gemini"?(a(),n("div",Vl,[t[99]||(t[99]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[33]||(t[33]=s=>l.value.projectId=s),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[_,l.value.projectId]]),t[100]||(t[100]=e("p",{class:"text-xs text-gray-500 mt-2"}," Google Cloud/Workspace 账号可能需要提供项目编号 ",-1))])):y("",!0),l.value.platform==="claude"||l.value.platform==="claude-console"?(a(),n("div",jl,[t[101]||(t[101]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[34]||(t[34]=s=>l.value.priority=s),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高"},null,512),[[_,l.value.priority,void 0,{number:!0}]]),t[102]||(t[102]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):y("",!0),l.value.platform==="claude-console"?(a(),n("div",Sl,[e("div",null,[t[103]||(t[103]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL",-1)),g(e("input",{"onUpdate:modelValue":t[35]||(t[35]=s=>l.value.apiUrl=s),type:"text",required:"",class:"form-input w-full",placeholder:"例如:https://api.example.com"},null,512),[[_,l.value.apiUrl]])]),e("div",null,[t[104]||(t[104]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key",-1)),g(e("input",{"onUpdate:modelValue":t[36]||(t[36]=s=>l.value.apiKey=s),type:"password",class:"form-input w-full",placeholder:"留空表示不更新"},null,512),[[_,l.value.apiKey]]),t[105]||(t[105]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示不更新 API Key ",-1))]),e("div",null,[t[106]||(t[106]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"支持的模型 (可选)",-1)),e("div",_l,[e("button",{type:"button",class:"px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors",onClick:t[37]||(t[37]=s=>B("claude-sonnet-4-20250514"))}," + claude-sonnet-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[38]||(t[38]=s=>B("claude-opus-4-20250514"))}," + claude-opus-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[39]||(t[39]=s=>B("claude-3-5-haiku-20241022"))}," + claude-3-5-haiku-20241022 ")]),g(e("textarea",{"onUpdate:modelValue":t[40]||(t[40]=s=>l.value.supportedModels=s),rows:"3",class:"form-input w-full resize-none",placeholder:"每行一个模型,留空表示支持所有模型。特别注意,ClaudeCode必须加上hiku模型!"},null,512),[[_,l.value.supportedModels]])]),e("div",null,[t[107]||(t[107]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[41]||(t[41]=s=>l.value.userAgent=s),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[_,l.value.userAgent]])]),e("div",null,[t[108]||(t[108]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[42]||(t[42]=s=>l.value.rateLimitDuration=s),type:"number",min:"1",class:"form-input w-full"},null,512),[[_,l.value.rateLimitDuration,void 0,{number:!0}]])])])):y("",!0),l.value.platform!=="claude-console"?(a(),n("div",Ml,[t[111]||(t[111]=e("div",{class:"flex items-start gap-3 mb-4"},[e("div",{class:"w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"},[e("i",{class:"fas fa-key text-white text-sm"})]),e("div",null,[e("h5",{class:"font-semibold text-amber-900 mb-2"}," 更新 Token "),e("p",{class:"text-sm text-amber-800 mb-2"}," 可以更新 Access Token 和 Refresh Token。为了安全起见,不会显示当前的 Token 值。 "),e("p",{class:"text-xs text-amber-600"}," 💡 留空表示不更新该字段。 ")])],-1)),e("div",Gl,[e("div",null,[t[109]||(t[109]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Access Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[43]||(t[43]=s=>l.value.accessToken=s),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[_,l.value.accessToken]])]),e("div",null,[t[110]||(t[110]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Refresh Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[44]||(t[44]=s=>l.value.refreshToken=s),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[_,l.value.refreshToken]])])])])):y("",!0),Ce(Ge,{modelValue:l.value.proxy,"onUpdate:modelValue":t[45]||(t[45]=s=>l.value.proxy=s)},null,8,["modelValue"]),e("div",Rl,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:t[46]||(t[46]=s=>o.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:K.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:j},[K.value?(a(),n("div",Ll)):y("",!0),C(" "+f(K.value?"更新中...":"更新"),1)],8,Kl)])])):y("",!0)])])):y("",!0),Ce(De,{show:Y(M),title:Y(I).title,message:Y(I).message,"confirm-text":Y(I).confirmText,"cancel-text":Y(I).cancelText,onConfirm:Y(w),onCancel:Y(v)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"]),Z.value?(a(),le(Is,{key:1,onClose:t[47]||(t[47]=s=>Z.value=!1),onRefresh:U})):y("",!0)]))}},Pl={class:"accounts-container"},Dl={class:"card p-4 sm:p-6"},zl={class:"flex flex-col gap-4 mb-4 sm:mb-6"},El={class:"flex flex-col sm:flex-row gap-2 sm:items-center sm:justify-between"},Ol={class:"flex flex-col sm:flex-row gap-2"},Wl=["value"],ql={key:0,class:"text-center py-12"},Fl={key:1,class:"text-center py-12"},Bl={key:2,class:"hidden md:block table-container"},Nl={class:"w-full table-fixed"},Hl={class:"bg-gray-50/80 backdrop-blur-sm"},Jl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Yl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Ql={key:1,class:"fas fa-sort ml-1 text-gray-400"},Xl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Zl={class:"divide-y divide-gray-200/50"},eo={class:"px-3 py-4"},to={class:"flex items-center"},so={class:"min-w-0"},lo={class:"flex items-center gap-2"},oo=["title"],ao={key:0,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800"},no={key:1,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"},ro={key:2,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"},io=["title"],uo=["title"],po={class:"px-3 py-4"},mo={class:"flex items-center gap-1"},co={key:0,class:"flex items-center gap-1.5 px-2.5 py-1 bg-gradient-to-r from-yellow-100 to-amber-100 rounded-lg border border-yellow-200"},fo={class:"text-xs font-medium text-yellow-700"},xo={key:1,class:"flex items-center gap-1.5 px-2.5 py-1 bg-gradient-to-r from-purple-100 to-pink-100 rounded-lg border border-purple-200"},vo={key:2,class:"flex items-center gap-1.5 px-2.5 py-1 bg-gradient-to-r from-indigo-100 to-blue-100 rounded-lg border border-indigo-200"},go={class:"text-xs font-medium text-indigo-700"},yo={class:"px-3 py-4 whitespace-nowrap"},bo={class:"flex flex-col gap-1"},wo={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"},ko={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-gray-100 text-gray-700"},ho=["title"],$o={key:3,class:"text-xs text-gray-500"},Co={class:"px-3 py-4 whitespace-nowrap"},To={key:0,class:"flex items-center gap-2"},Ao={class:"w-16 bg-gray-200 rounded-full h-2"},Uo={class:"text-xs text-gray-700 font-medium min-w-[20px]"},Io={key:1,class:"text-gray-400 text-sm"},Vo={class:"px-3 py-4 text-sm text-gray-600"},jo=["title"],So={key:1,class:"text-gray-400"},_o={class:"px-3 py-4 whitespace-nowrap text-sm"},Mo={key:0,class:"space-y-1"},Go={class:"flex items-center gap-2"},Ro={class:"text-sm font-medium text-gray-900"},Ko={class:"flex items-center gap-2"},Lo={class:"text-xs text-gray-600"},Po={key:0,class:"text-xs text-gray-500"},Do={key:1,class:"text-gray-400 text-xs"},zo={class:"px-3 py-4 whitespace-nowrap"},Eo={key:0,class:"space-y-2"},Oo={class:"flex items-center gap-2"},Wo={class:"w-24 bg-gray-200 rounded-full h-2"},qo={class:"text-xs text-gray-700 font-medium min-w-[32px]"},Fo={class:"text-xs text-gray-600"},Bo={key:0,class:"text-indigo-600 font-medium"},No={key:1,class:"text-gray-400 text-sm"},Ho={key:2,class:"text-gray-400 text-sm"},Jo={class:"px-3 py-4 whitespace-nowrap text-sm text-gray-600"},Yo={class:"px-3 py-4 whitespace-nowrap text-sm font-medium"},Qo={class:"flex items-center gap-1 flex-wrap"},Xo=["disabled","title","onClick"],Zo=["disabled","title","onClick"],ea={class:"ml-1"},ta=["onClick"],sa=["onClick"],la={key:3,class:"md:hidden space-y-3"},oa={class:"flex items-start justify-between mb-3"},aa={class:"flex items-center gap-3"},na={class:"text-sm font-semibold text-gray-900"},ra={class:"flex items-center gap-2 mt-0.5"},ia={class:"text-xs text-gray-500"},ua={class:"text-xs text-gray-500"},da={class:"grid grid-cols-2 gap-3 mb-3"},pa={class:"text-sm font-semibold text-gray-900"},ma={class:"text-xs text-gray-500 mt-0.5"},ca={class:"text-sm font-semibold text-gray-900"},fa={class:"text-xs text-gray-500 mt-0.5"},xa={class:"space-y-2 mb-3"},va={key:0,class:"flex items-center justify-between text-xs"},ga={class:"flex items-center gap-2"},ya={class:"w-20 h-1.5 bg-gray-200 rounded-full overflow-hidden"},ba={class:"flex items-center justify-between text-xs"},wa={class:"text-gray-700"},ka={key:1,class:"flex items-center justify-between text-xs"},ha={class:"text-gray-700"},$a={class:"flex items-center justify-between text-xs"},Ca={class:"text-gray-700 font-medium"},Ta={class:"flex gap-2 mt-3 pt-3 border-t border-gray-100"},Aa=["disabled","onClick"],Ua=["onClick","disabled"],Ia=["onClick"],Va=["onClick"],ja={__name:"AccountsView",setup(P){const{showConfirmModal:O,confirmOptions:d,showConfirm:$,handleConfirm:i,handleCancel:M}=Le(),I=b([]),T=b(!1),w=b("name"),v=b(""),m=b("asc"),G=b([]),S=b({}),K=b([]),q=b("all"),l=b([]),x=b(!1),r=b(!1),L=b(null),F=ne(()=>{const o=l.value.length>0?l.value:I.value;return v.value?[...o].sort((s,k)=>{var H,Q,J,z,ee,te,ae,Ue,Ie,Ve,je,Se;let D=s[v.value],N=k[v.value];return v.value==="dailyTokens"?(D=((Q=(H=s.usage)==null?void 0:H.daily)==null?void 0:Q.allTokens)||0,N=((z=(J=k.usage)==null?void 0:J.daily)==null?void 0:z.allTokens)||0):v.value==="dailyRequests"?(D=((te=(ee=s.usage)==null?void 0:ee.daily)==null?void 0:te.requests)||0,N=((Ue=(ae=k.usage)==null?void 0:ae.daily)==null?void 0:Ue.requests)||0):v.value==="totalTokens"&&(D=((Ve=(Ie=s.usage)==null?void 0:Ie.total)==null?void 0:Ve.allTokens)||0,N=((Se=(je=k.usage)==null?void 0:je.total)==null?void 0:Se.allTokens)||0),v.value==="lastUsed"&&(D=s.lastUsedAt?new Date(s.lastUsedAt).getTime():0,N=k.lastUsedAt?new Date(k.lastUsedAt).getTime():0),v.value==="status"&&(D=s.isActive?1:0,N=k.isActive?1:0),DN?m.value==="asc"?1:-1:0}):o}),W=async()=>{T.value=!0;try{const[o,t,s,k,D]=await Promise.all([V.get("/admin/claude-accounts"),V.get("/admin/claude-console-accounts"),V.get("/admin/gemini-accounts"),V.get("/admin/api-keys"),V.get("/admin/account-groups")]);k.success&&(G.value=k.data||[]),D.success&&(K.value=D.data||[]);const N=new Map,H=new Map;for(const J of K.value){N.set(J.id,J);try{const z=await V.get(`/admin/account-groups/${J.id}/members`);z.success&&(z.data||[]).forEach(te=>{H.set(te.id,J)})}catch(z){console.error(`Failed to load members for group ${J.id}:`,z)}}const Q=[];if(o.success){const J=(o.data||[]).map(z=>{const ee=G.value.filter(ae=>ae.claudeAccountId===z.id).length,te=H.get(z.id)||null;return{...z,platform:"claude",boundApiKeysCount:ee,groupInfo:te}});Q.push(...J)}if(t.success){const J=(t.data||[]).map(z=>{const ee=H.get(z.id)||null;return{...z,platform:"claude-console",boundApiKeysCount:0,groupInfo:ee}});Q.push(...J)}if(s.success){const J=(s.data||[]).map(z=>{const ee=G.value.filter(ae=>ae.geminiAccountId===z.id).length,te=H.get(z.id)||null;return{...z,platform:"gemini",boundApiKeysCount:ee,groupInfo:te}});Q.push(...J)}I.value=Q,oe()}catch{h("加载账户失败","error")}finally{T.value=!1}},j=o=>{o&&(v.value===o?m.value=m.value==="asc"?"desc":"asc":(v.value=o,m.value="asc"))},u=o=>{if(o==null)return"0";const t=Number(o);return t>=1e6?Math.floor(t/1e6).toLocaleString()+"M":t.toLocaleString()},A=o=>{if(!o)return"从未使用";const t=new Date(o),k=new Date-t;return k<6e4?"刚刚":k<36e5?`${Math.floor(k/6e4)} 分钟前`:k<864e5?`${Math.floor(k/36e5)} 小时前`:k<6048e5?`${Math.floor(k/864e5)} 天前`:t.toLocaleDateString("zh-CN")},Z=async()=>{try{const o=await V.get("/admin/api-keys");o.success&&(G.value=o.data)}catch(o){console.error("Failed to load API keys:",o)}},oe=()=>{q.value==="all"?l.value=I.value:q.value==="ungrouped"?l.value=I.value.filter(o=>!o.groupInfo):l.value=I.value.filter(o=>o.groupInfo&&o.groupInfo.id===q.value)},c=o=>{if(!o||!o.host||!o.port)return null;const t=o.type==="socks5"?"S5":o.type.toUpperCase();let s=o.host;s.length>15&&(s=s.substring(0,12)+"...");let k=`${t}://${s}:${o.port}`;return o.username&&(k=`${t}://***@${s}:${o.port}`),k},p=(o,t)=>{if(!o||!t)return"--";const s=new Date(o),k=new Date(t),D=s.getHours().toString().padStart(2,"0"),N=s.getMinutes().toString().padStart(2,"0"),H=k.getHours().toString().padStart(2,"0"),Q=k.getMinutes().toString().padStart(2,"0");return`${D}:${N} - ${H}:${Q}`},U=o=>{if(!o||o<=0)return"已结束";const t=Math.floor(o/60),s=o%60;return t>0?`${t}小时${s}分钟`:`${s}分钟`},B=()=>{x.value=!0},ue=o=>{L.value=o,r.value=!0},de=async o=>{const t=G.value.filter(k=>k.claudeAccountId===o.id||k.geminiAccountId===o.id).length;if(t>0){h(`无法删除此账号,有 ${t} 个API Key绑定到此账号,请先解绑所有API Key`,"error");return}if(await $("删除账户",`确定要删除账户 "${o.name}" 吗?
+`))||"",userAgent:o.userAgent||"",rateLimitDuration:o.rateLimitDuration||60},o.accountType==="group"&&c().then(()=>{u.value.forEach(k=>{V.get(`/admin/account-groups/${k.id}/members`).then(D=>{(D.data||[]).some(H=>H.id===o.id)&&(l.value.groupId=k.id)}).catch(()=>{})})})}},{immediate:!0}),(o,t)=>(a(),le(Ae,{to:"body"},[G.value?(a(),n("div",Vs,[e("div",js,[e("div",Ss,[e("div",_s,[t[48]||(t[48]=e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-user-circle text-white text-sm sm:text-base"})],-1)),e("h3",Ms,f(m.value?"编辑账户":"添加账户"),1)]),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:t[0]||(t[0]=s=>o.$emit("close"))},t[49]||(t[49]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),!m.value&&l.value.addType==="oauth"?(a(),n("div",Gs,[e("div",Ks,[e("div",Rs,[e("div",{class:K(["w-6 h-6 sm:w-8 sm:h-8 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold",S.value>=1?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 1 ",2),t[50]||(t[50]=e("span",{class:"ml-1.5 sm:ml-2 text-xs sm:text-sm font-medium text-gray-700"},"基本信息",-1))]),t[52]||(t[52]=e("div",{class:"w-4 sm:w-8 h-0.5 bg-gray-300"},null,-1)),e("div",Ls,[e("div",{class:K(["w-6 h-6 sm:w-8 sm:h-8 rounded-full flex items-center justify-center text-xs sm:text-sm font-semibold",S.value>=2?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 2 ",2),t[51]||(t[51]=e("span",{class:"ml-1.5 sm:ml-2 text-xs sm:text-sm font-medium text-gray-700"},"授权认证",-1))])])])):y("",!0),S.value===1&&!m.value?(a(),n("div",Ps,[e("div",Ds,[m.value?y("",!0):(a(),n("div",zs,[t[56]||(t[56]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"平台",-1)),e("div",Es,[e("label",Os,[g(e("input",{"onUpdate:modelValue":t[1]||(t[1]=s=>l.value.platform=s),type:"radio",value:"claude",class:"mr-2"},null,512),[[X,l.value.platform]]),t[53]||(t[53]=e("span",{class:"text-sm text-gray-700"},"Claude",-1))]),e("label",Ws,[g(e("input",{"onUpdate:modelValue":t[2]||(t[2]=s=>l.value.platform=s),type:"radio",value:"claude-console",class:"mr-2"},null,512),[[X,l.value.platform]]),t[54]||(t[54]=e("span",{class:"text-sm text-gray-700"},"Claude Console",-1))]),e("label",qs,[g(e("input",{"onUpdate:modelValue":t[3]||(t[3]=s=>l.value.platform=s),type:"radio",value:"gemini",class:"mr-2"},null,512),[[X,l.value.platform]]),t[55]||(t[55]=e("span",{class:"text-sm text-gray-700"},"Gemini",-1))])])])),!m.value&&l.value.platform!=="claude-console"?(a(),n("div",Bs,[t[59]||(t[59]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"添加方式",-1)),e("div",Fs,[e("label",Ns,[g(e("input",{"onUpdate:modelValue":t[4]||(t[4]=s=>l.value.addType=s),type:"radio",value:"oauth",class:"mr-2"},null,512),[[X,l.value.addType]]),t[57]||(t[57]=e("span",{class:"text-sm text-gray-700"},"OAuth 授权 (推荐)",-1))]),e("label",Hs,[g(e("input",{"onUpdate:modelValue":t[5]||(t[5]=s=>l.value.addType=s),type:"radio",value:"manual",class:"mr-2"},null,512),[[X,l.value.addType]]),t[58]||(t[58]=e("span",{class:"text-sm text-gray-700"},"手动输入 Access Token",-1))])])])):y("",!0),e("div",null,[t[60]||(t[60]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[6]||(t[6]=s=>l.value.name=s),type:"text",required:"",class:K(["form-input w-full",{"border-red-500":x.value.name}]),placeholder:"为账户设置一个易识别的名称"},null,2),[[_,l.value.name]]),x.value.name?(a(),n("p",Js,f(x.value.name),1)):y("",!0)]),e("div",null,[t[61]||(t[61]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[7]||(t[7]=s=>l.value.description=s),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[_,l.value.description]])]),e("div",null,[t[65]||(t[65]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",Ys,[e("label",Qs,[g(e("input",{"onUpdate:modelValue":t[8]||(t[8]=s=>l.value.accountType=s),type:"radio",value:"shared",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[62]||(t[62]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",Xs,[g(e("input",{"onUpdate:modelValue":t[9]||(t[9]=s=>l.value.accountType=s),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[63]||(t[63]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))]),e("label",Zs,[g(e("input",{"onUpdate:modelValue":t[10]||(t[10]=s=>l.value.accountType=s),type:"radio",value:"group",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[64]||(t[64]=e("span",{class:"text-sm text-gray-700"},"分组调度",-1))])]),t[66]||(t[66]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用;分组调度:加入分组供分组内调度 ",-1))]),l.value.accountType==="group"?(a(),n("div",el,[t[69]||(t[69]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"选择分组 *",-1)),e("div",tl,[g(e("select",{"onUpdate:modelValue":t[11]||(t[11]=s=>l.value.groupId=s),class:"form-input flex-1",required:""},[t[67]||(t[67]=e("option",{value:""},"请选择分组",-1)),(a(!0),n(re,null,ie(oe.value,s=>(a(),n("option",{key:s.id,value:s.id},f(s.name)+" ("+f(s.memberCount||0)+" 个成员) ",9,sl))),128)),t[68]||(t[68]=e("option",{value:"__new__"},"+ 新建分组",-1))],512),[[me,l.value.groupId]]),e("button",{type:"button",class:"px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",onClick:p},[e("i",{class:K(["fas fa-sync-alt",{"animate-spin":A.value}])},null,2)])])])):y("",!0),l.value.platform==="gemini"?(a(),n("div",ll,[t[70]||(t[70]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[12]||(t[12]=s=>l.value.projectId=s),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[_,l.value.projectId]]),t[71]||(t[71]=e("div",{class:"mt-2 p-3 bg-yellow-50 border border-yellow-200 rounded-lg"},[e("div",{class:"flex items-start gap-2"},[e("i",{class:"fas fa-info-circle text-yellow-600 mt-0.5"}),e("div",{class:"text-xs text-yellow-700"},[e("p",{class:"font-medium mb-1"}," Google Cloud/Workspace 账号需要提供项目编号 "),e("p",null,"某些 Google 账号(特别是绑定了 Google Cloud 的账号)会被识别为 Workspace 账号,需要提供额外的项目编号。"),e("div",{class:"mt-2 p-2 bg-white rounded border border-yellow-300"},[e("p",{class:"font-medium mb-1"}," 如何获取项目编号: "),e("ol",{class:"list-decimal list-inside space-y-1 ml-2"},[e("li",null,[$(" 访问 "),e("a",{href:"https://console.cloud.google.com/welcome",target:"_blank",class:"text-blue-600 hover:underline font-medium"},"Google Cloud Console")]),e("li",null,[$("复制"),e("span",{class:"font-semibold text-red-600"},"项目编号(Project Number)"),$(",通常是12位纯数字")]),e("li",{class:"text-red-600"}," ⚠️ 注意:不要复制项目ID(Project ID),要复制项目编号! ")])]),e("p",{class:"mt-2"},[e("strong",null,"提示:"),$("如果您的账号是普通个人账号(未绑定 Google Cloud),请留空此字段。 ")])])])],-1))])):y("",!0),l.value.platform==="claude-console"&&!m.value?(a(),n("div",ol,[e("div",null,[t[72]||(t[72]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL *",-1)),g(e("input",{"onUpdate:modelValue":t[13]||(t[13]=s=>l.value.apiUrl=s),type:"text",required:"",class:K(["form-input w-full",{"border-red-500":x.value.apiUrl}]),placeholder:"例如:https://api.example.com"},null,2),[[_,l.value.apiUrl]]),x.value.apiUrl?(a(),n("p",al,f(x.value.apiUrl),1)):y("",!0)]),e("div",null,[t[73]||(t[73]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key *",-1)),g(e("input",{"onUpdate:modelValue":t[14]||(t[14]=s=>l.value.apiKey=s),type:"password",required:"",class:K(["form-input w-full",{"border-red-500":x.value.apiKey}]),placeholder:"请输入API Key"},null,2),[[_,l.value.apiKey]]),x.value.apiKey?(a(),n("p",nl,f(x.value.apiKey),1)):y("",!0)]),e("div",null,[t[74]||(t[74]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"支持的模型 (可选)--注意,ClaudeCode必须加上hiku模型!",-1)),e("div",rl,[e("button",{type:"button",class:"px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors",onClick:t[15]||(t[15]=s=>F("claude-sonnet-4-20250514"))}," + claude-sonnet-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[16]||(t[16]=s=>F("claude-opus-4-20250514"))}," + claude-opus-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[17]||(t[17]=s=>F("claude-3-5-haiku-20241022"))}," + claude-3-5-haiku-20241022 ")]),g(e("textarea",{"onUpdate:modelValue":t[18]||(t[18]=s=>l.value.supportedModels=s),rows:"3",class:"form-input w-full resize-none",placeholder:"每行一个模型,留空表示支持所有模型。特别注意,ClaudeCode必须加上hiku模型!"},null,512),[[_,l.value.supportedModels]]),t[75]||(t[75]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示支持所有模型。如果指定模型,请求中的模型不在列表内将不会调度到此账号 ",-1))]),e("div",null,[t[76]||(t[76]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[19]||(t[19]=s=>l.value.userAgent=s),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[_,l.value.userAgent]])]),e("div",null,[t[77]||(t[77]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[20]||(t[20]=s=>l.value.rateLimitDuration=s),type:"number",min:"1",class:"form-input w-full",placeholder:"默认60分钟"},null,512),[[_,l.value.rateLimitDuration,void 0,{number:!0}]]),t[78]||(t[78]=e("p",{class:"text-xs text-gray-500 mt-1"}," 当账号返回429错误时,暂停调度的时间(分钟) ",-1))])])):y("",!0),l.value.platform==="claude"||l.value.platform==="claude-console"?(a(),n("div",il,[t[79]||(t[79]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[21]||(t[21]=s=>l.value.priority=s),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高,默认50"},null,512),[[_,l.value.priority,void 0,{number:!0}]]),t[80]||(t[80]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):y("",!0),l.value.addType==="manual"&&l.value.platform!=="claude-console"?(a(),n("div",ul,[e("div",dl,[t[86]||(t[86]=e("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"},[e("i",{class:"fas fa-info text-white text-sm"})],-1)),e("div",null,[t[84]||(t[84]=e("h5",{class:"font-semibold text-blue-900 mb-2"}," 手动输入 Token ",-1)),l.value.platform==="claude"?(a(),n("p",pl," 请输入有效的 Claude Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):l.value.platform==="gemini"?(a(),n("p",ml," 请输入有效的 Gemini Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):y("",!0),e("div",cl,[t[83]||(t[83]=e("p",{class:"text-sm text-blue-900 font-medium mb-1"},[e("i",{class:"fas fa-folder-open mr-1"}),$(" 获取 Access Token 的方法: ")],-1)),l.value.platform==="claude"?(a(),n("p",fl,t[81]||(t[81]=[$(" 请从已登录 Claude Code 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.claude/.credentials.json",-1),$(" 文件中的凭证, 请勿使用 Claude 官网 API Keys 页面的密钥。 ",-1)]))):l.value.platform==="gemini"?(a(),n("p",xl,t[82]||(t[82]=[$(" 请从已登录 Gemini CLI 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.config/gemini/credentials.json",-1),$(" 文件中的凭证。 ",-1)]))):y("",!0)]),t[85]||(t[85]=e("p",{class:"text-xs text-blue-600"}," 💡 如果未填写 Refresh Token,Token 过期后需要手动更新。 ",-1))])]),e("div",null,[t[87]||(t[87]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Access Token *",-1)),g(e("textarea",{"onUpdate:modelValue":t[22]||(t[22]=s=>l.value.accessToken=s),rows:"4",required:"",class:K(["form-input w-full resize-none font-mono text-xs",{"border-red-500":x.value.accessToken}]),placeholder:"请输入 Access Token..."},null,2),[[_,l.value.accessToken]]),x.value.accessToken?(a(),n("p",vl,f(x.value.accessToken),1)):y("",!0)]),e("div",null,[t[88]||(t[88]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Refresh Token (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[23]||(t[23]=s=>l.value.refreshToken=s),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"请输入 Refresh Token..."},null,512),[[_,l.value.refreshToken]])])])):y("",!0),$e(Ge,{modelValue:l.value.proxy,"onUpdate:modelValue":t[24]||(t[24]=s=>l.value.proxy=s)},null,8,["modelValue"]),e("div",gl,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:t[25]||(t[25]=s=>o.$emit("close"))}," 取消 "),l.value.addType==="oauth"&&l.value.platform!=="claude-console"?(a(),n("button",{key:0,type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:L}," 下一步 ",8,yl)):(a(),n("button",{key:1,type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:W},[R.value?(a(),n("div",wl)):y("",!0),$(" "+f(R.value?"创建中...":"创建"),1)],8,bl))])])])):y("",!0),S.value===2&&l.value.addType==="oauth"?(a(),le(Et,{key:2,platform:l.value.platform,proxy:l.value.proxy,onSuccess:B,onBack:t[26]||(t[26]=s=>S.value=1)},null,8,["platform","proxy"])):y("",!0),m.value?(a(),n("div",kl,[e("div",null,[t[89]||(t[89]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[27]||(t[27]=s=>l.value.name=s),type:"text",required:"",class:"form-input w-full",placeholder:"为账户设置一个易识别的名称"},null,512),[[_,l.value.name]])]),e("div",null,[t[90]||(t[90]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[28]||(t[28]=s=>l.value.description=s),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[_,l.value.description]])]),e("div",null,[t[94]||(t[94]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",hl,[e("label",$l,[g(e("input",{"onUpdate:modelValue":t[29]||(t[29]=s=>l.value.accountType=s),type:"radio",value:"shared",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[91]||(t[91]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",Cl,[g(e("input",{"onUpdate:modelValue":t[30]||(t[30]=s=>l.value.accountType=s),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[92]||(t[92]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))]),e("label",Tl,[g(e("input",{"onUpdate:modelValue":t[31]||(t[31]=s=>l.value.accountType=s),type:"radio",value:"group",class:"mr-2"},null,512),[[X,l.value.accountType]]),t[93]||(t[93]=e("span",{class:"text-sm text-gray-700"},"分组调度",-1))])]),t[95]||(t[95]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用;分组调度:加入分组供分组内调度 ",-1))]),l.value.accountType==="group"?(a(),n("div",Al,[t[98]||(t[98]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"选择分组 *",-1)),e("div",Ul,[g(e("select",{"onUpdate:modelValue":t[32]||(t[32]=s=>l.value.groupId=s),class:"form-input flex-1",required:""},[t[96]||(t[96]=e("option",{value:""},"请选择分组",-1)),(a(!0),n(re,null,ie(oe.value,s=>(a(),n("option",{key:s.id,value:s.id},f(s.name)+" ("+f(s.memberCount||0)+" 个成员) ",9,Il))),128)),t[97]||(t[97]=e("option",{value:"__new__"},"+ 新建分组",-1))],512),[[me,l.value.groupId]]),e("button",{type:"button",class:"px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",onClick:p},[e("i",{class:K(["fas fa-sync-alt",{"animate-spin":A.value}])},null,2)])])])):y("",!0),l.value.platform==="gemini"?(a(),n("div",Vl,[t[99]||(t[99]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[33]||(t[33]=s=>l.value.projectId=s),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[_,l.value.projectId]]),t[100]||(t[100]=e("p",{class:"text-xs text-gray-500 mt-2"}," Google Cloud/Workspace 账号可能需要提供项目编号 ",-1))])):y("",!0),l.value.platform==="claude"||l.value.platform==="claude-console"?(a(),n("div",jl,[t[101]||(t[101]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[34]||(t[34]=s=>l.value.priority=s),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高"},null,512),[[_,l.value.priority,void 0,{number:!0}]]),t[102]||(t[102]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):y("",!0),l.value.platform==="claude-console"?(a(),n("div",Sl,[e("div",null,[t[103]||(t[103]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL",-1)),g(e("input",{"onUpdate:modelValue":t[35]||(t[35]=s=>l.value.apiUrl=s),type:"text",required:"",class:"form-input w-full",placeholder:"例如:https://api.example.com"},null,512),[[_,l.value.apiUrl]])]),e("div",null,[t[104]||(t[104]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key",-1)),g(e("input",{"onUpdate:modelValue":t[36]||(t[36]=s=>l.value.apiKey=s),type:"password",class:"form-input w-full",placeholder:"留空表示不更新"},null,512),[[_,l.value.apiKey]]),t[105]||(t[105]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示不更新 API Key ",-1))]),e("div",null,[t[106]||(t[106]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"支持的模型 (可选)",-1)),e("div",_l,[e("button",{type:"button",class:"px-3 py-1 text-xs bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors",onClick:t[37]||(t[37]=s=>F("claude-sonnet-4-20250514"))}," + claude-sonnet-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[38]||(t[38]=s=>F("claude-opus-4-20250514"))}," + claude-opus-4-20250514 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-purple-200 transition-colors",onClick:t[39]||(t[39]=s=>F("claude-3-5-haiku-20241022"))}," + claude-3-5-haiku-20241022 ")]),g(e("textarea",{"onUpdate:modelValue":t[40]||(t[40]=s=>l.value.supportedModels=s),rows:"3",class:"form-input w-full resize-none",placeholder:"每行一个模型,留空表示支持所有模型。特别注意,ClaudeCode必须加上hiku模型!"},null,512),[[_,l.value.supportedModels]])]),e("div",null,[t[107]||(t[107]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[41]||(t[41]=s=>l.value.userAgent=s),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[_,l.value.userAgent]])]),e("div",null,[t[108]||(t[108]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[42]||(t[42]=s=>l.value.rateLimitDuration=s),type:"number",min:"1",class:"form-input w-full"},null,512),[[_,l.value.rateLimitDuration,void 0,{number:!0}]])])])):y("",!0),l.value.platform!=="claude-console"?(a(),n("div",Ml,[t[111]||(t[111]=e("div",{class:"flex items-start gap-3 mb-4"},[e("div",{class:"w-8 h-8 bg-amber-500 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"},[e("i",{class:"fas fa-key text-white text-sm"})]),e("div",null,[e("h5",{class:"font-semibold text-amber-900 mb-2"}," 更新 Token "),e("p",{class:"text-sm text-amber-800 mb-2"}," 可以更新 Access Token 和 Refresh Token。为了安全起见,不会显示当前的 Token 值。 "),e("p",{class:"text-xs text-amber-600"}," 💡 留空表示不更新该字段。 ")])],-1)),e("div",Gl,[e("div",null,[t[109]||(t[109]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Access Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[43]||(t[43]=s=>l.value.accessToken=s),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[_,l.value.accessToken]])]),e("div",null,[t[110]||(t[110]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Refresh Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[44]||(t[44]=s=>l.value.refreshToken=s),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[_,l.value.refreshToken]])])])])):y("",!0),$e(Ge,{modelValue:l.value.proxy,"onUpdate:modelValue":t[45]||(t[45]=s=>l.value.proxy=s)},null,8,["modelValue"]),e("div",Kl,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:t[46]||(t[46]=s=>o.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:j},[R.value?(a(),n("div",Ll)):y("",!0),$(" "+f(R.value?"更新中...":"更新"),1)],8,Rl)])])):y("",!0)])])):y("",!0),$e(De,{show:Y(M),title:Y(I).title,message:Y(I).message,"confirm-text":Y(I).confirmText,"cancel-text":Y(I).cancelText,onConfirm:Y(w),onCancel:Y(v)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"]),Z.value?(a(),le(Is,{key:1,onClose:t[47]||(t[47]=s=>Z.value=!1),onRefresh:U})):y("",!0)]))}},Pl={class:"accounts-container"},Dl={class:"card p-4 sm:p-6"},zl={class:"flex flex-col gap-4 mb-4 sm:mb-6"},El={class:"flex flex-col sm:flex-row gap-2 sm:items-center sm:justify-between"},Ol={class:"flex flex-col sm:flex-row gap-2"},Wl=["value"],ql={key:0,class:"text-center py-12"},Bl={key:1,class:"text-center py-12"},Fl={key:2,class:"hidden md:block table-container"},Nl={class:"w-full table-fixed"},Hl={class:"bg-gray-50/80 backdrop-blur-sm"},Jl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Yl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Ql={key:1,class:"fas fa-sort ml-1 text-gray-400"},Xl={key:1,class:"fas fa-sort ml-1 text-gray-400"},Zl={class:"divide-y divide-gray-200/50"},eo={class:"px-3 py-4"},to={class:"flex items-center"},so={class:"min-w-0"},lo={class:"flex items-center gap-2"},oo=["title"],ao={key:0,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800"},no={key:1,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"},ro={key:2,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"},io=["title"],uo=["title"],po={class:"px-3 py-4"},mo={class:"flex items-center gap-1"},co={key:0,class:"flex items-center gap-1.5 px-2.5 py-1 bg-gradient-to-r from-yellow-100 to-amber-100 rounded-lg border border-yellow-200"},fo={class:"text-xs font-medium text-yellow-700"},xo={key:1,class:"flex items-center gap-1.5 px-2.5 py-1 bg-gradient-to-r from-purple-100 to-pink-100 rounded-lg border border-purple-200"},vo={key:2,class:"flex items-center gap-1.5 px-2.5 py-1 bg-gradient-to-r from-indigo-100 to-blue-100 rounded-lg border border-indigo-200"},go={class:"text-xs font-medium text-indigo-700"},yo={class:"px-3 py-4 whitespace-nowrap"},bo={class:"flex flex-col gap-1"},wo={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"},ko={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-gray-100 text-gray-700"},ho=["title"],$o={key:3,class:"text-xs text-gray-500"},Co={class:"px-3 py-4 whitespace-nowrap"},To={key:0,class:"flex items-center gap-2"},Ao={class:"w-16 bg-gray-200 rounded-full h-2"},Uo={class:"text-xs text-gray-700 font-medium min-w-[20px]"},Io={key:1,class:"text-gray-400 text-sm"},Vo={class:"px-3 py-4 text-sm text-gray-600"},jo=["title"],So={key:1,class:"text-gray-400"},_o={class:"px-3 py-4 whitespace-nowrap text-sm"},Mo={key:0,class:"space-y-1"},Go={class:"flex items-center gap-2"},Ko={class:"text-sm font-medium text-gray-900"},Ro={class:"flex items-center gap-2"},Lo={class:"text-xs text-gray-600"},Po={key:0,class:"text-xs text-gray-500"},Do={key:1,class:"text-gray-400 text-xs"},zo={class:"px-3 py-4 whitespace-nowrap"},Eo={key:0,class:"space-y-2"},Oo={class:"flex items-center gap-2"},Wo={class:"w-24 bg-gray-200 rounded-full h-2"},qo={class:"text-xs text-gray-700 font-medium min-w-[32px]"},Bo={class:"text-xs text-gray-600"},Fo={key:0,class:"text-indigo-600 font-medium"},No={key:1,class:"text-gray-400 text-sm"},Ho={key:2,class:"text-gray-400 text-sm"},Jo={class:"px-3 py-4 whitespace-nowrap text-sm text-gray-600"},Yo={class:"px-3 py-4 whitespace-nowrap text-sm font-medium"},Qo={class:"flex items-center gap-1 flex-wrap"},Xo=["disabled","title","onClick"],Zo=["disabled","title","onClick"],ea={class:"ml-1"},ta=["onClick"],sa=["onClick"],la={key:3,class:"md:hidden space-y-3"},oa={class:"flex items-start justify-between mb-3"},aa={class:"flex items-center gap-3"},na={class:"text-sm font-semibold text-gray-900"},ra={class:"flex items-center gap-2 mt-0.5"},ia={class:"text-xs text-gray-500"},ua={class:"text-xs text-gray-500"},da={class:"grid grid-cols-2 gap-3 mb-3"},pa={class:"text-sm font-semibold text-gray-900"},ma={class:"text-xs text-gray-500 mt-0.5"},ca={class:"text-sm font-semibold text-gray-900"},fa={class:"text-xs text-gray-500 mt-0.5"},xa={class:"space-y-2 mb-3"},va={key:0,class:"flex items-center justify-between text-xs"},ga={class:"flex items-center gap-2"},ya={class:"w-20 h-1.5 bg-gray-200 rounded-full overflow-hidden"},ba={class:"flex items-center justify-between text-xs"},wa={class:"text-gray-700"},ka={key:1,class:"flex items-center justify-between text-xs"},ha={class:"text-gray-700"},$a={class:"flex items-center justify-between text-xs"},Ca={class:"text-gray-700 font-medium"},Ta={class:"flex gap-2 mt-3 pt-3 border-t border-gray-100"},Aa=["disabled","onClick"],Ua=["onClick","disabled"],Ia=["onClick"],Va=["onClick"],ja={__name:"AccountsView",setup(P){const{showConfirmModal:O,confirmOptions:d,showConfirm:C,handleConfirm:i,handleCancel:M}=Le(),I=b([]),T=b(!1),w=b("name"),v=b(""),m=b("asc"),G=b([]),S=b({}),R=b([]),q=b("all"),l=b([]),x=b(!1),r=b(!1),L=b(null),B=ne(()=>{const o=l.value.length>0?l.value:I.value;return v.value?[...o].sort((s,k)=>{var H,Q,J,z,ee,te,ae,Ue,Ie,Ve,je,Se;let D=s[v.value],N=k[v.value];return v.value==="dailyTokens"?(D=((Q=(H=s.usage)==null?void 0:H.daily)==null?void 0:Q.allTokens)||0,N=((z=(J=k.usage)==null?void 0:J.daily)==null?void 0:z.allTokens)||0):v.value==="dailyRequests"?(D=((te=(ee=s.usage)==null?void 0:ee.daily)==null?void 0:te.requests)||0,N=((Ue=(ae=k.usage)==null?void 0:ae.daily)==null?void 0:Ue.requests)||0):v.value==="totalTokens"&&(D=((Ve=(Ie=s.usage)==null?void 0:Ie.total)==null?void 0:Ve.allTokens)||0,N=((Se=(je=k.usage)==null?void 0:je.total)==null?void 0:Se.allTokens)||0),v.value==="lastUsed"&&(D=s.lastUsedAt?new Date(s.lastUsedAt).getTime():0,N=k.lastUsedAt?new Date(k.lastUsedAt).getTime():0),v.value==="status"&&(D=s.isActive?1:0,N=k.isActive?1:0),DN?m.value==="asc"?1:-1:0}):o}),W=async()=>{T.value=!0;try{const[o,t,s,k,D]=await Promise.all([V.get("/admin/claude-accounts"),V.get("/admin/claude-console-accounts"),V.get("/admin/gemini-accounts"),V.get("/admin/api-keys"),V.get("/admin/account-groups")]);k.success&&(G.value=k.data||[]),D.success&&(R.value=D.data||[]);const N=new Map,H=new Map;for(const J of R.value){N.set(J.id,J);try{const z=await V.get(`/admin/account-groups/${J.id}/members`);z.success&&(z.data||[]).forEach(te=>{H.set(te.id,J)})}catch(z){console.error(`Failed to load members for group ${J.id}:`,z)}}const Q=[];if(o.success){const J=(o.data||[]).map(z=>{const ee=G.value.filter(ae=>ae.claudeAccountId===z.id).length,te=H.get(z.id)||null;return{...z,platform:"claude",boundApiKeysCount:ee,groupInfo:te}});Q.push(...J)}if(t.success){const J=(t.data||[]).map(z=>{const ee=H.get(z.id)||null;return{...z,platform:"claude-console",boundApiKeysCount:0,groupInfo:ee}});Q.push(...J)}if(s.success){const J=(s.data||[]).map(z=>{const ee=G.value.filter(ae=>ae.geminiAccountId===z.id).length,te=H.get(z.id)||null;return{...z,platform:"gemini",boundApiKeysCount:ee,groupInfo:te}});Q.push(...J)}I.value=Q,oe()}catch{h("加载账户失败","error")}finally{T.value=!1}},j=o=>{o&&(v.value===o?m.value=m.value==="asc"?"desc":"asc":(v.value=o,m.value="asc"))},u=o=>{if(o==null)return"0";const t=Number(o);return t>=1e6?Math.floor(t/1e6).toLocaleString()+"M":t.toLocaleString()},A=o=>{if(!o)return"从未使用";const t=new Date(o),k=new Date-t;return k<6e4?"刚刚":k<36e5?`${Math.floor(k/6e4)} 分钟前`:k<864e5?`${Math.floor(k/36e5)} 小时前`:k<6048e5?`${Math.floor(k/864e5)} 天前`:t.toLocaleDateString("zh-CN")},Z=async()=>{try{const o=await V.get("/admin/api-keys");o.success&&(G.value=o.data)}catch(o){console.error("Failed to load API keys:",o)}},oe=()=>{q.value==="all"?l.value=I.value:q.value==="ungrouped"?l.value=I.value.filter(o=>!o.groupInfo):l.value=I.value.filter(o=>o.groupInfo&&o.groupInfo.id===q.value)},c=o=>{if(!o||!o.host||!o.port)return null;const t=o.type==="socks5"?"S5":o.type.toUpperCase();let s=o.host;s.length>15&&(s=s.substring(0,12)+"...");let k=`${t}://${s}:${o.port}`;return o.username&&(k=`${t}://***@${s}:${o.port}`),k},p=(o,t)=>{if(!o||!t)return"--";const s=new Date(o),k=new Date(t),D=s.getHours().toString().padStart(2,"0"),N=s.getMinutes().toString().padStart(2,"0"),H=k.getHours().toString().padStart(2,"0"),Q=k.getMinutes().toString().padStart(2,"0");return`${D}:${N} - ${H}:${Q}`},U=o=>{if(!o||o<=0)return"已结束";const t=Math.floor(o/60),s=o%60;return t>0?`${t}小时${s}分钟`:`${s}分钟`},F=()=>{x.value=!0},ue=o=>{L.value=o,r.value=!0},de=async o=>{const t=G.value.filter(k=>k.claudeAccountId===o.id||k.geminiAccountId===o.id).length;if(t>0){h(`无法删除此账号,有 ${t} 个API Key绑定到此账号,请先解绑所有API Key`,"error");return}if(await C("删除账户",`确定要删除账户 "${o.name}" 吗?
-此操作不可恢复。`,"删除","取消"))try{let k;o.platform==="claude"?k=`/admin/claude-accounts/${o.id}`:o.platform==="claude-console"?k=`/admin/claude-console-accounts/${o.id}`:k=`/admin/gemini-accounts/${o.id}`;const D=await V.delete(k);D.success?(h("账户已删除","success"),W()):h(D.message||"删除失败","error")}catch{h("删除失败","error")}},fe=async o=>{if(!o.isRefreshing)try{o.isRefreshing=!0;const t=await V.post(`/admin/claude-accounts/${o.id}/refresh`);t.success?(h("Token刷新成功","success"),W()):h(t.message||"Token刷新失败","error")}catch{h("Token刷新失败","error")}finally{o.isRefreshing=!1}},pe=async o=>{if(!o.isTogglingSchedulable)try{o.isTogglingSchedulable=!0;let t;if(o.platform==="claude")t=`/admin/claude-accounts/${o.id}/toggle-schedulable`;else if(o.platform==="claude-console")t=`/admin/claude-console-accounts/${o.id}/toggle-schedulable`;else{h("Gemini账户暂不支持调度控制","warning");return}const s=await V.put(t);s.success?(o.schedulable=s.schedulable,h(s.schedulable?"已启用调度":"已禁用调度","success")):h(s.message||"操作失败","error")}catch{h("切换调度状态失败","error")}finally{o.isTogglingSchedulable=!1}},xe=()=>{x.value=!1,h("账户创建成功","success"),W()},ve=()=>{r.value=!1,h("账户更新成功","success"),W()},ge=o=>o.status==="blocked"?"已封锁":o.isRateLimited||o.status==="rate_limited"||o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?"限流中":o.status==="error"||!o.isActive?"错误":o.schedulable===!1?"已暂停":"正常",ye=o=>o.status==="blocked"?"bg-red-100 text-red-800":o.isRateLimited||o.status==="rate_limited"||o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?"bg-orange-100 text-orange-800":o.status==="error"||!o.isActive?"bg-red-100 text-red-800":o.schedulable===!1?"bg-gray-100 text-gray-800":"bg-green-100 text-green-800",be=o=>o.status==="blocked"?"bg-red-500":o.isRateLimited||o.status==="rate_limited"||o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?"bg-orange-500":o.status==="error"||!o.isActive?"bg-red-500":o.schedulable===!1?"bg-gray-500":"bg-green-500",we=o=>{if(!o.sessionWindow)return 100;const{remaining:t,total:s}=o.sessionWindow;return!s||s===0?100:Math.round(t/s*100)},ke=o=>A(o),he=async o=>{if(!S.value[o.id])try{S.value[o.id]=!0;const t=await V.post(`/admin/claude-accounts/${o.id}/refresh`);t.success?(h("Token刷新成功","success"),W()):h(t.message||"Token刷新失败","error")}catch{h("Token刷新失败","error")}finally{S.value[o.id]=!1}};return E(w,o=>{const t={name:"name",dailyTokens:"dailyTokens",dailyRequests:"dailyRequests",totalTokens:"totalTokens",lastUsed:"lastUsed"};t[o]&&j(t[o])}),Ke(()=>{W(),Z()}),(o,t)=>(a(),n("div",Pl,[e("div",Dl,[e("div",zl,[t[13]||(t[13]=e("div",null,[e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900 mb-1 sm:mb-2"}," 账户管理 "),e("p",{class:"text-sm sm:text-base text-gray-600"}," 管理您的 Claude 和 Gemini 账户及代理配置 ")],-1)),e("div",El,[e("div",Ol,[g(e("select",{"onUpdate:modelValue":t[0]||(t[0]=s=>w.value=s),class:"form-input px-3 py-2 text-sm w-full sm:w-auto",onChange:t[1]||(t[1]=s=>j())},t[9]||(t[9]=[me('',5)]),544),[[ce,w.value]]),g(e("select",{"onUpdate:modelValue":t[2]||(t[2]=s=>q.value=s),class:"form-input px-3 py-2 text-sm w-full sm:w-auto",onChange:oe},[t[10]||(t[10]=e("option",{value:"all"},"所有账户",-1)),t[11]||(t[11]=e("option",{value:"ungrouped"},"未分组账户",-1)),(a(!0),n(re,null,ie(K.value,s=>(a(),n("option",{key:s.id,value:s.id},f(s.name)+" ("+f(s.platform==="claude"?"Claude":"Gemini")+") ",9,Wl))),128))],544),[[ce,q.value]])]),e("button",{class:"btn btn-success px-4 sm:px-6 py-2 sm:py-3 flex items-center gap-2 w-full sm:w-auto justify-center",onClick:We(B,["stop"])},t[12]||(t[12]=[e("i",{class:"fas fa-plus"},null,-1),C("添加账户 ",-1)]))])]),T.value?(a(),n("div",ql,t[14]||(t[14]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"}," 正在加载账户... ",-1)]))):F.value.length===0?(a(),n("div",Fl,t[15]||(t[15]=[e("div",{class:"w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center"},[e("i",{class:"fas fa-user-circle text-gray-400 text-xl"})],-1),e("p",{class:"text-gray-500 text-lg"}," 暂无账户 ",-1),e("p",{class:"text-gray-400 text-sm mt-2"}," 点击上方按钮添加您的第一个账户 ",-1)]))):(a(),n("div",Bl,[e("table",Nl,[e("thead",Hl,[e("tr",null,[e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[22%] min-w-[180px]",onClick:t[3]||(t[3]=s=>j("name"))},[t[16]||(t[16]=C(" 名称 ",-1)),v.value==="name"?(a(),n("i",{key:0,class:R(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Jl))]),e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[15%] min-w-[120px]",onClick:t[4]||(t[4]=s=>j("platform"))},[t[17]||(t[17]=C(" 平台/类型 ",-1)),v.value==="platform"?(a(),n("i",{key:0,class:R(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Yl))]),e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[12%] min-w-[100px]",onClick:t[5]||(t[5]=s=>j("status"))},[t[18]||(t[18]=C(" 状态 ",-1)),v.value==="status"?(a(),n("i",{key:0,class:R(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Ql))]),e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[8%] min-w-[80px]",onClick:t[6]||(t[6]=s=>j("priority"))},[t[19]||(t[19]=C(" 优先级 ",-1)),v.value==="priority"?(a(),n("i",{key:0,class:R(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Xl))]),t[20]||(t[20]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[10%] min-w-[100px]"}," 代理 ",-1)),t[21]||(t[21]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[10%] min-w-[90px]"}," 今日使用 ",-1)),t[22]||(t[22]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[10%] min-w-[100px]"}," 会话窗口 ",-1)),t[23]||(t[23]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[8%] min-w-[80px]"}," 最后使用 ",-1)),t[24]||(t[24]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[15%] min-w-[180px]"}," 操作 ",-1))])]),e("tbody",Zl,[(a(!0),n(re,null,ie(F.value,s=>(a(),n("tr",{key:s.id,class:"table-row"},[e("td",eo,[e("div",to,[t[29]||(t[29]=e("div",{class:"w-8 h-8 bg-gradient-to-br from-green-500 to-green-600 rounded-lg flex items-center justify-center mr-2 flex-shrink-0"},[e("i",{class:"fas fa-user-circle text-white text-xs"})],-1)),e("div",so,[e("div",lo,[e("div",{class:"text-sm font-semibold text-gray-900 truncate",title:s.name},f(s.name),9,oo),s.accountType==="dedicated"?(a(),n("span",ao,t[25]||(t[25]=[e("i",{class:"fas fa-lock mr-1"},null,-1),C("专属 ",-1)]))):s.accountType==="group"?(a(),n("span",no,t[26]||(t[26]=[e("i",{class:"fas fa-layer-group mr-1"},null,-1),C("分组调度 ",-1)]))):(a(),n("span",ro,t[27]||(t[27]=[e("i",{class:"fas fa-share-alt mr-1"},null,-1),C("共享 ",-1)]))),s.groupInfo?(a(),n("span",{key:3,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 ml-1",title:`所属分组: ${s.groupInfo.name}`},[t[28]||(t[28]=e("i",{class:"fas fa-folder mr-1"},null,-1)),C(f(s.groupInfo.name),1)],8,io)):y("",!0)]),e("div",{class:"text-xs text-gray-500 truncate",title:s.id},f(s.id),9,uo)])])]),e("td",po,[e("div",mo,[s.platform==="gemini"?(a(),n("div",co,[t[30]||(t[30]=e("i",{class:"fas fa-robot text-yellow-700 text-xs"},null,-1)),t[31]||(t[31]=e("span",{class:"text-xs font-semibold text-yellow-800"},"Gemini",-1)),t[32]||(t[32]=e("span",{class:"w-px h-4 bg-yellow-300 mx-1"},null,-1)),e("span",fo,f(s.scopes&&s.scopes.length>0?"OAuth":"传统"),1)])):s.platform==="claude-console"?(a(),n("div",xo,t[33]||(t[33]=[e("i",{class:"fas fa-terminal text-purple-700 text-xs"},null,-1),e("span",{class:"text-xs font-semibold text-purple-800"},"Console",-1),e("span",{class:"w-px h-4 bg-purple-300 mx-1"},null,-1),e("span",{class:"text-xs font-medium text-purple-700"},"API Key",-1)]))):(a(),n("div",vo,[t[34]||(t[34]=e("i",{class:"fas fa-brain text-indigo-700 text-xs"},null,-1)),t[35]||(t[35]=e("span",{class:"text-xs font-semibold text-indigo-800"},"Claude",-1)),t[36]||(t[36]=e("span",{class:"w-px h-4 bg-indigo-300 mx-1"},null,-1)),e("span",go,f(s.scopes&&s.scopes.length>0?"OAuth":"传统"),1)]))])]),e("td",yo,[e("div",bo,[e("span",{class:R(["inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold",s.status==="blocked"?"bg-orange-100 text-orange-800":s.isActive?"bg-green-100 text-green-800":"bg-red-100 text-red-800"])},[e("div",{class:R(["w-2 h-2 rounded-full mr-2",s.status==="blocked"?"bg-orange-500":s.isActive?"bg-green-500":"bg-red-500"])},null,2),C(" "+f(s.status==="blocked"?"已封锁":s.isActive?"正常":"异常"),1)],2),s.rateLimitStatus&&s.rateLimitStatus.isRateLimited?(a(),n("span",wo,[t[37]||(t[37]=e("i",{class:"fas fa-exclamation-triangle mr-1"},null,-1)),C(" 限流中 ("+f(s.rateLimitStatus.minutesRemaining)+"分钟) ",1)])):y("",!0),s.schedulable===!1?(a(),n("span",ko,t[38]||(t[38]=[e("i",{class:"fas fa-pause-circle mr-1"},null,-1),C(" 不可调度 ",-1)]))):y("",!0),s.status==="blocked"&&s.errorMessage?(a(),n("span",{key:2,class:"text-xs text-gray-500 mt-1 max-w-xs truncate",title:s.errorMessage},f(s.errorMessage),9,ho)):y("",!0),s.accountType==="dedicated"?(a(),n("span",$o," 绑定: "+f(s.boundApiKeysCount||0)+" 个API Key ",1)):y("",!0)])]),e("td",Co,[s.platform==="claude"||s.platform==="claude-console"?(a(),n("div",To,[e("div",Ao,[e("div",{class:"bg-gradient-to-r from-green-500 to-blue-600 h-2 rounded-full transition-all duration-300",style:Te({width:101-(s.priority||50)+"%"})},null,4)]),e("span",Uo,f(s.priority||50),1)])):(a(),n("div",Io,t[39]||(t[39]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Vo,[c(s.proxy)?(a(),n("div",{key:0,class:"text-xs bg-blue-50 px-2 py-1 rounded font-mono break-all",title:c(s.proxy)},f(c(s.proxy)),9,jo)):(a(),n("div",So," 无代理 "))]),e("td",_o,[s.usage&&s.usage.daily?(a(),n("div",Mo,[e("div",Go,[t[40]||(t[40]=e("div",{class:"w-2 h-2 bg-green-500 rounded-full"},null,-1)),e("span",Ro,f(s.usage.daily.requests||0)+" 次",1)]),e("div",Ko,[t[41]||(t[41]=e("div",{class:"w-2 h-2 bg-blue-500 rounded-full"},null,-1)),e("span",Lo,f(u(s.usage.daily.allTokens||0))+" tokens",1)]),s.usage.averages&&s.usage.averages.rpm>0?(a(),n("div",Po," 平均 "+f(s.usage.averages.rpm.toFixed(2))+" RPM ",1)):y("",!0)])):(a(),n("div",Do," 暂无数据 "))]),e("td",zo,[s.platform==="claude"&&s.sessionWindow&&s.sessionWindow.hasActiveWindow?(a(),n("div",Eo,[e("div",Oo,[e("div",Wo,[e("div",{class:"bg-gradient-to-r from-blue-500 to-indigo-600 h-2 rounded-full transition-all duration-300",style:Te({width:s.sessionWindow.progress+"%"})},null,4)]),e("span",qo,f(s.sessionWindow.progress)+"% ",1)]),e("div",Fo,[e("div",null,f(p(s.sessionWindow.windowStart,s.sessionWindow.windowEnd)),1),s.sessionWindow.remainingTime>0?(a(),n("div",Bo," 剩余 "+f(U(s.sessionWindow.remainingTime)),1)):y("",!0)])])):s.platform==="claude"?(a(),n("div",No,t[42]||(t[42]=[e("i",{class:"fas fa-minus"},null,-1)]))):(a(),n("div",Ho,t[43]||(t[43]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Jo,f(A(s.lastUsedAt)),1),e("td",Yo,[e("div",Qo,[s.platform==="claude"&&s.scopes?(a(),n("button",{key:0,disabled:s.isRefreshing,class:R(["px-2.5 py-1 rounded text-xs font-medium transition-colors",s.isRefreshing?"bg-gray-100 text-gray-400 cursor-not-allowed":"bg-blue-100 text-blue-700 hover:bg-blue-200"]),title:s.isRefreshing?"刷新中...":"刷新Token",onClick:k=>fe(s)},[e("i",{class:R(["fas fa-sync-alt",s.isRefreshing?"animate-spin":""])},null,2),t[44]||(t[44]=e("span",{class:"ml-1"},"刷新",-1))],10,Xo)):y("",!0),e("button",{disabled:s.isTogglingSchedulable,class:R(["px-2.5 py-1 rounded text-xs font-medium transition-colors",s.isTogglingSchedulable?"bg-gray-100 text-gray-400 cursor-not-allowed":s.schedulable?"bg-green-100 text-green-700 hover:bg-green-200":"bg-gray-100 text-gray-700 hover:bg-gray-200"]),title:s.schedulable?"点击禁用调度":"点击启用调度",onClick:k=>pe(s)},[e("i",{class:R(["fas",s.schedulable?"fa-toggle-on":"fa-toggle-off"])},null,2),e("span",ea,f(s.schedulable?"调度":"停用"),1)],10,Zo),e("button",{class:"px-2.5 py-1 bg-blue-100 text-blue-700 rounded text-xs font-medium hover:bg-blue-200 transition-colors",title:"编辑账户",onClick:k=>ue(s)},t[45]||(t[45]=[e("i",{class:"fas fa-edit"},null,-1),e("span",{class:"ml-1"},"编辑",-1)]),8,ta),e("button",{class:"px-2.5 py-1 bg-red-100 text-red-700 rounded text-xs font-medium hover:bg-red-200 transition-colors",title:"删除账户",onClick:k=>de(s)},t[46]||(t[46]=[e("i",{class:"fas fa-trash"},null,-1),e("span",{class:"ml-1"},"删除",-1)]),8,sa)])])]))),128))])])])),!T.value&&F.value.length>0?(a(),n("div",la,[(a(!0),n(re,null,ie(F.value,s=>{var k,D,N,H;return a(),n("div",{key:s.id,class:"card p-4 hover:shadow-lg transition-shadow"},[e("div",oa,[e("div",aa,[e("div",{class:R(["w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0",s.platform==="claude"?"bg-gradient-to-br from-purple-500 to-purple-600":"bg-gradient-to-br from-blue-500 to-blue-600"])},[e("i",{class:R(["text-white text-sm",s.platform==="claude"?"fas fa-brain":"fas fa-robot"])},null,2)],2),e("div",null,[e("h4",na,f(s.name||s.email),1),e("div",ra,[e("span",ia,f(s.platform),1),t[47]||(t[47]=e("span",{class:"text-xs text-gray-400"},"|",-1)),e("span",ua,f(s.type),1)])])]),e("span",{class:R(["inline-flex items-center px-2 py-1 rounded-full text-xs font-semibold",ye(s)])},[e("div",{class:R(["w-1.5 h-1.5 rounded-full mr-1.5",be(s)])},null,2),C(" "+f(ge(s)),1)],2)]),e("div",da,[e("div",null,[t[48]||(t[48]=e("p",{class:"text-xs text-gray-500"}," 今日使用 ",-1)),e("p",pa,f(u(((k=s.usage)==null?void 0:k.dailyRequests)||0))+" 次 ",1),e("p",ma,f(u(((D=s.usage)==null?void 0:D.dailyTokens)||0))+" tokens ",1)]),e("div",null,[t[49]||(t[49]=e("p",{class:"text-xs text-gray-500"}," 总使用量 ",-1)),e("p",ca,f(u(((N=s.usage)==null?void 0:N.totalRequests)||0))+" 次 ",1),e("p",fa,f(u(((H=s.usage)==null?void 0:H.totalTokens)||0))+" tokens ",1)])]),e("div",xa,[s.sessionWindow?(a(),n("div",va,[t[50]||(t[50]=e("span",{class:"text-gray-500"},"会话窗口",-1)),e("div",ga,[e("span",{class:R(["font-medium",s.sessionWindow.remaining<=20?"text-orange-600":"text-gray-900"])},f(s.sessionWindow.remaining||0)+" / "+f(s.sessionWindow.total||0),3),e("div",ya,[e("div",{class:"h-full bg-gradient-to-r from-blue-500 to-blue-600 transition-all duration-300",style:Te({width:`${we(s)}%`})},null,4)])])])):y("",!0),e("div",ba,[t[51]||(t[51]=e("span",{class:"text-gray-500"},"最后使用",-1)),e("span",wa,f(s.lastUsedAt?ke(s.lastUsedAt):"从未使用"),1)]),s.proxyConfig&&s.proxyConfig.type!=="none"?(a(),n("div",ka,[t[52]||(t[52]=e("span",{class:"text-gray-500"},"代理",-1)),e("span",ha,f(s.proxyConfig.type.toUpperCase()),1)])):y("",!0),e("div",$a,[t[53]||(t[53]=e("span",{class:"text-gray-500"},"优先级",-1)),e("span",Ca,f(s.priority||0),1)])]),e("div",Ta,[s.platform==="claude"&&s.type==="oauth"?(a(),n("button",{key:0,class:"flex-1 px-3 py-2 text-xs text-blue-600 bg-blue-50 rounded-lg hover:bg-blue-100 transition-colors flex items-center justify-center gap-1",disabled:S.value[s.id],onClick:Q=>he(s)},[e("i",{class:R(["fas fa-sync-alt",{"animate-spin":S.value[s.id]}])},null,2),C(" "+f(S.value[s.id]?"刷新中":"刷新"),1)],8,Aa)):y("",!0),e("button",{class:R(["flex-1 px-3 py-2 text-xs rounded-lg transition-colors flex items-center justify-center gap-1",s.schedulable?"text-gray-600 bg-gray-50 hover:bg-gray-100":"text-green-600 bg-green-50 hover:bg-green-100"]),onClick:Q=>pe(s),disabled:s.isTogglingSchedulable},[e("i",{class:R(["fas",s.schedulable?"fa-pause":"fa-play"])},null,2),C(" "+f(s.schedulable?"暂停":"启用"),1)],10,Ua),e("button",{class:"flex-1 px-3 py-2 text-xs text-gray-600 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors",onClick:Q=>ue(s)},t[54]||(t[54]=[e("i",{class:"fas fa-edit mr-1"},null,-1),C(" 编辑 ",-1)]),8,Ia),e("button",{class:"px-3 py-2 text-xs text-red-600 bg-red-50 rounded-lg hover:bg-red-100 transition-colors",onClick:Q=>de(s)},t[55]||(t[55]=[e("i",{class:"fas fa-trash"},null,-1)]),8,Va)])])}),128))])):y("",!0)]),x.value?(a(),le(Re,{key:0,onClose:t[7]||(t[7]=s=>x.value=!1),onSuccess:xe})):y("",!0),r.value?(a(),le(Re,{key:1,account:L.value,onClose:t[8]||(t[8]=s=>r.value=!1),onSuccess:ve},null,8,["account"])):y("",!0),Ce(De,{show:Y(O),title:Y(d).title,message:Y(d).message,"confirm-text":Y(d).confirmText,"cancel-text":Y(d).cancelText,onConfirm:Y(i),onCancel:Y(M)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"])]))}},Ka=qe(ja,[["__scopeId","data-v-ab3ae7fd"]]);export{Ka as default};
+此操作不可恢复。`,"删除","取消"))try{let k;o.platform==="claude"?k=`/admin/claude-accounts/${o.id}`:o.platform==="claude-console"?k=`/admin/claude-console-accounts/${o.id}`:k=`/admin/gemini-accounts/${o.id}`;const D=await V.delete(k);D.success?(h("账户已删除","success"),W()):h(D.message||"删除失败","error")}catch{h("删除失败","error")}},ce=async o=>{if(!o.isRefreshing)try{o.isRefreshing=!0;const t=await V.post(`/admin/claude-accounts/${o.id}/refresh`);t.success?(h("Token刷新成功","success"),W()):h(t.message||"Token刷新失败","error")}catch{h("Token刷新失败","error")}finally{o.isRefreshing=!1}},pe=async o=>{if(!o.isTogglingSchedulable)try{o.isTogglingSchedulable=!0;let t;if(o.platform==="claude")t=`/admin/claude-accounts/${o.id}/toggle-schedulable`;else if(o.platform==="claude-console")t=`/admin/claude-console-accounts/${o.id}/toggle-schedulable`;else{h("Gemini账户暂不支持调度控制","warning");return}const s=await V.put(t);s.success?(o.schedulable=s.schedulable,h(s.schedulable?"已启用调度":"已禁用调度","success")):h(s.message||"操作失败","error")}catch{h("切换调度状态失败","error")}finally{o.isTogglingSchedulable=!1}},fe=()=>{x.value=!1,h("账户创建成功","success"),W()},xe=()=>{r.value=!1,h("账户更新成功","success"),W()},ve=o=>o.status==="blocked"?"已封锁":o.isRateLimited||o.status==="rate_limited"||o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?"限流中":o.status==="error"||!o.isActive?"错误":o.schedulable===!1?"已暂停":"正常",ge=o=>o.status==="blocked"?"bg-red-100 text-red-800":o.isRateLimited||o.status==="rate_limited"||o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?"bg-orange-100 text-orange-800":o.status==="error"||!o.isActive?"bg-red-100 text-red-800":o.schedulable===!1?"bg-gray-100 text-gray-800":"bg-green-100 text-green-800",ye=o=>o.status==="blocked"?"bg-red-500":o.isRateLimited||o.status==="rate_limited"||o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?"bg-orange-500":o.status==="error"||!o.isActive?"bg-red-500":o.schedulable===!1?"bg-gray-500":"bg-green-500",be=o=>{if(!o.sessionWindow)return 100;const{remaining:t,total:s}=o.sessionWindow;return!s||s===0?100:Math.round(t/s*100)},we=o=>A(o),ke=async o=>{if(!S.value[o.id])try{S.value[o.id]=!0;const t=await V.post(`/admin/claude-accounts/${o.id}/refresh`);t.success?(h("Token刷新成功","success"),W()):h(t.message||"Token刷新失败","error")}catch{h("Token刷新失败","error")}finally{S.value[o.id]=!1}};return E(w,o=>{const t={name:"name",dailyTokens:"dailyTokens",dailyRequests:"dailyRequests",totalTokens:"totalTokens",lastUsed:"lastUsed"};t[o]&&j(t[o])}),Re(()=>{W(),Z()}),(o,t)=>(a(),n("div",Pl,[e("div",Dl,[e("div",zl,[t[13]||(t[13]=e("div",null,[e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900 mb-1 sm:mb-2"}," 账户管理 "),e("p",{class:"text-sm sm:text-base text-gray-600"}," 管理您的 Claude 和 Gemini 账户及代理配置 ")],-1)),e("div",El,[e("div",Ol,[g(e("select",{"onUpdate:modelValue":t[0]||(t[0]=s=>w.value=s),class:"form-input px-3 py-2 text-sm w-full sm:w-auto",onChange:t[1]||(t[1]=s=>j())},t[9]||(t[9]=[Ce('',5)]),544),[[me,w.value]]),g(e("select",{"onUpdate:modelValue":t[2]||(t[2]=s=>q.value=s),class:"form-input px-3 py-2 text-sm w-full sm:w-auto",onChange:oe},[t[10]||(t[10]=e("option",{value:"all"},"所有账户",-1)),t[11]||(t[11]=e("option",{value:"ungrouped"},"未分组账户",-1)),(a(!0),n(re,null,ie(R.value,s=>(a(),n("option",{key:s.id,value:s.id},f(s.name)+" ("+f(s.platform==="claude"?"Claude":"Gemini")+") ",9,Wl))),128))],544),[[me,q.value]])]),e("button",{class:"btn btn-success px-4 sm:px-6 py-2 sm:py-3 flex items-center gap-2 w-full sm:w-auto justify-center",onClick:We(F,["stop"])},t[12]||(t[12]=[e("i",{class:"fas fa-plus"},null,-1),$("添加账户 ",-1)]))])]),T.value?(a(),n("div",ql,t[14]||(t[14]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"}," 正在加载账户... ",-1)]))):B.value.length===0?(a(),n("div",Bl,t[15]||(t[15]=[e("div",{class:"w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center"},[e("i",{class:"fas fa-user-circle text-gray-400 text-xl"})],-1),e("p",{class:"text-gray-500 text-lg"}," 暂无账户 ",-1),e("p",{class:"text-gray-400 text-sm mt-2"}," 点击上方按钮添加您的第一个账户 ",-1)]))):(a(),n("div",Fl,[e("table",Nl,[e("thead",Hl,[e("tr",null,[e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[22%] min-w-[180px]",onClick:t[3]||(t[3]=s=>j("name"))},[t[16]||(t[16]=$(" 名称 ",-1)),v.value==="name"?(a(),n("i",{key:0,class:K(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Jl))]),e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[15%] min-w-[120px]",onClick:t[4]||(t[4]=s=>j("platform"))},[t[17]||(t[17]=$(" 平台/类型 ",-1)),v.value==="platform"?(a(),n("i",{key:0,class:K(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Yl))]),e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[12%] min-w-[100px]",onClick:t[5]||(t[5]=s=>j("status"))},[t[18]||(t[18]=$(" 状态 ",-1)),v.value==="status"?(a(),n("i",{key:0,class:K(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Ql))]),e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100 w-[8%] min-w-[80px]",onClick:t[6]||(t[6]=s=>j("priority"))},[t[19]||(t[19]=$(" 优先级 ",-1)),v.value==="priority"?(a(),n("i",{key:0,class:K(["fas",m.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),n("i",Xl))]),t[20]||(t[20]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[10%] min-w-[100px]"}," 代理 ",-1)),t[21]||(t[21]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[10%] min-w-[90px]"}," 今日使用 ",-1)),t[22]||(t[22]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[10%] min-w-[100px]"}," 会话窗口 ",-1)),t[23]||(t[23]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[8%] min-w-[80px]"}," 最后使用 ",-1)),t[24]||(t[24]=e("th",{class:"px-3 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider w-[15%] min-w-[180px]"}," 操作 ",-1))])]),e("tbody",Zl,[(a(!0),n(re,null,ie(B.value,s=>(a(),n("tr",{key:s.id,class:"table-row"},[e("td",eo,[e("div",to,[t[29]||(t[29]=e("div",{class:"w-8 h-8 bg-gradient-to-br from-green-500 to-green-600 rounded-lg flex items-center justify-center mr-2 flex-shrink-0"},[e("i",{class:"fas fa-user-circle text-white text-xs"})],-1)),e("div",so,[e("div",lo,[e("div",{class:"text-sm font-semibold text-gray-900 truncate",title:s.name},f(s.name),9,oo),s.accountType==="dedicated"?(a(),n("span",ao,t[25]||(t[25]=[e("i",{class:"fas fa-lock mr-1"},null,-1),$("专属 ",-1)]))):s.accountType==="group"?(a(),n("span",no,t[26]||(t[26]=[e("i",{class:"fas fa-layer-group mr-1"},null,-1),$("分组调度 ",-1)]))):(a(),n("span",ro,t[27]||(t[27]=[e("i",{class:"fas fa-share-alt mr-1"},null,-1),$("共享 ",-1)]))),s.groupInfo?(a(),n("span",{key:3,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 ml-1",title:`所属分组: ${s.groupInfo.name}`},[t[28]||(t[28]=e("i",{class:"fas fa-folder mr-1"},null,-1)),$(f(s.groupInfo.name),1)],8,io)):y("",!0)]),e("div",{class:"text-xs text-gray-500 truncate",title:s.id},f(s.id),9,uo)])])]),e("td",po,[e("div",mo,[s.platform==="gemini"?(a(),n("div",co,[t[30]||(t[30]=e("i",{class:"fas fa-robot text-yellow-700 text-xs"},null,-1)),t[31]||(t[31]=e("span",{class:"text-xs font-semibold text-yellow-800"},"Gemini",-1)),t[32]||(t[32]=e("span",{class:"w-px h-4 bg-yellow-300 mx-1"},null,-1)),e("span",fo,f(s.scopes&&s.scopes.length>0?"OAuth":"传统"),1)])):s.platform==="claude-console"?(a(),n("div",xo,t[33]||(t[33]=[e("i",{class:"fas fa-terminal text-purple-700 text-xs"},null,-1),e("span",{class:"text-xs font-semibold text-purple-800"},"Console",-1),e("span",{class:"w-px h-4 bg-purple-300 mx-1"},null,-1),e("span",{class:"text-xs font-medium text-purple-700"},"API Key",-1)]))):(a(),n("div",vo,[t[34]||(t[34]=e("i",{class:"fas fa-brain text-indigo-700 text-xs"},null,-1)),t[35]||(t[35]=e("span",{class:"text-xs font-semibold text-indigo-800"},"Claude",-1)),t[36]||(t[36]=e("span",{class:"w-px h-4 bg-indigo-300 mx-1"},null,-1)),e("span",go,f(s.scopes&&s.scopes.length>0?"OAuth":"传统"),1)]))])]),e("td",yo,[e("div",bo,[e("span",{class:K(["inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold",s.status==="blocked"?"bg-orange-100 text-orange-800":s.isActive?"bg-green-100 text-green-800":"bg-red-100 text-red-800"])},[e("div",{class:K(["w-2 h-2 rounded-full mr-2",s.status==="blocked"?"bg-orange-500":s.isActive?"bg-green-500":"bg-red-500"])},null,2),$(" "+f(s.status==="blocked"?"已封锁":s.isActive?"正常":"异常"),1)],2),s.rateLimitStatus&&s.rateLimitStatus.isRateLimited?(a(),n("span",wo,[t[37]||(t[37]=e("i",{class:"fas fa-exclamation-triangle mr-1"},null,-1)),$(" 限流中 ("+f(s.rateLimitStatus.minutesRemaining)+"分钟) ",1)])):y("",!0),s.schedulable===!1?(a(),n("span",ko,t[38]||(t[38]=[e("i",{class:"fas fa-pause-circle mr-1"},null,-1),$(" 不可调度 ",-1)]))):y("",!0),s.status==="blocked"&&s.errorMessage?(a(),n("span",{key:2,class:"text-xs text-gray-500 mt-1 max-w-xs truncate",title:s.errorMessage},f(s.errorMessage),9,ho)):y("",!0),s.accountType==="dedicated"?(a(),n("span",$o," 绑定: "+f(s.boundApiKeysCount||0)+" 个API Key ",1)):y("",!0)])]),e("td",Co,[s.platform==="claude"||s.platform==="claude-console"?(a(),n("div",To,[e("div",Ao,[e("div",{class:"bg-gradient-to-r from-green-500 to-blue-600 h-2 rounded-full transition-all duration-300",style:Te({width:101-(s.priority||50)+"%"})},null,4)]),e("span",Uo,f(s.priority||50),1)])):(a(),n("div",Io,t[39]||(t[39]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Vo,[c(s.proxy)?(a(),n("div",{key:0,class:"text-xs bg-blue-50 px-2 py-1 rounded font-mono break-all",title:c(s.proxy)},f(c(s.proxy)),9,jo)):(a(),n("div",So," 无代理 "))]),e("td",_o,[s.usage&&s.usage.daily?(a(),n("div",Mo,[e("div",Go,[t[40]||(t[40]=e("div",{class:"w-2 h-2 bg-green-500 rounded-full"},null,-1)),e("span",Ko,f(s.usage.daily.requests||0)+" 次",1)]),e("div",Ro,[t[41]||(t[41]=e("div",{class:"w-2 h-2 bg-blue-500 rounded-full"},null,-1)),e("span",Lo,f(u(s.usage.daily.allTokens||0))+" tokens",1)]),s.usage.averages&&s.usage.averages.rpm>0?(a(),n("div",Po," 平均 "+f(s.usage.averages.rpm.toFixed(2))+" RPM ",1)):y("",!0)])):(a(),n("div",Do," 暂无数据 "))]),e("td",zo,[s.platform==="claude"&&s.sessionWindow&&s.sessionWindow.hasActiveWindow?(a(),n("div",Eo,[e("div",Oo,[e("div",Wo,[e("div",{class:"bg-gradient-to-r from-blue-500 to-indigo-600 h-2 rounded-full transition-all duration-300",style:Te({width:s.sessionWindow.progress+"%"})},null,4)]),e("span",qo,f(s.sessionWindow.progress)+"% ",1)]),e("div",Bo,[e("div",null,f(p(s.sessionWindow.windowStart,s.sessionWindow.windowEnd)),1),s.sessionWindow.remainingTime>0?(a(),n("div",Fo," 剩余 "+f(U(s.sessionWindow.remainingTime)),1)):y("",!0)])])):s.platform==="claude"?(a(),n("div",No,t[42]||(t[42]=[e("i",{class:"fas fa-minus"},null,-1)]))):(a(),n("div",Ho,t[43]||(t[43]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Jo,f(A(s.lastUsedAt)),1),e("td",Yo,[e("div",Qo,[s.platform==="claude"&&s.scopes?(a(),n("button",{key:0,disabled:s.isRefreshing,class:K(["px-2.5 py-1 rounded text-xs font-medium transition-colors",s.isRefreshing?"bg-gray-100 text-gray-400 cursor-not-allowed":"bg-blue-100 text-blue-700 hover:bg-blue-200"]),title:s.isRefreshing?"刷新中...":"刷新Token",onClick:k=>ce(s)},[e("i",{class:K(["fas fa-sync-alt",s.isRefreshing?"animate-spin":""])},null,2),t[44]||(t[44]=e("span",{class:"ml-1"},"刷新",-1))],10,Xo)):y("",!0),e("button",{disabled:s.isTogglingSchedulable,class:K(["px-2.5 py-1 rounded text-xs font-medium transition-colors",s.isTogglingSchedulable?"bg-gray-100 text-gray-400 cursor-not-allowed":s.schedulable?"bg-green-100 text-green-700 hover:bg-green-200":"bg-gray-100 text-gray-700 hover:bg-gray-200"]),title:s.schedulable?"点击禁用调度":"点击启用调度",onClick:k=>pe(s)},[e("i",{class:K(["fas",s.schedulable?"fa-toggle-on":"fa-toggle-off"])},null,2),e("span",ea,f(s.schedulable?"调度":"停用"),1)],10,Zo),e("button",{class:"px-2.5 py-1 bg-blue-100 text-blue-700 rounded text-xs font-medium hover:bg-blue-200 transition-colors",title:"编辑账户",onClick:k=>ue(s)},t[45]||(t[45]=[e("i",{class:"fas fa-edit"},null,-1),e("span",{class:"ml-1"},"编辑",-1)]),8,ta),e("button",{class:"px-2.5 py-1 bg-red-100 text-red-700 rounded text-xs font-medium hover:bg-red-200 transition-colors",title:"删除账户",onClick:k=>de(s)},t[46]||(t[46]=[e("i",{class:"fas fa-trash"},null,-1),e("span",{class:"ml-1"},"删除",-1)]),8,sa)])])]))),128))])])])),!T.value&&B.value.length>0?(a(),n("div",la,[(a(!0),n(re,null,ie(B.value,s=>{var k,D,N,H;return a(),n("div",{key:s.id,class:"card p-4 hover:shadow-lg transition-shadow"},[e("div",oa,[e("div",aa,[e("div",{class:K(["w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0",s.platform==="claude"?"bg-gradient-to-br from-purple-500 to-purple-600":"bg-gradient-to-br from-blue-500 to-blue-600"])},[e("i",{class:K(["text-white text-sm",s.platform==="claude"?"fas fa-brain":"fas fa-robot"])},null,2)],2),e("div",null,[e("h4",na,f(s.name||s.email),1),e("div",ra,[e("span",ia,f(s.platform),1),t[47]||(t[47]=e("span",{class:"text-xs text-gray-400"},"|",-1)),e("span",ua,f(s.type),1)])])]),e("span",{class:K(["inline-flex items-center px-2 py-1 rounded-full text-xs font-semibold",ge(s)])},[e("div",{class:K(["w-1.5 h-1.5 rounded-full mr-1.5",ye(s)])},null,2),$(" "+f(ve(s)),1)],2)]),e("div",da,[e("div",null,[t[48]||(t[48]=e("p",{class:"text-xs text-gray-500"}," 今日使用 ",-1)),e("p",pa,f(u(((k=s.usage)==null?void 0:k.dailyRequests)||0))+" 次 ",1),e("p",ma,f(u(((D=s.usage)==null?void 0:D.dailyTokens)||0))+" tokens ",1)]),e("div",null,[t[49]||(t[49]=e("p",{class:"text-xs text-gray-500"}," 总使用量 ",-1)),e("p",ca,f(u(((N=s.usage)==null?void 0:N.totalRequests)||0))+" 次 ",1),e("p",fa,f(u(((H=s.usage)==null?void 0:H.totalTokens)||0))+" tokens ",1)])]),e("div",xa,[s.sessionWindow?(a(),n("div",va,[t[50]||(t[50]=e("span",{class:"text-gray-500"},"会话窗口",-1)),e("div",ga,[e("span",{class:K(["font-medium",s.sessionWindow.remaining<=20?"text-orange-600":"text-gray-900"])},f(s.sessionWindow.remaining||0)+" / "+f(s.sessionWindow.total||0),3),e("div",ya,[e("div",{class:"h-full bg-gradient-to-r from-blue-500 to-blue-600 transition-all duration-300",style:Te({width:`${be(s)}%`})},null,4)])])])):y("",!0),e("div",ba,[t[51]||(t[51]=e("span",{class:"text-gray-500"},"最后使用",-1)),e("span",wa,f(s.lastUsedAt?we(s.lastUsedAt):"从未使用"),1)]),s.proxyConfig&&s.proxyConfig.type!=="none"?(a(),n("div",ka,[t[52]||(t[52]=e("span",{class:"text-gray-500"},"代理",-1)),e("span",ha,f(s.proxyConfig.type.toUpperCase()),1)])):y("",!0),e("div",$a,[t[53]||(t[53]=e("span",{class:"text-gray-500"},"优先级",-1)),e("span",Ca,f(s.priority||0),1)])]),e("div",Ta,[s.platform==="claude"&&s.type==="oauth"?(a(),n("button",{key:0,class:"flex-1 px-3 py-2 text-xs text-blue-600 bg-blue-50 rounded-lg hover:bg-blue-100 transition-colors flex items-center justify-center gap-1",disabled:S.value[s.id],onClick:Q=>ke(s)},[e("i",{class:K(["fas fa-sync-alt",{"animate-spin":S.value[s.id]}])},null,2),$(" "+f(S.value[s.id]?"刷新中":"刷新"),1)],8,Aa)):y("",!0),e("button",{class:K(["flex-1 px-3 py-2 text-xs rounded-lg transition-colors flex items-center justify-center gap-1",s.schedulable?"text-gray-600 bg-gray-50 hover:bg-gray-100":"text-green-600 bg-green-50 hover:bg-green-100"]),onClick:Q=>pe(s),disabled:s.isTogglingSchedulable},[e("i",{class:K(["fas",s.schedulable?"fa-pause":"fa-play"])},null,2),$(" "+f(s.schedulable?"暂停":"启用"),1)],10,Ua),e("button",{class:"flex-1 px-3 py-2 text-xs text-gray-600 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors",onClick:Q=>ue(s)},t[54]||(t[54]=[e("i",{class:"fas fa-edit mr-1"},null,-1),$(" 编辑 ",-1)]),8,Ia),e("button",{class:"px-3 py-2 text-xs text-red-600 bg-red-50 rounded-lg hover:bg-red-100 transition-colors",onClick:Q=>de(s)},t[55]||(t[55]=[e("i",{class:"fas fa-trash"},null,-1)]),8,Va)])])}),128))])):y("",!0)]),x.value?(a(),le(Ke,{key:0,onClose:t[7]||(t[7]=s=>x.value=!1),onSuccess:fe})):y("",!0),r.value?(a(),le(Ke,{key:1,account:L.value,onClose:t[8]||(t[8]=s=>r.value=!1),onSuccess:xe},null,8,["account"])):y("",!0),$e(De,{show:Y(O),title:Y(d).title,message:Y(d).message,"confirm-text":Y(d).confirmText,"cancel-text":Y(d).cancelText,onConfirm:Y(i),onCancel:Y(M)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"])]))}},Ra=qe(ja,[["__scopeId","data-v-ab3ae7fd"]]);export{Ra as default};
diff --git a/web/admin-spa/dist/assets/ApiKeysView-H8g1IO_M.js b/web/admin-spa/dist/assets/ApiKeysView-Bkj34Z3E.js
similarity index 99%
rename from web/admin-spa/dist/assets/ApiKeysView-H8g1IO_M.js
rename to web/admin-spa/dist/assets/ApiKeysView-Bkj34Z3E.js
index 285d8538..6d3cacf2 100644
--- a/web/admin-spa/dist/assets/ApiKeysView-H8g1IO_M.js
+++ b/web/admin-spa/dist/assets/ApiKeysView-Bkj34Z3E.js
@@ -1,4 +1,4 @@
-import{E as Xe}from"./element-plus-B8Fs_0jW.js";import{aR as je,r as K,c as ee,_ as be,q as he,I as Z,y as n,z as e,Y as ie,x as i,L as y,C as P,K as D,an as ne,O as h,aq as z,P as u,Q as R,ac as G,aa as ye,aX as le,al as de,a5 as ue,o as $e,R as Se,B as Je}from"./vue-vendor-CKToUHZx.js";import{s as S}from"./toast-BvwA7Mwb.js";import{a as U,_ as ae,u as Re}from"./index-D3bIJLrk.js";import"./vendor-BDiMbLwQ.js";const Ae=je("clients",{state:()=>({supportedClients:[],loading:!1,error:null}),actions:{async loadSupportedClients(){if(this.supportedClients.length>0)return this.supportedClients;this.loading=!0,this.error=null;try{const I=await U.get("/admin/supported-clients");return I.success?this.supportedClients=I.data||[]:(this.error=I.message||"加载支持的客户端失败",console.error("Failed to load supported clients:",this.error)),this.supportedClients}catch(I){return this.error=I.message||"加载支持的客户端失败",console.error("Error loading supported clients:",I),[]}finally{this.loading=!1}}}}),Ee=je("apiKeys",()=>{const I=K([]),V=K(!1),f=K(null),M=K("all"),j=K(""),C=K("asc"),$=async()=>{V.value=!0,f.value=null;try{const A=await U.get("/admin/api-keys");if(A.success)I.value=A.data||[];else throw new Error(A.message||"获取API Keys失败")}catch(A){throw f.value=A.message,A}finally{V.value=!1}};return{apiKeys:I,loading:V,error:f,statsTimeRange:M,sortBy:j,sortOrder:C,fetchApiKeys:$,createApiKey:async A=>{V.value=!0,f.value=null;try{const x=await U.post("/admin/api-keys",A);if(x.success)return await $(),x.data;throw new Error(x.message||"创建API Key失败")}catch(x){throw f.value=x.message,x}finally{V.value=!1}},updateApiKey:async(A,x)=>{V.value=!0,f.value=null;try{const p=await U.put(`/admin/api-keys/${A}`,x);if(p.success)return await $(),p;throw new Error(p.message||"更新API Key失败")}catch(p){throw f.value=p.message,p}finally{V.value=!1}},toggleApiKey:async A=>{V.value=!0,f.value=null;try{const x=await U.put(`/admin/api-keys/${A}/toggle`);if(x.success)return await $(),x;throw new Error(x.message||"切换状态失败")}catch(x){throw f.value=x.message,x}finally{V.value=!1}},renewApiKey:async(A,x)=>{V.value=!0,f.value=null;try{const p=await U.put(`/admin/api-keys/${A}/renew`,x);if(p.success)return await $(),p;throw new Error(p.message||"续期失败")}catch(p){throw f.value=p.message,p}finally{V.value=!1}},deleteApiKey:async A=>{V.value=!0,f.value=null;try{const x=await U.delete(`/admin/api-keys/${A}`);if(x.success)return await $(),x;throw new Error(x.message||"删除失败")}catch(x){throw f.value=x.message,x}finally{V.value=!1}},fetchApiKeyStats:async(A,x="all")=>{try{const p=await U.get(`/admin/api-keys/${A}/stats`,{params:{timeRange:x}});if(p.success)return p.stats;throw new Error(p.message||"获取统计失败")}catch(p){return console.error("获取API Key统计失败:",p),null}},fetchTags:async()=>{try{const A=await U.get("/admin/api-keys/tags");if(A.success)return A.data||[];throw new Error(A.message||"获取标签失败")}catch(A){return console.error("获取标签失败:",A),[]}},sortApiKeys:A=>{j.value===A?C.value=C.value==="asc"?"desc":"asc":(j.value=A,C.value="asc")},reset:()=>{I.value=[],V.value=!1,f.value=null,M.value="all",j.value="",C.value="asc"}}}),Ze={class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},et={class:"modal-content w-full max-w-4xl p-4 sm:p-6 mx-auto max-h-[90vh] flex flex-col"},tt={class:"flex items-center justify-between mb-4"},st={class:"bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg p-3 sm:p-4 border border-blue-200"},lt={class:"flex gap-3 sm:gap-4 items-center"},ot={class:"flex items-center cursor-pointer"},nt={class:"flex items-center cursor-pointer"},it={key:0,class:"mt-3"},at={class:"flex items-center gap-4"},rt={class:"flex-1"},dt={class:"flex items-center gap-2"},ut={class:"text-xs text-amber-600 mt-2 flex items-start"},ct=["placeholder"],mt={key:0,class:"text-red-500 text-xs mt-1"},pt={class:"space-y-4"},xt={key:0},gt={class:"flex flex-wrap gap-2"},ft=["onClick"],yt={key:1},bt={class:"flex flex-wrap gap-2"},vt=["onClick"],wt={class:"flex gap-2"},$t=["onKeypress"],ht={class:"bg-blue-50 border border-blue-200 rounded-lg p-3"},At={class:"space-y-2"},Ct={class:"grid grid-cols-1 lg:grid-cols-3 gap-2"},Kt={class:"space-y-2"},kt={class:"flex gap-2"},_t={key:0,class:"mt-3"},Dt=["min"],It={key:1,class:"text-xs text-gray-500 mt-2"},Lt={class:"flex gap-4"},Tt={class:"flex items-center cursor-pointer"},Mt={class:"flex items-center cursor-pointer"},St={class:"flex items-center cursor-pointer"},jt={class:"flex items-center justify-between mb-2"},Rt=["disabled"],Et={class:"grid grid-cols-1 gap-3"},Pt=["disabled"],Ut={key:0,label:"调度分组"},Vt=["value"],Gt={key:1,label:"Claude OAuth 专属账号"},Ot=["value"],qt={key:2,label:"Claude Console 专属账号"},Ft=["value"],Wt=["disabled"],zt={key:0,label:"调度分组"},Nt=["value"],Yt={key:1,label:"Gemini 专属账号"},Bt=["value"],Ht={class:"flex items-center mb-2"},Qt={key:0,class:"space-y-2 bg-red-50 border border-red-200 rounded-lg p-3"},Xt={class:"flex flex-wrap gap-1 mb-2 min-h-[24px]"},Jt=["onClick"],Zt={key:0,class:"text-gray-400 text-xs"},es={class:"flex gap-2"},ts=["onKeydown"],ss={class:"flex items-center mb-2"},ls={key:0,class:"bg-green-50 border border-green-200 rounded-lg p-3"},os={class:"space-y-1"},ns=["id","value"],is=["for"],as={class:"text-sm font-medium text-gray-700"},rs={class:"text-xs text-gray-500 block"},ds={class:"flex gap-3 pt-2"},us=["disabled"],cs={key:0,class:"loading-spinner mr-2"},ms={key:1,class:"fas fa-plus mr-2"},ps={__name:"CreateApiKeyModal",props:{accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success","batch-success"],setup(I,{emit:V}){const f=I,M=V,j=Ae(),C=Ee(),$=K(!1),O=K(!1),b=K({claude:[],gemini:[],claudeGroups:[],geminiGroups:[]}),q=K({name:""}),L=K(""),w=K([]),k=ee(()=>w.value.filter(_=>!l.tags.includes(_))),d=K([]),l=be({createType:"single",batchCount:10,name:"",description:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",expireDuration:"",customExpireDate:"",expiresAt:null,permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]});he(async()=>{d.value=await j.loadSupportedClients(),w.value=await C.fetchTags(),f.accounts&&(b.value={claude:f.accounts.claude||[],gemini:f.accounts.gemini||[],claudeGroups:f.accounts.claudeGroups||[],geminiGroups:f.accounts.geminiGroups||[]})});const N=async()=>{var _,o;O.value=!0;try{const[r,F,Q,se]=await Promise.all([U.get("/admin/claude-accounts"),U.get("/admin/claude-console-accounts"),U.get("/admin/gemini-accounts"),U.get("/admin/account-groups")]),re=[];if(r.success&&((_=r.data)==null||_.forEach(X=>{re.push({...X,platform:"claude-oauth",isDedicated:X.accountType==="dedicated"})})),F.success&&((o=F.data)==null||o.forEach(X=>{re.push({...X,platform:"claude-console",isDedicated:X.accountType==="dedicated"})})),b.value.claude=re,Q.success&&(b.value.gemini=(Q.data||[]).map(X=>({...X,isDedicated:X.accountType==="dedicated"}))),se.success){const X=se.data||[];b.value.claudeGroups=X.filter(J=>J.platform==="claude"),b.value.geminiGroups=X.filter(J=>J.platform==="gemini")}S("账号列表已刷新","success")}catch{S("刷新账号列表失败","error")}finally{O.value=!1}},A=ee(()=>{const _=new Date;return _.setMinutes(_.getMinutes()+1),_.toISOString().slice(0,16)}),x=()=>{if(!l.expireDuration){l.expiresAt=null;return}if(l.expireDuration==="custom")return;const _=new Date,r=l.expireDuration.match(/(\d+)([dhmy])/);if(r){const[,F,Q]=r,se=parseInt(F);switch(Q){case"d":_.setDate(_.getDate()+se);break;case"h":_.setHours(_.getHours()+se);break;case"m":_.setMonth(_.getMonth()+se);break;case"y":_.setFullYear(_.getFullYear()+se);break}l.expiresAt=_.toISOString()}},p=()=>{l.customExpireDate&&(l.expiresAt=new Date(l.customExpireDate).toISOString())},Y=_=>new Date(_).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),H=()=>{l.modelInput&&!l.restrictedModels.includes(l.modelInput)&&(l.restrictedModels.push(l.modelInput),l.modelInput="")},T=_=>{l.restrictedModels.splice(_,1)},a=()=>{if(L.value&&L.value.trim()){const _=L.value.trim();l.tags.includes(_)||l.tags.push(_),L.value=""}},m=_=>{l.tags.includes(_)||l.tags.push(_)},B=_=>{l.tags.splice(_,1)},te=async()=>{if(q.value.name="",!l.name||!l.name.trim()){q.value.name="请输入API Key名称";return}if(l.createType==="batch"&&(!l.batchCount||l.batchCount<2||l.batchCount>500)){S("批量创建数量必须在 2-500 之间","error");return}$.value=!0;try{const _={description:l.description||void 0,tokenLimit:l.tokenLimit!==""&&l.tokenLimit!==null?parseInt(l.tokenLimit):null,rateLimitWindow:l.rateLimitWindow!==""&&l.rateLimitWindow!==null?parseInt(l.rateLimitWindow):null,rateLimitRequests:l.rateLimitRequests!==""&&l.rateLimitRequests!==null?parseInt(l.rateLimitRequests):null,concurrencyLimit:l.concurrencyLimit!==""&&l.concurrencyLimit!==null?parseInt(l.concurrencyLimit):0,dailyCostLimit:l.dailyCostLimit!==""&&l.dailyCostLimit!==null?parseFloat(l.dailyCostLimit):0,expiresAt:l.expiresAt||void 0,permissions:l.permissions,tags:l.tags.length>0?l.tags:void 0,enableModelRestriction:l.enableModelRestriction,restrictedModels:l.restrictedModels,enableClientRestriction:l.enableClientRestriction,allowedClients:l.allowedClients};if(l.claudeAccountId&&(l.claudeAccountId.startsWith("console:")?_.claudeConsoleAccountId=l.claudeAccountId.substring(8):_.claudeAccountId=l.claudeAccountId),l.geminiAccountId&&(_.geminiAccountId=l.geminiAccountId),l.createType==="single"){const o={..._,name:l.name},r=await U.post("/admin/api-keys",o);r.success?(S("API Key 创建成功","success"),M("success",r.data),M("close")):S(r.message||"创建失败","error")}else{const o={..._,createType:"batch",baseName:l.name,count:l.batchCount},r=await U.post("/admin/api-keys/batch",o);r.success?(S(`成功创建 ${r.data.length} 个 API Key`,"success"),M("batch-success",r.data),M("close")):S(r.message||"批量创建失败","error")}}catch{S("创建失败","error")}finally{$.value=!1}};return(_,o)=>(n(),Z(ue,{to:"body"},[e("div",Ze,[e("div",et,[e("div",tt,[o[30]||(o[30]=e("div",{class:"flex items-center gap-2 sm:gap-3"},[e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-key text-white text-sm sm:text-base"})]),e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 创建新的 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:o[0]||(o[0]=r=>_.$emit("close"))},o[29]||(o[29]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),e("form",{class:"space-y-4 modal-scroll-content custom-scrollbar flex-1",onSubmit:ie(te,["prevent"])},[e("div",st,[e("div",{class:P(["flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3",l.createType==="batch"?"mb-3":""])},[o[33]||(o[33]=e("label",{class:"text-xs sm:text-sm font-semibold text-gray-700 flex items-center h-full"},"创建类型",-1)),e("div",lt,[e("label",ot,[D(e("input",{"onUpdate:modelValue":o[1]||(o[1]=r=>l.createType=r),type:"radio",value:"single",class:"mr-1.5 sm:mr-2 text-blue-600"},null,512),[[ne,l.createType]]),o[31]||(o[31]=e("span",{class:"text-xs sm:text-sm text-gray-700 flex items-center"},[e("i",{class:"fas fa-key mr-1 text-xs"}),h(" 单个创建 ")],-1))]),e("label",nt,[D(e("input",{"onUpdate:modelValue":o[2]||(o[2]=r=>l.createType=r),type:"radio",value:"batch",class:"mr-1.5 sm:mr-2 text-blue-600"},null,512),[[ne,l.createType]]),o[32]||(o[32]=e("span",{class:"text-xs sm:text-sm text-gray-700 flex items-center"},[e("i",{class:"fas fa-layer-group mr-1 text-xs"}),h(" 批量创建 ")],-1))])])],2),l.createType==="batch"?(n(),i("div",it,[e("div",at,[e("div",rt,[o[35]||(o[35]=e("label",{class:"block text-xs font-medium text-gray-600 mb-1"},"创建数量",-1)),e("div",dt,[D(e("input",{"onUpdate:modelValue":o[3]||(o[3]=r=>l.batchCount=r),type:"number",min:"2",max:"500",required:"",class:"form-input w-full text-sm",placeholder:"输入数量 (2-500)"},null,512),[[z,l.batchCount,void 0,{number:!0}]]),o[34]||(o[34]=e("div",{class:"text-xs text-gray-500 whitespace-nowrap"}," 最大支持 500 个 ",-1))])])]),e("p",ut,[o[36]||(o[36]=e("i",{class:"fas fa-info-circle mr-1 mt-0.5 flex-shrink-0"},null,-1)),e("span",null,"批量创建时,每个 Key 的名称会自动添加序号后缀,例如:"+u(l.name||"MyKey")+"_1, "+u(l.name||"MyKey")+"_2 ...",1)])])):y("",!0)]),e("div",null,[o[37]||(o[37]=e("label",{class:"block text-xs sm:text-sm font-semibold text-gray-700 mb-1.5 sm:mb-2"},[h("名称 "),e("span",{class:"text-red-500"},"*")],-1)),D(e("input",{"onUpdate:modelValue":o[4]||(o[4]=r=>l.name=r),type:"text",required:"",class:P(["form-input w-full text-sm",{"border-red-500":q.value.name}]),placeholder:l.createType==="batch"?"输入基础名称(将自动添加序号)":"为您的 API Key 取一个名称",onInput:o[5]||(o[5]=r=>q.value.name="")},null,42,ct),[[z,l.name]]),q.value.name?(n(),i("p",mt,u(q.value.name),1)):y("",!0)]),e("div",null,[o[45]||(o[45]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"标签",-1)),e("div",pt,[l.tags.length>0?(n(),i("div",xt,[o[39]||(o[39]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 已选择的标签: ",-1)),e("div",gt,[(n(!0),i(R,null,G(l.tags,(r,F)=>(n(),i("span",{key:"selected-"+F,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[h(u(r)+" ",1),e("button",{type:"button",class:"ml-1 hover:text-blue-900",onClick:Q=>B(F)},o[38]||(o[38]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,ft)]))),128))])])):y("",!0),k.value.length>0?(n(),i("div",yt,[o[41]||(o[41]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 点击选择已有标签: ",-1)),e("div",bt,[(n(!0),i(R,null,G(k.value,r=>(n(),i("button",{key:"available-"+r,type:"button",class:"inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors",onClick:F=>m(r)},[o[40]||(o[40]=e("i",{class:"fas fa-tag text-gray-500 text-xs"},null,-1)),h(" "+u(r),1)],8,vt))),128))])])):y("",!0),e("div",null,[o[43]||(o[43]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 创建新标签: ",-1)),e("div",wt,[D(e("input",{"onUpdate:modelValue":o[6]||(o[6]=r=>L.value=r),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:ye(ie(a,["prevent"]),["enter"])},null,40,$t),[[z,L.value]]),e("button",{type:"button",class:"px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors",onClick:a},o[42]||(o[42]=[e("i",{class:"fas fa-plus"},null,-1)]))])]),o[44]||(o[44]=e("p",{class:"text-xs text-gray-500"}," 用于标记不同团队或用途,方便筛选管理 ",-1))])]),e("div",ht,[o[53]||(o[53]=e("div",{class:"flex items-center gap-2 mb-2"},[e("div",{class:"w-6 h-6 bg-blue-500 rounded flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-tachometer-alt text-white text-xs"})]),e("h4",{class:"font-semibold text-gray-800 text-sm"}," 速率限制设置 (可选) ")],-1)),e("div",At,[e("div",Ct,[e("div",null,[o[46]||(o[46]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"时间窗口 (分钟)",-1)),D(e("input",{"onUpdate:modelValue":o[7]||(o[7]=r=>l.rateLimitWindow=r),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,l.rateLimitWindow]]),o[47]||(o[47]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 时间段单位 ",-1))]),e("div",null,[o[48]||(o[48]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"请求次数限制",-1)),D(e("input",{"onUpdate:modelValue":o[8]||(o[8]=r=>l.rateLimitRequests=r),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,l.rateLimitRequests]]),o[49]||(o[49]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大请求 ",-1))]),e("div",null,[o[50]||(o[50]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"Token 限制",-1)),D(e("input",{"onUpdate:modelValue":o[9]||(o[9]=r=>l.tokenLimit=r),type:"number",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,l.tokenLimit]]),o[51]||(o[51]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大Token ",-1))])]),o[52]||(o[52]=e("div",{class:"bg-blue-100 rounded-lg p-2"},[e("h5",{class:"text-xs font-semibold text-blue-800 mb-1"}," 💡 使用示例 "),e("div",{class:"text-xs text-blue-700 space-y-0.5"},[e("div",null,[e("strong",null,"示例1:"),h(" 时间窗口=60,请求次数=1000 → 每60分钟最多1000次请求")]),e("div",null,[e("strong",null,"示例2:"),h(" 时间窗口=1,Token=10000 → 每分钟最多10,000个Token")]),e("div",null,[e("strong",null,"示例3:"),h(" 窗口=30,请求=50,Token=100000 → 每30分钟50次请求且不超10万Token")])])],-1))])]),e("div",null,[o[55]||(o[55]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"每日费用限制 (美元)",-1)),e("div",Kt,[e("div",kt,[e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[10]||(o[10]=r=>l.dailyCostLimit="50")}," $50 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[11]||(o[11]=r=>l.dailyCostLimit="100")}," $100 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[12]||(o[12]=r=>l.dailyCostLimit="200")}," $200 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[13]||(o[13]=r=>l.dailyCostLimit="")}," 自定义 ")]),D(e("input",{"onUpdate:modelValue":o[14]||(o[14]=r=>l.dailyCostLimit=r),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,l.dailyCostLimit]]),o[54]||(o[54]=e("p",{class:"text-xs text-gray-500"}," 设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制 ",-1))])]),e("div",null,[o[56]||(o[56]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"并发限制 (可选)",-1)),D(e("input",{"onUpdate:modelValue":o[15]||(o[15]=r=>l.concurrencyLimit=r),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,l.concurrencyLimit]]),o[57]||(o[57]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此 API Key 可同时处理的最大请求数,0 或留空表示无限制 ",-1))]),e("div",null,[o[58]||(o[58]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"备注 (可选)",-1)),D(e("textarea",{"onUpdate:modelValue":o[16]||(o[16]=r=>l.description=r),rows:"2",class:"form-input w-full resize-none text-sm",placeholder:"描述此 API Key 的用途..."},null,512),[[z,l.description]])]),e("div",null,[o[60]||(o[60]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"有效期限",-1)),D(e("select",{"onUpdate:modelValue":o[17]||(o[17]=r=>l.expireDuration=r),class:"form-input w-full",onChange:x},o[59]||(o[59]=[e("option",{value:""}," 永不过期 ",-1),e("option",{value:"1d"}," 1 天 ",-1),e("option",{value:"7d"}," 7 天 ",-1),e("option",{value:"30d"}," 30 天 ",-1),e("option",{value:"90d"}," 90 天 ",-1),e("option",{value:"180d"}," 180 天 ",-1),e("option",{value:"365d"}," 365 天 ",-1),e("option",{value:"custom"}," 自定义日期 ",-1)]),544),[[le,l.expireDuration]]),l.expireDuration==="custom"?(n(),i("div",_t,[D(e("input",{"onUpdate:modelValue":o[18]||(o[18]=r=>l.customExpireDate=r),type:"datetime-local",class:"form-input w-full",min:A.value,onChange:p},null,40,Dt),[[z,l.customExpireDate]])])):y("",!0),l.expiresAt?(n(),i("p",It," 将于 "+u(Y(l.expiresAt))+" 过期 ",1)):y("",!0)]),e("div",null,[o[64]||(o[64]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"服务权限",-1)),e("div",Lt,[e("label",Tt,[D(e("input",{"onUpdate:modelValue":o[19]||(o[19]=r=>l.permissions=r),type:"radio",value:"all",class:"mr-2"},null,512),[[ne,l.permissions]]),o[61]||(o[61]=e("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),e("label",Mt,[D(e("input",{"onUpdate:modelValue":o[20]||(o[20]=r=>l.permissions=r),type:"radio",value:"claude",class:"mr-2"},null,512),[[ne,l.permissions]]),o[62]||(o[62]=e("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),e("label",St,[D(e("input",{"onUpdate:modelValue":o[21]||(o[21]=r=>l.permissions=r),type:"radio",value:"gemini",class:"mr-2"},null,512),[[ne,l.permissions]]),o[63]||(o[63]=e("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),o[65]||(o[65]=e("p",{class:"text-xs text-gray-500 mt-2"}," 控制此 API Key 可以访问哪些服务 ",-1))]),e("div",null,[e("div",jt,[o[66]||(o[66]=e("label",{class:"text-sm font-semibold text-gray-700"},"专属账号绑定 (可选)",-1)),e("button",{type:"button",class:"text-blue-600 hover:text-blue-800 text-sm flex items-center gap-1 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",title:"刷新账号列表",disabled:O.value,onClick:N},[e("i",{class:P(["fas",O.value?"fa-spinner fa-spin":"fa-sync-alt","text-xs"])},null,2),e("span",null,u(O.value?"刷新中...":"刷新账号"),1)],8,Rt)]),e("div",Et,[e("div",null,[o[68]||(o[68]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),D(e("select",{"onUpdate:modelValue":o[22]||(o[22]=r=>l.claudeAccountId=r),class:"form-input w-full",disabled:l.permissions==="gemini"},[o[67]||(o[67]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.claudeGroups&&b.value.claudeGroups.length>0?(n(),i("optgroup",Ut,[(n(!0),i(R,null,G(b.value.claudeGroups,r=>(n(),i("option",{key:`group:${r.id}`,value:`group:${r.id}`},u(r.name)+" ("+u(r.memberCount||0)+" 个成员) ",9,Vt))),128))])):y("",!0),b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-oauth").length>0?(n(),i("optgroup",Gt,[(n(!0),i(R,null,G(b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-oauth"),r=>(n(),i("option",{key:r.id,value:r.id},u(r.name)+" ("+u(r.status==="active"?"正常":"异常")+") ",9,Ot))),128))])):y("",!0),b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-console").length>0?(n(),i("optgroup",qt,[(n(!0),i(R,null,G(b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-console"),r=>(n(),i("option",{key:r.id,value:`console:${r.id}`},u(r.name)+" ("+u(r.status==="active"?"正常":"异常")+") ",9,Ft))),128))])):y("",!0)],8,Pt),[[le,l.claudeAccountId]])]),e("div",null,[o[70]||(o[70]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),D(e("select",{"onUpdate:modelValue":o[23]||(o[23]=r=>l.geminiAccountId=r),class:"form-input w-full",disabled:l.permissions==="claude"},[o[69]||(o[69]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.geminiGroups&&b.value.geminiGroups.length>0?(n(),i("optgroup",zt,[(n(!0),i(R,null,G(b.value.geminiGroups,r=>(n(),i("option",{key:`group:${r.id}`,value:`group:${r.id}`},u(r.name)+" ("+u(r.memberCount||0)+" 个成员) ",9,Nt))),128))])):y("",!0),b.value.gemini.filter(r=>r.accountType==="dedicated").length>0?(n(),i("optgroup",Yt,[(n(!0),i(R,null,G(b.value.gemini.filter(r=>r.accountType==="dedicated"),r=>(n(),i("option",{key:r.id,value:r.id},u(r.name)+" ("+u(r.status==="active"?"正常":"异常")+") ",9,Bt))),128))])):y("",!0)],8,Wt),[[le,l.geminiAccountId]])])]),o[71]||(o[71]=e("p",{class:"text-xs text-gray-500 mt-2"}," 选择专属账号后,此API Key将只使用该账号,不选择则使用共享账号池 ",-1))]),e("div",null,[e("div",Ht,[D(e("input",{id:"enableModelRestriction","onUpdate:modelValue":o[24]||(o[24]=r=>l.enableModelRestriction=r),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,l.enableModelRestriction]]),o[72]||(o[72]=e("label",{for:"enableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),l.enableModelRestriction?(n(),i("div",Qt,[e("div",null,[o[75]||(o[75]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"限制的模型列表",-1)),e("div",Xt,[(n(!0),i(R,null,G(l.restrictedModels,(r,F)=>(n(),i("span",{key:F,class:"inline-flex items-center px-2 py-1 rounded-full text-xs bg-red-100 text-red-800"},[h(u(r)+" ",1),e("button",{type:"button",class:"ml-1 text-red-600 hover:text-red-800",onClick:Q=>T(F)},o[73]||(o[73]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,Jt)]))),128)),l.restrictedModels.length===0?(n(),i("span",Zt," 暂无限制的模型 ")):y("",!0)]),e("div",es,[D(e("input",{"onUpdate:modelValue":o[25]||(o[25]=r=>l.modelInput=r),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1 text-sm",onKeydown:ye(ie(H,["prevent"]),["enter"])},null,40,ts),[[z,l.modelInput]]),e("button",{type:"button",class:"px-3 py-1.5 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors text-sm",onClick:H},o[74]||(o[74]=[e("i",{class:"fas fa-plus"},null,-1)]))]),o[76]||(o[76]=e("p",{class:"text-xs text-gray-500 mt-1"}," 例如:claude-opus-4-20250514 ",-1))])])):y("",!0)]),e("div",null,[e("div",ss,[D(e("input",{id:"enableClientRestriction","onUpdate:modelValue":o[26]||(o[26]=r=>l.enableClientRestriction=r),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,l.enableClientRestriction]]),o[77]||(o[77]=e("label",{for:"enableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),l.enableClientRestriction?(n(),i("div",ls,[e("div",null,[o[78]||(o[78]=e("label",{class:"block text-xs font-medium text-gray-700 mb-2"},"允许的客户端",-1)),e("div",os,[(n(!0),i(R,null,G(d.value,r=>(n(),i("div",{key:r.id,class:"flex items-start"},[D(e("input",{id:`client_${r.id}`,"onUpdate:modelValue":o[27]||(o[27]=F=>l.allowedClients=F),type:"checkbox",value:r.id,class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,ns),[[de,l.allowedClients]]),e("label",{for:`client_${r.id}`,class:"ml-2 flex-1 cursor-pointer"},[e("span",as,u(r.name),1),e("span",rs,u(r.description),1)],8,is)]))),128))])])])):y("",!0)]),e("div",ds,[e("button",{type:"button",class:"flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-lg font-semibold hover:bg-gray-200 transition-colors text-sm",onClick:o[28]||(o[28]=r=>_.$emit("close"))}," 取消 "),e("button",{type:"submit",disabled:$.value,class:"btn btn-primary flex-1 py-2.5 px-4 font-semibold text-sm"},[$.value?(n(),i("div",cs)):(n(),i("i",ms)),h(" "+u($.value?"创建中...":"创建"),1)],8,us)])],32)])])]))}},xs=ae(ps,[["__scopeId","data-v-627c6d2b"]]),gs={class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},fs={class:"modal-content w-full max-w-4xl p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] flex flex-col"},ys={class:"flex items-center justify-between mb-4 sm:mb-6"},bs=["value"],vs={class:"space-y-4"},ws={key:0},$s={class:"flex flex-wrap gap-2"},hs=["onClick"],As={key:1},Cs={class:"flex flex-wrap gap-2"},Ks=["onClick"],ks={class:"flex gap-2"},_s=["onKeypress"],Ds={class:"bg-blue-50 border border-blue-200 rounded-lg p-3"},Is={class:"space-y-2"},Ls={class:"grid grid-cols-1 lg:grid-cols-3 gap-2"},Ts={class:"space-y-3"},Ms={class:"flex gap-2"},Ss={class:"flex gap-4"},js={class:"flex items-center cursor-pointer"},Rs={class:"flex items-center cursor-pointer"},Es={class:"flex items-center cursor-pointer"},Ps={class:"flex items-center justify-between mb-3"},Us=["disabled"],Vs={class:"grid grid-cols-1 gap-3"},Gs=["disabled"],Os={key:0,label:"调度分组"},qs=["value"],Fs={key:1,label:"Claude OAuth 专属账号"},Ws=["value"],zs={key:2,label:"Claude Console 专属账号"},Ns=["value"],Ys=["disabled"],Bs={key:0,label:"调度分组"},Hs=["value"],Qs={key:1,label:"Gemini 专属账号"},Xs=["value"],Js={class:"flex items-center mb-3"},Zs={key:0,class:"space-y-3"},el={class:"flex flex-wrap gap-2 mb-3 min-h-[32px] p-2 bg-gray-50 rounded-lg border border-gray-200"},tl=["onClick"],sl={key:0,class:"text-gray-400 text-sm"},ll={class:"flex gap-2"},ol=["onKeydown"],nl={class:"flex items-center mb-3"},il={key:0,class:"space-y-3"},al={class:"space-y-2"},rl=["id","value"],dl=["for"],ul={class:"text-sm font-medium text-gray-700"},cl={class:"text-xs text-gray-500 block"},ml={class:"flex gap-3 pt-4"},pl=["disabled"],xl={key:0,class:"loading-spinner mr-2"},gl={key:1,class:"fas fa-save mr-2"},fl={__name:"EditApiKeyModal",props:{apiKey:{type:Object,required:!0},accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success"],setup(I,{emit:V}){const f=I,M=V;Re();const j=Ae(),C=Ee(),$=K(!1),O=K(!1),b=K({claude:[],gemini:[],claudeGroups:[],geminiGroups:[]}),q=K([]),L=K(""),w=K([]),k=ee(()=>w.value.filter(T=>!d.tags.includes(T))),d=be({name:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]}),l=()=>{d.modelInput&&!d.restrictedModels.includes(d.modelInput)&&(d.restrictedModels.push(d.modelInput),d.modelInput="")},N=T=>{d.restrictedModels.splice(T,1)},A=()=>{if(L.value&&L.value.trim()){const T=L.value.trim();d.tags.includes(T)||d.tags.push(T),L.value=""}},x=T=>{d.tags.includes(T)||d.tags.push(T)},p=T=>{d.tags.splice(T,1)},Y=async()=>{$.value=!0;try{const T={tokenLimit:d.tokenLimit!==""&&d.tokenLimit!==null?parseInt(d.tokenLimit):0,rateLimitWindow:d.rateLimitWindow!==""&&d.rateLimitWindow!==null?parseInt(d.rateLimitWindow):0,rateLimitRequests:d.rateLimitRequests!==""&&d.rateLimitRequests!==null?parseInt(d.rateLimitRequests):0,concurrencyLimit:d.concurrencyLimit!==""&&d.concurrencyLimit!==null?parseInt(d.concurrencyLimit):0,dailyCostLimit:d.dailyCostLimit!==""&&d.dailyCostLimit!==null?parseFloat(d.dailyCostLimit):0,permissions:d.permissions,claudeAccountId:d.claudeAccountId||null,geminiAccountId:d.geminiAccountId||null,tags:d.tags};T.enableModelRestriction=d.enableModelRestriction,T.restrictedModels=d.restrictedModels,T.enableClientRestriction=d.enableClientRestriction,T.allowedClients=d.allowedClients;const a=await U.put(`/admin/api-keys/${f.apiKey.id}`,T);a.success?(M("success"),M("close")):S(a.message||"更新失败","error")}catch{S("更新失败","error")}finally{$.value=!1}},H=async()=>{var T,a;O.value=!0;try{const[m,B,te,_]=await Promise.all([U.get("/admin/claude-accounts"),U.get("/admin/claude-console-accounts"),U.get("/admin/gemini-accounts"),U.get("/admin/account-groups")]),o=[];if(m.success&&((T=m.data)==null||T.forEach(r=>{o.push({...r,platform:"claude-oauth",isDedicated:r.accountType==="dedicated"})})),B.success&&((a=B.data)==null||a.forEach(r=>{o.push({...r,platform:"claude-console",isDedicated:r.accountType==="dedicated"})})),b.value.claude=o,te.success&&(b.value.gemini=(te.data||[]).map(r=>({...r,isDedicated:r.accountType==="dedicated"}))),_.success){const r=_.data||[];b.value.claudeGroups=r.filter(F=>F.platform==="claude"),b.value.geminiGroups=r.filter(F=>F.platform==="gemini")}S("账号列表已刷新","success")}catch{S("刷新账号列表失败","error")}finally{O.value=!1}};return he(async()=>{q.value=await j.loadSupportedClients(),w.value=await C.fetchTags(),f.accounts&&(b.value={claude:f.accounts.claude||[],gemini:f.accounts.gemini||[],claudeGroups:f.accounts.claudeGroups||[],geminiGroups:f.accounts.geminiGroups||[]}),d.name=f.apiKey.name,d.tokenLimit=f.apiKey.tokenLimit||"",d.rateLimitWindow=f.apiKey.rateLimitWindow||"",d.rateLimitRequests=f.apiKey.rateLimitRequests||"",d.concurrencyLimit=f.apiKey.concurrencyLimit||"",d.dailyCostLimit=f.apiKey.dailyCostLimit||"",d.permissions=f.apiKey.permissions||"all",d.claudeAccountId=f.apiKey.claudeAccountId||"",d.geminiAccountId=f.apiKey.geminiAccountId||"",d.restrictedModels=f.apiKey.restrictedModels||[],d.allowedClients=f.apiKey.allowedClients||[],d.tags=f.apiKey.tags||[],d.enableModelRestriction=f.apiKey.enableModelRestriction||!1,d.enableClientRestriction=f.apiKey.enableClientRestriction||!1}),(T,a)=>(n(),Z(ue,{to:"body"},[e("div",gs,[e("div",fs,[e("div",ys,[a[22]||(a[22]=e("div",{class:"flex items-center gap-2 sm:gap-3"},[e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-edit text-white text-sm sm:text-base"})]),e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 编辑 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:a[0]||(a[0]=m=>T.$emit("close"))},a[21]||(a[21]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),e("form",{class:"space-y-4 sm:space-y-6 modal-scroll-content custom-scrollbar flex-1",onSubmit:ie(Y,["prevent"])},[e("div",null,[a[23]||(a[23]=e("label",{class:"block text-xs sm:text-sm font-semibold text-gray-700 mb-1.5 sm:mb-3"},"名称",-1)),e("input",{value:d.name,type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed text-sm"},null,8,bs),a[24]||(a[24]=e("p",{class:"text-xs text-gray-500 mt-1 sm:mt-2"}," 名称不可修改 ",-1))]),e("div",null,[a[32]||(a[32]=e("label",{class:"block text-xs sm:text-sm font-semibold text-gray-700 mb-1.5 sm:mb-3"},"标签",-1)),e("div",vs,[d.tags.length>0?(n(),i("div",ws,[a[26]||(a[26]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 已选择的标签: ",-1)),e("div",$s,[(n(!0),i(R,null,G(d.tags,(m,B)=>(n(),i("span",{key:"selected-"+B,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[h(u(m)+" ",1),e("button",{type:"button",class:"ml-1 hover:text-blue-900",onClick:te=>p(B)},a[25]||(a[25]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,hs)]))),128))])])):y("",!0),k.value.length>0?(n(),i("div",As,[a[28]||(a[28]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 点击选择已有标签: ",-1)),e("div",Cs,[(n(!0),i(R,null,G(k.value,m=>(n(),i("button",{key:"available-"+m,type:"button",class:"inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors",onClick:B=>x(m)},[a[27]||(a[27]=e("i",{class:"fas fa-tag text-gray-500 text-xs"},null,-1)),h(" "+u(m),1)],8,Ks))),128))])])):y("",!0),e("div",null,[a[30]||(a[30]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 创建新标签: ",-1)),e("div",ks,[D(e("input",{"onUpdate:modelValue":a[1]||(a[1]=m=>L.value=m),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:ye(ie(A,["prevent"]),["enter"])},null,40,_s),[[z,L.value]]),e("button",{type:"button",class:"px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors",onClick:A},a[29]||(a[29]=[e("i",{class:"fas fa-plus"},null,-1)]))])]),a[31]||(a[31]=e("p",{class:"text-xs text-gray-500"}," 用于标记不同团队或用途,方便筛选管理 ",-1))])]),e("div",Ds,[a[40]||(a[40]=e("div",{class:"flex items-center gap-2 mb-2"},[e("div",{class:"w-6 h-6 bg-blue-500 rounded flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-tachometer-alt text-white text-xs"})]),e("h4",{class:"font-semibold text-gray-800 text-sm"}," 速率限制设置 (可选) ")],-1)),e("div",Is,[e("div",Ls,[e("div",null,[a[33]||(a[33]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"时间窗口 (分钟)",-1)),D(e("input",{"onUpdate:modelValue":a[2]||(a[2]=m=>d.rateLimitWindow=m),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,d.rateLimitWindow]]),a[34]||(a[34]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 时间段单位 ",-1))]),e("div",null,[a[35]||(a[35]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"请求次数限制",-1)),D(e("input",{"onUpdate:modelValue":a[3]||(a[3]=m=>d.rateLimitRequests=m),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,d.rateLimitRequests]]),a[36]||(a[36]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大请求 ",-1))]),e("div",null,[a[37]||(a[37]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"Token 限制",-1)),D(e("input",{"onUpdate:modelValue":a[4]||(a[4]=m=>d.tokenLimit=m),type:"number",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,d.tokenLimit]]),a[38]||(a[38]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大Token ",-1))])]),a[39]||(a[39]=e("div",{class:"bg-blue-100 rounded-lg p-2"},[e("h5",{class:"text-xs font-semibold text-blue-800 mb-1"}," 💡 使用示例 "),e("div",{class:"text-xs text-blue-700 space-y-0.5"},[e("div",null,[e("strong",null,"示例1:"),h(" 时间窗口=60,请求次数=1000 → 每60分钟最多1000次请求")]),e("div",null,[e("strong",null,"示例2:"),h(" 时间窗口=1,Token=10000 → 每分钟最多10,000个Token")]),e("div",null,[e("strong",null,"示例3:"),h(" 窗口=30,请求=50,Token=100000 → 每30分钟50次请求且不超10万Token")])])],-1))])]),e("div",null,[a[42]||(a[42]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"每日费用限制 (美元)",-1)),e("div",Ts,[e("div",Ms,[e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[5]||(a[5]=m=>d.dailyCostLimit="50")}," $50 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[6]||(a[6]=m=>d.dailyCostLimit="100")}," $100 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[7]||(a[7]=m=>d.dailyCostLimit="200")}," $200 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[8]||(a[8]=m=>d.dailyCostLimit="")}," 自定义 ")]),D(e("input",{"onUpdate:modelValue":a[9]||(a[9]=m=>d.dailyCostLimit=m),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,d.dailyCostLimit]]),a[41]||(a[41]=e("p",{class:"text-xs text-gray-500"}," 设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制 ",-1))])]),e("div",null,[a[43]||(a[43]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"并发限制",-1)),D(e("input",{"onUpdate:modelValue":a[10]||(a[10]=m=>d.concurrencyLimit=m),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,d.concurrencyLimit]]),a[44]||(a[44]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此 API Key 可同时处理的最大请求数 ",-1))]),e("div",null,[a[48]||(a[48]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"服务权限",-1)),e("div",Ss,[e("label",js,[D(e("input",{"onUpdate:modelValue":a[11]||(a[11]=m=>d.permissions=m),type:"radio",value:"all",class:"mr-2"},null,512),[[ne,d.permissions]]),a[45]||(a[45]=e("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),e("label",Rs,[D(e("input",{"onUpdate:modelValue":a[12]||(a[12]=m=>d.permissions=m),type:"radio",value:"claude",class:"mr-2"},null,512),[[ne,d.permissions]]),a[46]||(a[46]=e("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),e("label",Es,[D(e("input",{"onUpdate:modelValue":a[13]||(a[13]=m=>d.permissions=m),type:"radio",value:"gemini",class:"mr-2"},null,512),[[ne,d.permissions]]),a[47]||(a[47]=e("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),a[49]||(a[49]=e("p",{class:"text-xs text-gray-500 mt-2"}," 控制此 API Key 可以访问哪些服务 ",-1))]),e("div",null,[e("div",Ps,[a[50]||(a[50]=e("label",{class:"text-sm font-semibold text-gray-700"},"专属账号绑定",-1)),e("button",{type:"button",class:"text-blue-600 hover:text-blue-800 text-sm flex items-center gap-1 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",title:"刷新账号列表",disabled:O.value,onClick:H},[e("i",{class:P(["fas",O.value?"fa-spinner fa-spin":"fa-sync-alt","text-xs"])},null,2),e("span",null,u(O.value?"刷新中...":"刷新账号"),1)],8,Us)]),e("div",Vs,[e("div",null,[a[52]||(a[52]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),D(e("select",{"onUpdate:modelValue":a[14]||(a[14]=m=>d.claudeAccountId=m),class:"form-input w-full",disabled:d.permissions==="gemini"},[a[51]||(a[51]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.claudeGroups&&b.value.claudeGroups.length>0?(n(),i("optgroup",Os,[(n(!0),i(R,null,G(b.value.claudeGroups,m=>(n(),i("option",{key:`group:${m.id}`,value:`group:${m.id}`},u(m.name)+" ("+u(m.memberCount||0)+" 个成员) ",9,qs))),128))])):y("",!0),b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-oauth").length>0?(n(),i("optgroup",Fs,[(n(!0),i(R,null,G(b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-oauth"),m=>(n(),i("option",{key:m.id,value:m.id},u(m.name)+" ("+u(m.status==="active"?"正常":"异常")+") ",9,Ws))),128))])):y("",!0),b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-console").length>0?(n(),i("optgroup",zs,[(n(!0),i(R,null,G(b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-console"),m=>(n(),i("option",{key:m.id,value:`console:${m.id}`},u(m.name)+" ("+u(m.status==="active"?"正常":"异常")+") ",9,Ns))),128))])):y("",!0)],8,Gs),[[le,d.claudeAccountId]])]),e("div",null,[a[54]||(a[54]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),D(e("select",{"onUpdate:modelValue":a[15]||(a[15]=m=>d.geminiAccountId=m),class:"form-input w-full",disabled:d.permissions==="claude"},[a[53]||(a[53]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.geminiGroups&&b.value.geminiGroups.length>0?(n(),i("optgroup",Bs,[(n(!0),i(R,null,G(b.value.geminiGroups,m=>(n(),i("option",{key:`group:${m.id}`,value:`group:${m.id}`},u(m.name)+" ("+u(m.memberCount||0)+" 个成员) ",9,Hs))),128))])):y("",!0),b.value.gemini.filter(m=>m.accountType==="dedicated").length>0?(n(),i("optgroup",Qs,[(n(!0),i(R,null,G(b.value.gemini.filter(m=>m.accountType==="dedicated"),m=>(n(),i("option",{key:m.id,value:m.id},u(m.name)+" ("+u(m.status==="active"?"正常":"异常")+") ",9,Xs))),128))])):y("",!0)],8,Ys),[[le,d.geminiAccountId]])])]),a[55]||(a[55]=e("p",{class:"text-xs text-gray-500 mt-2"}," 修改绑定账号将影响此API Key的请求路由 ",-1))]),e("div",null,[e("div",Js,[D(e("input",{id:"editEnableModelRestriction","onUpdate:modelValue":a[16]||(a[16]=m=>d.enableModelRestriction=m),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,d.enableModelRestriction]]),a[56]||(a[56]=e("label",{for:"editEnableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),d.enableModelRestriction?(n(),i("div",Zs,[e("div",null,[a[59]||(a[59]=e("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"限制的模型列表",-1)),e("div",el,[(n(!0),i(R,null,G(d.restrictedModels,(m,B)=>(n(),i("span",{key:B,class:"inline-flex items-center px-3 py-1 rounded-full text-sm bg-red-100 text-red-800"},[h(u(m)+" ",1),e("button",{type:"button",class:"ml-2 text-red-600 hover:text-red-800",onClick:te=>N(B)},a[57]||(a[57]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,tl)]))),128)),d.restrictedModels.length===0?(n(),i("span",sl," 暂无限制的模型 ")):y("",!0)]),e("div",ll,[D(e("input",{"onUpdate:modelValue":a[17]||(a[17]=m=>d.modelInput=m),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1",onKeydown:ye(ie(l,["prevent"]),["enter"])},null,40,ol),[[z,d.modelInput]]),e("button",{type:"button",class:"px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors",onClick:l},a[58]||(a[58]=[e("i",{class:"fas fa-plus"},null,-1)]))]),a[60]||(a[60]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此API Key无法访问的模型,例如:claude-opus-4-20250514 ",-1))])])):y("",!0)]),e("div",null,[e("div",nl,[D(e("input",{id:"editEnableClientRestriction","onUpdate:modelValue":a[18]||(a[18]=m=>d.enableClientRestriction=m),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,d.enableClientRestriction]]),a[61]||(a[61]=e("label",{for:"editEnableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),d.enableClientRestriction?(n(),i("div",il,[e("div",null,[a[62]||(a[62]=e("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"允许的客户端",-1)),a[63]||(a[63]=e("p",{class:"text-xs text-gray-500 mb-3"}," 勾选允许使用此API Key的客户端 ",-1)),e("div",al,[(n(!0),i(R,null,G(q.value,m=>(n(),i("div",{key:m.id,class:"flex items-start"},[D(e("input",{id:`edit_client_${m.id}`,"onUpdate:modelValue":a[19]||(a[19]=B=>d.allowedClients=B),type:"checkbox",value:m.id,class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,rl),[[de,d.allowedClients]]),e("label",{for:`edit_client_${m.id}`,class:"ml-2 flex-1 cursor-pointer"},[e("span",ul,u(m.name),1),e("span",cl,u(m.description),1)],8,dl)]))),128))])])])):y("",!0)]),e("div",ml,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:a[20]||(a[20]=m=>T.$emit("close"))}," 取消 "),e("button",{type:"submit",disabled:$.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[$.value?(n(),i("div",xl)):(n(),i("i",gl)),h(" "+u($.value?"保存中...":"保存修改"),1)],8,pl)])],32)])])]))}},yl=ae(fl,[["__scopeId","data-v-12fe4aaf"]]),bl={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},vl={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},wl={class:"flex items-center justify-between mb-6"},$l={class:"space-y-6 modal-scroll-content custom-scrollbar flex-1"},hl={class:"bg-blue-50 border border-blue-200 rounded-lg p-4"},Al={class:"flex items-start gap-3"},Cl={class:"text-sm text-gray-700"},Kl={class:"text-xs text-gray-600 mt-1"},kl={key:0,class:"mt-3"},_l=["min"],Dl={key:1,class:"text-xs text-gray-500 mt-2"},Il={class:"flex gap-3 pt-4"},Ll=["disabled"],Tl={key:0,class:"loading-spinner mr-2"},Ml={key:1,class:"fas fa-clock mr-2"},Sl={__name:"RenewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close","success"],setup(I,{emit:V}){const f=I,M=V;Re();const j=K(!1),C=be({renewDuration:"30d",customExpireDate:"",newExpiresAt:null}),$=ee(()=>{const w=new Date;return f.apiKey.expiresAt&&new Date(f.apiKey.expiresAt)>w?new Date(f.apiKey.expiresAt).toISOString().slice(0,16):(w.setMinutes(w.getMinutes()+1),w.toISOString().slice(0,16))}),O=w=>new Date(w).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),b=()=>{if(!C.renewDuration){C.newExpiresAt=null;return}if(C.renewDuration==="permanent"){C.newExpiresAt=null;return}if(C.renewDuration==="custom")return;const w=f.apiKey.expiresAt&&new Date(f.apiKey.expiresAt)>new Date?new Date(f.apiKey.expiresAt):new Date,d=C.renewDuration.match(/(\d+)([dhmy])/);if(d){const[,l,N]=d,A=parseInt(l);switch(N){case"d":w.setDate(w.getDate()+A);break;case"h":w.setHours(w.getHours()+A);break;case"m":w.setMonth(w.getMonth()+A);break;case"y":w.setFullYear(w.getFullYear()+A);break}C.newExpiresAt=w.toISOString()}},q=()=>{C.customExpireDate&&(C.newExpiresAt=new Date(C.customExpireDate).toISOString())},L=async()=>{j.value=!0;try{const w={expiresAt:C.renewDuration==="permanent"?null:C.newExpiresAt},k=await U.put(`/admin/api-keys/${f.apiKey.id}/renew`,w);k.success?(S("API Key 续期成功","success"),M("success"),M("close")):S(k.message||"续期失败","error")}catch{S("续期失败","error")}finally{j.value=!1}};return b(),(w,k)=>(n(),Z(ue,{to:"body"},[e("div",bl,[e("div",vl,[e("div",wl,[k[5]||(k[5]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-clock text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 续期 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:k[0]||(k[0]=d=>w.$emit("close"))},k[4]||(k[4]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("div",$l,[e("div",hl,[e("div",Al,[k[7]||(k[7]=e("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-info text-white text-sm"})],-1)),e("div",null,[k[6]||(k[6]=e("h4",{class:"font-semibold text-gray-800 mb-1"}," API Key 信息 ",-1)),e("p",Cl,u(I.apiKey.name),1),e("p",Kl," 当前过期时间:"+u(I.apiKey.expiresAt?O(I.apiKey.expiresAt):"永不过期"),1)])])]),e("div",null,[k[9]||(k[9]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"续期时长",-1)),D(e("select",{"onUpdate:modelValue":k[1]||(k[1]=d=>C.renewDuration=d),class:"form-input w-full",onChange:b},k[8]||(k[8]=[e("option",{value:"7d"}," 延长 7 天 ",-1),e("option",{value:"30d"}," 延长 30 天 ",-1),e("option",{value:"90d"}," 延长 90 天 ",-1),e("option",{value:"180d"}," 延长 180 天 ",-1),e("option",{value:"365d"}," 延长 365 天 ",-1),e("option",{value:"custom"}," 自定义日期 ",-1),e("option",{value:"permanent"}," 设为永不过期 ",-1)]),544),[[le,C.renewDuration]]),C.renewDuration==="custom"?(n(),i("div",kl,[D(e("input",{"onUpdate:modelValue":k[2]||(k[2]=d=>C.customExpireDate=d),type:"datetime-local",class:"form-input w-full",min:$.value,onChange:q},null,40,_l),[[z,C.customExpireDate]])])):y("",!0),C.newExpiresAt?(n(),i("p",Dl," 新的过期时间:"+u(O(C.newExpiresAt)),1)):y("",!0)])]),e("div",Il,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:k[3]||(k[3]=d=>w.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:j.value||!C.renewDuration,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:L},[j.value?(n(),i("div",Tl)):(n(),i("i",Ml)),h(" "+u(j.value?"续期中...":"确认续期"),1)],8,Ll)])])])]))}},jl=ae(Sl,[["__scopeId","data-v-0c3b1b3f"]]),Rl={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},El={class:"modal-content w-full max-w-lg p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Pl={class:"space-y-4 mb-6"},Ul={class:"p-3 bg-gray-50 rounded-lg border"},Vl={class:"text-gray-900 font-medium"},Gl={key:0},Ol={class:"p-3 bg-gray-50 rounded-lg border"},ql={class:"text-gray-700"},Fl={class:"relative"},Wl={class:"p-4 pr-14 bg-gray-900 rounded-lg border font-mono text-sm text-white break-all min-h-[60px] flex items-center"},zl={class:"absolute top-3 right-3"},Nl=["title"],Yl={__name:"NewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close"],setup(I,{emit:V}){const f=I,M=V,j=K(!1),C=()=>{j.value=!j.value},$=()=>{const L=f.apiKey.apiKey||f.apiKey.key||"";return L?j.value||L.length<=12?L:L.substring(0,8)+"●".repeat(Math.max(0,L.length-12))+L.substring(L.length-4):""},O=async()=>{const L=f.apiKey.apiKey||f.apiKey.key||"";if(!L){S("API Key 不存在","error");return}try{await navigator.clipboard.writeText(L),S("API Key 已复制到剪贴板","success")}catch(w){console.error("Failed to copy:",w);const k=document.createElement("textarea");k.value=L,document.body.appendChild(k),k.select();try{document.execCommand("copy"),S("API Key 已复制到剪贴板","success")}catch{S("复制失败,请手动复制","error")}finally{document.body.removeChild(k)}}},b=async()=>{window.showConfirm?await window.showConfirm("关闭提醒",`关闭后将无法再次查看完整的API Key,请确保已经妥善保存。
+import{E as Xe}from"./element-plus-B8Fs_0jW.js";import{aR as je,r as K,c as ee,_ as be,q as he,I as Z,y as n,z as e,Y as ie,x as i,L as y,C as P,K as D,an as ne,O as h,aq as z,P as u,Q as R,ac as G,aa as ye,aX as le,al as de,a5 as ue,o as $e,R as Se,B as Je}from"./vue-vendor-CKToUHZx.js";import{s as S}from"./toast-BvwA7Mwb.js";import{a as U,_ as ae,u as Re}from"./index-D1PUfDNP.js";import"./vendor-BDiMbLwQ.js";const Ae=je("clients",{state:()=>({supportedClients:[],loading:!1,error:null}),actions:{async loadSupportedClients(){if(this.supportedClients.length>0)return this.supportedClients;this.loading=!0,this.error=null;try{const I=await U.get("/admin/supported-clients");return I.success?this.supportedClients=I.data||[]:(this.error=I.message||"加载支持的客户端失败",console.error("Failed to load supported clients:",this.error)),this.supportedClients}catch(I){return this.error=I.message||"加载支持的客户端失败",console.error("Error loading supported clients:",I),[]}finally{this.loading=!1}}}}),Ee=je("apiKeys",()=>{const I=K([]),V=K(!1),f=K(null),M=K("all"),j=K(""),C=K("asc"),$=async()=>{V.value=!0,f.value=null;try{const A=await U.get("/admin/api-keys");if(A.success)I.value=A.data||[];else throw new Error(A.message||"获取API Keys失败")}catch(A){throw f.value=A.message,A}finally{V.value=!1}};return{apiKeys:I,loading:V,error:f,statsTimeRange:M,sortBy:j,sortOrder:C,fetchApiKeys:$,createApiKey:async A=>{V.value=!0,f.value=null;try{const x=await U.post("/admin/api-keys",A);if(x.success)return await $(),x.data;throw new Error(x.message||"创建API Key失败")}catch(x){throw f.value=x.message,x}finally{V.value=!1}},updateApiKey:async(A,x)=>{V.value=!0,f.value=null;try{const p=await U.put(`/admin/api-keys/${A}`,x);if(p.success)return await $(),p;throw new Error(p.message||"更新API Key失败")}catch(p){throw f.value=p.message,p}finally{V.value=!1}},toggleApiKey:async A=>{V.value=!0,f.value=null;try{const x=await U.put(`/admin/api-keys/${A}/toggle`);if(x.success)return await $(),x;throw new Error(x.message||"切换状态失败")}catch(x){throw f.value=x.message,x}finally{V.value=!1}},renewApiKey:async(A,x)=>{V.value=!0,f.value=null;try{const p=await U.put(`/admin/api-keys/${A}/renew`,x);if(p.success)return await $(),p;throw new Error(p.message||"续期失败")}catch(p){throw f.value=p.message,p}finally{V.value=!1}},deleteApiKey:async A=>{V.value=!0,f.value=null;try{const x=await U.delete(`/admin/api-keys/${A}`);if(x.success)return await $(),x;throw new Error(x.message||"删除失败")}catch(x){throw f.value=x.message,x}finally{V.value=!1}},fetchApiKeyStats:async(A,x="all")=>{try{const p=await U.get(`/admin/api-keys/${A}/stats`,{params:{timeRange:x}});if(p.success)return p.stats;throw new Error(p.message||"获取统计失败")}catch(p){return console.error("获取API Key统计失败:",p),null}},fetchTags:async()=>{try{const A=await U.get("/admin/api-keys/tags");if(A.success)return A.data||[];throw new Error(A.message||"获取标签失败")}catch(A){return console.error("获取标签失败:",A),[]}},sortApiKeys:A=>{j.value===A?C.value=C.value==="asc"?"desc":"asc":(j.value=A,C.value="asc")},reset:()=>{I.value=[],V.value=!1,f.value=null,M.value="all",j.value="",C.value="asc"}}}),Ze={class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},et={class:"modal-content w-full max-w-4xl p-4 sm:p-6 mx-auto max-h-[90vh] flex flex-col"},tt={class:"flex items-center justify-between mb-4"},st={class:"bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg p-3 sm:p-4 border border-blue-200"},lt={class:"flex gap-3 sm:gap-4 items-center"},ot={class:"flex items-center cursor-pointer"},nt={class:"flex items-center cursor-pointer"},it={key:0,class:"mt-3"},at={class:"flex items-center gap-4"},rt={class:"flex-1"},dt={class:"flex items-center gap-2"},ut={class:"text-xs text-amber-600 mt-2 flex items-start"},ct=["placeholder"],mt={key:0,class:"text-red-500 text-xs mt-1"},pt={class:"space-y-4"},xt={key:0},gt={class:"flex flex-wrap gap-2"},ft=["onClick"],yt={key:1},bt={class:"flex flex-wrap gap-2"},vt=["onClick"],wt={class:"flex gap-2"},$t=["onKeypress"],ht={class:"bg-blue-50 border border-blue-200 rounded-lg p-3"},At={class:"space-y-2"},Ct={class:"grid grid-cols-1 lg:grid-cols-3 gap-2"},Kt={class:"space-y-2"},kt={class:"flex gap-2"},_t={key:0,class:"mt-3"},Dt=["min"],It={key:1,class:"text-xs text-gray-500 mt-2"},Lt={class:"flex gap-4"},Tt={class:"flex items-center cursor-pointer"},Mt={class:"flex items-center cursor-pointer"},St={class:"flex items-center cursor-pointer"},jt={class:"flex items-center justify-between mb-2"},Rt=["disabled"],Et={class:"grid grid-cols-1 gap-3"},Pt=["disabled"],Ut={key:0,label:"调度分组"},Vt=["value"],Gt={key:1,label:"Claude OAuth 专属账号"},Ot=["value"],qt={key:2,label:"Claude Console 专属账号"},Ft=["value"],Wt=["disabled"],zt={key:0,label:"调度分组"},Nt=["value"],Yt={key:1,label:"Gemini 专属账号"},Bt=["value"],Ht={class:"flex items-center mb-2"},Qt={key:0,class:"space-y-2 bg-red-50 border border-red-200 rounded-lg p-3"},Xt={class:"flex flex-wrap gap-1 mb-2 min-h-[24px]"},Jt=["onClick"],Zt={key:0,class:"text-gray-400 text-xs"},es={class:"flex gap-2"},ts=["onKeydown"],ss={class:"flex items-center mb-2"},ls={key:0,class:"bg-green-50 border border-green-200 rounded-lg p-3"},os={class:"space-y-1"},ns=["id","value"],is=["for"],as={class:"text-sm font-medium text-gray-700"},rs={class:"text-xs text-gray-500 block"},ds={class:"flex gap-3 pt-2"},us=["disabled"],cs={key:0,class:"loading-spinner mr-2"},ms={key:1,class:"fas fa-plus mr-2"},ps={__name:"CreateApiKeyModal",props:{accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success","batch-success"],setup(I,{emit:V}){const f=I,M=V,j=Ae(),C=Ee(),$=K(!1),O=K(!1),b=K({claude:[],gemini:[],claudeGroups:[],geminiGroups:[]}),q=K({name:""}),L=K(""),w=K([]),k=ee(()=>w.value.filter(_=>!l.tags.includes(_))),d=K([]),l=be({createType:"single",batchCount:10,name:"",description:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",expireDuration:"",customExpireDate:"",expiresAt:null,permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]});he(async()=>{d.value=await j.loadSupportedClients(),w.value=await C.fetchTags(),f.accounts&&(b.value={claude:f.accounts.claude||[],gemini:f.accounts.gemini||[],claudeGroups:f.accounts.claudeGroups||[],geminiGroups:f.accounts.geminiGroups||[]})});const N=async()=>{var _,o;O.value=!0;try{const[r,F,Q,se]=await Promise.all([U.get("/admin/claude-accounts"),U.get("/admin/claude-console-accounts"),U.get("/admin/gemini-accounts"),U.get("/admin/account-groups")]),re=[];if(r.success&&((_=r.data)==null||_.forEach(X=>{re.push({...X,platform:"claude-oauth",isDedicated:X.accountType==="dedicated"})})),F.success&&((o=F.data)==null||o.forEach(X=>{re.push({...X,platform:"claude-console",isDedicated:X.accountType==="dedicated"})})),b.value.claude=re,Q.success&&(b.value.gemini=(Q.data||[]).map(X=>({...X,isDedicated:X.accountType==="dedicated"}))),se.success){const X=se.data||[];b.value.claudeGroups=X.filter(J=>J.platform==="claude"),b.value.geminiGroups=X.filter(J=>J.platform==="gemini")}S("账号列表已刷新","success")}catch{S("刷新账号列表失败","error")}finally{O.value=!1}},A=ee(()=>{const _=new Date;return _.setMinutes(_.getMinutes()+1),_.toISOString().slice(0,16)}),x=()=>{if(!l.expireDuration){l.expiresAt=null;return}if(l.expireDuration==="custom")return;const _=new Date,r=l.expireDuration.match(/(\d+)([dhmy])/);if(r){const[,F,Q]=r,se=parseInt(F);switch(Q){case"d":_.setDate(_.getDate()+se);break;case"h":_.setHours(_.getHours()+se);break;case"m":_.setMonth(_.getMonth()+se);break;case"y":_.setFullYear(_.getFullYear()+se);break}l.expiresAt=_.toISOString()}},p=()=>{l.customExpireDate&&(l.expiresAt=new Date(l.customExpireDate).toISOString())},Y=_=>new Date(_).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),H=()=>{l.modelInput&&!l.restrictedModels.includes(l.modelInput)&&(l.restrictedModels.push(l.modelInput),l.modelInput="")},T=_=>{l.restrictedModels.splice(_,1)},a=()=>{if(L.value&&L.value.trim()){const _=L.value.trim();l.tags.includes(_)||l.tags.push(_),L.value=""}},m=_=>{l.tags.includes(_)||l.tags.push(_)},B=_=>{l.tags.splice(_,1)},te=async()=>{if(q.value.name="",!l.name||!l.name.trim()){q.value.name="请输入API Key名称";return}if(l.createType==="batch"&&(!l.batchCount||l.batchCount<2||l.batchCount>500)){S("批量创建数量必须在 2-500 之间","error");return}$.value=!0;try{const _={description:l.description||void 0,tokenLimit:l.tokenLimit!==""&&l.tokenLimit!==null?parseInt(l.tokenLimit):null,rateLimitWindow:l.rateLimitWindow!==""&&l.rateLimitWindow!==null?parseInt(l.rateLimitWindow):null,rateLimitRequests:l.rateLimitRequests!==""&&l.rateLimitRequests!==null?parseInt(l.rateLimitRequests):null,concurrencyLimit:l.concurrencyLimit!==""&&l.concurrencyLimit!==null?parseInt(l.concurrencyLimit):0,dailyCostLimit:l.dailyCostLimit!==""&&l.dailyCostLimit!==null?parseFloat(l.dailyCostLimit):0,expiresAt:l.expiresAt||void 0,permissions:l.permissions,tags:l.tags.length>0?l.tags:void 0,enableModelRestriction:l.enableModelRestriction,restrictedModels:l.restrictedModels,enableClientRestriction:l.enableClientRestriction,allowedClients:l.allowedClients};if(l.claudeAccountId&&(l.claudeAccountId.startsWith("console:")?_.claudeConsoleAccountId=l.claudeAccountId.substring(8):_.claudeAccountId=l.claudeAccountId),l.geminiAccountId&&(_.geminiAccountId=l.geminiAccountId),l.createType==="single"){const o={..._,name:l.name},r=await U.post("/admin/api-keys",o);r.success?(S("API Key 创建成功","success"),M("success",r.data),M("close")):S(r.message||"创建失败","error")}else{const o={..._,createType:"batch",baseName:l.name,count:l.batchCount},r=await U.post("/admin/api-keys/batch",o);r.success?(S(`成功创建 ${r.data.length} 个 API Key`,"success"),M("batch-success",r.data),M("close")):S(r.message||"批量创建失败","error")}}catch{S("创建失败","error")}finally{$.value=!1}};return(_,o)=>(n(),Z(ue,{to:"body"},[e("div",Ze,[e("div",et,[e("div",tt,[o[30]||(o[30]=e("div",{class:"flex items-center gap-2 sm:gap-3"},[e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-key text-white text-sm sm:text-base"})]),e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 创建新的 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:o[0]||(o[0]=r=>_.$emit("close"))},o[29]||(o[29]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),e("form",{class:"space-y-4 modal-scroll-content custom-scrollbar flex-1",onSubmit:ie(te,["prevent"])},[e("div",st,[e("div",{class:P(["flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3",l.createType==="batch"?"mb-3":""])},[o[33]||(o[33]=e("label",{class:"text-xs sm:text-sm font-semibold text-gray-700 flex items-center h-full"},"创建类型",-1)),e("div",lt,[e("label",ot,[D(e("input",{"onUpdate:modelValue":o[1]||(o[1]=r=>l.createType=r),type:"radio",value:"single",class:"mr-1.5 sm:mr-2 text-blue-600"},null,512),[[ne,l.createType]]),o[31]||(o[31]=e("span",{class:"text-xs sm:text-sm text-gray-700 flex items-center"},[e("i",{class:"fas fa-key mr-1 text-xs"}),h(" 单个创建 ")],-1))]),e("label",nt,[D(e("input",{"onUpdate:modelValue":o[2]||(o[2]=r=>l.createType=r),type:"radio",value:"batch",class:"mr-1.5 sm:mr-2 text-blue-600"},null,512),[[ne,l.createType]]),o[32]||(o[32]=e("span",{class:"text-xs sm:text-sm text-gray-700 flex items-center"},[e("i",{class:"fas fa-layer-group mr-1 text-xs"}),h(" 批量创建 ")],-1))])])],2),l.createType==="batch"?(n(),i("div",it,[e("div",at,[e("div",rt,[o[35]||(o[35]=e("label",{class:"block text-xs font-medium text-gray-600 mb-1"},"创建数量",-1)),e("div",dt,[D(e("input",{"onUpdate:modelValue":o[3]||(o[3]=r=>l.batchCount=r),type:"number",min:"2",max:"500",required:"",class:"form-input w-full text-sm",placeholder:"输入数量 (2-500)"},null,512),[[z,l.batchCount,void 0,{number:!0}]]),o[34]||(o[34]=e("div",{class:"text-xs text-gray-500 whitespace-nowrap"}," 最大支持 500 个 ",-1))])])]),e("p",ut,[o[36]||(o[36]=e("i",{class:"fas fa-info-circle mr-1 mt-0.5 flex-shrink-0"},null,-1)),e("span",null,"批量创建时,每个 Key 的名称会自动添加序号后缀,例如:"+u(l.name||"MyKey")+"_1, "+u(l.name||"MyKey")+"_2 ...",1)])])):y("",!0)]),e("div",null,[o[37]||(o[37]=e("label",{class:"block text-xs sm:text-sm font-semibold text-gray-700 mb-1.5 sm:mb-2"},[h("名称 "),e("span",{class:"text-red-500"},"*")],-1)),D(e("input",{"onUpdate:modelValue":o[4]||(o[4]=r=>l.name=r),type:"text",required:"",class:P(["form-input w-full text-sm",{"border-red-500":q.value.name}]),placeholder:l.createType==="batch"?"输入基础名称(将自动添加序号)":"为您的 API Key 取一个名称",onInput:o[5]||(o[5]=r=>q.value.name="")},null,42,ct),[[z,l.name]]),q.value.name?(n(),i("p",mt,u(q.value.name),1)):y("",!0)]),e("div",null,[o[45]||(o[45]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"标签",-1)),e("div",pt,[l.tags.length>0?(n(),i("div",xt,[o[39]||(o[39]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 已选择的标签: ",-1)),e("div",gt,[(n(!0),i(R,null,G(l.tags,(r,F)=>(n(),i("span",{key:"selected-"+F,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[h(u(r)+" ",1),e("button",{type:"button",class:"ml-1 hover:text-blue-900",onClick:Q=>B(F)},o[38]||(o[38]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,ft)]))),128))])])):y("",!0),k.value.length>0?(n(),i("div",yt,[o[41]||(o[41]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 点击选择已有标签: ",-1)),e("div",bt,[(n(!0),i(R,null,G(k.value,r=>(n(),i("button",{key:"available-"+r,type:"button",class:"inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors",onClick:F=>m(r)},[o[40]||(o[40]=e("i",{class:"fas fa-tag text-gray-500 text-xs"},null,-1)),h(" "+u(r),1)],8,vt))),128))])])):y("",!0),e("div",null,[o[43]||(o[43]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 创建新标签: ",-1)),e("div",wt,[D(e("input",{"onUpdate:modelValue":o[6]||(o[6]=r=>L.value=r),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:ye(ie(a,["prevent"]),["enter"])},null,40,$t),[[z,L.value]]),e("button",{type:"button",class:"px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors",onClick:a},o[42]||(o[42]=[e("i",{class:"fas fa-plus"},null,-1)]))])]),o[44]||(o[44]=e("p",{class:"text-xs text-gray-500"}," 用于标记不同团队或用途,方便筛选管理 ",-1))])]),e("div",ht,[o[53]||(o[53]=e("div",{class:"flex items-center gap-2 mb-2"},[e("div",{class:"w-6 h-6 bg-blue-500 rounded flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-tachometer-alt text-white text-xs"})]),e("h4",{class:"font-semibold text-gray-800 text-sm"}," 速率限制设置 (可选) ")],-1)),e("div",At,[e("div",Ct,[e("div",null,[o[46]||(o[46]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"时间窗口 (分钟)",-1)),D(e("input",{"onUpdate:modelValue":o[7]||(o[7]=r=>l.rateLimitWindow=r),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,l.rateLimitWindow]]),o[47]||(o[47]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 时间段单位 ",-1))]),e("div",null,[o[48]||(o[48]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"请求次数限制",-1)),D(e("input",{"onUpdate:modelValue":o[8]||(o[8]=r=>l.rateLimitRequests=r),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,l.rateLimitRequests]]),o[49]||(o[49]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大请求 ",-1))]),e("div",null,[o[50]||(o[50]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"Token 限制",-1)),D(e("input",{"onUpdate:modelValue":o[9]||(o[9]=r=>l.tokenLimit=r),type:"number",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,l.tokenLimit]]),o[51]||(o[51]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大Token ",-1))])]),o[52]||(o[52]=e("div",{class:"bg-blue-100 rounded-lg p-2"},[e("h5",{class:"text-xs font-semibold text-blue-800 mb-1"}," 💡 使用示例 "),e("div",{class:"text-xs text-blue-700 space-y-0.5"},[e("div",null,[e("strong",null,"示例1:"),h(" 时间窗口=60,请求次数=1000 → 每60分钟最多1000次请求")]),e("div",null,[e("strong",null,"示例2:"),h(" 时间窗口=1,Token=10000 → 每分钟最多10,000个Token")]),e("div",null,[e("strong",null,"示例3:"),h(" 窗口=30,请求=50,Token=100000 → 每30分钟50次请求且不超10万Token")])])],-1))])]),e("div",null,[o[55]||(o[55]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"每日费用限制 (美元)",-1)),e("div",Kt,[e("div",kt,[e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[10]||(o[10]=r=>l.dailyCostLimit="50")}," $50 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[11]||(o[11]=r=>l.dailyCostLimit="100")}," $100 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[12]||(o[12]=r=>l.dailyCostLimit="200")}," $200 "),e("button",{type:"button",class:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs font-medium",onClick:o[13]||(o[13]=r=>l.dailyCostLimit="")}," 自定义 ")]),D(e("input",{"onUpdate:modelValue":o[14]||(o[14]=r=>l.dailyCostLimit=r),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,l.dailyCostLimit]]),o[54]||(o[54]=e("p",{class:"text-xs text-gray-500"}," 设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制 ",-1))])]),e("div",null,[o[56]||(o[56]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"并发限制 (可选)",-1)),D(e("input",{"onUpdate:modelValue":o[15]||(o[15]=r=>l.concurrencyLimit=r),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,l.concurrencyLimit]]),o[57]||(o[57]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此 API Key 可同时处理的最大请求数,0 或留空表示无限制 ",-1))]),e("div",null,[o[58]||(o[58]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"备注 (可选)",-1)),D(e("textarea",{"onUpdate:modelValue":o[16]||(o[16]=r=>l.description=r),rows:"2",class:"form-input w-full resize-none text-sm",placeholder:"描述此 API Key 的用途..."},null,512),[[z,l.description]])]),e("div",null,[o[60]||(o[60]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"有效期限",-1)),D(e("select",{"onUpdate:modelValue":o[17]||(o[17]=r=>l.expireDuration=r),class:"form-input w-full",onChange:x},o[59]||(o[59]=[e("option",{value:""}," 永不过期 ",-1),e("option",{value:"1d"}," 1 天 ",-1),e("option",{value:"7d"}," 7 天 ",-1),e("option",{value:"30d"}," 30 天 ",-1),e("option",{value:"90d"}," 90 天 ",-1),e("option",{value:"180d"}," 180 天 ",-1),e("option",{value:"365d"}," 365 天 ",-1),e("option",{value:"custom"}," 自定义日期 ",-1)]),544),[[le,l.expireDuration]]),l.expireDuration==="custom"?(n(),i("div",_t,[D(e("input",{"onUpdate:modelValue":o[18]||(o[18]=r=>l.customExpireDate=r),type:"datetime-local",class:"form-input w-full",min:A.value,onChange:p},null,40,Dt),[[z,l.customExpireDate]])])):y("",!0),l.expiresAt?(n(),i("p",It," 将于 "+u(Y(l.expiresAt))+" 过期 ",1)):y("",!0)]),e("div",null,[o[64]||(o[64]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"服务权限",-1)),e("div",Lt,[e("label",Tt,[D(e("input",{"onUpdate:modelValue":o[19]||(o[19]=r=>l.permissions=r),type:"radio",value:"all",class:"mr-2"},null,512),[[ne,l.permissions]]),o[61]||(o[61]=e("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),e("label",Mt,[D(e("input",{"onUpdate:modelValue":o[20]||(o[20]=r=>l.permissions=r),type:"radio",value:"claude",class:"mr-2"},null,512),[[ne,l.permissions]]),o[62]||(o[62]=e("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),e("label",St,[D(e("input",{"onUpdate:modelValue":o[21]||(o[21]=r=>l.permissions=r),type:"radio",value:"gemini",class:"mr-2"},null,512),[[ne,l.permissions]]),o[63]||(o[63]=e("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),o[65]||(o[65]=e("p",{class:"text-xs text-gray-500 mt-2"}," 控制此 API Key 可以访问哪些服务 ",-1))]),e("div",null,[e("div",jt,[o[66]||(o[66]=e("label",{class:"text-sm font-semibold text-gray-700"},"专属账号绑定 (可选)",-1)),e("button",{type:"button",class:"text-blue-600 hover:text-blue-800 text-sm flex items-center gap-1 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",title:"刷新账号列表",disabled:O.value,onClick:N},[e("i",{class:P(["fas",O.value?"fa-spinner fa-spin":"fa-sync-alt","text-xs"])},null,2),e("span",null,u(O.value?"刷新中...":"刷新账号"),1)],8,Rt)]),e("div",Et,[e("div",null,[o[68]||(o[68]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),D(e("select",{"onUpdate:modelValue":o[22]||(o[22]=r=>l.claudeAccountId=r),class:"form-input w-full",disabled:l.permissions==="gemini"},[o[67]||(o[67]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.claudeGroups&&b.value.claudeGroups.length>0?(n(),i("optgroup",Ut,[(n(!0),i(R,null,G(b.value.claudeGroups,r=>(n(),i("option",{key:`group:${r.id}`,value:`group:${r.id}`},u(r.name)+" ("+u(r.memberCount||0)+" 个成员) ",9,Vt))),128))])):y("",!0),b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-oauth").length>0?(n(),i("optgroup",Gt,[(n(!0),i(R,null,G(b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-oauth"),r=>(n(),i("option",{key:r.id,value:r.id},u(r.name)+" ("+u(r.status==="active"?"正常":"异常")+") ",9,Ot))),128))])):y("",!0),b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-console").length>0?(n(),i("optgroup",qt,[(n(!0),i(R,null,G(b.value.claude.filter(r=>r.accountType==="dedicated"&&r.platform==="claude-console"),r=>(n(),i("option",{key:r.id,value:`console:${r.id}`},u(r.name)+" ("+u(r.status==="active"?"正常":"异常")+") ",9,Ft))),128))])):y("",!0)],8,Pt),[[le,l.claudeAccountId]])]),e("div",null,[o[70]||(o[70]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),D(e("select",{"onUpdate:modelValue":o[23]||(o[23]=r=>l.geminiAccountId=r),class:"form-input w-full",disabled:l.permissions==="claude"},[o[69]||(o[69]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.geminiGroups&&b.value.geminiGroups.length>0?(n(),i("optgroup",zt,[(n(!0),i(R,null,G(b.value.geminiGroups,r=>(n(),i("option",{key:`group:${r.id}`,value:`group:${r.id}`},u(r.name)+" ("+u(r.memberCount||0)+" 个成员) ",9,Nt))),128))])):y("",!0),b.value.gemini.filter(r=>r.accountType==="dedicated").length>0?(n(),i("optgroup",Yt,[(n(!0),i(R,null,G(b.value.gemini.filter(r=>r.accountType==="dedicated"),r=>(n(),i("option",{key:r.id,value:r.id},u(r.name)+" ("+u(r.status==="active"?"正常":"异常")+") ",9,Bt))),128))])):y("",!0)],8,Wt),[[le,l.geminiAccountId]])])]),o[71]||(o[71]=e("p",{class:"text-xs text-gray-500 mt-2"}," 选择专属账号后,此API Key将只使用该账号,不选择则使用共享账号池 ",-1))]),e("div",null,[e("div",Ht,[D(e("input",{id:"enableModelRestriction","onUpdate:modelValue":o[24]||(o[24]=r=>l.enableModelRestriction=r),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,l.enableModelRestriction]]),o[72]||(o[72]=e("label",{for:"enableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),l.enableModelRestriction?(n(),i("div",Qt,[e("div",null,[o[75]||(o[75]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"限制的模型列表",-1)),e("div",Xt,[(n(!0),i(R,null,G(l.restrictedModels,(r,F)=>(n(),i("span",{key:F,class:"inline-flex items-center px-2 py-1 rounded-full text-xs bg-red-100 text-red-800"},[h(u(r)+" ",1),e("button",{type:"button",class:"ml-1 text-red-600 hover:text-red-800",onClick:Q=>T(F)},o[73]||(o[73]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,Jt)]))),128)),l.restrictedModels.length===0?(n(),i("span",Zt," 暂无限制的模型 ")):y("",!0)]),e("div",es,[D(e("input",{"onUpdate:modelValue":o[25]||(o[25]=r=>l.modelInput=r),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1 text-sm",onKeydown:ye(ie(H,["prevent"]),["enter"])},null,40,ts),[[z,l.modelInput]]),e("button",{type:"button",class:"px-3 py-1.5 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors text-sm",onClick:H},o[74]||(o[74]=[e("i",{class:"fas fa-plus"},null,-1)]))]),o[76]||(o[76]=e("p",{class:"text-xs text-gray-500 mt-1"}," 例如:claude-opus-4-20250514 ",-1))])])):y("",!0)]),e("div",null,[e("div",ss,[D(e("input",{id:"enableClientRestriction","onUpdate:modelValue":o[26]||(o[26]=r=>l.enableClientRestriction=r),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,l.enableClientRestriction]]),o[77]||(o[77]=e("label",{for:"enableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),l.enableClientRestriction?(n(),i("div",ls,[e("div",null,[o[78]||(o[78]=e("label",{class:"block text-xs font-medium text-gray-700 mb-2"},"允许的客户端",-1)),e("div",os,[(n(!0),i(R,null,G(d.value,r=>(n(),i("div",{key:r.id,class:"flex items-start"},[D(e("input",{id:`client_${r.id}`,"onUpdate:modelValue":o[27]||(o[27]=F=>l.allowedClients=F),type:"checkbox",value:r.id,class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,ns),[[de,l.allowedClients]]),e("label",{for:`client_${r.id}`,class:"ml-2 flex-1 cursor-pointer"},[e("span",as,u(r.name),1),e("span",rs,u(r.description),1)],8,is)]))),128))])])])):y("",!0)]),e("div",ds,[e("button",{type:"button",class:"flex-1 px-4 py-2.5 bg-gray-100 text-gray-700 rounded-lg font-semibold hover:bg-gray-200 transition-colors text-sm",onClick:o[28]||(o[28]=r=>_.$emit("close"))}," 取消 "),e("button",{type:"submit",disabled:$.value,class:"btn btn-primary flex-1 py-2.5 px-4 font-semibold text-sm"},[$.value?(n(),i("div",cs)):(n(),i("i",ms)),h(" "+u($.value?"创建中...":"创建"),1)],8,us)])],32)])])]))}},xs=ae(ps,[["__scopeId","data-v-627c6d2b"]]),gs={class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},fs={class:"modal-content w-full max-w-4xl p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] flex flex-col"},ys={class:"flex items-center justify-between mb-4 sm:mb-6"},bs=["value"],vs={class:"space-y-4"},ws={key:0},$s={class:"flex flex-wrap gap-2"},hs=["onClick"],As={key:1},Cs={class:"flex flex-wrap gap-2"},Ks=["onClick"],ks={class:"flex gap-2"},_s=["onKeypress"],Ds={class:"bg-blue-50 border border-blue-200 rounded-lg p-3"},Is={class:"space-y-2"},Ls={class:"grid grid-cols-1 lg:grid-cols-3 gap-2"},Ts={class:"space-y-3"},Ms={class:"flex gap-2"},Ss={class:"flex gap-4"},js={class:"flex items-center cursor-pointer"},Rs={class:"flex items-center cursor-pointer"},Es={class:"flex items-center cursor-pointer"},Ps={class:"flex items-center justify-between mb-3"},Us=["disabled"],Vs={class:"grid grid-cols-1 gap-3"},Gs=["disabled"],Os={key:0,label:"调度分组"},qs=["value"],Fs={key:1,label:"Claude OAuth 专属账号"},Ws=["value"],zs={key:2,label:"Claude Console 专属账号"},Ns=["value"],Ys=["disabled"],Bs={key:0,label:"调度分组"},Hs=["value"],Qs={key:1,label:"Gemini 专属账号"},Xs=["value"],Js={class:"flex items-center mb-3"},Zs={key:0,class:"space-y-3"},el={class:"flex flex-wrap gap-2 mb-3 min-h-[32px] p-2 bg-gray-50 rounded-lg border border-gray-200"},tl=["onClick"],sl={key:0,class:"text-gray-400 text-sm"},ll={class:"flex gap-2"},ol=["onKeydown"],nl={class:"flex items-center mb-3"},il={key:0,class:"space-y-3"},al={class:"space-y-2"},rl=["id","value"],dl=["for"],ul={class:"text-sm font-medium text-gray-700"},cl={class:"text-xs text-gray-500 block"},ml={class:"flex gap-3 pt-4"},pl=["disabled"],xl={key:0,class:"loading-spinner mr-2"},gl={key:1,class:"fas fa-save mr-2"},fl={__name:"EditApiKeyModal",props:{apiKey:{type:Object,required:!0},accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success"],setup(I,{emit:V}){const f=I,M=V;Re();const j=Ae(),C=Ee(),$=K(!1),O=K(!1),b=K({claude:[],gemini:[],claudeGroups:[],geminiGroups:[]}),q=K([]),L=K(""),w=K([]),k=ee(()=>w.value.filter(T=>!d.tags.includes(T))),d=be({name:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]}),l=()=>{d.modelInput&&!d.restrictedModels.includes(d.modelInput)&&(d.restrictedModels.push(d.modelInput),d.modelInput="")},N=T=>{d.restrictedModels.splice(T,1)},A=()=>{if(L.value&&L.value.trim()){const T=L.value.trim();d.tags.includes(T)||d.tags.push(T),L.value=""}},x=T=>{d.tags.includes(T)||d.tags.push(T)},p=T=>{d.tags.splice(T,1)},Y=async()=>{$.value=!0;try{const T={tokenLimit:d.tokenLimit!==""&&d.tokenLimit!==null?parseInt(d.tokenLimit):0,rateLimitWindow:d.rateLimitWindow!==""&&d.rateLimitWindow!==null?parseInt(d.rateLimitWindow):0,rateLimitRequests:d.rateLimitRequests!==""&&d.rateLimitRequests!==null?parseInt(d.rateLimitRequests):0,concurrencyLimit:d.concurrencyLimit!==""&&d.concurrencyLimit!==null?parseInt(d.concurrencyLimit):0,dailyCostLimit:d.dailyCostLimit!==""&&d.dailyCostLimit!==null?parseFloat(d.dailyCostLimit):0,permissions:d.permissions,claudeAccountId:d.claudeAccountId||null,geminiAccountId:d.geminiAccountId||null,tags:d.tags};T.enableModelRestriction=d.enableModelRestriction,T.restrictedModels=d.restrictedModels,T.enableClientRestriction=d.enableClientRestriction,T.allowedClients=d.allowedClients;const a=await U.put(`/admin/api-keys/${f.apiKey.id}`,T);a.success?(M("success"),M("close")):S(a.message||"更新失败","error")}catch{S("更新失败","error")}finally{$.value=!1}},H=async()=>{var T,a;O.value=!0;try{const[m,B,te,_]=await Promise.all([U.get("/admin/claude-accounts"),U.get("/admin/claude-console-accounts"),U.get("/admin/gemini-accounts"),U.get("/admin/account-groups")]),o=[];if(m.success&&((T=m.data)==null||T.forEach(r=>{o.push({...r,platform:"claude-oauth",isDedicated:r.accountType==="dedicated"})})),B.success&&((a=B.data)==null||a.forEach(r=>{o.push({...r,platform:"claude-console",isDedicated:r.accountType==="dedicated"})})),b.value.claude=o,te.success&&(b.value.gemini=(te.data||[]).map(r=>({...r,isDedicated:r.accountType==="dedicated"}))),_.success){const r=_.data||[];b.value.claudeGroups=r.filter(F=>F.platform==="claude"),b.value.geminiGroups=r.filter(F=>F.platform==="gemini")}S("账号列表已刷新","success")}catch{S("刷新账号列表失败","error")}finally{O.value=!1}};return he(async()=>{q.value=await j.loadSupportedClients(),w.value=await C.fetchTags(),f.accounts&&(b.value={claude:f.accounts.claude||[],gemini:f.accounts.gemini||[],claudeGroups:f.accounts.claudeGroups||[],geminiGroups:f.accounts.geminiGroups||[]}),d.name=f.apiKey.name,d.tokenLimit=f.apiKey.tokenLimit||"",d.rateLimitWindow=f.apiKey.rateLimitWindow||"",d.rateLimitRequests=f.apiKey.rateLimitRequests||"",d.concurrencyLimit=f.apiKey.concurrencyLimit||"",d.dailyCostLimit=f.apiKey.dailyCostLimit||"",d.permissions=f.apiKey.permissions||"all",d.claudeAccountId=f.apiKey.claudeAccountId||"",d.geminiAccountId=f.apiKey.geminiAccountId||"",d.restrictedModels=f.apiKey.restrictedModels||[],d.allowedClients=f.apiKey.allowedClients||[],d.tags=f.apiKey.tags||[],d.enableModelRestriction=f.apiKey.enableModelRestriction||!1,d.enableClientRestriction=f.apiKey.enableClientRestriction||!1}),(T,a)=>(n(),Z(ue,{to:"body"},[e("div",gs,[e("div",fs,[e("div",ys,[a[22]||(a[22]=e("div",{class:"flex items-center gap-2 sm:gap-3"},[e("div",{class:"w-8 h-8 sm:w-10 sm:h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg sm:rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-edit text-white text-sm sm:text-base"})]),e("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 编辑 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors p-1",onClick:a[0]||(a[0]=m=>T.$emit("close"))},a[21]||(a[21]=[e("i",{class:"fas fa-times text-lg sm:text-xl"},null,-1)]))]),e("form",{class:"space-y-4 sm:space-y-6 modal-scroll-content custom-scrollbar flex-1",onSubmit:ie(Y,["prevent"])},[e("div",null,[a[23]||(a[23]=e("label",{class:"block text-xs sm:text-sm font-semibold text-gray-700 mb-1.5 sm:mb-3"},"名称",-1)),e("input",{value:d.name,type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed text-sm"},null,8,bs),a[24]||(a[24]=e("p",{class:"text-xs text-gray-500 mt-1 sm:mt-2"}," 名称不可修改 ",-1))]),e("div",null,[a[32]||(a[32]=e("label",{class:"block text-xs sm:text-sm font-semibold text-gray-700 mb-1.5 sm:mb-3"},"标签",-1)),e("div",vs,[d.tags.length>0?(n(),i("div",ws,[a[26]||(a[26]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 已选择的标签: ",-1)),e("div",$s,[(n(!0),i(R,null,G(d.tags,(m,B)=>(n(),i("span",{key:"selected-"+B,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[h(u(m)+" ",1),e("button",{type:"button",class:"ml-1 hover:text-blue-900",onClick:te=>p(B)},a[25]||(a[25]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,hs)]))),128))])])):y("",!0),k.value.length>0?(n(),i("div",As,[a[28]||(a[28]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 点击选择已有标签: ",-1)),e("div",Cs,[(n(!0),i(R,null,G(k.value,m=>(n(),i("button",{key:"available-"+m,type:"button",class:"inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-blue-100 hover:text-blue-700 transition-colors",onClick:B=>x(m)},[a[27]||(a[27]=e("i",{class:"fas fa-tag text-gray-500 text-xs"},null,-1)),h(" "+u(m),1)],8,Ks))),128))])])):y("",!0),e("div",null,[a[30]||(a[30]=e("div",{class:"text-xs font-medium text-gray-600 mb-2"}," 创建新标签: ",-1)),e("div",ks,[D(e("input",{"onUpdate:modelValue":a[1]||(a[1]=m=>L.value=m),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:ye(ie(A,["prevent"]),["enter"])},null,40,_s),[[z,L.value]]),e("button",{type:"button",class:"px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors",onClick:A},a[29]||(a[29]=[e("i",{class:"fas fa-plus"},null,-1)]))])]),a[31]||(a[31]=e("p",{class:"text-xs text-gray-500"}," 用于标记不同团队或用途,方便筛选管理 ",-1))])]),e("div",Ds,[a[40]||(a[40]=e("div",{class:"flex items-center gap-2 mb-2"},[e("div",{class:"w-6 h-6 bg-blue-500 rounded flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-tachometer-alt text-white text-xs"})]),e("h4",{class:"font-semibold text-gray-800 text-sm"}," 速率限制设置 (可选) ")],-1)),e("div",Is,[e("div",Ls,[e("div",null,[a[33]||(a[33]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"时间窗口 (分钟)",-1)),D(e("input",{"onUpdate:modelValue":a[2]||(a[2]=m=>d.rateLimitWindow=m),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,d.rateLimitWindow]]),a[34]||(a[34]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 时间段单位 ",-1))]),e("div",null,[a[35]||(a[35]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"请求次数限制",-1)),D(e("input",{"onUpdate:modelValue":a[3]||(a[3]=m=>d.rateLimitRequests=m),type:"number",min:"1",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,d.rateLimitRequests]]),a[36]||(a[36]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大请求 ",-1))]),e("div",null,[a[37]||(a[37]=e("label",{class:"block text-xs font-medium text-gray-700 mb-1"},"Token 限制",-1)),D(e("input",{"onUpdate:modelValue":a[4]||(a[4]=m=>d.tokenLimit=m),type:"number",placeholder:"无限制",class:"form-input w-full text-sm"},null,512),[[z,d.tokenLimit]]),a[38]||(a[38]=e("p",{class:"text-xs text-gray-500 mt-0.5 ml-2"}," 窗口内最大Token ",-1))])]),a[39]||(a[39]=e("div",{class:"bg-blue-100 rounded-lg p-2"},[e("h5",{class:"text-xs font-semibold text-blue-800 mb-1"}," 💡 使用示例 "),e("div",{class:"text-xs text-blue-700 space-y-0.5"},[e("div",null,[e("strong",null,"示例1:"),h(" 时间窗口=60,请求次数=1000 → 每60分钟最多1000次请求")]),e("div",null,[e("strong",null,"示例2:"),h(" 时间窗口=1,Token=10000 → 每分钟最多10,000个Token")]),e("div",null,[e("strong",null,"示例3:"),h(" 窗口=30,请求=50,Token=100000 → 每30分钟50次请求且不超10万Token")])])],-1))])]),e("div",null,[a[42]||(a[42]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"每日费用限制 (美元)",-1)),e("div",Ts,[e("div",Ms,[e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[5]||(a[5]=m=>d.dailyCostLimit="50")}," $50 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[6]||(a[6]=m=>d.dailyCostLimit="100")}," $100 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[7]||(a[7]=m=>d.dailyCostLimit="200")}," $200 "),e("button",{type:"button",class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium",onClick:a[8]||(a[8]=m=>d.dailyCostLimit="")}," 自定义 ")]),D(e("input",{"onUpdate:modelValue":a[9]||(a[9]=m=>d.dailyCostLimit=m),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,d.dailyCostLimit]]),a[41]||(a[41]=e("p",{class:"text-xs text-gray-500"}," 设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制 ",-1))])]),e("div",null,[a[43]||(a[43]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"并发限制",-1)),D(e("input",{"onUpdate:modelValue":a[10]||(a[10]=m=>d.concurrencyLimit=m),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[z,d.concurrencyLimit]]),a[44]||(a[44]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此 API Key 可同时处理的最大请求数 ",-1))]),e("div",null,[a[48]||(a[48]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"服务权限",-1)),e("div",Ss,[e("label",js,[D(e("input",{"onUpdate:modelValue":a[11]||(a[11]=m=>d.permissions=m),type:"radio",value:"all",class:"mr-2"},null,512),[[ne,d.permissions]]),a[45]||(a[45]=e("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),e("label",Rs,[D(e("input",{"onUpdate:modelValue":a[12]||(a[12]=m=>d.permissions=m),type:"radio",value:"claude",class:"mr-2"},null,512),[[ne,d.permissions]]),a[46]||(a[46]=e("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),e("label",Es,[D(e("input",{"onUpdate:modelValue":a[13]||(a[13]=m=>d.permissions=m),type:"radio",value:"gemini",class:"mr-2"},null,512),[[ne,d.permissions]]),a[47]||(a[47]=e("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),a[49]||(a[49]=e("p",{class:"text-xs text-gray-500 mt-2"}," 控制此 API Key 可以访问哪些服务 ",-1))]),e("div",null,[e("div",Ps,[a[50]||(a[50]=e("label",{class:"text-sm font-semibold text-gray-700"},"专属账号绑定",-1)),e("button",{type:"button",class:"text-blue-600 hover:text-blue-800 text-sm flex items-center gap-1 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",title:"刷新账号列表",disabled:O.value,onClick:H},[e("i",{class:P(["fas",O.value?"fa-spinner fa-spin":"fa-sync-alt","text-xs"])},null,2),e("span",null,u(O.value?"刷新中...":"刷新账号"),1)],8,Us)]),e("div",Vs,[e("div",null,[a[52]||(a[52]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),D(e("select",{"onUpdate:modelValue":a[14]||(a[14]=m=>d.claudeAccountId=m),class:"form-input w-full",disabled:d.permissions==="gemini"},[a[51]||(a[51]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.claudeGroups&&b.value.claudeGroups.length>0?(n(),i("optgroup",Os,[(n(!0),i(R,null,G(b.value.claudeGroups,m=>(n(),i("option",{key:`group:${m.id}`,value:`group:${m.id}`},u(m.name)+" ("+u(m.memberCount||0)+" 个成员) ",9,qs))),128))])):y("",!0),b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-oauth").length>0?(n(),i("optgroup",Fs,[(n(!0),i(R,null,G(b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-oauth"),m=>(n(),i("option",{key:m.id,value:m.id},u(m.name)+" ("+u(m.status==="active"?"正常":"异常")+") ",9,Ws))),128))])):y("",!0),b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-console").length>0?(n(),i("optgroup",zs,[(n(!0),i(R,null,G(b.value.claude.filter(m=>m.accountType==="dedicated"&&m.platform==="claude-console"),m=>(n(),i("option",{key:m.id,value:`console:${m.id}`},u(m.name)+" ("+u(m.status==="active"?"正常":"异常")+") ",9,Ns))),128))])):y("",!0)],8,Gs),[[le,d.claudeAccountId]])]),e("div",null,[a[54]||(a[54]=e("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),D(e("select",{"onUpdate:modelValue":a[15]||(a[15]=m=>d.geminiAccountId=m),class:"form-input w-full",disabled:d.permissions==="claude"},[a[53]||(a[53]=e("option",{value:""}," 使用共享账号池 ",-1)),b.value.geminiGroups&&b.value.geminiGroups.length>0?(n(),i("optgroup",Bs,[(n(!0),i(R,null,G(b.value.geminiGroups,m=>(n(),i("option",{key:`group:${m.id}`,value:`group:${m.id}`},u(m.name)+" ("+u(m.memberCount||0)+" 个成员) ",9,Hs))),128))])):y("",!0),b.value.gemini.filter(m=>m.accountType==="dedicated").length>0?(n(),i("optgroup",Qs,[(n(!0),i(R,null,G(b.value.gemini.filter(m=>m.accountType==="dedicated"),m=>(n(),i("option",{key:m.id,value:m.id},u(m.name)+" ("+u(m.status==="active"?"正常":"异常")+") ",9,Xs))),128))])):y("",!0)],8,Ys),[[le,d.geminiAccountId]])])]),a[55]||(a[55]=e("p",{class:"text-xs text-gray-500 mt-2"}," 修改绑定账号将影响此API Key的请求路由 ",-1))]),e("div",null,[e("div",Js,[D(e("input",{id:"editEnableModelRestriction","onUpdate:modelValue":a[16]||(a[16]=m=>d.enableModelRestriction=m),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,d.enableModelRestriction]]),a[56]||(a[56]=e("label",{for:"editEnableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),d.enableModelRestriction?(n(),i("div",Zs,[e("div",null,[a[59]||(a[59]=e("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"限制的模型列表",-1)),e("div",el,[(n(!0),i(R,null,G(d.restrictedModels,(m,B)=>(n(),i("span",{key:B,class:"inline-flex items-center px-3 py-1 rounded-full text-sm bg-red-100 text-red-800"},[h(u(m)+" ",1),e("button",{type:"button",class:"ml-2 text-red-600 hover:text-red-800",onClick:te=>N(B)},a[57]||(a[57]=[e("i",{class:"fas fa-times text-xs"},null,-1)]),8,tl)]))),128)),d.restrictedModels.length===0?(n(),i("span",sl," 暂无限制的模型 ")):y("",!0)]),e("div",ll,[D(e("input",{"onUpdate:modelValue":a[17]||(a[17]=m=>d.modelInput=m),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1",onKeydown:ye(ie(l,["prevent"]),["enter"])},null,40,ol),[[z,d.modelInput]]),e("button",{type:"button",class:"px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors",onClick:l},a[58]||(a[58]=[e("i",{class:"fas fa-plus"},null,-1)]))]),a[60]||(a[60]=e("p",{class:"text-xs text-gray-500 mt-2"}," 设置此API Key无法访问的模型,例如:claude-opus-4-20250514 ",-1))])])):y("",!0)]),e("div",null,[e("div",nl,[D(e("input",{id:"editEnableClientRestriction","onUpdate:modelValue":a[18]||(a[18]=m=>d.enableClientRestriction=m),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[de,d.enableClientRestriction]]),a[61]||(a[61]=e("label",{for:"editEnableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),d.enableClientRestriction?(n(),i("div",il,[e("div",null,[a[62]||(a[62]=e("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"允许的客户端",-1)),a[63]||(a[63]=e("p",{class:"text-xs text-gray-500 mb-3"}," 勾选允许使用此API Key的客户端 ",-1)),e("div",al,[(n(!0),i(R,null,G(q.value,m=>(n(),i("div",{key:m.id,class:"flex items-start"},[D(e("input",{id:`edit_client_${m.id}`,"onUpdate:modelValue":a[19]||(a[19]=B=>d.allowedClients=B),type:"checkbox",value:m.id,class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,rl),[[de,d.allowedClients]]),e("label",{for:`edit_client_${m.id}`,class:"ml-2 flex-1 cursor-pointer"},[e("span",ul,u(m.name),1),e("span",cl,u(m.description),1)],8,dl)]))),128))])])])):y("",!0)]),e("div",ml,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:a[20]||(a[20]=m=>T.$emit("close"))}," 取消 "),e("button",{type:"submit",disabled:$.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[$.value?(n(),i("div",xl)):(n(),i("i",gl)),h(" "+u($.value?"保存中...":"保存修改"),1)],8,pl)])],32)])])]))}},yl=ae(fl,[["__scopeId","data-v-12fe4aaf"]]),bl={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},vl={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},wl={class:"flex items-center justify-between mb-6"},$l={class:"space-y-6 modal-scroll-content custom-scrollbar flex-1"},hl={class:"bg-blue-50 border border-blue-200 rounded-lg p-4"},Al={class:"flex items-start gap-3"},Cl={class:"text-sm text-gray-700"},Kl={class:"text-xs text-gray-600 mt-1"},kl={key:0,class:"mt-3"},_l=["min"],Dl={key:1,class:"text-xs text-gray-500 mt-2"},Il={class:"flex gap-3 pt-4"},Ll=["disabled"],Tl={key:0,class:"loading-spinner mr-2"},Ml={key:1,class:"fas fa-clock mr-2"},Sl={__name:"RenewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close","success"],setup(I,{emit:V}){const f=I,M=V;Re();const j=K(!1),C=be({renewDuration:"30d",customExpireDate:"",newExpiresAt:null}),$=ee(()=>{const w=new Date;return f.apiKey.expiresAt&&new Date(f.apiKey.expiresAt)>w?new Date(f.apiKey.expiresAt).toISOString().slice(0,16):(w.setMinutes(w.getMinutes()+1),w.toISOString().slice(0,16))}),O=w=>new Date(w).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),b=()=>{if(!C.renewDuration){C.newExpiresAt=null;return}if(C.renewDuration==="permanent"){C.newExpiresAt=null;return}if(C.renewDuration==="custom")return;const w=f.apiKey.expiresAt&&new Date(f.apiKey.expiresAt)>new Date?new Date(f.apiKey.expiresAt):new Date,d=C.renewDuration.match(/(\d+)([dhmy])/);if(d){const[,l,N]=d,A=parseInt(l);switch(N){case"d":w.setDate(w.getDate()+A);break;case"h":w.setHours(w.getHours()+A);break;case"m":w.setMonth(w.getMonth()+A);break;case"y":w.setFullYear(w.getFullYear()+A);break}C.newExpiresAt=w.toISOString()}},q=()=>{C.customExpireDate&&(C.newExpiresAt=new Date(C.customExpireDate).toISOString())},L=async()=>{j.value=!0;try{const w={expiresAt:C.renewDuration==="permanent"?null:C.newExpiresAt},k=await U.put(`/admin/api-keys/${f.apiKey.id}/renew`,w);k.success?(S("API Key 续期成功","success"),M("success"),M("close")):S(k.message||"续期失败","error")}catch{S("续期失败","error")}finally{j.value=!1}};return b(),(w,k)=>(n(),Z(ue,{to:"body"},[e("div",bl,[e("div",vl,[e("div",wl,[k[5]||(k[5]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-clock text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 续期 API Key ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:k[0]||(k[0]=d=>w.$emit("close"))},k[4]||(k[4]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("div",$l,[e("div",hl,[e("div",Al,[k[7]||(k[7]=e("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[e("i",{class:"fas fa-info text-white text-sm"})],-1)),e("div",null,[k[6]||(k[6]=e("h4",{class:"font-semibold text-gray-800 mb-1"}," API Key 信息 ",-1)),e("p",Cl,u(I.apiKey.name),1),e("p",Kl," 当前过期时间:"+u(I.apiKey.expiresAt?O(I.apiKey.expiresAt):"永不过期"),1)])])]),e("div",null,[k[9]||(k[9]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"续期时长",-1)),D(e("select",{"onUpdate:modelValue":k[1]||(k[1]=d=>C.renewDuration=d),class:"form-input w-full",onChange:b},k[8]||(k[8]=[e("option",{value:"7d"}," 延长 7 天 ",-1),e("option",{value:"30d"}," 延长 30 天 ",-1),e("option",{value:"90d"}," 延长 90 天 ",-1),e("option",{value:"180d"}," 延长 180 天 ",-1),e("option",{value:"365d"}," 延长 365 天 ",-1),e("option",{value:"custom"}," 自定义日期 ",-1),e("option",{value:"permanent"}," 设为永不过期 ",-1)]),544),[[le,C.renewDuration]]),C.renewDuration==="custom"?(n(),i("div",kl,[D(e("input",{"onUpdate:modelValue":k[2]||(k[2]=d=>C.customExpireDate=d),type:"datetime-local",class:"form-input w-full",min:$.value,onChange:q},null,40,_l),[[z,C.customExpireDate]])])):y("",!0),C.newExpiresAt?(n(),i("p",Dl," 新的过期时间:"+u(O(C.newExpiresAt)),1)):y("",!0)])]),e("div",Il,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:k[3]||(k[3]=d=>w.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:j.value||!C.renewDuration,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:L},[j.value?(n(),i("div",Tl)):(n(),i("i",Ml)),h(" "+u(j.value?"续期中...":"确认续期"),1)],8,Ll)])])])]))}},jl=ae(Sl,[["__scopeId","data-v-0c3b1b3f"]]),Rl={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},El={class:"modal-content w-full max-w-lg p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Pl={class:"space-y-4 mb-6"},Ul={class:"p-3 bg-gray-50 rounded-lg border"},Vl={class:"text-gray-900 font-medium"},Gl={key:0},Ol={class:"p-3 bg-gray-50 rounded-lg border"},ql={class:"text-gray-700"},Fl={class:"relative"},Wl={class:"p-4 pr-14 bg-gray-900 rounded-lg border font-mono text-sm text-white break-all min-h-[60px] flex items-center"},zl={class:"absolute top-3 right-3"},Nl=["title"],Yl={__name:"NewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close"],setup(I,{emit:V}){const f=I,M=V,j=K(!1),C=()=>{j.value=!j.value},$=()=>{const L=f.apiKey.apiKey||f.apiKey.key||"";return L?j.value||L.length<=12?L:L.substring(0,8)+"●".repeat(Math.max(0,L.length-12))+L.substring(L.length-4):""},O=async()=>{const L=f.apiKey.apiKey||f.apiKey.key||"";if(!L){S("API Key 不存在","error");return}try{await navigator.clipboard.writeText(L),S("API Key 已复制到剪贴板","success")}catch(w){console.error("Failed to copy:",w);const k=document.createElement("textarea");k.value=L,document.body.appendChild(k),k.select();try{document.execCommand("copy"),S("API Key 已复制到剪贴板","success")}catch{S("复制失败,请手动复制","error")}finally{document.body.removeChild(k)}}},b=async()=>{window.showConfirm?await window.showConfirm("关闭提醒",`关闭后将无法再次查看完整的API Key,请确保已经妥善保存。
确定要关闭吗?`,"确定关闭","取消")&&M("close"):confirm(`关闭后将无法再次查看完整的API Key,请确保已经妥善保存。
diff --git a/web/admin-spa/dist/assets/ApiStatsView-Bw7MZuTj.js b/web/admin-spa/dist/assets/ApiStatsView-CTdd2uJw.js
similarity index 99%
rename from web/admin-spa/dist/assets/ApiStatsView-Bw7MZuTj.js
rename to web/admin-spa/dist/assets/ApiStatsView-CTdd2uJw.js
index 97d27eac..f7d5a014 100644
--- a/web/admin-spa/dist/assets/ApiStatsView-Bw7MZuTj.js
+++ b/web/admin-spa/dist/assets/ApiStatsView-CTdd2uJw.js
@@ -1 +1 @@
-import{aR as B,r as $,c as J,aW as A,x,y as u,z as t,O as p,K as H,aq as Q,u as e,aa as G,f as X,P as r,C as P,L as C,Q as O,ac as F,q as Z,aU as tt,V as et,o as st,R as S,J as at,av as it}from"./vue-vendor-CKToUHZx.js";import{L as ot}from"./LogoTitle-BIy_PC38.js";import{_ as K}from"./index-D3bIJLrk.js";import{b as lt}from"./vendor-BDiMbLwQ.js";import nt from"./TutorialView-Bj1w0Zae.js";/* empty css */import"./element-plus-B8Fs_0jW.js";class rt{constructor(){this.baseURL=window.location.origin,this.isDev=!1}async request(l,a={}){try{this.isDev&&l.startsWith("/admin")&&(l="/webapi"+l);const n=await fetch(`${this.baseURL}${l}`,{headers:{"Content-Type":"application/json",...a.headers},...a}),d=await n.json();if(!n.ok)throw new Error(d.message||`请求失败: ${n.status}`);return d}catch(n){throw console.error("API Stats request error:",n),n}}async getKeyId(l){return this.request("/apiStats/api/get-key-id",{method:"POST",body:JSON.stringify({apiKey:l})})}async getUserStats(l){return this.request("/apiStats/api/user-stats",{method:"POST",body:JSON.stringify({apiId:l})})}async getUserModelStats(l,a="daily"){return this.request("/apiStats/api/user-model-stats",{method:"POST",body:JSON.stringify({apiId:l,period:a})})}async getOemSettings(){try{return await this.request("/admin/oem-settings")}catch(l){return console.error("Failed to load OEM settings:",l),{success:!0,data:{siteName:"Claude Relay Service",siteIcon:"",siteIconData:""}}}}}const D=new rt,M=B("apistats",()=>{const w=$(""),l=$(null),a=$(!1),n=$(!1),d=$(!0),s=$(""),i=$("daily"),m=$(null),b=$([]),v=$(null),h=$(null),f=$({siteName:"",siteIcon:"",siteIconData:""}),c=J(()=>{const o={requests:0,inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,allTokens:0,cost:0,formattedCost:"$0.000000"};return i.value==="daily"?v.value||o:h.value||o}),U=J(()=>{if(!m.value||!c.value)return{tokenUsage:0,costUsage:0,requestUsage:0};const o=c.value,g=m.value.limits;return{tokenUsage:g.tokenLimit>0?Math.min(o.allTokens/g.tokenLimit*100,100):0,costUsage:g.dailyCostLimit>0?Math.min(o.cost/g.dailyCostLimit*100,100):0,requestUsage:g.rateLimitRequests>0?Math.min(o.requests/g.rateLimitRequests*100,100):0}});async function T(){if(!w.value.trim()){s.value="请输入 API Key";return}a.value=!0,s.value="",m.value=null,b.value=[],l.value=null;try{const o=await D.getKeyId(w.value);if(o.success){l.value=o.data.id;const g=await D.getUserStats(l.value);if(g.success)m.value=g.data,await R(),s.value="",j();else throw new Error(g.message||"查询失败")}else throw new Error(o.message||"获取 API Key ID 失败")}catch(o){console.error("Query stats error:",o),s.value=o.message||"查询统计数据失败,请检查您的 API Key 是否正确",m.value=null,b.value=[],l.value=null}finally{a.value=!1}}async function R(){l.value&&(await Promise.all([L("daily"),L("monthly")]),await q(i.value))}async function L(o){try{const g=await D.getUserModelStats(l.value,o);if(g.success){const z=g.data||[],k={requests:0,inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,allTokens:0,cost:0,formattedCost:"$0.000000"};z.forEach(I=>{var W;k.requests+=I.requests||0,k.inputTokens+=I.inputTokens||0,k.outputTokens+=I.outputTokens||0,k.cacheCreateTokens+=I.cacheCreateTokens||0,k.cacheReadTokens+=I.cacheReadTokens||0,k.allTokens+=I.allTokens||0,k.cost+=((W=I.costs)==null?void 0:W.total)||0}),k.formattedCost=N(k.cost),o==="daily"?v.value=k:h.value=k}else console.warn(`Failed to load ${o} stats:`,g.message)}catch(g){console.error(`Load ${o} stats error:`,g)}}async function q(o="daily"){if(l.value){n.value=!0;try{const g=await D.getUserModelStats(l.value,o);if(g.success)b.value=g.data||[];else throw new Error(g.message||"加载模型统计失败")}catch(g){console.error("Load model stats error:",g),b.value=[]}finally{n.value=!1}}}async function E(o){i.value===o||n.value||(i.value=o,(o==="daily"&&!v.value||o==="monthly"&&!h.value)&&await L(o),await q(o))}async function _(){if(l.value){a.value=!0,s.value="",m.value=null,b.value=[];try{const o=await D.getUserStats(l.value);if(o.success)m.value=o.data,await R(),s.value="";else throw new Error(o.message||"查询失败")}catch(o){console.error("Load stats with apiId error:",o),s.value=o.message||"查询统计数据失败",m.value=null,b.value=[]}finally{a.value=!1}}}async function y(){d.value=!0;try{const o=await D.getOemSettings();o&&o.success&&o.data&&(f.value={...f.value,...o.data})}catch(o){console.error("Error loading OEM settings:",o),f.value={siteName:"Claude Relay Service",siteIcon:"",siteIconData:""}}finally{d.value=!1}}function N(o){return typeof o!="number"||o===0?"$0.000000":o>=1?"$"+o.toFixed(2):o>=.01?"$"+o.toFixed(4):"$"+o.toFixed(6)}function j(){if(l.value){const o=new URL(window.location);o.searchParams.set("apiId",l.value),window.history.pushState({},"",o)}}function V(){m.value=null,b.value=[],v.value=null,h.value=null,s.value="",i.value="daily",l.value=null}function Y(){w.value="",V()}return{apiKey:w,apiId:l,loading:a,modelStatsLoading:n,oemLoading:d,error:s,statsPeriod:i,statsData:m,modelStats:b,dailyStats:v,monthlyStats:h,oemSettings:f,currentPeriodData:c,usagePercentages:U,queryStats:T,loadAllPeriodStats:R,loadPeriodStats:L,loadModelStats:q,switchPeriod:E,loadStatsWithApiId:_,loadOemSettings:y,clearData:V,reset:Y}}),dt={class:"api-input-wide-card glass-strong rounded-3xl p-6 mb-8 shadow-xl"},mt={class:"max-w-4xl mx-auto"},ct={class:"api-input-grid grid grid-cols-1 lg:grid-cols-4"},xt={class:"lg:col-span-3"},ut=["disabled"],ft={class:"lg:col-span-1"},pt=["disabled"],yt={key:0,class:"fas fa-spinner loading-spinner"},gt={key:1,class:"fas fa-search"},bt={__name:"ApiKeyInput",setup(w){const l=M(),{apiKey:a,loading:n}=A(l),{queryStats:d}=l;return(s,i)=>(u(),x("div",dt,[i[6]||(i[6]=t("div",{class:"wide-card-title text-center mb-6"},[t("h2",{class:"text-2xl font-bold mb-2"},[t("i",{class:"fas fa-chart-line mr-3"}),p(" 使用统计查询 ")]),t("p",{class:"text-base text-gray-600"}," 查询您的 API Key 使用情况和统计数据 ")],-1)),t("div",mt,[t("div",ct,[t("div",xt,[i[3]||(i[3]=t("label",{class:"block text-sm font-medium mb-2 text-gray-700"},[t("i",{class:"fas fa-key mr-2"}),p(" 输入您的 API Key ")],-1)),H(t("input",{"onUpdate:modelValue":i[0]||(i[0]=m=>X(a)?a.value=m:null),type:"password",placeholder:"请输入您的 API Key (cr_...)",class:"wide-card-input w-full",disabled:e(n),onKeyup:i[1]||(i[1]=G((...m)=>e(d)&&e(d)(...m),["enter"]))},null,40,ut),[[Q,e(a)]])]),t("div",ft,[i[4]||(i[4]=t("label",{class:"hidden lg:block text-sm font-medium mb-2 text-gray-700"}," ",-1)),t("button",{disabled:e(n)||!e(a).trim(),class:"btn btn-primary btn-query w-full h-full flex items-center justify-center gap-2",onClick:i[2]||(i[2]=(...m)=>e(d)&&e(d)(...m))},[e(n)?(u(),x("i",yt)):(u(),x("i",gt)),p(" "+r(e(n)?"查询中...":"查询统计"),1)],8,pt)])]),i[5]||(i[5]=t("div",{class:"security-notice mt-4"},[t("i",{class:"fas fa-shield-alt mr-2"}),p(" 您的 API Key 仅用于查询自己的统计数据,不会被存储或用于其他用途 ")],-1))])]))}},vt=K(bt,[["__scopeId","data-v-d80546e3"]]),_t={class:"grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 mb-6 md:mb-8"},ht={class:"card p-4 md:p-6"},$t={class:"space-y-2 md:space-y-3"},wt={class:"flex justify-between items-center"},kt={class:"font-medium text-gray-900 text-sm md:text-base break-all"},St={class:"flex justify-between items-center"},Tt={class:"flex justify-between items-center"},It={class:"font-medium text-gray-900 text-sm md:text-base"},Ct={class:"flex justify-between items-center"},Lt={class:"font-medium text-gray-900 text-xs md:text-base break-all"},Dt={class:"flex justify-between items-start"},Pt={key:0,class:"text-right"},At={key:0,class:"text-red-600 font-medium text-sm md:text-base"},Kt={key:1,class:"text-orange-600 font-medium text-xs md:text-base break-all"},Mt={key:2,class:"text-gray-900 font-medium text-xs md:text-base break-all"},Rt={key:1,class:"text-gray-400 font-medium text-sm md:text-base"},qt={class:"card p-4 md:p-6"},jt={class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex flex-col sm:flex-row sm:items-center text-gray-900"},Ut={class:"text-xs md:text-sm font-normal text-gray-600 sm:ml-2"},Et={class:"grid grid-cols-2 gap-3 md:gap-4"},Nt={class:"stat-card text-center"},Ot={class:"text-lg md:text-3xl font-bold text-green-600"},Ft={class:"text-xs md:text-sm text-gray-600"},Vt={class:"stat-card text-center"},Wt={class:"text-lg md:text-3xl font-bold text-blue-600"},Jt={class:"text-xs md:text-sm text-gray-600"},Yt={class:"stat-card text-center"},zt={class:"text-lg md:text-3xl font-bold text-purple-600"},Bt={class:"text-xs md:text-sm text-gray-600"},Ht={class:"stat-card text-center"},Qt={class:"text-lg md:text-3xl font-bold text-yellow-600"},Gt={class:"text-xs md:text-sm text-gray-600"},Xt={__name:"StatsOverview",setup(w){const l=M(),{statsData:a,statsPeriod:n,currentPeriodData:d}=A(l),s=f=>{if(!f)return"无";try{return lt(f).format("YYYY年MM月DD日 HH:mm")}catch{return"格式错误"}},i=f=>f?new Date(f).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}):"",m=f=>f?new Date(f){if(!f)return!1;const T=(new Date(f)-new Date)/(1e3*60*60*24);return T>0&&T<=7},v=f=>(typeof f!="number"&&(f=parseInt(f)||0),f===0?"0":f>=1e6?(f/1e6).toFixed(1)+"M":f>=1e3?(f/1e3).toFixed(1)+"K":f.toLocaleString()),h=f=>({claude:"Claude",gemini:"Gemini",all:"全部模型"})[f]||f||"未知";return(f,c)=>(u(),x("div",_t,[t("div",ht,[c[8]||(c[8]=t("h3",{class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-info-circle mr-2 md:mr-3 text-blue-500 text-sm md:text-base"}),p(" API Key 信息 ")],-1)),t("div",$t,[t("div",wt,[c[0]||(c[0]=t("span",{class:"text-gray-600 text-sm md:text-base"},"名称",-1)),t("span",kt,r(e(a).name),1)]),t("div",St,[c[1]||(c[1]=t("span",{class:"text-gray-600 text-sm md:text-base"},"状态",-1)),t("span",{class:P([e(a).isActive?"text-green-600":"text-red-600","font-medium text-sm md:text-base"])},[t("i",{class:P([e(a).isActive?"fas fa-check-circle":"fas fa-times-circle","mr-1 text-xs md:text-sm"])},null,2),p(" "+r(e(a).isActive?"活跃":"已停用"),1)],2)]),t("div",Tt,[c[2]||(c[2]=t("span",{class:"text-gray-600 text-sm md:text-base"},"权限",-1)),t("span",It,r(h(e(a).permissions)),1)]),t("div",Ct,[c[3]||(c[3]=t("span",{class:"text-gray-600 text-sm md:text-base"},"创建时间",-1)),t("span",Lt,r(s(e(a).createdAt)),1)]),t("div",Dt,[c[7]||(c[7]=t("span",{class:"text-gray-600 text-sm md:text-base flex-shrink-0 mt-1"},"过期时间",-1)),e(a).expiresAt?(u(),x("div",Pt,[m(e(a).expiresAt)?(u(),x("div",At,c[4]||(c[4]=[t("i",{class:"fas fa-exclamation-circle mr-1 text-xs md:text-sm"},null,-1),p(" 已过期 ",-1)]))):b(e(a).expiresAt)?(u(),x("div",Kt,[c[5]||(c[5]=t("i",{class:"fas fa-clock mr-1 text-xs md:text-sm"},null,-1)),p(" "+r(i(e(a).expiresAt)),1)])):(u(),x("div",Mt,r(i(e(a).expiresAt)),1))])):(u(),x("div",Rt,c[6]||(c[6]=[t("i",{class:"fas fa-infinity mr-1 text-xs md:text-sm"},null,-1),p(" 永不过期 ",-1)])))])])]),t("div",qt,[t("h3",jt,[c[9]||(c[9]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-chart-bar mr-2 md:mr-3 text-green-500 text-sm md:text-base"}),p(" 使用统计概览 ")],-1)),t("span",Ut,"("+r(e(n)==="daily"?"今日":"本月")+")",1)]),t("div",Et,[t("div",Nt,[t("div",Ot,r(v(e(d).requests)),1),t("div",Ft,r(e(n)==="daily"?"今日":"本月")+"请求数 ",1)]),t("div",Vt,[t("div",Wt,r(v(e(d).allTokens)),1),t("div",Jt,r(e(n)==="daily"?"今日":"本月")+"Token数 ",1)]),t("div",Yt,[t("div",zt,r(e(d).formattedCost||"$0.000000"),1),t("div",Bt,r(e(n)==="daily"?"今日":"本月")+"费用 ",1)]),t("div",Ht,[t("div",Qt,r(v(e(d).inputTokens)),1),t("div",Gt,r(e(n)==="daily"?"今日":"本月")+"输入Token ",1)])])])]))}},Zt=K(Xt,[["__scopeId","data-v-41acf5a1"]]),te={class:"card p-4 md:p-6"},ee={class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex flex-col sm:flex-row sm:items-center text-gray-900"},se={class:"text-xs md:text-sm font-normal text-gray-600 sm:ml-2"},ae={class:"space-y-2 md:space-y-3"},ie={class:"flex justify-between items-center"},oe={class:"font-medium text-gray-900 text-sm md:text-base"},le={class:"flex justify-between items-center"},ne={class:"font-medium text-gray-900 text-sm md:text-base"},re={class:"flex justify-between items-center"},de={class:"font-medium text-gray-900 text-sm md:text-base"},me={class:"flex justify-between items-center"},ce={class:"font-medium text-gray-900 text-sm md:text-base"},xe={class:"mt-3 md:mt-4 pt-3 md:pt-4 border-t border-gray-200"},ue={class:"flex justify-between items-center font-bold text-gray-900"},fe={class:"text-sm md:text-base"},pe={class:"text-lg md:text-xl"},ye={__name:"TokenDistribution",setup(w){const l=M(),{statsPeriod:a,currentPeriodData:n}=A(l),d=s=>(typeof s!="number"&&(s=parseInt(s)||0),s===0?"0":s>=1e6?(s/1e6).toFixed(1)+"M":s>=1e3?(s/1e3).toFixed(1)+"K":s.toLocaleString());return(s,i)=>(u(),x("div",te,[t("h3",ee,[i[0]||(i[0]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-coins mr-2 md:mr-3 text-yellow-500 text-sm md:text-base"}),p(" Token 使用分布 ")],-1)),t("span",se,"("+r(e(a)==="daily"?"今日":"本月")+")",1)]),t("div",ae,[t("div",ie,[i[1]||(i[1]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-arrow-right mr-1 md:mr-2 text-green-500 text-xs md:text-sm"}),p(" 输入 Token ")],-1)),t("span",oe,r(d(e(n).inputTokens)),1)]),t("div",le,[i[2]||(i[2]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-arrow-left mr-1 md:mr-2 text-blue-500 text-xs md:text-sm"}),p(" 输出 Token ")],-1)),t("span",ne,r(d(e(n).outputTokens)),1)]),t("div",re,[i[3]||(i[3]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-save mr-1 md:mr-2 text-purple-500 text-xs md:text-sm"}),p(" 缓存创建 Token ")],-1)),t("span",de,r(d(e(n).cacheCreateTokens)),1)]),t("div",me,[i[4]||(i[4]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-download mr-1 md:mr-2 text-orange-500 text-xs md:text-sm"}),p(" 缓存读取 Token ")],-1)),t("span",ce,r(d(e(n).cacheReadTokens)),1)])]),t("div",xe,[t("div",ue,[t("span",fe,r(e(a)==="daily"?"今日":"本月")+"总计",1),t("span",pe,r(d(e(n).allTokens)),1)])])]))}},ge=K(ye,[["__scopeId","data-v-499bb025"]]),be={class:"card p-4 md:p-6"},ve={class:"space-y-2 md:space-y-3"},_e={class:"flex justify-between items-center"},he={class:"font-medium text-gray-900 text-sm md:text-base"},$e={class:"flex justify-between items-center"},we={class:"font-medium text-gray-900 text-sm md:text-base"},ke={class:"flex justify-between items-center"},Se={class:"font-medium text-gray-900 text-sm md:text-base"},Te={class:"flex justify-between items-center"},Ie={class:"font-medium text-gray-900 text-sm md:text-base"},Ce={class:"flex justify-between items-center"},Le={class:"font-medium text-gray-900 text-sm md:text-base"},De={key:0,class:"text-orange-600"},Pe={key:1,class:"text-green-600"},Ae={class:"flex justify-between items-center"},Ke={class:"font-medium text-gray-900 text-sm md:text-base"},Me={key:0,class:"text-orange-600"},Re={key:1,class:"text-green-600"},qe={key:0,class:"card p-4 md:p-6 mt-4 md:mt-6"},je={class:"grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6"},Ue={key:0,class:"bg-amber-50 border border-amber-200 rounded-lg p-3 md:p-4"},Ee={class:"space-y-1 md:space-y-2"},Ne={class:"text-gray-800 break-all"},Oe={key:1,class:"bg-blue-50 border border-blue-200 rounded-lg p-3 md:p-4"},Fe={class:"space-y-1 md:space-y-2"},Ve={class:"text-gray-800 break-all"},We={__name:"LimitConfig",setup(w){const l=M(),{statsData:a}=A(l),n=d=>(typeof d!="number"&&(d=parseInt(d)||0),d===0?"0":d>=1e6?(d/1e6).toFixed(1)+"M":d>=1e3?(d/1e3).toFixed(1)+"K":d.toLocaleString());return(d,s)=>(u(),x("div",null,[t("div",be,[s[10]||(s[10]=t("h3",{class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-shield-alt mr-2 md:mr-3 text-red-500 text-sm md:text-base"}),p(" 限制配置 ")],-1)),t("div",ve,[t("div",_e,[s[0]||(s[0]=t("span",{class:"text-gray-600 text-sm md:text-base"},"Token 限制",-1)),t("span",he,r(e(a).limits.tokenLimit>0?n(e(a).limits.tokenLimit):"无限制"),1)]),t("div",$e,[s[1]||(s[1]=t("span",{class:"text-gray-600 text-sm md:text-base"},"并发限制",-1)),t("span",we,r(e(a).limits.concurrencyLimit>0?e(a).limits.concurrencyLimit:"无限制"),1)]),t("div",ke,[s[2]||(s[2]=t("span",{class:"text-gray-600 text-sm md:text-base"},"速率限制",-1)),t("span",Se,r(e(a).limits.rateLimitRequests>0&&e(a).limits.rateLimitWindow>0?`${e(a).limits.rateLimitRequests}次/${e(a).limits.rateLimitWindow}分钟`:"无限制"),1)]),t("div",Te,[s[3]||(s[3]=t("span",{class:"text-gray-600 text-sm md:text-base"},"每日费用限制",-1)),t("span",Ie,r(e(a).limits.dailyCostLimit>0?"$"+e(a).limits.dailyCostLimit:"无限制"),1)]),t("div",Ce,[s[6]||(s[6]=t("span",{class:"text-gray-600 text-sm md:text-base"},"模型限制",-1)),t("span",Le,[e(a).restrictions.enableModelRestriction&&e(a).restrictions.restrictedModels.length>0?(u(),x("span",De,[s[4]||(s[4]=t("i",{class:"fas fa-exclamation-triangle mr-1 text-xs md:text-sm"},null,-1)),p(" 限制 "+r(e(a).restrictions.restrictedModels.length)+" 个模型 ",1)])):(u(),x("span",Pe,s[5]||(s[5]=[t("i",{class:"fas fa-check-circle mr-1 text-xs md:text-sm"},null,-1),p(" 允许所有模型 ",-1)])))])]),t("div",Ae,[s[9]||(s[9]=t("span",{class:"text-gray-600 text-sm md:text-base"},"客户端限制",-1)),t("span",Ke,[e(a).restrictions.enableClientRestriction&&e(a).restrictions.allowedClients.length>0?(u(),x("span",Me,[s[7]||(s[7]=t("i",{class:"fas fa-exclamation-triangle mr-1 text-xs md:text-sm"},null,-1)),p(" 限制 "+r(e(a).restrictions.allowedClients.length)+" 个客户端 ",1)])):(u(),x("span",Re,s[8]||(s[8]=[t("i",{class:"fas fa-check-circle mr-1 text-xs md:text-sm"},null,-1),p(" 允许所有客户端 ",-1)])))])])])]),e(a).restrictions.enableModelRestriction&&e(a).restrictions.restrictedModels.length>0||e(a).restrictions.enableClientRestriction&&e(a).restrictions.allowedClients.length>0?(u(),x("div",qe,[s[17]||(s[17]=t("h3",{class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-list-alt mr-2 md:mr-3 text-amber-500 text-sm md:text-base"}),p(" 详细限制信息 ")],-1)),t("div",je,[e(a).restrictions.enableModelRestriction&&e(a).restrictions.restrictedModels.length>0?(u(),x("div",Ue,[s[12]||(s[12]=t("h4",{class:"font-bold text-amber-800 mb-2 md:mb-3 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-robot mr-1 md:mr-2 text-xs md:text-sm"}),p(" 受限模型列表 ")],-1)),t("div",Ee,[(u(!0),x(O,null,F(e(a).restrictions.restrictedModels,i=>(u(),x("div",{key:i,class:"bg-white rounded px-2 md:px-3 py-1 md:py-2 text-xs md:text-sm border border-amber-200"},[s[11]||(s[11]=t("i",{class:"fas fa-ban mr-1 md:mr-2 text-red-500 text-xs"},null,-1)),t("span",Ne,r(i),1)]))),128))]),s[13]||(s[13]=t("p",{class:"text-xs text-amber-700 mt-2 md:mt-3"},[t("i",{class:"fas fa-info-circle mr-1"}),p(" 此 API Key 不能访问以上列出的模型 ")],-1))])):C("",!0),e(a).restrictions.enableClientRestriction&&e(a).restrictions.allowedClients.length>0?(u(),x("div",Oe,[s[15]||(s[15]=t("h4",{class:"font-bold text-blue-800 mb-2 md:mb-3 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-desktop mr-1 md:mr-2 text-xs md:text-sm"}),p(" 允许的客户端 ")],-1)),t("div",Fe,[(u(!0),x(O,null,F(e(a).restrictions.allowedClients,i=>(u(),x("div",{key:i,class:"bg-white rounded px-2 md:px-3 py-1 md:py-2 text-xs md:text-sm border border-blue-200"},[s[14]||(s[14]=t("i",{class:"fas fa-check mr-1 md:mr-2 text-green-500 text-xs"},null,-1)),t("span",Ve,r(i),1)]))),128))]),s[16]||(s[16]=t("p",{class:"text-xs text-blue-700 mt-2 md:mt-3"},[t("i",{class:"fas fa-info-circle mr-1"}),p(" 此 API Key 只能被以上列出的客户端使用 ")],-1))])):C("",!0)])])):C("",!0)]))}},Je=K(We,[["__scopeId","data-v-8b510ae2"]]),Ye={class:"card p-4 md:p-6"},ze={class:"mb-4 md:mb-6"},Be={class:"text-lg md:text-xl font-bold flex flex-col sm:flex-row sm:items-center text-gray-900"},He={class:"text-xs md:text-sm font-normal text-gray-600 sm:ml-2"},Qe={key:0,class:"text-center py-6 md:py-8"},Ge={key:1,class:"space-y-3 md:space-y-4"},Xe={class:"flex justify-between items-start mb-2 md:mb-3"},Ze={class:"flex-1 min-w-0"},ts={class:"font-bold text-base md:text-lg text-gray-900 break-all"},es={class:"text-gray-600 text-xs md:text-sm"},ss={class:"text-right flex-shrink-0 ml-3"},as={class:"text-base md:text-lg font-bold text-green-600"},is={class:"grid grid-cols-2 md:grid-cols-4 gap-2 md:gap-3 text-xs md:text-sm"},os={class:"bg-gray-50 rounded p-2"},ls={class:"font-medium text-gray-900"},ns={class:"bg-gray-50 rounded p-2"},rs={class:"font-medium text-gray-900"},ds={class:"bg-gray-50 rounded p-2"},ms={class:"font-medium text-gray-900"},cs={class:"bg-gray-50 rounded p-2"},xs={class:"font-medium text-gray-900"},us={key:2,class:"text-center py-6 md:py-8 text-gray-500"},fs={class:"text-sm md:text-base"},ps={__name:"ModelUsageStats",setup(w){const l=M(),{statsPeriod:a,modelStats:n,modelStatsLoading:d}=A(l),s=i=>(typeof i!="number"&&(i=parseInt(i)||0),i===0?"0":i>=1e6?(i/1e6).toFixed(1)+"M":i>=1e3?(i/1e3).toFixed(1)+"K":i.toLocaleString());return(i,m)=>(u(),x("div",Ye,[t("div",ze,[t("h3",Be,[m[0]||(m[0]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-robot mr-2 md:mr-3 text-indigo-500 text-sm md:text-base"}),p(" 模型使用统计 ")],-1)),t("span",He,"("+r(e(a)==="daily"?"今日":"本月")+")",1)])]),e(d)?(u(),x("div",Qe,m[1]||(m[1]=[t("i",{class:"fas fa-spinner loading-spinner text-xl md:text-2xl mb-2 text-gray-600"},null,-1),t("p",{class:"text-gray-600 text-sm md:text-base"}," 加载模型统计数据中... ",-1)]))):e(n).length>0?(u(),x("div",Ge,[(u(!0),x(O,null,F(e(n),(b,v)=>{var h;return u(),x("div",{key:v,class:"model-usage-item"},[t("div",Xe,[t("div",Ze,[t("h4",ts,r(b.model),1),t("p",es,r(b.requests)+" 次请求 ",1)]),t("div",ss,[t("div",as,r(((h=b.formatted)==null?void 0:h.total)||"$0.000000"),1),m[2]||(m[2]=t("div",{class:"text-xs md:text-sm text-gray-600"}," 总费用 ",-1))])]),t("div",is,[t("div",os,[m[3]||(m[3]=t("div",{class:"text-gray-600"}," 输入 Token ",-1)),t("div",ls,r(s(b.inputTokens)),1)]),t("div",ns,[m[4]||(m[4]=t("div",{class:"text-gray-600"}," 输出 Token ",-1)),t("div",rs,r(s(b.outputTokens)),1)]),t("div",ds,[m[5]||(m[5]=t("div",{class:"text-gray-600"}," 缓存创建 ",-1)),t("div",ms,r(s(b.cacheCreateTokens)),1)]),t("div",cs,[m[6]||(m[6]=t("div",{class:"text-gray-600"}," 缓存读取 ",-1)),t("div",xs,r(s(b.cacheReadTokens)),1)])])])}),128))])):(u(),x("div",us,[m[7]||(m[7]=t("i",{class:"fas fa-chart-pie text-2xl md:text-3xl mb-3"},null,-1)),t("p",fs," 暂无"+r(e(a)==="daily"?"今日":"本月")+"模型使用数据 ",1)]))]))}},ys=K(ps,[["__scopeId","data-v-56679d54"]]),gs={class:"min-h-screen gradient-bg p-4 md:p-6"},bs={class:"glass-strong rounded-3xl p-4 md:p-6 mb-6 md:mb-8 shadow-xl"},vs={class:"flex flex-col md:flex-row justify-between items-center gap-4"},_s={class:"flex items-center gap-3"},hs={class:"mb-6 md:mb-8"},$s={class:"flex justify-center"},ws={class:"inline-flex bg-white/10 backdrop-blur-xl rounded-full p-1 shadow-lg border border-white/20 w-full max-w-md md:w-auto"},ks={key:0,class:"tab-content"},Ss={key:0,class:"mb-6 md:mb-8"},Ts={class:"bg-red-500/20 border border-red-500/30 rounded-xl p-3 md:p-4 text-red-800 backdrop-blur-sm text-sm md:text-base"},Is={key:1,class:"fade-in"},Cs={class:"glass-strong rounded-3xl p-4 md:p-6 shadow-xl"},Ls={class:"mb-4 md:mb-6 pb-4 md:pb-6 border-b border-gray-200"},Ds={class:"flex flex-col md:flex-row items-start md:items-center justify-between gap-3 md:gap-4"},Ps={class:"flex gap-2 w-full md:w-auto"},As=["disabled"],Ks=["disabled"],Ms={class:"grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 mb-6 md:mb-8"},Rs={key:1,class:"tab-content"},qs={class:"glass-strong rounded-3xl shadow-xl"},js={__name:"ApiStatsView",setup(w){const l=tt(),a=M(),n=$("stats"),{apiKey:d,apiId:s,loading:i,modelStatsLoading:m,oemLoading:b,error:v,statsPeriod:h,statsData:f,oemSettings:c}=A(a),{queryStats:U,switchPeriod:T,loadStatsWithApiId:R,loadOemSettings:L,reset:q}=a,E=_=>{(_.ctrlKey||_.metaKey)&&_.key==="Enter"&&(!i.value&&d.value.trim()&&U(),_.preventDefault()),_.key==="Escape"&&q()};return Z(()=>{console.log("API Stats Page loaded"),L();const _=l.query.apiId,y=l.query.apiKey;_&&_.match(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i)?(s.value=_,R()):y&&y.length>10&&(d.value=y),document.addEventListener("keydown",E)}),et(()=>{document.removeEventListener("keydown",E)}),st(d,_=>{_||a.clearData()}),(_,y)=>{const N=it("router-link");return u(),x("div",gs,[t("div",bs,[t("div",vs,[S(ot,{loading:e(b),title:e(c).siteName,subtitle:n.value==="stats"?"API Key 使用统计":"使用教程","logo-src":e(c).siteIconData||e(c).siteIcon},null,8,["loading","title","subtitle","logo-src"]),t("div",_s,[S(N,{to:"/dashboard",class:"admin-button rounded-xl px-3 py-2 md:px-4 md:py-2 text-white transition-all duration-300 flex items-center gap-2"},{default:at(()=>y[4]||(y[4]=[t("i",{class:"fas fa-cog text-sm"},null,-1),t("span",{class:"text-xs md:text-sm font-medium"},"管理后台",-1)])),_:1,__:[4]})])])]),t("div",hs,[t("div",$s,[t("div",ws,[t("button",{class:P(["tab-pill-button",n.value==="stats"?"active":""]),onClick:y[0]||(y[0]=j=>n.value="stats")},y[5]||(y[5]=[t("i",{class:"fas fa-chart-line mr-1 md:mr-2"},null,-1),t("span",{class:"text-sm md:text-base"},"统计查询",-1)]),2),t("button",{class:P(["tab-pill-button",n.value==="tutorial"?"active":""]),onClick:y[1]||(y[1]=j=>n.value="tutorial")},y[6]||(y[6]=[t("i",{class:"fas fa-graduation-cap mr-1 md:mr-2"},null,-1),t("span",{class:"text-sm md:text-base"},"使用教程",-1)]),2)])])]),n.value==="stats"?(u(),x("div",ks,[S(vt),e(v)?(u(),x("div",Ss,[t("div",Ts,[y[7]||(y[7]=t("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),p(" "+r(e(v)),1)])])):C("",!0),e(f)?(u(),x("div",Is,[t("div",Cs,[t("div",Ls,[t("div",Ds,[y[10]||(y[10]=t("div",{class:"flex items-center gap-2 md:gap-3"},[t("i",{class:"fas fa-clock text-blue-500 text-base md:text-lg"}),t("span",{class:"text-base md:text-lg font-medium text-gray-700"},"统计时间范围")],-1)),t("div",Ps,[t("button",{class:P([["period-btn",{active:e(h)==="daily"}],"px-4 md:px-6 py-2 text-xs md:text-sm font-medium flex items-center gap-1 md:gap-2 flex-1 md:flex-none justify-center"]),disabled:e(i)||e(m),onClick:y[2]||(y[2]=j=>e(T)("daily"))},y[8]||(y[8]=[t("i",{class:"fas fa-calendar-day text-xs md:text-sm"},null,-1),p(" 今日 ",-1)]),10,As),t("button",{class:P([["period-btn",{active:e(h)==="monthly"}],"px-4 md:px-6 py-2 text-xs md:text-sm font-medium flex items-center gap-1 md:gap-2 flex-1 md:flex-none justify-center"]),disabled:e(i)||e(m),onClick:y[3]||(y[3]=j=>e(T)("monthly"))},y[9]||(y[9]=[t("i",{class:"fas fa-calendar-alt text-xs md:text-sm"},null,-1),p(" 本月 ",-1)]),10,Ks)])])]),S(Zt),t("div",Ms,[S(ge),S(Je)]),S(ys)])])):C("",!0)])):C("",!0),n.value==="tutorial"?(u(),x("div",Rs,[t("div",qs,[S(nt)])])):C("",!0)])}}},Js=K(js,[["__scopeId","data-v-8e64b220"]]);export{Js as default};
+import{aR as B,r as $,c as J,aW as A,x,y as u,z as t,O as p,K as H,aq as Q,u as e,aa as G,f as X,P as r,C as P,L as C,Q as O,ac as F,q as Z,aU as tt,V as et,o as st,R as S,J as at,av as it}from"./vue-vendor-CKToUHZx.js";import{L as ot}from"./LogoTitle-CCr5FYLm.js";import{_ as K}from"./index-D1PUfDNP.js";import{b as lt}from"./vendor-BDiMbLwQ.js";import nt from"./TutorialView-DmH0Lh6x.js";/* empty css */import"./element-plus-B8Fs_0jW.js";class rt{constructor(){this.baseURL=window.location.origin,this.isDev=!1}async request(l,a={}){try{this.isDev&&l.startsWith("/admin")&&(l="/webapi"+l);const n=await fetch(`${this.baseURL}${l}`,{headers:{"Content-Type":"application/json",...a.headers},...a}),d=await n.json();if(!n.ok)throw new Error(d.message||`请求失败: ${n.status}`);return d}catch(n){throw console.error("API Stats request error:",n),n}}async getKeyId(l){return this.request("/apiStats/api/get-key-id",{method:"POST",body:JSON.stringify({apiKey:l})})}async getUserStats(l){return this.request("/apiStats/api/user-stats",{method:"POST",body:JSON.stringify({apiId:l})})}async getUserModelStats(l,a="daily"){return this.request("/apiStats/api/user-model-stats",{method:"POST",body:JSON.stringify({apiId:l,period:a})})}async getOemSettings(){try{return await this.request("/admin/oem-settings")}catch(l){return console.error("Failed to load OEM settings:",l),{success:!0,data:{siteName:"Claude Relay Service",siteIcon:"",siteIconData:""}}}}}const D=new rt,M=B("apistats",()=>{const w=$(""),l=$(null),a=$(!1),n=$(!1),d=$(!0),s=$(""),i=$("daily"),m=$(null),b=$([]),v=$(null),h=$(null),f=$({siteName:"",siteIcon:"",siteIconData:""}),c=J(()=>{const o={requests:0,inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,allTokens:0,cost:0,formattedCost:"$0.000000"};return i.value==="daily"?v.value||o:h.value||o}),U=J(()=>{if(!m.value||!c.value)return{tokenUsage:0,costUsage:0,requestUsage:0};const o=c.value,g=m.value.limits;return{tokenUsage:g.tokenLimit>0?Math.min(o.allTokens/g.tokenLimit*100,100):0,costUsage:g.dailyCostLimit>0?Math.min(o.cost/g.dailyCostLimit*100,100):0,requestUsage:g.rateLimitRequests>0?Math.min(o.requests/g.rateLimitRequests*100,100):0}});async function T(){if(!w.value.trim()){s.value="请输入 API Key";return}a.value=!0,s.value="",m.value=null,b.value=[],l.value=null;try{const o=await D.getKeyId(w.value);if(o.success){l.value=o.data.id;const g=await D.getUserStats(l.value);if(g.success)m.value=g.data,await R(),s.value="",j();else throw new Error(g.message||"查询失败")}else throw new Error(o.message||"获取 API Key ID 失败")}catch(o){console.error("Query stats error:",o),s.value=o.message||"查询统计数据失败,请检查您的 API Key 是否正确",m.value=null,b.value=[],l.value=null}finally{a.value=!1}}async function R(){l.value&&(await Promise.all([L("daily"),L("monthly")]),await q(i.value))}async function L(o){try{const g=await D.getUserModelStats(l.value,o);if(g.success){const z=g.data||[],k={requests:0,inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,allTokens:0,cost:0,formattedCost:"$0.000000"};z.forEach(I=>{var W;k.requests+=I.requests||0,k.inputTokens+=I.inputTokens||0,k.outputTokens+=I.outputTokens||0,k.cacheCreateTokens+=I.cacheCreateTokens||0,k.cacheReadTokens+=I.cacheReadTokens||0,k.allTokens+=I.allTokens||0,k.cost+=((W=I.costs)==null?void 0:W.total)||0}),k.formattedCost=N(k.cost),o==="daily"?v.value=k:h.value=k}else console.warn(`Failed to load ${o} stats:`,g.message)}catch(g){console.error(`Load ${o} stats error:`,g)}}async function q(o="daily"){if(l.value){n.value=!0;try{const g=await D.getUserModelStats(l.value,o);if(g.success)b.value=g.data||[];else throw new Error(g.message||"加载模型统计失败")}catch(g){console.error("Load model stats error:",g),b.value=[]}finally{n.value=!1}}}async function E(o){i.value===o||n.value||(i.value=o,(o==="daily"&&!v.value||o==="monthly"&&!h.value)&&await L(o),await q(o))}async function _(){if(l.value){a.value=!0,s.value="",m.value=null,b.value=[];try{const o=await D.getUserStats(l.value);if(o.success)m.value=o.data,await R(),s.value="";else throw new Error(o.message||"查询失败")}catch(o){console.error("Load stats with apiId error:",o),s.value=o.message||"查询统计数据失败",m.value=null,b.value=[]}finally{a.value=!1}}}async function y(){d.value=!0;try{const o=await D.getOemSettings();o&&o.success&&o.data&&(f.value={...f.value,...o.data})}catch(o){console.error("Error loading OEM settings:",o),f.value={siteName:"Claude Relay Service",siteIcon:"",siteIconData:""}}finally{d.value=!1}}function N(o){return typeof o!="number"||o===0?"$0.000000":o>=1?"$"+o.toFixed(2):o>=.01?"$"+o.toFixed(4):"$"+o.toFixed(6)}function j(){if(l.value){const o=new URL(window.location);o.searchParams.set("apiId",l.value),window.history.pushState({},"",o)}}function V(){m.value=null,b.value=[],v.value=null,h.value=null,s.value="",i.value="daily",l.value=null}function Y(){w.value="",V()}return{apiKey:w,apiId:l,loading:a,modelStatsLoading:n,oemLoading:d,error:s,statsPeriod:i,statsData:m,modelStats:b,dailyStats:v,monthlyStats:h,oemSettings:f,currentPeriodData:c,usagePercentages:U,queryStats:T,loadAllPeriodStats:R,loadPeriodStats:L,loadModelStats:q,switchPeriod:E,loadStatsWithApiId:_,loadOemSettings:y,clearData:V,reset:Y}}),dt={class:"api-input-wide-card glass-strong rounded-3xl p-6 mb-8 shadow-xl"},mt={class:"max-w-4xl mx-auto"},ct={class:"api-input-grid grid grid-cols-1 lg:grid-cols-4"},xt={class:"lg:col-span-3"},ut=["disabled"],ft={class:"lg:col-span-1"},pt=["disabled"],yt={key:0,class:"fas fa-spinner loading-spinner"},gt={key:1,class:"fas fa-search"},bt={__name:"ApiKeyInput",setup(w){const l=M(),{apiKey:a,loading:n}=A(l),{queryStats:d}=l;return(s,i)=>(u(),x("div",dt,[i[6]||(i[6]=t("div",{class:"wide-card-title text-center mb-6"},[t("h2",{class:"text-2xl font-bold mb-2"},[t("i",{class:"fas fa-chart-line mr-3"}),p(" 使用统计查询 ")]),t("p",{class:"text-base text-gray-600"}," 查询您的 API Key 使用情况和统计数据 ")],-1)),t("div",mt,[t("div",ct,[t("div",xt,[i[3]||(i[3]=t("label",{class:"block text-sm font-medium mb-2 text-gray-700"},[t("i",{class:"fas fa-key mr-2"}),p(" 输入您的 API Key ")],-1)),H(t("input",{"onUpdate:modelValue":i[0]||(i[0]=m=>X(a)?a.value=m:null),type:"password",placeholder:"请输入您的 API Key (cr_...)",class:"wide-card-input w-full",disabled:e(n),onKeyup:i[1]||(i[1]=G((...m)=>e(d)&&e(d)(...m),["enter"]))},null,40,ut),[[Q,e(a)]])]),t("div",ft,[i[4]||(i[4]=t("label",{class:"hidden lg:block text-sm font-medium mb-2 text-gray-700"}," ",-1)),t("button",{disabled:e(n)||!e(a).trim(),class:"btn btn-primary btn-query w-full h-full flex items-center justify-center gap-2",onClick:i[2]||(i[2]=(...m)=>e(d)&&e(d)(...m))},[e(n)?(u(),x("i",yt)):(u(),x("i",gt)),p(" "+r(e(n)?"查询中...":"查询统计"),1)],8,pt)])]),i[5]||(i[5]=t("div",{class:"security-notice mt-4"},[t("i",{class:"fas fa-shield-alt mr-2"}),p(" 您的 API Key 仅用于查询自己的统计数据,不会被存储或用于其他用途 ")],-1))])]))}},vt=K(bt,[["__scopeId","data-v-d80546e3"]]),_t={class:"grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 mb-6 md:mb-8"},ht={class:"card p-4 md:p-6"},$t={class:"space-y-2 md:space-y-3"},wt={class:"flex justify-between items-center"},kt={class:"font-medium text-gray-900 text-sm md:text-base break-all"},St={class:"flex justify-between items-center"},Tt={class:"flex justify-between items-center"},It={class:"font-medium text-gray-900 text-sm md:text-base"},Ct={class:"flex justify-between items-center"},Lt={class:"font-medium text-gray-900 text-xs md:text-base break-all"},Dt={class:"flex justify-between items-start"},Pt={key:0,class:"text-right"},At={key:0,class:"text-red-600 font-medium text-sm md:text-base"},Kt={key:1,class:"text-orange-600 font-medium text-xs md:text-base break-all"},Mt={key:2,class:"text-gray-900 font-medium text-xs md:text-base break-all"},Rt={key:1,class:"text-gray-400 font-medium text-sm md:text-base"},qt={class:"card p-4 md:p-6"},jt={class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex flex-col sm:flex-row sm:items-center text-gray-900"},Ut={class:"text-xs md:text-sm font-normal text-gray-600 sm:ml-2"},Et={class:"grid grid-cols-2 gap-3 md:gap-4"},Nt={class:"stat-card text-center"},Ot={class:"text-lg md:text-3xl font-bold text-green-600"},Ft={class:"text-xs md:text-sm text-gray-600"},Vt={class:"stat-card text-center"},Wt={class:"text-lg md:text-3xl font-bold text-blue-600"},Jt={class:"text-xs md:text-sm text-gray-600"},Yt={class:"stat-card text-center"},zt={class:"text-lg md:text-3xl font-bold text-purple-600"},Bt={class:"text-xs md:text-sm text-gray-600"},Ht={class:"stat-card text-center"},Qt={class:"text-lg md:text-3xl font-bold text-yellow-600"},Gt={class:"text-xs md:text-sm text-gray-600"},Xt={__name:"StatsOverview",setup(w){const l=M(),{statsData:a,statsPeriod:n,currentPeriodData:d}=A(l),s=f=>{if(!f)return"无";try{return lt(f).format("YYYY年MM月DD日 HH:mm")}catch{return"格式错误"}},i=f=>f?new Date(f).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}):"",m=f=>f?new Date(f){if(!f)return!1;const T=(new Date(f)-new Date)/(1e3*60*60*24);return T>0&&T<=7},v=f=>(typeof f!="number"&&(f=parseInt(f)||0),f===0?"0":f>=1e6?(f/1e6).toFixed(1)+"M":f>=1e3?(f/1e3).toFixed(1)+"K":f.toLocaleString()),h=f=>({claude:"Claude",gemini:"Gemini",all:"全部模型"})[f]||f||"未知";return(f,c)=>(u(),x("div",_t,[t("div",ht,[c[8]||(c[8]=t("h3",{class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-info-circle mr-2 md:mr-3 text-blue-500 text-sm md:text-base"}),p(" API Key 信息 ")],-1)),t("div",$t,[t("div",wt,[c[0]||(c[0]=t("span",{class:"text-gray-600 text-sm md:text-base"},"名称",-1)),t("span",kt,r(e(a).name),1)]),t("div",St,[c[1]||(c[1]=t("span",{class:"text-gray-600 text-sm md:text-base"},"状态",-1)),t("span",{class:P([e(a).isActive?"text-green-600":"text-red-600","font-medium text-sm md:text-base"])},[t("i",{class:P([e(a).isActive?"fas fa-check-circle":"fas fa-times-circle","mr-1 text-xs md:text-sm"])},null,2),p(" "+r(e(a).isActive?"活跃":"已停用"),1)],2)]),t("div",Tt,[c[2]||(c[2]=t("span",{class:"text-gray-600 text-sm md:text-base"},"权限",-1)),t("span",It,r(h(e(a).permissions)),1)]),t("div",Ct,[c[3]||(c[3]=t("span",{class:"text-gray-600 text-sm md:text-base"},"创建时间",-1)),t("span",Lt,r(s(e(a).createdAt)),1)]),t("div",Dt,[c[7]||(c[7]=t("span",{class:"text-gray-600 text-sm md:text-base flex-shrink-0 mt-1"},"过期时间",-1)),e(a).expiresAt?(u(),x("div",Pt,[m(e(a).expiresAt)?(u(),x("div",At,c[4]||(c[4]=[t("i",{class:"fas fa-exclamation-circle mr-1 text-xs md:text-sm"},null,-1),p(" 已过期 ",-1)]))):b(e(a).expiresAt)?(u(),x("div",Kt,[c[5]||(c[5]=t("i",{class:"fas fa-clock mr-1 text-xs md:text-sm"},null,-1)),p(" "+r(i(e(a).expiresAt)),1)])):(u(),x("div",Mt,r(i(e(a).expiresAt)),1))])):(u(),x("div",Rt,c[6]||(c[6]=[t("i",{class:"fas fa-infinity mr-1 text-xs md:text-sm"},null,-1),p(" 永不过期 ",-1)])))])])]),t("div",qt,[t("h3",jt,[c[9]||(c[9]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-chart-bar mr-2 md:mr-3 text-green-500 text-sm md:text-base"}),p(" 使用统计概览 ")],-1)),t("span",Ut,"("+r(e(n)==="daily"?"今日":"本月")+")",1)]),t("div",Et,[t("div",Nt,[t("div",Ot,r(v(e(d).requests)),1),t("div",Ft,r(e(n)==="daily"?"今日":"本月")+"请求数 ",1)]),t("div",Vt,[t("div",Wt,r(v(e(d).allTokens)),1),t("div",Jt,r(e(n)==="daily"?"今日":"本月")+"Token数 ",1)]),t("div",Yt,[t("div",zt,r(e(d).formattedCost||"$0.000000"),1),t("div",Bt,r(e(n)==="daily"?"今日":"本月")+"费用 ",1)]),t("div",Ht,[t("div",Qt,r(v(e(d).inputTokens)),1),t("div",Gt,r(e(n)==="daily"?"今日":"本月")+"输入Token ",1)])])])]))}},Zt=K(Xt,[["__scopeId","data-v-41acf5a1"]]),te={class:"card p-4 md:p-6"},ee={class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex flex-col sm:flex-row sm:items-center text-gray-900"},se={class:"text-xs md:text-sm font-normal text-gray-600 sm:ml-2"},ae={class:"space-y-2 md:space-y-3"},ie={class:"flex justify-between items-center"},oe={class:"font-medium text-gray-900 text-sm md:text-base"},le={class:"flex justify-between items-center"},ne={class:"font-medium text-gray-900 text-sm md:text-base"},re={class:"flex justify-between items-center"},de={class:"font-medium text-gray-900 text-sm md:text-base"},me={class:"flex justify-between items-center"},ce={class:"font-medium text-gray-900 text-sm md:text-base"},xe={class:"mt-3 md:mt-4 pt-3 md:pt-4 border-t border-gray-200"},ue={class:"flex justify-between items-center font-bold text-gray-900"},fe={class:"text-sm md:text-base"},pe={class:"text-lg md:text-xl"},ye={__name:"TokenDistribution",setup(w){const l=M(),{statsPeriod:a,currentPeriodData:n}=A(l),d=s=>(typeof s!="number"&&(s=parseInt(s)||0),s===0?"0":s>=1e6?(s/1e6).toFixed(1)+"M":s>=1e3?(s/1e3).toFixed(1)+"K":s.toLocaleString());return(s,i)=>(u(),x("div",te,[t("h3",ee,[i[0]||(i[0]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-coins mr-2 md:mr-3 text-yellow-500 text-sm md:text-base"}),p(" Token 使用分布 ")],-1)),t("span",se,"("+r(e(a)==="daily"?"今日":"本月")+")",1)]),t("div",ae,[t("div",ie,[i[1]||(i[1]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-arrow-right mr-1 md:mr-2 text-green-500 text-xs md:text-sm"}),p(" 输入 Token ")],-1)),t("span",oe,r(d(e(n).inputTokens)),1)]),t("div",le,[i[2]||(i[2]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-arrow-left mr-1 md:mr-2 text-blue-500 text-xs md:text-sm"}),p(" 输出 Token ")],-1)),t("span",ne,r(d(e(n).outputTokens)),1)]),t("div",re,[i[3]||(i[3]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-save mr-1 md:mr-2 text-purple-500 text-xs md:text-sm"}),p(" 缓存创建 Token ")],-1)),t("span",de,r(d(e(n).cacheCreateTokens)),1)]),t("div",me,[i[4]||(i[4]=t("span",{class:"text-gray-600 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-download mr-1 md:mr-2 text-orange-500 text-xs md:text-sm"}),p(" 缓存读取 Token ")],-1)),t("span",ce,r(d(e(n).cacheReadTokens)),1)])]),t("div",xe,[t("div",ue,[t("span",fe,r(e(a)==="daily"?"今日":"本月")+"总计",1),t("span",pe,r(d(e(n).allTokens)),1)])])]))}},ge=K(ye,[["__scopeId","data-v-499bb025"]]),be={class:"card p-4 md:p-6"},ve={class:"space-y-2 md:space-y-3"},_e={class:"flex justify-between items-center"},he={class:"font-medium text-gray-900 text-sm md:text-base"},$e={class:"flex justify-between items-center"},we={class:"font-medium text-gray-900 text-sm md:text-base"},ke={class:"flex justify-between items-center"},Se={class:"font-medium text-gray-900 text-sm md:text-base"},Te={class:"flex justify-between items-center"},Ie={class:"font-medium text-gray-900 text-sm md:text-base"},Ce={class:"flex justify-between items-center"},Le={class:"font-medium text-gray-900 text-sm md:text-base"},De={key:0,class:"text-orange-600"},Pe={key:1,class:"text-green-600"},Ae={class:"flex justify-between items-center"},Ke={class:"font-medium text-gray-900 text-sm md:text-base"},Me={key:0,class:"text-orange-600"},Re={key:1,class:"text-green-600"},qe={key:0,class:"card p-4 md:p-6 mt-4 md:mt-6"},je={class:"grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6"},Ue={key:0,class:"bg-amber-50 border border-amber-200 rounded-lg p-3 md:p-4"},Ee={class:"space-y-1 md:space-y-2"},Ne={class:"text-gray-800 break-all"},Oe={key:1,class:"bg-blue-50 border border-blue-200 rounded-lg p-3 md:p-4"},Fe={class:"space-y-1 md:space-y-2"},Ve={class:"text-gray-800 break-all"},We={__name:"LimitConfig",setup(w){const l=M(),{statsData:a}=A(l),n=d=>(typeof d!="number"&&(d=parseInt(d)||0),d===0?"0":d>=1e6?(d/1e6).toFixed(1)+"M":d>=1e3?(d/1e3).toFixed(1)+"K":d.toLocaleString());return(d,s)=>(u(),x("div",null,[t("div",be,[s[10]||(s[10]=t("h3",{class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-shield-alt mr-2 md:mr-3 text-red-500 text-sm md:text-base"}),p(" 限制配置 ")],-1)),t("div",ve,[t("div",_e,[s[0]||(s[0]=t("span",{class:"text-gray-600 text-sm md:text-base"},"Token 限制",-1)),t("span",he,r(e(a).limits.tokenLimit>0?n(e(a).limits.tokenLimit):"无限制"),1)]),t("div",$e,[s[1]||(s[1]=t("span",{class:"text-gray-600 text-sm md:text-base"},"并发限制",-1)),t("span",we,r(e(a).limits.concurrencyLimit>0?e(a).limits.concurrencyLimit:"无限制"),1)]),t("div",ke,[s[2]||(s[2]=t("span",{class:"text-gray-600 text-sm md:text-base"},"速率限制",-1)),t("span",Se,r(e(a).limits.rateLimitRequests>0&&e(a).limits.rateLimitWindow>0?`${e(a).limits.rateLimitRequests}次/${e(a).limits.rateLimitWindow}分钟`:"无限制"),1)]),t("div",Te,[s[3]||(s[3]=t("span",{class:"text-gray-600 text-sm md:text-base"},"每日费用限制",-1)),t("span",Ie,r(e(a).limits.dailyCostLimit>0?"$"+e(a).limits.dailyCostLimit:"无限制"),1)]),t("div",Ce,[s[6]||(s[6]=t("span",{class:"text-gray-600 text-sm md:text-base"},"模型限制",-1)),t("span",Le,[e(a).restrictions.enableModelRestriction&&e(a).restrictions.restrictedModels.length>0?(u(),x("span",De,[s[4]||(s[4]=t("i",{class:"fas fa-exclamation-triangle mr-1 text-xs md:text-sm"},null,-1)),p(" 限制 "+r(e(a).restrictions.restrictedModels.length)+" 个模型 ",1)])):(u(),x("span",Pe,s[5]||(s[5]=[t("i",{class:"fas fa-check-circle mr-1 text-xs md:text-sm"},null,-1),p(" 允许所有模型 ",-1)])))])]),t("div",Ae,[s[9]||(s[9]=t("span",{class:"text-gray-600 text-sm md:text-base"},"客户端限制",-1)),t("span",Ke,[e(a).restrictions.enableClientRestriction&&e(a).restrictions.allowedClients.length>0?(u(),x("span",Me,[s[7]||(s[7]=t("i",{class:"fas fa-exclamation-triangle mr-1 text-xs md:text-sm"},null,-1)),p(" 限制 "+r(e(a).restrictions.allowedClients.length)+" 个客户端 ",1)])):(u(),x("span",Re,s[8]||(s[8]=[t("i",{class:"fas fa-check-circle mr-1 text-xs md:text-sm"},null,-1),p(" 允许所有客户端 ",-1)])))])])])]),e(a).restrictions.enableModelRestriction&&e(a).restrictions.restrictedModels.length>0||e(a).restrictions.enableClientRestriction&&e(a).restrictions.allowedClients.length>0?(u(),x("div",qe,[s[17]||(s[17]=t("h3",{class:"text-lg md:text-xl font-bold mb-3 md:mb-4 flex items-center text-gray-900"},[t("i",{class:"fas fa-list-alt mr-2 md:mr-3 text-amber-500 text-sm md:text-base"}),p(" 详细限制信息 ")],-1)),t("div",je,[e(a).restrictions.enableModelRestriction&&e(a).restrictions.restrictedModels.length>0?(u(),x("div",Ue,[s[12]||(s[12]=t("h4",{class:"font-bold text-amber-800 mb-2 md:mb-3 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-robot mr-1 md:mr-2 text-xs md:text-sm"}),p(" 受限模型列表 ")],-1)),t("div",Ee,[(u(!0),x(O,null,F(e(a).restrictions.restrictedModels,i=>(u(),x("div",{key:i,class:"bg-white rounded px-2 md:px-3 py-1 md:py-2 text-xs md:text-sm border border-amber-200"},[s[11]||(s[11]=t("i",{class:"fas fa-ban mr-1 md:mr-2 text-red-500 text-xs"},null,-1)),t("span",Ne,r(i),1)]))),128))]),s[13]||(s[13]=t("p",{class:"text-xs text-amber-700 mt-2 md:mt-3"},[t("i",{class:"fas fa-info-circle mr-1"}),p(" 此 API Key 不能访问以上列出的模型 ")],-1))])):C("",!0),e(a).restrictions.enableClientRestriction&&e(a).restrictions.allowedClients.length>0?(u(),x("div",Oe,[s[15]||(s[15]=t("h4",{class:"font-bold text-blue-800 mb-2 md:mb-3 flex items-center text-sm md:text-base"},[t("i",{class:"fas fa-desktop mr-1 md:mr-2 text-xs md:text-sm"}),p(" 允许的客户端 ")],-1)),t("div",Fe,[(u(!0),x(O,null,F(e(a).restrictions.allowedClients,i=>(u(),x("div",{key:i,class:"bg-white rounded px-2 md:px-3 py-1 md:py-2 text-xs md:text-sm border border-blue-200"},[s[14]||(s[14]=t("i",{class:"fas fa-check mr-1 md:mr-2 text-green-500 text-xs"},null,-1)),t("span",Ve,r(i),1)]))),128))]),s[16]||(s[16]=t("p",{class:"text-xs text-blue-700 mt-2 md:mt-3"},[t("i",{class:"fas fa-info-circle mr-1"}),p(" 此 API Key 只能被以上列出的客户端使用 ")],-1))])):C("",!0)])])):C("",!0)]))}},Je=K(We,[["__scopeId","data-v-8b510ae2"]]),Ye={class:"card p-4 md:p-6"},ze={class:"mb-4 md:mb-6"},Be={class:"text-lg md:text-xl font-bold flex flex-col sm:flex-row sm:items-center text-gray-900"},He={class:"text-xs md:text-sm font-normal text-gray-600 sm:ml-2"},Qe={key:0,class:"text-center py-6 md:py-8"},Ge={key:1,class:"space-y-3 md:space-y-4"},Xe={class:"flex justify-between items-start mb-2 md:mb-3"},Ze={class:"flex-1 min-w-0"},ts={class:"font-bold text-base md:text-lg text-gray-900 break-all"},es={class:"text-gray-600 text-xs md:text-sm"},ss={class:"text-right flex-shrink-0 ml-3"},as={class:"text-base md:text-lg font-bold text-green-600"},is={class:"grid grid-cols-2 md:grid-cols-4 gap-2 md:gap-3 text-xs md:text-sm"},os={class:"bg-gray-50 rounded p-2"},ls={class:"font-medium text-gray-900"},ns={class:"bg-gray-50 rounded p-2"},rs={class:"font-medium text-gray-900"},ds={class:"bg-gray-50 rounded p-2"},ms={class:"font-medium text-gray-900"},cs={class:"bg-gray-50 rounded p-2"},xs={class:"font-medium text-gray-900"},us={key:2,class:"text-center py-6 md:py-8 text-gray-500"},fs={class:"text-sm md:text-base"},ps={__name:"ModelUsageStats",setup(w){const l=M(),{statsPeriod:a,modelStats:n,modelStatsLoading:d}=A(l),s=i=>(typeof i!="number"&&(i=parseInt(i)||0),i===0?"0":i>=1e6?(i/1e6).toFixed(1)+"M":i>=1e3?(i/1e3).toFixed(1)+"K":i.toLocaleString());return(i,m)=>(u(),x("div",Ye,[t("div",ze,[t("h3",Be,[m[0]||(m[0]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-robot mr-2 md:mr-3 text-indigo-500 text-sm md:text-base"}),p(" 模型使用统计 ")],-1)),t("span",He,"("+r(e(a)==="daily"?"今日":"本月")+")",1)])]),e(d)?(u(),x("div",Qe,m[1]||(m[1]=[t("i",{class:"fas fa-spinner loading-spinner text-xl md:text-2xl mb-2 text-gray-600"},null,-1),t("p",{class:"text-gray-600 text-sm md:text-base"}," 加载模型统计数据中... ",-1)]))):e(n).length>0?(u(),x("div",Ge,[(u(!0),x(O,null,F(e(n),(b,v)=>{var h;return u(),x("div",{key:v,class:"model-usage-item"},[t("div",Xe,[t("div",Ze,[t("h4",ts,r(b.model),1),t("p",es,r(b.requests)+" 次请求 ",1)]),t("div",ss,[t("div",as,r(((h=b.formatted)==null?void 0:h.total)||"$0.000000"),1),m[2]||(m[2]=t("div",{class:"text-xs md:text-sm text-gray-600"}," 总费用 ",-1))])]),t("div",is,[t("div",os,[m[3]||(m[3]=t("div",{class:"text-gray-600"}," 输入 Token ",-1)),t("div",ls,r(s(b.inputTokens)),1)]),t("div",ns,[m[4]||(m[4]=t("div",{class:"text-gray-600"}," 输出 Token ",-1)),t("div",rs,r(s(b.outputTokens)),1)]),t("div",ds,[m[5]||(m[5]=t("div",{class:"text-gray-600"}," 缓存创建 ",-1)),t("div",ms,r(s(b.cacheCreateTokens)),1)]),t("div",cs,[m[6]||(m[6]=t("div",{class:"text-gray-600"}," 缓存读取 ",-1)),t("div",xs,r(s(b.cacheReadTokens)),1)])])])}),128))])):(u(),x("div",us,[m[7]||(m[7]=t("i",{class:"fas fa-chart-pie text-2xl md:text-3xl mb-3"},null,-1)),t("p",fs," 暂无"+r(e(a)==="daily"?"今日":"本月")+"模型使用数据 ",1)]))]))}},ys=K(ps,[["__scopeId","data-v-56679d54"]]),gs={class:"min-h-screen gradient-bg p-4 md:p-6"},bs={class:"glass-strong rounded-3xl p-4 md:p-6 mb-6 md:mb-8 shadow-xl"},vs={class:"flex flex-col md:flex-row justify-between items-center gap-4"},_s={class:"flex items-center gap-3"},hs={class:"mb-6 md:mb-8"},$s={class:"flex justify-center"},ws={class:"inline-flex bg-white/10 backdrop-blur-xl rounded-full p-1 shadow-lg border border-white/20 w-full max-w-md md:w-auto"},ks={key:0,class:"tab-content"},Ss={key:0,class:"mb-6 md:mb-8"},Ts={class:"bg-red-500/20 border border-red-500/30 rounded-xl p-3 md:p-4 text-red-800 backdrop-blur-sm text-sm md:text-base"},Is={key:1,class:"fade-in"},Cs={class:"glass-strong rounded-3xl p-4 md:p-6 shadow-xl"},Ls={class:"mb-4 md:mb-6 pb-4 md:pb-6 border-b border-gray-200"},Ds={class:"flex flex-col md:flex-row items-start md:items-center justify-between gap-3 md:gap-4"},Ps={class:"flex gap-2 w-full md:w-auto"},As=["disabled"],Ks=["disabled"],Ms={class:"grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 mb-6 md:mb-8"},Rs={key:1,class:"tab-content"},qs={class:"glass-strong rounded-3xl shadow-xl"},js={__name:"ApiStatsView",setup(w){const l=tt(),a=M(),n=$("stats"),{apiKey:d,apiId:s,loading:i,modelStatsLoading:m,oemLoading:b,error:v,statsPeriod:h,statsData:f,oemSettings:c}=A(a),{queryStats:U,switchPeriod:T,loadStatsWithApiId:R,loadOemSettings:L,reset:q}=a,E=_=>{(_.ctrlKey||_.metaKey)&&_.key==="Enter"&&(!i.value&&d.value.trim()&&U(),_.preventDefault()),_.key==="Escape"&&q()};return Z(()=>{console.log("API Stats Page loaded"),L();const _=l.query.apiId,y=l.query.apiKey;_&&_.match(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i)?(s.value=_,R()):y&&y.length>10&&(d.value=y),document.addEventListener("keydown",E)}),et(()=>{document.removeEventListener("keydown",E)}),st(d,_=>{_||a.clearData()}),(_,y)=>{const N=it("router-link");return u(),x("div",gs,[t("div",bs,[t("div",vs,[S(ot,{loading:e(b),title:e(c).siteName,subtitle:n.value==="stats"?"API Key 使用统计":"使用教程","logo-src":e(c).siteIconData||e(c).siteIcon},null,8,["loading","title","subtitle","logo-src"]),t("div",_s,[S(N,{to:"/dashboard",class:"admin-button rounded-xl px-3 py-2 md:px-4 md:py-2 text-white transition-all duration-300 flex items-center gap-2"},{default:at(()=>y[4]||(y[4]=[t("i",{class:"fas fa-cog text-sm"},null,-1),t("span",{class:"text-xs md:text-sm font-medium"},"管理后台",-1)])),_:1,__:[4]})])])]),t("div",hs,[t("div",$s,[t("div",ws,[t("button",{class:P(["tab-pill-button",n.value==="stats"?"active":""]),onClick:y[0]||(y[0]=j=>n.value="stats")},y[5]||(y[5]=[t("i",{class:"fas fa-chart-line mr-1 md:mr-2"},null,-1),t("span",{class:"text-sm md:text-base"},"统计查询",-1)]),2),t("button",{class:P(["tab-pill-button",n.value==="tutorial"?"active":""]),onClick:y[1]||(y[1]=j=>n.value="tutorial")},y[6]||(y[6]=[t("i",{class:"fas fa-graduation-cap mr-1 md:mr-2"},null,-1),t("span",{class:"text-sm md:text-base"},"使用教程",-1)]),2)])])]),n.value==="stats"?(u(),x("div",ks,[S(vt),e(v)?(u(),x("div",Ss,[t("div",Ts,[y[7]||(y[7]=t("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),p(" "+r(e(v)),1)])])):C("",!0),e(f)?(u(),x("div",Is,[t("div",Cs,[t("div",Ls,[t("div",Ds,[y[10]||(y[10]=t("div",{class:"flex items-center gap-2 md:gap-3"},[t("i",{class:"fas fa-clock text-blue-500 text-base md:text-lg"}),t("span",{class:"text-base md:text-lg font-medium text-gray-700"},"统计时间范围")],-1)),t("div",Ps,[t("button",{class:P([["period-btn",{active:e(h)==="daily"}],"px-4 md:px-6 py-2 text-xs md:text-sm font-medium flex items-center gap-1 md:gap-2 flex-1 md:flex-none justify-center"]),disabled:e(i)||e(m),onClick:y[2]||(y[2]=j=>e(T)("daily"))},y[8]||(y[8]=[t("i",{class:"fas fa-calendar-day text-xs md:text-sm"},null,-1),p(" 今日 ",-1)]),10,As),t("button",{class:P([["period-btn",{active:e(h)==="monthly"}],"px-4 md:px-6 py-2 text-xs md:text-sm font-medium flex items-center gap-1 md:gap-2 flex-1 md:flex-none justify-center"]),disabled:e(i)||e(m),onClick:y[3]||(y[3]=j=>e(T)("monthly"))},y[9]||(y[9]=[t("i",{class:"fas fa-calendar-alt text-xs md:text-sm"},null,-1),p(" 本月 ",-1)]),10,Ks)])])]),S(Zt),t("div",Ms,[S(ge),S(Je)]),S(ys)])])):C("",!0)])):C("",!0),n.value==="tutorial"?(u(),x("div",Rs,[t("div",qs,[S(nt)])])):C("",!0)])}}},Js=K(js,[["__scopeId","data-v-8e64b220"]]);export{Js as default};
diff --git a/web/admin-spa/dist/assets/DashboardView-C1WGP7UM.js b/web/admin-spa/dist/assets/DashboardView-a7p7jSsT.js
similarity index 99%
rename from web/admin-spa/dist/assets/DashboardView-C1WGP7UM.js
rename to web/admin-spa/dist/assets/DashboardView-a7p7jSsT.js
index c66cb908..a252c5a1 100644
--- a/web/admin-spa/dist/assets/DashboardView-C1WGP7UM.js
+++ b/web/admin-spa/dist/assets/DashboardView-a7p7jSsT.js
@@ -1 +1 @@
-import{E as Ct}from"./element-plus-B8Fs_0jW.js";import{aR as wt,r as k,c as Tt,aW as _t,o as mt,q as St,D as ot,V as Rt,x as _,z as t,P as y,u as o,O as S,L as H,Q as bt,ac as kt,C as G,R as $t,K as At,al as Ut,y as R}from"./vue-vendor-CKToUHZx.js";import{a as J,_ as It}from"./index-D3bIJLrk.js";import{s as xt}from"./toast-BvwA7Mwb.js";import{C as vt}from"./chart-Cor9iTVD.js";import"./vendor-BDiMbLwQ.js";const Mt=wt("dashboard",()=>{const nt=k(!1),V=k({totalApiKeys:0,activeApiKeys:0,totalAccounts:0,activeAccounts:0,rateLimitedAccounts:0,todayRequests:0,totalRequests:0,todayTokens:0,todayInputTokens:0,todayOutputTokens:0,totalTokens:0,totalInputTokens:0,totalOutputTokens:0,totalCacheCreateTokens:0,totalCacheReadTokens:0,todayCacheCreateTokens:0,todayCacheReadTokens:0,systemRPM:0,systemTPM:0,realtimeRPM:0,realtimeTPM:0,metricsWindow:5,isHistoricalMetrics:!1,systemStatus:"正常",uptime:0,systemTimezone:8}),m=k({todayCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}}}),lt=k([]),q=k([]),X=k([]),U=k({data:[],topApiKeys:[],totalApiKeys:0}),n=k({type:"preset",preset:"7days",customStart:"",customEnd:"",customRange:null,presetOptions:[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}]}),C=k("day"),E=k("requests"),F=k([new Date(2e3,1,1,0,0,0),new Date(2e3,2,1,23,59,59)]),pt=Tt(()=>{const s=V.value.uptime,d=Math.floor(s/86400),i=Math.floor(s%86400/3600),l=Math.floor(s%3600/60);return d>0?`${d}天 ${i}小时`:i>0?`${i}小时 ${l}分钟`:`${l}分钟`});function w(s,d=!0){const i=s.getFullYear(),l=s.getMonth(),a=s.getDate();return d?new Date(Date.UTC(i,l,a-1,16,0,0,0)):new Date(Date.UTC(i,l,a,15,59,59,999))}async function yt(){nt.value=!0;try{const[s,d,i]=await Promise.all([J.get("/admin/dashboard"),J.get("/admin/usage-costs?period=today"),J.get("/admin/usage-costs?period=all")]);if(s.success){const l=s.data.overview||{},a=s.data.recentActivity||{},r=s.data.systemAverages||{},u=s.data.realtimeMetrics||{},p=s.data.systemHealth||{};V.value={totalApiKeys:l.totalApiKeys||0,activeApiKeys:l.activeApiKeys||0,totalAccounts:l.totalClaudeAccounts||0,activeAccounts:l.activeClaudeAccounts||0,rateLimitedAccounts:l.rateLimitedClaudeAccounts||0,todayRequests:a.requestsToday||0,totalRequests:l.totalRequestsUsed||0,todayTokens:a.tokensToday||0,todayInputTokens:a.inputTokensToday||0,todayOutputTokens:a.outputTokensToday||0,totalTokens:l.totalTokensUsed||0,totalInputTokens:l.totalInputTokensUsed||0,totalOutputTokens:l.totalOutputTokensUsed||0,totalCacheCreateTokens:l.totalCacheCreateTokensUsed||0,totalCacheReadTokens:l.totalCacheReadTokensUsed||0,todayCacheCreateTokens:a.cacheCreateTokensToday||0,todayCacheReadTokens:a.cacheReadTokensToday||0,systemRPM:r.rpm||0,systemTPM:r.tpm||0,realtimeRPM:u.rpm||0,realtimeTPM:u.tpm||0,metricsWindow:u.windowMinutes||5,isHistoricalMetrics:u.isHistorical||!1,systemStatus:p.redisConnected?"正常":"异常",uptime:p.uptime||0,systemTimezone:s.data.systemTimezone||8}}d.success&&i.success&&(m.value={todayCosts:d.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:i.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}}})}catch(s){console.error("加载仪表板数据失败:",s)}finally{nt.value=!1}}async function rt(s=7,d="day"){try{let i="/admin/usage-trend?";if(d==="hour")if(i+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const a=r=>{const[p,c]=r.split(" "),[$,K,P]=p.split("-").map(Number),[I,O,B]=c.split(":").map(Number);return new Date(Date.UTC($,K-1,P,I-8,O,B)).toISOString()};i+=`&startDate=${encodeURIComponent(a(n.value.customRange[0]))}`,i+=`&endDate=${encodeURIComponent(a(n.value.customRange[1]))}`}else{const a=new Date;let r,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(a),r=new Date(a.getTime()-24*60*60*1e3);break;case"yesterday":const p=new Date;p.setDate(p.getDate()-1),r=w(p,!0),u=w(p,!1);break;case"dayBefore":const c=new Date;c.setDate(c.getDate()-2),r=w(c,!0),u=w(c,!1);break;default:r=new Date(a.getTime()-24*60*60*1e3),u=a}else r=new Date(a.getTime()-s*24*60*60*1e3),u=a;i+=`&startDate=${encodeURIComponent(r.toISOString())}`,i+=`&endDate=${encodeURIComponent(u.toISOString())}`}else i+=`granularity=day&days=${s}`;const l=await J.get(i);l.success&&(q.value=l.data)}catch(i){console.error("加载使用趋势失败:",i)}}async function it(s="daily"){try{let d=`/admin/model-stats?period=${s}`;if(n.value.type==="custom"||C.value==="hour"){if(n.value.customRange&&n.value.customRange.length===2){const l=a=>{const[u,p]=a.split(" "),[c,$,K]=u.split("-").map(Number),[P,I,O]=p.split(":").map(Number);return new Date(Date.UTC(c,$-1,K,P-8,I,O)).toISOString()};d+=`&startDate=${encodeURIComponent(l(n.value.customRange[0]))}`,d+=`&endDate=${encodeURIComponent(l(n.value.customRange[1]))}`}else if(C.value==="hour"&&n.value.type==="preset"){const l=new Date;let a,r;switch(n.value.preset){case"last24h":r=new Date(l),a=new Date(l.getTime()-24*60*60*1e3);break;case"yesterday":const u=new Date;u.setDate(u.getDate()-1),a=w(u,!0),r=w(u,!1);break;case"dayBefore":const p=new Date;p.setDate(p.getDate()-2),a=w(p,!0),r=w(p,!1);break;default:a=new Date(l.getTime()-24*60*60*1e3),r=l}d+=`&startDate=${encodeURIComponent(a.toISOString())}`,d+=`&endDate=${encodeURIComponent(r.toISOString())}`}}const i=await J.get(d);i.success&&(X.value=i.data)}catch(d){console.error("加载模型统计失败:",d)}}async function tt(s="requests"){try{let d="/admin/api-keys-usage-trend?",i=7;if(C.value==="hour")if(d+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const a=r=>{const[p,c]=r.split(" "),[$,K,P]=p.split("-").map(Number),[I,O,B]=c.split(":").map(Number);return new Date(Date.UTC($,K-1,P,I-8,O,B)).toISOString()};d+=`&startDate=${encodeURIComponent(a(n.value.customRange[0]))}`,d+=`&endDate=${encodeURIComponent(a(n.value.customRange[1]))}`}else{const a=new Date;let r,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(a),r=new Date(a.getTime()-24*60*60*1e3);break;case"yesterday":const p=new Date;p.setDate(p.getDate()-1),r=w(p,!0),u=w(p,!1);break;case"dayBefore":const c=new Date;c.setDate(c.getDate()-2),r=w(c,!0),u=w(c,!1);break;default:r=new Date(a.getTime()-24*60*60*1e3),u=a}else r=new Date(a.getTime()-24*60*60*1e3),u=a;d+=`&startDate=${encodeURIComponent(r.toISOString())}`,d+=`&endDate=${encodeURIComponent(u.toISOString())}`}else i=n.value.type==="preset"?n.value.preset==="today"?1:n.value.preset==="7days"?7:30:Q(n.value.customStart,n.value.customEnd),d+=`granularity=day&days=${i}`;d+=`&metric=${s}`;const l=await J.get(d);l.success&&(U.value={data:l.data||[],topApiKeys:l.topApiKeys||[],totalApiKeys:l.totalApiKeys||0})}catch(d){console.error("加载API Keys趋势失败:",d)}}function j(s){n.value.type="preset",n.value.preset=s;const d=n.value.presetOptions.find(i=>i.value===s);if(d){const i=new Date;let l,a;if(C.value==="hour")switch(s){case"last24h":a=new Date(i),l=new Date(i.getTime()-24*60*60*1e3);break;case"yesterday":const r=new Date;r.setDate(r.getDate()-1),l=w(r,!0),a=w(r,!1);break;case"dayBefore":const u=new Date;u.setDate(u.getDate()-2),l=w(u,!0),a=w(u,!1);break}else l=new Date(i),a=new Date(i),s==="today"?(l.setHours(0,0,0,0),a.setHours(23,59,59,999)):(l.setDate(i.getDate()-(d.days-1)),l.setHours(0,0,0,0),a.setHours(23,59,59,999));if(n.value.customStart=l.toISOString().split("T")[0],n.value.customEnd=a.toISOString().split("T")[0],C.value==="hour"&&(s==="yesterday"||s==="dayBefore")){const r=new Date;s==="yesterday"?r.setDate(r.getDate()-1):r.setDate(r.getDate()-2);const u=r.getFullYear(),p=String(r.getMonth()+1).padStart(2,"0"),c=String(r.getDate()).padStart(2,"0");n.value.customRange=[`${u}-${p}-${c} 00:00:00`,`${u}-${p}-${c} 23:59:59`]}else{const r=u=>{const $=new Date(u.getTime()+288e5),K=$.getUTCFullYear(),P=String($.getUTCMonth()+1).padStart(2,"0"),I=String($.getUTCDate()).padStart(2,"0"),O=String($.getUTCHours()).padStart(2,"0"),B=String($.getUTCMinutes()).padStart(2,"0"),Z=String($.getUTCSeconds()).padStart(2,"0");return`${K}-${P}-${I} ${O}:${B}:${Z}`};n.value.customRange=[r(l),r(a)]}}N()}function ft(s){if(s&&s.length===2){n.value.type="custom",n.value.preset="",n.value.customRange=s,n.value.customStart=s[0].split(" ")[0],n.value.customEnd=s[1].split(" ")[0],V.value.systemTimezone;const d=a=>{const[r,u]=a.split(" "),[p,c,$]=r.split("-").map(Number),[K,P,I]=u.split(":").map(Number);return new Date(p,c-1,$,K,P,I)},i=d(s[0]),l=d(s[1]);if(C.value==="hour"){if((l-i)/36e5>24){xt("小时粒度下日期范围不能超过24小时","warning");return}}else if(Math.ceil((l-i)/864e5)+1>31){xt("日期范围不能超过 31 天","warning");return}N()}else s===null&&j(C.value==="hour"?"last24h":"7days")}function et(s){if(C.value=s,s==="hour"){if(n.value.presetOptions=[{value:"last24h",label:"近24小时",hours:24},{value:"yesterday",label:"昨天",hours:24},{value:"dayBefore",label:"前天",hours:24}],n.value.type==="custom"&&n.value.customRange&&n.value.customRange.length===2){const d=new Date(n.value.customRange[0]);if((new Date(n.value.customRange[1])-d)/(1e3*60*60)>24){xt("小时粒度下日期范围不能超过24小时,已切换到近24小时","warning"),j("last24h");return}}if(["today","7days","30days"].includes(n.value.preset)){j("last24h");return}}else if(n.value.presetOptions=[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}],["last24h","yesterday","dayBefore"].includes(n.value.preset)){j("7days");return}N()}async function N(){let s,d="monthly";if(n.value.type==="preset"){const i=n.value.presetOptions.find(l=>l.value===n.value.preset);C.value==="hour"?(s=1,d="daily"):(s=i?i.days:7,n.value.preset==="today"?d="daily":d="monthly")}else{if(C.value==="hour"){const i=new Date(n.value.customRange[0]),l=new Date(n.value.customRange[1]),a=Math.ceil((l-i)/(1e3*60*60));s=Math.ceil(a/24)||1}else s=Q(n.value.customStart,n.value.customEnd);d="daily"}await Promise.all([rt(s,C.value),it(d),tt(E.value)])}function Q(s,d){if(!s||!d)return 7;const i=new Date(s),l=new Date(d),a=Math.abs(l-i);return Math.ceil(a/(1e3*60*60*24))||7}function Y(s){return s>new Date}return{loading:nt,dashboardData:V,costsData:m,modelStats:lt,trendData:q,dashboardModelStats:X,apiKeysTrendData:U,dateFilter:n,trendGranularity:C,apiKeysTrendMetric:E,defaultTime:F,formattedUptime:pt,loadDashboardData:yt,loadUsageTrend:rt,loadModelStats:it,loadApiKeysTrend:tt,setDateFilterPreset:j,onCustomDateRangeChange:ft,setTrendGranularity:et,refreshChartsData:N,disabledDate:Y}}),Kt={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-4 sm:mb-6 md:mb-8"},Pt={class:"stat-card"},Ft={class:"flex items-center justify-between"},Ot={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Bt={class:"text-xs text-gray-500 mt-1"},zt={class:"stat-card"},Ht={class:"flex items-center justify-between"},qt={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Et={class:"text-xs text-gray-500 mt-1"},Nt={key:0,class:"text-yellow-600"},Lt={class:"stat-card"},Vt={class:"flex items-center justify-between"},jt={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Yt={class:"text-xs text-gray-500 mt-1"},Wt={class:"stat-card"},Gt={class:"flex items-center justify-between"},Qt={class:"text-2xl sm:text-3xl font-bold text-green-600"},Zt={class:"text-xs text-gray-500 mt-1"},Jt={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-4 sm:mb-6 md:mb-8"},Xt={class:"stat-card"},te={class:"flex items-center justify-between"},ee={class:"flex-1 mr-8"},se={class:"flex items-baseline gap-2 mb-2 flex-wrap"},ae={class:"text-xl sm:text-2xl md:text-3xl font-bold text-blue-600"},oe={class:"text-sm text-green-600 font-medium"},ne={class:"text-xs text-gray-500"},le={class:"flex justify-between items-center flex-wrap gap-x-4"},re={class:"font-medium"},ie={class:"font-medium"},de={key:0,class:"text-purple-600"},ue={class:"font-medium"},ce={key:1,class:"text-purple-600"},me={class:"font-medium"},pe={class:"stat-card"},ye={class:"flex items-center justify-between"},fe={class:"flex-1 mr-8"},ge={class:"flex items-baseline gap-2 mb-2 flex-wrap"},xe={class:"text-xl sm:text-2xl md:text-3xl font-bold text-emerald-600"},ve={class:"text-sm text-green-600 font-medium"},he={class:"text-xs text-gray-500"},be={class:"flex justify-between items-center flex-wrap gap-x-4"},ke={class:"font-medium"},Te={class:"font-medium"},De={key:0,class:"text-purple-600"},Ce={class:"font-medium"},we={key:1,class:"text-purple-600"},_e={class:"font-medium"},Se={class:"stat-card"},Re={class:"flex items-center justify-between"},$e={class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"},Ae={class:"text-xs text-gray-400"},Ue={class:"text-2xl sm:text-3xl font-bold text-orange-600"},Ie={class:"text-xs text-gray-500 mt-1"},Me={key:0,class:"text-yellow-600"},Ke={class:"stat-card"},Pe={class:"flex items-center justify-between"},Fe={class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"},Oe={class:"text-xs text-gray-400"},Be={class:"text-2xl sm:text-3xl font-bold text-rose-600"},ze={class:"text-xs text-gray-500 mt-1"},He={key:0,class:"text-yellow-600"},qe={class:"mb-8"},Ee={class:"flex flex-col gap-4 mb-4 sm:mb-6"},Ne={class:"flex flex-col lg:flex-row gap-2 lg:items-center lg:justify-end"},Le={class:"flex gap-1 bg-gray-100 rounded-lg p-1 overflow-x-auto flex-shrink-0"},Ve=["onClick"],je={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ye={class:"flex items-center gap-2"},We={key:0,class:"text-xs text-orange-600"},Ge={class:"flex items-center gap-2"},Qe={class:"flex items-center bg-gray-100 rounded-lg px-3 py-1"},Ze={class:"relative inline-flex items-center cursor-pointer"},Je={class:"ml-2.5 text-sm font-medium text-gray-600 select-none flex items-center gap-1"},Xe=["disabled"],ts={class:"hidden sm:inline"},es={class:"grid grid-cols-1 lg:grid-cols-2 gap-6"},ss={class:"card p-4 sm:p-6"},as={class:"relative",style:{height:"250px"}},os={class:"card p-4 sm:p-6"},ns={key:0,class:"text-center py-8"},ls={key:1,class:"overflow-auto max-h-[250px] sm:max-h-[300px]"},rs={class:"min-w-full"},is={class:"divide-y divide-gray-200"},ds={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-900"},us=["title"],cs={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-600 text-right hidden sm:table-cell"},ms={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-600 text-right"},ps={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-green-600 text-right font-medium"},ys={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-right hidden sm:table-cell"},fs={class:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800"},gs={class:"mb-4 sm:mb-6 md:mb-8"},xs={class:"card p-4 sm:p-6"},vs={style:{height:"250px"},class:"sm:h-[300px]"},hs={class:"mb-4 sm:mb-6 md:mb-8"},bs={class:"card p-4 sm:p-6"},ks={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4"},Ts={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ds={class:"mb-4 text-xs sm:text-sm text-gray-600"},Cs={key:0},ws={key:1},_s={style:{height:"300px"},class:"sm:h-[350px]"},Ss={__name:"DashboardView",setup(nt){const V=Mt(),{dashboardData:m,costsData:lt,dashboardModelStats:q,trendData:X,apiKeysTrendData:U,formattedUptime:n,dateFilter:C,trendGranularity:E,apiKeysTrendMetric:F,defaultTime:pt}=_t(V),{loadDashboardData:w,loadApiKeysTrend:yt,setDateFilterPreset:rt,onCustomDateRangeChange:it,setTrendGranularity:tt,refreshChartsData:j,disabledDate:ft}=V,et=k(null),N=k(null),Q=k(null);let Y=null,s=null,d=null;const i=k(!1),l=k(30),a=k(null),r=k(0),u=k(null),p=k(!1);Tt(()=>!i.value||r.value<=0?"":`${r.value}秒后刷新`);function c(v){return v>=1e6?(v/1e6).toFixed(2)+"M":v>=1e3?(v/1e3).toFixed(2)+"K":v.toString()}function $(v,e){if(!e||e.length===0)return 0;const T=e.reduce((g,L)=>g+L.allTokens,0);return T===0?0:(v/T*100).toFixed(1)}function K(){if(!et.value)return;Y&&Y.destroy();const v=q.value||[],e={labels:v.map(T=>T.model),datasets:[{data:v.map(T=>T.allTokens),backgroundColor:["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],borderWidth:0}]};Y=new vt(et.value,{type:"doughnut",data:e,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:15,usePointStyle:!0,font:{size:12}}},tooltip:{callbacks:{label:function(T){const g=T.label||"",L=c(T.parsed),st=$(T.parsed,v);return`${g}: ${L} (${st}%)`}}}}}})}function P(){var D;if(!N.value)return;s&&s.destroy();const v=X.value||[],e=v.map(f=>f.inputTokens||0),T=v.map(f=>f.outputTokens||0),g=v.map(f=>f.cacheCreateTokens||0),L=v.map(f=>f.cacheReadTokens||0),st=v.map(f=>f.requests||0),dt=v.map(f=>f.cost||0),ut=(D=v[0])!=null&&D.date?"date":"hour",M={labels:v.map(f=>{if(f.label)return f.label;if(ut==="hour"){const x=new Date(f.hour),A=String(x.getMonth()+1).padStart(2,"0"),W=String(x.getDate()).padStart(2,"0"),ct=String(x.getHours()).padStart(2,"0");return`${A}/${W} ${ct}:00`}const b=f.date;if(b&&b.includes("-")){const x=b.split("-");if(x.length>=3)return`${x[1]}/${x[2]}`}return f.date}),datasets:[{label:"输入Token",data:e,borderColor:"rgb(102, 126, 234)",backgroundColor:"rgba(102, 126, 234, 0.1)",tension:.3},{label:"输出Token",data:T,borderColor:"rgb(240, 147, 251)",backgroundColor:"rgba(240, 147, 251, 0.1)",tension:.3},{label:"缓存创建Token",data:g,borderColor:"rgb(59, 130, 246)",backgroundColor:"rgba(59, 130, 246, 0.1)",tension:.3},{label:"缓存读取Token",data:L,borderColor:"rgb(147, 51, 234)",backgroundColor:"rgba(147, 51, 234, 0.1)",tension:.3},{label:"费用 (USD)",data:dt,borderColor:"rgb(34, 197, 94)",backgroundColor:"rgba(34, 197, 94, 0.1)",tension:.3,yAxisID:"y2"},{label:"请求数",data:st,borderColor:"rgb(16, 185, 129)",backgroundColor:"rgba(16, 185, 129, 0.1)",tension:.3,yAxisID:"y1"}]};s=new vt(N.value,{type:"line",data:M,options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"index",intersect:!1},plugins:{title:{display:!0,text:"Token使用趋势",font:{size:16,weight:"bold"}},legend:{position:"top"},tooltip:{mode:"index",intersect:!1,itemSort:function(f,b){const x=f.dataset.label||"",A=b.dataset.label||"";return x==="费用 (USD)"||A==="费用 (USD)"?x==="费用 (USD)"?-1:1:x==="请求数"||A==="请求数"?x==="请求数"?1:-1:b.parsed.y-f.parsed.y},callbacks:{label:function(f){const b=f.dataset.label||"";let x=f.parsed.y;return b==="费用 (USD)"?x<.01?b+": $"+x.toFixed(6):b+": $"+x.toFixed(4):b==="请求数"?b+": "+x.toLocaleString()+" 次":x>=1e6?b+": "+(x/1e6).toFixed(2)+"M tokens":x>=1e3?b+": "+(x/1e3).toFixed(2)+"K tokens":b+": "+x.toLocaleString()+" tokens"}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:E.value==="hour"?"时间":"日期"}},y:{type:"linear",display:!0,position:"left",title:{display:!0,text:"Token数量"},ticks:{callback:function(f){return c(f)}}},y1:{type:"linear",display:!0,position:"right",title:{display:!0,text:"请求数"},grid:{drawOnChartArea:!1},ticks:{callback:function(f){return f.toLocaleString()}}},y2:{type:"linear",display:!1,position:"right"}}}})}function I(){var dt,ut;if(!Q.value)return;d&&d.destroy();const v=U.value.data||[],e=F.value,T=["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],g=((dt=U.value.topApiKeys)==null?void 0:dt.map((h,M)=>{var b,x;const D=U.value.data.map(A=>!A.apiKeys||!A.apiKeys[h]?0:e==="tokens"?A.apiKeys[h].tokens:A.apiKeys[h].requests||0);return{label:((x=(b=U.value.data.find(A=>A.apiKeys&&A.apiKeys[h]))==null?void 0:b.apiKeys[h])==null?void 0:x.name)||`API Key ${h}`,data:D,borderColor:T[M%T.length],backgroundColor:T[M%T.length]+"20",tension:.4,fill:!1}}))||[],L=(ut=v[0])!=null&&ut.date?"date":"hour",st={labels:v.map(h=>{if(h.label)return h.label;if(L==="hour"){const D=new Date(h.hour),f=String(D.getMonth()+1).padStart(2,"0"),b=String(D.getDate()).padStart(2,"0"),x=String(D.getHours()).padStart(2,"0");return`${f}/${b} ${x}:00`}const M=h.date;if(M&&M.includes("-")){const D=M.split("-");if(D.length>=3)return`${D[1]}/${D[2]}`}return h.date}),datasets:g};d=new vt(Q.value,{type:"line",data:st,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:20,usePointStyle:!0,font:{size:12}}},tooltip:{mode:"index",intersect:!1,itemSort:function(h,M){return M.parsed.y-h.parsed.y},callbacks:{label:function(h){var ct;const M=h.dataset.label||"",D=h.parsed.y,f=h.dataIndex,b=U.value.data[f],A=h.chart.data.datasets.map((z,at)=>({value:z.data[f]||0,index:at})).sort((z,at)=>at.value-z.value).findIndex(z=>z.index===h.datasetIndex)+1;let W="";if(A===1?W="🥇 ":A===2?W="🥈 ":A===3&&(W="🥉 "),F.value==="tokens"){let z="";D>=1e6?z=(D/1e6).toFixed(2)+"M":D>=1e3?z=(D/1e3).toFixed(2)+"K":z=D.toLocaleString();const at=U.value.topApiKeys[h.datasetIndex],gt=(ct=b==null?void 0:b.apiKeys)==null?void 0:ct[at],Dt=(gt==null?void 0:gt.formattedCost)||"$0.00";return`${W}${M}: ${z} tokens (${Dt})`}else return`${W}${M}: ${D.toLocaleString()} 次`}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:E.value==="hour"?"时间":"日期"}},y:{beginAtZero:!0,title:{display:!0,text:F.value==="tokens"?"Token 数量":"请求次数"},ticks:{callback:function(h){return c(h)}}}}}})}async function O(){await yt(F.value),await ot(),I()}mt(q,()=>{ot(()=>K())}),mt(X,()=>{ot(()=>P())}),mt(U,()=>{ot(()=>I())});async function B(){if(!p.value){p.value=!0;try{await Promise.all([w(),j()])}finally{p.value=!1}}}function Z(){i.value&&(r.value=l.value,u.value&&clearInterval(u.value),a.value&&clearTimeout(a.value),u.value=setInterval(()=>{r.value--,r.value<=0&&clearInterval(u.value)},1e3),a.value=setTimeout(async()=>{await B(),i.value&&Z()},l.value*1e3))}function ht(){u.value&&(clearInterval(u.value),u.value=null),a.value&&(clearTimeout(a.value),a.value=null),r.value=0}return mt(i,v=>{v?Z():ht()}),St(async()=>{await B(),await ot(),K(),P(),I()}),Rt(()=>{ht(),Y&&Y.destroy(),s&&s.destroy(),d&&d.destroy()}),(v,e)=>{const T=Ct;return R(),_("div",null,[t("div",Kt,[t("div",Pt,[t("div",Ft,[t("div",null,[e[7]||(e[7]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 总API Keys ",-1)),t("p",Ot,y(o(m).totalApiKeys),1),t("p",Bt," 活跃: "+y(o(m).activeApiKeys||0),1)]),e[8]||(e[8]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-blue-500 to-blue-600"},[t("i",{class:"fas fa-key"})],-1))])]),t("div",zt,[t("div",Ht,[t("div",null,[e[9]||(e[9]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 服务账户 ",-1)),t("p",qt,y(o(m).totalAccounts),1),t("p",Et,[S(" 活跃: "+y(o(m).activeAccounts||0)+" ",1),o(m).rateLimitedAccounts>0?(R(),_("span",Nt," | 限流: "+y(o(m).rateLimitedAccounts),1)):H("",!0)])]),e[10]||(e[10]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-green-500 to-green-600"},[t("i",{class:"fas fa-user-circle"})],-1))])]),t("div",Lt,[t("div",Vt,[t("div",null,[e[11]||(e[11]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 今日请求 ",-1)),t("p",jt,y(o(m).todayRequests),1),t("p",Yt," 总请求: "+y(c(o(m).totalRequests||0)),1)]),e[12]||(e[12]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-purple-500 to-purple-600"},[t("i",{class:"fas fa-chart-line"})],-1))])]),t("div",Wt,[t("div",Gt,[t("div",null,[e[13]||(e[13]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 系统状态 ",-1)),t("p",Qt,y(o(m).systemStatus),1),t("p",Zt," 运行时间: "+y(o(n)),1)]),e[14]||(e[14]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-yellow-500 to-orange-500"},[t("i",{class:"fas fa-heartbeat"})],-1))])])]),t("div",Jt,[t("div",Xt,[t("div",te,[t("div",ee,[e[19]||(e[19]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 今日Token ",-1)),t("div",se,[t("p",ae,y(c((o(m).todayInputTokens||0)+(o(m).todayOutputTokens||0)+(o(m).todayCacheCreateTokens||0)+(o(m).todayCacheReadTokens||0))),1),t("span",oe,"/ "+y(o(lt).todayCosts.formatted.totalCost),1)]),t("div",ne,[t("div",le,[t("span",null,[e[15]||(e[15]=S("输入: ",-1)),t("span",re,y(c(o(m).todayInputTokens||0)),1)]),t("span",null,[e[16]||(e[16]=S("输出: ",-1)),t("span",ie,y(c(o(m).todayOutputTokens||0)),1)]),(o(m).todayCacheCreateTokens||0)>0?(R(),_("span",de,[e[17]||(e[17]=S("缓存创建: ",-1)),t("span",ue,y(c(o(m).todayCacheCreateTokens||0)),1)])):H("",!0),(o(m).todayCacheReadTokens||0)>0?(R(),_("span",ce,[e[18]||(e[18]=S("缓存读取: ",-1)),t("span",me,y(c(o(m).todayCacheReadTokens||0)),1)])):H("",!0)])])]),e[20]||(e[20]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-indigo-500 to-indigo-600"},[t("i",{class:"fas fa-coins"})],-1))])]),t("div",pe,[t("div",ye,[t("div",fe,[e[25]||(e[25]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 总Token消耗 ",-1)),t("div",ge,[t("p",xe,y(c((o(m).totalInputTokens||0)+(o(m).totalOutputTokens||0)+(o(m).totalCacheCreateTokens||0)+(o(m).totalCacheReadTokens||0))),1),t("span",ve,"/ "+y(o(lt).totalCosts.formatted.totalCost),1)]),t("div",he,[t("div",be,[t("span",null,[e[21]||(e[21]=S("输入: ",-1)),t("span",ke,y(c(o(m).totalInputTokens||0)),1)]),t("span",null,[e[22]||(e[22]=S("输出: ",-1)),t("span",Te,y(c(o(m).totalOutputTokens||0)),1)]),(o(m).totalCacheCreateTokens||0)>0?(R(),_("span",De,[e[23]||(e[23]=S("缓存创建: ",-1)),t("span",Ce,y(c(o(m).totalCacheCreateTokens||0)),1)])):H("",!0),(o(m).totalCacheReadTokens||0)>0?(R(),_("span",we,[e[24]||(e[24]=S("缓存读取: ",-1)),t("span",_e,y(c(o(m).totalCacheReadTokens||0)),1)])):H("",!0)])])]),e[26]||(e[26]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-emerald-500 to-emerald-600"},[t("i",{class:"fas fa-database"})],-1))])]),t("div",Se,[t("div",Re,[t("div",null,[t("p",$e,[e[27]||(e[27]=S(" 实时RPM ",-1)),t("span",Ae,"("+y(o(m).metricsWindow)+"分钟)",1)]),t("p",Ue,y(o(m).realtimeRPM||0),1),t("p",Ie,[e[29]||(e[29]=S(" 每分钟请求数 ",-1)),o(m).isHistoricalMetrics?(R(),_("span",Me,e[28]||(e[28]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),S(" 历史数据 ",-1)]))):H("",!0)])]),e[30]||(e[30]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-orange-500 to-orange-600"},[t("i",{class:"fas fa-tachometer-alt"})],-1))])]),t("div",Ke,[t("div",Pe,[t("div",null,[t("p",Fe,[e[31]||(e[31]=S(" 实时TPM ",-1)),t("span",Oe,"("+y(o(m).metricsWindow)+"分钟)",1)]),t("p",Be,y(c(o(m).realtimeTPM||0)),1),t("p",ze,[e[33]||(e[33]=S(" 每分钟Token数 ",-1)),o(m).isHistoricalMetrics?(R(),_("span",He,e[32]||(e[32]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),S(" 历史数据 ",-1)]))):H("",!0)])]),e[34]||(e[34]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-rose-500 to-rose-600"},[t("i",{class:"fas fa-rocket"})],-1))])])]),t("div",qe,[t("div",Ee,[e[41]||(e[41]=t("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 模型使用分布与Token使用趋势 ",-1)),t("div",Ne,[t("div",Le,[(R(!0),_(bt,null,kt(o(C).presetOptions,g=>(R(),_("button",{key:g.value,class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(C).preset===g.value&&o(C).type==="preset"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:L=>o(rt)(g.value)},y(g.label),11,Ve))),128))]),t("div",je,[t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(E)==="day"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[0]||(e[0]=g=>o(tt)("day"))},e[35]||(e[35]=[t("i",{class:"fas fa-calendar-day mr-1"},null,-1),S("按天 ",-1)]),2),t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(E)==="hour"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[1]||(e[1]=g=>o(tt)("hour"))},e[36]||(e[36]=[t("i",{class:"fas fa-clock mr-1"},null,-1),S("按小时 ",-1)]),2)]),t("div",Ye,[$t(T,{modelValue:o(C).customRange,"onUpdate:modelValue":e[2]||(e[2]=g=>o(C).customRange=g),"default-time":o(pt),type:"datetimerange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期",format:"YYYY-MM-DD HH:mm:ss","value-format":"YYYY-MM-DD HH:mm:ss","disabled-date":o(ft),size:"default",class:"w-full lg:w-auto custom-date-picker",style:{"max-width":"400px"},onChange:o(it)},null,8,["modelValue","default-time","disabled-date","onChange"]),o(E)==="hour"?(R(),_("span",We,e[37]||(e[37]=[t("i",{class:"fas fa-info-circle"},null,-1),S(" 最多24小时 ",-1)]))):H("",!0)]),t("div",Ge,[t("div",Qe,[t("label",Ze,[At(t("input",{"onUpdate:modelValue":e[3]||(e[3]=g=>i.value=g),type:"checkbox",class:"sr-only peer"},null,512),[[Ut,i.value]]),e[40]||(e[40]=t("div",{class:"relative w-9 h-5 bg-gray-300 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:bg-blue-500 transition-all duration-200 after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:w-4 after:h-4 after:rounded-full after:shadow-sm after:transition-transform after:duration-200 peer-checked:after:translate-x-4"},null,-1)),t("span",Je,[e[38]||(e[38]=t("i",{class:"fas fa-redo-alt text-xs text-gray-500"},null,-1)),e[39]||(e[39]=t("span",null,"自动刷新",-1)),i.value?(R(),_("span",{key:0,class:G(["ml-1 text-xs text-blue-600 font-mono transition-opacity",r.value>0?"opacity-100":"opacity-0"])},y(r.value)+"s ",3)):H("",!0)])])]),t("button",{disabled:p.value,class:"px-3 py-1 rounded-md text-sm font-medium transition-colors bg-white text-blue-600 shadow-sm hover:bg-gray-50 border border-gray-300 flex items-center gap-1 sm:gap-2 disabled:opacity-50 disabled:cursor-not-allowed",title:"立即刷新数据",onClick:e[4]||(e[4]=g=>B())},[t("i",{class:G(["fas fa-sync-alt text-xs",{"animate-spin":p.value}])},null,2),t("span",ts,y(p.value?"刷新中":"刷新"),1)],8,Xe)])])]),t("div",es,[t("div",ss,[e[42]||(e[42]=t("h4",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-4"}," Token使用分布 ",-1)),t("div",as,[t("canvas",{ref_key:"modelUsageChart",ref:et},null,512)])]),t("div",os,[e[45]||(e[45]=t("h4",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-4"}," 详细统计数据 ",-1)),o(q).length===0?(R(),_("div",ns,e[43]||(e[43]=[t("p",{class:"text-gray-500 text-sm sm:text-base"}," 暂无模型使用数据 ",-1)]))):(R(),_("div",ls,[t("table",rs,[e[44]||(e[44]=t("thead",{class:"bg-gray-50 sticky top-0"},[t("tr",null,[t("th",{class:"px-2 sm:px-4 py-2 text-left text-xs font-medium text-gray-700"}," 模型 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700 hidden sm:table-cell"}," 请求数 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700"}," 总Token "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700"}," 费用 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700 hidden sm:table-cell"}," 占比 ")])],-1)),t("tbody",is,[(R(!0),_(bt,null,kt(o(q),g=>(R(),_("tr",{key:g.model,class:"hover:bg-gray-50"},[t("td",ds,[t("span",{class:"block truncate max-w-[100px] sm:max-w-none",title:g.model},y(g.model),9,us)]),t("td",cs,y(c(g.requests)),1),t("td",ms,y(c(g.allTokens)),1),t("td",ps,y(g.formatted?g.formatted.total:"$0.000000"),1),t("td",ys,[t("span",fs,y($(g.allTokens,o(q)))+"% ",1)])]))),128))])])]))])])]),t("div",gs,[t("div",xs,[t("div",vs,[t("canvas",{ref_key:"usageTrendChart",ref:N},null,512)])])]),t("div",hs,[t("div",bs,[t("div",ks,[e[48]||(e[48]=t("h3",{class:"text-base sm:text-lg font-semibold text-gray-900"}," API Keys 使用趋势 ",-1)),t("div",Ts,[t("button",{class:G(["px-2 sm:px-3 py-1 rounded-md text-xs sm:text-sm font-medium transition-colors",o(F)==="requests"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[5]||(e[5]=g=>{F.value="requests",O()})},e[46]||(e[46]=[t("i",{class:"fas fa-exchange-alt mr-1"},null,-1),t("span",{class:"hidden sm:inline"},"请求次数",-1),t("span",{class:"sm:hidden"},"请求",-1)]),2),t("button",{class:G(["px-2 sm:px-3 py-1 rounded-md text-xs sm:text-sm font-medium transition-colors",o(F)==="tokens"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[6]||(e[6]=g=>{F.value="tokens",O()})},e[47]||(e[47]=[t("i",{class:"fas fa-coins mr-1"},null,-1),t("span",{class:"hidden sm:inline"},"Token 数量",-1),t("span",{class:"sm:hidden"},"Token",-1)]),2)])]),t("div",Ds,[o(U).totalApiKeys>10?(R(),_("span",Cs," 共 "+y(o(U).totalApiKeys)+" 个 API Key,显示使用量前 10 个 ",1)):(R(),_("span",ws," 共 "+y(o(U).totalApiKeys)+" 个 API Key ",1))]),t("div",_s,[t("canvas",{ref_key:"apiKeysUsageTrendChart",ref:Q},null,512)])])])])}}},Ks=It(Ss,[["__scopeId","data-v-a1b368e2"]]);export{Ks as default};
+import{E as Ct}from"./element-plus-B8Fs_0jW.js";import{aR as wt,r as k,c as Tt,aW as _t,o as mt,q as St,D as ot,V as Rt,x as _,z as t,P as y,u as o,O as S,L as H,Q as bt,ac as kt,C as G,R as $t,K as At,al as Ut,y as R}from"./vue-vendor-CKToUHZx.js";import{a as J,_ as It}from"./index-D1PUfDNP.js";import{s as xt}from"./toast-BvwA7Mwb.js";import{C as vt}from"./chart-Cor9iTVD.js";import"./vendor-BDiMbLwQ.js";const Mt=wt("dashboard",()=>{const nt=k(!1),V=k({totalApiKeys:0,activeApiKeys:0,totalAccounts:0,activeAccounts:0,rateLimitedAccounts:0,todayRequests:0,totalRequests:0,todayTokens:0,todayInputTokens:0,todayOutputTokens:0,totalTokens:0,totalInputTokens:0,totalOutputTokens:0,totalCacheCreateTokens:0,totalCacheReadTokens:0,todayCacheCreateTokens:0,todayCacheReadTokens:0,systemRPM:0,systemTPM:0,realtimeRPM:0,realtimeTPM:0,metricsWindow:5,isHistoricalMetrics:!1,systemStatus:"正常",uptime:0,systemTimezone:8}),m=k({todayCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}}}),lt=k([]),q=k([]),X=k([]),U=k({data:[],topApiKeys:[],totalApiKeys:0}),n=k({type:"preset",preset:"7days",customStart:"",customEnd:"",customRange:null,presetOptions:[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}]}),C=k("day"),E=k("requests"),F=k([new Date(2e3,1,1,0,0,0),new Date(2e3,2,1,23,59,59)]),pt=Tt(()=>{const s=V.value.uptime,d=Math.floor(s/86400),i=Math.floor(s%86400/3600),l=Math.floor(s%3600/60);return d>0?`${d}天 ${i}小时`:i>0?`${i}小时 ${l}分钟`:`${l}分钟`});function w(s,d=!0){const i=s.getFullYear(),l=s.getMonth(),a=s.getDate();return d?new Date(Date.UTC(i,l,a-1,16,0,0,0)):new Date(Date.UTC(i,l,a,15,59,59,999))}async function yt(){nt.value=!0;try{const[s,d,i]=await Promise.all([J.get("/admin/dashboard"),J.get("/admin/usage-costs?period=today"),J.get("/admin/usage-costs?period=all")]);if(s.success){const l=s.data.overview||{},a=s.data.recentActivity||{},r=s.data.systemAverages||{},u=s.data.realtimeMetrics||{},p=s.data.systemHealth||{};V.value={totalApiKeys:l.totalApiKeys||0,activeApiKeys:l.activeApiKeys||0,totalAccounts:l.totalClaudeAccounts||0,activeAccounts:l.activeClaudeAccounts||0,rateLimitedAccounts:l.rateLimitedClaudeAccounts||0,todayRequests:a.requestsToday||0,totalRequests:l.totalRequestsUsed||0,todayTokens:a.tokensToday||0,todayInputTokens:a.inputTokensToday||0,todayOutputTokens:a.outputTokensToday||0,totalTokens:l.totalTokensUsed||0,totalInputTokens:l.totalInputTokensUsed||0,totalOutputTokens:l.totalOutputTokensUsed||0,totalCacheCreateTokens:l.totalCacheCreateTokensUsed||0,totalCacheReadTokens:l.totalCacheReadTokensUsed||0,todayCacheCreateTokens:a.cacheCreateTokensToday||0,todayCacheReadTokens:a.cacheReadTokensToday||0,systemRPM:r.rpm||0,systemTPM:r.tpm||0,realtimeRPM:u.rpm||0,realtimeTPM:u.tpm||0,metricsWindow:u.windowMinutes||5,isHistoricalMetrics:u.isHistorical||!1,systemStatus:p.redisConnected?"正常":"异常",uptime:p.uptime||0,systemTimezone:s.data.systemTimezone||8}}d.success&&i.success&&(m.value={todayCosts:d.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:i.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}}})}catch(s){console.error("加载仪表板数据失败:",s)}finally{nt.value=!1}}async function rt(s=7,d="day"){try{let i="/admin/usage-trend?";if(d==="hour")if(i+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const a=r=>{const[p,c]=r.split(" "),[$,K,P]=p.split("-").map(Number),[I,O,B]=c.split(":").map(Number);return new Date(Date.UTC($,K-1,P,I-8,O,B)).toISOString()};i+=`&startDate=${encodeURIComponent(a(n.value.customRange[0]))}`,i+=`&endDate=${encodeURIComponent(a(n.value.customRange[1]))}`}else{const a=new Date;let r,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(a),r=new Date(a.getTime()-24*60*60*1e3);break;case"yesterday":const p=new Date;p.setDate(p.getDate()-1),r=w(p,!0),u=w(p,!1);break;case"dayBefore":const c=new Date;c.setDate(c.getDate()-2),r=w(c,!0),u=w(c,!1);break;default:r=new Date(a.getTime()-24*60*60*1e3),u=a}else r=new Date(a.getTime()-s*24*60*60*1e3),u=a;i+=`&startDate=${encodeURIComponent(r.toISOString())}`,i+=`&endDate=${encodeURIComponent(u.toISOString())}`}else i+=`granularity=day&days=${s}`;const l=await J.get(i);l.success&&(q.value=l.data)}catch(i){console.error("加载使用趋势失败:",i)}}async function it(s="daily"){try{let d=`/admin/model-stats?period=${s}`;if(n.value.type==="custom"||C.value==="hour"){if(n.value.customRange&&n.value.customRange.length===2){const l=a=>{const[u,p]=a.split(" "),[c,$,K]=u.split("-").map(Number),[P,I,O]=p.split(":").map(Number);return new Date(Date.UTC(c,$-1,K,P-8,I,O)).toISOString()};d+=`&startDate=${encodeURIComponent(l(n.value.customRange[0]))}`,d+=`&endDate=${encodeURIComponent(l(n.value.customRange[1]))}`}else if(C.value==="hour"&&n.value.type==="preset"){const l=new Date;let a,r;switch(n.value.preset){case"last24h":r=new Date(l),a=new Date(l.getTime()-24*60*60*1e3);break;case"yesterday":const u=new Date;u.setDate(u.getDate()-1),a=w(u,!0),r=w(u,!1);break;case"dayBefore":const p=new Date;p.setDate(p.getDate()-2),a=w(p,!0),r=w(p,!1);break;default:a=new Date(l.getTime()-24*60*60*1e3),r=l}d+=`&startDate=${encodeURIComponent(a.toISOString())}`,d+=`&endDate=${encodeURIComponent(r.toISOString())}`}}const i=await J.get(d);i.success&&(X.value=i.data)}catch(d){console.error("加载模型统计失败:",d)}}async function tt(s="requests"){try{let d="/admin/api-keys-usage-trend?",i=7;if(C.value==="hour")if(d+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const a=r=>{const[p,c]=r.split(" "),[$,K,P]=p.split("-").map(Number),[I,O,B]=c.split(":").map(Number);return new Date(Date.UTC($,K-1,P,I-8,O,B)).toISOString()};d+=`&startDate=${encodeURIComponent(a(n.value.customRange[0]))}`,d+=`&endDate=${encodeURIComponent(a(n.value.customRange[1]))}`}else{const a=new Date;let r,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(a),r=new Date(a.getTime()-24*60*60*1e3);break;case"yesterday":const p=new Date;p.setDate(p.getDate()-1),r=w(p,!0),u=w(p,!1);break;case"dayBefore":const c=new Date;c.setDate(c.getDate()-2),r=w(c,!0),u=w(c,!1);break;default:r=new Date(a.getTime()-24*60*60*1e3),u=a}else r=new Date(a.getTime()-24*60*60*1e3),u=a;d+=`&startDate=${encodeURIComponent(r.toISOString())}`,d+=`&endDate=${encodeURIComponent(u.toISOString())}`}else i=n.value.type==="preset"?n.value.preset==="today"?1:n.value.preset==="7days"?7:30:Q(n.value.customStart,n.value.customEnd),d+=`granularity=day&days=${i}`;d+=`&metric=${s}`;const l=await J.get(d);l.success&&(U.value={data:l.data||[],topApiKeys:l.topApiKeys||[],totalApiKeys:l.totalApiKeys||0})}catch(d){console.error("加载API Keys趋势失败:",d)}}function j(s){n.value.type="preset",n.value.preset=s;const d=n.value.presetOptions.find(i=>i.value===s);if(d){const i=new Date;let l,a;if(C.value==="hour")switch(s){case"last24h":a=new Date(i),l=new Date(i.getTime()-24*60*60*1e3);break;case"yesterday":const r=new Date;r.setDate(r.getDate()-1),l=w(r,!0),a=w(r,!1);break;case"dayBefore":const u=new Date;u.setDate(u.getDate()-2),l=w(u,!0),a=w(u,!1);break}else l=new Date(i),a=new Date(i),s==="today"?(l.setHours(0,0,0,0),a.setHours(23,59,59,999)):(l.setDate(i.getDate()-(d.days-1)),l.setHours(0,0,0,0),a.setHours(23,59,59,999));if(n.value.customStart=l.toISOString().split("T")[0],n.value.customEnd=a.toISOString().split("T")[0],C.value==="hour"&&(s==="yesterday"||s==="dayBefore")){const r=new Date;s==="yesterday"?r.setDate(r.getDate()-1):r.setDate(r.getDate()-2);const u=r.getFullYear(),p=String(r.getMonth()+1).padStart(2,"0"),c=String(r.getDate()).padStart(2,"0");n.value.customRange=[`${u}-${p}-${c} 00:00:00`,`${u}-${p}-${c} 23:59:59`]}else{const r=u=>{const $=new Date(u.getTime()+288e5),K=$.getUTCFullYear(),P=String($.getUTCMonth()+1).padStart(2,"0"),I=String($.getUTCDate()).padStart(2,"0"),O=String($.getUTCHours()).padStart(2,"0"),B=String($.getUTCMinutes()).padStart(2,"0"),Z=String($.getUTCSeconds()).padStart(2,"0");return`${K}-${P}-${I} ${O}:${B}:${Z}`};n.value.customRange=[r(l),r(a)]}}N()}function ft(s){if(s&&s.length===2){n.value.type="custom",n.value.preset="",n.value.customRange=s,n.value.customStart=s[0].split(" ")[0],n.value.customEnd=s[1].split(" ")[0],V.value.systemTimezone;const d=a=>{const[r,u]=a.split(" "),[p,c,$]=r.split("-").map(Number),[K,P,I]=u.split(":").map(Number);return new Date(p,c-1,$,K,P,I)},i=d(s[0]),l=d(s[1]);if(C.value==="hour"){if((l-i)/36e5>24){xt("小时粒度下日期范围不能超过24小时","warning");return}}else if(Math.ceil((l-i)/864e5)+1>31){xt("日期范围不能超过 31 天","warning");return}N()}else s===null&&j(C.value==="hour"?"last24h":"7days")}function et(s){if(C.value=s,s==="hour"){if(n.value.presetOptions=[{value:"last24h",label:"近24小时",hours:24},{value:"yesterday",label:"昨天",hours:24},{value:"dayBefore",label:"前天",hours:24}],n.value.type==="custom"&&n.value.customRange&&n.value.customRange.length===2){const d=new Date(n.value.customRange[0]);if((new Date(n.value.customRange[1])-d)/(1e3*60*60)>24){xt("小时粒度下日期范围不能超过24小时,已切换到近24小时","warning"),j("last24h");return}}if(["today","7days","30days"].includes(n.value.preset)){j("last24h");return}}else if(n.value.presetOptions=[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}],["last24h","yesterday","dayBefore"].includes(n.value.preset)){j("7days");return}N()}async function N(){let s,d="monthly";if(n.value.type==="preset"){const i=n.value.presetOptions.find(l=>l.value===n.value.preset);C.value==="hour"?(s=1,d="daily"):(s=i?i.days:7,n.value.preset==="today"?d="daily":d="monthly")}else{if(C.value==="hour"){const i=new Date(n.value.customRange[0]),l=new Date(n.value.customRange[1]),a=Math.ceil((l-i)/(1e3*60*60));s=Math.ceil(a/24)||1}else s=Q(n.value.customStart,n.value.customEnd);d="daily"}await Promise.all([rt(s,C.value),it(d),tt(E.value)])}function Q(s,d){if(!s||!d)return 7;const i=new Date(s),l=new Date(d),a=Math.abs(l-i);return Math.ceil(a/(1e3*60*60*24))||7}function Y(s){return s>new Date}return{loading:nt,dashboardData:V,costsData:m,modelStats:lt,trendData:q,dashboardModelStats:X,apiKeysTrendData:U,dateFilter:n,trendGranularity:C,apiKeysTrendMetric:E,defaultTime:F,formattedUptime:pt,loadDashboardData:yt,loadUsageTrend:rt,loadModelStats:it,loadApiKeysTrend:tt,setDateFilterPreset:j,onCustomDateRangeChange:ft,setTrendGranularity:et,refreshChartsData:N,disabledDate:Y}}),Kt={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-4 sm:mb-6 md:mb-8"},Pt={class:"stat-card"},Ft={class:"flex items-center justify-between"},Ot={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Bt={class:"text-xs text-gray-500 mt-1"},zt={class:"stat-card"},Ht={class:"flex items-center justify-between"},qt={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Et={class:"text-xs text-gray-500 mt-1"},Nt={key:0,class:"text-yellow-600"},Lt={class:"stat-card"},Vt={class:"flex items-center justify-between"},jt={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Yt={class:"text-xs text-gray-500 mt-1"},Wt={class:"stat-card"},Gt={class:"flex items-center justify-between"},Qt={class:"text-2xl sm:text-3xl font-bold text-green-600"},Zt={class:"text-xs text-gray-500 mt-1"},Jt={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-4 sm:mb-6 md:mb-8"},Xt={class:"stat-card"},te={class:"flex items-center justify-between"},ee={class:"flex-1 mr-8"},se={class:"flex items-baseline gap-2 mb-2 flex-wrap"},ae={class:"text-xl sm:text-2xl md:text-3xl font-bold text-blue-600"},oe={class:"text-sm text-green-600 font-medium"},ne={class:"text-xs text-gray-500"},le={class:"flex justify-between items-center flex-wrap gap-x-4"},re={class:"font-medium"},ie={class:"font-medium"},de={key:0,class:"text-purple-600"},ue={class:"font-medium"},ce={key:1,class:"text-purple-600"},me={class:"font-medium"},pe={class:"stat-card"},ye={class:"flex items-center justify-between"},fe={class:"flex-1 mr-8"},ge={class:"flex items-baseline gap-2 mb-2 flex-wrap"},xe={class:"text-xl sm:text-2xl md:text-3xl font-bold text-emerald-600"},ve={class:"text-sm text-green-600 font-medium"},he={class:"text-xs text-gray-500"},be={class:"flex justify-between items-center flex-wrap gap-x-4"},ke={class:"font-medium"},Te={class:"font-medium"},De={key:0,class:"text-purple-600"},Ce={class:"font-medium"},we={key:1,class:"text-purple-600"},_e={class:"font-medium"},Se={class:"stat-card"},Re={class:"flex items-center justify-between"},$e={class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"},Ae={class:"text-xs text-gray-400"},Ue={class:"text-2xl sm:text-3xl font-bold text-orange-600"},Ie={class:"text-xs text-gray-500 mt-1"},Me={key:0,class:"text-yellow-600"},Ke={class:"stat-card"},Pe={class:"flex items-center justify-between"},Fe={class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"},Oe={class:"text-xs text-gray-400"},Be={class:"text-2xl sm:text-3xl font-bold text-rose-600"},ze={class:"text-xs text-gray-500 mt-1"},He={key:0,class:"text-yellow-600"},qe={class:"mb-8"},Ee={class:"flex flex-col gap-4 mb-4 sm:mb-6"},Ne={class:"flex flex-col lg:flex-row gap-2 lg:items-center lg:justify-end"},Le={class:"flex gap-1 bg-gray-100 rounded-lg p-1 overflow-x-auto flex-shrink-0"},Ve=["onClick"],je={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ye={class:"flex items-center gap-2"},We={key:0,class:"text-xs text-orange-600"},Ge={class:"flex items-center gap-2"},Qe={class:"flex items-center bg-gray-100 rounded-lg px-3 py-1"},Ze={class:"relative inline-flex items-center cursor-pointer"},Je={class:"ml-2.5 text-sm font-medium text-gray-600 select-none flex items-center gap-1"},Xe=["disabled"],ts={class:"hidden sm:inline"},es={class:"grid grid-cols-1 lg:grid-cols-2 gap-6"},ss={class:"card p-4 sm:p-6"},as={class:"relative",style:{height:"250px"}},os={class:"card p-4 sm:p-6"},ns={key:0,class:"text-center py-8"},ls={key:1,class:"overflow-auto max-h-[250px] sm:max-h-[300px]"},rs={class:"min-w-full"},is={class:"divide-y divide-gray-200"},ds={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-900"},us=["title"],cs={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-600 text-right hidden sm:table-cell"},ms={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-600 text-right"},ps={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-green-600 text-right font-medium"},ys={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-right hidden sm:table-cell"},fs={class:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800"},gs={class:"mb-4 sm:mb-6 md:mb-8"},xs={class:"card p-4 sm:p-6"},vs={style:{height:"250px"},class:"sm:h-[300px]"},hs={class:"mb-4 sm:mb-6 md:mb-8"},bs={class:"card p-4 sm:p-6"},ks={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4"},Ts={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ds={class:"mb-4 text-xs sm:text-sm text-gray-600"},Cs={key:0},ws={key:1},_s={style:{height:"300px"},class:"sm:h-[350px]"},Ss={__name:"DashboardView",setup(nt){const V=Mt(),{dashboardData:m,costsData:lt,dashboardModelStats:q,trendData:X,apiKeysTrendData:U,formattedUptime:n,dateFilter:C,trendGranularity:E,apiKeysTrendMetric:F,defaultTime:pt}=_t(V),{loadDashboardData:w,loadApiKeysTrend:yt,setDateFilterPreset:rt,onCustomDateRangeChange:it,setTrendGranularity:tt,refreshChartsData:j,disabledDate:ft}=V,et=k(null),N=k(null),Q=k(null);let Y=null,s=null,d=null;const i=k(!1),l=k(30),a=k(null),r=k(0),u=k(null),p=k(!1);Tt(()=>!i.value||r.value<=0?"":`${r.value}秒后刷新`);function c(v){return v>=1e6?(v/1e6).toFixed(2)+"M":v>=1e3?(v/1e3).toFixed(2)+"K":v.toString()}function $(v,e){if(!e||e.length===0)return 0;const T=e.reduce((g,L)=>g+L.allTokens,0);return T===0?0:(v/T*100).toFixed(1)}function K(){if(!et.value)return;Y&&Y.destroy();const v=q.value||[],e={labels:v.map(T=>T.model),datasets:[{data:v.map(T=>T.allTokens),backgroundColor:["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],borderWidth:0}]};Y=new vt(et.value,{type:"doughnut",data:e,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:15,usePointStyle:!0,font:{size:12}}},tooltip:{callbacks:{label:function(T){const g=T.label||"",L=c(T.parsed),st=$(T.parsed,v);return`${g}: ${L} (${st}%)`}}}}}})}function P(){var D;if(!N.value)return;s&&s.destroy();const v=X.value||[],e=v.map(f=>f.inputTokens||0),T=v.map(f=>f.outputTokens||0),g=v.map(f=>f.cacheCreateTokens||0),L=v.map(f=>f.cacheReadTokens||0),st=v.map(f=>f.requests||0),dt=v.map(f=>f.cost||0),ut=(D=v[0])!=null&&D.date?"date":"hour",M={labels:v.map(f=>{if(f.label)return f.label;if(ut==="hour"){const x=new Date(f.hour),A=String(x.getMonth()+1).padStart(2,"0"),W=String(x.getDate()).padStart(2,"0"),ct=String(x.getHours()).padStart(2,"0");return`${A}/${W} ${ct}:00`}const b=f.date;if(b&&b.includes("-")){const x=b.split("-");if(x.length>=3)return`${x[1]}/${x[2]}`}return f.date}),datasets:[{label:"输入Token",data:e,borderColor:"rgb(102, 126, 234)",backgroundColor:"rgba(102, 126, 234, 0.1)",tension:.3},{label:"输出Token",data:T,borderColor:"rgb(240, 147, 251)",backgroundColor:"rgba(240, 147, 251, 0.1)",tension:.3},{label:"缓存创建Token",data:g,borderColor:"rgb(59, 130, 246)",backgroundColor:"rgba(59, 130, 246, 0.1)",tension:.3},{label:"缓存读取Token",data:L,borderColor:"rgb(147, 51, 234)",backgroundColor:"rgba(147, 51, 234, 0.1)",tension:.3},{label:"费用 (USD)",data:dt,borderColor:"rgb(34, 197, 94)",backgroundColor:"rgba(34, 197, 94, 0.1)",tension:.3,yAxisID:"y2"},{label:"请求数",data:st,borderColor:"rgb(16, 185, 129)",backgroundColor:"rgba(16, 185, 129, 0.1)",tension:.3,yAxisID:"y1"}]};s=new vt(N.value,{type:"line",data:M,options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"index",intersect:!1},plugins:{title:{display:!0,text:"Token使用趋势",font:{size:16,weight:"bold"}},legend:{position:"top"},tooltip:{mode:"index",intersect:!1,itemSort:function(f,b){const x=f.dataset.label||"",A=b.dataset.label||"";return x==="费用 (USD)"||A==="费用 (USD)"?x==="费用 (USD)"?-1:1:x==="请求数"||A==="请求数"?x==="请求数"?1:-1:b.parsed.y-f.parsed.y},callbacks:{label:function(f){const b=f.dataset.label||"";let x=f.parsed.y;return b==="费用 (USD)"?x<.01?b+": $"+x.toFixed(6):b+": $"+x.toFixed(4):b==="请求数"?b+": "+x.toLocaleString()+" 次":x>=1e6?b+": "+(x/1e6).toFixed(2)+"M tokens":x>=1e3?b+": "+(x/1e3).toFixed(2)+"K tokens":b+": "+x.toLocaleString()+" tokens"}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:E.value==="hour"?"时间":"日期"}},y:{type:"linear",display:!0,position:"left",title:{display:!0,text:"Token数量"},ticks:{callback:function(f){return c(f)}}},y1:{type:"linear",display:!0,position:"right",title:{display:!0,text:"请求数"},grid:{drawOnChartArea:!1},ticks:{callback:function(f){return f.toLocaleString()}}},y2:{type:"linear",display:!1,position:"right"}}}})}function I(){var dt,ut;if(!Q.value)return;d&&d.destroy();const v=U.value.data||[],e=F.value,T=["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],g=((dt=U.value.topApiKeys)==null?void 0:dt.map((h,M)=>{var b,x;const D=U.value.data.map(A=>!A.apiKeys||!A.apiKeys[h]?0:e==="tokens"?A.apiKeys[h].tokens:A.apiKeys[h].requests||0);return{label:((x=(b=U.value.data.find(A=>A.apiKeys&&A.apiKeys[h]))==null?void 0:b.apiKeys[h])==null?void 0:x.name)||`API Key ${h}`,data:D,borderColor:T[M%T.length],backgroundColor:T[M%T.length]+"20",tension:.4,fill:!1}}))||[],L=(ut=v[0])!=null&&ut.date?"date":"hour",st={labels:v.map(h=>{if(h.label)return h.label;if(L==="hour"){const D=new Date(h.hour),f=String(D.getMonth()+1).padStart(2,"0"),b=String(D.getDate()).padStart(2,"0"),x=String(D.getHours()).padStart(2,"0");return`${f}/${b} ${x}:00`}const M=h.date;if(M&&M.includes("-")){const D=M.split("-");if(D.length>=3)return`${D[1]}/${D[2]}`}return h.date}),datasets:g};d=new vt(Q.value,{type:"line",data:st,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:20,usePointStyle:!0,font:{size:12}}},tooltip:{mode:"index",intersect:!1,itemSort:function(h,M){return M.parsed.y-h.parsed.y},callbacks:{label:function(h){var ct;const M=h.dataset.label||"",D=h.parsed.y,f=h.dataIndex,b=U.value.data[f],A=h.chart.data.datasets.map((z,at)=>({value:z.data[f]||0,index:at})).sort((z,at)=>at.value-z.value).findIndex(z=>z.index===h.datasetIndex)+1;let W="";if(A===1?W="🥇 ":A===2?W="🥈 ":A===3&&(W="🥉 "),F.value==="tokens"){let z="";D>=1e6?z=(D/1e6).toFixed(2)+"M":D>=1e3?z=(D/1e3).toFixed(2)+"K":z=D.toLocaleString();const at=U.value.topApiKeys[h.datasetIndex],gt=(ct=b==null?void 0:b.apiKeys)==null?void 0:ct[at],Dt=(gt==null?void 0:gt.formattedCost)||"$0.00";return`${W}${M}: ${z} tokens (${Dt})`}else return`${W}${M}: ${D.toLocaleString()} 次`}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:E.value==="hour"?"时间":"日期"}},y:{beginAtZero:!0,title:{display:!0,text:F.value==="tokens"?"Token 数量":"请求次数"},ticks:{callback:function(h){return c(h)}}}}}})}async function O(){await yt(F.value),await ot(),I()}mt(q,()=>{ot(()=>K())}),mt(X,()=>{ot(()=>P())}),mt(U,()=>{ot(()=>I())});async function B(){if(!p.value){p.value=!0;try{await Promise.all([w(),j()])}finally{p.value=!1}}}function Z(){i.value&&(r.value=l.value,u.value&&clearInterval(u.value),a.value&&clearTimeout(a.value),u.value=setInterval(()=>{r.value--,r.value<=0&&clearInterval(u.value)},1e3),a.value=setTimeout(async()=>{await B(),i.value&&Z()},l.value*1e3))}function ht(){u.value&&(clearInterval(u.value),u.value=null),a.value&&(clearTimeout(a.value),a.value=null),r.value=0}return mt(i,v=>{v?Z():ht()}),St(async()=>{await B(),await ot(),K(),P(),I()}),Rt(()=>{ht(),Y&&Y.destroy(),s&&s.destroy(),d&&d.destroy()}),(v,e)=>{const T=Ct;return R(),_("div",null,[t("div",Kt,[t("div",Pt,[t("div",Ft,[t("div",null,[e[7]||(e[7]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 总API Keys ",-1)),t("p",Ot,y(o(m).totalApiKeys),1),t("p",Bt," 活跃: "+y(o(m).activeApiKeys||0),1)]),e[8]||(e[8]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-blue-500 to-blue-600"},[t("i",{class:"fas fa-key"})],-1))])]),t("div",zt,[t("div",Ht,[t("div",null,[e[9]||(e[9]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 服务账户 ",-1)),t("p",qt,y(o(m).totalAccounts),1),t("p",Et,[S(" 活跃: "+y(o(m).activeAccounts||0)+" ",1),o(m).rateLimitedAccounts>0?(R(),_("span",Nt," | 限流: "+y(o(m).rateLimitedAccounts),1)):H("",!0)])]),e[10]||(e[10]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-green-500 to-green-600"},[t("i",{class:"fas fa-user-circle"})],-1))])]),t("div",Lt,[t("div",Vt,[t("div",null,[e[11]||(e[11]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 今日请求 ",-1)),t("p",jt,y(o(m).todayRequests),1),t("p",Yt," 总请求: "+y(c(o(m).totalRequests||0)),1)]),e[12]||(e[12]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-purple-500 to-purple-600"},[t("i",{class:"fas fa-chart-line"})],-1))])]),t("div",Wt,[t("div",Gt,[t("div",null,[e[13]||(e[13]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 系统状态 ",-1)),t("p",Qt,y(o(m).systemStatus),1),t("p",Zt," 运行时间: "+y(o(n)),1)]),e[14]||(e[14]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-yellow-500 to-orange-500"},[t("i",{class:"fas fa-heartbeat"})],-1))])])]),t("div",Jt,[t("div",Xt,[t("div",te,[t("div",ee,[e[19]||(e[19]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 今日Token ",-1)),t("div",se,[t("p",ae,y(c((o(m).todayInputTokens||0)+(o(m).todayOutputTokens||0)+(o(m).todayCacheCreateTokens||0)+(o(m).todayCacheReadTokens||0))),1),t("span",oe,"/ "+y(o(lt).todayCosts.formatted.totalCost),1)]),t("div",ne,[t("div",le,[t("span",null,[e[15]||(e[15]=S("输入: ",-1)),t("span",re,y(c(o(m).todayInputTokens||0)),1)]),t("span",null,[e[16]||(e[16]=S("输出: ",-1)),t("span",ie,y(c(o(m).todayOutputTokens||0)),1)]),(o(m).todayCacheCreateTokens||0)>0?(R(),_("span",de,[e[17]||(e[17]=S("缓存创建: ",-1)),t("span",ue,y(c(o(m).todayCacheCreateTokens||0)),1)])):H("",!0),(o(m).todayCacheReadTokens||0)>0?(R(),_("span",ce,[e[18]||(e[18]=S("缓存读取: ",-1)),t("span",me,y(c(o(m).todayCacheReadTokens||0)),1)])):H("",!0)])])]),e[20]||(e[20]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-indigo-500 to-indigo-600"},[t("i",{class:"fas fa-coins"})],-1))])]),t("div",pe,[t("div",ye,[t("div",fe,[e[25]||(e[25]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 总Token消耗 ",-1)),t("div",ge,[t("p",xe,y(c((o(m).totalInputTokens||0)+(o(m).totalOutputTokens||0)+(o(m).totalCacheCreateTokens||0)+(o(m).totalCacheReadTokens||0))),1),t("span",ve,"/ "+y(o(lt).totalCosts.formatted.totalCost),1)]),t("div",he,[t("div",be,[t("span",null,[e[21]||(e[21]=S("输入: ",-1)),t("span",ke,y(c(o(m).totalInputTokens||0)),1)]),t("span",null,[e[22]||(e[22]=S("输出: ",-1)),t("span",Te,y(c(o(m).totalOutputTokens||0)),1)]),(o(m).totalCacheCreateTokens||0)>0?(R(),_("span",De,[e[23]||(e[23]=S("缓存创建: ",-1)),t("span",Ce,y(c(o(m).totalCacheCreateTokens||0)),1)])):H("",!0),(o(m).totalCacheReadTokens||0)>0?(R(),_("span",we,[e[24]||(e[24]=S("缓存读取: ",-1)),t("span",_e,y(c(o(m).totalCacheReadTokens||0)),1)])):H("",!0)])])]),e[26]||(e[26]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-emerald-500 to-emerald-600"},[t("i",{class:"fas fa-database"})],-1))])]),t("div",Se,[t("div",Re,[t("div",null,[t("p",$e,[e[27]||(e[27]=S(" 实时RPM ",-1)),t("span",Ae,"("+y(o(m).metricsWindow)+"分钟)",1)]),t("p",Ue,y(o(m).realtimeRPM||0),1),t("p",Ie,[e[29]||(e[29]=S(" 每分钟请求数 ",-1)),o(m).isHistoricalMetrics?(R(),_("span",Me,e[28]||(e[28]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),S(" 历史数据 ",-1)]))):H("",!0)])]),e[30]||(e[30]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-orange-500 to-orange-600"},[t("i",{class:"fas fa-tachometer-alt"})],-1))])]),t("div",Ke,[t("div",Pe,[t("div",null,[t("p",Fe,[e[31]||(e[31]=S(" 实时TPM ",-1)),t("span",Oe,"("+y(o(m).metricsWindow)+"分钟)",1)]),t("p",Be,y(c(o(m).realtimeTPM||0)),1),t("p",ze,[e[33]||(e[33]=S(" 每分钟Token数 ",-1)),o(m).isHistoricalMetrics?(R(),_("span",He,e[32]||(e[32]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),S(" 历史数据 ",-1)]))):H("",!0)])]),e[34]||(e[34]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-rose-500 to-rose-600"},[t("i",{class:"fas fa-rocket"})],-1))])])]),t("div",qe,[t("div",Ee,[e[41]||(e[41]=t("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 模型使用分布与Token使用趋势 ",-1)),t("div",Ne,[t("div",Le,[(R(!0),_(bt,null,kt(o(C).presetOptions,g=>(R(),_("button",{key:g.value,class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(C).preset===g.value&&o(C).type==="preset"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:L=>o(rt)(g.value)},y(g.label),11,Ve))),128))]),t("div",je,[t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(E)==="day"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[0]||(e[0]=g=>o(tt)("day"))},e[35]||(e[35]=[t("i",{class:"fas fa-calendar-day mr-1"},null,-1),S("按天 ",-1)]),2),t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(E)==="hour"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[1]||(e[1]=g=>o(tt)("hour"))},e[36]||(e[36]=[t("i",{class:"fas fa-clock mr-1"},null,-1),S("按小时 ",-1)]),2)]),t("div",Ye,[$t(T,{modelValue:o(C).customRange,"onUpdate:modelValue":e[2]||(e[2]=g=>o(C).customRange=g),"default-time":o(pt),type:"datetimerange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期",format:"YYYY-MM-DD HH:mm:ss","value-format":"YYYY-MM-DD HH:mm:ss","disabled-date":o(ft),size:"default",class:"w-full lg:w-auto custom-date-picker",style:{"max-width":"400px"},onChange:o(it)},null,8,["modelValue","default-time","disabled-date","onChange"]),o(E)==="hour"?(R(),_("span",We,e[37]||(e[37]=[t("i",{class:"fas fa-info-circle"},null,-1),S(" 最多24小时 ",-1)]))):H("",!0)]),t("div",Ge,[t("div",Qe,[t("label",Ze,[At(t("input",{"onUpdate:modelValue":e[3]||(e[3]=g=>i.value=g),type:"checkbox",class:"sr-only peer"},null,512),[[Ut,i.value]]),e[40]||(e[40]=t("div",{class:"relative w-9 h-5 bg-gray-300 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:bg-blue-500 transition-all duration-200 after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:w-4 after:h-4 after:rounded-full after:shadow-sm after:transition-transform after:duration-200 peer-checked:after:translate-x-4"},null,-1)),t("span",Je,[e[38]||(e[38]=t("i",{class:"fas fa-redo-alt text-xs text-gray-500"},null,-1)),e[39]||(e[39]=t("span",null,"自动刷新",-1)),i.value?(R(),_("span",{key:0,class:G(["ml-1 text-xs text-blue-600 font-mono transition-opacity",r.value>0?"opacity-100":"opacity-0"])},y(r.value)+"s ",3)):H("",!0)])])]),t("button",{disabled:p.value,class:"px-3 py-1 rounded-md text-sm font-medium transition-colors bg-white text-blue-600 shadow-sm hover:bg-gray-50 border border-gray-300 flex items-center gap-1 sm:gap-2 disabled:opacity-50 disabled:cursor-not-allowed",title:"立即刷新数据",onClick:e[4]||(e[4]=g=>B())},[t("i",{class:G(["fas fa-sync-alt text-xs",{"animate-spin":p.value}])},null,2),t("span",ts,y(p.value?"刷新中":"刷新"),1)],8,Xe)])])]),t("div",es,[t("div",ss,[e[42]||(e[42]=t("h4",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-4"}," Token使用分布 ",-1)),t("div",as,[t("canvas",{ref_key:"modelUsageChart",ref:et},null,512)])]),t("div",os,[e[45]||(e[45]=t("h4",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-4"}," 详细统计数据 ",-1)),o(q).length===0?(R(),_("div",ns,e[43]||(e[43]=[t("p",{class:"text-gray-500 text-sm sm:text-base"}," 暂无模型使用数据 ",-1)]))):(R(),_("div",ls,[t("table",rs,[e[44]||(e[44]=t("thead",{class:"bg-gray-50 sticky top-0"},[t("tr",null,[t("th",{class:"px-2 sm:px-4 py-2 text-left text-xs font-medium text-gray-700"}," 模型 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700 hidden sm:table-cell"}," 请求数 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700"}," 总Token "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700"}," 费用 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700 hidden sm:table-cell"}," 占比 ")])],-1)),t("tbody",is,[(R(!0),_(bt,null,kt(o(q),g=>(R(),_("tr",{key:g.model,class:"hover:bg-gray-50"},[t("td",ds,[t("span",{class:"block truncate max-w-[100px] sm:max-w-none",title:g.model},y(g.model),9,us)]),t("td",cs,y(c(g.requests)),1),t("td",ms,y(c(g.allTokens)),1),t("td",ps,y(g.formatted?g.formatted.total:"$0.000000"),1),t("td",ys,[t("span",fs,y($(g.allTokens,o(q)))+"% ",1)])]))),128))])])]))])])]),t("div",gs,[t("div",xs,[t("div",vs,[t("canvas",{ref_key:"usageTrendChart",ref:N},null,512)])])]),t("div",hs,[t("div",bs,[t("div",ks,[e[48]||(e[48]=t("h3",{class:"text-base sm:text-lg font-semibold text-gray-900"}," API Keys 使用趋势 ",-1)),t("div",Ts,[t("button",{class:G(["px-2 sm:px-3 py-1 rounded-md text-xs sm:text-sm font-medium transition-colors",o(F)==="requests"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[5]||(e[5]=g=>{F.value="requests",O()})},e[46]||(e[46]=[t("i",{class:"fas fa-exchange-alt mr-1"},null,-1),t("span",{class:"hidden sm:inline"},"请求次数",-1),t("span",{class:"sm:hidden"},"请求",-1)]),2),t("button",{class:G(["px-2 sm:px-3 py-1 rounded-md text-xs sm:text-sm font-medium transition-colors",o(F)==="tokens"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[6]||(e[6]=g=>{F.value="tokens",O()})},e[47]||(e[47]=[t("i",{class:"fas fa-coins mr-1"},null,-1),t("span",{class:"hidden sm:inline"},"Token 数量",-1),t("span",{class:"sm:hidden"},"Token",-1)]),2)])]),t("div",Ds,[o(U).totalApiKeys>10?(R(),_("span",Cs," 共 "+y(o(U).totalApiKeys)+" 个 API Key,显示使用量前 10 个 ",1)):(R(),_("span",ws," 共 "+y(o(U).totalApiKeys)+" 个 API Key ",1))]),t("div",_s,[t("canvas",{ref_key:"apiKeysUsageTrendChart",ref:Q},null,512)])])])])}}},Ks=It(Ss,[["__scopeId","data-v-a1b368e2"]]);export{Ks as default};
diff --git a/web/admin-spa/dist/assets/LoginView-BccX9MEv.js b/web/admin-spa/dist/assets/LoginView-BkyYshFQ.js
similarity index 98%
rename from web/admin-spa/dist/assets/LoginView-BccX9MEv.js
rename to web/admin-spa/dist/assets/LoginView-BkyYshFQ.js
index 31fcc649..0ac3b327 100644
--- a/web/admin-spa/dist/assets/LoginView-BccX9MEv.js
+++ b/web/admin-spa/dist/assets/LoginView-BkyYshFQ.js
@@ -1 +1 @@
-import{c as x,r as b,q as f,x as a,z as t,L as i,Q as y,u as o,P as d,Y as w,K as u,aq as c,O as p,y as n}from"./vue-vendor-CKToUHZx.js";import{_,u as v}from"./index-D3bIJLrk.js";/* empty css */import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const h={class:"flex items-center justify-center min-h-screen p-4 sm:p-6"},k={class:"glass-strong rounded-xl sm:rounded-2xl md:rounded-3xl p-6 sm:p-8 md:p-10 w-full max-w-md shadow-2xl"},L={class:"text-center mb-6 sm:mb-8"},S={class:"w-16 h-16 sm:w-20 sm:h-20 mx-auto mb-4 sm:mb-6 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl sm:rounded-2xl flex items-center justify-center backdrop-blur-sm overflow-hidden"},V=["src"],I={key:1,class:"fas fa-cloud text-2xl sm:text-3xl text-gray-700"},N={key:1,class:"w-10 h-10 sm:w-12 sm:h-12 bg-gray-300/50 rounded animate-pulse"},q={key:0,class:"text-2xl sm:text-3xl font-bold text-white mb-2 header-title"},D={key:1,class:"h-8 sm:h-9 w-48 sm:w-64 bg-gray-300/50 rounded animate-pulse mx-auto mb-2"},E=["disabled"],j={key:0,class:"fas fa-sign-in-alt mr-2"},B={key:1,class:"loading-spinner mr-2"},M={key:0,class:"mt-4 sm:mt-6 p-3 sm:p-4 bg-red-500/20 border border-red-500/30 rounded-lg sm:rounded-xl text-red-800 text-xs sm:text-sm text-center backdrop-blur-sm"},F={__name:"LoginView",setup(O){const e=v(),m=x(()=>e.oemLoading),l=b({username:"",password:""});f(()=>{e.loadOemSettings()});const g=async()=>{await e.login(l.value)};return(T,s)=>(n(),a("div",h,[t("div",k,[t("div",L,[t("div",S,[m.value?(n(),a("div",N)):(n(),a(y,{key:0},[o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon?(n(),a("img",{key:0,src:o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon,alt:"Logo",class:"w-10 h-10 sm:w-12 sm:h-12 object-contain",onError:s[0]||(s[0]=r=>r.target.style.display="none")},null,40,V)):(n(),a("i",I))],64))]),!m.value&&o(e).oemSettings.siteName?(n(),a("h1",q,d(o(e).oemSettings.siteName),1)):m.value?(n(),a("div",D)):i("",!0),s[3]||(s[3]=t("p",{class:"text-gray-600 text-base sm:text-lg"}," 管理后台 ",-1))]),t("form",{class:"space-y-4 sm:space-y-6",onSubmit:w(g,["prevent"])},[t("div",null,[s[4]||(s[4]=t("label",{class:"block text-sm font-semibold text-gray-900 mb-2 sm:mb-3"},"用户名",-1)),u(t("input",{"onUpdate:modelValue":s[1]||(s[1]=r=>l.value.username=r),type:"text",required:"",class:"form-input w-full",placeholder:"请输入用户名"},null,512),[[c,l.value.username]])]),t("div",null,[s[5]||(s[5]=t("label",{class:"block text-sm font-semibold text-gray-900 mb-2 sm:mb-3"},"密码",-1)),u(t("input",{"onUpdate:modelValue":s[2]||(s[2]=r=>l.value.password=r),type:"password",required:"",class:"form-input w-full",placeholder:"请输入密码"},null,512),[[c,l.value.password]])]),t("button",{type:"submit",disabled:o(e).loginLoading,class:"btn btn-primary w-full py-3 sm:py-4 px-4 sm:px-6 text-base sm:text-lg font-semibold"},[o(e).loginLoading?i("",!0):(n(),a("i",j)),o(e).loginLoading?(n(),a("div",B)):i("",!0),p(" "+d(o(e).loginLoading?"登录中...":"登录"),1)],8,E)],32),o(e).loginError?(n(),a("div",M,[s[6]||(s[6]=t("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),p(d(o(e).loginError),1)])):i("",!0)])]))}},P=_(F,[["__scopeId","data-v-d68c64ae"]]);export{P as default};
+import{c as x,r as b,q as f,x as a,z as t,L as i,Q as y,u as o,P as d,Y as w,K as u,aq as c,O as p,y as n}from"./vue-vendor-CKToUHZx.js";import{_,u as v}from"./index-D1PUfDNP.js";/* empty css */import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const h={class:"flex items-center justify-center min-h-screen p-4 sm:p-6"},k={class:"glass-strong rounded-xl sm:rounded-2xl md:rounded-3xl p-6 sm:p-8 md:p-10 w-full max-w-md shadow-2xl"},L={class:"text-center mb-6 sm:mb-8"},S={class:"w-16 h-16 sm:w-20 sm:h-20 mx-auto mb-4 sm:mb-6 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl sm:rounded-2xl flex items-center justify-center backdrop-blur-sm overflow-hidden"},V=["src"],I={key:1,class:"fas fa-cloud text-2xl sm:text-3xl text-gray-700"},N={key:1,class:"w-10 h-10 sm:w-12 sm:h-12 bg-gray-300/50 rounded animate-pulse"},q={key:0,class:"text-2xl sm:text-3xl font-bold text-white mb-2 header-title"},D={key:1,class:"h-8 sm:h-9 w-48 sm:w-64 bg-gray-300/50 rounded animate-pulse mx-auto mb-2"},E=["disabled"],j={key:0,class:"fas fa-sign-in-alt mr-2"},B={key:1,class:"loading-spinner mr-2"},M={key:0,class:"mt-4 sm:mt-6 p-3 sm:p-4 bg-red-500/20 border border-red-500/30 rounded-lg sm:rounded-xl text-red-800 text-xs sm:text-sm text-center backdrop-blur-sm"},F={__name:"LoginView",setup(O){const e=v(),m=x(()=>e.oemLoading),l=b({username:"",password:""});f(()=>{e.loadOemSettings()});const g=async()=>{await e.login(l.value)};return(T,s)=>(n(),a("div",h,[t("div",k,[t("div",L,[t("div",S,[m.value?(n(),a("div",N)):(n(),a(y,{key:0},[o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon?(n(),a("img",{key:0,src:o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon,alt:"Logo",class:"w-10 h-10 sm:w-12 sm:h-12 object-contain",onError:s[0]||(s[0]=r=>r.target.style.display="none")},null,40,V)):(n(),a("i",I))],64))]),!m.value&&o(e).oemSettings.siteName?(n(),a("h1",q,d(o(e).oemSettings.siteName),1)):m.value?(n(),a("div",D)):i("",!0),s[3]||(s[3]=t("p",{class:"text-gray-600 text-base sm:text-lg"}," 管理后台 ",-1))]),t("form",{class:"space-y-4 sm:space-y-6",onSubmit:w(g,["prevent"])},[t("div",null,[s[4]||(s[4]=t("label",{class:"block text-sm font-semibold text-gray-900 mb-2 sm:mb-3"},"用户名",-1)),u(t("input",{"onUpdate:modelValue":s[1]||(s[1]=r=>l.value.username=r),type:"text",required:"",class:"form-input w-full",placeholder:"请输入用户名"},null,512),[[c,l.value.username]])]),t("div",null,[s[5]||(s[5]=t("label",{class:"block text-sm font-semibold text-gray-900 mb-2 sm:mb-3"},"密码",-1)),u(t("input",{"onUpdate:modelValue":s[2]||(s[2]=r=>l.value.password=r),type:"password",required:"",class:"form-input w-full",placeholder:"请输入密码"},null,512),[[c,l.value.password]])]),t("button",{type:"submit",disabled:o(e).loginLoading,class:"btn btn-primary w-full py-3 sm:py-4 px-4 sm:px-6 text-base sm:text-lg font-semibold"},[o(e).loginLoading?i("",!0):(n(),a("i",j)),o(e).loginLoading?(n(),a("div",B)):i("",!0),p(" "+d(o(e).loginLoading?"登录中...":"登录"),1)],8,E)],32),o(e).loginError?(n(),a("div",M,[s[6]||(s[6]=t("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),p(d(o(e).loginError),1)])):i("",!0)])]))}},P=_(F,[["__scopeId","data-v-d68c64ae"]]);export{P as default};
diff --git a/web/admin-spa/dist/assets/LogoTitle-BIy_PC38.js b/web/admin-spa/dist/assets/LogoTitle-CCr5FYLm.js
similarity index 96%
rename from web/admin-spa/dist/assets/LogoTitle-BIy_PC38.js
rename to web/admin-spa/dist/assets/LogoTitle-CCr5FYLm.js
index 146499fb..a7634449 100644
--- a/web/admin-spa/dist/assets/LogoTitle-BIy_PC38.js
+++ b/web/admin-spa/dist/assets/LogoTitle-CCr5FYLm.js
@@ -1 +1 @@
-/* empty css */import{_ as r}from"./index-D3bIJLrk.js";import{x as t,y as s,z as o,Q as d,L as a,A as c,C as g,P as i}from"./vue-vendor-CKToUHZx.js";const u={class:"flex items-center gap-4"},f={class:"w-12 h-12 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl flex items-center justify-center backdrop-blur-sm flex-shrink-0 overflow-hidden"},y=["src"],m={key:1,class:"fas fa-cloud text-xl text-gray-700"},h={key:1,class:"w-8 h-8 bg-gray-300/50 rounded animate-pulse"},x={class:"flex flex-col justify-center min-h-[48px]"},b={class:"flex items-center gap-3"},k={key:1,class:"h-8 w-64 bg-gray-300/50 rounded animate-pulse"},_={key:0,class:"text-gray-600 text-sm leading-tight mt-0.5"},S={__name:"LogoTitle",props:{loading:{type:Boolean,default:!1},title:{type:String,default:""},subtitle:{type:String,default:""},logoSrc:{type:String,default:""},titleClass:{type:String,default:"text-gray-900"}},setup(e){const n=l=>{l.target.style.display="none"};return(l,p)=>(s(),t("div",u,[o("div",f,[e.loading?(s(),t("div",h)):(s(),t(d,{key:0},[e.logoSrc?(s(),t("img",{key:0,src:e.logoSrc,alt:"Logo",class:"w-8 h-8 object-contain",onError:n},null,40,y)):(s(),t("i",m))],64))]),o("div",x,[o("div",b,[!e.loading&&e.title?(s(),t("h1",{key:0,class:g(["text-2xl font-bold header-title leading-tight",e.titleClass])},i(e.title),3)):e.loading?(s(),t("div",k)):a("",!0),c(l.$slots,"after-title",{},void 0,!0)]),e.subtitle?(s(),t("p",_,i(e.subtitle),1)):a("",!0)])]))}},C=r(S,[["__scopeId","data-v-718feedc"]]);export{C as L};
+/* empty css */import{_ as r}from"./index-D1PUfDNP.js";import{x as t,y as s,z as o,Q as d,L as a,A as c,C as g,P as i}from"./vue-vendor-CKToUHZx.js";const u={class:"flex items-center gap-4"},f={class:"w-12 h-12 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl flex items-center justify-center backdrop-blur-sm flex-shrink-0 overflow-hidden"},y=["src"],m={key:1,class:"fas fa-cloud text-xl text-gray-700"},h={key:1,class:"w-8 h-8 bg-gray-300/50 rounded animate-pulse"},x={class:"flex flex-col justify-center min-h-[48px]"},b={class:"flex items-center gap-3"},k={key:1,class:"h-8 w-64 bg-gray-300/50 rounded animate-pulse"},_={key:0,class:"text-gray-600 text-sm leading-tight mt-0.5"},S={__name:"LogoTitle",props:{loading:{type:Boolean,default:!1},title:{type:String,default:""},subtitle:{type:String,default:""},logoSrc:{type:String,default:""},titleClass:{type:String,default:"text-gray-900"}},setup(e){const n=l=>{l.target.style.display="none"};return(l,p)=>(s(),t("div",u,[o("div",f,[e.loading?(s(),t("div",h)):(s(),t(d,{key:0},[e.logoSrc?(s(),t("img",{key:0,src:e.logoSrc,alt:"Logo",class:"w-8 h-8 object-contain",onError:n},null,40,y)):(s(),t("i",m))],64))]),o("div",x,[o("div",b,[!e.loading&&e.title?(s(),t("h1",{key:0,class:g(["text-2xl font-bold header-title leading-tight",e.titleClass])},i(e.title),3)):e.loading?(s(),t("div",k)):a("",!0),c(l.$slots,"after-title",{},void 0,!0)]),e.subtitle?(s(),t("p",_,i(e.subtitle),1)):a("",!0)])]))}},C=r(S,[["__scopeId","data-v-718feedc"]]);export{C as L};
diff --git a/web/admin-spa/dist/assets/MainLayout-VM3pfyce.js b/web/admin-spa/dist/assets/MainLayout-B_VPCr7N.js
similarity index 99%
rename from web/admin-spa/dist/assets/MainLayout-VM3pfyce.js
rename to web/admin-spa/dist/assets/MainLayout-B_VPCr7N.js
index 0f1d18a5..7c04d2c7 100644
--- a/web/admin-spa/dist/assets/MainLayout-VM3pfyce.js
+++ b/web/admin-spa/dist/assets/MainLayout-B_VPCr7N.js
@@ -1 +1 @@
-import{c as $,r as h,_ as E,q as R,V as F,x as l,y as o,z as e,L as M,R as y,J as C,P as p,C as T,Y as S,O as v,T as q,K as _,aq as U,Q as N,aT as z,ac as A,o as J,av as H,aU as Q,I as j,aV as Y,M as G}from"./vue-vendor-CKToUHZx.js";import{_ as V,u as W,a as D}from"./index-D3bIJLrk.js";import{s as b}from"./toast-BvwA7Mwb.js";import{L as X}from"./LogoTitle-BIy_PC38.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";/* empty css */const Z={class:"glass-strong rounded-xl sm:rounded-2xl md:rounded-3xl p-3 sm:p-4 md:p-6 mb-4 sm:mb-6 md:mb-8 shadow-xl",style:{"z-index":"10",position:"relative"}},ee={class:"flex flex-col sm:flex-row justify-between items-center gap-3 sm:gap-4"},se={class:"flex items-center gap-2 sm:gap-3 md:gap-4 w-full sm:w-auto justify-center sm:justify-start"},te={class:"flex items-center gap-1 sm:gap-2"},ae={class:"text-xs sm:text-sm text-gray-400 font-mono"},ne=["href"],oe={class:"relative user-menu-container"},le={class:"hidden sm:inline"},re={class:"px-4 py-3 border-b border-gray-100"},ie={class:"flex items-center justify-between text-sm"},de={class:"font-mono text-gray-700"},ue={key:0,class:"mt-2"},ce={class:"flex items-center justify-between text-sm mb-2"},me={class:"font-mono text-green-600"},pe=["href"],fe={key:1,class:"mt-2 text-center text-xs text-gray-500"},xe={key:2,class:"mt-2 text-center"},ge={key:"message",class:"px-3 py-1.5 bg-green-100 border border-green-200 rounded-lg inline-block"},ve={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},be={class:"modal-content w-full max-w-md p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] flex flex-col"},ye=["value"],he={class:"flex gap-3 pt-4"},we=["disabled"],ke={key:0,class:"loading-spinner mr-2"},_e={key:1,class:"fas fa-save mr-2"},Ue={__name:"AppHeader",setup(w){const f=z(),u=W(),c=$(()=>u.user||{username:"Admin"}),a=$(()=>u.oemSettings||{}),k=$(()=>u.oemLoading),t=h({current:"...",latest:"",hasUpdate:!1,checkingUpdate:!1,lastChecked:null,releaseInfo:null,noUpdateMessage:!1}),r=h(!1),x=h(!1),g=h(!1),n=E({currentPassword:"",newPassword:"",confirmPassword:"",newUsername:""}),P=async()=>{if(!t.value.checkingUpdate){t.value.checkingUpdate=!0;try{const d=await D.get("/admin/check-updates");if(d.success){const s=d.data;t.value.current=s.current,t.value.latest=s.latest,t.value.hasUpdate=s.hasUpdate,t.value.releaseInfo=s.releaseInfo,t.value.lastChecked=new Date,localStorage.setItem("versionInfo",JSON.stringify({current:s.current,latest:s.latest,lastChecked:t.value.lastChecked,hasUpdate:s.hasUpdate,releaseInfo:s.releaseInfo})),s.hasUpdate||(t.value.noUpdateMessage=!0,setTimeout(()=>{t.value.noUpdateMessage=!1},3e3))}}catch(d){console.error("Error checking for updates:",d);const s=localStorage.getItem("versionInfo");if(s){const m=JSON.parse(s);t.value.current=m.current||t.value.current,t.value.latest=m.latest,t.value.hasUpdate=m.hasUpdate,t.value.releaseInfo=m.releaseInfo,t.value.lastChecked=new Date(m.lastChecked)}}finally{t.value.checkingUpdate=!1}}},B=()=>{n.currentPassword="",n.newPassword="",n.confirmPassword="",n.newUsername="",x.value=!0,r.value=!1},I=()=>{x.value=!1},K=async()=>{if(n.newPassword!==n.confirmPassword){b("两次输入的密码不一致","error");return}if(n.newPassword.length<8){b("新密码长度至少8位","error");return}g.value=!0;try{const d=await D.post("/admin/change-password",{currentPassword:n.currentPassword,newPassword:n.newPassword,newUsername:n.newUsername||void 0});if(d.success){const s=n.newUsername?"账户信息修改成功,请重新登录":"密码修改成功,请重新登录";b(s,"success"),I(),setTimeout(()=>{u.logout(),f.push("/login")},1500)}else b(d.message||"修改失败","error")}catch{b("修改密码失败","error")}finally{g.value=!1}},O=()=>{confirm("确定要退出登录吗?")&&(u.logout(),f.push("/login"),b("已安全退出","success")),r.value=!1},L=d=>{!d.target.closest(".user-menu-container")&&r.value&&(r.value=!1)};return R(()=>{P(),setInterval(()=>{P()},36e5),document.addEventListener("click",L)}),F(()=>{document.removeEventListener("click",L)}),(d,s)=>{var m;return o(),l(N,null,[e("div",Z,[e("div",ee,[e("div",se,[y(X,{loading:k.value,title:a.value.siteName,subtitle:"管理后台","logo-src":a.value.siteIconData||a.value.siteIcon,"title-class":"text-white"},{"after-title":C(()=>{var i;return[e("div",te,[e("span",ae,"v"+p(t.value.current||"..."),1),t.value.hasUpdate?(o(),l("a",{key:0,href:((i=t.value.releaseInfo)==null?void 0:i.htmlUrl)||"#",target:"_blank",class:"inline-flex items-center gap-1 px-2 py-0.5 bg-green-500 border border-green-600 rounded-full text-xs text-white hover:bg-green-600 transition-colors animate-pulse",title:"有新版本可用"},s[7]||(s[7]=[e("i",{class:"fas fa-arrow-up text-[10px]"},null,-1),e("span",null,"新版本",-1)]),8,ne)):M("",!0)])]}),_:1},8,["loading","title","logo-src"])]),e("div",oe,[e("button",{class:"btn btn-primary px-3 sm:px-4 py-2 sm:py-3 flex items-center gap-1 sm:gap-2 relative text-sm sm:text-base",onClick:s[0]||(s[0]=i=>r.value=!r.value)},[s[8]||(s[8]=e("i",{class:"fas fa-user-circle"},null,-1)),e("span",le,p(c.value.username||"Admin"),1),e("i",{class:T(["fas fa-chevron-down text-xs transition-transform duration-200",{"rotate-180":r.value}])},null,2)]),r.value?(o(),l("div",{key:0,class:"absolute right-0 top-full mt-2 w-48 sm:w-56 bg-white rounded-xl shadow-xl border border-gray-200 py-2 user-menu-dropdown",style:{"z-index":"999999"},onClick:s[2]||(s[2]=S(()=>{},["stop"]))},[e("div",re,[e("div",ie,[s[9]||(s[9]=e("span",{class:"text-gray-500"},"当前版本",-1)),e("span",de,"v"+p(t.value.current||"..."),1)]),t.value.hasUpdate?(o(),l("div",ue,[e("div",ce,[s[10]||(s[10]=e("span",{class:"text-green-600 font-medium"},[e("i",{class:"fas fa-arrow-up mr-1"}),v("有新版本 ")],-1)),e("span",me,"v"+p(t.value.latest),1)]),e("a",{href:((m=t.value.releaseInfo)==null?void 0:m.htmlUrl)||"#",target:"_blank",class:"block w-full text-center px-3 py-1.5 bg-green-500 text-white text-sm rounded-lg hover:bg-green-600 transition-colors"},s[11]||(s[11]=[e("i",{class:"fas fa-external-link-alt mr-1"},null,-1),v("查看更新 ",-1)]),8,pe)])):t.value.checkingUpdate?(o(),l("div",fe,s[12]||(s[12]=[e("i",{class:"fas fa-spinner fa-spin mr-1"},null,-1),v("检查更新中... ",-1)]))):(o(),l("div",xe,[y(q,{name:"fade",mode:"out-in"},{default:C(()=>[t.value.noUpdateMessage?(o(),l("div",ge,s[13]||(s[13]=[e("p",{class:"text-xs text-green-700 font-medium"},[e("i",{class:"fas fa-check-circle mr-1"}),v("当前已是最新版本 ")],-1)]))):(o(),l("button",{key:"button",class:"text-xs text-blue-500 hover:text-blue-700 transition-colors",onClick:s[1]||(s[1]=i=>P())},s[14]||(s[14]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),v("检查更新 ",-1)])))]),_:1})]))]),e("button",{class:"w-full px-4 py-3 text-left text-gray-700 hover:bg-gray-50 transition-colors flex items-center gap-3",onClick:B},s[15]||(s[15]=[e("i",{class:"fas fa-key text-blue-500"},null,-1),e("span",null,"修改账户信息",-1)])),s[17]||(s[17]=e("hr",{class:"my-2 border-gray-200"},null,-1)),e("button",{class:"w-full px-4 py-3 text-left text-gray-700 hover:bg-gray-50 transition-colors flex items-center gap-3",onClick:O},s[16]||(s[16]=[e("i",{class:"fas fa-sign-out-alt text-red-500"},null,-1),e("span",null,"退出登录",-1)]))])):M("",!0)])])]),x.value?(o(),l("div",ve,[e("div",be,[e("div",{class:"flex items-center justify-between mb-6"},[s[19]||(s[19]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-key text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 修改账户信息 ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:I},s[18]||(s[18]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("form",{class:"space-y-6 modal-scroll-content custom-scrollbar flex-1",onSubmit:S(K,["prevent"])},[e("div",null,[s[20]||(s[20]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"当前用户名",-1)),e("input",{value:c.value.username||"Admin",type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed"},null,8,ye),s[21]||(s[21]=e("p",{class:"text-xs text-gray-500 mt-2"}," 当前用户名,输入新用户名以修改 ",-1))]),e("div",null,[s[22]||(s[22]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新用户名",-1)),_(e("input",{"onUpdate:modelValue":s[3]||(s[3]=i=>n.newUsername=i),type:"text",class:"form-input w-full",placeholder:"输入新用户名(留空保持不变)"},null,512),[[U,n.newUsername]]),s[23]||(s[23]=e("p",{class:"text-xs text-gray-500 mt-2"}," 留空表示不修改用户名 ",-1))]),e("div",null,[s[24]||(s[24]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"当前密码",-1)),_(e("input",{"onUpdate:modelValue":s[4]||(s[4]=i=>n.currentPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请输入当前密码"},null,512),[[U,n.currentPassword]])]),e("div",null,[s[25]||(s[25]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新密码",-1)),_(e("input",{"onUpdate:modelValue":s[5]||(s[5]=i=>n.newPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请输入新密码"},null,512),[[U,n.newPassword]]),s[26]||(s[26]=e("p",{class:"text-xs text-gray-500 mt-2"}," 密码长度至少8位 ",-1))]),e("div",null,[s[27]||(s[27]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"确认新密码",-1)),_(e("input",{"onUpdate:modelValue":s[6]||(s[6]=i=>n.confirmPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请再次输入新密码"},null,512),[[U,n.confirmPassword]])]),e("div",he,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:I}," 取消 "),e("button",{type:"submit",disabled:g.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[g.value?(o(),l("div",ke)):(o(),l("i",_e)),v(" "+p(g.value?"保存中...":"保存修改"),1)],8,we)])],32)])])):M("",!0)],64)}}},Ce=V(Ue,[["__scopeId","data-v-9c585a16"]]),Pe={class:"mb-4 sm:mb-6"},Ie={class:"block sm:hidden bg-white/10 rounded-xl p-2 backdrop-blur-sm"},$e=["value"],Me=["value"],Te={class:"hidden sm:flex flex-wrap gap-2 bg-white/10 rounded-2xl p-2 backdrop-blur-sm"},Ne=["onClick"],Ve={class:"hidden md:inline"},Le={class:"md:hidden"},Se={__name:"TabBar",props:{activeTab:{type:String,required:!0}},emits:["tab-change"],setup(w){const f=[{key:"dashboard",name:"仪表板",shortName:"仪表板",icon:"fas fa-tachometer-alt"},{key:"apiKeys",name:"API Keys",shortName:"API",icon:"fas fa-key"},{key:"accounts",name:"账户管理",shortName:"账户",icon:"fas fa-user-circle"},{key:"tutorial",name:"使用教程",shortName:"教程",icon:"fas fa-graduation-cap"},{key:"settings",name:"其他设置",shortName:"设置",icon:"fas fa-cogs"}];return(u,c)=>(o(),l("div",Pe,[e("div",Ie,[e("select",{value:w.activeTab,class:"w-full px-4 py-3 bg-white/90 rounded-lg text-gray-700 font-semibold focus:outline-none focus:ring-2 focus:ring-primary-color",onChange:c[0]||(c[0]=a=>u.$emit("tab-change",a.target.value))},[(o(),l(N,null,A(f,a=>e("option",{key:a.key,value:a.key},p(a.name),9,Me)),64))],40,$e)]),e("div",Te,[(o(),l(N,null,A(f,a=>e("button",{key:a.key,class:T(["tab-btn flex-1 py-2 sm:py-3 px-3 sm:px-4 md:px-6 text-xs sm:text-sm font-semibold transition-all duration-300",w.activeTab===a.key?"active":"text-gray-700 hover:bg-white/10 hover:text-gray-900"]),onClick:k=>u.$emit("tab-change",a.key)},[e("i",{class:T(a.icon+" mr-1 sm:mr-2")},null,2),e("span",Ve,p(a.name),1),e("span",Le,p(a.shortName||a.name),1)],10,Ne)),64))])]))}},Ae=V(Se,[["__scopeId","data-v-4c6ce4e1"]]),je={class:"min-h-screen p-3 sm:p-4 md:p-6"},De={class:"glass-strong rounded-xl sm:rounded-2xl md:rounded-3xl p-3 sm:p-4 md:p-6 shadow-xl",style:{"z-index":"1","min-height":"calc(100vh - 120px)"}},qe={class:"tab-content"},ze={__name:"MainLayout",setup(w){const f=Q(),u=z(),c=h("dashboard"),a={dashboard:"/dashboard",apiKeys:"/api-keys",accounts:"/accounts",tutorial:"/tutorial",settings:"/settings"};J(()=>f.path,t=>{const r=Object.keys(a).find(x=>a[x]===t);r&&(c.value=r)},{immediate:!0});const k=t=>{c.value=t,u.push(a[t])};return(t,r)=>{const x=H("router-view");return o(),l("div",je,[y(Ce),e("div",De,[y(Ae,{"active-tab":c.value,onTabChange:k},null,8,["active-tab"]),e("div",qe,[y(x,null,{default:C(({Component:g})=>[y(q,{name:"slide-up",mode:"out-in"},{default:C(()=>[(o(),j(Y,{include:["DashboardView","ApiKeysView"]},[(o(),j(G(g)))],1024))]),_:2},1024)]),_:1})])])])}}},He=V(ze,[["__scopeId","data-v-d57a6347"]]);export{He as default};
+import{c as $,r as h,_ as E,q as R,V as F,x as l,y as o,z as e,L as M,R as y,J as C,P as p,C as T,Y as S,O as v,T as q,K as _,aq as U,Q as N,aT as z,ac as A,o as J,av as H,aU as Q,I as j,aV as Y,M as G}from"./vue-vendor-CKToUHZx.js";import{_ as V,u as W,a as D}from"./index-D1PUfDNP.js";import{s as b}from"./toast-BvwA7Mwb.js";import{L as X}from"./LogoTitle-CCr5FYLm.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";/* empty css */const Z={class:"glass-strong rounded-xl sm:rounded-2xl md:rounded-3xl p-3 sm:p-4 md:p-6 mb-4 sm:mb-6 md:mb-8 shadow-xl",style:{"z-index":"10",position:"relative"}},ee={class:"flex flex-col sm:flex-row justify-between items-center gap-3 sm:gap-4"},se={class:"flex items-center gap-2 sm:gap-3 md:gap-4 w-full sm:w-auto justify-center sm:justify-start"},te={class:"flex items-center gap-1 sm:gap-2"},ae={class:"text-xs sm:text-sm text-gray-400 font-mono"},ne=["href"],oe={class:"relative user-menu-container"},le={class:"hidden sm:inline"},re={class:"px-4 py-3 border-b border-gray-100"},ie={class:"flex items-center justify-between text-sm"},de={class:"font-mono text-gray-700"},ue={key:0,class:"mt-2"},ce={class:"flex items-center justify-between text-sm mb-2"},me={class:"font-mono text-green-600"},pe=["href"],fe={key:1,class:"mt-2 text-center text-xs text-gray-500"},xe={key:2,class:"mt-2 text-center"},ge={key:"message",class:"px-3 py-1.5 bg-green-100 border border-green-200 rounded-lg inline-block"},ve={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-3 sm:p-4"},be={class:"modal-content w-full max-w-md p-4 sm:p-6 md:p-8 mx-auto max-h-[90vh] flex flex-col"},ye=["value"],he={class:"flex gap-3 pt-4"},we=["disabled"],ke={key:0,class:"loading-spinner mr-2"},_e={key:1,class:"fas fa-save mr-2"},Ue={__name:"AppHeader",setup(w){const f=z(),u=W(),c=$(()=>u.user||{username:"Admin"}),a=$(()=>u.oemSettings||{}),k=$(()=>u.oemLoading),t=h({current:"...",latest:"",hasUpdate:!1,checkingUpdate:!1,lastChecked:null,releaseInfo:null,noUpdateMessage:!1}),r=h(!1),x=h(!1),g=h(!1),n=E({currentPassword:"",newPassword:"",confirmPassword:"",newUsername:""}),P=async()=>{if(!t.value.checkingUpdate){t.value.checkingUpdate=!0;try{const d=await D.get("/admin/check-updates");if(d.success){const s=d.data;t.value.current=s.current,t.value.latest=s.latest,t.value.hasUpdate=s.hasUpdate,t.value.releaseInfo=s.releaseInfo,t.value.lastChecked=new Date,localStorage.setItem("versionInfo",JSON.stringify({current:s.current,latest:s.latest,lastChecked:t.value.lastChecked,hasUpdate:s.hasUpdate,releaseInfo:s.releaseInfo})),s.hasUpdate||(t.value.noUpdateMessage=!0,setTimeout(()=>{t.value.noUpdateMessage=!1},3e3))}}catch(d){console.error("Error checking for updates:",d);const s=localStorage.getItem("versionInfo");if(s){const m=JSON.parse(s);t.value.current=m.current||t.value.current,t.value.latest=m.latest,t.value.hasUpdate=m.hasUpdate,t.value.releaseInfo=m.releaseInfo,t.value.lastChecked=new Date(m.lastChecked)}}finally{t.value.checkingUpdate=!1}}},B=()=>{n.currentPassword="",n.newPassword="",n.confirmPassword="",n.newUsername="",x.value=!0,r.value=!1},I=()=>{x.value=!1},K=async()=>{if(n.newPassword!==n.confirmPassword){b("两次输入的密码不一致","error");return}if(n.newPassword.length<8){b("新密码长度至少8位","error");return}g.value=!0;try{const d=await D.post("/admin/change-password",{currentPassword:n.currentPassword,newPassword:n.newPassword,newUsername:n.newUsername||void 0});if(d.success){const s=n.newUsername?"账户信息修改成功,请重新登录":"密码修改成功,请重新登录";b(s,"success"),I(),setTimeout(()=>{u.logout(),f.push("/login")},1500)}else b(d.message||"修改失败","error")}catch{b("修改密码失败","error")}finally{g.value=!1}},O=()=>{confirm("确定要退出登录吗?")&&(u.logout(),f.push("/login"),b("已安全退出","success")),r.value=!1},L=d=>{!d.target.closest(".user-menu-container")&&r.value&&(r.value=!1)};return R(()=>{P(),setInterval(()=>{P()},36e5),document.addEventListener("click",L)}),F(()=>{document.removeEventListener("click",L)}),(d,s)=>{var m;return o(),l(N,null,[e("div",Z,[e("div",ee,[e("div",se,[y(X,{loading:k.value,title:a.value.siteName,subtitle:"管理后台","logo-src":a.value.siteIconData||a.value.siteIcon,"title-class":"text-white"},{"after-title":C(()=>{var i;return[e("div",te,[e("span",ae,"v"+p(t.value.current||"..."),1),t.value.hasUpdate?(o(),l("a",{key:0,href:((i=t.value.releaseInfo)==null?void 0:i.htmlUrl)||"#",target:"_blank",class:"inline-flex items-center gap-1 px-2 py-0.5 bg-green-500 border border-green-600 rounded-full text-xs text-white hover:bg-green-600 transition-colors animate-pulse",title:"有新版本可用"},s[7]||(s[7]=[e("i",{class:"fas fa-arrow-up text-[10px]"},null,-1),e("span",null,"新版本",-1)]),8,ne)):M("",!0)])]}),_:1},8,["loading","title","logo-src"])]),e("div",oe,[e("button",{class:"btn btn-primary px-3 sm:px-4 py-2 sm:py-3 flex items-center gap-1 sm:gap-2 relative text-sm sm:text-base",onClick:s[0]||(s[0]=i=>r.value=!r.value)},[s[8]||(s[8]=e("i",{class:"fas fa-user-circle"},null,-1)),e("span",le,p(c.value.username||"Admin"),1),e("i",{class:T(["fas fa-chevron-down text-xs transition-transform duration-200",{"rotate-180":r.value}])},null,2)]),r.value?(o(),l("div",{key:0,class:"absolute right-0 top-full mt-2 w-48 sm:w-56 bg-white rounded-xl shadow-xl border border-gray-200 py-2 user-menu-dropdown",style:{"z-index":"999999"},onClick:s[2]||(s[2]=S(()=>{},["stop"]))},[e("div",re,[e("div",ie,[s[9]||(s[9]=e("span",{class:"text-gray-500"},"当前版本",-1)),e("span",de,"v"+p(t.value.current||"..."),1)]),t.value.hasUpdate?(o(),l("div",ue,[e("div",ce,[s[10]||(s[10]=e("span",{class:"text-green-600 font-medium"},[e("i",{class:"fas fa-arrow-up mr-1"}),v("有新版本 ")],-1)),e("span",me,"v"+p(t.value.latest),1)]),e("a",{href:((m=t.value.releaseInfo)==null?void 0:m.htmlUrl)||"#",target:"_blank",class:"block w-full text-center px-3 py-1.5 bg-green-500 text-white text-sm rounded-lg hover:bg-green-600 transition-colors"},s[11]||(s[11]=[e("i",{class:"fas fa-external-link-alt mr-1"},null,-1),v("查看更新 ",-1)]),8,pe)])):t.value.checkingUpdate?(o(),l("div",fe,s[12]||(s[12]=[e("i",{class:"fas fa-spinner fa-spin mr-1"},null,-1),v("检查更新中... ",-1)]))):(o(),l("div",xe,[y(q,{name:"fade",mode:"out-in"},{default:C(()=>[t.value.noUpdateMessage?(o(),l("div",ge,s[13]||(s[13]=[e("p",{class:"text-xs text-green-700 font-medium"},[e("i",{class:"fas fa-check-circle mr-1"}),v("当前已是最新版本 ")],-1)]))):(o(),l("button",{key:"button",class:"text-xs text-blue-500 hover:text-blue-700 transition-colors",onClick:s[1]||(s[1]=i=>P())},s[14]||(s[14]=[e("i",{class:"fas fa-sync-alt mr-1"},null,-1),v("检查更新 ",-1)])))]),_:1})]))]),e("button",{class:"w-full px-4 py-3 text-left text-gray-700 hover:bg-gray-50 transition-colors flex items-center gap-3",onClick:B},s[15]||(s[15]=[e("i",{class:"fas fa-key text-blue-500"},null,-1),e("span",null,"修改账户信息",-1)])),s[17]||(s[17]=e("hr",{class:"my-2 border-gray-200"},null,-1)),e("button",{class:"w-full px-4 py-3 text-left text-gray-700 hover:bg-gray-50 transition-colors flex items-center gap-3",onClick:O},s[16]||(s[16]=[e("i",{class:"fas fa-sign-out-alt text-red-500"},null,-1),e("span",null,"退出登录",-1)]))])):M("",!0)])])]),x.value?(o(),l("div",ve,[e("div",be,[e("div",{class:"flex items-center justify-between mb-6"},[s[19]||(s[19]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[e("i",{class:"fas fa-key text-white"})]),e("h3",{class:"text-xl font-bold text-gray-900"}," 修改账户信息 ")],-1)),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:I},s[18]||(s[18]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),e("form",{class:"space-y-6 modal-scroll-content custom-scrollbar flex-1",onSubmit:S(K,["prevent"])},[e("div",null,[s[20]||(s[20]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"当前用户名",-1)),e("input",{value:c.value.username||"Admin",type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed"},null,8,ye),s[21]||(s[21]=e("p",{class:"text-xs text-gray-500 mt-2"}," 当前用户名,输入新用户名以修改 ",-1))]),e("div",null,[s[22]||(s[22]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新用户名",-1)),_(e("input",{"onUpdate:modelValue":s[3]||(s[3]=i=>n.newUsername=i),type:"text",class:"form-input w-full",placeholder:"输入新用户名(留空保持不变)"},null,512),[[U,n.newUsername]]),s[23]||(s[23]=e("p",{class:"text-xs text-gray-500 mt-2"}," 留空表示不修改用户名 ",-1))]),e("div",null,[s[24]||(s[24]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"当前密码",-1)),_(e("input",{"onUpdate:modelValue":s[4]||(s[4]=i=>n.currentPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请输入当前密码"},null,512),[[U,n.currentPassword]])]),e("div",null,[s[25]||(s[25]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新密码",-1)),_(e("input",{"onUpdate:modelValue":s[5]||(s[5]=i=>n.newPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请输入新密码"},null,512),[[U,n.newPassword]]),s[26]||(s[26]=e("p",{class:"text-xs text-gray-500 mt-2"}," 密码长度至少8位 ",-1))]),e("div",null,[s[27]||(s[27]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"确认新密码",-1)),_(e("input",{"onUpdate:modelValue":s[6]||(s[6]=i=>n.confirmPassword=i),type:"password",required:"",class:"form-input w-full",placeholder:"请再次输入新密码"},null,512),[[U,n.confirmPassword]])]),e("div",he,[e("button",{type:"button",class:"flex-1 px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors",onClick:I}," 取消 "),e("button",{type:"submit",disabled:g.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[g.value?(o(),l("div",ke)):(o(),l("i",_e)),v(" "+p(g.value?"保存中...":"保存修改"),1)],8,we)])],32)])])):M("",!0)],64)}}},Ce=V(Ue,[["__scopeId","data-v-9c585a16"]]),Pe={class:"mb-4 sm:mb-6"},Ie={class:"block sm:hidden bg-white/10 rounded-xl p-2 backdrop-blur-sm"},$e=["value"],Me=["value"],Te={class:"hidden sm:flex flex-wrap gap-2 bg-white/10 rounded-2xl p-2 backdrop-blur-sm"},Ne=["onClick"],Ve={class:"hidden md:inline"},Le={class:"md:hidden"},Se={__name:"TabBar",props:{activeTab:{type:String,required:!0}},emits:["tab-change"],setup(w){const f=[{key:"dashboard",name:"仪表板",shortName:"仪表板",icon:"fas fa-tachometer-alt"},{key:"apiKeys",name:"API Keys",shortName:"API",icon:"fas fa-key"},{key:"accounts",name:"账户管理",shortName:"账户",icon:"fas fa-user-circle"},{key:"tutorial",name:"使用教程",shortName:"教程",icon:"fas fa-graduation-cap"},{key:"settings",name:"其他设置",shortName:"设置",icon:"fas fa-cogs"}];return(u,c)=>(o(),l("div",Pe,[e("div",Ie,[e("select",{value:w.activeTab,class:"w-full px-4 py-3 bg-white/90 rounded-lg text-gray-700 font-semibold focus:outline-none focus:ring-2 focus:ring-primary-color",onChange:c[0]||(c[0]=a=>u.$emit("tab-change",a.target.value))},[(o(),l(N,null,A(f,a=>e("option",{key:a.key,value:a.key},p(a.name),9,Me)),64))],40,$e)]),e("div",Te,[(o(),l(N,null,A(f,a=>e("button",{key:a.key,class:T(["tab-btn flex-1 py-2 sm:py-3 px-3 sm:px-4 md:px-6 text-xs sm:text-sm font-semibold transition-all duration-300",w.activeTab===a.key?"active":"text-gray-700 hover:bg-white/10 hover:text-gray-900"]),onClick:k=>u.$emit("tab-change",a.key)},[e("i",{class:T(a.icon+" mr-1 sm:mr-2")},null,2),e("span",Ve,p(a.name),1),e("span",Le,p(a.shortName||a.name),1)],10,Ne)),64))])]))}},Ae=V(Se,[["__scopeId","data-v-4c6ce4e1"]]),je={class:"min-h-screen p-3 sm:p-4 md:p-6"},De={class:"glass-strong rounded-xl sm:rounded-2xl md:rounded-3xl p-3 sm:p-4 md:p-6 shadow-xl",style:{"z-index":"1","min-height":"calc(100vh - 120px)"}},qe={class:"tab-content"},ze={__name:"MainLayout",setup(w){const f=Q(),u=z(),c=h("dashboard"),a={dashboard:"/dashboard",apiKeys:"/api-keys",accounts:"/accounts",tutorial:"/tutorial",settings:"/settings"};J(()=>f.path,t=>{const r=Object.keys(a).find(x=>a[x]===t);r&&(c.value=r)},{immediate:!0});const k=t=>{c.value=t,u.push(a[t])};return(t,r)=>{const x=H("router-view");return o(),l("div",je,[y(Ce),e("div",De,[y(Ae,{"active-tab":c.value,onTabChange:k},null,8,["active-tab"]),e("div",qe,[y(x,null,{default:C(({Component:g})=>[y(q,{name:"slide-up",mode:"out-in"},{default:C(()=>[(o(),j(Y,{include:["DashboardView","ApiKeysView"]},[(o(),j(G(g)))],1024))]),_:2},1024)]),_:1})])])])}}},He=V(ze,[["__scopeId","data-v-d57a6347"]]);export{He as default};
diff --git a/web/admin-spa/dist/assets/SettingsView-s66COg9q.js b/web/admin-spa/dist/assets/SettingsView-Dr_Y0aLV.js
similarity index 99%
rename from web/admin-spa/dist/assets/SettingsView-s66COg9q.js
rename to web/admin-spa/dist/assets/SettingsView-Dr_Y0aLV.js
index 7ad6ef16..e35b35a3 100644
--- a/web/admin-spa/dist/assets/SettingsView-s66COg9q.js
+++ b/web/admin-spa/dist/assets/SettingsView-Dr_Y0aLV.js
@@ -1,3 +1,3 @@
-import{aR as F,r as h,aW as O,q as T,x as d,z as t,L as v,u as s,K as S,aq as D,O as p,C as j,P as w,aY as C,y as c}from"./vue-vendor-CKToUHZx.js";import{s as g}from"./toast-BvwA7Mwb.js";import{a as N,_ as E}from"./index-D3bIJLrk.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const V=F("settings",()=>{const l=h({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null}),u=h(!1),f=h(!1),m=async()=>{u.value=!0;try{const i=await N.get("/admin/oem-settings");return i&&i.success&&(l.value={...l.value,...i.data},x()),i}catch(i){throw console.error("Failed to load OEM settings:",i),i}finally{u.value=!1}},a=async i=>{f.value=!0;try{const o=await N.put("/admin/oem-settings",i);return o&&o.success&&(l.value={...l.value,...o.data},x()),o}catch(o){throw console.error("Failed to save OEM settings:",o),o}finally{f.value=!1}},y=async()=>{const i={siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null};return l.value={...i},await a(i)},x=()=>{if(l.value.siteName&&(document.title=`${l.value.siteName} - 管理后台`),l.value.siteIconData||l.value.siteIcon){const i=document.querySelector('link[rel="icon"]')||document.createElement("link");i.rel="icon",i.href=l.value.siteIconData||l.value.siteIcon,document.querySelector('link[rel="icon"]')||document.head.appendChild(i)}};return{oemSettings:l,loading:u,saving:f,loadOemSettings:m,saveOemSettings:a,resetOemSettings:y,applyOemSettings:x,formatDateTime:i=>i?new Date(i).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}):"",validateIconFile:i=>{const o=[];return i.size>350*1024&&o.push("图标文件大小不能超过 350KB"),["image/x-icon","image/png","image/jpeg","image/jpg","image/svg+xml"].includes(i.type)||o.push("不支持的文件类型,请选择 .ico, .png, .jpg 或 .svg 文件"),{isValid:o.length===0,errors:o}},fileToBase64:i=>new Promise((o,n)=>{const e=new FileReader;e.onload=r=>o(r.target.result),e.onerror=n,e.readAsDataURL(i)})}}),R={class:"settings-container"},B={class:"card p-4 sm:p-6"},A={key:0,class:"text-center py-12"},M={key:1,class:"hidden sm:block table-container"},U={class:"min-w-full"},$={class:"divide-y divide-gray-200/50"},q={class:"table-row"},z={class:"px-6 py-4"},L={class:"table-row"},P={class:"px-6 py-4"},G={class:"space-y-3"},K={key:0,class:"inline-flex items-center gap-3 p-3 bg-gray-50 rounded-lg"},J=["src"],W={class:"px-6 py-6",colspan:"2"},Y={class:"flex items-center justify-between"},H={class:"flex gap-3"},Q=["disabled"],X={key:0,class:"loading-spinner mr-2"},Z={key:1,class:"fas fa-save mr-2"},tt=["disabled"],et={key:0,class:"text-sm text-gray-500"},st={key:2,class:"sm:hidden space-y-4"},at={class:"bg-gray-50 rounded-lg p-4"},it={class:"space-y-2"},ot={class:"bg-gray-50 rounded-lg p-4"},nt={class:"space-y-3"},lt={key:0,class:"inline-flex items-center gap-3 p-3 bg-white rounded-lg border border-gray-200 w-full"},rt=["src"],dt={class:"flex flex-col gap-2"},ct={class:"space-y-3 pt-2"},ut=["disabled"],mt={key:0,class:"loading-spinner mr-2"},pt={key:1,class:"fas fa-save mr-2"},gt=["disabled"],ft={key:0,class:"text-center text-xs text-gray-500"},xt={__name:"SettingsView",setup(l){const u=V(),{loading:f,saving:m,oemSettings:a}=O(u),y=h();T(async()=>{try{await u.loadOemSettings()}catch{g("加载设置失败","error")}});const x=async()=>{try{const n={siteName:a.value.siteName,siteIcon:a.value.siteIcon,siteIconData:a.value.siteIconData},e=await u.saveOemSettings(n);e&&e.success?g("OEM设置保存成功","success"):g((e==null?void 0:e.message)||"保存失败","error")}catch{g("保存OEM设置失败","error")}},I=async()=>{if(confirm(`确定要重置为默认设置吗?
+import{aR as F,r as h,aW as O,q as T,x as d,z as t,L as v,u as s,K as S,aq as D,O as p,C as j,P as w,aY as C,y as c}from"./vue-vendor-CKToUHZx.js";import{s as g}from"./toast-BvwA7Mwb.js";import{a as N,_ as E}from"./index-D1PUfDNP.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const V=F("settings",()=>{const l=h({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null}),u=h(!1),f=h(!1),m=async()=>{u.value=!0;try{const i=await N.get("/admin/oem-settings");return i&&i.success&&(l.value={...l.value,...i.data},x()),i}catch(i){throw console.error("Failed to load OEM settings:",i),i}finally{u.value=!1}},a=async i=>{f.value=!0;try{const o=await N.put("/admin/oem-settings",i);return o&&o.success&&(l.value={...l.value,...o.data},x()),o}catch(o){throw console.error("Failed to save OEM settings:",o),o}finally{f.value=!1}},y=async()=>{const i={siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null};return l.value={...i},await a(i)},x=()=>{if(l.value.siteName&&(document.title=`${l.value.siteName} - 管理后台`),l.value.siteIconData||l.value.siteIcon){const i=document.querySelector('link[rel="icon"]')||document.createElement("link");i.rel="icon",i.href=l.value.siteIconData||l.value.siteIcon,document.querySelector('link[rel="icon"]')||document.head.appendChild(i)}};return{oemSettings:l,loading:u,saving:f,loadOemSettings:m,saveOemSettings:a,resetOemSettings:y,applyOemSettings:x,formatDateTime:i=>i?new Date(i).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}):"",validateIconFile:i=>{const o=[];return i.size>350*1024&&o.push("图标文件大小不能超过 350KB"),["image/x-icon","image/png","image/jpeg","image/jpg","image/svg+xml"].includes(i.type)||o.push("不支持的文件类型,请选择 .ico, .png, .jpg 或 .svg 文件"),{isValid:o.length===0,errors:o}},fileToBase64:i=>new Promise((o,n)=>{const e=new FileReader;e.onload=r=>o(r.target.result),e.onerror=n,e.readAsDataURL(i)})}}),R={class:"settings-container"},B={class:"card p-4 sm:p-6"},A={key:0,class:"text-center py-12"},M={key:1,class:"hidden sm:block table-container"},U={class:"min-w-full"},$={class:"divide-y divide-gray-200/50"},q={class:"table-row"},z={class:"px-6 py-4"},L={class:"table-row"},P={class:"px-6 py-4"},G={class:"space-y-3"},K={key:0,class:"inline-flex items-center gap-3 p-3 bg-gray-50 rounded-lg"},J=["src"],W={class:"px-6 py-6",colspan:"2"},Y={class:"flex items-center justify-between"},H={class:"flex gap-3"},Q=["disabled"],X={key:0,class:"loading-spinner mr-2"},Z={key:1,class:"fas fa-save mr-2"},tt=["disabled"],et={key:0,class:"text-sm text-gray-500"},st={key:2,class:"sm:hidden space-y-4"},at={class:"bg-gray-50 rounded-lg p-4"},it={class:"space-y-2"},ot={class:"bg-gray-50 rounded-lg p-4"},nt={class:"space-y-3"},lt={key:0,class:"inline-flex items-center gap-3 p-3 bg-white rounded-lg border border-gray-200 w-full"},rt=["src"],dt={class:"flex flex-col gap-2"},ct={class:"space-y-3 pt-2"},ut=["disabled"],mt={key:0,class:"loading-spinner mr-2"},pt={key:1,class:"fas fa-save mr-2"},gt=["disabled"],ft={key:0,class:"text-center text-xs text-gray-500"},xt={__name:"SettingsView",setup(l){const u=V(),{loading:f,saving:m,oemSettings:a}=O(u),y=h();T(async()=>{try{await u.loadOemSettings()}catch{g("加载设置失败","error")}});const x=async()=>{try{const n={siteName:a.value.siteName,siteIcon:a.value.siteIcon,siteIconData:a.value.siteIconData},e=await u.saveOemSettings(n);e&&e.success?g("OEM设置保存成功","success"):g((e==null?void 0:e.message)||"保存失败","error")}catch{g("保存OEM设置失败","error")}},I=async()=>{if(confirm(`确定要重置为默认设置吗?
这将清除所有自定义的网站名称和图标设置。`))try{const n=await u.resetOemSettings();n&&n.success?g("已重置为默认设置","success"):g("重置失败","error")}catch{g("重置失败","error")}},k=async n=>{const e=n.target.files[0];if(!e)return;const r=u.validateIconFile(e);if(!r.isValid){r.errors.forEach(b=>g(b,"error"));return}try{const b=await u.fileToBase64(e);a.value.siteIconData=b}catch{g("文件读取失败","error")}n.target.value=""},_=()=>{a.value.siteIcon="",a.value.siteIconData=""},i=()=>{console.warn("Icon failed to load")},o=u.formatDateTime;return(n,e)=>(c(),d("div",R,[t("div",B,[e[25]||(e[25]=t("div",{class:"mb-4 sm:mb-6"},[t("h3",{class:"text-lg sm:text-xl font-bold text-gray-900 mb-1 sm:mb-2"}," 其他设置 "),t("p",{class:"text-sm sm:text-base text-gray-600"}," 自定义网站名称和图标 ")],-1)),s(f)?(c(),d("div",A,e[5]||(e[5]=[t("div",{class:"loading-spinner mx-auto mb-4"},null,-1),t("p",{class:"text-gray-500"}," 正在加载设置... ",-1)]))):(c(),d("div",M,[t("table",U,[t("tbody",$,[t("tr",q,[e[7]||(e[7]=t("td",{class:"px-6 py-4 whitespace-nowrap w-48"},[t("div",{class:"flex items-center"},[t("div",{class:"w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3"},[t("i",{class:"fas fa-font text-white text-xs"})]),t("div",null,[t("div",{class:"text-sm font-semibold text-gray-900"}," 网站名称 "),t("div",{class:"text-xs text-gray-500"}," 品牌标识 ")])])],-1)),t("td",z,[S(t("input",{"onUpdate:modelValue":e[0]||(e[0]=r=>s(a).siteName=r),type:"text",class:"form-input w-full max-w-md",placeholder:"Claude Relay Service",maxlength:"100"},null,512),[[D,s(a).siteName]]),e[6]||(e[6]=t("p",{class:"text-xs text-gray-500 mt-1"}," 将显示在浏览器标题和页面头部 ",-1))])]),t("tr",L,[e[12]||(e[12]=t("td",{class:"px-6 py-4 whitespace-nowrap w-48"},[t("div",{class:"flex items-center"},[t("div",{class:"w-8 h-8 bg-gradient-to-br from-purple-500 to-purple-600 rounded-lg flex items-center justify-center mr-3"},[t("i",{class:"fas fa-image text-white text-xs"})]),t("div",null,[t("div",{class:"text-sm font-semibold text-gray-900"}," 网站图标 "),t("div",{class:"text-xs text-gray-500"}," Favicon ")])])],-1)),t("td",P,[t("div",G,[s(a).siteIconData||s(a).siteIcon?(c(),d("div",K,[t("img",{src:s(a).siteIconData||s(a).siteIcon,alt:"图标预览",class:"w-8 h-8",onError:i},null,40,J),e[9]||(e[9]=t("span",{class:"text-sm text-gray-600"},"当前图标",-1)),t("button",{class:"text-red-600 hover:text-red-900 font-medium hover:bg-red-50 px-3 py-1 rounded-lg transition-colors",onClick:_},e[8]||(e[8]=[t("i",{class:"fas fa-trash mr-1"},null,-1),p("删除 ",-1)]))])):v("",!0),t("div",null,[t("input",{ref_key:"iconFileInput",ref:y,type:"file",accept:".ico,.png,.jpg,.jpeg,.svg",class:"hidden",onChange:k},null,544),t("button",{class:"btn btn-success px-4 py-2",onClick:e[1]||(e[1]=r=>n.$refs.iconFileInput.click())},e[10]||(e[10]=[t("i",{class:"fas fa-upload mr-2"},null,-1),p(" 上传图标 ",-1)])),e[11]||(e[11]=t("span",{class:"text-xs text-gray-500 ml-3"},"支持 .ico, .png, .jpg, .svg 格式,最大 350KB",-1))])])])]),t("tr",null,[t("td",W,[t("div",Y,[t("div",H,[t("button",{disabled:s(m),class:j(["btn btn-primary px-6 py-3",{"opacity-50 cursor-not-allowed":s(m)}]),onClick:x},[s(m)?(c(),d("div",X)):(c(),d("i",Z)),p(" "+w(s(m)?"保存中...":"保存设置"),1)],10,Q),t("button",{class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3",disabled:s(m),onClick:I},e[13]||(e[13]=[t("i",{class:"fas fa-undo mr-2"},null,-1),p(" 重置为默认 ",-1)]),8,tt)]),s(a).updatedAt?(c(),d("div",et,[e[14]||(e[14]=t("i",{class:"fas fa-clock mr-1"},null,-1)),p(" 最后更新:"+w(s(o)(s(a).updatedAt)),1)])):v("",!0)])])])])])])),s(f)?v("",!0):(c(),d("div",st,[t("div",at,[e[16]||(e[16]=C('',1)),t("div",it,[S(t("input",{"onUpdate:modelValue":e[2]||(e[2]=r=>s(a).siteName=r),type:"text",class:"form-input w-full text-sm",placeholder:"Claude Relay Service",maxlength:"100"},null,512),[[D,s(a).siteName]]),e[15]||(e[15]=t("p",{class:"text-xs text-gray-500"}," 将显示在浏览器标题和页面头部 ",-1))])]),t("div",ot,[e[22]||(e[22]=C('',1)),t("div",nt,[s(a).siteIconData||s(a).siteIcon?(c(),d("div",lt,[t("img",{src:s(a).siteIconData||s(a).siteIcon,alt:"图标预览",class:"w-8 h-8",onError:i},null,40,rt),e[18]||(e[18]=t("span",{class:"text-sm text-gray-600 flex-1"},"当前图标",-1)),t("button",{class:"text-red-600 hover:text-red-900 text-sm font-medium hover:bg-red-50 px-3 py-1 rounded-lg transition-colors",onClick:_},e[17]||(e[17]=[t("i",{class:"fas fa-trash mr-1"},null,-1),p("删除 ",-1)]))])):v("",!0),t("input",{ref_key:"iconFileInput",ref:y,type:"file",accept:"image/*",style:{display:"none"},onChange:k},null,544),t("div",dt,[t("button",{class:"w-full px-4 py-2 bg-white border border-gray-200 rounded-lg text-sm text-gray-700 hover:bg-gray-50 transition-colors flex items-center justify-center gap-2",onClick:e[3]||(e[3]=r=>n.$refs.iconFileInput.click())},e[19]||(e[19]=[t("i",{class:"fas fa-upload"},null,-1),p(" 上传图标 ",-1)])),e[20]||(e[20]=t("div",{class:"text-xs text-gray-500"}," 或者输入图标URL: ",-1)),S(t("input",{"onUpdate:modelValue":e[4]||(e[4]=r=>s(a).siteIcon=r),type:"url",class:"form-input w-full text-sm",placeholder:"https://example.com/icon.png"},null,512),[[D,s(a).siteIcon]])]),e[21]||(e[21]=t("p",{class:"text-xs text-gray-500"}," 支持 PNG、JPEG、GIF 格式,建议使用正方形图片 ",-1))])]),t("div",ct,[t("button",{class:"btn btn-primary w-full py-3 text-sm font-semibold",disabled:s(m),onClick:x},[s(m)?(c(),d("div",mt)):(c(),d("i",pt)),p(" "+w(s(m)?"保存中...":"保存设置"),1)],8,ut),t("button",{class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 w-full py-3 text-sm",disabled:s(m),onClick:I},e[23]||(e[23]=[t("i",{class:"fas fa-undo mr-2"},null,-1),p(" 重置为默认 ",-1)]),8,gt),s(a).updatedAt?(c(),d("div",ft,[e[24]||(e[24]=t("i",{class:"fas fa-clock mr-1"},null,-1)),p(" 最后更新:"+w(s(o)(s(a).updatedAt)),1)])):v("",!0)])]))])]))}},It=E(xt,[["__scopeId","data-v-b9afc490"]]);export{It as default};
diff --git a/web/admin-spa/dist/assets/TutorialView-Bj1w0Zae.js b/web/admin-spa/dist/assets/TutorialView-DmH0Lh6x.js
similarity index 99%
rename from web/admin-spa/dist/assets/TutorialView-Bj1w0Zae.js
rename to web/admin-spa/dist/assets/TutorialView-DmH0Lh6x.js
index 393f853c..8fcb4ed4 100644
--- a/web/admin-spa/dist/assets/TutorialView-Bj1w0Zae.js
+++ b/web/admin-spa/dist/assets/TutorialView-DmH0Lh6x.js
@@ -1 +1 @@
-import{_ as v}from"./index-D3bIJLrk.js";import{r as n,c as p,x as r,z as s,L as g,O as e,Q as c,ac as u,aY as m,P as a,y as b,C as i}from"./vue-vendor-CKToUHZx.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const y={class:"card p-3 sm:p-6"},f={class:"mb-4 sm:mb-8"},w={class:"flex flex-wrap gap-1 sm:gap-2 p-1 sm:p-2 bg-gray-100 rounded-xl"},h=["onClick"],C={key:0,class:"tutorial-content"},A={class:"mb-6 sm:mb-10"},T={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-4 sm:p-6 border border-orange-100 mb-4 sm:mb-6"},P={class:"space-y-4"},N={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},S={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},H={class:"text-gray-300 whitespace-nowrap"},O={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},I={class:"mt-3 space-y-2"},R={class:"bg-gray-100 p-2 rounded text-sm"},_={class:"font-mono"},j={class:"bg-blue-50 border border-blue-200 rounded-lg p-3 sm:p-4 mt-6"},E={class:"mt-3 space-y-2"},B={class:"bg-gray-100 p-2 rounded text-sm font-mono"},U={key:1,class:"tutorial-content"},L={class:"mb-6 sm:mb-10"},q={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-4 sm:p-6 border border-orange-100 mb-4 sm:mb-6"},k={class:"space-y-4"},G={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},K={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},z={class:"text-gray-300 whitespace-nowrap"},D={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},W={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto mb-3"},$={class:"text-gray-300 whitespace-nowrap"},M={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},V={class:"text-gray-300 whitespace-nowrap"},F={key:2,class:"tutorial-content"},Q={class:"mb-6 sm:mb-10"},Y={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-4 sm:p-6 border border-orange-100 mb-4 sm:mb-6"},J={class:"space-y-4"},X={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},Z={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},tt={class:"text-gray-300 whitespace-nowrap"},st={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},et={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto mb-3"},at={class:"text-gray-300 whitespace-nowrap"},dt={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},mt={class:"text-gray-300 whitespace-nowrap"},ot={__name:"TutorialView",setup(lt){const o=n("windows"),x=[{key:"windows",name:"Windows",icon:"fab fa-windows"},{key:"macos",name:"macOS",icon:"fab fa-apple"},{key:"linux",name:"Linux / WSL2",icon:"fab fa-linux"}],d=p(()=>window.location.origin);return(rt,t)=>(b(),r("div",y,[t[55]||(t[55]=s("div",{class:"mb-4 sm:mb-8"},[s("h3",{class:"text-xl sm:text-2xl font-bold text-gray-900 mb-3 sm:mb-4 flex items-center"},[s("i",{class:"fas fa-graduation-cap text-blue-600 mr-2 sm:mr-3"}),e(" Claude Code 使用教程 ")]),s("p",{class:"text-gray-600 text-sm sm:text-lg"}," 跟着这个教程,你可以轻松在自己的电脑上安装并使用 Claude Code。 ")],-1)),s("div",f,[s("div",w,[(b(),r(c,null,u(x,l=>s("button",{key:l.key,class:i(["flex-1 py-2 sm:py-3 px-3 sm:px-6 text-xs sm:text-sm font-semibold rounded-lg transition-all duration-300 flex items-center justify-center gap-1 sm:gap-2",o.value===l.key?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:bg-white/50 hover:text-gray-900"]),onClick:bt=>o.value=l.key},[s("i",{class:i(l.icon)},null,2),e(" "+a(l.name),1)],10,h)),64))])]),o.value==="windows"?(b(),r("div",C,[t[19]||(t[19]=m('1 安装 Node.js 环境
Claude Code 需要 Node.js 环境才能运行。
Windows 安装方法
方法一:官网下载(推荐)
- 打开浏览器访问
https://nodejs.org/ - 点击 "LTS" 版本进行下载(推荐长期支持版本)
- 下载完成后双击
.msi 文件 - 按照安装向导完成安装,保持默认设置即可
方法二:使用包管理器
如果你安装了 Chocolatey 或 Scoop,可以使用命令行安装:
# 使用 Chocolatey
choco install nodejs
# 或使用 Scoop
scoop install nodejs
Windows 注意事项
- • 建议使用 PowerShell 而不是 CMD
- • 如果遇到权限问题,尝试以管理员身份运行
- • 某些杀毒软件可能会误报,需要添加白名单
验证安装是否成功
安装完成后,打开 PowerShell 或 CMD,输入以下命令:
node --version
npm --version
如果显示版本号,说明安装成功了!
2 安装 Git Bash
Windows 环境下需要使用 Git Bash 安装Claude code。安装完成后,环境变量设置和使用 Claude Code 仍然在普通的 PowerShell 或 CMD 中进行。
下载并安装 Git for Windows
- 访问
https://git-scm.com/downloads/win - 点击 "Download for Windows" 下载安装包
- 运行下载的
.exe 安装文件 - 在安装过程中保持默认设置,直接点击 "Next" 完成安装
安装完成后
- • 在任意文件夹右键可以看到 "Git Bash Here" 选项
- • 也可以从开始菜单启动 "Git Bash"
- • 只需要在 Git Bash 中运行 npm install 命令
- • 后续的环境变量设置和使用都在 PowerShell/CMD 中
验证 Git Bash 安装
打开 Git Bash,输入以下命令验证:
如果显示 Git 版本号,说明安装成功!
3 安装 Claude Code
安装 Claude Code
打开 Git Bash(重要:不要使用 PowerShell),运行以下命令:
# 在 Git Bash 中全局安装 Claude Code
npm install -g @anthropic-ai/claude-code
这个命令会从 npm 官方仓库下载并安装最新版本的 Claude Code。
重要提醒
- • 必须在 Git Bash 中运行,不要在 PowerShell 中运行
- • 如果遇到权限问题,可以尝试在 Git Bash 中使用 sudo 命令
验证 Claude Code 安装
安装完成后,输入以下命令检查是否安装成功:
如果显示版本号,恭喜你!Claude Code 已经成功安装了。
',3)),s("div",A,[t[18]||(t[18]=s("h4",{class:"text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4 flex items-center"},[s("span",{class:"w-6 h-6 sm:w-8 sm:h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-xs sm:text-sm font-bold mr-2 sm:mr-3"},"4"),e(" 设置环境变量 ")],-1)),s("div",T,[t[12]||(t[12]=s("h5",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-2 sm:mb-3 flex items-center"},[s("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[13]||(t[13]=s("p",{class:"text-gray-700 mb-3 sm:mb-4 text-sm sm:text-base"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),s("div",P,[s("div",N,[t[1]||(t[1]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法一:PowerShell 临时设置(推荐) ",-1)),t[2]||(t[2]=s("p",{class:"text-gray-600 text-sm mb-3"}," 在 PowerShell 中运行以下命令: ",-1)),s("div",S,[s("div",H,' $env:ANTHROPIC_BASE_URL = "'+a(d.value)+'" ',1),t[0]||(t[0]=s("div",{class:"text-gray-300 whitespace-nowrap"},' $env:ANTHROPIC_AUTH_TOKEN = "你的API密钥" ',-1))]),t[3]||(t[3]=s("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),s("div",O,[t[10]||(t[10]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法二:系统环境变量(永久设置) ",-1)),t[11]||(t[11]=s("ol",{class:"text-gray-600 text-xs sm:text-sm space-y-1 list-decimal list-inside"},[s("li",null,'右键"此电脑" → "属性" → "高级系统设置"'),s("li",null,'点击"环境变量"按钮'),s("li",null,'在"用户变量"或"系统变量"中点击"新建"'),s("li",null,"添加以下两个变量:")],-1)),s("div",I,[s("div",R,[t[4]||(t[4]=s("strong",null,"变量名:",-1)),t[5]||(t[5]=e(" ANTHROPIC_BASE_URL",-1)),t[6]||(t[6]=s("br",null,null,-1)),t[7]||(t[7]=s("strong",null,"变量值:",-1)),t[8]||(t[8]=e()),s("span",_,a(d.value),1)]),t[9]||(t[9]=s("div",{class:"bg-gray-100 p-2 rounded text-sm"},[s("strong",null,"变量名:"),e(" ANTHROPIC_AUTH_TOKEN"),s("br"),s("strong",null,"变量值:"),e(),s("span",{class:"font-mono"},"你的API密钥")],-1))])])])]),s("div",j,[t[17]||(t[17]=m(' 验证环境变量设置
设置完环境变量后,可以通过以下命令验证是否设置成功:
在 PowerShell 中验证:
echo $env:ANTHROPIC_BASE_URL
echo $env:ANTHROPIC_AUTH_TOKEN
在 CMD 中验证:
echo %ANTHROPIC_BASE_URL%
echo %ANTHROPIC_AUTH_TOKEN%
',3)),s("div",E,[t[15]||(t[15]=s("p",{class:"text-blue-700 text-sm"},[s("strong",null,"预期输出示例:")],-1)),s("div",B,[s("div",null,a(d.value),1),t[14]||(t[14]=s("div",null,"cr_xxxxxxxxxxxxxxxxxx",-1))]),t[16]||(t[16]=s("p",{class:"text-blue-700 text-xs"}," 💡 如果输出为空或显示变量名本身,说明环境变量设置失败,请重新设置。 ",-1))])])]),t[20]||(t[20]=m('5 开始使用 Claude Code
现在你可以开始使用 Claude Code 了!
在特定项目中使用
# 进入你的项目目录
cd C:\\path\\to\\your\\project
# 启动 Claude Code
claude
Windows 常见问题解决
安装时提示 "permission denied" 错误
这通常是权限问题,尝试以下解决方法:
- 以管理员身份运行 PowerShell
- 或者配置 npm 使用用户目录:
npm config set prefix %APPDATA%\\npm
PowerShell 执行策略错误
如果遇到执行策略限制,运行:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
环境变量设置后不生效
设置永久环境变量后需要:
- 重新启动 PowerShell 或 CMD
- 或者注销并重新登录 Windows
- 验证设置:
echo $env:ANTHROPIC_BASE_URL
',2))])):o.value==="macos"?(b(),r("div",U,[t[36]||(t[36]=m('1 安装 Node.js 环境
Claude Code 需要 Node.js 环境才能运行。
macOS 安装方法
方法一:使用 Homebrew(推荐)
如果你已经安装了 Homebrew,使用它安装 Node.js 会更方便:
# 更新 Homebrew
brew update
# 安装 Node.js
brew install node
方法二:官网下载
- 访问
https://nodejs.org/ - 下载适合 macOS 的 LTS 版本
- 打开下载的
.pkg 文件 - 按照安装程序指引完成安装
macOS 注意事项
- • 如果遇到权限问题,可能需要使用
sudo - • 首次运行可能需要在系统偏好设置中允许
- • 建议使用 Terminal 或 iTerm2
验证安装是否成功
安装完成后,打开 Terminal,输入以下命令:
node --version
npm --version
如果显示版本号,说明安装成功了!
2 安装 Claude Code
安装 Claude Code
打开 Terminal,运行以下命令:
# 全局安装 Claude Code
npm install -g @anthropic-ai/claude-code
如果遇到权限问题,可以使用 sudo:
sudo npm install -g @anthropic-ai/claude-code
验证 Claude Code 安装
安装完成后,输入以下命令检查是否安装成功:
如果显示版本号,恭喜你!Claude Code 已经成功安装了。
',2)),s("div",L,[t[35]||(t[35]=s("h4",{class:"text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4 flex items-center"},[s("span",{class:"w-6 h-6 sm:w-8 sm:h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-xs sm:text-sm font-bold mr-2 sm:mr-3"},"3"),e(" 设置环境变量 ")],-1)),s("div",q,[t[33]||(t[33]=s("h5",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-2 sm:mb-3 flex items-center"},[s("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[34]||(t[34]=s("p",{class:"text-gray-700 mb-3 sm:mb-4 text-sm sm:text-base"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),s("div",k,[s("div",G,[t[22]||(t[22]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法一:临时设置(当前会话) ",-1)),t[23]||(t[23]=s("p",{class:"text-gray-600 text-sm mb-3"}," 在 Terminal 中运行以下命令: ",-1)),s("div",K,[s("div",z,' export ANTHROPIC_BASE_URL="'+a(d.value)+'" ',1),t[21]||(t[21]=s("div",{class:"text-gray-300 whitespace-nowrap"},' export ANTHROPIC_AUTH_TOKEN="你的API密钥" ',-1))]),t[24]||(t[24]=s("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),s("div",D,[t[31]||(t[31]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法二:永久设置 ",-1)),t[32]||(t[32]=s("p",{class:"text-gray-600 text-sm mb-3"}," 编辑你的 shell 配置文件(根据你使用的 shell): ",-1)),s("div",W,[t[25]||(t[25]=s("div",{class:"mb-2"}," # 对于 zsh (默认) ",-1)),s("div",$,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.zshrc `,1),t[26]||(t[26]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.zshrc `,-1)),t[27]||(t[27]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.zshrc ",-1))]),s("div",M,[t[28]||(t[28]=s("div",{class:"mb-2"}," # 对于 bash ",-1)),s("div",V,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.bash_profile `,1),t[29]||(t[29]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.bash_profile `,-1)),t[30]||(t[30]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.bash_profile ",-1))])])])])]),t[37]||(t[37]=m('4 开始使用 Claude Code
现在你可以开始使用 Claude Code 了!
在特定项目中使用
# 进入你的项目目录
cd /path/to/your/project
# 启动 Claude Code
claude
macOS 常见问题解决
安装时提示权限错误
尝试以下解决方法:
- 使用 sudo 安装:
sudo npm install -g @anthropic-ai/claude-code - 或者配置 npm 使用用户目录:
npm config set prefix ~/.npm-global
macOS 安全设置阻止运行
如果系统阻止运行 Claude Code:
- 打开"系统偏好设置" → "安全性与隐私"
- 点击"仍要打开"或"允许"
- 或者在 Terminal 中运行:
sudo spctl --master-disable
环境变量不生效
检查以下几点:
- 确认修改了正确的配置文件(.zshrc 或 .bash_profile)
- 重新启动 Terminal
- 验证设置:
echo $ANTHROPIC_BASE_URL
',2))])):o.value==="linux"?(b(),r("div",F,[t[53]||(t[53]=m('1 安装 Node.js 环境
Claude Code 需要 Node.js 环境才能运行。
Linux 安装方法
方法一:使用官方仓库(推荐)
# 添加 NodeSource 仓库
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
# 安装 Node.js
sudo apt-get install -y nodejs
方法二:使用系统包管理器
虽然版本可能不是最新的,但对于基本使用已经足够:
# Ubuntu/Debian
sudo apt update
sudo apt install nodejs npm
# CentOS/RHEL/Fedora
sudo dnf install nodejs npm
Linux 注意事项
- • 某些发行版可能需要安装额外的依赖
- • 如果遇到权限问题,使用
sudo - • 确保你的用户在 npm 的全局目录有写权限
验证安装是否成功
安装完成后,打开终端,输入以下命令:
node --version
npm --version
如果显示版本号,说明安装成功了!
2 安装 Claude Code
安装 Claude Code
打开终端,运行以下命令:
# 全局安装 Claude Code
npm install -g @anthropic-ai/claude-code
如果遇到权限问题,可以使用 sudo:
sudo npm install -g @anthropic-ai/claude-code
验证 Claude Code 安装
安装完成后,输入以下命令检查是否安装成功:
如果显示版本号,恭喜你!Claude Code 已经成功安装了。
',2)),s("div",Q,[t[52]||(t[52]=s("h4",{class:"text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4 flex items-center"},[s("span",{class:"w-6 h-6 sm:w-8 sm:h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-xs sm:text-sm font-bold mr-2 sm:mr-3"},"3"),e(" 设置环境变量 ")],-1)),s("div",Y,[t[50]||(t[50]=s("h5",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-2 sm:mb-3 flex items-center"},[s("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[51]||(t[51]=s("p",{class:"text-gray-700 mb-3 sm:mb-4 text-sm sm:text-base"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),s("div",J,[s("div",X,[t[39]||(t[39]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法一:临时设置(当前会话) ",-1)),t[40]||(t[40]=s("p",{class:"text-gray-600 text-sm mb-3"}," 在终端中运行以下命令: ",-1)),s("div",Z,[s("div",tt,' export ANTHROPIC_BASE_URL="'+a(d.value)+'" ',1),t[38]||(t[38]=s("div",{class:"text-gray-300 whitespace-nowrap"},' export ANTHROPIC_AUTH_TOKEN="你的API密钥" ',-1))]),t[41]||(t[41]=s("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),s("div",st,[t[48]||(t[48]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法二:永久设置 ",-1)),t[49]||(t[49]=s("p",{class:"text-gray-600 text-sm mb-3"}," 编辑你的 shell 配置文件: ",-1)),s("div",et,[t[42]||(t[42]=s("div",{class:"mb-2"}," # 对于 bash (默认) ",-1)),s("div",at,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.bashrc `,1),t[43]||(t[43]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.bashrc `,-1)),t[44]||(t[44]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.bashrc ",-1))]),s("div",dt,[t[45]||(t[45]=s("div",{class:"mb-2"}," # 对于 zsh ",-1)),s("div",mt,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.zshrc `,1),t[46]||(t[46]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.zshrc `,-1)),t[47]||(t[47]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.zshrc ",-1))])])])])]),t[54]||(t[54]=m('4 开始使用 Claude Code
现在你可以开始使用 Claude Code 了!
在特定项目中使用
# 进入你的项目目录
cd /path/to/your/project
# 启动 Claude Code
claude
Linux 常见问题解决
安装时提示权限错误
尝试以下解决方法:
- 使用 sudo 安装:
sudo npm install -g @anthropic-ai/claude-code - 或者配置 npm 使用用户目录:
npm config set prefix ~/.npm-global - 然后添加到 PATH:
export PATH=~/.npm-global/bin:$PATH
缺少依赖库
某些 Linux 发行版需要安装额外依赖:
# Ubuntu/Debian
sudo apt install build-essential
# CentOS/RHEL
sudo dnf groupinstall "Development Tools"
环境变量不生效
检查以下几点:
- 确认修改了正确的配置文件(.bashrc 或 .zshrc)
- 重新启动终端或运行
source ~/.bashrc - 验证设置:
echo $ANTHROPIC_BASE_URL
',2))])):g("",!0),t[56]||(t[56]=s("div",{class:"bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-xl p-4 sm:p-6 text-center"},[s("h5",{class:"text-lg sm:text-xl font-semibold mb-2"}," 🎉 恭喜你! "),s("p",{class:"text-blue-100 mb-3 sm:mb-4 text-sm sm:text-base"}," 你已经成功安装并配置了 Claude Code,现在可以开始享受 AI 编程助手带来的便利了。 "),s("p",{class:"text-xs sm:text-sm text-blue-200"}," 如果在使用过程中遇到任何问题,可以查看官方文档或社区讨论获取帮助。 ")],-1))]))}},pt=v(ot,[["__scopeId","data-v-573d0b94"]]);export{pt as default};
+import{_ as v}from"./index-D1PUfDNP.js";import{r as n,c as p,x as r,z as s,L as g,O as e,Q as c,ac as u,aY as m,P as a,y as b,C as i}from"./vue-vendor-CKToUHZx.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const y={class:"card p-3 sm:p-6"},f={class:"mb-4 sm:mb-8"},w={class:"flex flex-wrap gap-1 sm:gap-2 p-1 sm:p-2 bg-gray-100 rounded-xl"},h=["onClick"],C={key:0,class:"tutorial-content"},A={class:"mb-6 sm:mb-10"},T={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-4 sm:p-6 border border-orange-100 mb-4 sm:mb-6"},P={class:"space-y-4"},N={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},S={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},H={class:"text-gray-300 whitespace-nowrap"},O={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},I={class:"mt-3 space-y-2"},R={class:"bg-gray-100 p-2 rounded text-sm"},_={class:"font-mono"},j={class:"bg-blue-50 border border-blue-200 rounded-lg p-3 sm:p-4 mt-6"},E={class:"mt-3 space-y-2"},B={class:"bg-gray-100 p-2 rounded text-sm font-mono"},U={key:1,class:"tutorial-content"},L={class:"mb-6 sm:mb-10"},q={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-4 sm:p-6 border border-orange-100 mb-4 sm:mb-6"},k={class:"space-y-4"},G={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},K={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},z={class:"text-gray-300 whitespace-nowrap"},D={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},W={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto mb-3"},$={class:"text-gray-300 whitespace-nowrap"},M={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},V={class:"text-gray-300 whitespace-nowrap"},F={key:2,class:"tutorial-content"},Q={class:"mb-6 sm:mb-10"},Y={class:"bg-gradient-to-r from-orange-50 to-yellow-50 rounded-xl p-4 sm:p-6 border border-orange-100 mb-4 sm:mb-6"},J={class:"space-y-4"},X={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},Z={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},tt={class:"text-gray-300 whitespace-nowrap"},st={class:"bg-white rounded-lg p-3 sm:p-4 border border-orange-200"},et={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto mb-3"},at={class:"text-gray-300 whitespace-nowrap"},dt={class:"bg-gray-900 text-green-400 p-2 sm:p-3 rounded font-mono text-xs sm:text-sm overflow-x-auto"},mt={class:"text-gray-300 whitespace-nowrap"},ot={__name:"TutorialView",setup(lt){const o=n("windows"),x=[{key:"windows",name:"Windows",icon:"fab fa-windows"},{key:"macos",name:"macOS",icon:"fab fa-apple"},{key:"linux",name:"Linux / WSL2",icon:"fab fa-linux"}],d=p(()=>window.location.origin);return(rt,t)=>(b(),r("div",y,[t[55]||(t[55]=s("div",{class:"mb-4 sm:mb-8"},[s("h3",{class:"text-xl sm:text-2xl font-bold text-gray-900 mb-3 sm:mb-4 flex items-center"},[s("i",{class:"fas fa-graduation-cap text-blue-600 mr-2 sm:mr-3"}),e(" Claude Code 使用教程 ")]),s("p",{class:"text-gray-600 text-sm sm:text-lg"}," 跟着这个教程,你可以轻松在自己的电脑上安装并使用 Claude Code。 ")],-1)),s("div",f,[s("div",w,[(b(),r(c,null,u(x,l=>s("button",{key:l.key,class:i(["flex-1 py-2 sm:py-3 px-3 sm:px-6 text-xs sm:text-sm font-semibold rounded-lg transition-all duration-300 flex items-center justify-center gap-1 sm:gap-2",o.value===l.key?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:bg-white/50 hover:text-gray-900"]),onClick:bt=>o.value=l.key},[s("i",{class:i(l.icon)},null,2),e(" "+a(l.name),1)],10,h)),64))])]),o.value==="windows"?(b(),r("div",C,[t[19]||(t[19]=m('1 安装 Node.js 环境
Claude Code 需要 Node.js 环境才能运行。
Windows 安装方法
方法一:官网下载(推荐)
- 打开浏览器访问
https://nodejs.org/ - 点击 "LTS" 版本进行下载(推荐长期支持版本)
- 下载完成后双击
.msi 文件 - 按照安装向导完成安装,保持默认设置即可
方法二:使用包管理器
如果你安装了 Chocolatey 或 Scoop,可以使用命令行安装:
# 使用 Chocolatey
choco install nodejs
# 或使用 Scoop
scoop install nodejs
Windows 注意事项
- • 建议使用 PowerShell 而不是 CMD
- • 如果遇到权限问题,尝试以管理员身份运行
- • 某些杀毒软件可能会误报,需要添加白名单
验证安装是否成功
安装完成后,打开 PowerShell 或 CMD,输入以下命令:
node --version
npm --version
如果显示版本号,说明安装成功了!
2 安装 Git Bash
Windows 环境下需要使用 Git Bash 安装Claude code。安装完成后,环境变量设置和使用 Claude Code 仍然在普通的 PowerShell 或 CMD 中进行。
下载并安装 Git for Windows
- 访问
https://git-scm.com/downloads/win - 点击 "Download for Windows" 下载安装包
- 运行下载的
.exe 安装文件 - 在安装过程中保持默认设置,直接点击 "Next" 完成安装
安装完成后
- • 在任意文件夹右键可以看到 "Git Bash Here" 选项
- • 也可以从开始菜单启动 "Git Bash"
- • 只需要在 Git Bash 中运行 npm install 命令
- • 后续的环境变量设置和使用都在 PowerShell/CMD 中
验证 Git Bash 安装
打开 Git Bash,输入以下命令验证:
如果显示 Git 版本号,说明安装成功!
3 安装 Claude Code
安装 Claude Code
打开 Git Bash(重要:不要使用 PowerShell),运行以下命令:
# 在 Git Bash 中全局安装 Claude Code
npm install -g @anthropic-ai/claude-code
这个命令会从 npm 官方仓库下载并安装最新版本的 Claude Code。
重要提醒
- • 必须在 Git Bash 中运行,不要在 PowerShell 中运行
- • 如果遇到权限问题,可以尝试在 Git Bash 中使用 sudo 命令
验证 Claude Code 安装
安装完成后,输入以下命令检查是否安装成功:
如果显示版本号,恭喜你!Claude Code 已经成功安装了。
',3)),s("div",A,[t[18]||(t[18]=s("h4",{class:"text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4 flex items-center"},[s("span",{class:"w-6 h-6 sm:w-8 sm:h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-xs sm:text-sm font-bold mr-2 sm:mr-3"},"4"),e(" 设置环境变量 ")],-1)),s("div",T,[t[12]||(t[12]=s("h5",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-2 sm:mb-3 flex items-center"},[s("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[13]||(t[13]=s("p",{class:"text-gray-700 mb-3 sm:mb-4 text-sm sm:text-base"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),s("div",P,[s("div",N,[t[1]||(t[1]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法一:PowerShell 临时设置(推荐) ",-1)),t[2]||(t[2]=s("p",{class:"text-gray-600 text-sm mb-3"}," 在 PowerShell 中运行以下命令: ",-1)),s("div",S,[s("div",H,' $env:ANTHROPIC_BASE_URL = "'+a(d.value)+'" ',1),t[0]||(t[0]=s("div",{class:"text-gray-300 whitespace-nowrap"},' $env:ANTHROPIC_AUTH_TOKEN = "你的API密钥" ',-1))]),t[3]||(t[3]=s("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),s("div",O,[t[10]||(t[10]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法二:系统环境变量(永久设置) ",-1)),t[11]||(t[11]=s("ol",{class:"text-gray-600 text-xs sm:text-sm space-y-1 list-decimal list-inside"},[s("li",null,'右键"此电脑" → "属性" → "高级系统设置"'),s("li",null,'点击"环境变量"按钮'),s("li",null,'在"用户变量"或"系统变量"中点击"新建"'),s("li",null,"添加以下两个变量:")],-1)),s("div",I,[s("div",R,[t[4]||(t[4]=s("strong",null,"变量名:",-1)),t[5]||(t[5]=e(" ANTHROPIC_BASE_URL",-1)),t[6]||(t[6]=s("br",null,null,-1)),t[7]||(t[7]=s("strong",null,"变量值:",-1)),t[8]||(t[8]=e()),s("span",_,a(d.value),1)]),t[9]||(t[9]=s("div",{class:"bg-gray-100 p-2 rounded text-sm"},[s("strong",null,"变量名:"),e(" ANTHROPIC_AUTH_TOKEN"),s("br"),s("strong",null,"变量值:"),e(),s("span",{class:"font-mono"},"你的API密钥")],-1))])])])]),s("div",j,[t[17]||(t[17]=m(' 验证环境变量设置
设置完环境变量后,可以通过以下命令验证是否设置成功:
在 PowerShell 中验证:
echo $env:ANTHROPIC_BASE_URL
echo $env:ANTHROPIC_AUTH_TOKEN
在 CMD 中验证:
echo %ANTHROPIC_BASE_URL%
echo %ANTHROPIC_AUTH_TOKEN%
',3)),s("div",E,[t[15]||(t[15]=s("p",{class:"text-blue-700 text-sm"},[s("strong",null,"预期输出示例:")],-1)),s("div",B,[s("div",null,a(d.value),1),t[14]||(t[14]=s("div",null,"cr_xxxxxxxxxxxxxxxxxx",-1))]),t[16]||(t[16]=s("p",{class:"text-blue-700 text-xs"}," 💡 如果输出为空或显示变量名本身,说明环境变量设置失败,请重新设置。 ",-1))])])]),t[20]||(t[20]=m('5 开始使用 Claude Code
现在你可以开始使用 Claude Code 了!
在特定项目中使用
# 进入你的项目目录
cd C:\\path\\to\\your\\project
# 启动 Claude Code
claude
Windows 常见问题解决
安装时提示 "permission denied" 错误
这通常是权限问题,尝试以下解决方法:
- 以管理员身份运行 PowerShell
- 或者配置 npm 使用用户目录:
npm config set prefix %APPDATA%\\npm
PowerShell 执行策略错误
如果遇到执行策略限制,运行:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
环境变量设置后不生效
设置永久环境变量后需要:
- 重新启动 PowerShell 或 CMD
- 或者注销并重新登录 Windows
- 验证设置:
echo $env:ANTHROPIC_BASE_URL
',2))])):o.value==="macos"?(b(),r("div",U,[t[36]||(t[36]=m('1 安装 Node.js 环境
Claude Code 需要 Node.js 环境才能运行。
macOS 安装方法
方法一:使用 Homebrew(推荐)
如果你已经安装了 Homebrew,使用它安装 Node.js 会更方便:
# 更新 Homebrew
brew update
# 安装 Node.js
brew install node
方法二:官网下载
- 访问
https://nodejs.org/ - 下载适合 macOS 的 LTS 版本
- 打开下载的
.pkg 文件 - 按照安装程序指引完成安装
macOS 注意事项
- • 如果遇到权限问题,可能需要使用
sudo - • 首次运行可能需要在系统偏好设置中允许
- • 建议使用 Terminal 或 iTerm2
验证安装是否成功
安装完成后,打开 Terminal,输入以下命令:
node --version
npm --version
如果显示版本号,说明安装成功了!
2 安装 Claude Code
安装 Claude Code
打开 Terminal,运行以下命令:
# 全局安装 Claude Code
npm install -g @anthropic-ai/claude-code
如果遇到权限问题,可以使用 sudo:
sudo npm install -g @anthropic-ai/claude-code
验证 Claude Code 安装
安装完成后,输入以下命令检查是否安装成功:
如果显示版本号,恭喜你!Claude Code 已经成功安装了。
',2)),s("div",L,[t[35]||(t[35]=s("h4",{class:"text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4 flex items-center"},[s("span",{class:"w-6 h-6 sm:w-8 sm:h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-xs sm:text-sm font-bold mr-2 sm:mr-3"},"3"),e(" 设置环境变量 ")],-1)),s("div",q,[t[33]||(t[33]=s("h5",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-2 sm:mb-3 flex items-center"},[s("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[34]||(t[34]=s("p",{class:"text-gray-700 mb-3 sm:mb-4 text-sm sm:text-base"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),s("div",k,[s("div",G,[t[22]||(t[22]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法一:临时设置(当前会话) ",-1)),t[23]||(t[23]=s("p",{class:"text-gray-600 text-sm mb-3"}," 在 Terminal 中运行以下命令: ",-1)),s("div",K,[s("div",z,' export ANTHROPIC_BASE_URL="'+a(d.value)+'" ',1),t[21]||(t[21]=s("div",{class:"text-gray-300 whitespace-nowrap"},' export ANTHROPIC_AUTH_TOKEN="你的API密钥" ',-1))]),t[24]||(t[24]=s("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),s("div",D,[t[31]||(t[31]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法二:永久设置 ",-1)),t[32]||(t[32]=s("p",{class:"text-gray-600 text-sm mb-3"}," 编辑你的 shell 配置文件(根据你使用的 shell): ",-1)),s("div",W,[t[25]||(t[25]=s("div",{class:"mb-2"}," # 对于 zsh (默认) ",-1)),s("div",$,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.zshrc `,1),t[26]||(t[26]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.zshrc `,-1)),t[27]||(t[27]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.zshrc ",-1))]),s("div",M,[t[28]||(t[28]=s("div",{class:"mb-2"}," # 对于 bash ",-1)),s("div",V,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.bash_profile `,1),t[29]||(t[29]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.bash_profile `,-1)),t[30]||(t[30]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.bash_profile ",-1))])])])])]),t[37]||(t[37]=m('4 开始使用 Claude Code
现在你可以开始使用 Claude Code 了!
在特定项目中使用
# 进入你的项目目录
cd /path/to/your/project
# 启动 Claude Code
claude
macOS 常见问题解决
安装时提示权限错误
尝试以下解决方法:
- 使用 sudo 安装:
sudo npm install -g @anthropic-ai/claude-code - 或者配置 npm 使用用户目录:
npm config set prefix ~/.npm-global
macOS 安全设置阻止运行
如果系统阻止运行 Claude Code:
- 打开"系统偏好设置" → "安全性与隐私"
- 点击"仍要打开"或"允许"
- 或者在 Terminal 中运行:
sudo spctl --master-disable
环境变量不生效
检查以下几点:
- 确认修改了正确的配置文件(.zshrc 或 .bash_profile)
- 重新启动 Terminal
- 验证设置:
echo $ANTHROPIC_BASE_URL
',2))])):o.value==="linux"?(b(),r("div",F,[t[53]||(t[53]=m('1 安装 Node.js 环境
Claude Code 需要 Node.js 环境才能运行。
Linux 安装方法
方法一:使用官方仓库(推荐)
# 添加 NodeSource 仓库
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
# 安装 Node.js
sudo apt-get install -y nodejs
方法二:使用系统包管理器
虽然版本可能不是最新的,但对于基本使用已经足够:
# Ubuntu/Debian
sudo apt update
sudo apt install nodejs npm
# CentOS/RHEL/Fedora
sudo dnf install nodejs npm
Linux 注意事项
- • 某些发行版可能需要安装额外的依赖
- • 如果遇到权限问题,使用
sudo - • 确保你的用户在 npm 的全局目录有写权限
验证安装是否成功
安装完成后,打开终端,输入以下命令:
node --version
npm --version
如果显示版本号,说明安装成功了!
2 安装 Claude Code
安装 Claude Code
打开终端,运行以下命令:
# 全局安装 Claude Code
npm install -g @anthropic-ai/claude-code
如果遇到权限问题,可以使用 sudo:
sudo npm install -g @anthropic-ai/claude-code
验证 Claude Code 安装
安装完成后,输入以下命令检查是否安装成功:
如果显示版本号,恭喜你!Claude Code 已经成功安装了。
',2)),s("div",Q,[t[52]||(t[52]=s("h4",{class:"text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4 flex items-center"},[s("span",{class:"w-6 h-6 sm:w-8 sm:h-8 bg-orange-500 text-white rounded-full flex items-center justify-center text-xs sm:text-sm font-bold mr-2 sm:mr-3"},"3"),e(" 设置环境变量 ")],-1)),s("div",Y,[t[50]||(t[50]=s("h5",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-2 sm:mb-3 flex items-center"},[s("i",{class:"fas fa-cog text-orange-600 mr-2"}),e(" 配置 Claude Code 环境变量 ")],-1)),t[51]||(t[51]=s("p",{class:"text-gray-700 mb-3 sm:mb-4 text-sm sm:text-base"}," 为了让 Claude Code 连接到你的中转服务,需要设置两个环境变量: ",-1)),s("div",J,[s("div",X,[t[39]||(t[39]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法一:临时设置(当前会话) ",-1)),t[40]||(t[40]=s("p",{class:"text-gray-600 text-sm mb-3"}," 在终端中运行以下命令: ",-1)),s("div",Z,[s("div",tt,' export ANTHROPIC_BASE_URL="'+a(d.value)+'" ',1),t[38]||(t[38]=s("div",{class:"text-gray-300 whitespace-nowrap"},' export ANTHROPIC_AUTH_TOKEN="你的API密钥" ',-1))]),t[41]||(t[41]=s("p",{class:"text-yellow-700 text-xs mt-2"},' 💡 记得将 "你的API密钥" 替换为在上方 "API Keys" 标签页中创建的实际密钥。 ',-1))]),s("div",st,[t[48]||(t[48]=s("h6",{class:"font-medium text-sm sm:text-base text-gray-800 mb-2"}," 方法二:永久设置 ",-1)),t[49]||(t[49]=s("p",{class:"text-gray-600 text-sm mb-3"}," 编辑你的 shell 配置文件: ",-1)),s("div",et,[t[42]||(t[42]=s("div",{class:"mb-2"}," # 对于 bash (默认) ",-1)),s("div",at,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.bashrc `,1),t[43]||(t[43]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.bashrc `,-1)),t[44]||(t[44]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.bashrc ",-1))]),s("div",dt,[t[45]||(t[45]=s("div",{class:"mb-2"}," # 对于 zsh ",-1)),s("div",mt,` echo 'export ANTHROPIC_BASE_URL="`+a(d.value)+`"' >> ~/.zshrc `,1),t[46]||(t[46]=s("div",{class:"text-gray-300 whitespace-nowrap"},` echo 'export ANTHROPIC_AUTH_TOKEN="你的API密钥"' >> ~/.zshrc `,-1)),t[47]||(t[47]=s("div",{class:"text-gray-300 whitespace-nowrap"}," source ~/.zshrc ",-1))])])])])]),t[54]||(t[54]=m('4 开始使用 Claude Code
现在你可以开始使用 Claude Code 了!
在特定项目中使用
# 进入你的项目目录
cd /path/to/your/project
# 启动 Claude Code
claude
Linux 常见问题解决
安装时提示权限错误
尝试以下解决方法:
- 使用 sudo 安装:
sudo npm install -g @anthropic-ai/claude-code - 或者配置 npm 使用用户目录:
npm config set prefix ~/.npm-global - 然后添加到 PATH:
export PATH=~/.npm-global/bin:$PATH
缺少依赖库
某些 Linux 发行版需要安装额外依赖:
# Ubuntu/Debian
sudo apt install build-essential
# CentOS/RHEL
sudo dnf groupinstall "Development Tools"
环境变量不生效
检查以下几点:
- 确认修改了正确的配置文件(.bashrc 或 .zshrc)
- 重新启动终端或运行
source ~/.bashrc - 验证设置:
echo $ANTHROPIC_BASE_URL
',2))])):g("",!0),t[56]||(t[56]=s("div",{class:"bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-xl p-4 sm:p-6 text-center"},[s("h5",{class:"text-lg sm:text-xl font-semibold mb-2"}," 🎉 恭喜你! "),s("p",{class:"text-blue-100 mb-3 sm:mb-4 text-sm sm:text-base"}," 你已经成功安装并配置了 Claude Code,现在可以开始享受 AI 编程助手带来的便利了。 "),s("p",{class:"text-xs sm:text-sm text-blue-200"}," 如果在使用过程中遇到任何问题,可以查看官方文档或社区讨论获取帮助。 ")],-1))]))}},pt=v(ot,[["__scopeId","data-v-573d0b94"]]);export{pt as default};
diff --git a/web/admin-spa/dist/assets/index-D3bIJLrk.js b/web/admin-spa/dist/assets/index-D1PUfDNP.js
similarity index 91%
rename from web/admin-spa/dist/assets/index-D3bIJLrk.js
rename to web/admin-spa/dist/assets/index-D1PUfDNP.js
index b2d41f9b..79c75b85 100644
--- a/web/admin-spa/dist/assets/index-D3bIJLrk.js
+++ b/web/admin-spa/dist/assets/index-D1PUfDNP.js
@@ -1,2 +1,2 @@
-const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/LoginView-BccX9MEv.js","assets/vue-vendor-CKToUHZx.js","assets/element-plus-B8Fs_0jW.js","assets/vendor-BDiMbLwQ.js","assets/element-plus-CPnoEkWW.css","assets/LoginView-tn0RQdqM.css","assets/LogoTitle-BiOf3Vkp.css","assets/MainLayout-VM3pfyce.js","assets/toast-BvwA7Mwb.js","assets/LogoTitle-BIy_PC38.js","assets/MainLayout-CXiJ2-1D.css","assets/DashboardView-C1WGP7UM.js","assets/chart-Cor9iTVD.js","assets/DashboardView-R6dMwgzw.css","assets/ApiKeysView-H8g1IO_M.js","assets/ApiKeysView-CID1mfnM.css","assets/AccountsView-tVq-jcj7.js","assets/AccountsView-DwS76LKN.css","assets/TutorialView-Bj1w0Zae.js","assets/TutorialView-B16hEjh7.css","assets/SettingsView-s66COg9q.js","assets/SettingsView-CY0posDI.css","assets/ApiStatsView-Bw7MZuTj.js","assets/ApiStatsView-BP2davUr.css"])))=>i.map(i=>d[i]);
-import{aP as K,aQ as W,aR as M,r as _,c as S,q as V,V as D,I as q,z as h,x as b,ac as F,Q as G,a5 as N,y,C as R,L as x,P as T,Y as U,B as H,R as k,J,T as Q,O as X,av as Y,aM as Z,aS as ee}from"./vue-vendor-CKToUHZx.js";import{i as te,z as oe}from"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const r of n)if(r.type==="childList")for(const a of r.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&o(a)}).observe(document,{childList:!0,subtree:!0});function e(n){const r={};return n.integrity&&(r.integrity=n.integrity),n.referrerPolicy&&(r.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?r.credentials="include":n.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function o(n){if(n.ep)return;n.ep=!0;const r=e(n);fetch(n.href,r)}})();const se="modulepreload",ne=function(s){return"/admin-next/"+s},$={},w=function(t,e,o){let n=Promise.resolve();if(e&&e.length>0){document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),p=(a==null?void 0:a.nonce)||(a==null?void 0:a.getAttribute("nonce"));n=Promise.allSettled(e.map(c=>{if(c=ne(c),c in $)return;$[c]=!0;const l=c.endsWith(".css"),d=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${d}`))return;const i=document.createElement("link");if(i.rel=l?"stylesheet":se,l||(i.as="script"),i.crossOrigin="",i.href=c,p&&i.setAttribute("nonce",p),document.head.appendChild(i),l)return new Promise((m,f)=>{i.addEventListener("load",m),i.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${c}`)))})}))}function r(a){const p=new Event("vite:preloadError",{cancelable:!0});if(p.payload=a,window.dispatchEvent(p),!p.defaultPrevented)throw a}return n.then(a=>{for(const p of a||[])p.status==="rejected"&&r(p.reason);return t().catch(r)})},I={basePath:"/admin-next/",apiPrefix:""};function ae(s=""){return s&&!s.startsWith("/")&&(s="/"+s),I.basePath+(s.startsWith("#")?s:"#"+s)}function re(){return ae("/login")}const ie=()=>w(()=>import("./LoginView-BccX9MEv.js"),__vite__mapDeps([0,1,2,3,4,5,6])),E=()=>w(()=>import("./MainLayout-VM3pfyce.js"),__vite__mapDeps([7,1,8,9,6,2,3,4,10])),ce=()=>w(()=>import("./DashboardView-C1WGP7UM.js"),__vite__mapDeps([11,2,1,3,4,8,12,13])),le=()=>w(()=>import("./ApiKeysView-H8g1IO_M.js"),__vite__mapDeps([14,2,1,3,4,8,15])),ue=()=>w(()=>import("./AccountsView-tVq-jcj7.js"),__vite__mapDeps([16,1,8,2,3,4,17])),de=()=>w(()=>import("./TutorialView-Bj1w0Zae.js"),__vite__mapDeps([18,1,2,3,4,19])),fe=()=>w(()=>import("./SettingsView-s66COg9q.js"),__vite__mapDeps([20,1,8,2,3,4,21])),he=()=>w(()=>import("./ApiStatsView-Bw7MZuTj.js"),__vite__mapDeps([22,1,9,6,3,18,2,4,19,23])),me=[{path:"/",redirect:()=>{const s=window.location.pathname,t=I.basePath.replace(/\/$/,"");return s===t||s===t+"/","/api-stats"}},{path:"/login",name:"Login",component:ie,meta:{requiresAuth:!1}},{path:"/api-stats",name:"ApiStats",component:he,meta:{requiresAuth:!1}},{path:"/dashboard",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Dashboard",component:ce}]},{path:"/api-keys",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"ApiKeys",component:le}]},{path:"/accounts",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Accounts",component:ue}]},{path:"/tutorial",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Tutorial",component:de}]},{path:"/settings",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Settings",component:fe}]},{path:"/:pathMatch(.*)*",redirect:"/api-stats"}],C=K({history:W(I.basePath),routes:me});C.beforeEach((s,t,e)=>{const o=B();if(console.log("路由导航:",{to:s.path,from:t.path,fullPath:s.fullPath,requiresAuth:s.meta.requiresAuth,isAuthenticated:o.isAuthenticated}),s.path===t.path&&s.fullPath===t.fullPath)return e();s.path==="/api-stats"||s.path.startsWith("/api-stats")?e():s.meta.requiresAuth&&!o.isAuthenticated?e("/login"):s.path==="/login"&&o.isAuthenticated?e("/dashboard"):e()});const z=I.apiPrefix;function P(s){return s.startsWith("/")||(s="/"+s),z+s}class pe{constructor(){this.baseURL=z}getAuthToken(){return localStorage.getItem("authToken")||null}buildConfig(t={}){const e={headers:{"Content-Type":"application/json",...t.headers},...t},o=this.getAuthToken();return o&&(e.headers.Authorization=`Bearer ${o}`),e}async handleResponse(t){if(t.status===401){const o=window.location.pathname+window.location.hash;throw o.includes("/login")||o.endsWith("/")||(localStorage.removeItem("authToken"),window.location.href=re()),new Error("Unauthorized")}const e=t.headers.get("content-type");if(e&&e.includes("application/json")){const o=await t.json();if(!t.ok)throw new Error(o.message||`HTTP ${t.status}`);return o}if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);return t}async get(t,e={}){const o=P(t),n=this.buildConfig({...e,method:"GET"});try{const r=await fetch(o,n);return await this.handleResponse(r)}catch(r){throw console.error("API GET Error:",r),r}}async post(t,e=null,o={}){const n=P(t),r=this.buildConfig({...o,method:"POST",body:e?JSON.stringify(e):void 0});try{const a=await fetch(n,r);return await this.handleResponse(a)}catch(a){throw console.error("API POST Error:",a),a}}async put(t,e=null,o={}){const n=P(t),r=this.buildConfig({...o,method:"PUT",body:e?JSON.stringify(e):void 0});try{const a=await fetch(n,r);return await this.handleResponse(a)}catch(a){throw console.error("API PUT Error:",a),a}}async delete(t,e={}){const o=P(t),n=this.buildConfig({...e,method:"DELETE"});try{const r=await fetch(o,n);return await this.handleResponse(r)}catch(r){throw console.error("API DELETE Error:",r),r}}}const A=new pe,B=M("auth",()=>{const s=_(!1),t=_(localStorage.getItem("authToken")||""),e=_(""),o=_(""),n=_(!1),r=_({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",faviconData:""}),a=_(!0),p=S(()=>!!t.value&&s.value),c=S(()=>t.value),l=S(()=>({username:e.value}));async function d(u){n.value=!0,o.value="";try{const g=await A.post("/web/auth/login",u);g.success?(t.value=g.token,e.value=g.username||u.username,s.value=!0,localStorage.setItem("authToken",g.token),await C.push("/dashboard")):o.value=g.message||"登录失败"}catch(g){o.value=g.message||"登录失败,请检查用户名和密码"}finally{n.value=!1}}function i(){s.value=!1,t.value="",e.value="",localStorage.removeItem("authToken"),C.push("/login")}function m(){t.value&&(s.value=!0,f())}async function f(){try{const u=await A.get("/web/auth/user");u.success&&u.user&&(e.value=u.user.username),(await A.get("/admin/dashboard")).success||i()}catch{i()}}async function v(){a.value=!0;try{const u=await A.get("/admin/oem-settings");if(u.success&&u.data){if(r.value={...r.value,...u.data},u.data.siteIconData||u.data.siteIcon){const g=document.querySelector("link[rel*='icon']")||document.createElement("link");g.type="image/x-icon",g.rel="shortcut icon",g.href=u.data.siteIconData||u.data.siteIcon,document.getElementsByTagName("head")[0].appendChild(g)}u.data.siteName&&(document.title=`${u.data.siteName} - 管理后台`)}}catch(u){console.error("加载OEM设置失败:",u)}finally{a.value=!1}}return{isLoggedIn:s,authToken:t,username:e,loginError:o,loginLoading:n,oemSettings:r,oemLoading:a,isAuthenticated:p,token:c,user:l,login:d,logout:i,checkAuth:m,loadOemSettings:v}}),O=(s,t)=>{const e=s.__vccOpts||s;for(const[o,n]of t)e[o]=n;return e},_e={class:"toast-container"},ge=["onClick"],ve={class:"toast-content"},ye={class:"toast-icon"},we={class:"toast-body"},be={key:0,class:"toast-title"},Te={class:"toast-message"},Ee=["onClick"],Pe={__name:"ToastNotification",setup(s,{expose:t}){const e=_([]);let o=0;const n=l=>{const d={success:"fas fa-check-circle",error:"fas fa-exclamation-circle",warning:"fas fa-exclamation-triangle",info:"fas fa-info-circle"};return d[l]||d.info},r=(l,d="info",i=null,m=5e3)=>{const f=++o,v={id:f,message:l,type:d,title:i,duration:m,isVisible:!1};return e.value.push(v),setTimeout(()=>{v.isVisible=!0},10),m>0&&setTimeout(()=>{a(f)},m),f},a=l=>{const d=e.value.findIndex(i=>i.id===l);if(d>-1){const i=e.value[d];i.isVisible=!1,setTimeout(()=>{const m=e.value.findIndex(f=>f.id===l);m>-1&&e.value.splice(m,1)},300)}},p=()=>{e.value.forEach(l=>{l.isVisible=!1}),setTimeout(()=>{e.value.length=0},300)},c=(l,d="info",i=null,m=5e3)=>r(l,d,i,m);return V(()=>{window.showToast=c}),D(()=>{window.showToast===c&&delete window.showToast}),t({showToast:c,removeToast:a,clearAllToasts:p}),(l,d)=>(y(),q(N,{to:"body"},[h("div",_e,[(y(!0),b(G,null,F(e.value,i=>(y(),b("div",{key:i.id,class:R(["toast",`toast-${i.type}`,i.isVisible?"toast-show":"toast-hide"]),onClick:m=>a(i.id)},[h("div",ve,[h("div",ye,[h("i",{class:R(n(i.type))},null,2)]),h("div",we,[i.title?(y(),b("div",be,T(i.title),1)):x("",!0),h("div",Te,T(i.message),1)]),h("button",{class:"toast-close",onClick:U(m=>a(i.id),["stop"])},d[0]||(d[0]=[h("i",{class:"fas fa-times"},null,-1)]),8,Ee)]),i.duration>0?(y(),b("div",{key:0,class:"toast-progress",style:H({animationDuration:`${i.duration}ms`})},null,4)):x("",!0)],10,ge))),128))])]))}},Ae=O(Pe,[["__scopeId","data-v-1a3ab19b"]]),ke={class:"modal-content w-full max-w-md p-6 mx-auto"},xe={class:"flex items-start gap-4 mb-6"},Ce={class:"flex-1"},Ie={class:"text-lg font-semibold text-gray-900 mb-2"},Le={class:"text-gray-600 leading-relaxed whitespace-pre-line"},Se={class:"flex items-center justify-end gap-3"},Re=["disabled"],Ve=["disabled"],Oe={key:0,class:"loading-spinner mr-2"},$e={__name:"ConfirmDialog",setup(s,{expose:t}){const e=_(!1),o=_(!1),n=_(""),r=_(""),a=_("确认"),p=_("取消");let c=null;const l=(f,v,u="确认",g="取消")=>new Promise(j=>{n.value=f,r.value=v,a.value=u,p.value=g,e.value=!0,o.value=!1,c=j}),d=()=>{o.value||(o.value=!0,setTimeout(()=>{e.value=!1,o.value=!1,c&&(c(!0),c=null)},200))},i=()=>{o.value||(e.value=!1,c&&(c(!1),c=null))},m=f=>{e.value&&(f.key==="Escape"?i():f.key==="Enter"&&!f.shiftKey&&!f.ctrlKey&&!f.altKey&&d())};return V(()=>{window.showConfirm=l,document.addEventListener("keydown",m)}),D(()=>{window.showConfirm===l&&delete window.showConfirm,document.removeEventListener("keydown",m)}),t({showConfirm:l}),(f,v)=>(y(),q(N,{to:"body"},[k(Q,{name:"modal",appear:""},{default:J(()=>[e.value?(y(),b("div",{key:0,class:"fixed inset-0 modal z-[100] flex items-center justify-center p-4",onClick:U(i,["self"])},[h("div",ke,[h("div",xe,[v[0]||(v[0]=h("div",{class:"flex-shrink-0 w-12 h-12 bg-gradient-to-br from-amber-500 to-amber-600 rounded-xl flex items-center justify-center"},[h("i",{class:"fas fa-exclamation-triangle text-white text-lg"})],-1)),h("div",Ce,[h("h3",Ie,T(n.value),1),h("div",Le,T(r.value),1)])]),h("div",Se,[h("button",{class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3",disabled:o.value,onClick:i},T(p.value),9,Re),h("button",{class:R(["btn btn-warning px-6 py-3",{"opacity-50 cursor-not-allowed":o.value}]),disabled:o.value,onClick:d},[o.value?(y(),b("div",Oe)):x("",!0),X(" "+T(a.value),1)],10,Ve)])])])):x("",!0)]),_:1})]))}},De=O($e,[["__scopeId","data-v-bdb20ffd"]]),qe={id:"app"},Ne={__name:"App",setup(s){const t=B(),e=_(),o=_();return V(()=>{t.checkAuth(),t.loadOemSettings()}),(n,r)=>{const a=Y("router-view");return y(),b("div",qe,[k(a),k(Ae,{ref_key:"toastRef",ref:e},null,512),k(De,{ref_key:"confirmRef",ref:o},null,512)])}}},Ue=O(Ne,[["__scopeId","data-v-5cba45f5"]]),L=Z(Ue),ze=ee();L.use(ze);L.use(C);L.use(te,{locale:oe});L.mount("#app");export{O as _,A as a,B as u};
+const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/LoginView-BkyYshFQ.js","assets/vue-vendor-CKToUHZx.js","assets/element-plus-B8Fs_0jW.js","assets/vendor-BDiMbLwQ.js","assets/element-plus-CPnoEkWW.css","assets/LoginView-tn0RQdqM.css","assets/LogoTitle-BiOf3Vkp.css","assets/MainLayout-B_VPCr7N.js","assets/toast-BvwA7Mwb.js","assets/LogoTitle-CCr5FYLm.js","assets/MainLayout-CXiJ2-1D.css","assets/DashboardView-a7p7jSsT.js","assets/chart-Cor9iTVD.js","assets/DashboardView-R6dMwgzw.css","assets/ApiKeysView-Bkj34Z3E.js","assets/ApiKeysView-CID1mfnM.css","assets/AccountsView-DHI8l47P.js","assets/AccountsView-DwS76LKN.css","assets/TutorialView-DmH0Lh6x.js","assets/TutorialView-B16hEjh7.css","assets/SettingsView-Dr_Y0aLV.js","assets/SettingsView-CY0posDI.css","assets/ApiStatsView-CTdd2uJw.js","assets/ApiStatsView-BP2davUr.css"])))=>i.map(i=>d[i]);
+import{aP as K,aQ as W,aR as M,r as _,c as S,q as V,V as D,I as q,z as h,x as b,ac as F,Q as G,a5 as N,y,C as R,L as x,P as T,Y as U,B as H,R as k,J,T as Q,O as X,av as Y,aM as Z,aS as ee}from"./vue-vendor-CKToUHZx.js";import{i as te,z as oe}from"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const r of n)if(r.type==="childList")for(const a of r.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&o(a)}).observe(document,{childList:!0,subtree:!0});function e(n){const r={};return n.integrity&&(r.integrity=n.integrity),n.referrerPolicy&&(r.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?r.credentials="include":n.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function o(n){if(n.ep)return;n.ep=!0;const r=e(n);fetch(n.href,r)}})();const se="modulepreload",ne=function(s){return"/admin-next/"+s},$={},w=function(t,e,o){let n=Promise.resolve();if(e&&e.length>0){document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),p=(a==null?void 0:a.nonce)||(a==null?void 0:a.getAttribute("nonce"));n=Promise.allSettled(e.map(c=>{if(c=ne(c),c in $)return;$[c]=!0;const l=c.endsWith(".css"),d=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${d}`))return;const i=document.createElement("link");if(i.rel=l?"stylesheet":se,l||(i.as="script"),i.crossOrigin="",i.href=c,p&&i.setAttribute("nonce",p),document.head.appendChild(i),l)return new Promise((m,f)=>{i.addEventListener("load",m),i.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${c}`)))})}))}function r(a){const p=new Event("vite:preloadError",{cancelable:!0});if(p.payload=a,window.dispatchEvent(p),!p.defaultPrevented)throw a}return n.then(a=>{for(const p of a||[])p.status==="rejected"&&r(p.reason);return t().catch(r)})},I={basePath:"/admin-next/",apiPrefix:""};function ae(s=""){return s&&!s.startsWith("/")&&(s="/"+s),I.basePath+(s.startsWith("#")?s:"#"+s)}function re(){return ae("/login")}const ie=()=>w(()=>import("./LoginView-BkyYshFQ.js"),__vite__mapDeps([0,1,2,3,4,5,6])),E=()=>w(()=>import("./MainLayout-B_VPCr7N.js"),__vite__mapDeps([7,1,8,9,6,2,3,4,10])),ce=()=>w(()=>import("./DashboardView-a7p7jSsT.js"),__vite__mapDeps([11,2,1,3,4,8,12,13])),le=()=>w(()=>import("./ApiKeysView-Bkj34Z3E.js"),__vite__mapDeps([14,2,1,3,4,8,15])),ue=()=>w(()=>import("./AccountsView-DHI8l47P.js"),__vite__mapDeps([16,1,8,2,3,4,17])),de=()=>w(()=>import("./TutorialView-DmH0Lh6x.js"),__vite__mapDeps([18,1,2,3,4,19])),fe=()=>w(()=>import("./SettingsView-Dr_Y0aLV.js"),__vite__mapDeps([20,1,8,2,3,4,21])),he=()=>w(()=>import("./ApiStatsView-CTdd2uJw.js"),__vite__mapDeps([22,1,9,6,3,18,2,4,19,23])),me=[{path:"/",redirect:()=>{const s=window.location.pathname,t=I.basePath.replace(/\/$/,"");return s===t||s===t+"/","/api-stats"}},{path:"/login",name:"Login",component:ie,meta:{requiresAuth:!1}},{path:"/api-stats",name:"ApiStats",component:he,meta:{requiresAuth:!1}},{path:"/dashboard",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Dashboard",component:ce}]},{path:"/api-keys",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"ApiKeys",component:le}]},{path:"/accounts",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Accounts",component:ue}]},{path:"/tutorial",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Tutorial",component:de}]},{path:"/settings",component:E,meta:{requiresAuth:!0},children:[{path:"",name:"Settings",component:fe}]},{path:"/:pathMatch(.*)*",redirect:"/api-stats"}],C=K({history:W(I.basePath),routes:me});C.beforeEach((s,t,e)=>{const o=B();if(console.log("路由导航:",{to:s.path,from:t.path,fullPath:s.fullPath,requiresAuth:s.meta.requiresAuth,isAuthenticated:o.isAuthenticated}),s.path===t.path&&s.fullPath===t.fullPath)return e();s.path==="/api-stats"||s.path.startsWith("/api-stats")?e():s.meta.requiresAuth&&!o.isAuthenticated?e("/login"):s.path==="/login"&&o.isAuthenticated?e("/dashboard"):e()});const z=I.apiPrefix;function P(s){return s.startsWith("/")||(s="/"+s),z+s}class pe{constructor(){this.baseURL=z}getAuthToken(){return localStorage.getItem("authToken")||null}buildConfig(t={}){const e={headers:{"Content-Type":"application/json",...t.headers},...t},o=this.getAuthToken();return o&&(e.headers.Authorization=`Bearer ${o}`),e}async handleResponse(t){if(t.status===401){const o=window.location.pathname+window.location.hash;throw o.includes("/login")||o.endsWith("/")||(localStorage.removeItem("authToken"),window.location.href=re()),new Error("Unauthorized")}const e=t.headers.get("content-type");if(e&&e.includes("application/json")){const o=await t.json();if(!t.ok)throw new Error(o.message||`HTTP ${t.status}`);return o}if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);return t}async get(t,e={}){const o=P(t),n=this.buildConfig({...e,method:"GET"});try{const r=await fetch(o,n);return await this.handleResponse(r)}catch(r){throw console.error("API GET Error:",r),r}}async post(t,e=null,o={}){const n=P(t),r=this.buildConfig({...o,method:"POST",body:e?JSON.stringify(e):void 0});try{const a=await fetch(n,r);return await this.handleResponse(a)}catch(a){throw console.error("API POST Error:",a),a}}async put(t,e=null,o={}){const n=P(t),r=this.buildConfig({...o,method:"PUT",body:e?JSON.stringify(e):void 0});try{const a=await fetch(n,r);return await this.handleResponse(a)}catch(a){throw console.error("API PUT Error:",a),a}}async delete(t,e={}){const o=P(t),n=this.buildConfig({...e,method:"DELETE"});try{const r=await fetch(o,n);return await this.handleResponse(r)}catch(r){throw console.error("API DELETE Error:",r),r}}}const A=new pe,B=M("auth",()=>{const s=_(!1),t=_(localStorage.getItem("authToken")||""),e=_(""),o=_(""),n=_(!1),r=_({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",faviconData:""}),a=_(!0),p=S(()=>!!t.value&&s.value),c=S(()=>t.value),l=S(()=>({username:e.value}));async function d(u){n.value=!0,o.value="";try{const g=await A.post("/web/auth/login",u);g.success?(t.value=g.token,e.value=g.username||u.username,s.value=!0,localStorage.setItem("authToken",g.token),await C.push("/dashboard")):o.value=g.message||"登录失败"}catch(g){o.value=g.message||"登录失败,请检查用户名和密码"}finally{n.value=!1}}function i(){s.value=!1,t.value="",e.value="",localStorage.removeItem("authToken"),C.push("/login")}function m(){t.value&&(s.value=!0,f())}async function f(){try{const u=await A.get("/web/auth/user");u.success&&u.user&&(e.value=u.user.username),(await A.get("/admin/dashboard")).success||i()}catch{i()}}async function v(){a.value=!0;try{const u=await A.get("/admin/oem-settings");if(u.success&&u.data){if(r.value={...r.value,...u.data},u.data.siteIconData||u.data.siteIcon){const g=document.querySelector("link[rel*='icon']")||document.createElement("link");g.type="image/x-icon",g.rel="shortcut icon",g.href=u.data.siteIconData||u.data.siteIcon,document.getElementsByTagName("head")[0].appendChild(g)}u.data.siteName&&(document.title=`${u.data.siteName} - 管理后台`)}}catch(u){console.error("加载OEM设置失败:",u)}finally{a.value=!1}}return{isLoggedIn:s,authToken:t,username:e,loginError:o,loginLoading:n,oemSettings:r,oemLoading:a,isAuthenticated:p,token:c,user:l,login:d,logout:i,checkAuth:m,loadOemSettings:v}}),O=(s,t)=>{const e=s.__vccOpts||s;for(const[o,n]of t)e[o]=n;return e},_e={class:"toast-container"},ge=["onClick"],ve={class:"toast-content"},ye={class:"toast-icon"},we={class:"toast-body"},be={key:0,class:"toast-title"},Te={class:"toast-message"},Ee=["onClick"],Pe={__name:"ToastNotification",setup(s,{expose:t}){const e=_([]);let o=0;const n=l=>{const d={success:"fas fa-check-circle",error:"fas fa-exclamation-circle",warning:"fas fa-exclamation-triangle",info:"fas fa-info-circle"};return d[l]||d.info},r=(l,d="info",i=null,m=5e3)=>{const f=++o,v={id:f,message:l,type:d,title:i,duration:m,isVisible:!1};return e.value.push(v),setTimeout(()=>{v.isVisible=!0},10),m>0&&setTimeout(()=>{a(f)},m),f},a=l=>{const d=e.value.findIndex(i=>i.id===l);if(d>-1){const i=e.value[d];i.isVisible=!1,setTimeout(()=>{const m=e.value.findIndex(f=>f.id===l);m>-1&&e.value.splice(m,1)},300)}},p=()=>{e.value.forEach(l=>{l.isVisible=!1}),setTimeout(()=>{e.value.length=0},300)},c=(l,d="info",i=null,m=5e3)=>r(l,d,i,m);return V(()=>{window.showToast=c}),D(()=>{window.showToast===c&&delete window.showToast}),t({showToast:c,removeToast:a,clearAllToasts:p}),(l,d)=>(y(),q(N,{to:"body"},[h("div",_e,[(y(!0),b(G,null,F(e.value,i=>(y(),b("div",{key:i.id,class:R(["toast",`toast-${i.type}`,i.isVisible?"toast-show":"toast-hide"]),onClick:m=>a(i.id)},[h("div",ve,[h("div",ye,[h("i",{class:R(n(i.type))},null,2)]),h("div",we,[i.title?(y(),b("div",be,T(i.title),1)):x("",!0),h("div",Te,T(i.message),1)]),h("button",{class:"toast-close",onClick:U(m=>a(i.id),["stop"])},d[0]||(d[0]=[h("i",{class:"fas fa-times"},null,-1)]),8,Ee)]),i.duration>0?(y(),b("div",{key:0,class:"toast-progress",style:H({animationDuration:`${i.duration}ms`})},null,4)):x("",!0)],10,ge))),128))])]))}},Ae=O(Pe,[["__scopeId","data-v-1a3ab19b"]]),ke={class:"modal-content w-full max-w-md p-6 mx-auto"},xe={class:"flex items-start gap-4 mb-6"},Ce={class:"flex-1"},Ie={class:"text-lg font-semibold text-gray-900 mb-2"},Le={class:"text-gray-600 leading-relaxed whitespace-pre-line"},Se={class:"flex items-center justify-end gap-3"},Re=["disabled"],Ve=["disabled"],Oe={key:0,class:"loading-spinner mr-2"},$e={__name:"ConfirmDialog",setup(s,{expose:t}){const e=_(!1),o=_(!1),n=_(""),r=_(""),a=_("确认"),p=_("取消");let c=null;const l=(f,v,u="确认",g="取消")=>new Promise(j=>{n.value=f,r.value=v,a.value=u,p.value=g,e.value=!0,o.value=!1,c=j}),d=()=>{o.value||(o.value=!0,setTimeout(()=>{e.value=!1,o.value=!1,c&&(c(!0),c=null)},200))},i=()=>{o.value||(e.value=!1,c&&(c(!1),c=null))},m=f=>{e.value&&(f.key==="Escape"?i():f.key==="Enter"&&!f.shiftKey&&!f.ctrlKey&&!f.altKey&&d())};return V(()=>{window.showConfirm=l,document.addEventListener("keydown",m)}),D(()=>{window.showConfirm===l&&delete window.showConfirm,document.removeEventListener("keydown",m)}),t({showConfirm:l}),(f,v)=>(y(),q(N,{to:"body"},[k(Q,{name:"modal",appear:""},{default:J(()=>[e.value?(y(),b("div",{key:0,class:"fixed inset-0 modal z-[100] flex items-center justify-center p-4",onClick:U(i,["self"])},[h("div",ke,[h("div",xe,[v[0]||(v[0]=h("div",{class:"flex-shrink-0 w-12 h-12 bg-gradient-to-br from-amber-500 to-amber-600 rounded-xl flex items-center justify-center"},[h("i",{class:"fas fa-exclamation-triangle text-white text-lg"})],-1)),h("div",Ce,[h("h3",Ie,T(n.value),1),h("div",Le,T(r.value),1)])]),h("div",Se,[h("button",{class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3",disabled:o.value,onClick:i},T(p.value),9,Re),h("button",{class:R(["btn btn-warning px-6 py-3",{"opacity-50 cursor-not-allowed":o.value}]),disabled:o.value,onClick:d},[o.value?(y(),b("div",Oe)):x("",!0),X(" "+T(a.value),1)],10,Ve)])])])):x("",!0)]),_:1})]))}},De=O($e,[["__scopeId","data-v-bdb20ffd"]]),qe={id:"app"},Ne={__name:"App",setup(s){const t=B(),e=_(),o=_();return V(()=>{t.checkAuth(),t.loadOemSettings()}),(n,r)=>{const a=Y("router-view");return y(),b("div",qe,[k(a),k(Ae,{ref_key:"toastRef",ref:e},null,512),k(De,{ref_key:"confirmRef",ref:o},null,512)])}}},Ue=O(Ne,[["__scopeId","data-v-5cba45f5"]]),L=Z(Ue),ze=ee();L.use(ze);L.use(C);L.use(te,{locale:oe});L.mount("#app");export{O as _,A as a,B as u};
diff --git a/web/admin-spa/dist/index.html b/web/admin-spa/dist/index.html
index 42950ddf..97114ccd 100644
--- a/web/admin-spa/dist/index.html
+++ b/web/admin-spa/dist/index.html
@@ -18,7 +18,7 @@
-
+