PageSourceSearch

https://easyquizehou.io.vn/assets/AdminTokenUsagePage-i2Hzn18u.js

js easyquizehou.io.vn collected 2026-10-02 01:12:23 UTC 34,264 bytes, 1 lines download raw bytes

1import{j as e}from"./vendor-editor-tiptap-DxFZQymd.js";import{r as i}from"./vendor-react-Ci3E8-6d.js";import{aO as ge,bH as ue,a2 as b,bE as Oe,al as Te,aC as De,a1 as rt,b2 as J,a6 as ct,aE as _,U as w,a0 as je,$ as Se,a7 as z,bb as Ce,aF as Ne,I as we,aX as X,F as dt,bf as Ue,bl as Ie,ah as oe,be as B,X as Ee,V as ut,bB as mt,aj as pt}from"./vendor-antd-Osf0nwkm.js";import{t as v,f as me,a as K,b as Me,c as ht}from"./tokenUsageService-DGfDL03q.js";import{C as gt,g as kt,q as M,u as qe,ax as Ae}from"./index-CMVZ1QIP.js";import{R as yt,u as xt,k as ft,i as vt,B as bt,d as _t,e as Tt,H as A,P}from"./style-C7YIef0W.js";import{g as jt,P as Ye}from"./ProviderLogo-C8R8_Tzr.js";import{r as Fe}from"./relativeTime-C-eEPy85.js";import{W as St}from"./WebSearchLogo-Bgwhg3dU.js";import{L as Ct}from"./vendor-charts-Dq7xLlt_.js";import"./zoom-CAW9i-qj.js";/* empty css                     */const Nt="/topic/admin/ai-usage",wt=50,He=6e4,It=["STARTED","COMPLETED","FAILED"];function Et(t){let s;try{s=JSON.parse(t)}catch{return null}if(typeof s!="object"||s===null)return null;const n=s;return typeof n.requestId!="string"||!n.requestId||typeof n.providerId!="string"||!n.providerId||typeof n.status!="string"||!It.includes(n.status)?null:{requestId:n.requestId,providerId:n.providerId,providerName:typeof n.providerName=="string"?n.providerName:n.providerId,status:n.status,timestamp:typeof n.timestamp=="string"?n.timestamp:new Date().toISOString(),latencyMs:typeof n.latencyMs=="number"?n.latencyMs:null}}function Mt(t,s){const n=new Map(t);return s.status==="STARTED"?n.set(s.requestId,{requestId:s.requestId,providerId:s.providerId,providerName:s.providerName,startedAt:Date.now()}):n.delete(s.requestId),n}function Pe(t){const s=Date.now(),n=new Map(t);let l=!1;return n.forEach((c,u)=>{s-c.startedAt>He&&(n.delete(u),l=!0)}),l?n:t}function At(t){const[s,n]=i.useState(new Map),[l,c]=i.useState([]),[u,m]=i.useState(!1),h=i.useRef(null);return i.useEffect(()=>{if(!t){m(!1),n(new Map),c([]);return}const y=localStorage.getItem("accessToken");if(!y){m(!1),n(new Map),c([]);return}const r="https://be.easyquizehou.io.vn/api".replace(/\/api\/?$/,"").replace(/\/$/,"").replace(/^http/,"ws")+"/ws/websocket",a=new gt({brokerURL:r,connectHeaders:{Authorization:`Bearer ${y}`},reconnectDelay:5e3,heartbeatIncoming:4e3,heartbeatOutgoing:4e3});a.onConnect=()=>{m(!0),a.subscribe(Nt,g=>{const T=Et(g.body);T&&(n(j=>Pe(Mt(j,T))),c(j=>[T,...j].slice(0,wt)))})},a.onDisconnect=()=>m(!1),a.onStompError=()=>m(!1),a.onWebSocketError=()=>m(!1),h.current=a,a.activate();const d=window.setInterval(()=>{n(g=>Pe(g))},He);return()=>{h.current=null,m(!1),window.clearInterval(d),a.deactivate()}},[t]),{activeRequests:s,lastEvents:l,isConnected:u}}const{RangePicker:Pt}=ue,Rt=[{label:"Today",value:"today"},{label:"24h",value:"24h"},{label:"7D",value:"7d"},{label:"30D",value:"30d"},{label:"60D",value:"60d"}];function Lt(t,s){const n=b();return t==="today"?[n.startOf("day"),n.endOf("day")]:t==="24h"?[n.subtract(24,"hour"),n]:t==="7d"?[n.subtract(7,"day"),n]:t==="30d"?[n.subtract(30,"day"),n]:t==="60d"?[n.subtract(60,"day"),n]:s??[n.subtract(7,"day"),n]}const Ot=({preset:t,onPresetChange:s,customRange:n,onCustomRangeChange:l})=>e.jsxs("div",{className:"token-usage-header",children:[e.jsx(ge,{className:"token-usage-header__presets",size:"small",value:t==="custom"?void 0:t,onChange:c=>s(c),options:Rt}),e.jsx(Pt,{className:"token-usage-header__range",size:"small",value:n,allowClear:!1,format:"DD/MM/YYYY",onChange:c=>{c?.[0]&&c[1]&&(l([c[0],c[1]]),s("custom"))}})]});function Z(t){return(Number(t)||0).toLocaleString("en-US")}function Dt(t){return`~$${(Number(t)||0).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}`}const Ut=({data:t,loading:s})=>{const n=[{key:"requests",label:"Total Requests",value:Z(t?.totalCalls??0),tone:"neutral"},{key:"input",label:"Total Input Tokens",value:Z(t?.inputTokens??0),tone:"input"},{key:"cached",label:"Cached Tokens",value:Z(t?.cachedInputTokens??0),tone:"cached"},{key:"output",label:"Output Tokens",value:Z(t?.outputTokens??0),tone:"output"},{key:"cost",label:"Est. Cost",value:Dt(t?.totalCost??0),tone:"cost",hint:"Estimated, not actual billing"}];return e.jsx("div",{className:"token-kpi-grid","aria-label":"Token usage summary",children:n.map(l=>e.jsx("article",{className:`token-kpi-card token-kpi-card--${l.tone}`,children:s&&!t?e.jsx(Oe,{active:!0,title:!1,paragraph:{rows:2}}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"token-kpi-card__label",children:l.label}),e.jsx("div",{className:"token-kpi-card__value",children:l.value}),l.hint&&e.jsx("div",{className:"token-kpi-card__hint",children:l.hint})]})},l.key))})},Re=240,pe=340,he=240,ie={padding:.28,minZoom:.35,maxZoom:1.2};function qt(t,s){const n=Math.PI/4;return Math.abs(t+Math.PI/2)<n?{centerHandle:"top",providerHandle:"bottom"}:Math.abs(t-Math.PI/2)<n?{centerHandle:"bottom",providerHandle:"top"}:s>0?{centerHandle:"right",providerHandle:"left"}:{centerHandle:"left",providerHandle:"right"}}const Yt=({data:t})=>e.jsxs("div",{className:`topology-center-node${t.linked?" is-linked":""}`,children:[e.jsx(A,{type:"source",position:P.Top,id:"top",style:{opacity:0}
1}),e.jsx(A,{type:"source",position:P.Right,id:"right",style:{opacity:0}}),e.jsx(A,{type:"source",position:P.Bottom,id:"bottom",style:{opacity:0}}),e.jsx(A,{type:"source",position:P.Left,id:"left",style:{opacity:0}}),e.jsx("img",{src:kt,alt:"",className:"topology-center-node__logo"}),e.jsx("span",{children:t.label})]}),Ft=({data:t})=>{const s=jt({providerType:t.providerType,presetKey:t.presetKey});return e.jsxs("div",{className:`topology-provider-node${t.active?" active":""}${t.enabled?"":" disabled"}`,children:[e.jsx(A,{type:"target",position:P.Top,id:"top",style:{opacity:0}}),e.jsx(A,{type:"target",position:P.Right,id:"right",style:{opacity:0}}),e.jsx(A,{type:"target",position:P.Bottom,id:"bottom",style:{opacity:0}}),e.jsx(A,{type:"target",position:P.Left,id:"left",style:{opacity:0}}),e.jsx(Ye,{brandKey:s,providerName:t.label,size:"sm",decorative:!0}),e.jsx("span",{className:"topology-provider-node__label",children:t.label})]})},Ht={center:Yt,provider:Ft};function zt(t){const s=Math.max(t.length,1);return t.map((n,l)=>{const c=2*Math.PI*l/s-Math.PI/2,u=Re*Math.cos(c),m=Re*Math.sin(c);return{x:pe+u,y:he+m,...qt(c,u)}})}const Bt=({providers:t,activeRequests:s})=>{const n=i.useRef(null),l=i.useRef(!1),{fitView:c}=xt(),u=ft(),m=i.useMemo(()=>{const r=new Set;return s.forEach(a=>r.add(a.providerId)),r},[s]),h=i.useMemo(()=>zt(t),[t]),y=i.useMemo(()=>[{id:"center",type:"center",position:{x:pe,y:he},data:{label:"Easy Quiz",linked:m.size>0},draggable:!1,selectable:!1},...t.map((r,a)=>({id:r.id,type:"provider",position:{x:h[a]?.x??pe,y:h[a]?.y??he},data:{label:r.name,presetKey:r.presetKey,providerType:r.providerType,active:m.has(r.id),enabled:r.enabled},draggable:!1,selectable:!1}))],[m,h,t]),x=i.useMemo(()=>t.map((r,a)=>{const d=m.has(r.id),g=h[a];return{id:`edge-${r.id}`,source:"center",target:r.id,animated:d,className:d?"topology-edge--live":void 0,sourceHandle:g?.centerHandle??"bottom",targetHandle:g?.providerHandle??"top",type:"default",style:d?{stroke:"#38bdf8",strokeWidth:3.2,opacity:1}:{stroke:"var(--topology-edge-idle, #cbd5e1)",strokeWidth:1.4,opacity:.55}}}),[m,h,t]),f=i.useCallback((r=!1)=>{c({...ie,duration:r?200:0}),l.current=!0},[c]);return i.useEffect(()=>{if(!u||t.length===0)return;let r=!1;const a=[0,100,250].map(d=>window.setTimeout(()=>{r||f(d>0)},d));return()=>{r=!0,a.forEach(d=>window.clearTimeout(d))}},[u,t.length,f]),i.useEffect(()=>{const r=n.current;if(!r)return;let a=0,d=0;const g=new ResizeObserver(T=>{const j=T[0]?.contentRect.width??0;if(j<80)return;const N=a<80&&j>=80,O=a>0&&Math.abs(j-a)>24;a=j,!(!u||t.length===0)&&(!N&&!O&&l.current||(window.cancelAnimationFrame(d),d=window.requestAnimationFrame(()=>f(!1))))});return g.observe(r),()=>{window.cancelAnimationFrame(d),g.disconnect()}},[u,t.length,f]),e.jsxs("div",{ref:n,className:"topology-canvas",role:"img","aria-label":"Sơ đồ kết nối AI provider theo thời gian thực",children:[e.jsxs("div",{className:"topology-canvas__active-badge",children:[e.jsx("span",{className:"topology-canvas__active-dot"}),"Active now: ",m.size]}),e.jsxs(vt,{nodes:y,edges:x,nodeTypes:Ht,fitView:!0,fitViewOptions:ie,minZoom:.35,maxZoom:1.4,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!1,zoomOnScroll:!0,zoomActivationKeyCode:"Control",preventScrolling:!1,onInit:r=>{t.length>0&&(r.fitView(ie),l.current=!0)},proOptions:{hideAttribution:!0},children:[e.jsx(bt,{variant:_t.Dots,gap:16,size:1,className:"topology-canvas__dots"}),e.jsx(Tt,{className:"topology-canvas__controls",showInteractive:!1,position:"bottom-left"})]})]})},$t=({providers:t,activeRequests:s})=>{const n=t.map(l=>l.id).join("|")||"empty";return e.jsx(yt,{children:e.jsx(Bt,{providers:t,activeRequests:s})},n)};b.extend(Fe);const Kt={CONTENT_SUMMARY:"Tóm tắt",TEXT_REWRITE:"Viết lại",EMBEDDING:"Embedding",TOOL_WEB_SEARCH:"Web search",SEARCH_ANSWER:"Chat / Search",OCR_EXTRACT:"OCR",CHATBOT_FAQ:"Chatbot",ADMIN_STUDENT_AI:"Copilot sinh viên",ADMIN_SUBJECT_AI:"Copilot môn học",MEETING_STT:"Meeting STT",MEETING_TRANSLATE:"Meeting dịch",MEETING_COACH:"Meeting coach",RAG_GENERATION:"RAG",RAG_DOCUMENT_SEARCH:"RAG search"},Wt={tavily:"Tavily",brave:"Brave Search",serper:"Serper",ninerouter:"9Router",duckduckgo:"DuckDuckGo"};function Gt(t){return t?Kt[t]??t:null}function ze(t){return[t.providerName,t.model,t.toolName,t.agentName,t.usageType].filter(
1Boolean).join(" ").toLowerCase()}function Vt(t){const s=ze(t);return s.includes("tavily")?"tavily":s.includes("brave")?"brave":s.includes("serper")?"serper":s.includes("duckduckgo")||s.includes("duck-duck-go")?"duckduckgo":s.includes("9router")||s.includes("ninerouter")||s.includes("nine-router")?"ninerouter":null}function Qt(t){const s=ze(t);return s?s.includes("groq")?"groq":s.includes("openai")?"openai":s.includes("anthropic")||s.includes("claude")?"anthropic":s.includes("gemini")||s.includes("google")?"gemini":s.includes("openrouter")?"openrouter":s.includes("deepseek")?"deepseek":s.includes("mistral")?"mistral":s.includes("grok")||s.includes("xai")?"grok":s.includes("9router")||s.includes("ninerouter")?"router_9router":"custom":"custom"}function Xt(t){const s=[t.providerName,t.agentName,t.toolName].filter(Boolean);return s.length?s.join(" · "):void 0}function Zt({item:t}){const s=Vt(t);if(s)return e.jsx(St,{sourceId:s,label:Wt[s],size:"sm",decorative:!0});const n=t.providerName?.trim()||t.model||"Unknown";return e.jsx(Ye,{brandKey:Qt(t),providerName:n,size:"sm",decorative:!0})}const Jt=({items:t,loading:s,limit:n=30})=>{const l=t.slice(0,n);return e.jsxs("section",{className:"recent-requests-panel","aria-label":"Recent requests",children:[e.jsx("header",{className:"recent-requests-panel__header",children:e.jsx("h2",{children:"Recent Requests"})}),e.jsxs("div",{className:"recent-requests-panel__columns","aria-hidden":"true",children:[e.jsx("span",{children:"Model / Type"}),e.jsx("span",{children:"In / Out"}),e.jsx("span",{children:"When"})]}),s&&l.length===0?e.jsx("div",{className:"recent-requests-panel__body",children:e.jsx(Oe,{active:!0,paragraph:{rows:6},title:!1})}):l.length===0?e.jsx("div",{className:"recent-requests-panel__empty",children:e.jsx(Te,{image:Te.PRESENTED_IMAGE_SIMPLE,description:"Chưa có request nào"})}):e.jsx("div",{className:"recent-requests-panel__body",children:l.map(c=>{const u=Gt(c.usageType);return e.jsxs("div",{className:`recent-requests-row${c.status==="FAILED"?" is-failed":""}`,children:[e.jsxs("div",{className:"recent-requests-row__main",children:[e.jsx("span",{className:"recent-requests-row__logo",title:Xt(c),children:e.jsx(Zt,{item:c})}),e.jsxs("div",{className:"recent-requests-row__model-wrap",children:[e.jsx("div",{className:"recent-requests-row__model",title:c.model,children:c.model}),u&&e.jsx("div",{className:"recent-requests-row__type",title:c.usageType??void 0,children:u})]})]}),e.jsxs("div",{className:"recent-requests-row__tokens",children:[e.jsxs("span",{className:"recent-requests-row__in",children:[c.inputTokens.toLocaleString("en-US"),"↑"]}),e.jsxs("span",{className:"recent-requests-row__out",children:[c.outputTokens.toLocaleString("en-US"),"↓"]})]}),e.jsx("div",{className:"recent-requests-row__when",children:b(c.createdAt).fromNow()})]},c.id)})})]})},es=({from:t,to:s,granularity:n,provider:l})=>{const[c,u]=i.useState("tokens"),[m,h]=i.useState([]),[y,x]=i.useState(!1);i.useEffect(()=>{const r=new AbortController;return(async()=>{x(!0);try{const a=await v.getDashboardTimeseries({from:t,to:s,granularity:n,metric:c,groupBy:"none",provider:l});r.signal.aborted||h(a.data||[])}catch(a){r.signal.aborted||M(a,"Lỗi tải biểu đồ")}finally{r.signal.aborted||x(!1)}})(),()=>r.abort()},[t,s,n,c,l]);const f=i.useMemo(()=>({data:m,xField:"bucket",yField:"value",height:260,smooth:!0,area:{style:{fillOpacity:.12}},axis:{x:{labelFormatter:r=>Me(r,n)},y:{labelFormatter:r=>c==="cost"?me(Number(r)):K(Number(r))}},tooltip:{title:r=>Me(r.bucket,n),items:[{channel:"y",valueFormatter:r=>c==="cost"?me(Number(r)):K(Number(r))}]}}),[m,n,c]);return e.jsxs(De,{size:"small",className:"usage-trend-chart",title:"Usage Trend",children:[e.jsx("div",{className:"usage-trend-chart__toolbar",children:e.jsx(ge,{value:c,onChange:r=>u(r),options:[{label:"Tokens",value:"tokens"},{label:"Cost",value:"cost"}]})}),y&&m.length===0?e.jsx("div",{className:"usage-trend-chart__loading",children:e.jsx(rt,{})}):e.jsx(Ct,{...f})]})};b.extend(Fe);const{Text:le}=ct;function Le(t,s){return{key:`${s}:${t.provider}:${t.model}`,model:t.model,provider:t.provider,calls:t.calls,inputTokens:t.inputTokens,outputTokens:t.outputTokens,cachedInputTokens:t.cachedInputTokens,totalTokens:t.totalTokens,totalCost:t.totalCost,lastUsedAt:t.lastUsedAt}}function ts(t){const s=new Map;return t.forEach(n=>{const l=s.get(n.model)??[];l.push(n),s.set(n.model,l)}),Array.from(s.entries()).map(([n,l])=>
1{if(l.length===1)return Le(l[0],"solo");const c=l.reduce((a,d)=>a+d.calls,0),u=l.reduce((a,d)=>a+d.inputTokens,0),m=l.reduce((a,d)=>a+d.outputTokens,0),h=l.reduce((a,d)=>a+d.cachedInputTokens,0),y=l.reduce((a,d)=>a+d.totalTokens,0),x=l.reduce((a,d)=>a+d.totalCost,0),f=l.reduce((a,d)=>d.lastUsedAt&&(!a||b(d.lastUsedAt).isAfter(b(a)))?d.lastUsedAt:a,null),r=[...new Set(l.map(a=>a.provider).filter(a=>!!a&&a!=="null"))];return{key:`group:${n}`,model:n,provider:r.length===0?null:r.length===1?r[0]:r.join(", "),calls:c,inputTokens:u,outputTokens:m,cachedInputTokens:h,totalTokens:y,totalCost:x,lastUsedAt:f,children:l.map(a=>Le(a,"row"))}}).sort((n,l)=>l.totalCost-n.totalCost||l.calls-n.calls)}const ss=({from:t,to:s,provider:n})=>{const[l,c]=i.useState("costs"),[u,m]=i.useState([]),[h,y]=i.useState(!1);i.useEffect(()=>{const a=new AbortController;return(async()=>{y(!0);try{const d=await v.getDashboardByModel({from:t,to:s,provider:n});a.signal.aborted||m(d.data||[])}catch(d){a.signal.aborted||M(d,"Lỗi tải bảng model")}finally{a.signal.aborted||y(!1)}})(),()=>a.abort()},[t,s,n]);const x=i.useMemo(()=>ts(u),[u]),f=[{title:"MODEL",dataIndex:"model",key:"model"},{title:"PROVIDER",dataIndex:"provider",key:"provider",render:a=>a&&a!=="null"?a:e.jsx(le,{type:"secondary",children:"—"})},{title:"REQUESTS",dataIndex:"calls",key:"calls",align:"right"},{title:"LAST USED",dataIndex:"lastUsedAt",key:"lastUsedAt",render:a=>a?b(a).fromNow():e.jsx(le,{type:"secondary",children:"—"})},{title:"INPUT TOKENS",dataIndex:"inputTokens",key:"inputTokens",align:"right",render:a=>K(a)},{title:"CACHED TOKENS",dataIndex:"cachedInputTokens",key:"cachedInputTokens",align:"right",render:a=>K(a)},{title:"OUTPUT TOKENS",dataIndex:"outputTokens",key:"outputTokens",align:"right",render:a=>K(a)},{title:"TOTAL COST",dataIndex:"totalCost",key:"totalCost",align:"right",render:a=>e.jsx(le,{className:"usage-by-model-table__cost",children:me(a)})}],r=f.filter(a=>a.key!=="totalCost");return e.jsx(De,{size:"small",className:"usage-by-model-table",title:"Usage by Model",extra:e.jsx(ge,{value:l,onChange:a=>c(a),options:[{label:"Costs",value:"costs"},{label:"Tokens",value:"tokens"}]}),children:e.jsx(J,{rowKey:"key",loading:h,dataSource:x,columns:l==="costs"?f:r,pagination:!1,size:"small",scroll:{x:900}})})},$=30,ns=({active:t,preset:s,customRange:n})=>{const[l,c]=i.useState(null),[u,m]=i.useState([]),[h,y]=i.useState([]),[x,f]=i.useState(!1),r=i.useRef(!0),a=i.useMemo(()=>Lt(s,n),[n,s]),d=a[0].format("YYYY-MM-DD"),g=a[1].format("YYYY-MM-DD"),T=i.useMemo(()=>ht(d,g),[d,g]),{activeRequests:j,lastEvents:N,isConnected:O}=At(t),W=i.useCallback(async()=>{f(!0);try{const[S,I,D]=await Promise.all([v.getDashboardOverview({from:d,to:g}),v.getDashboardProviders(),v.getDashboardRecent($,{from:d,to:g})]);if(!r.current)return;c(S.data||null),m(I.data||[]),y((D.data||[]).slice(0,$))}catch(S){r.current&&M(S,"Không tải được dữ liệu tổng quan")}finally{r.current&&f(!1)}},[d,g]);i.useEffect(()=>{t&&W()},[t,W]);const G=i.useCallback(async()=>{try{const[S,I]=await Promise.all([v.getDashboardRecent($,{from:d,to:g}),v.getDashboardOverview({from:d,to:g})]);if(!r.current)return;y((S.data||[]).slice(0,$)),c(I.data||null)}catch(S){M(S,"Không cập nhật được dữ liệu realtime")}},[d,g]);return i.useEffect(()=>{const S=N[0];if(!t||!S||S.status==="STARTED")return;const I=window.setTimeout(()=>{G()},400);return()=>window.clearTimeout(I)},[t,N,G]),i.useEffect(()=>(r.current=!0,()=>{r.current=!1}),[]),e.jsxs("div",{className:"token-overview",children:[e.jsx(Ut,{data:l,loading:x}),e.jsxs("div",{className:"token-overview-grid",children:[e.jsx($t,{providers:u,activeRequests:j}),e.jsx(Jt,{items:h,loading:x,limit:$})]}),!O&&t&&e.jsx("div",{className:"token-realtime-status",children:"Realtime disconnected — đang thử kết nối lại..."}),e.jsxs("div",{className:"token-overview-bottom",children:[e.jsx(es,{from:d,to:g,granularity:T}),e.jsx(ss,{from:d,to:g})]})]})},re=["10","20","50","100"],as=({options:t,hiddenColumns:s,onToggle:n})=>e.jsx("div",{style:{minWidth:180},children:t.map(l=>{const c=!s.has(l.key);return e.jsxs("div",{role:"button",tabIndex:0,onClick:()=>n(l.key),onKeyDown:u=>{(u.key==="Enter"||u.key===" ")&&n(l.key)},style:{display:"flex",alignItems:"center",gap:8,padding:"5px 4px",cursor:"pointer"},children:[e.jsx(pt,{checked:c,onChange:u=>{u.stopPropagation(),n(l.key)}}),e.jsx("span",{style:{fontSize:13},children:l.label})]},l.key)})}),ce=t=>{const[s,n]=i.useState(!1);return e.jsx(ut,{trigger:"click",placement:"bottomRight",open:s,onOpenChange:n,title:e.jsx("span",{style:{fontSize:13},children:"Hiển thị cột"}),content:e.jsx(as,{...t}),children:e.jsx(w,{size:"small",icon:e.jsx(mt,{}),children:"View"})})};function de(t,s){t(n=>{const l=new Set(n);return l.has(s)?l.delete(s):l.add(s),l})}const os=[{key:"createdAt",label:"Timestamp"},{key:"model",label:"Model"},{key:"provider",label:"Provider"},{key:"usageType",label:"Usage Type"},{key:"inputTokens",label:"Input Tokens"},{key:"cachedInputTokens",label:"Cached"},{key:"cacheCreation",label:"Cache Creation"},{key:"outputTokens",label:"Output Tokens"},{key:"latency",label:"Latency"},{key:"action",label:"Action"}],is=[{key:"provider",label:"Provider"},{key:"model",label:"Model"},{key:"inputPricePerMillion",label:"Giá input"},{key:"outputPricePerMillion",label:"Giá output"},{key:"isActive",label:"Hoạt động"},{key:"action",label:"Thao tác"}],ls=[{key:"limitType",label:"Loại giới hạn"},{key:"model",label:"Model"},{key:"maxTokens",label:"Max tokens"},{key:"maxCostUsd",label:"Max cost"},{key:"actionOnExceed",label:"Khi vượt mức"},{key:"alertThresholdPercent",label:"Ngưỡng cảnh báo"},{key:"isActive",label:"Hoạt động"},{key:"action",label:"Thao tác"}],rs=()=>{const{t}=qe(),[s,n]=i.useState([b().subtract(7,"day"),b()]),[l,c]=i.useState([]),[u,m]=i.useState(0),[h,y]=i.useState(0),[x,f]=i.useState(20),[r,a]=i.useState(!1),[d,g]=i.useState(""),[T,j]=i.useState(""),[N,O]=i.useState(""),[W,G]=i.useState([]),[S,I]=i.useState(!1),[D,ke]=i.useState(null),[Be,V]=i.useState(!1),[$e,Ke]=i.useState([]),[We,ye]=i.useState(!1),[ee,xe]=i.useState(null),[Ge,Q]=i.useState(!1),[U]=_.useForm(),[q]=_.useForm(),[te,Ve]=i.useState(new Set),[se,Qe]=i.useState(new Set),[ne,Xe]=i.useState(new Set),[k,ae]=i.useState(null),[C]=i.useState({createdAt:170,model:180,provider:140,usageType:160,inputTokens:120,cachedInputTokens:110,cacheCreation:120,outputTokens:120,latency:130,action:90}),[R]=i.useState({provider:120,model:220,inputPricePerMillion:160,outputPricePerMillion:160,isActive:100}),[E]=i.useState({limitType:120,model:160,maxTokens:130,maxCostUsd:130,actionOnExceed:120,alertThresholdPercent:110,isActive:100}),fe=i.useMemo(()=>s[0].format("YYYY-MM-DD"),[s]),ve=i.useMemo(()=>s[1].format("YYYY-MM-DD"),[s]),Y=i.useCallback(async(o=0,p=20)=>{a(!0);try{const L={page:String(o),size:String(p),from:fe,to:ve};d&&(L.provider=d),T&&(L.usageType=T),N&&(L.status=N);const _e=await v.getLogs(L);c(_e.data?.content||[]),m(_e.data?.totalElements||0)}catch(L){M(L,t("token_usage.load_error"))}finally{a(!1)}},[fe,d,N,T,ve,t]),F=i.useCallback(async()=>{I(!0);try{const o=await v.getAllPricing();G(o.data||[])}catch(o){M(o,t("token_usage.load_error"))}finally{I(!1)}},[t]),H=i.useCallback(async()=>{ye(!0);try{const o=await v.getAllLimits();Ke(o.data||[])}catch(o){M(o,t("token_usage.load_error"))}finally{ye(!1)}},[t]);i.useEffect(()=>{F(),H(),Y(0,x)},[]);const Ze=i.useCallback(()=>{y(0),Y(0,x)},[Y,x]),Je=i.useCallback(()=>{const o=[b().subtract(7,"day"),b()];n(o),g(""),j(""),O(""),y(0),f(20),a(!0),v.getLogs({page:"0",size:"20",from:o[0].format("YYYY-MM-DD"),to:o[1].format("YYYY-MM-DD")}).then(p=>{c(p.data?.content||[]),m(p.data?.totalElements||0)}).catch(p=>M(p,t("token_usage.load_error"))).finally(()=>a(!1))},[t]),be=o=>
1o==null||o===0?"—":o.toLocaleString("en-US"),et=l,tt=W,st=$e,nt=i.useMemo(()=>[{title:"Timestamp",dataIndex:"createdAt",key:"createdAt",width:C.createdAt,render:o=>b(o).format(Ae)},{title:"Model",dataIndex:"model",key:"model",width:C.model,ellipsis:!0},{title:"Provider",key:"provider",width:C.provider,ellipsis:!0,render:(o,p)=>p.providerName||p.provider},{title:"Usage Type",dataIndex:"usageType",key:"usageType",width:C.usageType,ellipsis:!0,render:o=>o==="ADMIN_STUDENT_AI"?"Copilot sinh viên":o==="ADMIN_SUBJECT_AI"?"Copilot môn học":o==="CHATBOT_FAQ"?"Chatbot":o||"—"},{title:"Input Tokens",dataIndex:"inputTokens",key:"inputTokens",width:C.inputTokens,align:"right",render:o=>(o??0).toLocaleString("en-US")},{title:"Cached",dataIndex:"cachedInputTokens",key:"cachedInputTokens",width:C.cachedInputTokens,align:"right",render:o=>be(o)},{title:"Cache Creation",key:"cacheCreation",width:C.cacheCreation,align:"right",render:()=>"—"},{title:"Output Tokens",dataIndex:"outputTokens",key:"outputTokens",width:C.outputTokens,align:"right",render:o=>(o??0).toLocaleString("en-US")},{title:"Latency",key:"latency",width:C.latency,render:(o,p)=>e.jsxs("div",{className:"token-details-latency",children:[e.jsx("span",{children:"TTFT: —"}),e.jsxs("span",{children:["Total:"," ",p.latencyMs!=null?`${p.latencyMs.toLocaleString("en-US")}ms`:"—"]})]})},{title:"Action",key:"action",width:C.action,fixed:"right",render:(o,p)=>e.jsx(w,{size:"small",className:"token-details-action-btn",onClick:()=>ae(p),children:"Detail"})}].filter(o=>!te.has(o.key)),[te,C]),at=i.useMemo(()=>[{title:t("token_usage.col_provider"),dataIndex:"provider",key:"provider",width:R.provider},{title:t("token_usage.col_model"),dataIndex:"model",key:"model",width:R.model},{title:t("token_usage.pricing_input"),dataIndex:"inputPricePerMillion",key:"inputPricePerMillion",width:R.inputPricePerMillion,render:o=>`$${o}`},{title:t("token_usage.pricing_output"),dataIndex:"outputPricePerMillion",key:"outputPricePerMillion",width:R.outputPricePerMillion,render:o=>`$${o}`},{title:t("token_usage.col_active"),dataIndex:"isActive",key:"isActive",width:R.isActive,render:o=>e.jsx(je,{color:o?"green":"red",children:o?"Yes":"No"})},{title:"",key:"action",fixed:"right",width:52,render:(o,p)=>e.jsx(Se,{menu:{items:[{key:"edit",icon:e.jsx(Ne,{}),label:t("common.edit"),onClick:()=>{ke(p),U.setFieldsValue(p),V(!0)}},{key:"delete",danger:!0,icon:e.jsx(we,{}),label:t("common.delete"),onClick:()=>z.confirm({title:t("token_usage.pricing_delete_confirm"),onOk:async()=>{await v.deletePricing(p.id),await F()}})}]},children:e.jsx(w,{type:"text",icon:e.jsx(Ce,{})})})}].filter(o=>!se.has(o.key)),[F,se,R,U,t]),ot=i.useMemo(()=>[{title:t("token_usage.limit_type"),dataIndex:"limitType",key:"limitType",width:E.limitType},{title:t("token_usage.col_model"),dataIndex:"model",key:"model",width:E.model},{title:t("token_usage.limit_max_tokens"),dataIndex:"maxTokens",key:"maxTokens",width:E.maxTokens},{title:t("token_usage.limit_max_cost"),dataIndex:"maxCostUsd",key:"maxCostUsd",width:E.maxCostUsd},{title:t("token_usage.limit_action"),dataIndex:"actionOnExceed",key:"actionOnExceed",width:E.actionOnExceed},{title:t("token_usage.limit_alert_percent"),dataIndex:"alertThresholdPercent",key:"alertThresholdPercent",width:E.alertThresholdPercent},{title:t("token_usage.col_active"),dataIndex:"isActive",key:"isActive",width:E.isActive,render:o=>e.jsx(je,{color:o?"green":"red",children:o?"Yes":"No"})},{title:"",key:"action",fixed:"right",width:52,render:(o,p)=>e.jsx(Se,{menu:{items:[{key:"edit",icon:e.jsx(Ne,{}),label:t("common.edit"),onClick:()=>{xe(p),q.setFieldsValue(p),Q(!0)}},{key:"delete",danger:!0,icon:e.jsx(we,{}),label:t("common.delete"),onClick:()=>z.confirm({title:t("token_usage.limit_delete_confirm"),onOk:async()=>{await v.deleteLimit(p.id),await H()}})}]},children:e.jsx(w,{type:"text",icon:e.jsx(Ce,{})})})}].filter(o=>!ne.has(o.key)),[H,ne,E,q,t]),it=!!(d||T||N||!s[0].isSame(b().subtract(7,"day"),"day")||!s[1].isSame(b(),"day")),lt=e.jsxs("div",{className:"token-details-filters",children:[e.jsxs("div",{className:"token-details-filters__field",children:[e.jsx("span",{className:"token-details-filters__label",children:"Provider"}),e.jsx(X,{className:"token-details-filters__control",placeholder:"All Providers",allowClear:!0,options:[{value:"GROQ",label:"Groq"},{value:"OPENAI",label:"OpenAI"},{value:"TAVILY",label:"Tavily"},{value:"LOCAL",label:"Local"},{value:"OTHER",label:"Other"}],value:d||void 0,onChange:o=>g(o||"")})]}),e.jsxs("div",{className:"token-details-filters__field",children:[e.jsx("span",{className:"token-details-filters__label",children:"Usage Type"}),e.jsx(X,{className:"token-details-filters__control",placeholder:"All types",allowClear:!0,options:[{value:"ADMIN_STUDENT_AI",label:"Copilot sinh viên"},{value:"ADMIN_SUBJECT_AI",label:"Copilot môn học"},{value:"CHATBOT_FAQ",label:"Chatbot"},{value:"SEARCH_ANSWER",label:"Chat / Search"},{value:"OCR_EXTRACT",label:"OCR"},{value:"CONTENT_SUMMARY",label:"Tóm tắt"},{value:"TEXT_REWRITE",label:"Viết lại"},{value:"EMBEDDING",label:"Embedding"},{value:"TOOL_WEB_SEARCH",label:"Web search"}],value:T||void 0,onChange:o=>j(o||"")})]}),e.jsxs("div",{className:"token-details-filters__field",children:[e.jsx("span",{className:"token-details-filters__label",children:"Start Date"}),e.jsx(ue,{className:"token-details-filters__control",showTime:!0,format:"DD/MM/YYYY HH:mm",value:s[0],onChange:o=>{o&&n([o,s[1]])},allowClear:!1})]}),e.jsxs("div",{className:"token-details-filters__field",children:[e.jsx("span",{className:"token-details-filters__label",children:"End Date"}),e.jsx(ue,{className:"token-details-filters__control",showTime:!0,format:"DD/MM/YYYY HH:mm",value:s[1],onChange:o=>{o&&n([s[0],o])},allowClear:!1})]}),e.jsxs("div",{className:"token-details-filters__actions",children:[e.jsx(w,{type:"primary",icon:e.jsx(dt,{}),onClick:Ze,children:"Apply"}),e.jsx(w,{type:"link",className:`token-details-filters__clear${it?" is-active":""}`,onClick:Je,children:"Clear Filters"}),e.jsx(ce,{options:os,hiddenColumns:te,onToggle:o=>de(Ve,o)})]})]});return e.jsxs("div",{className:"token-details",children:[e.jsx(Ue,{className:"token-details__subtabs",defaultActiveKey:"logs",onChange:o=>{o==="logs"&&Y(0,x),o==="pricing"&&F(),o==="limits"&&H()},items:[{key:"logs",label:"Request Logs",children:e.jsxs("div",{className:"token-details-logs",children:[lt,e.jsx("div",{className:"token-details-table-card",children:e.jsx(J,{className:"token-details-table",dataSource:et,columns:nt,rowKey:"id",loading:r,scroll:{x:1200},pagination:{current:h+1,total:u,pageSize:x,showSizeChanger:!0,pageSizeOptions:re,onChange:(o,p)=>{y(o-1),f(p),Y(o-1,p)}}})})]})},{key:"pricing",label:t("token_usage.tab_pricing"),children:e.jsxs("div",{className:"token-details-secondary",children:[e.jsxs("div",{className:"token-details-secondary__toolbar",children:[e.jsx(w,{type:"primary",icon:e.jsx(Ie,{}),onClick:()=>{ke(null),U.resetFields(),V(!0)},children:t("token_usage.pricing_add")}),e.jsx(ce,{options:is,hiddenColumns:se,onToggle:o=>de(Qe,o)})]}),e.jsx("div",{className:"token-details-table-card",children:e.jsx(J,{dataSource:tt,columns:at,rowKey:"id",loading:S,scroll:{x:900},pagination:{pageSize:20,showSizeChanger:!0,pageSizeOptions:re}})})]})},{key:"limits",label:t("token_usage.tab_limits"),children:e.jsxs("div",{className:"token-details-secondary",children:[e.jsxs("div",{className:"token-details-secondary__toolbar",children:[e.jsx(w,{type:"primary",icon:e.jsx(Ie,{}),onClick:()=>{xe(null),q.resetFields(),Q(!0)},children:t("token_usage.limit_add")}),e.jsx(ce,{options:ls,hiddenColumns:ne,onToggle:o=>de(Xe,o)})]}),e.jsx("div",{className:"token-details-table-card",children:e.jsx(J,{dataSource:st,columns:ot,rowKey:"id",loading:We,scroll:{x:1e3},pagination:{pageSize:20,showSizeChanger:!0,pageSizeOptions:re}})})]})}]}),e.jsx(z,{title:"Request Detail",open:!!k,onCancel:()=>ae(null),footer:e.jsx(w,{onClick:()=>ae(null),children:"Close"}),width:520,destroyOnClose:!0,children:k&&e.jsxs("div",{className:"token-details-modal",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Timestamp"}),e.jsx("strong",{children:b(k.createdAt).format(Ae)}
1)]}),e.jsxs("div",{children:[e.jsx("span",{children:"Model"}),e.jsx("strong",{children:k.model})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Provider"}),e.jsx("strong",{children:k.providerName||k.provider})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Usage Type"}),e.jsx("strong",{children:k.usageType})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Input Tokens"}),e.jsx("strong",{children:(k.inputTokens??0).toLocaleString("en-US")})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Cached"}),e.jsx("strong",{children:be(k.cachedInputTokens)})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Output Tokens"}),e.jsx("strong",{children:(k.outputTokens??0).toLocaleString("en-US")})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Total Tokens"}),e.jsx("strong",{children:(k.totalTokens??0).toLocaleString("en-US")})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Latency"}),e.jsx("strong",{children:k.latencyMs!=null?`${k.latencyMs}ms`:"—"})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Cost"}),e.jsx("strong",{children:k.costEstimate==null?"—":`$${Number(k.costEstimate).toFixed(6)}`})]}),e.jsxs("div",{children:[e.jsx("span",{children:"User"}),e.jsx("strong",{children:k.username})]}),e.jsxs("div",{children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:k.status})]}),k.errorMessage&&e.jsxs("div",{children:[e.jsx("span",{children:"Error"}),e.jsx("strong",{children:k.errorMessage})]})]})}),e.jsx(z,{title:t(D?"token_usage.pricing_update":"token_usage.pricing_add"),open:Be,onCancel:()=>V(!1),onOk:()=>U.submit(),children:e.jsxs(_,{form:U,layout:"vertical",onFinish:async o=>{D?await v.updatePricing(D.id,o):await v.createPricing(o),V(!1),await F()},children:[e.jsx(_.Item,{name:"provider",label:"Provider",rules:[{required:!0}],children:e.jsx(oe,{})}),e.jsx(_.Item,{name:"model",label:"Model",rules:[{required:!0}],children:e.jsx(oe,{})}),e.jsx(_.Item,{name:"inputPricePerMillion",label:t("token_usage.pricing_input"),children:e.jsx(B,{min:0})}),e.jsx(_.Item,{name:"outputPricePerMillion",label:t("token_usage.pricing_output"),children:e.jsx(B,{min:0})}),e.jsx(_.Item,{name:"isActive",label:t("token_usage.limit_active"),valuePropName:"checked",initialValue:!0,children:e.jsx(Ee,{})})]})}),e.jsx(z,{title:t(ee?"token_usage.limit_edit":"token_usage.limit_add"),open:Ge,onCancel:()=>Q(!1),onOk:()=>q.submit(),children:e.jsxs(_,{form:q,layout:"vertical",onFinish:async o=>{ee?await v.updateLimit(ee.id,o):await v.createLimit(o),Q(!1),await H()},children:[e.jsx(_.Item,{name:"limitType",label:t("token_usage.limit_type"),rules:[{required:!0}],children:e.jsx(X,{options:[{value:"DAILY",label:"Daily"},{value:"MONTHLY",label:"Monthly"}]})}),e.jsx(_.Item,{name:"model",label:t("token_usage.limit_model"),children:e.jsx(oe,{})}),e.jsx(_.Item,{name:"maxTokens",label:t("token_usage.limit_max_tokens"),children:e.jsx(B,{min:0})}),e.jsx(_.Item,{name:"maxCostUsd",label:t("token_usage.limit_max_cost"),children:e.jsx(B,{min:0})}),e.jsx(_.Item,{name:"actionOnExceed",label:t("token_usage.limit_action"),rules:[{required:!0}],children:e.jsx(X,{options:[{value:"WARN",label:"Warn"},{value:"BLOCK",label:"Block"}]})}),e.jsx(_.Item,{name:"alertThresholdPercent",label:t("token_usage.limit_alert_percent"),children:e.jsx(B,{min:1,max:100})}),e.jsx(_.Item,{name:"isActive",label:t("token_usage.limit_active"),valuePropName:"checked",initialValue:!0,children:e.jsx(Ee,{})})]})})]})},bs=()=>{const{t}=qe(),[s,n]=i.useState("overview"),[l,c]=i.useState("today"),[u,m]=i.useState(null);return i.useEffect(()=>{document.title="Token Usage | EHOU Easy Quiz"},[]),e.jsxs("div",{className:"admin-token-page token-usage-page",children:[e.jsx("header",{className:"token-usage-page__title",children:e.jsx("h1",{children:t("token_usage.title")})}),e.jsx(Ue,{className:"token-usage-page__tabs",activeKey:s,onChange:h=>n(h),tabBarExtraContent:s==="overview"?e.jsx(Ot,{preset:l,onPresetChange:h=>{c(h),h!=="custom"&&m(null)},customRange:u??[b().subtract(7,"day"),b()],onCustomRangeChange:m}):null,items:[{key:"overview",label:"Overview",children:e.jsx(ns,{active:s==="overview",preset:l,customRange:u})},{key:"details",label:"Details",children:e.jsx(rs,{})}]})]})};export{bs as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.