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