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