mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 20:03:54 +00:00
2 lines
32 KiB
JavaScript
2 lines
32 KiB
JavaScript
import{E as Ct}from"./element-plus-B8Fs_0jW.js";import{aR as wt,r as k,c as Tt,aW as _t,o as mt,q as St,D as ot,V as Rt,x as _,z as t,P as y,u as o,O as S,L as H,Q as bt,ac as kt,C as G,R as $t,K as At,al as Ut,y as R}from"./vue-vendor-CKToUHZx.js";import{a as J,_ as It}from"./index-D3bIJLrk.js";import{s as xt}from"./toast-BvwA7Mwb.js";import{C as vt}from"./chart-Cor9iTVD.js";import"./vendor-BDiMbLwQ.js";const Mt=wt("dashboard",()=>{const nt=k(!1),V=k({totalApiKeys:0,activeApiKeys:0,totalAccounts:0,activeAccounts:0,rateLimitedAccounts:0,todayRequests:0,totalRequests:0,todayTokens:0,todayInputTokens:0,todayOutputTokens:0,totalTokens:0,totalInputTokens:0,totalOutputTokens:0,totalCacheCreateTokens:0,totalCacheReadTokens:0,todayCacheCreateTokens:0,todayCacheReadTokens:0,systemRPM:0,systemTPM:0,realtimeRPM:0,realtimeTPM:0,metricsWindow:5,isHistoricalMetrics:!1,systemStatus:"正常",uptime:0,systemTimezone:8}),m=k({todayCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:{totalCost:0,formatted:{totalCost:"$0.000000"}}}),lt=k([]),q=k([]),X=k([]),U=k({data:[],topApiKeys:[],totalApiKeys:0}),n=k({type:"preset",preset:"7days",customStart:"",customEnd:"",customRange:null,presetOptions:[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}]}),C=k("day"),E=k("requests"),F=k([new Date(2e3,1,1,0,0,0),new Date(2e3,2,1,23,59,59)]),pt=Tt(()=>{const s=V.value.uptime,d=Math.floor(s/86400),i=Math.floor(s%86400/3600),l=Math.floor(s%3600/60);return d>0?`${d}天 ${i}小时`:i>0?`${i}小时 ${l}分钟`:`${l}分钟`});function w(s,d=!0){const i=s.getFullYear(),l=s.getMonth(),a=s.getDate();return d?new Date(Date.UTC(i,l,a-1,16,0,0,0)):new Date(Date.UTC(i,l,a,15,59,59,999))}async function yt(){nt.value=!0;try{const[s,d,i]=await Promise.all([J.get("/admin/dashboard"),J.get("/admin/usage-costs?period=today"),J.get("/admin/usage-costs?period=all")]);if(s.success){const l=s.data.overview||{},a=s.data.recentActivity||{},r=s.data.systemAverages||{},u=s.data.realtimeMetrics||{},p=s.data.systemHealth||{};V.value={totalApiKeys:l.totalApiKeys||0,activeApiKeys:l.activeApiKeys||0,totalAccounts:l.totalClaudeAccounts||0,activeAccounts:l.activeClaudeAccounts||0,rateLimitedAccounts:l.rateLimitedClaudeAccounts||0,todayRequests:a.requestsToday||0,totalRequests:l.totalRequestsUsed||0,todayTokens:a.tokensToday||0,todayInputTokens:a.inputTokensToday||0,todayOutputTokens:a.outputTokensToday||0,totalTokens:l.totalTokensUsed||0,totalInputTokens:l.totalInputTokensUsed||0,totalOutputTokens:l.totalOutputTokensUsed||0,totalCacheCreateTokens:l.totalCacheCreateTokensUsed||0,totalCacheReadTokens:l.totalCacheReadTokensUsed||0,todayCacheCreateTokens:a.cacheCreateTokensToday||0,todayCacheReadTokens:a.cacheReadTokensToday||0,systemRPM:r.rpm||0,systemTPM:r.tpm||0,realtimeRPM:u.rpm||0,realtimeTPM:u.tpm||0,metricsWindow:u.windowMinutes||5,isHistoricalMetrics:u.isHistorical||!1,systemStatus:p.redisConnected?"正常":"异常",uptime:p.uptime||0,systemTimezone:s.data.systemTimezone||8}}d.success&&i.success&&(m.value={todayCosts:d.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}},totalCosts:i.data.totalCosts||{totalCost:0,formatted:{totalCost:"$0.000000"}}})}catch(s){console.error("加载仪表板数据失败:",s)}finally{nt.value=!1}}async function rt(s=7,d="day"){try{let i="/admin/usage-trend?";if(d==="hour")if(i+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const a=r=>{const[p,c]=r.split(" "),[$,K,P]=p.split("-").map(Number),[I,O,B]=c.split(":").map(Number);return new Date(Date.UTC($,K-1,P,I-8,O,B)).toISOString()};i+=`&startDate=${encodeURIComponent(a(n.value.customRange[0]))}`,i+=`&endDate=${encodeURIComponent(a(n.value.customRange[1]))}`}else{const a=new Date;let r,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(a),r=new Date(a.getTime()-24*60*60*1e3);break;case"yesterday":const p=new Date;p.setDate(p.getDate()-1),r=w(p,!0),u=w(p,!1);break;case"dayBefore":const c=new Date;c.setDate(c.getDate()-2),r=w(c,!0),u=w(c,!1);break;default:r=new Date(a.getTime()-24*60*60*1e3),u=a}else r=new Date(a.getTime()-s*24*60*60*1e3),u=a;i+=`&startDate=${encodeURIComponent(r.toISOString())}`,i+=`&endDate=${encodeURIComponent(u.toISOString())}`}else i+=`granularity=day&days=${s}`;const l=await J.get(i);l.success&&(q.value=l.data)}catch(i){console.error("加载使用趋势失败:",i)}}async function it(s="daily"){try{let d=`/admin/model-stats?period=${s}`;if(n.value.type==="custom"||C.value==="hour"){if(n.value.customRange&&n.value.customRange.length===2){const l=a=>{const[u,p]=a.split(" "),[c,$,K]=u.split("-").map(Number),[P,I,O]=p.split(":").map(Number);return new Date(Date.UTC(c,$-1,K,P-8,I,O)).toISOString()};d+=`&startDate=${encodeURIComponent(l(n.value.customRange[0]))}`,d+=`&endDate=${encodeURIComponent(l(n.value.customRange[1]))}`}else if(C.value==="hour"&&n.value.type==="preset"){const l=new Date;let a,r;switch(n.value.preset){case"last24h":r=new Date(l),a=new Date(l.getTime()-24*60*60*1e3);break;case"yesterday":const u=new Date;u.setDate(u.getDate()-1),a=w(u,!0),r=w(u,!1);break;case"dayBefore":const p=new Date;p.setDate(p.getDate()-2),a=w(p,!0),r=w(p,!1);break;default:a=new Date(l.getTime()-24*60*60*1e3),r=l}d+=`&startDate=${encodeURIComponent(a.toISOString())}`,d+=`&endDate=${encodeURIComponent(r.toISOString())}`}}const i=await J.get(d);i.success&&(X.value=i.data)}catch(d){console.error("加载模型统计失败:",d)}}async function tt(s="requests"){try{let d="/admin/api-keys-usage-trend?",i=7;if(C.value==="hour")if(d+="granularity=hour",n.value.customRange&&n.value.customRange.length===2){const a=r=>{const[p,c]=r.split(" "),[$,K,P]=p.split("-").map(Number),[I,O,B]=c.split(":").map(Number);return new Date(Date.UTC($,K-1,P,I-8,O,B)).toISOString()};d+=`&startDate=${encodeURIComponent(a(n.value.customRange[0]))}`,d+=`&endDate=${encodeURIComponent(a(n.value.customRange[1]))}`}else{const a=new Date;let r,u;if(n.value.type==="preset")switch(n.value.preset){case"last24h":u=new Date(a),r=new Date(a.getTime()-24*60*60*1e3);break;case"yesterday":const p=new Date;p.setDate(p.getDate()-1),r=w(p,!0),u=w(p,!1);break;case"dayBefore":const c=new Date;c.setDate(c.getDate()-2),r=w(c,!0),u=w(c,!1);break;default:r=new Date(a.getTime()-24*60*60*1e3),u=a}else r=new Date(a.getTime()-24*60*60*1e3),u=a;d+=`&startDate=${encodeURIComponent(r.toISOString())}`,d+=`&endDate=${encodeURIComponent(u.toISOString())}`}else i=n.value.type==="preset"?n.value.preset==="today"?1:n.value.preset==="7days"?7:30:Q(n.value.customStart,n.value.customEnd),d+=`granularity=day&days=${i}`;d+=`&metric=${s}`;const l=await J.get(d);l.success&&(U.value={data:l.data||[],topApiKeys:l.topApiKeys||[],totalApiKeys:l.totalApiKeys||0})}catch(d){console.error("加载API Keys趋势失败:",d)}}function j(s){n.value.type="preset",n.value.preset=s;const d=n.value.presetOptions.find(i=>i.value===s);if(d){const i=new Date;let l,a;if(C.value==="hour")switch(s){case"last24h":a=new Date(i),l=new Date(i.getTime()-24*60*60*1e3);break;case"yesterday":const r=new Date;r.setDate(r.getDate()-1),l=w(r,!0),a=w(r,!1);break;case"dayBefore":const u=new Date;u.setDate(u.getDate()-2),l=w(u,!0),a=w(u,!1);break}else l=new Date(i),a=new Date(i),s==="today"?(l.setHours(0,0,0,0),a.setHours(23,59,59,999)):(l.setDate(i.getDate()-(d.days-1)),l.setHours(0,0,0,0),a.setHours(23,59,59,999));if(n.value.customStart=l.toISOString().split("T")[0],n.value.customEnd=a.toISOString().split("T")[0],C.value==="hour"&&(s==="yesterday"||s==="dayBefore")){const r=new Date;s==="yesterday"?r.setDate(r.getDate()-1):r.setDate(r.getDate()-2);const u=r.getFullYear(),p=String(r.getMonth()+1).padStart(2,"0"),c=String(r.getDate()).padStart(2,"0");n.value.customRange=[`${u}-${p}-${c} 00:00:00`,`${u}-${p}-${c} 23:59:59`]}else{const r=u=>{const $=new Date(u.getTime()+288e5),K=$.getUTCFullYear(),P=String($.getUTCMonth()+1).padStart(2,"0"),I=String($.getUTCDate()).padStart(2,"0"),O=String($.getUTCHours()).padStart(2,"0"),B=String($.getUTCMinutes()).padStart(2,"0"),Z=String($.getUTCSeconds()).padStart(2,"0");return`${K}-${P}-${I} ${O}:${B}:${Z}`};n.value.customRange=[r(l),r(a)]}}N()}function ft(s){if(s&&s.length===2){n.value.type="custom",n.value.preset="",n.value.customRange=s,n.value.customStart=s[0].split(" ")[0],n.value.customEnd=s[1].split(" ")[0],V.value.systemTimezone;const d=a=>{const[r,u]=a.split(" "),[p,c,$]=r.split("-").map(Number),[K,P,I]=u.split(":").map(Number);return new Date(p,c-1,$,K,P,I)},i=d(s[0]),l=d(s[1]);if(C.value==="hour"){if((l-i)/36e5>24){xt("小时粒度下日期范围不能超过24小时","warning");return}}else if(Math.ceil((l-i)/864e5)+1>31){xt("日期范围不能超过 31 天","warning");return}N()}else s===null&&j(C.value==="hour"?"last24h":"7days")}function et(s){if(C.value=s,s==="hour"){if(n.value.presetOptions=[{value:"last24h",label:"近24小时",hours:24},{value:"yesterday",label:"昨天",hours:24},{value:"dayBefore",label:"前天",hours:24}],n.value.type==="custom"&&n.value.customRange&&n.value.customRange.length===2){const d=new Date(n.value.customRange[0]);if((new Date(n.value.customRange[1])-d)/(1e3*60*60)>24){xt("小时粒度下日期范围不能超过24小时,已切换到近24小时","warning"),j("last24h");return}}if(["today","7days","30days"].includes(n.value.preset)){j("last24h");return}}else if(n.value.presetOptions=[{value:"today",label:"今日",days:1},{value:"7days",label:"7天",days:7},{value:"30days",label:"30天",days:30}],["last24h","yesterday","dayBefore"].includes(n.value.preset)){j("7days");return}N()}async function N(){let s,d="monthly";if(n.value.type==="preset"){const i=n.value.presetOptions.find(l=>l.value===n.value.preset);C.value==="hour"?(s=1,d="daily"):(s=i?i.days:7,n.value.preset==="today"?d="daily":d="monthly")}else{if(C.value==="hour"){const i=new Date(n.value.customRange[0]),l=new Date(n.value.customRange[1]),a=Math.ceil((l-i)/(1e3*60*60));s=Math.ceil(a/24)||1}else s=Q(n.value.customStart,n.value.customEnd);d="daily"}await Promise.all([rt(s,C.value),it(d),tt(E.value)])}function Q(s,d){if(!s||!d)return 7;const i=new Date(s),l=new Date(d),a=Math.abs(l-i);return Math.ceil(a/(1e3*60*60*24))||7}function Y(s){return s>new Date}return{loading:nt,dashboardData:V,costsData:m,modelStats:lt,trendData:q,dashboardModelStats:X,apiKeysTrendData:U,dateFilter:n,trendGranularity:C,apiKeysTrendMetric:E,defaultTime:F,formattedUptime:pt,loadDashboardData:yt,loadUsageTrend:rt,loadModelStats:it,loadApiKeysTrend:tt,setDateFilterPreset:j,onCustomDateRangeChange:ft,setTrendGranularity:et,refreshChartsData:N,disabledDate:Y}}),Kt={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-4 sm:mb-6 md:mb-8"},Pt={class:"stat-card"},Ft={class:"flex items-center justify-between"},Ot={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Bt={class:"text-xs text-gray-500 mt-1"},zt={class:"stat-card"},Ht={class:"flex items-center justify-between"},qt={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Et={class:"text-xs text-gray-500 mt-1"},Nt={key:0,class:"text-yellow-600"},Lt={class:"stat-card"},Vt={class:"flex items-center justify-between"},jt={class:"text-2xl sm:text-3xl font-bold text-gray-900"},Yt={class:"text-xs text-gray-500 mt-1"},Wt={class:"stat-card"},Gt={class:"flex items-center justify-between"},Qt={class:"text-2xl sm:text-3xl font-bold text-green-600"},Zt={class:"text-xs text-gray-500 mt-1"},Jt={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-4 sm:mb-6 md:mb-8"},Xt={class:"stat-card"},te={class:"flex items-center justify-between"},ee={class:"flex-1 mr-8"},se={class:"flex items-baseline gap-2 mb-2 flex-wrap"},ae={class:"text-xl sm:text-2xl md:text-3xl font-bold text-blue-600"},oe={class:"text-sm text-green-600 font-medium"},ne={class:"text-xs text-gray-500"},le={class:"flex justify-between items-center flex-wrap gap-x-4"},re={class:"font-medium"},ie={class:"font-medium"},de={key:0,class:"text-purple-600"},ue={class:"font-medium"},ce={key:1,class:"text-purple-600"},me={class:"font-medium"},pe={class:"stat-card"},ye={class:"flex items-center justify-between"},fe={class:"flex-1 mr-8"},ge={class:"flex items-baseline gap-2 mb-2 flex-wrap"},xe={class:"text-xl sm:text-2xl md:text-3xl font-bold text-emerald-600"},ve={class:"text-sm text-green-600 font-medium"},he={class:"text-xs text-gray-500"},be={class:"flex justify-between items-center flex-wrap gap-x-4"},ke={class:"font-medium"},Te={class:"font-medium"},De={key:0,class:"text-purple-600"},Ce={class:"font-medium"},we={key:1,class:"text-purple-600"},_e={class:"font-medium"},Se={class:"stat-card"},Re={class:"flex items-center justify-between"},$e={class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"},Ae={class:"text-xs text-gray-400"},Ue={class:"text-2xl sm:text-3xl font-bold text-orange-600"},Ie={class:"text-xs text-gray-500 mt-1"},Me={key:0,class:"text-yellow-600"},Ke={class:"stat-card"},Pe={class:"flex items-center justify-between"},Fe={class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"},Oe={class:"text-xs text-gray-400"},Be={class:"text-2xl sm:text-3xl font-bold text-rose-600"},ze={class:"text-xs text-gray-500 mt-1"},He={key:0,class:"text-yellow-600"},qe={class:"mb-8"},Ee={class:"flex flex-col gap-4 mb-4 sm:mb-6"},Ne={class:"flex flex-col lg:flex-row gap-2 lg:items-center lg:justify-end"},Le={class:"flex gap-1 bg-gray-100 rounded-lg p-1 overflow-x-auto flex-shrink-0"},Ve=["onClick"],je={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ye={class:"flex items-center gap-2"},We={key:0,class:"text-xs text-orange-600"},Ge={class:"flex items-center gap-2"},Qe={class:"flex items-center bg-gray-100 rounded-lg px-3 py-1"},Ze={class:"relative inline-flex items-center cursor-pointer"},Je={class:"ml-2.5 text-sm font-medium text-gray-600 select-none flex items-center gap-1"},Xe=["disabled"],ts={class:"hidden sm:inline"},es={class:"grid grid-cols-1 lg:grid-cols-2 gap-6"},ss={class:"card p-4 sm:p-6"},as={class:"relative",style:{height:"250px"}},os={class:"card p-4 sm:p-6"},ns={key:0,class:"text-center py-8"},ls={key:1,class:"overflow-auto max-h-[250px] sm:max-h-[300px]"},rs={class:"min-w-full"},is={class:"divide-y divide-gray-200"},ds={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-900"},us=["title"],cs={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-600 text-right hidden sm:table-cell"},ms={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-gray-600 text-right"},ps={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm text-green-600 text-right font-medium"},ys={class:"px-2 sm:px-4 py-2 text-xs sm:text-sm font-medium text-right hidden sm:table-cell"},fs={class:"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800"},gs={class:"mb-4 sm:mb-6 md:mb-8"},xs={class:"card p-4 sm:p-6"},vs={style:{height:"250px"},class:"sm:h-[300px]"},hs={class:"mb-4 sm:mb-6 md:mb-8"},bs={class:"card p-4 sm:p-6"},ks={class:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4"},Ts={class:"flex gap-1 bg-gray-100 rounded-lg p-1"},Ds={class:"mb-4 text-xs sm:text-sm text-gray-600"},Cs={key:0},ws={key:1},_s={style:{height:"300px"},class:"sm:h-[350px]"},Ss={__name:"DashboardView",setup(nt){const V=Mt(),{dashboardData:m,costsData:lt,dashboardModelStats:q,trendData:X,apiKeysTrendData:U,formattedUptime:n,dateFilter:C,trendGranularity:E,apiKeysTrendMetric:F,defaultTime:pt}=_t(V),{loadDashboardData:w,loadApiKeysTrend:yt,setDateFilterPreset:rt,onCustomDateRangeChange:it,setTrendGranularity:tt,refreshChartsData:j,disabledDate:ft}=V,et=k(null),N=k(null),Q=k(null);let Y=null,s=null,d=null;const i=k(!1),l=k(30),a=k(null),r=k(0),u=k(null),p=k(!1);Tt(()=>!i.value||r.value<=0?"":`${r.value}秒后刷新`);function c(v){return v>=1e6?(v/1e6).toFixed(2)+"M":v>=1e3?(v/1e3).toFixed(2)+"K":v.toString()}function $(v,e){if(!e||e.length===0)return 0;const T=e.reduce((g,L)=>g+L.allTokens,0);return T===0?0:(v/T*100).toFixed(1)}function K(){if(!et.value)return;Y&&Y.destroy();const v=q.value||[],e={labels:v.map(T=>T.model),datasets:[{data:v.map(T=>T.allTokens),backgroundColor:["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],borderWidth:0}]};Y=new vt(et.value,{type:"doughnut",data:e,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:15,usePointStyle:!0,font:{size:12}}},tooltip:{callbacks:{label:function(T){const g=T.label||"",L=c(T.parsed),st=$(T.parsed,v);return`${g}: ${L} (${st}%)`}}}}}})}function P(){var D;if(!N.value)return;s&&s.destroy();const v=X.value||[],e=v.map(f=>f.inputTokens||0),T=v.map(f=>f.outputTokens||0),g=v.map(f=>f.cacheCreateTokens||0),L=v.map(f=>f.cacheReadTokens||0),st=v.map(f=>f.requests||0),dt=v.map(f=>f.cost||0),ut=(D=v[0])!=null&&D.date?"date":"hour",M={labels:v.map(f=>{if(f.label)return f.label;if(ut==="hour"){const x=new Date(f.hour),A=String(x.getMonth()+1).padStart(2,"0"),W=String(x.getDate()).padStart(2,"0"),ct=String(x.getHours()).padStart(2,"0");return`${A}/${W} ${ct}:00`}const b=f.date;if(b&&b.includes("-")){const x=b.split("-");if(x.length>=3)return`${x[1]}/${x[2]}`}return f.date}),datasets:[{label:"输入Token",data:e,borderColor:"rgb(102, 126, 234)",backgroundColor:"rgba(102, 126, 234, 0.1)",tension:.3},{label:"输出Token",data:T,borderColor:"rgb(240, 147, 251)",backgroundColor:"rgba(240, 147, 251, 0.1)",tension:.3},{label:"缓存创建Token",data:g,borderColor:"rgb(59, 130, 246)",backgroundColor:"rgba(59, 130, 246, 0.1)",tension:.3},{label:"缓存读取Token",data:L,borderColor:"rgb(147, 51, 234)",backgroundColor:"rgba(147, 51, 234, 0.1)",tension:.3},{label:"费用 (USD)",data:dt,borderColor:"rgb(34, 197, 94)",backgroundColor:"rgba(34, 197, 94, 0.1)",tension:.3,yAxisID:"y2"},{label:"请求数",data:st,borderColor:"rgb(16, 185, 129)",backgroundColor:"rgba(16, 185, 129, 0.1)",tension:.3,yAxisID:"y1"}]};s=new vt(N.value,{type:"line",data:M,options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"index",intersect:!1},plugins:{title:{display:!0,text:"Token使用趋势",font:{size:16,weight:"bold"}},legend:{position:"top"},tooltip:{mode:"index",intersect:!1,itemSort:function(f,b){const x=f.dataset.label||"",A=b.dataset.label||"";return x==="费用 (USD)"||A==="费用 (USD)"?x==="费用 (USD)"?-1:1:x==="请求数"||A==="请求数"?x==="请求数"?1:-1:b.parsed.y-f.parsed.y},callbacks:{label:function(f){const b=f.dataset.label||"";let x=f.parsed.y;return b==="费用 (USD)"?x<.01?b+": $"+x.toFixed(6):b+": $"+x.toFixed(4):b==="请求数"?b+": "+x.toLocaleString()+" 次":x>=1e6?b+": "+(x/1e6).toFixed(2)+"M tokens":x>=1e3?b+": "+(x/1e3).toFixed(2)+"K tokens":b+": "+x.toLocaleString()+" tokens"}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:E.value==="hour"?"时间":"日期"}},y:{type:"linear",display:!0,position:"left",title:{display:!0,text:"Token数量"},ticks:{callback:function(f){return c(f)}}},y1:{type:"linear",display:!0,position:"right",title:{display:!0,text:"请求数"},grid:{drawOnChartArea:!1},ticks:{callback:function(f){return f.toLocaleString()}}},y2:{type:"linear",display:!1,position:"right"}}}})}function I(){var dt,ut;if(!Q.value)return;d&&d.destroy();const v=U.value.data||[],e=F.value,T=["#3B82F6","#10B981","#F59E0B","#EF4444","#8B5CF6","#EC4899","#14B8A6","#F97316","#6366F1","#84CC16"],g=((dt=U.value.topApiKeys)==null?void 0:dt.map((h,M)=>{var b,x;const D=U.value.data.map(A=>!A.apiKeys||!A.apiKeys[h]?0:e==="tokens"?A.apiKeys[h].tokens:A.apiKeys[h].requests||0);return{label:((x=(b=U.value.data.find(A=>A.apiKeys&&A.apiKeys[h]))==null?void 0:b.apiKeys[h])==null?void 0:x.name)||`API Key ${h}`,data:D,borderColor:T[M%T.length],backgroundColor:T[M%T.length]+"20",tension:.4,fill:!1}}))||[],L=(ut=v[0])!=null&&ut.date?"date":"hour",st={labels:v.map(h=>{if(h.label)return h.label;if(L==="hour"){const D=new Date(h.hour),f=String(D.getMonth()+1).padStart(2,"0"),b=String(D.getDate()).padStart(2,"0"),x=String(D.getHours()).padStart(2,"0");return`${f}/${b} ${x}:00`}const M=h.date;if(M&&M.includes("-")){const D=M.split("-");if(D.length>=3)return`${D[1]}/${D[2]}`}return h.date}),datasets:g};d=new vt(Q.value,{type:"line",data:st,options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{position:"bottom",labels:{padding:20,usePointStyle:!0,font:{size:12}}},tooltip:{mode:"index",intersect:!1,itemSort:function(h,M){return M.parsed.y-h.parsed.y},callbacks:{label:function(h){var ct;const M=h.dataset.label||"",D=h.parsed.y,f=h.dataIndex,b=U.value.data[f],A=h.chart.data.datasets.map((z,at)=>({value:z.data[f]||0,index:at})).sort((z,at)=>at.value-z.value).findIndex(z=>z.index===h.datasetIndex)+1;let W="";if(A===1?W="🥇 ":A===2?W="🥈 ":A===3&&(W="🥉 "),F.value==="tokens"){let z="";D>=1e6?z=(D/1e6).toFixed(2)+"M":D>=1e3?z=(D/1e3).toFixed(2)+"K":z=D.toLocaleString();const at=U.value.topApiKeys[h.datasetIndex],gt=(ct=b==null?void 0:b.apiKeys)==null?void 0:ct[at],Dt=(gt==null?void 0:gt.formattedCost)||"$0.00";return`${W}${M}: ${z} tokens (${Dt})`}else return`${W}${M}: ${D.toLocaleString()} 次`}}}},scales:{x:{type:"category",display:!0,title:{display:!0,text:E.value==="hour"?"时间":"日期"}},y:{beginAtZero:!0,title:{display:!0,text:F.value==="tokens"?"Token 数量":"请求次数"},ticks:{callback:function(h){return c(h)}}}}}})}async function O(){await yt(F.value),await ot(),I()}mt(q,()=>{ot(()=>K())}),mt(X,()=>{ot(()=>P())}),mt(U,()=>{ot(()=>I())});async function B(){if(!p.value){p.value=!0;try{await Promise.all([w(),j()])}finally{p.value=!1}}}function Z(){i.value&&(r.value=l.value,u.value&&clearInterval(u.value),a.value&&clearTimeout(a.value),u.value=setInterval(()=>{r.value--,r.value<=0&&clearInterval(u.value)},1e3),a.value=setTimeout(async()=>{await B(),i.value&&Z()},l.value*1e3))}function ht(){u.value&&(clearInterval(u.value),u.value=null),a.value&&(clearTimeout(a.value),a.value=null),r.value=0}return mt(i,v=>{v?Z():ht()}),St(async()=>{await B(),await ot(),K(),P(),I()}),Rt(()=>{ht(),Y&&Y.destroy(),s&&s.destroy(),d&&d.destroy()}),(v,e)=>{const T=Ct;return R(),_("div",null,[t("div",Kt,[t("div",Pt,[t("div",Ft,[t("div",null,[e[7]||(e[7]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 总API Keys ",-1)),t("p",Ot,y(o(m).totalApiKeys),1),t("p",Bt," 活跃: "+y(o(m).activeApiKeys||0),1)]),e[8]||(e[8]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-blue-500 to-blue-600"},[t("i",{class:"fas fa-key"})],-1))])]),t("div",zt,[t("div",Ht,[t("div",null,[e[9]||(e[9]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 服务账户 ",-1)),t("p",qt,y(o(m).totalAccounts),1),t("p",Et,[S(" 活跃: "+y(o(m).activeAccounts||0)+" ",1),o(m).rateLimitedAccounts>0?(R(),_("span",Nt," | 限流: "+y(o(m).rateLimitedAccounts),1)):H("",!0)])]),e[10]||(e[10]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-green-500 to-green-600"},[t("i",{class:"fas fa-user-circle"})],-1))])]),t("div",Lt,[t("div",Vt,[t("div",null,[e[11]||(e[11]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 今日请求 ",-1)),t("p",jt,y(o(m).todayRequests),1),t("p",Yt," 总请求: "+y(c(o(m).totalRequests||0)),1)]),e[12]||(e[12]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-purple-500 to-purple-600"},[t("i",{class:"fas fa-chart-line"})],-1))])]),t("div",Wt,[t("div",Gt,[t("div",null,[e[13]||(e[13]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 系统状态 ",-1)),t("p",Qt,y(o(m).systemStatus),1),t("p",Zt," 运行时间: "+y(o(n)),1)]),e[14]||(e[14]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-yellow-500 to-orange-500"},[t("i",{class:"fas fa-heartbeat"})],-1))])])]),t("div",Jt,[t("div",Xt,[t("div",te,[t("div",ee,[e[19]||(e[19]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 今日Token ",-1)),t("div",se,[t("p",ae,y(c((o(m).todayInputTokens||0)+(o(m).todayOutputTokens||0)+(o(m).todayCacheCreateTokens||0)+(o(m).todayCacheReadTokens||0))),1),t("span",oe,"/ "+y(o(lt).todayCosts.formatted.totalCost),1)]),t("div",ne,[t("div",le,[t("span",null,[e[15]||(e[15]=S("输入: ",-1)),t("span",re,y(c(o(m).todayInputTokens||0)),1)]),t("span",null,[e[16]||(e[16]=S("输出: ",-1)),t("span",ie,y(c(o(m).todayOutputTokens||0)),1)]),(o(m).todayCacheCreateTokens||0)>0?(R(),_("span",de,[e[17]||(e[17]=S("缓存创建: ",-1)),t("span",ue,y(c(o(m).todayCacheCreateTokens||0)),1)])):H("",!0),(o(m).todayCacheReadTokens||0)>0?(R(),_("span",ce,[e[18]||(e[18]=S("缓存读取: ",-1)),t("span",me,y(c(o(m).todayCacheReadTokens||0)),1)])):H("",!0)])])]),e[20]||(e[20]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-indigo-500 to-indigo-600"},[t("i",{class:"fas fa-coins"})],-1))])]),t("div",pe,[t("div",ye,[t("div",fe,[e[25]||(e[25]=t("p",{class:"text-xs sm:text-sm font-semibold text-gray-600 mb-1"}," 总Token消耗 ",-1)),t("div",ge,[t("p",xe,y(c((o(m).totalInputTokens||0)+(o(m).totalOutputTokens||0)+(o(m).totalCacheCreateTokens||0)+(o(m).totalCacheReadTokens||0))),1),t("span",ve,"/ "+y(o(lt).totalCosts.formatted.totalCost),1)]),t("div",he,[t("div",be,[t("span",null,[e[21]||(e[21]=S("输入: ",-1)),t("span",ke,y(c(o(m).totalInputTokens||0)),1)]),t("span",null,[e[22]||(e[22]=S("输出: ",-1)),t("span",Te,y(c(o(m).totalOutputTokens||0)),1)]),(o(m).totalCacheCreateTokens||0)>0?(R(),_("span",De,[e[23]||(e[23]=S("缓存创建: ",-1)),t("span",Ce,y(c(o(m).totalCacheCreateTokens||0)),1)])):H("",!0),(o(m).totalCacheReadTokens||0)>0?(R(),_("span",we,[e[24]||(e[24]=S("缓存读取: ",-1)),t("span",_e,y(c(o(m).totalCacheReadTokens||0)),1)])):H("",!0)])])]),e[26]||(e[26]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-emerald-500 to-emerald-600"},[t("i",{class:"fas fa-database"})],-1))])]),t("div",Se,[t("div",Re,[t("div",null,[t("p",$e,[e[27]||(e[27]=S(" 实时RPM ",-1)),t("span",Ae,"("+y(o(m).metricsWindow)+"分钟)",1)]),t("p",Ue,y(o(m).realtimeRPM||0),1),t("p",Ie,[e[29]||(e[29]=S(" 每分钟请求数 ",-1)),o(m).isHistoricalMetrics?(R(),_("span",Me,e[28]||(e[28]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),S(" 历史数据 ",-1)]))):H("",!0)])]),e[30]||(e[30]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-orange-500 to-orange-600"},[t("i",{class:"fas fa-tachometer-alt"})],-1))])]),t("div",Ke,[t("div",Pe,[t("div",null,[t("p",Fe,[e[31]||(e[31]=S(" 实时TPM ",-1)),t("span",Oe,"("+y(o(m).metricsWindow)+"分钟)",1)]),t("p",Be,y(c(o(m).realtimeTPM||0)),1),t("p",ze,[e[33]||(e[33]=S(" 每分钟Token数 ",-1)),o(m).isHistoricalMetrics?(R(),_("span",He,e[32]||(e[32]=[t("i",{class:"fas fa-exclamation-circle"},null,-1),S(" 历史数据 ",-1)]))):H("",!0)])]),e[34]||(e[34]=t("div",{class:"stat-icon flex-shrink-0 bg-gradient-to-br from-rose-500 to-rose-600"},[t("i",{class:"fas fa-rocket"})],-1))])])]),t("div",qe,[t("div",Ee,[e[41]||(e[41]=t("h3",{class:"text-lg sm:text-xl font-bold text-gray-900"}," 模型使用分布与Token使用趋势 ",-1)),t("div",Ne,[t("div",Le,[(R(!0),_(bt,null,kt(o(C).presetOptions,g=>(R(),_("button",{key:g.value,class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(C).preset===g.value&&o(C).type==="preset"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:L=>o(rt)(g.value)},y(g.label),11,Ve))),128))]),t("div",je,[t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(E)==="day"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[0]||(e[0]=g=>o(tt)("day"))},e[35]||(e[35]=[t("i",{class:"fas fa-calendar-day mr-1"},null,-1),S("按天 ",-1)]),2),t("button",{class:G(["px-3 py-1 rounded-md text-sm font-medium transition-colors",o(E)==="hour"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[1]||(e[1]=g=>o(tt)("hour"))},e[36]||(e[36]=[t("i",{class:"fas fa-clock mr-1"},null,-1),S("按小时 ",-1)]),2)]),t("div",Ye,[$t(T,{modelValue:o(C).customRange,"onUpdate:modelValue":e[2]||(e[2]=g=>o(C).customRange=g),"default-time":o(pt),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":o(ft),size:"default",class:"w-full lg:w-auto custom-date-picker",style:{"max-width":"400px"},onChange:o(it)},null,8,["modelValue","default-time","disabled-date","onChange"]),o(E)==="hour"?(R(),_("span",We,e[37]||(e[37]=[t("i",{class:"fas fa-info-circle"},null,-1),S(" 最多24小时 ",-1)]))):H("",!0)]),t("div",Ge,[t("div",Qe,[t("label",Ze,[At(t("input",{"onUpdate:modelValue":e[3]||(e[3]=g=>i.value=g),type:"checkbox",class:"sr-only peer"},null,512),[[Ut,i.value]]),e[40]||(e[40]=t("div",{class:"relative w-9 h-5 bg-gray-300 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:bg-blue-500 transition-all duration-200 after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:w-4 after:h-4 after:rounded-full after:shadow-sm after:transition-transform after:duration-200 peer-checked:after:translate-x-4"},null,-1)),t("span",Je,[e[38]||(e[38]=t("i",{class:"fas fa-redo-alt text-xs text-gray-500"},null,-1)),e[39]||(e[39]=t("span",null,"自动刷新",-1)),i.value?(R(),_("span",{key:0,class:G(["ml-1 text-xs text-blue-600 font-mono transition-opacity",r.value>0?"opacity-100":"opacity-0"])},y(r.value)+"s ",3)):H("",!0)])])]),t("button",{disabled:p.value,class:"px-3 py-1 rounded-md text-sm font-medium transition-colors bg-white text-blue-600 shadow-sm hover:bg-gray-50 border border-gray-300 flex items-center gap-1 sm:gap-2 disabled:opacity-50 disabled:cursor-not-allowed",title:"立即刷新数据",onClick:e[4]||(e[4]=g=>B())},[t("i",{class:G(["fas fa-sync-alt text-xs",{"animate-spin":p.value}])},null,2),t("span",ts,y(p.value?"刷新中":"刷新"),1)],8,Xe)])])]),t("div",es,[t("div",ss,[e[42]||(e[42]=t("h4",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-4"}," Token使用分布 ",-1)),t("div",as,[t("canvas",{ref_key:"modelUsageChart",ref:et},null,512)])]),t("div",os,[e[45]||(e[45]=t("h4",{class:"text-base sm:text-lg font-semibold text-gray-800 mb-4"}," 详细统计数据 ",-1)),o(q).length===0?(R(),_("div",ns,e[43]||(e[43]=[t("p",{class:"text-gray-500 text-sm sm:text-base"}," 暂无模型使用数据 ",-1)]))):(R(),_("div",ls,[t("table",rs,[e[44]||(e[44]=t("thead",{class:"bg-gray-50 sticky top-0"},[t("tr",null,[t("th",{class:"px-2 sm:px-4 py-2 text-left text-xs font-medium text-gray-700"}," 模型 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700 hidden sm:table-cell"}," 请求数 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700"}," 总Token "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700"}," 费用 "),t("th",{class:"px-2 sm:px-4 py-2 text-right text-xs font-medium text-gray-700 hidden sm:table-cell"}," 占比 ")])],-1)),t("tbody",is,[(R(!0),_(bt,null,kt(o(q),g=>(R(),_("tr",{key:g.model,class:"hover:bg-gray-50"},[t("td",ds,[t("span",{class:"block truncate max-w-[100px] sm:max-w-none",title:g.model},y(g.model),9,us)]),t("td",cs,y(c(g.requests)),1),t("td",ms,y(c(g.allTokens)),1),t("td",ps,y(g.formatted?g.formatted.total:"$0.000000"),1),t("td",ys,[t("span",fs,y($(g.allTokens,o(q)))+"% ",1)])]))),128))])])]))])])]),t("div",gs,[t("div",xs,[t("div",vs,[t("canvas",{ref_key:"usageTrendChart",ref:N},null,512)])])]),t("div",hs,[t("div",bs,[t("div",ks,[e[48]||(e[48]=t("h3",{class:"text-base sm:text-lg font-semibold text-gray-900"}," API Keys 使用趋势 ",-1)),t("div",Ts,[t("button",{class:G(["px-2 sm:px-3 py-1 rounded-md text-xs sm:text-sm font-medium transition-colors",o(F)==="requests"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[5]||(e[5]=g=>{F.value="requests",O()})},e[46]||(e[46]=[t("i",{class:"fas fa-exchange-alt mr-1"},null,-1),t("span",{class:"hidden sm:inline"},"请求次数",-1),t("span",{class:"sm:hidden"},"请求",-1)]),2),t("button",{class:G(["px-2 sm:px-3 py-1 rounded-md text-xs sm:text-sm font-medium transition-colors",o(F)==="tokens"?"bg-white text-blue-600 shadow-sm":"text-gray-600 hover:text-gray-900"]),onClick:e[6]||(e[6]=g=>{F.value="tokens",O()})},e[47]||(e[47]=[t("i",{class:"fas fa-coins mr-1"},null,-1),t("span",{class:"hidden sm:inline"},"Token 数量",-1),t("span",{class:"sm:hidden"},"Token",-1)]),2)])]),t("div",Ds,[o(U).totalApiKeys>10?(R(),_("span",Cs," 共 "+y(o(U).totalApiKeys)+" 个 API Key,显示使用量前 10 个 ",1)):(R(),_("span",ws," 共 "+y(o(U).totalApiKeys)+" 个 API Key ",1))]),t("div",_s,[t("canvas",{ref_key:"apiKeysUsageTrendChart",ref:Q},null,512)])])])])}}},Ks=It(Ss,[["__scopeId","data-v-a1b368e2"]]);export{Ks as default};
|