mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
4 lines
64 KiB
JavaScript
4 lines
64 KiB
JavaScript
import{E as Rt}from"./element-plus-B8Fs_0jW.js";import{aR as ht,r as C,_ as it,q as at,c as rt,I as W,y as a,z as t,Y as z,K as v,aq as S,x as d,L as A,Q as T,ac as _,O as f,P as m,aa as et,aX as Y,an as B,al as G,a5 as st,C as U,R as St,B as Tt}from"./vue-vendor-CKToUHZx.js";import{s as M}from"./toast-BvwA7Mwb.js";import{a as F,_ as J,u as dt}from"./index-CXaPsBVx.js";import"./vendor-BDiMbLwQ.js";const ut=ht("clients",{state:()=>({supportedClients:[],loading:!1,error:null}),actions:{async loadSupportedClients(){if(this.supportedClients.length>0)return this.supportedClients;this.loading=!0,this.error=null;try{const D=await F.get("/admin/supported-clients");return D.success?this.supportedClients=D.data||[]:(this.error=D.message||"加载支持的客户端失败",console.error("Failed to load supported clients:",this.error)),this.supportedClients}catch(D){return this.error=D.message||"加载支持的客户端失败",console.error("Error loading supported clients:",D),[]}finally{this.loading=!1}}}}),Pt={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},_t={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},Et={class:"flex items-center justify-between mb-6"},Vt={class:"space-y-3"},jt={key:0,class:"flex flex-wrap gap-2"},Ut=["onClick"],qt={class:"flex gap-2"},Ft=["onKeypress"],Ot={class:"bg-blue-50 border border-blue-200 rounded-lg p-4 space-y-4"},Wt={class:"space-y-3"},Yt={class:"flex gap-2"},zt={key:0,class:"mt-3"},Nt=["min"],Ht={key:1,class:"text-xs text-gray-500 mt-2"},Bt={class:"flex gap-4"},Gt={class:"flex items-center cursor-pointer"},Qt={class:"flex items-center cursor-pointer"},Xt={class:"flex items-center cursor-pointer"},Jt={class:"grid grid-cols-1 gap-3"},Zt=["disabled"],te=["value"],ee=["disabled"],se=["value"],le={class:"flex items-center mb-3"},oe={key:0,class:"space-y-3"},ne={class:"flex flex-wrap gap-2 mb-3 min-h-[32px] p-2 bg-gray-50 rounded-lg border border-gray-200"},ie=["onClick"],ae={key:0,class:"text-gray-400 text-sm"},re={class:"flex gap-2"},de=["onKeydown"],ue={class:"flex items-center mb-3"},me={key:0,class:"space-y-3"},pe={class:"space-y-2"},ce=["id","value"],xe=["for"],ge={class:"text-sm font-medium text-gray-700"},ye={class:"text-xs text-gray-500 block"},fe={class:"flex gap-3 pt-4"},be=["disabled"],ve={key:0,class:"loading-spinner mr-2"},we={key:1,class:"fas fa-plus mr-2"},$e={__name:"CreateApiKeyModal",props:{accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success"],setup(D,{emit:q}){const $=q;dt();const V=ut(),I=C(!1),x=C(""),R=C([]),i=it({name:"",description:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",expireDuration:"",customExpireDate:"",expiresAt:null,permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]});at(async()=>{R.value=await V.loadSupportedClients()});const n=rt(()=>{const y=new Date;return y.setMinutes(y.getMinutes()+1),y.toISOString().slice(0,16)}),K=()=>{if(!i.expireDuration){i.expiresAt=null;return}if(i.expireDuration==="custom")return;const y=new Date,u=i.expireDuration.match(/(\d+)([dhmy])/);if(u){const[,j,Q]=u,N=parseInt(j);switch(Q){case"d":y.setDate(y.getDate()+N);break;case"h":y.setHours(y.getHours()+N);break;case"m":y.setMonth(y.getMonth()+N);break;case"y":y.setFullYear(y.getFullYear()+N);break}i.expiresAt=y.toISOString()}},k=()=>{i.customExpireDate&&(i.expiresAt=new Date(i.customExpireDate).toISOString())},b=y=>new Date(y).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),w=()=>{i.modelInput&&!i.restrictedModels.includes(i.modelInput)&&(i.restrictedModels.push(i.modelInput),i.modelInput="")},P=y=>{i.restrictedModels.splice(y,1)},L=()=>{if(x.value&&x.value.trim()){const y=x.value.trim();i.tags.includes(y)||i.tags.push(y),x.value=""}},o=y=>{i.tags.splice(y,1)},p=async()=>{I.value=!0;try{const y={name:i.name,description:i.description||void 0,tokenLimit:i.tokenLimit!==""&&i.tokenLimit!==null?parseInt(i.tokenLimit):null,rateLimitWindow:i.rateLimitWindow!==""&&i.rateLimitWindow!==null?parseInt(i.rateLimitWindow):null,rateLimitRequests:i.rateLimitRequests!==""&&i.rateLimitRequests!==null?parseInt(i.rateLimitRequests):null,concurrencyLimit:i.concurrencyLimit!==""&&i.concurrencyLimit!==null?parseInt(i.concurrencyLimit):0,dailyCostLimit:i.dailyCostLimit!==""&&i.dailyCostLimit!==null?parseFloat(i.dailyCostLimit):0,expiresAt:i.expiresAt||void 0,permissions:i.permissions,claudeAccountId:i.claudeAccountId||void 0,geminiAccountId:i.geminiAccountId||void 0,tags:i.tags.length>0?i.tags:void 0};y.enableModelRestriction=i.enableModelRestriction,y.restrictedModels=i.restrictedModels,y.enableClientRestriction=i.enableClientRestriction,y.allowedClients=i.allowedClients;const l=await F.post("/admin/api-keys",y);l.success?(M("API Key 创建成功","success"),$("success",l.data),$("close")):M(l.message||"创建失败","error")}catch{M("创建失败","error")}finally{I.value=!1}};return(y,l)=>(a(),W(st,{to:"body"},[t("div",Pt,[t("div",_t,[t("div",Et,[l[26]||(l[26]=t("div",{class:"flex items-center gap-3"},[t("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[t("i",{class:"fas fa-key text-white"})]),t("h3",{class:"text-xl font-bold text-gray-900"},"创建新的 API Key")],-1)),t("button",{onClick:l[0]||(l[0]=u=>y.$emit("close")),class:"text-gray-400 hover:text-gray-600 transition-colors"},l[25]||(l[25]=[t("i",{class:"fas fa-times text-xl"},null,-1)]))]),t("form",{onSubmit:z(p,["prevent"]),class:"space-y-6 modal-scroll-content custom-scrollbar flex-1"},[t("div",null,[l[27]||(l[27]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"名称",-1)),v(t("input",{"onUpdate:modelValue":l[1]||(l[1]=u=>i.name=u),type:"text",required:"",class:"form-input w-full",placeholder:"为您的 API Key 取一个名称"},null,512),[[S,i.name]])]),t("div",null,[l[31]||(l[31]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"标签",-1)),t("div",Vt,[i.tags.length>0?(a(),d("div",jt,[(a(!0),d(T,null,_(i.tags,(u,j)=>(a(),d("span",{key:j,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[f(m(u)+" ",1),t("button",{type:"button",onClick:Q=>o(j),class:"ml-1 hover:text-blue-900"},l[28]||(l[28]=[t("i",{class:"fas fa-times text-xs"},null,-1)]),8,Ut)]))),128))])):A("",!0),t("div",qt,[v(t("input",{"onUpdate:modelValue":l[2]||(l[2]=u=>x.value=u),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:et(z(L,["prevent"]),["enter"])},null,40,Ft),[[S,x.value]]),t("button",{type:"button",onClick:L,class:"px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"},l[29]||(l[29]=[t("i",{class:"fas fa-plus"},null,-1)]))]),l[30]||(l[30]=t("p",{class:"text-xs text-gray-500"},"用于标记不同团队或用途,方便筛选管理",-1))])]),t("div",Ot,[l[38]||(l[38]=t("div",{class:"flex items-start gap-3 mb-3"},[t("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[t("i",{class:"fas fa-tachometer-alt text-white text-sm"})]),t("div",{class:"flex-1"},[t("h4",{class:"font-semibold text-gray-800 mb-1"},"速率限制设置 (可选)"),t("p",{class:"text-sm text-gray-600"},"控制 API Key 的使用频率和资源消耗")])],-1)),t("div",null,[l[32]||(l[32]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"时间窗口 (分钟)",-1)),v(t("input",{"onUpdate:modelValue":l[3]||(l[3]=u=>i.rateLimitWindow=u),type:"number",min:"1",placeholder:"留空表示无限制",class:"form-input w-full"},null,512),[[S,i.rateLimitWindow]]),l[33]||(l[33]=t("p",{class:"text-xs text-gray-500 mt-2"},"设置一个时间段(以分钟为单位),用于计算速率限制",-1))]),t("div",null,[l[34]||(l[34]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"时间窗口内的请求次数限制",-1)),v(t("input",{"onUpdate:modelValue":l[4]||(l[4]=u=>i.rateLimitRequests=u),type:"number",min:"1",placeholder:"留空表示无限制",class:"form-input w-full"},null,512),[[S,i.rateLimitRequests]]),l[35]||(l[35]=t("p",{class:"text-xs text-gray-500 mt-2"},"在时间窗口内允许的最大请求次数(需要先设置时间窗口)",-1))]),t("div",null,[l[36]||(l[36]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"时间窗口内的 Token 使用量限制",-1)),v(t("input",{"onUpdate:modelValue":l[5]||(l[5]=u=>i.tokenLimit=u),type:"number",placeholder:"留空表示无限制",class:"form-input w-full"},null,512),[[S,i.tokenLimit]]),l[37]||(l[37]=t("p",{class:"text-xs text-gray-500 mt-2"},"在时间窗口内允许消耗的最大 Token 数量(需要先设置时间窗口)",-1))]),l[39]||(l[39]=t("div",{class:"bg-blue-100 rounded-lg p-3 mt-3"},[t("h5",{class:"text-sm font-semibold text-blue-800 mb-2"},"💡 使用示例"),t("div",{class:"text-xs text-blue-700 space-y-1"},[t("p",null,[t("strong",null,"示例1:"),f(" 时间窗口=60,请求次数限制=1000")]),t("p",{class:"ml-4"},"→ 每60分钟内最多1000次请求"),t("p",{class:"mt-2"},[t("strong",null,"示例2:"),f(" 时间窗口=1,Token限制=10000")]),t("p",{class:"ml-4"},"→ 每分钟最多消耗10,000个Token"),t("p",{class:"mt-2"},[t("strong",null,"示例3:"),f(" 时间窗口=30,请求次数限制=50,Token限制=100000")]),t("p",{class:"ml-4"},"→ 每30分钟内最多50次请求且总Token不超过100,000")])],-1))]),t("div",null,[l[41]||(l[41]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"每日费用限制 (美元)",-1)),t("div",Wt,[t("div",Yt,[t("button",{type:"button",onClick:l[6]||(l[6]=u=>i.dailyCostLimit="50"),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"$50"),t("button",{type:"button",onClick:l[7]||(l[7]=u=>i.dailyCostLimit="100"),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"$100"),t("button",{type:"button",onClick:l[8]||(l[8]=u=>i.dailyCostLimit="200"),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"$200"),t("button",{type:"button",onClick:l[9]||(l[9]=u=>i.dailyCostLimit=""),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"自定义")]),v(t("input",{"onUpdate:modelValue":l[10]||(l[10]=u=>i.dailyCostLimit=u),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[S,i.dailyCostLimit]]),l[40]||(l[40]=t("p",{class:"text-xs text-gray-500"},"设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制",-1))])]),t("div",null,[l[42]||(l[42]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"并发限制 (可选)",-1)),v(t("input",{"onUpdate:modelValue":l[11]||(l[11]=u=>i.concurrencyLimit=u),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[S,i.concurrencyLimit]]),l[43]||(l[43]=t("p",{class:"text-xs text-gray-500 mt-2"},"设置此 API Key 可同时处理的最大请求数,0 或留空表示无限制",-1))]),t("div",null,[l[44]||(l[44]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"备注 (可选)",-1)),v(t("textarea",{"onUpdate:modelValue":l[12]||(l[12]=u=>i.description=u),rows:"3",class:"form-input w-full resize-none",placeholder:"描述此 API Key 的用途..."},null,512),[[S,i.description]])]),t("div",null,[l[46]||(l[46]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"有效期限",-1)),v(t("select",{"onUpdate:modelValue":l[13]||(l[13]=u=>i.expireDuration=u),onChange:K,class:"form-input w-full"},l[45]||(l[45]=[t("option",{value:""},"永不过期",-1),t("option",{value:"1d"},"1 天",-1),t("option",{value:"7d"},"7 天",-1),t("option",{value:"30d"},"30 天",-1),t("option",{value:"90d"},"90 天",-1),t("option",{value:"180d"},"180 天",-1),t("option",{value:"365d"},"365 天",-1),t("option",{value:"custom"},"自定义日期",-1)]),544),[[Y,i.expireDuration]]),i.expireDuration==="custom"?(a(),d("div",zt,[v(t("input",{"onUpdate:modelValue":l[14]||(l[14]=u=>i.customExpireDate=u),type:"datetime-local",class:"form-input w-full",min:n.value,onChange:k},null,40,Nt),[[S,i.customExpireDate]])])):A("",!0),i.expiresAt?(a(),d("p",Ht," 将于 "+m(b(i.expiresAt))+" 过期 ",1)):A("",!0)]),t("div",null,[l[50]||(l[50]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"服务权限",-1)),t("div",Bt,[t("label",Gt,[v(t("input",{type:"radio","onUpdate:modelValue":l[15]||(l[15]=u=>i.permissions=u),value:"all",class:"mr-2"},null,512),[[B,i.permissions]]),l[47]||(l[47]=t("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),t("label",Qt,[v(t("input",{type:"radio","onUpdate:modelValue":l[16]||(l[16]=u=>i.permissions=u),value:"claude",class:"mr-2"},null,512),[[B,i.permissions]]),l[48]||(l[48]=t("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),t("label",Xt,[v(t("input",{type:"radio","onUpdate:modelValue":l[17]||(l[17]=u=>i.permissions=u),value:"gemini",class:"mr-2"},null,512),[[B,i.permissions]]),l[49]||(l[49]=t("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),l[51]||(l[51]=t("p",{class:"text-xs text-gray-500 mt-2"},"控制此 API Key 可以访问哪些服务",-1))]),t("div",null,[l[56]||(l[56]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"专属账号绑定 (可选)",-1)),t("div",Jt,[t("div",null,[l[53]||(l[53]=t("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),v(t("select",{"onUpdate:modelValue":l[18]||(l[18]=u=>i.claudeAccountId=u),class:"form-input w-full",disabled:i.permissions==="gemini"},[l[52]||(l[52]=t("option",{value:""},"使用共享账号池",-1)),(a(!0),d(T,null,_(D.accounts.claude.filter(u=>u.isDedicated),u=>(a(),d("option",{key:u.id,value:u.id},m(u.name)+" ("+m(u.status==="active"?"正常":"异常")+") ",9,te))),128))],8,Zt),[[Y,i.claudeAccountId]])]),t("div",null,[l[55]||(l[55]=t("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),v(t("select",{"onUpdate:modelValue":l[19]||(l[19]=u=>i.geminiAccountId=u),class:"form-input w-full",disabled:i.permissions==="claude"},[l[54]||(l[54]=t("option",{value:""},"使用共享账号池",-1)),(a(!0),d(T,null,_(D.accounts.gemini.filter(u=>u.isDedicated),u=>(a(),d("option",{key:u.id,value:u.id},m(u.name)+" ("+m(u.status==="active"?"正常":"异常")+") ",9,se))),128))],8,ee),[[Y,i.geminiAccountId]])])]),l[57]||(l[57]=t("p",{class:"text-xs text-gray-500 mt-2"},"选择专属账号后,此API Key将只使用该账号,不选择则使用共享账号池",-1))]),t("div",null,[t("div",le,[v(t("input",{type:"checkbox","onUpdate:modelValue":l[20]||(l[20]=u=>i.enableModelRestriction=u),id:"enableModelRestriction",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[G,i.enableModelRestriction]]),l[58]||(l[58]=t("label",{for:"enableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),i.enableModelRestriction?(a(),d("div",oe,[t("div",null,[l[61]||(l[61]=t("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"限制的模型列表",-1)),t("div",ne,[(a(!0),d(T,null,_(i.restrictedModels,(u,j)=>(a(),d("span",{key:j,class:"inline-flex items-center px-3 py-1 rounded-full text-sm bg-red-100 text-red-800"},[f(m(u)+" ",1),t("button",{type:"button",onClick:Q=>P(j),class:"ml-2 text-red-600 hover:text-red-800"},l[59]||(l[59]=[t("i",{class:"fas fa-times text-xs"},null,-1)]),8,ie)]))),128)),i.restrictedModels.length===0?(a(),d("span",ae," 暂无限制的模型 ")):A("",!0)]),t("div",re,[v(t("input",{"onUpdate:modelValue":l[21]||(l[21]=u=>i.modelInput=u),onKeydown:et(z(w,["prevent"]),["enter"]),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1"},null,40,de),[[S,i.modelInput]]),t("button",{type:"button",onClick:w,class:"px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors"},l[60]||(l[60]=[t("i",{class:"fas fa-plus"},null,-1)]))]),l[62]||(l[62]=t("p",{class:"text-xs text-gray-500 mt-2"},"设置此API Key无法访问的模型,例如:claude-opus-4-20250514",-1))])])):A("",!0)]),t("div",null,[t("div",ue,[v(t("input",{type:"checkbox","onUpdate:modelValue":l[22]||(l[22]=u=>i.enableClientRestriction=u),id:"enableClientRestriction",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[G,i.enableClientRestriction]]),l[63]||(l[63]=t("label",{for:"enableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),i.enableClientRestriction?(a(),d("div",me,[t("div",null,[l[64]||(l[64]=t("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"允许的客户端",-1)),l[65]||(l[65]=t("p",{class:"text-xs text-gray-500 mb-3"},"勾选允许使用此API Key的客户端",-1)),t("div",pe,[(a(!0),d(T,null,_(R.value,u=>(a(),d("div",{key:u.id,class:"flex items-start"},[v(t("input",{type:"checkbox",id:`client_${u.id}`,value:u.id,"onUpdate:modelValue":l[23]||(l[23]=j=>i.allowedClients=j),class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,ce),[[G,i.allowedClients]]),t("label",{for:`client_${u.id}`,class:"ml-2 flex-1 cursor-pointer"},[t("span",ge,m(u.name),1),t("span",ye,m(u.description),1)],8,xe)]))),128))])])])):A("",!0)]),t("div",fe,[t("button",{type:"button",onClick:l[24]||(l[24]=u=>y.$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"}," 取消 "),t("button",{type:"submit",disabled:I.value||!i.name,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[I.value?(a(),d("div",ve)):(a(),d("i",we)),f(" "+m(I.value?"创建中...":"创建"),1)],8,be)])],32)])])]))}},Ae=J($e,[["__scopeId","data-v-d14515d2"]]),Ce={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Ke={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},ke={class:"flex items-center justify-between mb-6"},Le=["value"],De={class:"space-y-3"},Ie={key:0,class:"flex flex-wrap gap-2"},Me=["onClick"],Re={class:"flex gap-2"},he=["onKeypress"],Se={class:"bg-blue-50 border border-blue-200 rounded-lg p-4 space-y-4"},Te={class:"space-y-3"},Pe={class:"flex gap-2"},_e={class:"flex gap-4"},Ee={class:"flex items-center cursor-pointer"},Ve={class:"flex items-center cursor-pointer"},je={class:"flex items-center cursor-pointer"},Ue={class:"grid grid-cols-1 gap-3"},qe=["disabled"],Fe=["value"],Oe=["disabled"],We=["value"],Ye={class:"flex items-center mb-3"},ze={key:0,class:"space-y-3"},Ne={class:"flex flex-wrap gap-2 mb-3 min-h-[32px] p-2 bg-gray-50 rounded-lg border border-gray-200"},He=["onClick"],Be={key:0,class:"text-gray-400 text-sm"},Ge={class:"flex gap-2"},Qe=["onKeydown"],Xe={class:"flex items-center mb-3"},Je={key:0,class:"space-y-3"},Ze={class:"space-y-2"},ts=["id","value"],es=["for"],ss={class:"text-sm font-medium text-gray-700"},ls={class:"text-xs text-gray-500 block"},os={class:"flex gap-3 pt-4"},ns=["disabled"],is={key:0,class:"loading-spinner mr-2"},as={key:1,class:"fas fa-save mr-2"},rs={__name:"EditApiKeyModal",props:{apiKey:{type:Object,required:!0},accounts:{type:Object,default:()=>({claude:[],gemini:[]})}},emits:["close","success"],setup(D,{emit:q}){const $=D,V=q;dt();const I=ut(),x=C(!1),R=C([]),i=C(""),n=it({name:"",tokenLimit:"",rateLimitWindow:"",rateLimitRequests:"",concurrencyLimit:"",dailyCostLimit:"",permissions:"all",claudeAccountId:"",geminiAccountId:"",enableModelRestriction:!1,restrictedModels:[],modelInput:"",enableClientRestriction:!1,allowedClients:[],tags:[]}),K=()=>{n.modelInput&&!n.restrictedModels.includes(n.modelInput)&&(n.restrictedModels.push(n.modelInput),n.modelInput="")},k=L=>{n.restrictedModels.splice(L,1)},b=()=>{if(i.value&&i.value.trim()){const L=i.value.trim();n.tags.includes(L)||n.tags.push(L),i.value=""}},w=L=>{n.tags.splice(L,1)},P=async()=>{x.value=!0;try{const L={tokenLimit:n.tokenLimit!==""&&n.tokenLimit!==null?parseInt(n.tokenLimit):0,rateLimitWindow:n.rateLimitWindow!==""&&n.rateLimitWindow!==null?parseInt(n.rateLimitWindow):0,rateLimitRequests:n.rateLimitRequests!==""&&n.rateLimitRequests!==null?parseInt(n.rateLimitRequests):0,concurrencyLimit:n.concurrencyLimit!==""&&n.concurrencyLimit!==null?parseInt(n.concurrencyLimit):0,dailyCostLimit:n.dailyCostLimit!==""&&n.dailyCostLimit!==null?parseFloat(n.dailyCostLimit):0,permissions:n.permissions,claudeAccountId:n.claudeAccountId||null,geminiAccountId:n.geminiAccountId||null,tags:n.tags};L.enableModelRestriction=n.enableModelRestriction,L.restrictedModels=n.restrictedModels,L.enableClientRestriction=n.enableClientRestriction,L.allowedClients=n.allowedClients;const o=await F.put(`/admin/api-keys/${$.apiKey.id}`,L);o.success?(V("success"),V("close")):M(o.message||"更新失败","error")}catch{M("更新失败","error")}finally{x.value=!1}};return at(async()=>{R.value=await I.loadSupportedClients(),n.name=$.apiKey.name,n.tokenLimit=$.apiKey.tokenLimit||"",n.rateLimitWindow=$.apiKey.rateLimitWindow||"",n.rateLimitRequests=$.apiKey.rateLimitRequests||"",n.concurrencyLimit=$.apiKey.concurrencyLimit||"",n.dailyCostLimit=$.apiKey.dailyCostLimit||"",n.permissions=$.apiKey.permissions||"all",n.claudeAccountId=$.apiKey.claudeAccountId||"",n.geminiAccountId=$.apiKey.geminiAccountId||"",n.restrictedModels=$.apiKey.restrictedModels||[],n.allowedClients=$.apiKey.allowedClients||[],n.tags=$.apiKey.tags||[],n.enableModelRestriction=n.restrictedModels.length>0,n.enableClientRestriction=n.allowedClients.length>0}),(L,o)=>(a(),W(st,{to:"body"},[t("div",Ce,[t("div",Ke,[t("div",ke,[o[22]||(o[22]=t("div",{class:"flex items-center gap-3"},[t("div",{class:"w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center"},[t("i",{class:"fas fa-edit text-white"})]),t("h3",{class:"text-xl font-bold text-gray-900"},"编辑 API Key")],-1)),t("button",{onClick:o[0]||(o[0]=p=>L.$emit("close")),class:"text-gray-400 hover:text-gray-600 transition-colors"},o[21]||(o[21]=[t("i",{class:"fas fa-times text-xl"},null,-1)]))]),t("form",{onSubmit:z(P,["prevent"]),class:"space-y-6 modal-scroll-content custom-scrollbar flex-1"},[t("div",null,[o[23]||(o[23]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"名称",-1)),t("input",{value:n.name,type:"text",disabled:"",class:"form-input w-full bg-gray-100 cursor-not-allowed"},null,8,Le),o[24]||(o[24]=t("p",{class:"text-xs text-gray-500 mt-2"},"名称不可修改",-1))]),t("div",null,[o[28]||(o[28]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"标签",-1)),t("div",De,[n.tags.length>0?(a(),d("div",Ie,[(a(!0),d(T,null,_(n.tags,(p,y)=>(a(),d("span",{key:y,class:"inline-flex items-center gap-1 px-3 py-1 bg-blue-100 text-blue-800 text-sm rounded-full"},[f(m(p)+" ",1),t("button",{type:"button",onClick:l=>w(y),class:"ml-1 hover:text-blue-900"},o[25]||(o[25]=[t("i",{class:"fas fa-times text-xs"},null,-1)]),8,Me)]))),128))])):A("",!0),t("div",Re,[v(t("input",{"onUpdate:modelValue":o[1]||(o[1]=p=>i.value=p),type:"text",class:"form-input flex-1",placeholder:"输入新标签名称",onKeypress:et(z(b,["prevent"]),["enter"])},null,40,he),[[S,i.value]]),t("button",{type:"button",onClick:b,class:"px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"},o[26]||(o[26]=[t("i",{class:"fas fa-plus"},null,-1)]))]),o[27]||(o[27]=t("p",{class:"text-xs text-gray-500"},"用于标记不同团队或用途,方便筛选管理",-1))])]),t("div",Se,[o[35]||(o[35]=t("div",{class:"flex items-start gap-3 mb-3"},[t("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[t("i",{class:"fas fa-tachometer-alt text-white text-sm"})]),t("div",{class:"flex-1"},[t("h4",{class:"font-semibold text-gray-800 mb-1"},"速率限制设置"),t("p",{class:"text-sm text-gray-600"},"控制 API Key 的使用频率和资源消耗")])],-1)),t("div",null,[o[29]||(o[29]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"时间窗口 (分钟)",-1)),v(t("input",{"onUpdate:modelValue":o[2]||(o[2]=p=>n.rateLimitWindow=p),type:"number",min:"1",placeholder:"留空表示无限制",class:"form-input w-full"},null,512),[[S,n.rateLimitWindow]]),o[30]||(o[30]=t("p",{class:"text-xs text-gray-500 mt-2"},"设置一个时间段(以分钟为单位),用于计算速率限制",-1))]),t("div",null,[o[31]||(o[31]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"时间窗口内的请求次数限制",-1)),v(t("input",{"onUpdate:modelValue":o[3]||(o[3]=p=>n.rateLimitRequests=p),type:"number",min:"1",placeholder:"留空表示无限制",class:"form-input w-full"},null,512),[[S,n.rateLimitRequests]]),o[32]||(o[32]=t("p",{class:"text-xs text-gray-500 mt-2"},"在时间窗口内允许的最大请求次数(需要先设置时间窗口)",-1))]),t("div",null,[o[33]||(o[33]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"时间窗口内的 Token 使用量限制",-1)),v(t("input",{"onUpdate:modelValue":o[4]||(o[4]=p=>n.tokenLimit=p),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[S,n.tokenLimit]]),o[34]||(o[34]=t("p",{class:"text-xs text-gray-500 mt-2"},"在时间窗口内允许消耗的最大 Token 数量(需要先设置时间窗口),0 或留空表示无限制",-1))]),o[36]||(o[36]=t("div",{class:"bg-blue-100 rounded-lg p-3 mt-3"},[t("h5",{class:"text-sm font-semibold text-blue-800 mb-2"},"💡 使用示例"),t("div",{class:"text-xs text-blue-700 space-y-1"},[t("p",null,[t("strong",null,"示例1:"),f(" 时间窗口=60,请求次数限制=100")]),t("p",{class:"ml-4"},"→ 每60分钟内最多允许100次请求"),t("p",{class:"mt-2"},[t("strong",null,"示例2:"),f(" 时间窗口=10,Token限制=50000")]),t("p",{class:"ml-4"},"→ 每10分钟内最多消耗50,000个Token"),t("p",{class:"mt-2"},[t("strong",null,"示例3:"),f(" 时间窗口=30,请求次数限制=50,Token限制=100000")]),t("p",{class:"ml-4"},"→ 每30分钟内最多50次请求且总Token不超过100,000")])],-1))]),t("div",null,[o[38]||(o[38]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"每日费用限制 (美元)",-1)),t("div",Te,[t("div",Pe,[t("button",{type:"button",onClick:o[5]||(o[5]=p=>n.dailyCostLimit="50"),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"$50"),t("button",{type:"button",onClick:o[6]||(o[6]=p=>n.dailyCostLimit="100"),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"$100"),t("button",{type:"button",onClick:o[7]||(o[7]=p=>n.dailyCostLimit="200"),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"$200"),t("button",{type:"button",onClick:o[8]||(o[8]=p=>n.dailyCostLimit=""),class:"px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-lg text-sm font-medium"},"自定义")]),v(t("input",{"onUpdate:modelValue":o[9]||(o[9]=p=>n.dailyCostLimit=p),type:"number",min:"0",step:"0.01",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[S,n.dailyCostLimit]]),o[37]||(o[37]=t("p",{class:"text-xs text-gray-500"},"设置此 API Key 每日的费用限制,超过限制将拒绝请求,0 或留空表示无限制",-1))])]),t("div",null,[o[39]||(o[39]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"并发限制",-1)),v(t("input",{"onUpdate:modelValue":o[10]||(o[10]=p=>n.concurrencyLimit=p),type:"number",min:"0",placeholder:"0 表示无限制",class:"form-input w-full"},null,512),[[S,n.concurrencyLimit]]),o[40]||(o[40]=t("p",{class:"text-xs text-gray-500 mt-2"},"设置此 API Key 可同时处理的最大请求数",-1))]),t("div",null,[o[44]||(o[44]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"服务权限",-1)),t("div",_e,[t("label",Ee,[v(t("input",{type:"radio","onUpdate:modelValue":o[11]||(o[11]=p=>n.permissions=p),value:"all",class:"mr-2"},null,512),[[B,n.permissions]]),o[41]||(o[41]=t("span",{class:"text-sm text-gray-700"},"全部服务",-1))]),t("label",Ve,[v(t("input",{type:"radio","onUpdate:modelValue":o[12]||(o[12]=p=>n.permissions=p),value:"claude",class:"mr-2"},null,512),[[B,n.permissions]]),o[42]||(o[42]=t("span",{class:"text-sm text-gray-700"},"仅 Claude",-1))]),t("label",je,[v(t("input",{type:"radio","onUpdate:modelValue":o[13]||(o[13]=p=>n.permissions=p),value:"gemini",class:"mr-2"},null,512),[[B,n.permissions]]),o[43]||(o[43]=t("span",{class:"text-sm text-gray-700"},"仅 Gemini",-1))])]),o[45]||(o[45]=t("p",{class:"text-xs text-gray-500 mt-2"},"控制此 API Key 可以访问哪些服务",-1))]),t("div",null,[o[50]||(o[50]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"专属账号绑定",-1)),t("div",Ue,[t("div",null,[o[47]||(o[47]=t("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Claude 专属账号",-1)),v(t("select",{"onUpdate:modelValue":o[14]||(o[14]=p=>n.claudeAccountId=p),class:"form-input w-full",disabled:n.permissions==="gemini"},[o[46]||(o[46]=t("option",{value:""},"使用共享账号池",-1)),(a(!0),d(T,null,_(D.accounts.claude,p=>(a(),d("option",{key:p.id,value:p.id},m(p.name)+" ("+m(p.status==="active"?"正常":"异常")+") ",9,Fe))),128))],8,qe),[[Y,n.claudeAccountId]])]),t("div",null,[o[49]||(o[49]=t("label",{class:"block text-sm font-medium text-gray-600 mb-1"},"Gemini 专属账号",-1)),v(t("select",{"onUpdate:modelValue":o[15]||(o[15]=p=>n.geminiAccountId=p),class:"form-input w-full",disabled:n.permissions==="claude"},[o[48]||(o[48]=t("option",{value:""},"使用共享账号池",-1)),(a(!0),d(T,null,_(D.accounts.gemini,p=>(a(),d("option",{key:p.id,value:p.id},m(p.name)+" ("+m(p.status==="active"?"正常":"异常")+") ",9,We))),128))],8,Oe),[[Y,n.geminiAccountId]])])]),o[51]||(o[51]=t("p",{class:"text-xs text-gray-500 mt-2"},"修改绑定账号将影响此API Key的请求路由",-1))]),t("div",null,[t("div",Ye,[v(t("input",{type:"checkbox","onUpdate:modelValue":o[16]||(o[16]=p=>n.enableModelRestriction=p),id:"editEnableModelRestriction",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[G,n.enableModelRestriction]]),o[52]||(o[52]=t("label",{for:"editEnableModelRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用模型限制 ",-1))]),n.enableModelRestriction?(a(),d("div",ze,[t("div",null,[o[55]||(o[55]=t("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"限制的模型列表",-1)),t("div",Ne,[(a(!0),d(T,null,_(n.restrictedModels,(p,y)=>(a(),d("span",{key:y,class:"inline-flex items-center px-3 py-1 rounded-full text-sm bg-red-100 text-red-800"},[f(m(p)+" ",1),t("button",{type:"button",onClick:l=>k(y),class:"ml-2 text-red-600 hover:text-red-800"},o[53]||(o[53]=[t("i",{class:"fas fa-times text-xs"},null,-1)]),8,He)]))),128)),n.restrictedModels.length===0?(a(),d("span",Be," 暂无限制的模型 ")):A("",!0)]),t("div",Ge,[v(t("input",{"onUpdate:modelValue":o[17]||(o[17]=p=>n.modelInput=p),onKeydown:et(z(K,["prevent"]),["enter"]),type:"text",placeholder:"输入模型名称,按回车添加",class:"form-input flex-1"},null,40,Qe),[[S,n.modelInput]]),t("button",{type:"button",onClick:K,class:"px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors"},o[54]||(o[54]=[t("i",{class:"fas fa-plus"},null,-1)]))]),o[56]||(o[56]=t("p",{class:"text-xs text-gray-500 mt-2"},"设置此API Key无法访问的模型,例如:claude-opus-4-20250514",-1))])])):A("",!0)]),t("div",null,[t("div",Xe,[v(t("input",{type:"checkbox","onUpdate:modelValue":o[18]||(o[18]=p=>n.enableClientRestriction=p),id:"editEnableClientRestriction",class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"},null,512),[[G,n.enableClientRestriction]]),o[57]||(o[57]=t("label",{for:"editEnableClientRestriction",class:"ml-2 text-sm font-semibold text-gray-700 cursor-pointer"}," 启用客户端限制 ",-1))]),n.enableClientRestriction?(a(),d("div",Je,[t("div",null,[o[58]||(o[58]=t("label",{class:"block text-sm font-medium text-gray-600 mb-2"},"允许的客户端",-1)),o[59]||(o[59]=t("p",{class:"text-xs text-gray-500 mb-3"},"勾选允许使用此API Key的客户端",-1)),t("div",Ze,[(a(!0),d(T,null,_(R.value,p=>(a(),d("div",{key:p.id,class:"flex items-start"},[v(t("input",{type:"checkbox",id:`edit_client_${p.id}`,value:p.id,"onUpdate:modelValue":o[19]||(o[19]=y=>n.allowedClients=y),class:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 mt-0.5"},null,8,ts),[[G,n.allowedClients]]),t("label",{for:`edit_client_${p.id}`,class:"ml-2 flex-1 cursor-pointer"},[t("span",ss,m(p.name),1),t("span",ls,m(p.description),1)],8,es)]))),128))])])])):A("",!0)]),t("div",os,[t("button",{type:"button",onClick:o[20]||(o[20]=p=>L.$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"}," 取消 "),t("button",{type:"submit",disabled:x.value,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[x.value?(a(),d("div",is)):(a(),d("i",as)),f(" "+m(x.value?"保存中...":"保存修改"),1)],8,ns)])],32)])])]))}},ds=J(rs,[["__scopeId","data-v-35ae96db"]]),us={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},ms={class:"modal-content w-full max-w-md p-8 mx-auto max-h-[90vh] flex flex-col"},ps={class:"flex items-center justify-between mb-6"},cs={class:"space-y-6 modal-scroll-content custom-scrollbar flex-1"},xs={class:"bg-blue-50 border border-blue-200 rounded-lg p-4"},gs={class:"flex items-start gap-3"},ys={class:"text-sm text-gray-700"},fs={class:"text-xs text-gray-600 mt-1"},bs={key:0,class:"mt-3"},vs=["min"],ws={key:1,class:"text-xs text-gray-500 mt-2"},$s={class:"flex gap-3 pt-4"},As=["disabled"],Cs={key:0,class:"loading-spinner mr-2"},Ks={key:1,class:"fas fa-clock mr-2"},ks={__name:"RenewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close","success"],setup(D,{emit:q}){const $=D,V=q;dt();const I=C(!1),x=it({renewDuration:"30d",customExpireDate:"",newExpiresAt:null}),R=rt(()=>{const b=new Date;return $.apiKey.expiresAt&&new Date($.apiKey.expiresAt)>b?new Date($.apiKey.expiresAt).toISOString().slice(0,16):(b.setMinutes(b.getMinutes()+1),b.toISOString().slice(0,16))}),i=b=>new Date(b).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}),n=()=>{if(!x.renewDuration){x.newExpiresAt=null;return}if(x.renewDuration==="permanent"){x.newExpiresAt=null;return}if(x.renewDuration==="custom")return;const b=$.apiKey.expiresAt&&new Date($.apiKey.expiresAt)>new Date?new Date($.apiKey.expiresAt):new Date,P=x.renewDuration.match(/(\d+)([dhmy])/);if(P){const[,L,o]=P,p=parseInt(L);switch(o){case"d":b.setDate(b.getDate()+p);break;case"h":b.setHours(b.getHours()+p);break;case"m":b.setMonth(b.getMonth()+p);break;case"y":b.setFullYear(b.getFullYear()+p);break}x.newExpiresAt=b.toISOString()}},K=()=>{x.customExpireDate&&(x.newExpiresAt=new Date(x.customExpireDate).toISOString())},k=async()=>{I.value=!0;try{const b={expiresAt:x.renewDuration==="permanent"?null:x.newExpiresAt},w=await F.put(`/admin/api-keys/${$.apiKey.id}/renew`,b);w.success?(M("API Key 续期成功","success"),V("success"),V("close")):M(w.message||"续期失败","error")}catch{M("续期失败","error")}finally{I.value=!1}};return n(),(b,w)=>(a(),W(st,{to:"body"},[t("div",us,[t("div",ms,[t("div",ps,[w[5]||(w[5]=t("div",{class:"flex items-center gap-3"},[t("div",{class:"w-10 h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[t("i",{class:"fas fa-clock text-white"})]),t("h3",{class:"text-xl font-bold text-gray-900"},"续期 API Key")],-1)),t("button",{onClick:w[0]||(w[0]=P=>b.$emit("close")),class:"text-gray-400 hover:text-gray-600 transition-colors"},w[4]||(w[4]=[t("i",{class:"fas fa-times text-xl"},null,-1)]))]),t("div",cs,[t("div",xs,[t("div",gs,[w[7]||(w[7]=t("div",{class:"w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center flex-shrink-0"},[t("i",{class:"fas fa-info text-white text-sm"})],-1)),t("div",null,[w[6]||(w[6]=t("h4",{class:"font-semibold text-gray-800 mb-1"},"API Key 信息",-1)),t("p",ys,m(D.apiKey.name),1),t("p",fs," 当前过期时间:"+m(D.apiKey.expiresAt?i(D.apiKey.expiresAt):"永不过期"),1)])])]),t("div",null,[w[9]||(w[9]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-3"},"续期时长",-1)),v(t("select",{"onUpdate:modelValue":w[1]||(w[1]=P=>x.renewDuration=P),onChange:n,class:"form-input w-full"},w[8]||(w[8]=[t("option",{value:"7d"},"延长 7 天",-1),t("option",{value:"30d"},"延长 30 天",-1),t("option",{value:"90d"},"延长 90 天",-1),t("option",{value:"180d"},"延长 180 天",-1),t("option",{value:"365d"},"延长 365 天",-1),t("option",{value:"custom"},"自定义日期",-1),t("option",{value:"permanent"},"设为永不过期",-1)]),544),[[Y,x.renewDuration]]),x.renewDuration==="custom"?(a(),d("div",bs,[v(t("input",{"onUpdate:modelValue":w[2]||(w[2]=P=>x.customExpireDate=P),type:"datetime-local",class:"form-input w-full",min:R.value,onChange:K},null,40,vs),[[S,x.customExpireDate]])])):A("",!0),x.newExpiresAt?(a(),d("p",ws," 新的过期时间:"+m(i(x.newExpiresAt)),1)):A("",!0)])]),t("div",$s,[t("button",{type:"button",onClick:w[3]||(w[3]=P=>b.$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"}," 取消 "),t("button",{type:"button",onClick:k,disabled:I.value||!x.renewDuration,class:"btn btn-primary flex-1 py-3 px-6 font-semibold"},[I.value?(a(),d("div",Cs)):(a(),d("i",Ks)),f(" "+m(I.value?"续期中...":"确认续期"),1)],8,As)])])])]))}},Ls=J(ks,[["__scopeId","data-v-5486ec2f"]]),Ds={class:"fixed inset-0 modal z-50 flex items-center justify-center p-4"},Is={class:"modal-content w-full max-w-lg p-8 mx-auto max-h-[90vh] overflow-y-auto custom-scrollbar"},Ms={class:"space-y-4 mb-6"},Rs={class:"p-3 bg-gray-50 rounded-lg border"},hs={class:"text-gray-900 font-medium"},Ss={key:0},Ts={class:"p-3 bg-gray-50 rounded-lg border"},Ps={class:"text-gray-700"},_s={class:"relative"},Es={class:"p-4 pr-14 bg-gray-900 rounded-lg border font-mono text-sm text-white break-all min-h-[60px] flex items-center"},Vs={class:"absolute top-3 right-3"},js=["title"],Us={__name:"NewApiKeyModal",props:{apiKey:{type:Object,required:!0}},emits:["close"],setup(D,{emit:q}){const $=D,V=q,I=C(!1),x=()=>{I.value=!I.value},R=()=>{const K=$.apiKey.apiKey||$.apiKey.key||"";return K?I.value||K.length<=12?K:K.substring(0,8)+"●".repeat(Math.max(0,K.length-12))+K.substring(K.length-4):""},i=async()=>{const K=$.apiKey.apiKey||$.apiKey.key||"";if(!K){M("API Key 不存在","error");return}try{await navigator.clipboard.writeText(K),M("API Key 已复制到剪贴板","success")}catch(k){console.error("Failed to copy:",k);const b=document.createElement("textarea");b.value=K,document.body.appendChild(b),b.select();try{document.execCommand("copy"),M("API Key 已复制到剪贴板","success")}catch{M("复制失败,请手动复制","error")}finally{document.body.removeChild(b)}}},n=()=>{confirm(`关闭后将无法再次查看完整的API Key,请确保已经妥善保存。
|
||
|
||
确定要关闭吗?`)&&V("close")};return(K,k)=>(a(),W(st,{to:"body"},[t("div",Ds,[t("div",Is,[t("div",{class:"flex items-center justify-between mb-6"},[k[1]||(k[1]=t("div",{class:"flex items-center gap-3"},[t("div",{class:"w-12 h-12 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center"},[t("i",{class:"fas fa-check text-white text-lg"})]),t("div",null,[t("h3",{class:"text-xl font-bold text-gray-900"},"API Key 创建成功"),t("p",{class:"text-sm text-gray-600"},"请妥善保存您的 API Key")])],-1)),t("button",{onClick:n,class:"text-gray-400 hover:text-gray-600 transition-colors"},k[0]||(k[0]=[t("i",{class:"fas fa-times text-xl"},null,-1)]))]),k[7]||(k[7]=t("div",{class:"bg-amber-50 border-l-4 border-amber-400 p-4 mb-6"},[t("div",{class:"flex items-start"},[t("div",{class:"w-6 h-6 bg-amber-400 rounded-lg flex items-center justify-center flex-shrink-0 mt-0.5"},[t("i",{class:"fas fa-exclamation-triangle text-white text-sm"})]),t("div",{class:"ml-3"},[t("h5",{class:"font-semibold text-amber-900 mb-1"},"重要提醒"),t("p",{class:"text-sm text-amber-800"}," 这是您唯一能看到完整 API Key 的机会。关闭此窗口后,系统将不再显示完整的 API Key。请立即复制并妥善保存。 ")])])],-1)),t("div",Ms,[t("div",null,[k[2]||(k[2]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"API Key 名称",-1)),t("div",Rs,[t("span",hs,m(D.apiKey.name),1)])]),D.apiKey.description?(a(),d("div",Ss,[k[3]||(k[3]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"备注",-1)),t("div",Ts,[t("span",Ps,m(D.apiKey.description||"无描述"),1)])])):A("",!0),t("div",null,[k[4]||(k[4]=t("label",{class:"block text-sm font-semibold text-gray-700 mb-2"},"API Key",-1)),t("div",_s,[t("div",Es,m(R()),1),t("div",Vs,[t("button",{onClick:x,type:"button",class:"btn-icon-sm hover:bg-gray-800 bg-gray-700",title:I.value?"隐藏API Key":"显示完整API Key"},[t("i",{class:U(["fas",I.value?"fa-eye-slash":"fa-eye","text-gray-300"])},null,2)],8,js)])]),k[5]||(k[5]=t("p",{class:"text-xs text-gray-500 mt-2"}," 点击眼睛图标切换显示模式,使用下方按钮复制完整 API Key ",-1))])]),t("div",{class:"flex gap-3"},[t("button",{onClick:i,class:"flex-1 btn btn-primary py-3 px-6 font-semibold flex items-center justify-center gap-2"},k[6]||(k[6]=[t("i",{class:"fas fa-copy"},null,-1),f(" 复制 API Key ",-1)])),t("button",{onClick:n,class:"px-6 py-3 bg-gray-100 text-gray-700 rounded-xl font-semibold hover:bg-gray-200 transition-colors"}," 我已保存 ")])])])]))}},qs=J(Us,[["__scopeId","data-v-3a595107"]]),Fs={class:"tab-content"},Os={class:"card p-6"},Ws={class:"flex flex-col md:flex-row justify-between items-center gap-4 mb-6"},Ys={class:"flex items-center gap-3"},zs=["value"],Ns={key:0,class:"text-center py-12"},Hs={key:1,class:"text-center py-12"},Bs={key:2,class:"table-container"},Gs={class:"min-w-full"},Qs={class:"bg-gray-50/80 backdrop-blur-sm"},Xs={key:1,class:"fas fa-sort ml-1 text-gray-400"},Js={key:1,class:"fas fa-sort ml-1 text-gray-400"},Zs={class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"},tl={key:1,class:"fas fa-sort ml-1 text-gray-400"},el={key:1,class:"fas fa-sort ml-1 text-gray-400"},sl={key:1,class:"fas fa-sort ml-1 text-gray-400"},ll={class:"divide-y divide-gray-200/50"},ol={class:"table-row"},nl={class:"px-6 py-4 whitespace-nowrap"},il={class:"flex items-center"},al={class:"text-sm font-semibold text-gray-900"},rl={class:"text-xs text-gray-500"},dl={class:"text-xs text-gray-500 mt-1"},ul={key:0},ml={key:1},pl={class:"px-6 py-4"},cl={class:"flex flex-wrap gap-1"},xl={key:0,class:"text-xs text-gray-400"},gl={class:"px-6 py-4 whitespace-nowrap"},yl={class:"text-sm font-mono text-gray-600 bg-gray-50 px-3 py-1 rounded-lg"},fl={class:"px-6 py-4 whitespace-nowrap"},bl={class:"px-6 py-4"},vl={class:"space-y-1"},wl={class:"flex justify-between text-sm"},$l={class:"font-medium text-gray-900"},Al={class:"flex justify-between text-sm"},Cl={class:"font-medium text-gray-900"},Kl={class:"flex justify-between text-sm"},kl={class:"font-medium text-green-600"},Ll={key:0,class:"flex justify-between text-sm"},Dl={class:"flex justify-between text-sm"},Il={class:"font-medium text-purple-600"},Ml={class:"flex justify-between text-sm"},Rl={key:0,class:"text-xs text-gray-500"},hl={key:1,class:"flex justify-between text-sm"},Sl={class:"font-medium text-indigo-600"},Tl={key:2,class:"flex justify-between text-sm"},Pl={class:"font-medium text-indigo-600"},_l={class:"flex justify-between text-xs text-gray-500"},El={key:3,class:"flex justify-between text-xs text-orange-500"},Vl={class:"flex justify-between text-xs text-blue-600"},jl={class:"pt-1 border-t border-gray-100"},Ul={class:"flex justify-between text-xs text-green-600"},ql={class:"pt-2"},Fl=["onClick"],Ol={class:"px-6 py-4 whitespace-nowrap text-sm text-gray-500"},Wl={class:"px-6 py-4 whitespace-nowrap text-sm"},Yl={key:0},zl={key:0,class:"text-red-600"},Nl={key:1,class:"text-orange-600"},Hl={key:2,class:"text-gray-600"},Bl={key:1,class:"text-gray-400"},Gl={class:"px-6 py-4 whitespace-nowrap text-sm"},Ql={class:"flex gap-2"},Xl=["onClick"],Jl=["onClick"],Zl=["onClick"],to=["onClick"],eo={key:0},so={colspan:"7",class:"px-6 py-4 bg-gray-50"},lo={key:0,class:"text-center py-4"},oo={class:"space-y-4"},no={class:"flex items-center justify-between mb-4"},io={class:"flex items-center gap-2"},ao={key:0,class:"text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded-full"},ro={class:"flex gap-1 items-center"},uo={class:"flex gap-1 bg-gray-100 rounded p-1"},mo=["onClick"],po={key:0,class:"text-center py-8"},co={class:"flex items-center justify-center gap-2 mb-3"},xo=["onClick"],go={key:1,class:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"},yo={class:"flex justify-between items-start mb-3"},fo={class:"flex-1"},bo={class:"text-sm font-semibold text-gray-800 block mb-1"},vo={class:"text-xs text-gray-500 bg-blue-50 px-2 py-1 rounded-full"},wo={class:"space-y-2 mb-3"},$o={class:"flex justify-between items-center text-sm"},Ao={class:"font-semibold text-gray-900"},Co={class:"flex justify-between items-center text-sm"},Ko={class:"font-semibold text-green-600"},ko={class:"pt-2 mt-2 border-t border-gray-100"},Lo={class:"flex justify-between items-center text-xs text-gray-500"},Do={class:"font-medium"},Io={class:"flex justify-between items-center text-xs text-gray-500"},Mo={class:"font-medium"},Ro={key:0,class:"flex justify-between items-center text-xs text-purple-600"},ho={class:"font-medium"},So={key:1,class:"flex justify-between items-center text-xs text-purple-600"},To={class:"font-medium"},Po={class:"w-full bg-gray-200 rounded-full h-2 mt-3"},_o={class:"text-right mt-1"},Eo={class:"text-xs font-medium text-indigo-600"},Vo={key:2,class:"mt-4 p-3 bg-gradient-to-r from-indigo-50 to-purple-50 rounded-lg border border-indigo-100"},jo={class:"flex items-center justify-between text-sm"},Uo={class:"flex gap-4 text-xs"},qo={class:"text-gray-600"},Fo={class:"font-semibold text-gray-800"},Oo={class:"text-gray-600"},Wo={class:"font-semibold text-gray-800"},Yo={__name:"ApiKeysView",setup(D){const q=ut(),$=C([]),V=C(!1),I=C("today"),x=C(""),R=C("asc"),i=C({}),n=C({}),K=C({}),k=C([new Date(2e3,1,1,0,0,0),new Date(2e3,2,1,23,59,59)]),b=C({claude:[],gemini:[]}),w=C(""),P=C([]),L=C(!1),o=C(!1),p=C(!1),y=C(!1),l=C(null),u=C(null),j=C(null),Q=rt(()=>{let r=$.value;return w.value&&(r=$.value.filter(g=>g.tags&&g.tags.includes(w.value))),x.value?[...r].sort((g,s)=>{let c=g[x.value],h=s[x.value];return x.value==="status"?(c=g.isActive?1:0,h=s.isActive?1:0):x.value==="cost"?(c=parseFloat(lt(g.usage).replace("$","")),h=parseFloat(lt(s.usage).replace("$",""))):(x.value==="createdAt"||x.value==="expiresAt")&&(c=c?new Date(c).getTime():0,h=h?new Date(h).getTime():0),c<h?R.value==="asc"?-1:1:c>h?R.value==="asc"?1:-1:0}):r}),N=async()=>{try{const[r,e]=await Promise.all([F.get("/admin/claude-accounts"),F.get("/admin/gemini-accounts")]);r.success&&(b.value.claude=r.data||[]),e.success&&(b.value.gemini=e.data||[])}catch(r){console.error("加载账户列表失败:",r)}},H=async()=>{V.value=!0;try{const r=await F.get(`/admin/api-keys?timeRange=${I.value}`);if(r.success){$.value=r.data||[];const e=new Set;$.value.forEach(g=>{g.tags&&Array.isArray(g.tags)&&g.tags.forEach(s=>e.add(s))}),P.value=Array.from(e).sort()}}catch{M("加载 API Keys 失败","error")}finally{V.value=!1}},X=r=>{x.value===r?R.value=R.value==="asc"?"desc":"asc":(x.value=r,R.value="asc")},E=r=>!r&&r!==0?"0":r.toLocaleString("zh-CN"),lt=r=>!r||!r.total?"$0.0000":`$${(r.total.cost||0).toFixed(4)}`,yt=r=>{if(!r)return"未知账户";const e=b.value.claude.find(s=>s.id===r);if(e)return e.name;const g=b.value.gemini.find(s=>s.id===r);return g?g.name:`账户-${r.substring(0,8)}`},ot=r=>r?new Date(r)<new Date:!1,mt=r=>!r||ot(r)?!1:(new Date(r)-new Date)/(1e3*60*60*24)<=7,pt=r=>r?new Date(r).toLocaleDateString("zh-CN"):"",ft=async r=>{i.value[r]?i.value[r]=!1:(i.value[r]=!0,K.value[r]||xt(r),await Z(r,!0))},Z=async(r,e=!1)=>{if(!e&&n.value[r]&&n.value[r].length>0)return;const g=O(r);try{let s=`/admin/api-keys/${r}/model-stats`;const c=new URLSearchParams;if(g.customStart&&g.customEnd)c.append("startDate",g.customStart),c.append("endDate",g.customEnd),c.append("period","custom");else{const tt=g.preset==="today"?"daily":"monthly";c.append("period",tt)}s+="?"+c.toString();const h=await F.get(s);h.success&&(n.value[r]=h.data||[])}catch{M("加载模型统计失败","error"),n.value[r]=[]}},ct=(r,e)=>{const g=e.reduce((s,c)=>s+(c.allTokens||0),0);return g===0?0:Math.round(r/g*100)},bt=r=>r.formatted&&r.formatted.total?r.formatted.total:r.cost!==void 0?`$${r.cost.toFixed(6)}`:"$0.000000",xt=r=>{const e=new Date,g=new Date(e);g.setDate(e.getDate()-6),K.value[r]={type:"preset",preset:"7days",customStart:g.toISOString().split("T")[0],customEnd:e.toISOString().split("T")[0],customRange:null,presetOptions:[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}]}},O=r=>(K.value[r]||xt(r),K.value[r]),gt=(r,e)=>{const g=O(e);g.type="preset",g.preset=r;const s=g.presetOptions.find(c=>c.value===r);if(s){const c=new Date,h=new Date(c);h.setDate(c.getDate()-(s.days-1)),g.customStart=h.toISOString().split("T")[0],g.customEnd=c.toISOString().split("T")[0];const tt=nt=>nt.getFullYear()+"-"+String(nt.getMonth()+1).padStart(2,"0")+"-"+String(nt.getDate()).padStart(2,"0")+" 00:00:00";g.customRange=[tt(h),tt(c)]}Z(e,!0)},vt=(r,e)=>{const g=O(r);e&&e.length===2?(g.type="custom",g.preset="",g.customRange=e,g.customStart=e[0].split(" ")[0],g.customEnd=e[1].split(" ")[0],Z(r,!0)):e===null&>("7days",r)},wt=r=>r>new Date,$t=r=>{const e=O(r);e.type="preset",e.preset="7days";const g=new Date,s=new Date(g);s.setDate(g.getDate()-6),e.customStart=s.toISOString().split("T")[0],e.customEnd=g.toISOString().split("T")[0],e.customRange=null,Z(r,!0),M("已重置筛选条件并刷新数据","info")},At=()=>{L.value=!0},Ct=r=>{l.value=r,o.value=!0},Kt=r=>{u.value=r,p.value=!0},kt=r=>{L.value=!1,j.value=r,y.value=!0,H()},Lt=()=>{o.value=!1,M("API Key 更新成功","success"),H()},Dt=()=>{p.value=!1,M("API Key 续期成功","success"),H()},It=async r=>{if(confirm("确定要删除这个 API Key 吗?此操作不可恢复。"))try{const e=await F.delete(`/admin/api-keys/${r}`);e.success?(M("API Key 已删除","success"),H()):M(e.message||"删除失败","error")}catch{M("删除失败","error")}},Mt=r=>{const g=`${window.location.origin}/admin/api-stats?apiId=${r.id}`,s=document.createElement("textarea");s.value=g,s.style.position="fixed",s.style.opacity="0",s.style.left="-9999px",document.body.appendChild(s),s.select(),s.setSelectionRange(0,99999);try{document.execCommand("copy")?M("已复制统计页面链接","success"):(M("复制失败,请手动复制","error"),console.log("统计页面链接:",g))}catch(c){M("复制失败,请手动复制","error"),console.error("复制错误:",c),console.log("统计页面链接:",g)}finally{document.body.removeChild(s)}};return at(async()=>{await Promise.all([q.loadSupportedClients(),N(),H()])}),(r,e)=>{const g=Rt;return a(),d("div",Fs,[t("div",Os,[t("div",Ws,[e[15]||(e[15]=t("div",null,[t("h3",{class:"text-xl font-bold text-gray-900 mb-2"},"API Keys 管理"),t("p",{class:"text-gray-600"},"管理和监控您的 API 密钥")],-1)),t("div",Ys,[v(t("select",{"onUpdate:modelValue":e[0]||(e[0]=s=>I.value=s),onChange:e[1]||(e[1]=s=>H()),class:"form-input px-3 py-2 text-sm"},e[12]||(e[12]=[t("option",{value:"today"},"今日",-1),t("option",{value:"7days"},"最近7天",-1),t("option",{value:"monthly"},"本月",-1),t("option",{value:"all"},"全部时间",-1)]),544),[[Y,I.value]]),v(t("select",{"onUpdate:modelValue":e[2]||(e[2]=s=>w.value=s),class:"form-input px-3 py-2 text-sm"},[e[13]||(e[13]=t("option",{value:""},"所有标签",-1)),(a(!0),d(T,null,_(P.value,s=>(a(),d("option",{key:s,value:s},m(s),9,zs))),128))],512),[[Y,w.value]]),t("button",{onClick:z(At,["stop"]),class:"btn btn-primary px-6 py-3 flex items-center gap-2"},e[14]||(e[14]=[t("i",{class:"fas fa-plus"},null,-1),f("创建新 Key ",-1)]))])]),V.value?(a(),d("div",Ns,e[16]||(e[16]=[t("div",{class:"loading-spinner mx-auto mb-4"},null,-1),t("p",{class:"text-gray-500"},"正在加载 API Keys...",-1)]))):$.value.length===0?(a(),d("div",Hs,e[17]||(e[17]=[t("div",{class:"w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center"},[t("i",{class:"fas fa-key text-gray-400 text-xl"})],-1),t("p",{class:"text-gray-500 text-lg"},"暂无 API Keys",-1),t("p",{class:"text-gray-400 text-sm mt-2"},"点击上方按钮创建您的第一个 API Key",-1)]))):(a(),d("div",Bs,[t("table",Gs,[t("thead",Qs,[t("tr",null,[t("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:e[3]||(e[3]=s=>X("name"))},[e[18]||(e[18]=f(" 名称 ",-1)),x.value==="name"?(a(),d("i",{key:0,class:U(["fas",R.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),d("i",Xs))]),e[25]||(e[25]=t("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"},"标签",-1)),e[26]||(e[26]=t("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"},"API Key",-1)),t("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:e[4]||(e[4]=s=>X("status"))},[e[19]||(e[19]=f(" 状态 ",-1)),x.value==="status"?(a(),d("i",{key:0,class:U(["fas",R.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),d("i",Js))]),t("th",Zs,[e[22]||(e[22]=f(" 使用统计 ",-1)),t("span",{class:"cursor-pointer hover:bg-gray-100 px-2 py-1 rounded",onClick:e[5]||(e[5]=s=>X("cost"))},[e[20]||(e[20]=f(" (费用 ",-1)),x.value==="cost"?(a(),d("i",{key:0,class:U(["fas",R.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),d("i",tl)),e[21]||(e[21]=f(") ",-1))])]),t("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:e[6]||(e[6]=s=>X("createdAt"))},[e[23]||(e[23]=f(" 创建时间 ",-1)),x.value==="createdAt"?(a(),d("i",{key:0,class:U(["fas",R.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),d("i",el))]),t("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:e[7]||(e[7]=s=>X("expiresAt"))},[e[24]||(e[24]=f(" 过期时间 ",-1)),x.value==="expiresAt"?(a(),d("i",{key:0,class:U(["fas",R.value==="asc"?"fa-sort-up":"fa-sort-down","ml-1"])},null,2)):(a(),d("i",sl))]),e[27]||(e[27]=t("th",{class:"px-6 py-4 text-left text-xs font-bold text-gray-700 uppercase tracking-wider"},"操作",-1))])]),t("tbody",ll,[(a(!0),d(T,null,_(Q.value,s=>(a(),d(T,{key:s.id},[t("tr",ol,[t("td",nl,[t("div",il,[e[30]||(e[30]=t("div",{class:"w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3"},[t("i",{class:"fas fa-key text-white text-xs"})],-1)),t("div",null,[t("div",al,m(s.name),1),t("div",rl,m(s.id),1),t("div",dl,[s.claudeAccountId?(a(),d("span",ul,[e[28]||(e[28]=t("i",{class:"fas fa-link mr-1"},null,-1)),f(" 绑定: "+m(yt(s.claudeAccountId)),1)])):(a(),d("span",ml,e[29]||(e[29]=[t("i",{class:"fas fa-share-alt mr-1"},null,-1),f(" 使用共享池 ",-1)])))])])])]),t("td",pl,[t("div",cl,[(a(!0),d(T,null,_(s.tags||[],c=>(a(),d("span",{key:c,class:"inline-flex items-center px-2 py-0.5 bg-blue-100 text-blue-800 text-xs rounded-full"},m(c),1))),128)),!s.tags||s.tags.length===0?(a(),d("span",xl,"无标签")):A("",!0)])]),t("td",gl,[t("div",yl,m((s.apiKey||"").substring(0,20))+"... ",1)]),t("td",fl,[t("span",{class:U(["inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold",s.isActive?"bg-green-100 text-green-800":"bg-red-100 text-red-800"])},[t("div",{class:U(["w-2 h-2 rounded-full mr-2",s.isActive?"bg-green-500":"bg-red-500"])},null,2),f(" "+m(s.isActive?"活跃":"禁用"),1)],2)]),t("td",bl,[t("div",vl,[t("div",wl,[e[31]||(e[31]=t("span",{class:"text-gray-600"},"请求数:",-1)),t("span",$l,m(E(s.usage&&s.usage.total&&s.usage.total.requests||0)),1)]),t("div",Al,[e[32]||(e[32]=t("span",{class:"text-gray-600"},"Token:",-1)),t("span",Cl,m(E(s.usage&&s.usage.total&&s.usage.total.tokens||0)),1)]),t("div",Kl,[e[33]||(e[33]=t("span",{class:"text-gray-600"},"费用:",-1)),t("span",kl,m(lt(s.usage)),1)]),s.dailyCostLimit>0?(a(),d("div",Ll,[e[34]||(e[34]=t("span",{class:"text-gray-600"},"今日费用:",-1)),t("span",{class:U(["font-medium",(s.dailyCost||0)>=s.dailyCostLimit?"text-red-600":"text-blue-600"])}," $"+m((s.dailyCost||0).toFixed(2))+" / $"+m(s.dailyCostLimit.toFixed(2)),3)])):A("",!0),t("div",Dl,[e[35]||(e[35]=t("span",{class:"text-gray-600"},"并发限制:",-1)),t("span",Il,m(s.concurrencyLimit>0?s.concurrencyLimit:"无限制"),1)]),t("div",Ml,[e[36]||(e[36]=t("span",{class:"text-gray-600"},"当前并发:",-1)),t("span",{class:U(["font-medium",s.currentConcurrency>0?"text-orange-600":"text-gray-600"])},[f(m(s.currentConcurrency||0)+" ",1),s.concurrencyLimit>0?(a(),d("span",Rl,"/ "+m(s.concurrencyLimit),1)):A("",!0)],2)]),s.rateLimitWindow>0?(a(),d("div",hl,[e[37]||(e[37]=t("span",{class:"text-gray-600"},"时间窗口:",-1)),t("span",Sl,m(s.rateLimitWindow)+" 分钟",1)])):A("",!0),s.rateLimitRequests>0?(a(),d("div",Tl,[e[38]||(e[38]=t("span",{class:"text-gray-600"},"请求限制:",-1)),t("span",Pl,m(s.rateLimitRequests)+" 次/窗口",1)])):A("",!0),t("div",_l,[t("span",null,"输入: "+m(E(s.usage&&s.usage.total&&s.usage.total.inputTokens||0)),1),t("span",null,"输出: "+m(E(s.usage&&s.usage.total&&s.usage.total.outputTokens||0)),1)]),(s.usage&&s.usage.total&&s.usage.total.cacheCreateTokens||0)>0||(s.usage&&s.usage.total&&s.usage.total.cacheReadTokens||0)>0?(a(),d("div",El,[t("span",null,"缓存创建: "+m(E(s.usage&&s.usage.total&&s.usage.total.cacheCreateTokens||0)),1),t("span",null,"缓存读取: "+m(E(s.usage&&s.usage.total&&s.usage.total.cacheReadTokens||0)),1)])):A("",!0),t("div",Vl,[t("span",null,"RPM: "+m(s.usage&&s.usage.averages&&s.usage.averages.rpm||0),1),t("span",null,"TPM: "+m(s.usage&&s.usage.averages&&s.usage.averages.tpm||0),1)]),t("div",jl,[t("div",Ul,[t("span",null,"今日: "+m(E(s.usage&&s.usage.daily&&s.usage.daily.requests||0))+"次",1),t("span",null,m(E(s.usage&&s.usage.daily&&s.usage.daily.tokens||0))+"T",1)])]),t("div",ql,[s&&s.id?(a(),d("button",{key:0,onClick:c=>ft(s.id),class:"text-xs text-indigo-600 hover:text-indigo-800 font-medium"},[t("i",{class:U(["fas",i.value[s.id]?"fa-chevron-up":"fa-chevron-down","mr-1"])},null,2),e[39]||(e[39]=f(" 模型使用分布 ",-1))],8,Fl)):A("",!0)])])]),t("td",Ol,m(new Date(s.createdAt).toLocaleDateString()),1),t("td",Wl,[s.expiresAt?(a(),d("div",Yl,[ot(s.expiresAt)?(a(),d("div",zl,e[40]||(e[40]=[t("i",{class:"fas fa-exclamation-circle mr-1"},null,-1),f(" 已过期 ",-1)]))):mt(s.expiresAt)?(a(),d("div",Nl,[e[41]||(e[41]=t("i",{class:"fas fa-clock mr-1"},null,-1)),f(" "+m(pt(s.expiresAt)),1)])):(a(),d("div",Hl,m(pt(s.expiresAt)),1))])):(a(),d("div",Bl,e[42]||(e[42]=[t("i",{class:"fas fa-infinity mr-1"},null,-1),f(" 永不过期 ",-1)])))]),t("td",Gl,[t("div",Ql,[t("button",{onClick:c=>Mt(s),class:"text-purple-600 hover:text-purple-900 font-medium hover:bg-purple-50 px-3 py-1 rounded-lg transition-colors",title:"复制统计页面链接"},e[43]||(e[43]=[t("i",{class:"fas fa-chart-bar mr-1"},null,-1),f("统计 ",-1)]),8,Xl),t("button",{onClick:c=>Ct(s),class:"text-blue-600 hover:text-blue-900 font-medium hover:bg-blue-50 px-3 py-1 rounded-lg transition-colors"},e[44]||(e[44]=[t("i",{class:"fas fa-edit mr-1"},null,-1),f("编辑 ",-1)]),8,Jl),s.expiresAt&&(ot(s.expiresAt)||mt(s.expiresAt))?(a(),d("button",{key:0,onClick:c=>Kt(s),class:"text-green-600 hover:text-green-900 font-medium hover:bg-green-50 px-3 py-1 rounded-lg transition-colors"},e[45]||(e[45]=[t("i",{class:"fas fa-clock mr-1"},null,-1),f("续期 ",-1)]),8,Zl)):A("",!0),t("button",{onClick:c=>It(s.id),class:"text-red-600 hover:text-red-900 font-medium hover:bg-red-50 px-3 py-1 rounded-lg transition-colors"},e[46]||(e[46]=[t("i",{class:"fas fa-trash mr-1"},null,-1),f("删除 ",-1)]),8,to)])])]),s&&s.id&&i.value[s.id]?(a(),d("tr",eo,[t("td",so,[n.value[s.id]?A("",!0):(a(),d("div",lo,e[47]||(e[47]=[t("div",{class:"loading-spinner mx-auto"},null,-1),t("p",{class:"text-sm text-gray-500 mt-2"},"加载模型统计...",-1)]))),t("div",oo,[t("div",no,[e[48]||(e[48]=t("h5",{class:"text-sm font-semibold text-gray-700 flex items-center"},[t("i",{class:"fas fa-chart-pie text-indigo-500 mr-2"}),f(" 模型使用分布 ")],-1)),t("div",io,[n.value[s.id]&&n.value[s.id].length>0?(a(),d("span",ao,m(n.value[s.id].length)+" 个模型 ",1)):A("",!0),t("div",ro,[t("div",uo,[(a(!0),d(T,null,_(O(s.id).presetOptions,c=>(a(),d("button",{key:c.value,onClick:h=>gt(c.value,s.id),class:U(["px-2 py-1 rounded text-xs font-medium transition-colors",O(s.id).preset===c.value&&O(s.id).type==="preset"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"])},m(c.label),11,mo))),128))]),St(g,{"model-value":O(s.id).customRange,"onUpdate:modelValue":c=>vt(s.id,c),type:"datetimerange","range-separator":"至","start-placeholder":"开始日期","end-placeholder":"结束日期",format:"YYYY-MM-DD HH:mm:ss","value-format":"YYYY-MM-DD HH:mm:ss","disabled-date":wt,"default-time":k.value,size:"small",style:{width:"280px"},class:"api-key-date-picker",clearable:!0,"unlink-panels":!1},null,8,["model-value","onUpdate:modelValue","default-time"])])])]),n.value[s.id]&&n.value[s.id].length===0?(a(),d("div",po,[t("div",co,[e[50]||(e[50]=t("i",{class:"fas fa-chart-line text-gray-400 text-lg"},null,-1)),e[51]||(e[51]=t("p",{class:"text-sm text-gray-500"},"暂无模型使用数据",-1)),t("button",{onClick:c=>$t(s.id),class:"text-blue-500 hover:text-blue-700 text-sm ml-2 flex items-center gap-1 transition-colors",title:"重置筛选条件并刷新"},e[49]||(e[49]=[t("i",{class:"fas fa-sync-alt text-xs"},null,-1),t("span",{class:"text-xs"},"刷新",-1)]),8,xo)]),e[52]||(e[52]=t("p",{class:"text-xs text-gray-400"},"尝试调整时间范围或点击刷新重新加载数据",-1))])):n.value[s.id]&&n.value[s.id].length>0?(a(),d("div",go,[(a(!0),d(T,null,_(n.value[s.id],c=>(a(),d("div",{key:c.model,class:"bg-gradient-to-br from-white to-gray-50 rounded-xl p-4 border border-gray-200 hover:border-indigo-300 hover:shadow-lg transition-all duration-200"},[t("div",yo,[t("div",fo,[t("span",bo,m(c.model),1),t("span",vo,m(c.requests)+" 次请求",1)])]),t("div",wo,[t("div",$o,[e[53]||(e[53]=t("span",{class:"text-gray-600 flex items-center"},[t("i",{class:"fas fa-coins text-yellow-500 mr-1 text-xs"}),f(" 总Token: ")],-1)),t("span",Ao,m(E(c.allTokens)),1)]),t("div",Co,[e[54]||(e[54]=t("span",{class:"text-gray-600 flex items-center"},[t("i",{class:"fas fa-dollar-sign text-green-500 mr-1 text-xs"}),f(" 费用: ")],-1)),t("span",Ko,m(bt(c)),1)]),t("div",ko,[t("div",Lo,[e[55]||(e[55]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-arrow-down text-green-500 mr-1"}),f(" 输入: ")],-1)),t("span",Do,m(E(c.inputTokens)),1)]),t("div",Io,[e[56]||(e[56]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-arrow-up text-blue-500 mr-1"}),f(" 输出: ")],-1)),t("span",Mo,m(E(c.outputTokens)),1)]),c.cacheCreateTokens>0?(a(),d("div",Ro,[e[57]||(e[57]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-save mr-1"}),f(" 缓存创建: ")],-1)),t("span",ho,m(E(c.cacheCreateTokens)),1)])):A("",!0),c.cacheReadTokens>0?(a(),d("div",So,[e[58]||(e[58]=t("span",{class:"flex items-center"},[t("i",{class:"fas fa-download mr-1"}),f(" 缓存读取: ")],-1)),t("span",To,m(E(c.cacheReadTokens)),1)])):A("",!0)])]),t("div",Po,[t("div",{class:"bg-gradient-to-r from-indigo-500 to-purple-600 h-2 rounded-full transition-all duration-500",style:Tt({width:ct(c.allTokens,n.value[s.id])+"%"})},null,4)]),t("div",_o,[t("span",Eo,m(ct(c.allTokens,n.value[s.id]))+"% ",1)])]))),128))])):A("",!0),n.value[s.id]&&n.value[s.id].length>0?(a(),d("div",Vo,[t("div",jo,[e[61]||(e[61]=t("span",{class:"font-semibold text-gray-700 flex items-center"},[t("i",{class:"fas fa-calculator text-indigo-500 mr-2"}),f(" 总计统计 ")],-1)),t("div",Uo,[t("span",qo,[e[59]||(e[59]=f(" 总请求: ",-1)),t("span",Fo,m(n.value[s.id].reduce((c,h)=>c+h.requests,0)),1)]),t("span",Oo,[e[60]||(e[60]=f(" 总Token: ",-1)),t("span",Wo,m(E(n.value[s.id].reduce((c,h)=>c+h.allTokens,0))),1)])])])])):A("",!0)])])])):A("",!0)],64))),128))])])]))]),L.value?(a(),W(Ae,{key:0,accounts:b.value,onClose:e[8]||(e[8]=s=>L.value=!1),onSuccess:kt},null,8,["accounts"])):A("",!0),o.value?(a(),W(ds,{key:1,apiKey:l.value,accounts:b.value,onClose:e[9]||(e[9]=s=>o.value=!1),onSuccess:Lt},null,8,["apiKey","accounts"])):A("",!0),p.value?(a(),W(Ls,{key:2,apiKey:u.value,onClose:e[10]||(e[10]=s=>p.value=!1),onSuccess:Dt},null,8,["apiKey"])):A("",!0),y.value?(a(),W(qs,{key:3,apiKey:j.value,onClose:e[11]||(e[11]=s=>y.value=!1)},null,8,["apiKey"])):A("",!0)])}}},Qo=J(Yo,[["__scopeId","data-v-3c03d38e"]]);export{Qo as default};
|