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