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