mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 09:38:02 +00:00
10 lines
73 KiB
JavaScript
10 lines
73 KiB
JavaScript
import{r as C,aR as Ue,o as z,V as Ve,x as u,y as i,z as e,L as $,K as g,al as ye,aY as se,aX as he,aq as V,aZ as Ie,C as L,O as b,c as le,P as I,I as oe,a5 as $e,R as ue,an as Y,Q as de,ac as pe,u as N,q as Se,Y as je,B as ge}from"./vue-vendor-CKToUHZx.js";import{s as S}from"./toast-BvwA7Mwb.js";import{a as P,_ as Me}from"./index-9AMT1Op2.js";import"./element-plus-B8Fs_0jW.js";import"./vendor-BDiMbLwQ.js";const ie=C(!1),be=C({title:"",message:"",confirmText:"继续",cancelText:"取消"}),X=C(null);function Ce(){return{showConfirmModal:ie,confirmOptions:be,showConfirm:(w,d,K="继续",j="取消")=>new Promise(T=>{be.value={title:w,message:d,confirmText:K,cancelText:j},X.value=T,ie.value=!0}),handleConfirm:()=>{ie.value=!1,X.value&&(X.value(!0),X.value=null)},handleCancel:()=>{ie.value=!1,X.value&&(X.value(!1),X.value=null)}}}const Te=Ue("accounts",()=>{const D=C([]),W=C([]),p=C([]),w=C(!1),d=C(null),K=C(""),j=C("asc"),T=async()=>{w.value=!0,d.value=null;try{const f=await P.get("/admin/claude-accounts");if(f.success)D.value=f.data||[];else throw new Error(f.message||"获取Claude账户失败")}catch(f){throw d.value=f.message,f}finally{w.value=!1}},A=async()=>{w.value=!0,d.value=null;try{const f=await P.get("/admin/claude-console-accounts");if(f.success)W.value=f.data||[];else throw new Error(f.message||"获取Claude Console账户失败")}catch(f){throw d.value=f.message,f}finally{w.value=!1}},y=async()=>{w.value=!0,d.value=null;try{const f=await P.get("/admin/gemini-accounts");if(f.success)p.value=f.data||[];else throw new Error(f.message||"获取Gemini账户失败")}catch(f){throw d.value=f.message,f}finally{w.value=!1}};return{claudeAccounts:D,claudeConsoleAccounts:W,geminiAccounts:p,loading:w,error:d,sortBy:K,sortOrder:j,fetchClaudeAccounts:T,fetchClaudeConsoleAccounts:A,fetchGeminiAccounts:y,fetchAllAccounts:async()=>{w.value=!0,d.value=null;try{await Promise.all([T(),A(),y()])}catch(f){throw d.value=f.message,f}finally{w.value=!1}},createClaudeAccount:async f=>{w.value=!0,d.value=null;try{const m=await P.post("/admin/claude-accounts",f);if(m.success)return await T(),m.data;throw new Error(m.message||"创建Claude账户失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},createClaudeConsoleAccount:async f=>{w.value=!0,d.value=null;try{const m=await P.post("/admin/claude-console-accounts",f);if(m.success)return await A(),m.data;throw new Error(m.message||"创建Claude Console账户失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},createGeminiAccount:async f=>{w.value=!0,d.value=null;try{const m=await P.post("/admin/gemini-accounts",f);if(m.success)return await y(),m.data;throw new Error(m.message||"创建Gemini账户失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},updateClaudeAccount:async(f,m)=>{w.value=!0,d.value=null;try{const k=await P.put(`/admin/claude-accounts/${f}`,m);if(k.success)return await T(),k;throw new Error(k.message||"更新Claude账户失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},updateClaudeConsoleAccount:async(f,m)=>{w.value=!0,d.value=null;try{const k=await P.put(`/admin/claude-console-accounts/${f}`,m);if(k.success)return await A(),k;throw new Error(k.message||"更新Claude Console账户失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},updateGeminiAccount:async(f,m)=>{w.value=!0,d.value=null;try{const k=await P.put(`/admin/gemini-accounts/${f}`,m);if(k.success)return await y(),k;throw new Error(k.message||"更新Gemini账户失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},toggleAccount:async(f,m)=>{w.value=!0,d.value=null;try{let k;f==="claude"?k=`/admin/claude-accounts/${m}/toggle`:f==="claude-console"?k=`/admin/claude-console-accounts/${m}/toggle`:k=`/admin/gemini-accounts/${m}/toggle`;const H=await P.put(k);if(H.success)return f==="claude"?await T():f==="claude-console"?await A():await y(),H;throw new Error(H.message||"切换状态失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},deleteAccount:async(f,m)=>{w.value=!0,d.value=null;try{let k;f==="claude"?k=`/admin/claude-accounts/${m}`:f==="claude-console"?k=`/admin/claude-console-accounts/${m}`:k=`/admin/gemini-accounts/${m}`;const H=await P.delete(k);if(H.success)return f==="claude"?await T():f==="claude-console"?await A():await y(),H;throw new Error(H.message||"删除失败")}catch(k){throw d.value=k.message,k}finally{w.value=!1}},refreshClaudeToken:async f=>{w.value=!0,d.value=null;try{const m=await P.post(`/admin/claude-accounts/${f}/refresh`);if(m.success)return await T(),m;throw new Error(m.message||"Token刷新失败")}catch(m){throw d.value=m.message,m}finally{w.value=!1}},generateClaudeAuthUrl:async f=>{try{const m=await P.post("/admin/claude-accounts/generate-auth-url",f);if(m.success)return m.data;throw new Error(m.message||"生成授权URL失败")}catch(m){throw d.value=m.message,m}},exchangeClaudeCode:async f=>{try{const m=await P.post("/admin/claude-accounts/exchange-code",f);if(m.success)return m.data;throw new Error(m.message||"交换授权码失败")}catch(m){throw d.value=m.message,m}},generateGeminiAuthUrl:async f=>{try{const m=await P.post("/admin/gemini-accounts/generate-auth-url",f);if(m.success)return m.data;throw new Error(m.message||"生成授权URL失败")}catch(m){throw d.value=m.message,m}},exchangeGeminiCode:async f=>{try{const m=await P.post("/admin/gemini-accounts/exchange-code",f);if(m.success)return m.data;throw new Error(m.message||"交换授权码失败")}catch(m){throw d.value=m.message,m}},sortAccounts:f=>{K.value===f?j.value=j.value==="asc"?"desc":"asc":(K.value=f,j.value="asc")},reset:()=>{D.value=[],W.value=[],p.value=[],w.value=!1,d.value=null,K.value="",j.value="asc"}}}),Ke={class:"space-y-4"},Pe={class:"flex items-center justify-between"},Re={class:"flex items-center cursor-pointer"},Ge={key:0,class:"bg-gray-50 p-4 rounded-lg border border-gray-200 space-y-4"},Le={class:"grid grid-cols-2 gap-4"},De={class:"space-y-4"},Oe={class:"flex items-center"},Ee={key:0,class:"grid grid-cols-2 gap-4"},ze={class:"relative"},We=["type"],we={__name:"ProxyConfig",props:{modelValue:{type:Object,default:()=>({enabled:!1,type:"socks5",host:"",port:"",username:"",password:""})}},emits:["update:modelValue"],setup(D,{emit:W}){const p=D,w=W,d=C({...p.modelValue}),K=C(!!(d.value.username||d.value.password)),j=C(!1);z(()=>p.modelValue,y=>{JSON.stringify(y)!==JSON.stringify(d.value)&&(d.value={...y},K.value=!!(y.username||y.password))},{deep:!0}),z(()=>d.value.enabled,y=>{A()}),z(()=>d.value.type,y=>{A()}),z(()=>d.value.host,y=>{A()}),z(()=>d.value.port,y=>{A()}),z(()=>d.value.username,y=>{A()}),z(()=>d.value.password,y=>{A()}),z(K,y=>{y||(d.value.username="",d.value.password="",A())});let T=null;function A(){T&&clearTimeout(T),T=setTimeout(()=>{const y={...d.value};K.value||(y.username="",y.password=""),w("update:modelValue",y)},100)}return Ve(()=>{T&&clearTimeout(T)}),(y,x)=>(i(),u("div",Ke,[e("div",Pe,[x[9]||(x[9]=e("h4",{class:"text-sm font-semibold text-gray-700"}," 代理设置 (可选) ",-1)),e("label",Re,[g(e("input",{"onUpdate:modelValue":x[0]||(x[0]=M=>d.value.enabled=M),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[ye,d.value.enabled]]),x[8]||(x[8]=e("span",{class:"ml-2 text-sm text-gray-700"},"启用代理",-1))])]),d.value.enabled?(i(),u("div",Ge,[x[17]||(x[17]=se('<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,[x[11]||(x[11]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"代理类型",-1)),g(e("select",{"onUpdate:modelValue":x[1]||(x[1]=M=>d.value.type=M),class:"form-input w-full"},x[10]||(x[10]=[e("option",{value:"socks5"}," SOCKS5 ",-1),e("option",{value:"http"}," HTTP ",-1),e("option",{value:"https"}," HTTPS ",-1)]),512),[[he,d.value.type]])]),e("div",Le,[e("div",null,[x[12]||(x[12]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"主机地址",-1)),g(e("input",{"onUpdate:modelValue":x[2]||(x[2]=M=>d.value.host=M),type:"text",placeholder:"例如: 192.168.1.100",class:"form-input w-full"},null,512),[[V,d.value.host]])]),e("div",null,[x[13]||(x[13]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"端口",-1)),g(e("input",{"onUpdate:modelValue":x[3]||(x[3]=M=>d.value.port=M),type:"number",placeholder:"例如: 1080",class:"form-input w-full"},null,512),[[V,d.value.port]])])]),e("div",De,[e("div",Oe,[g(e("input",{id:"proxyAuth","onUpdate:modelValue":x[4]||(x[4]=M=>K.value=M),type:"checkbox",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[ye,K.value]]),x[14]||(x[14]=e("label",{for:"proxyAuth",class:"ml-2 text-sm text-gray-700 cursor-pointer"}," 需要身份验证 ",-1))]),K.value?(i(),u("div",Ee,[e("div",null,[x[15]||(x[15]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"用户名",-1)),g(e("input",{"onUpdate:modelValue":x[5]||(x[5]=M=>d.value.username=M),type:"text",placeholder:"代理用户名",class:"form-input w-full"},null,512),[[V,d.value.username]])]),e("div",null,[x[16]||(x[16]=e("label",{class:"block text-sm font-medium text-gray-700 mb-2"},"密码",-1)),e("div",ze,[g(e("input",{"onUpdate:modelValue":x[6]||(x[6]=M=>d.value.password=M),type:j.value?"text":"password",placeholder:"代理密码",class:"form-input w-full pr-10"},null,8,We),[[Ie,d.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:x[7]||(x[7]=M=>j.value=!j.value)},[e("i",{class:L(j.value?"fas fa-eye-slash":"fas fa-eye")},null,2)])])])])):$("",!0)]),x[18]||(x[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,"提示:"),b("代理设置将用于所有与此账户相关的API请求。请确保代理服务器支持HTTPS流量转发。 ")])],-1))])):$("",!0)]))}},qe={class:"space-y-6"},Ne={key:0},Be={class:"bg-blue-50 p-6 rounded-lg border border-blue-200"},He={class:"flex items-start gap-4"},Fe={class:"flex-1"},_e={class:"space-y-4"},Je={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},Ye={class:"flex items-start gap-3"},Qe={class:"flex-1"},Xe=["disabled"],Ze={key:0,class:"fas fa-link mr-2"},et={key:1,class:"loading-spinner mr-2"},tt={key:1,class:"space-y-3"},st={class:"flex items-center gap-2"},lt=["value"],ot={class:"bg-white/80 rounded-lg p-4 border border-blue-300"},at={class:"flex items-start gap-3"},nt={class:"flex-1"},rt={class:"space-y-3"},it={key:1},ut={class:"bg-green-50 p-6 rounded-lg border border-green-200"},dt={class:"flex items-start gap-4"},pt={class:"flex-1"},ct={class:"space-y-4"},mt={class:"bg-white/80 rounded-lg p-4 border border-green-300"},ft={class:"flex items-start gap-3"},xt={class:"flex-1"},vt=["disabled"],yt={key:0,class:"fas fa-link mr-2"},gt={key:1,class:"loading-spinner mr-2"},bt={key:1,class:"space-y-3"},wt={class:"flex items-center gap-2"},kt=["value"],ht={class:"bg-white/80 rounded-lg p-4 border border-green-300"},$t={class:"flex items-start gap-3"},Ct={class:"flex-1"},Tt={class:"space-y-3"},At={class:"flex gap-3 pt-4"},Ut=["disabled"],Vt={key:0,class:"loading-spinner mr-2"},It={__name:"OAuthFlow",props:{platform:{type:String,required:!0},proxy:{type:Object,default:null}},emits:["success","back"],setup(D,{emit:W}){const p=D,w=W,d=Te(),K=C(!1),j=C(!1),T=C(""),A=C(""),y=C(!1),x=C(""),M=le(()=>T.value&&A.value.trim());z(A,U=>{if(!U||typeof U!="string")return;const r=U.trim();if(!r)return;if(r.startsWith("http://")||r.startsWith("https://"))if(r.startsWith("http://localhost:45462"))try{const _=new URL(r).searchParams.get("code");_?(A.value=_,S("成功提取授权码!","success"),console.log("Successfully extracted authorization code from URL")):S("URL 中未找到授权码参数,请检查链接是否正确","error")}catch(J){console.error("Failed to parse URL:",J),S("链接格式错误,请检查是否为完整的 URL","error")}else if(p.platform==="gemini")try{const _=new URL(r).searchParams.get("code");_&&(A.value=_,S("成功提取授权码!","success"))}catch{}else S("请粘贴以 http://localhost:45462 开头的链接","error")});const O=async()=>{var U;K.value=!0;try{const r=(U=p.proxy)!=null&&U.enabled?{proxy:{type:p.proxy.type,host:p.proxy.host,port:parseInt(p.proxy.port),username:p.proxy.username||null,password:p.proxy.password||null}}:{};if(p.platform==="claude"){const v=await d.generateClaudeAuthUrl(r);T.value=v.authUrl,x.value=v.sessionId}else if(p.platform==="gemini"){const v=await d.generateGeminiAuthUrl(r);T.value=v.authUrl,x.value=v.sessionId}}catch(r){S(r.message||"生成授权链接失败","error")}finally{K.value=!1}},R=()=>{T.value="",A.value="",O()},Q=async()=>{try{await navigator.clipboard.writeText(T.value),y.value=!0,S("链接已复制","success"),setTimeout(()=>{y.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),y.value=!0,S("链接已复制","success"),setTimeout(()=>{y.value=!1},2e3)}},s=async()=>{var U;if(M.value){j.value=!0;try{let r={};p.platform==="claude"?r={sessionId:x.value,callbackUrl:A.value.trim()}:p.platform==="gemini"&&(r={code:A.value.trim(),sessionId:x.value}),(U=p.proxy)!=null&&U.enabled&&(r.proxy={type:p.proxy.type,host:p.proxy.host,port:parseInt(p.proxy.port),username:p.proxy.username||null,password:p.proxy.password||null});let v;p.platform==="claude"?v=await d.exchangeClaudeCode(r):p.platform==="gemini"&&(v=await d.exchangeGeminiCode(r)),w("success",v)}catch(r){S(r.message||"授权失败,请检查授权码是否正确","error")}finally{j.value=!1}}};return(U,r)=>(i(),u("div",qe,[D.platform==="claude"?(i(),u("div",Ne,[e("div",Be,[e("div",He,[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",Fe,[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",_e,[e("div",Je,[e("div",Ye,[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",Qe,[r[4]||(r[4]=e("p",{class:"font-medium text-blue-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(i(),u("div",tt,[e("div",st,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,lt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:Q},[e("i",{class:L(y.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),b("重新生成 ",-1)]))])):(i(),u("button",{key:0,disabled:K.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:O},[K.value?(i(),u("div",et)):(i(),u("i",Ze)),b(" "+I(K.value?"生成中...":"生成授权链接"),1)],8,Xe))])])]),r[11]||(r[11]=se('<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",ot,[e("div",at,[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",nt,[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"},[b(" 授权完成后,页面会显示一个 "),e("strong",null,"Authorization Code"),b(",请将其复制并粘贴到下方输入框: ")],-1)),e("div",rt,[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"}),b("Authorization Code ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[0]||(r[0]=v=>A.value=v),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴从Claude页面获取的Authorization Code..."},null,512),[[V,A.value]])]),r[7]||(r[7]=e("p",{class:"text-xs text-gray-500 mt-2"},[e("i",{class:"fas fa-info-circle mr-1"}),b(" 请粘贴从Claude页面复制的Authorization Code ")],-1))])])])])])])])])])):D.platform==="gemini"?(i(),u("div",it,[e("div",ut,[e("div",dt,[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",pt,[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",mt,[e("div",ft,[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",xt,[r[16]||(r[16]=e("p",{class:"font-medium text-green-900 mb-2"}," 点击下方按钮生成授权链接 ",-1)),T.value?(i(),u("div",bt,[e("div",wt,[e("input",{type:"text",value:T.value,readonly:"",class:"form-input flex-1 text-xs font-mono bg-gray-50"},null,8,kt),e("button",{class:"px-3 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors",title:"复制链接",onClick:Q},[e("i",{class:L(y.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),b("重新生成 ",-1)]))])):(i(),u("button",{key:0,disabled:K.value,class:"btn btn-primary px-4 py-2 text-sm",onClick:O},[K.value?(i(),u("div",gt)):(i(),u("i",yt)),b(" "+I(K.value?"生成中...":"生成授权链接"),1)],8,vt))])])]),r[23]||(r[23]=se('<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",ht,[e("div",$t,[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",Ct,[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",Tt,[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"}),b("复制oauth后的链接 ")],-1)),g(e("textarea",{"onUpdate:modelValue":r[1]||(r[1]=v=>A.value=v),rows:"3",class:"form-input w-full resize-none font-mono text-sm",placeholder:"粘贴以 http://localhost:45462 开头的完整链接..."},null,512),[[V,A.value]])]),r[19]||(r[19]=se('<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))])])])])])])])])])):$("",!0),e("div",At,[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]=v=>U.$emit("back"))}," 上一步 "),e("button",{type:"button",disabled:!M.value||j.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:s},[j.value?(i(),u("div",Vt)):$("",!0),b(" "+I(j.value?"验证中...":"完成授权"),1)],8,Ut)])]))}},St={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},jt={class:"modal-content w-full max-w-md p-6 mx-auto"},Mt={class:"flex items-start gap-4 mb-6"},Kt={class:"flex-1"},Pt={class:"text-lg font-bold text-gray-900 mb-2"},Rt={class:"text-gray-600 text-sm leading-relaxed whitespace-pre-line"},Gt={class:"flex gap-3"},Ae={__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(D){return(W,p)=>(i(),oe($e,{to:"body"},[D.show?(i(),u("div",St,[e("div",jt,[e("div",Mt,[p[2]||(p[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",Kt,[e("h3",Pt,I(D.title),1),e("p",Rt,I(D.message),1)])]),e("div",Gt,[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:p[0]||(p[0]=w=>W.$emit("cancel"))},I(D.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:p[1]||(p[1]=w=>W.$emit("confirm"))},I(D.confirmText),1)])])])):$("",!0)]))}},Lt={key:0,class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Dt={class:"modal-content w-full max-w-2xl p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Ot={class:"flex items-center justify-between mb-6"},Et={class:"flex items-center gap-3"},zt={class:"text-xl font-bold text-gray-900"},Wt={key:0,class:"flex items-center justify-center mb-8"},qt={class:"flex items-center space-x-4"},Nt={class:"flex items-center"},Bt={class:"flex items-center"},Ht={key:1},Ft={class:"space-y-6"},_t={key:0},Jt={class:"flex gap-4"},Yt={class:"flex items-center cursor-pointer"},Qt={class:"flex items-center cursor-pointer"},Xt={class:"flex items-center cursor-pointer"},Zt={key:1},es={class:"flex gap-4"},ts={class:"flex items-center cursor-pointer"},ss={class:"flex items-center cursor-pointer"},ls={key:0,class:"text-red-500 text-xs mt-1"},os={class:"flex gap-4"},as={class:"flex items-center cursor-pointer"},ns={class:"flex items-center cursor-pointer"},rs={key:2},is={key:3,class:"space-y-4"},us={key:0,class:"text-red-500 text-xs mt-1"},ds={key:0,class:"text-red-500 text-xs mt-1"},ps={class:"space-y-2 mb-3"},cs=["onUpdate:modelValue"],ms=["onUpdate:modelValue"],fs=["onClick"],xs={class:"mt-3 flex flex-wrap gap-2"},vs={key:4},ys={key:5,class:"space-y-4 bg-blue-50 p-4 rounded-lg border border-blue-200"},gs={class:"flex items-start gap-3 mb-4"},bs={key:0,class:"text-sm text-blue-800 mb-2"},ws={key:1,class:"text-sm text-blue-800 mb-2"},ks={class:"bg-white/80 rounded-lg p-3 mt-2 mb-2 border border-blue-300"},hs={key:0,class:"text-xs text-blue-800"},$s={key:1,class:"text-xs text-blue-800"},Cs={key:0,class:"text-red-500 text-xs mt-1"},Ts={class:"flex gap-3 pt-4"},As=["disabled"],Us=["disabled"],Vs={key:0,class:"loading-spinner mr-2"},Is={key:3,class:"space-y-6"},Ss={class:"flex gap-4"},js={class:"flex items-center cursor-pointer"},Ms={class:"flex items-center cursor-pointer"},Ks={key:0},Ps={key:1},Rs={key:2,class:"space-y-4"},Gs={class:"space-y-2 mb-3"},Ls=["onUpdate:modelValue"],Ds=["onUpdate:modelValue"],Os=["onClick"],Es={class:"mt-3 flex flex-wrap gap-2"},zs={key:3,class:"bg-amber-50 p-4 rounded-lg border border-amber-200"},Ws={class:"space-y-4"},qs={class:"flex gap-3 pt-4"},Ns=["disabled"],Bs={key:0,class:"loading-spinner mr-2"},ke={__name:"AccountForm",props:{account:{type:Object,default:null}},emits:["close","success"],setup(D,{emit:W}){var k,H,re,c,l,o,h,G,B,E;const p=D,w=W,d=Te(),{showConfirmModal:K,confirmOptions:j,showConfirm:T,handleConfirm:A,handleCancel:y}=Ce(),x=le(()=>!!p.account),M=C(!0),O=C(1),R=C(!1),Q=()=>{var n;return(n=p.account)!=null&&n.proxy&&p.account.proxy.host&&p.account.proxy.port?{enabled:!0,type:p.account.proxy.type||"socks5",host:p.account.proxy.host,port:p.account.proxy.port,username:p.account.proxy.username||"",password:p.account.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""}},s=C({platform:((k=p.account)==null?void 0:k.platform)||"claude",addType:"oauth",name:((H=p.account)==null?void 0:H.name)||"",description:((re=p.account)==null?void 0:re.description)||"",accountType:((c=p.account)==null?void 0:c.accountType)||"shared",projectId:((l=p.account)==null?void 0:l.projectId)||"",accessToken:"",refreshToken:"",proxy:Q(),apiUrl:((o=p.account)==null?void 0:o.apiUrl)||"",apiKey:((h=p.account)==null?void 0:h.apiKey)||"",priority:((G=p.account)==null?void 0:G.priority)||50,userAgent:((B=p.account)==null?void 0:B.userAgent)||"",rateLimitDuration:((E=p.account)==null?void 0:E.rateLimitDuration)||60}),U=C([]),r=()=>{var n;(n=p.account)!=null&&n.supportedModels&&(typeof p.account.supportedModels=="object"&&!Array.isArray(p.account.supportedModels)?U.value=Object.entries(p.account.supportedModels).map(([t,a])=>({from:t,to:a})):Array.isArray(p.account.supportedModels)&&(U.value=p.account.supportedModels.map(t=>({from:t,to:t}))))},v=C({name:"",accessToken:"",apiUrl:"",apiKey:""}),J=le(()=>{var n;return((n=s.value.name)==null?void 0:n.trim())&&s.value.platform});le(()=>{var n,t,a;return s.value.addType==="manual"?((n=s.value.name)==null?void 0:n.trim())&&((t=s.value.accessToken)==null?void 0:t.trim()):(a=s.value.name)==null?void 0:a.trim()});const _=async()=>{if(v.value.name="",!J.value){(!s.value.name||s.value.name.trim()==="")&&(v.value.name="请填写账户名称");return}s.value.platform==="gemini"&&O.value===1&&s.value.addType==="oauth"&&(!s.value.projectId||s.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。
|
||
|
||
如果您的Google账号绑定了Google Cloud或被识别为Workspace账号,需要提供项目编号。
|
||
如果您使用的是普通个人账号,可以继续不填写。`,"继续","返回填写")||(O.value=2)},Z=async n=>{R.value=!0;try{const t={name:s.value.name,description:s.value.description,accountType:s.value.accountType,proxy:s.value.proxy.enabled?{type:s.value.proxy.type,host:s.value.proxy.host,port:parseInt(s.value.proxy.port),username:s.value.proxy.username||null,password:s.value.proxy.password||null}:null};s.value.platform==="claude"?(t.claudeAiOauth=n.claudeAiOauth||n,t.priority=s.value.priority||50):s.value.platform==="gemini"&&(t.geminiOauth=n.tokens||n,s.value.projectId&&(t.projectId=s.value.projectId));let a;s.value.platform==="claude"?a=await d.createClaudeAccount(t):a=await d.createGeminiAccount(t),w("success",a)}catch(t){S(t.message||"账户创建失败","error")}finally{R.value=!1}},ae=async()=>{v.value.name="",v.value.accessToken="",v.value.apiUrl="",v.value.apiKey="";let n=!1;if((!s.value.name||s.value.name.trim()==="")&&(v.value.name="请填写账户名称",n=!0),s.value.platform==="claude-console"?((!s.value.apiUrl||s.value.apiUrl.trim()==="")&&(v.value.apiUrl="请填写 API URL",n=!0),(!s.value.apiKey||s.value.apiKey.trim()==="")&&(v.value.apiKey="请填写 API Key",n=!0)):s.value.addType==="manual"&&(!s.value.accessToken||s.value.accessToken.trim()==="")&&(v.value.accessToken="请填写 Access Token",n=!0),!n){R.value=!0;try{const t={name:s.value.name,description:s.value.description,accountType:s.value.accountType,proxy:s.value.proxy.enabled?{type:s.value.proxy.type,host:s.value.proxy.host,port:parseInt(s.value.proxy.port),username:s.value.proxy.username||null,password:s.value.proxy.password||null}:null};if(s.value.platform==="claude"){const q=s.value.refreshToken?6e5:31536e6;t.claudeAiOauth={accessToken:s.value.accessToken,refreshToken:s.value.refreshToken||"",expiresAt:Date.now()+q,scopes:["user:inference"]},t.priority=s.value.priority||50}else if(s.value.platform==="gemini"){const q=s.value.refreshToken?6e5:31536e6;t.geminiOauth={access_token:s.value.accessToken,refresh_token:s.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+q},s.value.projectId&&(t.projectId=s.value.projectId)}else s.value.platform==="claude-console"&&(t.apiUrl=s.value.apiUrl,t.apiKey=s.value.apiKey,t.priority=s.value.priority||50,t.supportedModels=m()||{},t.userAgent=s.value.userAgent||null,t.rateLimitDuration=s.value.rateLimitDuration||60);let a;s.value.platform==="claude"?a=await d.createClaudeAccount(t):s.value.platform==="claude-console"?a=await d.createClaudeConsoleAccount(t):a=await d.createGeminiAccount(t),w("success",a)}catch(t){S(t.message||"账户创建失败","error")}finally{R.value=!1}}},ne=async()=>{if(v.value.name="",!s.value.name||s.value.name.trim()===""){v.value.name="请填写账户名称";return}if(!(s.value.platform==="gemini"&&(!s.value.projectId||s.value.projectId.trim()==="")&&!await T("项目编号未填写",`您尚未填写项目编号。
|
||
|
||
如果您的Google账号绑定了Google Cloud或被识别为Workspace账号,需要提供项目编号。
|
||
如果您使用的是普通个人账号,可以继续不填写。`,"继续保存","返回填写"))){R.value=!0;try{const n={name:s.value.name,description:s.value.description,accountType:s.value.accountType,proxy:s.value.proxy.enabled?{type:s.value.proxy.type,host:s.value.proxy.host,port:parseInt(s.value.proxy.port),username:s.value.proxy.username||null,password:s.value.proxy.password||null}:null};if(s.value.accessToken||s.value.refreshToken){if(p.account.platform==="claude"){const t=s.value.refreshToken?6e5:31536e6;n.claudeAiOauth={accessToken:s.value.accessToken||"",refreshToken:s.value.refreshToken||"",expiresAt:Date.now()+t,scopes:["user:inference"]}}else if(p.account.platform==="gemini"){const t=s.value.refreshToken?6e5:31536e6;n.geminiOauth={access_token:s.value.accessToken||"",refresh_token:s.value.refreshToken||"",scope:"https://www.googleapis.com/auth/cloud-platform",token_type:"Bearer",expiry_date:Date.now()+t}}}p.account.platform==="gemini"&&s.value.projectId&&(n.projectId=s.value.projectId),p.account.platform==="claude"&&(n.priority=s.value.priority||50),p.account.platform==="claude-console"&&(n.apiUrl=s.value.apiUrl,s.value.apiKey&&(n.apiKey=s.value.apiKey),n.priority=s.value.priority||50,n.supportedModels=m()||{},n.userAgent=s.value.userAgent||null,n.rateLimitDuration=s.value.rateLimitDuration||60),p.account.platform==="claude"?await d.updateClaudeAccount(p.account.id,n):p.account.platform==="claude-console"?await d.updateClaudeConsoleAccount(p.account.id,n):await d.updateGeminiAccount(p.account.id,n),w("success")}catch(n){S(n.message||"账户更新失败","error")}finally{R.value=!1}}};z(()=>s.value.name,()=>{var n;v.value.name&&((n=s.value.name)!=null&&n.trim())&&(v.value.name="")}),z(()=>s.value.accessToken,()=>{var n;v.value.accessToken&&((n=s.value.accessToken)!=null&&n.trim())&&(v.value.accessToken="")}),z(()=>s.value.apiUrl,()=>{var n;v.value.apiUrl&&((n=s.value.apiUrl)!=null&&n.trim())&&(v.value.apiUrl="")}),z(()=>s.value.apiKey,()=>{var n;v.value.apiKey&&((n=s.value.apiKey)!=null&&n.trim())&&(v.value.apiKey="")}),z(()=>s.value.platform,n=>{n==="claude-console"&&(s.value.addType="manual")});const ee=()=>{U.value.push({from:"",to:""})},te=n=>{U.value.splice(n,1)},f=(n,t)=>{if(U.value.some(q=>q.from===n)){S(`模型 ${n} 的映射已存在`,"info");return}U.value.push({from:n,to:t}),S(`已添加映射: ${n} → ${t}`,"success")},m=()=>{const n={};return U.value.forEach(t=>{t.from&&t.to&&(n[t.from]=t.to)}),Object.keys(n).length>0?n:null};return z(()=>p.account,n=>{if(n){r();const t=n.proxy&&n.proxy.host&&n.proxy.port?{enabled:!0,type:n.proxy.type||"socks5",host:n.proxy.host,port:n.proxy.port,username:n.proxy.username||"",password:n.proxy.password||""}:{enabled:!1,type:"socks5",host:"",port:"",username:"",password:""};s.value={platform:n.platform,addType:"oauth",name:n.name,description:n.description||"",accountType:n.accountType||"shared",projectId:n.projectId||"",accessToken:"",refreshToken:"",proxy:t,apiUrl:n.apiUrl||"",apiKey:"",priority:n.priority||50,userAgent:n.userAgent||"",rateLimitDuration:n.rateLimitDuration||60}}},{immediate:!0}),r(),(n,t)=>(i(),oe($e,{to:"body"},[M.value?(i(),u("div",Lt,[e("div",Dt,[e("div",Ot,[e("div",Et,[t[45]||(t[45]=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-user-circle text-white"})],-1)),e("h3",zt,I(x.value?"编辑账户":"添加账户"),1)]),e("button",{class:"text-gray-400 hover:text-gray-600 transition-colors",onClick:t[0]||(t[0]=a=>n.$emit("close"))},t[46]||(t[46]=[e("i",{class:"fas fa-times text-xl"},null,-1)]))]),!x.value&&s.value.addType==="oauth"?(i(),u("div",Wt,[e("div",qt,[e("div",Nt,[e("div",{class:L(["w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",O.value>=1?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 1 ",2),t[47]||(t[47]=e("span",{class:"ml-2 text-sm font-medium text-gray-700"},"基本信息",-1))]),t[49]||(t[49]=e("div",{class:"w-8 h-0.5 bg-gray-300"},null,-1)),e("div",Bt,[e("div",{class:L(["w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold",O.value>=2?"bg-blue-500 text-white":"bg-gray-200 text-gray-500"])}," 2 ",2),t[48]||(t[48]=e("span",{class:"ml-2 text-sm font-medium text-gray-700"},"授权认证",-1))])])])):$("",!0),O.value===1&&!x.value?(i(),u("div",Ht,[e("div",Ft,[x.value?$("",!0):(i(),u("div",_t,[t[53]||(t[53]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"平台",-1)),e("div",Jt,[e("label",Yt,[g(e("input",{"onUpdate:modelValue":t[1]||(t[1]=a=>s.value.platform=a),type:"radio",value:"claude",class:"mr-2"},null,512),[[Y,s.value.platform]]),t[50]||(t[50]=e("span",{class:"text-sm text-gray-700"},"Claude",-1))]),e("label",Qt,[g(e("input",{"onUpdate:modelValue":t[2]||(t[2]=a=>s.value.platform=a),type:"radio",value:"claude-console",class:"mr-2"},null,512),[[Y,s.value.platform]]),t[51]||(t[51]=e("span",{class:"text-sm text-gray-700"},"Claude Console",-1))]),e("label",Xt,[g(e("input",{"onUpdate:modelValue":t[3]||(t[3]=a=>s.value.platform=a),type:"radio",value:"gemini",class:"mr-2"},null,512),[[Y,s.value.platform]]),t[52]||(t[52]=e("span",{class:"text-sm text-gray-700"},"Gemini",-1))])])])),!x.value&&s.value.platform!=="claude-console"?(i(),u("div",Zt,[t[56]||(t[56]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"添加方式",-1)),e("div",es,[e("label",ts,[g(e("input",{"onUpdate:modelValue":t[4]||(t[4]=a=>s.value.addType=a),type:"radio",value:"oauth",class:"mr-2"},null,512),[[Y,s.value.addType]]),t[54]||(t[54]=e("span",{class:"text-sm text-gray-700"},"OAuth 授权 (推荐)",-1))]),e("label",ss,[g(e("input",{"onUpdate:modelValue":t[5]||(t[5]=a=>s.value.addType=a),type:"radio",value:"manual",class:"mr-2"},null,512),[[Y,s.value.addType]]),t[55]||(t[55]=e("span",{class:"text-sm text-gray-700"},"手动输入 Access Token",-1))])])])):$("",!0),e("div",null,[t[57]||(t[57]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[6]||(t[6]=a=>s.value.name=a),type:"text",required:"",class:L(["form-input w-full",{"border-red-500":v.value.name}]),placeholder:"为账户设置一个易识别的名称"},null,2),[[V,s.value.name]]),v.value.name?(i(),u("p",ls,I(v.value.name),1)):$("",!0)]),e("div",null,[t[58]||(t[58]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[7]||(t[7]=a=>s.value.description=a),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[V,s.value.description]])]),e("div",null,[t[61]||(t[61]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",os,[e("label",as,[g(e("input",{"onUpdate:modelValue":t[8]||(t[8]=a=>s.value.accountType=a),type:"radio",value:"shared",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[59]||(t[59]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",ns,[g(e("input",{"onUpdate:modelValue":t[9]||(t[9]=a=>s.value.accountType=a),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[60]||(t[60]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))])]),t[62]||(t[62]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用 ",-1))]),s.value.platform==="gemini"?(i(),u("div",rs,[t[63]||(t[63]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[10]||(t[10]=a=>s.value.projectId=a),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[V,s.value.projectId]]),t[64]||(t[64]=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,[b(" 访问 "),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,[b("复制"),e("span",{class:"font-semibold text-red-600"},"项目编号(Project Number)"),b(",通常是12位纯数字")]),e("li",{class:"text-red-600"}," ⚠️ 注意:不要复制项目ID(Project ID),要复制项目编号! ")])]),e("p",{class:"mt-2"},[e("strong",null,"提示:"),b("如果您的账号是普通个人账号(未绑定 Google Cloud),请留空此字段。 ")])])])],-1))])):$("",!0),s.value.platform==="claude-console"&&!x.value?(i(),u("div",is,[e("div",null,[t[65]||(t[65]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL *",-1)),g(e("input",{"onUpdate:modelValue":t[11]||(t[11]=a=>s.value.apiUrl=a),type:"text",required:"",class:L(["form-input w-full",{"border-red-500":v.value.apiUrl}]),placeholder:"例如:https://api.example.com"},null,2),[[V,s.value.apiUrl]]),v.value.apiUrl?(i(),u("p",us,I(v.value.apiUrl),1)):$("",!0)]),e("div",null,[t[66]||(t[66]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key *",-1)),g(e("input",{"onUpdate:modelValue":t[12]||(t[12]=a=>s.value.apiKey=a),type:"password",required:"",class:L(["form-input w-full",{"border-red-500":v.value.apiKey}]),placeholder:"请输入API Key"},null,2),[[V,s.value.apiKey]]),v.value.apiKey?(i(),u("p",ds,I(v.value.apiKey),1)):$("",!0)]),e("div",null,[t[70]||(t[70]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"模型映射表 (可选)",-1)),t[71]||(t[71]=e("div",{class:"bg-blue-50 p-3 rounded-lg mb-3"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),b(" 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 ")])],-1)),e("div",ps,[(i(!0),u(de,null,pe(U.value,(a,q)=>(i(),u("div",{key:q,class:"flex items-center gap-2"},[g(e("input",{"onUpdate:modelValue":F=>a.from=F,type:"text",class:"form-input flex-1",placeholder:"原始模型名称"},null,8,cs),[[V,a.from]]),t[68]||(t[68]=e("i",{class:"fas fa-arrow-right text-gray-400"},null,-1)),g(e("input",{"onUpdate:modelValue":F=>a.to=F,type:"text",class:"form-input flex-1",placeholder:"映射后的模型名称"},null,8,ms),[[V,a.to]]),e("button",{type:"button",class:"p-2 text-red-500 hover:bg-red-50 rounded-lg transition-colors",onClick:F=>te(q)},t[67]||(t[67]=[e("i",{class:"fas fa-trash"},null,-1)]),8,fs)]))),128))]),e("button",{type:"button",class:"w-full px-4 py-2 border-2 border-dashed border-gray-300 text-gray-600 rounded-lg hover:border-gray-400 hover:text-gray-700 transition-colors",onClick:ee},t[69]||(t[69]=[e("i",{class:"fas fa-plus mr-2"},null,-1),b(" 添加模型映射 ",-1)])),e("div",xs,[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[13]||(t[13]=a=>f("claude-3-5-sonnet-20241022","claude-3-5-sonnet-20241022"))}," + Sonnet 3.5 "),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[14]||(t[14]=a=>f("claude-3-opus-20240229","claude-3-opus-20240229"))}," + Opus 3 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-green-200 transition-colors",onClick:t[15]||(t[15]=a=>f("claude-3-5-haiku-20241022","claude-3-5-haiku-20241022"))}," + Haiku 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-orange-100 text-orange-700 rounded-lg hover:bg-orange-200 transition-colors",onClick:t[16]||(t[16]=a=>f("claude-sonnet-4-20250514","claude-3-5-sonnet-20241022"))}," + Sonnet 4 → 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-colors",onClick:t[17]||(t[17]=a=>f("claude-opus-4-20250514","claude-3-opus-20240229"))}," + Opus 4 → 3 ")]),t[72]||(t[72]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示支持所有模型。如果指定模型,请求中的模型不在列表内将不会调度到此账号 ",-1))]),e("div",null,[t[73]||(t[73]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[18]||(t[18]=a=>s.value.userAgent=a),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[V,s.value.userAgent]])]),e("div",null,[t[74]||(t[74]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[19]||(t[19]=a=>s.value.rateLimitDuration=a),type:"number",min:"1",class:"form-input w-full",placeholder:"默认60分钟"},null,512),[[V,s.value.rateLimitDuration,void 0,{number:!0}]]),t[75]||(t[75]=e("p",{class:"text-xs text-gray-500 mt-1"}," 当账号返回429错误时,暂停调度的时间(分钟) ",-1))])])):$("",!0),s.value.platform==="claude"||s.value.platform==="claude-console"?(i(),u("div",vs,[t[76]||(t[76]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[20]||(t[20]=a=>s.value.priority=a),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高,默认50"},null,512),[[V,s.value.priority,void 0,{number:!0}]]),t[77]||(t[77]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):$("",!0),s.value.addType==="manual"&&s.value.platform!=="claude-console"?(i(),u("div",ys,[e("div",gs,[t[83]||(t[83]=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[81]||(t[81]=e("h5",{class:"font-semibold text-blue-900 mb-2"}," 手动输入 Token ",-1)),s.value.platform==="claude"?(i(),u("p",bs," 请输入有效的 Claude Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):s.value.platform==="gemini"?(i(),u("p",ws," 请输入有效的 Gemini Access Token。如果您有 Refresh Token,建议也一并填写以支持自动刷新。 ")):$("",!0),e("div",ks,[t[80]||(t[80]=e("p",{class:"text-sm text-blue-900 font-medium mb-1"},[e("i",{class:"fas fa-folder-open mr-1"}),b(" 获取 Access Token 的方法: ")],-1)),s.value.platform==="claude"?(i(),u("p",hs,t[78]||(t[78]=[b(" 请从已登录 Claude Code 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.claude/.credentials.json",-1),b(" 文件中的凭证, 请勿使用 Claude 官网 API Keys 页面的密钥。 ",-1)]))):s.value.platform==="gemini"?(i(),u("p",$s,t[79]||(t[79]=[b(" 请从已登录 Gemini CLI 的机器上获取 ",-1),e("code",{class:"bg-blue-100 px-1 py-0.5 rounded font-mono"},"~/.config/gemini/credentials.json",-1),b(" 文件中的凭证。 ",-1)]))):$("",!0)]),t[82]||(t[82]=e("p",{class:"text-xs text-blue-600"}," 💡 如果未填写 Refresh Token,Token 过期后需要手动更新。 ",-1))])]),e("div",null,[t[84]||(t[84]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Access Token *",-1)),g(e("textarea",{"onUpdate:modelValue":t[21]||(t[21]=a=>s.value.accessToken=a),rows:"4",required:"",class:L(["form-input w-full resize-none font-mono text-xs",{"border-red-500":v.value.accessToken}]),placeholder:"请输入 Access Token..."},null,2),[[V,s.value.accessToken]]),v.value.accessToken?(i(),u("p",Cs,I(v.value.accessToken),1)):$("",!0)]),e("div",null,[t[85]||(t[85]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"Refresh Token (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[22]||(t[22]=a=>s.value.refreshToken=a),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"请输入 Refresh Token..."},null,512),[[V,s.value.refreshToken]])])])):$("",!0),ue(we,{modelValue:s.value.proxy,"onUpdate:modelValue":t[23]||(t[23]=a=>s.value.proxy=a)},null,8,["modelValue"]),e("div",Ts,[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[24]||(t[24]=a=>n.$emit("close"))}," 取消 "),s.value.addType==="oauth"&&s.value.platform!=="claude-console"?(i(),u("button",{key:0,type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:_}," 下一步 ",8,As)):(i(),u("button",{key:1,type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:ae},[R.value?(i(),u("div",Vs)):$("",!0),b(" "+I(R.value?"创建中...":"创建"),1)],8,Us))])])])):$("",!0),O.value===2&&s.value.addType==="oauth"?(i(),oe(It,{key:2,platform:s.value.platform,proxy:s.value.proxy,onSuccess:Z,onBack:t[25]||(t[25]=a=>O.value=1)},null,8,["platform","proxy"])):$("",!0),x.value?(i(),u("div",Is,[e("div",null,[t[86]||(t[86]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户名称",-1)),g(e("input",{"onUpdate:modelValue":t[26]||(t[26]=a=>s.value.name=a),type:"text",required:"",class:"form-input w-full",placeholder:"为账户设置一个易识别的名称"},null,512),[[V,s.value.name]])]),e("div",null,[t[87]||(t[87]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"描述 (可选)",-1)),g(e("textarea",{"onUpdate:modelValue":t[27]||(t[27]=a=>s.value.description=a),rows:"3",class:"form-input w-full resize-none",placeholder:"账户用途说明..."},null,512),[[V,s.value.description]])]),e("div",null,[t[90]||(t[90]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"账户类型",-1)),e("div",Ss,[e("label",js,[g(e("input",{"onUpdate:modelValue":t[28]||(t[28]=a=>s.value.accountType=a),type:"radio",value:"shared",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[88]||(t[88]=e("span",{class:"text-sm text-gray-700"},"共享账户",-1))]),e("label",Ms,[g(e("input",{"onUpdate:modelValue":t[29]||(t[29]=a=>s.value.accountType=a),type:"radio",value:"dedicated",class:"mr-2"},null,512),[[Y,s.value.accountType]]),t[89]||(t[89]=e("span",{class:"text-sm text-gray-700"},"专属账户",-1))])]),t[91]||(t[91]=e("p",{class:"text-xs text-gray-500 mt-2"}," 共享账户:供所有API Key使用;专属账户:仅供特定API Key使用 ",-1))]),s.value.platform==="gemini"?(i(),u("div",Ks,[t[92]||(t[92]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"项目编号 (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[30]||(t[30]=a=>s.value.projectId=a),type:"text",class:"form-input w-full",placeholder:"例如:123456789012(纯数字)"},null,512),[[V,s.value.projectId]]),t[93]||(t[93]=e("p",{class:"text-xs text-gray-500 mt-2"}," Google Cloud/Workspace 账号可能需要提供项目编号 ",-1))])):$("",!0),s.value.platform==="claude"||s.value.platform==="claude-console"?(i(),u("div",Ps,[t[94]||(t[94]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"调度优先级 (1-100)",-1)),g(e("input",{"onUpdate:modelValue":t[31]||(t[31]=a=>s.value.priority=a),type:"number",min:"1",max:"100",class:"form-input w-full",placeholder:"数字越小优先级越高"},null,512),[[V,s.value.priority,void 0,{number:!0}]]),t[95]||(t[95]=e("p",{class:"text-xs text-gray-500 mt-1"}," 数字越小优先级越高,建议范围:1-100 ",-1))])):$("",!0),s.value.platform==="claude-console"?(i(),u("div",Rs,[e("div",null,[t[96]||(t[96]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API URL",-1)),g(e("input",{"onUpdate:modelValue":t[32]||(t[32]=a=>s.value.apiUrl=a),type:"text",required:"",class:"form-input w-full",placeholder:"例如:https://api.example.com"},null,512),[[V,s.value.apiUrl]])]),e("div",null,[t[97]||(t[97]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"API Key",-1)),g(e("input",{"onUpdate:modelValue":t[33]||(t[33]=a=>s.value.apiKey=a),type:"password",class:"form-input w-full",placeholder:"留空表示不更新"},null,512),[[V,s.value.apiKey]]),t[98]||(t[98]=e("p",{class:"text-xs text-gray-500 mt-1"}," 留空表示不更新 API Key ",-1))]),e("div",null,[t[102]||(t[102]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"模型映射表 (可选)",-1)),t[103]||(t[103]=e("div",{class:"bg-blue-50 p-3 rounded-lg mb-3"},[e("p",{class:"text-xs text-blue-700"},[e("i",{class:"fas fa-info-circle mr-1"}),b(" 留空表示支持所有模型且不修改请求。配置映射后,左侧模型会被识别为支持的模型,右侧是实际发送的模型。 ")])],-1)),e("div",Gs,[(i(!0),u(de,null,pe(U.value,(a,q)=>(i(),u("div",{key:q,class:"flex items-center gap-2"},[g(e("input",{"onUpdate:modelValue":F=>a.from=F,type:"text",class:"form-input flex-1",placeholder:"原始模型名称"},null,8,Ls),[[V,a.from]]),t[100]||(t[100]=e("i",{class:"fas fa-arrow-right text-gray-400"},null,-1)),g(e("input",{"onUpdate:modelValue":F=>a.to=F,type:"text",class:"form-input flex-1",placeholder:"映射后的模型名称"},null,8,Ds),[[V,a.to]]),e("button",{type:"button",class:"p-2 text-red-500 hover:bg-red-50 rounded-lg transition-colors",onClick:F=>te(q)},t[99]||(t[99]=[e("i",{class:"fas fa-trash"},null,-1)]),8,Os)]))),128))]),e("button",{type:"button",class:"w-full px-4 py-2 border-2 border-dashed border-gray-300 text-gray-600 rounded-lg hover:border-gray-400 hover:text-gray-700 transition-colors",onClick:ee},t[101]||(t[101]=[e("i",{class:"fas fa-plus mr-2"},null,-1),b(" 添加模型映射 ",-1)])),e("div",Es,[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[34]||(t[34]=a=>f("claude-3-5-sonnet-20241022","claude-3-5-sonnet-20241022"))}," + Sonnet 3.5 "),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[35]||(t[35]=a=>f("claude-3-opus-20240229","claude-3-opus-20240229"))}," + Opus 3 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-green-100 text-green-700 rounded-lg hover:bg-green-200 transition-colors",onClick:t[36]||(t[36]=a=>f("claude-3-5-haiku-20241022","claude-3-5-haiku-20241022"))}," + Haiku 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-orange-100 text-orange-700 rounded-lg hover:bg-orange-200 transition-colors",onClick:t[37]||(t[37]=a=>f("claude-sonnet-4-20250514","claude-3-5-sonnet-20241022"))}," + Sonnet 4 → 3.5 "),e("button",{type:"button",class:"px-3 py-1 text-xs bg-red-100 text-red-700 rounded-lg hover:bg-red-200 transition-colors",onClick:t[38]||(t[38]=a=>f("claude-opus-4-20250514","claude-3-opus-20240229"))}," + Opus 4 → 3 ")])]),e("div",null,[t[104]||(t[104]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"自定义 User-Agent (可选)",-1)),g(e("input",{"onUpdate:modelValue":t[39]||(t[39]=a=>s.value.userAgent=a),type:"text",class:"form-input w-full",placeholder:"默认:claude-cli/1.0.61 (console, cli)"},null,512),[[V,s.value.userAgent]])]),e("div",null,[t[105]||(t[105]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"限流时间 (分钟)",-1)),g(e("input",{"onUpdate:modelValue":t[40]||(t[40]=a=>s.value.rateLimitDuration=a),type:"number",min:"1",class:"form-input w-full"},null,512),[[V,s.value.rateLimitDuration,void 0,{number:!0}]])])])):$("",!0),s.value.platform!=="claude-console"?(i(),u("div",zs,[t[108]||(t[108]=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",Ws,[e("div",null,[t[106]||(t[106]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Access Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[41]||(t[41]=a=>s.value.accessToken=a),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[V,s.value.accessToken]])]),e("div",null,[t[107]||(t[107]=e("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"新的 Refresh Token",-1)),g(e("textarea",{"onUpdate:modelValue":t[42]||(t[42]=a=>s.value.refreshToken=a),rows:"4",class:"form-input w-full resize-none font-mono text-xs",placeholder:"留空表示不更新..."},null,512),[[V,s.value.refreshToken]])])])])):$("",!0),ue(we,{modelValue:s.value.proxy,"onUpdate:modelValue":t[43]||(t[43]=a=>s.value.proxy=a)},null,8,["modelValue"]),e("div",qs,[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[44]||(t[44]=a=>n.$emit("close"))}," 取消 "),e("button",{type:"button",disabled:R.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold",onClick:ne},[R.value?(i(),u("div",Bs)):$("",!0),b(" "+I(R.value?"更新中...":"更新"),1)],8,Ns)])])):$("",!0)])])):$("",!0),ue(Ae,{show:N(K),title:N(j).title,message:N(j).message,"confirm-text":N(j).confirmText,"cancel-text":N(j).cancelText,onConfirm:N(A),onCancel:N(y)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"])]))}},Hs={class:"accounts-container"},Fs={class:"card p-6"},_s={class:"flex flex-col md:flex-row justify-between items-center gap-4 mb-6"},Js={class:"flex gap-2"},Ys={key:0,class:"text-center py-12"},Qs={key:1,class:"text-center py-12"},Xs={key:2,class:"table-container"},Zs={class:"min-w-full"},el={class:"bg-gray-50/80 backdrop-blur-sm"},tl={key:1,class:"fas fa-sort ml-1 text-gray-400"},sl={key:1,class:"fas fa-sort ml-1 text-gray-400"},ll={key:1,class:"fas fa-sort ml-1 text-gray-400"},ol={key:1,class:"fas fa-sort ml-1 text-gray-400"},al={key:1,class:"fas fa-sort ml-1 text-gray-400"},nl={class:"divide-y divide-gray-200/50"},rl={class:"px-6 py-4 whitespace-nowrap"},il={class:"flex items-center"},ul={class:"flex items-center gap-2"},dl={class:"text-sm font-semibold text-gray-900"},pl={key:0,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800"},cl={key:1,class:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"},ml={class:"text-xs text-gray-500"},fl={class:"px-6 py-4 whitespace-nowrap"},xl={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"},vl={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-purple-100 text-purple-800"},yl={key:2,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-indigo-100 text-indigo-800"},gl={class:"px-6 py-4 whitespace-nowrap"},bl={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800"},wl={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-800"},kl={key:2,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-orange-100 text-orange-800"},hl={class:"px-6 py-4 whitespace-nowrap"},$l={class:"flex flex-col gap-1"},Cl={key:0,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800"},Tl={key:1,class:"inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold bg-gray-100 text-gray-700"},Al=["title"],Ul={key:3,class:"text-xs text-gray-500"},Vl={class:"px-6 py-4 whitespace-nowrap"},Il={key:0,class:"flex items-center gap-2"},Sl={class:"w-16 bg-gray-200 rounded-full h-2"},jl={class:"text-xs text-gray-700 font-medium min-w-[20px]"},Ml={key:1,class:"text-gray-400 text-sm"},Kl={class:"px-6 py-4 whitespace-nowrap text-sm text-gray-600"},Pl={key:0,class:"text-xs bg-blue-50 px-2 py-1 rounded font-mono"},Rl={key:1,class:"text-gray-400"},Gl={class:"px-6 py-4 whitespace-nowrap text-sm"},Ll={key:0,class:"space-y-1"},Dl={class:"flex items-center gap-2"},Ol={class:"text-sm font-medium text-gray-900"},El={class:"flex items-center gap-2"},zl={class:"text-xs text-gray-600"},Wl={key:0,class:"text-xs text-gray-500"},ql={key:1,class:"text-gray-400 text-xs"},Nl={class:"px-6 py-4 whitespace-nowrap"},Bl={key:0,class:"space-y-2"},Hl={class:"flex items-center gap-2"},Fl={class:"w-24 bg-gray-200 rounded-full h-2"},_l={class:"text-xs text-gray-700 font-medium min-w-[32px]"},Jl={class:"text-xs text-gray-600"},Yl={key:0,class:"text-indigo-600 font-medium"},Ql={key:1,class:"text-gray-400 text-sm"},Xl={key:2,class:"text-gray-400 text-sm"},Zl={class:"px-6 py-4 whitespace-nowrap text-sm text-gray-600"},eo={class:"px-6 py-4 whitespace-nowrap text-sm font-medium"},to={class:"flex items-center gap-2"},so=["disabled","title","onClick"],lo=["disabled","title","onClick"],oo=["onClick"],ao=["onClick"],no={__name:"AccountsView",setup(D){const{showConfirmModal:W,confirmOptions:p,showConfirm:w,handleConfirm:d,handleCancel:K}=Ce(),j=C([]),T=C(!1),A=C("name"),y=C(""),x=C("asc"),M=C([]),O=C(!1),R=C(!1),Q=C(null),s=le(()=>y.value?[...j.value].sort((l,o)=>{var B,E,n,t,a,q,F,ce,me,fe,xe,ve;let h=l[y.value],G=o[y.value];return y.value==="dailyTokens"?(h=((E=(B=l.usage)==null?void 0:B.daily)==null?void 0:E.allTokens)||0,G=((t=(n=o.usage)==null?void 0:n.daily)==null?void 0:t.allTokens)||0):y.value==="dailyRequests"?(h=((q=(a=l.usage)==null?void 0:a.daily)==null?void 0:q.requests)||0,G=((ce=(F=o.usage)==null?void 0:F.daily)==null?void 0:ce.requests)||0):y.value==="totalTokens"&&(h=((fe=(me=l.usage)==null?void 0:me.total)==null?void 0:fe.allTokens)||0,G=((ve=(xe=o.usage)==null?void 0:xe.total)==null?void 0:ve.allTokens)||0),y.value==="lastUsed"&&(h=l.lastUsedAt?new Date(l.lastUsedAt).getTime():0,G=o.lastUsedAt?new Date(o.lastUsedAt).getTime():0),y.value==="status"&&(h=l.isActive?1:0,G=o.isActive?1:0),h<G?x.value==="asc"?-1:1:h>G?x.value==="asc"?1:-1:0}):j.value),U=async()=>{T.value=!0;try{const[c,l,o,h]=await Promise.all([P.get("/admin/claude-accounts"),P.get("/admin/claude-console-accounts"),P.get("/admin/gemini-accounts"),P.get("/admin/api-keys")]);h.success&&(M.value=h.data||[]);const G=[];if(c.success){const B=(c.data||[]).map(E=>{const n=M.value.filter(t=>t.claudeAccountId===E.id).length;return{...E,platform:"claude",boundApiKeysCount:n}});G.push(...B)}if(l.success){const B=(l.data||[]).map(E=>{const n=M.value.filter(t=>t.claudeConsoleAccountId===E.id).length;return{...E,platform:"claude-console",boundApiKeysCount:n}});G.push(...B)}if(o.success){const B=(o.data||[]).map(E=>{const n=M.value.filter(t=>t.geminiAccountId===E.id).length;return{...E,platform:"gemini",boundApiKeysCount:n}});G.push(...B)}j.value=G}catch{S("加载账户失败","error")}finally{T.value=!1}},r=c=>{c&&(y.value===c?x.value=x.value==="asc"?"desc":"asc":(y.value=c,x.value="asc"))},v=c=>{if(c==null)return"0";const l=Number(c);return l>=1e6?Math.floor(l/1e6).toLocaleString()+"M":l.toLocaleString()},J=c=>{if(!c)return"从未使用";const l=new Date(c),h=new Date-l;return h<6e4?"刚刚":h<36e5?`${Math.floor(h/6e4)} 分钟前`:h<864e5?`${Math.floor(h/36e5)} 小时前`:h<6048e5?`${Math.floor(h/864e5)} 天前`:l.toLocaleDateString("zh-CN")},_=async()=>{try{const c=await P.get("/admin/api-keys");c.success&&(M.value=c.data)}catch(c){console.error("Failed to load API keys:",c)}},Z=c=>{if(!c||!c.host||!c.port)return null;let l=`${c.type}://${c.host}:${c.port}`;if(c.username){const o=c.username.length>2?c.username[0]+"***"+c.username[c.username.length-1]:"***",h=c.password?"****":"";l=`${c.type}://${o}:${h}@${c.host}:${c.port}`}return l},ae=(c,l)=>{if(!c||!l)return"--";const o=new Date(c),h=new Date(l),G=o.getHours().toString().padStart(2,"0"),B=o.getMinutes().toString().padStart(2,"0"),E=h.getHours().toString().padStart(2,"0"),n=h.getMinutes().toString().padStart(2,"0");return`${G}:${B} - ${E}:${n}`},ne=c=>{if(!c||c<=0)return"已结束";const l=Math.floor(c/60),o=c%60;return l>0?`${l}小时${o}分钟`:`${o}分钟`},ee=()=>{O.value=!0},te=c=>{Q.value=c,R.value=!0},f=async c=>{const l=M.value.filter(h=>h.claudeAccountId===c.id||h.geminiAccountId===c.id).length;if(l>0){S(`无法删除此账号,有 ${l} 个API Key绑定到此账号,请先解绑所有API Key`,"error");return}if(await w("删除账户",`确定要删除账户 "${c.name}" 吗?
|
||
|
||
此操作不可恢复。`,"删除","取消"))try{let h;c.platform==="claude"?h=`/admin/claude-accounts/${c.id}`:c.platform==="claude-console"?h=`/admin/claude-console-accounts/${c.id}`:h=`/admin/gemini-accounts/${c.id}`;const G=await P.delete(h);G.success?(S("账户已删除","success"),U()):S(G.message||"删除失败","error")}catch{S("删除失败","error")}},m=async c=>{if(!c.isRefreshing)try{c.isRefreshing=!0;const l=await P.post(`/admin/claude-accounts/${c.id}/refresh`);l.success?(S("Token刷新成功","success"),U()):S(l.message||"Token刷新失败","error")}catch{S("Token刷新失败","error")}finally{c.isRefreshing=!1}},k=async c=>{if(!c.isTogglingSchedulable)try{c.isTogglingSchedulable=!0;let l;if(c.platform==="claude")l=`/admin/claude-accounts/${c.id}/toggle-schedulable`;else if(c.platform==="claude-console")l=`/admin/claude-console-accounts/${c.id}/toggle-schedulable`;else{S("Gemini账户暂不支持调度控制","warning");return}const o=await P.put(l);o.success?(c.schedulable=o.schedulable,S(o.schedulable?"已启用调度":"已禁用调度","success")):S(o.message||"操作失败","error")}catch{S("切换调度状态失败","error")}finally{c.isTogglingSchedulable=!1}},H=()=>{O.value=!1,S("账户创建成功","success"),U()},re=()=>{R.value=!1,S("账户更新成功","success"),U()};return z(A,c=>{const l={name:"name",dailyTokens:"dailyTokens",dailyRequests:"dailyRequests",totalTokens:"totalTokens",lastUsed:"lastUsed"};l[c]&&r(l[c])}),Se(()=>{U(),_()}),(c,l)=>(i(),u("div",Hs,[e("div",Fs,[e("div",_s,[l[11]||(l[11]=e("div",null,[e("h3",{class:"text-xl font-bold text-gray-900 mb-2"}," 账户管理 "),e("p",{class:"text-gray-600"}," 管理您的 Claude 和 Gemini 账户及代理配置 ")],-1)),e("div",Js,[g(e("select",{"onUpdate:modelValue":l[0]||(l[0]=o=>A.value=o),class:"form-input px-3 py-2 text-sm",onChange:l[1]||(l[1]=o=>r())},l[9]||(l[9]=[se('<option value="name" data-v-981f21d9> 按名称排序 </option><option value="dailyTokens" data-v-981f21d9> 按今日Token排序 </option><option value="dailyRequests" data-v-981f21d9> 按今日请求数排序 </option><option value="totalTokens" data-v-981f21d9> 按总Token排序 </option><option value="lastUsed" data-v-981f21d9> 按最后使用排序 </option>',5)]),544),[[he,A.value]]),e("button",{class:"btn btn-success px-6 py-3 flex items-center gap-2",onClick:je(ee,["stop"])},l[10]||(l[10]=[e("i",{class:"fas fa-plus"},null,-1),b("添加账户 ",-1)]))])]),T.value?(i(),u("div",Ys,l[12]||(l[12]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"}," 正在加载账户... ",-1)]))):s.value.length===0?(i(),u("div",Qs,l[13]||(l[13]=[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)]))):(i(),u("div",Xs,[e("table",Zs,[e("thead",el,[e("tr",null,[e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[2]||(l[2]=o=>r("name"))},[l[14]||(l[14]=b(" 名称 ",-1)),y.value==="name"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",tl))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[3]||(l[3]=o=>r("platform"))},[l[15]||(l[15]=b(" 平台 ",-1)),y.value==="platform"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",sl))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[4]||(l[4]=o=>r("accountType"))},[l[16]||(l[16]=b(" 类型 ",-1)),y.value==="accountType"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",ll))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[5]||(l[5]=o=>r("status"))},[l[17]||(l[17]=b(" 状态 ",-1)),y.value==="status"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",ol))]),e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider cursor-pointer hover:bg-gray-100",onClick:l[6]||(l[6]=o=>r("priority"))},[l[18]||(l[18]=b(" 优先级 ",-1)),y.value==="priority"?(i(),u("i",{key:0,class:L(["fas",x.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(i(),u("i",al))]),l[19]||(l[19]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 代理 ",-1)),l[20]||(l[20]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 今日使用 ",-1)),l[21]||(l[21]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 会话窗口 ",-1)),l[22]||(l[22]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 最后使用 ",-1)),l[23]||(l[23]=e("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"}," 操作 ",-1))])]),e("tbody",nl,[(i(!0),u(de,null,pe(s.value,o=>(i(),u("tr",{key:o.id,class:"table-row"},[e("td",rl,[e("div",il,[l[26]||(l[26]=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-3"},[e("i",{class:"fas fa-user-circle text-white text-xs"})],-1)),e("div",null,[e("div",ul,[e("div",dl,I(o.name),1),o.accountType==="dedicated"?(i(),u("span",pl,l[24]||(l[24]=[e("i",{class:"fas fa-lock mr-1"},null,-1),b("专属 ",-1)]))):(i(),u("span",cl,l[25]||(l[25]=[e("i",{class:"fas fa-share-alt mr-1"},null,-1),b("共享 ",-1)])))]),e("div",ml,I(o.id),1)])])]),e("td",fl,[o.platform==="gemini"?(i(),u("span",xl,l[27]||(l[27]=[e("i",{class:"fas fa-robot mr-1"},null,-1),b("Gemini ",-1)]))):o.platform==="claude-console"?(i(),u("span",vl,l[28]||(l[28]=[e("i",{class:"fas fa-terminal mr-1"},null,-1),b("Claude Console ",-1)]))):(i(),u("span",yl,l[29]||(l[29]=[e("i",{class:"fas fa-brain mr-1"},null,-1),b("Claude ",-1)])))]),e("td",gl,[o.platform==="claude-console"?(i(),u("span",bl,l[30]||(l[30]=[e("i",{class:"fas fa-key mr-1"},null,-1),b("API Key ",-1)]))):o.scopes&&o.scopes.length>0?(i(),u("span",wl,l[31]||(l[31]=[e("i",{class:"fas fa-lock mr-1"},null,-1),b("OAuth ",-1)]))):(i(),u("span",kl,l[32]||(l[32]=[e("i",{class:"fas fa-key mr-1"},null,-1),b("传统 ",-1)])))]),e("td",hl,[e("div",$l,[e("span",{class:L(["inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold",o.status==="blocked"?"bg-orange-100 text-orange-800":o.isActive?"bg-green-100 text-green-800":"bg-red-100 text-red-800"])},[e("div",{class:L(["w-2 h-2 rounded-full mr-2",o.status==="blocked"?"bg-orange-500":o.isActive?"bg-green-500":"bg-red-500"])},null,2),b(" "+I(o.status==="blocked"?"已封锁":o.isActive?"正常":"异常"),1)],2),o.rateLimitStatus&&o.rateLimitStatus.isRateLimited?(i(),u("span",Cl,[l[33]||(l[33]=e("i",{class:"fas fa-exclamation-triangle mr-1"},null,-1)),b(" 限流中 ("+I(o.rateLimitStatus.minutesRemaining)+"分钟) ",1)])):$("",!0),o.schedulable===!1?(i(),u("span",Tl,l[34]||(l[34]=[e("i",{class:"fas fa-pause-circle mr-1"},null,-1),b(" 不可调度 ",-1)]))):$("",!0),o.status==="blocked"&&o.errorMessage?(i(),u("span",{key:2,class:"text-xs text-gray-500 mt-1 max-w-xs truncate",title:o.errorMessage},I(o.errorMessage),9,Al)):$("",!0),o.accountType==="dedicated"?(i(),u("span",Ul," 绑定: "+I(o.boundApiKeysCount||0)+" 个API Key ",1)):$("",!0)])]),e("td",Vl,[o.platform==="claude"||o.platform==="claude-console"?(i(),u("div",Il,[e("div",Sl,[e("div",{class:"bg-gradient-to-r from-green-500 to-blue-600 h-2 rounded-full transition-all duration-300",style:ge({width:101-(o.priority||50)+"%"})},null,4)]),e("span",jl,I(o.priority||50),1)])):(i(),u("div",Ml,l[35]||(l[35]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Kl,[Z(o.proxy)?(i(),u("div",Pl,I(Z(o.proxy)),1)):(i(),u("div",Rl," 无代理 "))]),e("td",Gl,[o.usage&&o.usage.daily?(i(),u("div",Ll,[e("div",Dl,[l[36]||(l[36]=e("div",{class:"w-2 h-2 bg-green-500 rounded-full"},null,-1)),e("span",Ol,I(o.usage.daily.requests||0)+" 次",1)]),e("div",El,[l[37]||(l[37]=e("div",{class:"w-2 h-2 bg-blue-500 rounded-full"},null,-1)),e("span",zl,I(v(o.usage.daily.allTokens||0))+" tokens",1)]),o.usage.averages&&o.usage.averages.rpm>0?(i(),u("div",Wl," 平均 "+I(o.usage.averages.rpm.toFixed(2))+" RPM ",1)):$("",!0)])):(i(),u("div",ql," 暂无数据 "))]),e("td",Nl,[o.platform==="claude"&&o.sessionWindow&&o.sessionWindow.hasActiveWindow?(i(),u("div",Bl,[e("div",Hl,[e("div",Fl,[e("div",{class:"bg-gradient-to-r from-blue-500 to-indigo-600 h-2 rounded-full transition-all duration-300",style:ge({width:o.sessionWindow.progress+"%"})},null,4)]),e("span",_l,I(o.sessionWindow.progress)+"% ",1)]),e("div",Jl,[e("div",null,I(ae(o.sessionWindow.windowStart,o.sessionWindow.windowEnd)),1),o.sessionWindow.remainingTime>0?(i(),u("div",Yl," 剩余 "+I(ne(o.sessionWindow.remainingTime)),1)):$("",!0)])])):o.platform==="claude"?(i(),u("div",Ql,l[38]||(l[38]=[e("i",{class:"fas fa-minus"},null,-1)]))):(i(),u("div",Xl,l[39]||(l[39]=[e("span",{class:"text-xs"},"N/A",-1)])))]),e("td",Zl,I(J(o.lastUsedAt)),1),e("td",eo,[e("div",to,[o.platform==="claude"&&o.scopes?(i(),u("button",{key:0,disabled:o.isRefreshing,class:L(["px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",o.isRefreshing?"bg-gray-100 text-gray-400 cursor-not-allowed":"bg-blue-100 text-blue-700 hover:bg-blue-200"]),title:o.isRefreshing?"刷新中...":"刷新Token",onClick:h=>m(o)},[e("i",{class:L(["fas fa-sync-alt",o.isRefreshing?"animate-spin":""])},null,2)],10,so)):$("",!0),e("button",{disabled:o.isTogglingSchedulable,class:L(["px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",o.isTogglingSchedulable?"bg-gray-100 text-gray-400 cursor-not-allowed":o.schedulable?"bg-green-100 text-green-700 hover:bg-green-200":"bg-gray-100 text-gray-700 hover:bg-gray-200"]),title:o.schedulable?"点击禁用调度":"点击启用调度",onClick:h=>k(o)},[e("i",{class:L(["fas",o.schedulable?"fa-toggle-on":"fa-toggle-off"])},null,2)],10,lo),e("button",{class:"px-3 py-1.5 bg-blue-100 text-blue-700 rounded-lg text-xs font-medium hover:bg-blue-200 transition-colors",onClick:h=>te(o)},l[40]||(l[40]=[e("i",{class:"fas fa-edit"},null,-1)]),8,oo),e("button",{class:"px-3 py-1.5 bg-red-100 text-red-700 rounded-lg text-xs font-medium hover:bg-red-200 transition-colors",onClick:h=>f(o)},l[41]||(l[41]=[e("i",{class:"fas fa-trash"},null,-1)]),8,ao)])])]))),128))])])]))]),O.value?(i(),oe(ke,{key:0,onClose:l[7]||(l[7]=o=>O.value=!1),onSuccess:H})):$("",!0),R.value?(i(),oe(ke,{key:1,account:Q.value,onClose:l[8]||(l[8]=o=>R.value=!1),onSuccess:re},null,8,["account"])):$("",!0),ue(Ae,{show:N(W),title:N(p).title,message:N(p).message,"confirm-text":N(p).confirmText,"cancel-text":N(p).cancelText,onConfirm:N(d),onCancel:N(K)},null,8,["show","title","message","confirm-text","cancel-text","onConfirm","onCancel"])]))}},mo=Me(no,[["__scopeId","data-v-981f21d9"]]);export{mo as default};
|