mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 20:03:54 +00:00
16 lines
90 KiB
JavaScript
16 lines
90 KiB
JavaScript
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('<div class="flex items-start gap-3 mb-3"><div class="w-8 h-8 bg-gray-500 rounded-lg flex items-center justify-center flex-shrink-0"><i class="fas fa-server text-white text-sm"></i></div><div class="flex-1"><p class="text-sm text-gray-700"> 配置代理以访问受限的网络资源。支持 SOCKS5 和 HTTP 代理。 </p><p class="text-xs text-gray-500 mt-1"> 请确保代理服务器稳定可用,否则会影响账户的正常使用。 </p></div></div>',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('<div class="bg-white/80 rounded-lg p-4 border border-blue-300"><div class="flex items-start gap-3"><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"> 2 </div><div class="flex-1"><p class="font-medium text-blue-900 mb-2"> 在浏览器中打开链接并完成授权 </p><p class="text-sm text-blue-700 mb-2"> 请在新标签页中打开授权链接,登录您的 Claude 账户并授权。 </p><div class="bg-yellow-50 p-3 rounded border border-yellow-300"><p class="text-xs text-yellow-800"><i class="fas fa-exclamation-triangle mr-1"></i><strong>注意:</strong>如果您设置了代理,请确保浏览器也使用相同的代理访问授权页面。 </p></div></div></div></div>',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('<div class="bg-white/80 rounded-lg p-4 border border-green-300"><div class="flex items-start gap-3"><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"> 2 </div><div class="flex-1"><p class="font-medium text-green-900 mb-2"> 在浏览器中打开链接并完成授权 </p><ol class="text-sm text-green-800 space-y-1 list-decimal list-inside mb-3"><li>点击上方的授权链接,在新页面中完成Google账号登录</li><li>点击“登录”按钮后可能会加载很慢(这是正常的)</li><li>如果超过1分钟还在加载,请按 F5 刷新页面</li><li>授权完成后会跳转到 http://localhost:45462 (可能显示无法访问)</li></ol><div class="bg-green-100 p-3 rounded border border-green-300"><p class="text-xs text-green-700"><i class="fas fa-lightbulb mr-1"></i><strong>提示:</strong>如果页面一直无法跳转,可以打开浏览器开发者工具(F12),F5刷新一下授权页再点击页面的登录按钮,在“网络”标签中找到以 localhost:45462 开头的请求,复制其完整URL。 </p></div></div></div></div>',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('<div class="mt-2 space-y-1"><p class="text-xs text-gray-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> 支持粘贴完整链接,系统会自动提取授权码 </p><p class="text-xs text-gray-600"><i class="fas fa-check-circle text-green-500 mr-1"></i> 也可以直接粘贴授权码(code参数的值) </p></div>',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("项目编号未填写",`您尚未填写项目编号。
|
||
|
||
如果您的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("项目编号未填写",`您尚未填写项目编号。
|
||
|
||
如果您的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(`
|
||
`).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),D<N?m.value==="asc"?-1:1:D>N?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}" 吗?
|
||
|
||
此操作不可恢复。`,"删除","取消"))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('<option value="name" data-v-ab3ae7fd> 按名称排序 </option><option value="dailyTokens" data-v-ab3ae7fd> 按今日Token排序 </option><option value="dailyRequests" data-v-ab3ae7fd> 按今日请求数排序 </option><option value="totalTokens" data-v-ab3ae7fd> 按总Token排序 </option><option value="lastUsed" data-v-ab3ae7fd> 按最后使用排序 </option>',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};
|