ezllm 0.0.31 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/cli.js +27 -31
  2. package/dist/daemon.js +15 -19
  3. package/dist/server.js +94 -82
  4. package/dist/web-ui/assets/{DashboardView-upcGoFpc.js → DashboardView-G5UgfzzO.js} +1 -1
  5. package/dist/web-ui/assets/{LayoutView-CruZSfjc.css → LayoutView-BLjO8ed9.css} +1 -1
  6. package/dist/web-ui/assets/{LayoutView-DtXN7Xi_.js → LayoutView-CwDRqFye.js} +1 -1
  7. package/dist/web-ui/assets/{LoginView-CUe0fqRV.js → LoginView-CdCs2Ukh.js} +1 -1
  8. package/dist/web-ui/assets/LogsView-CAszK0sY.js +5 -0
  9. package/dist/web-ui/assets/LogsView-D7FTeaYQ.css +1 -0
  10. package/dist/web-ui/assets/{ManagedServicesView-BEoMqaxE.js → ManagedServicesView-C7L56_Tq.js} +4 -4
  11. package/dist/web-ui/assets/{ManagedServicesView-Bi180Qjf.css → ManagedServicesView-D29NyvP6.css} +1 -1
  12. package/dist/web-ui/assets/{ProvidersView-5-nXXTf1.css → ProvidersView-DIlimMSR.css} +1 -1
  13. package/dist/web-ui/assets/{ProvidersView-BaddfTOz.js → ProvidersView-Du8ZqQ7C.js} +3 -3
  14. package/dist/web-ui/assets/{ServiceStatusView-RjFNR9tF.js → ServiceStatusView-BTa1U_mq.js} +1 -1
  15. package/dist/web-ui/assets/{SettingsView-CQ7lvwL9.js → SettingsView-C-lQq_Fn.js} +1 -1
  16. package/dist/web-ui/assets/SetupView-BLl-ZFOA.css +1 -0
  17. package/dist/web-ui/assets/SetupView-Oop8FC0p.js +1 -0
  18. package/dist/web-ui/assets/{config-MgmZ-7E2.js → config-a3WGd94V.js} +1 -1
  19. package/dist/web-ui/assets/format-BwEbbkjl.js +1 -0
  20. package/dist/web-ui/assets/index-DPq2QylL.js +49 -0
  21. package/dist/web-ui/assets/message-C5ZFfxcO.js +2 -0
  22. package/dist/web-ui/assets/{providers-D_WDYn62.js → providers-CmBRlVkF.js} +1 -1
  23. package/dist/web-ui/assets/router-DvvoEPD-.js +6 -0
  24. package/dist/web-ui/assets/{useCopyToast-CO6fr7kf.js → useCopyToast-BNDnj8jd.js} +1 -1
  25. package/dist/web-ui/assets/{useManagerApi-CCQ0LO2A.js → useManagerApi-CqT4wuBt.js} +1 -1
  26. package/dist/web-ui/assets/{useQuickRangeFilter-DOA0bSoV.js → useQuickRangeFilter-DPujpXE5.js} +1 -1
  27. package/dist/web-ui/assets/useToast-DeKoozwQ.js +1 -0
  28. package/dist/web-ui/index.html +3 -3
  29. package/package.json +2 -2
  30. package/dist/web-ui/assets/LogsView-CHp-pVu3.css +0 -1
  31. package/dist/web-ui/assets/LogsView-D31Tc6MJ.js +0 -5
  32. package/dist/web-ui/assets/SetupView-BDyHouba.css +0 -1
  33. package/dist/web-ui/assets/SetupView-Cm7iSrjI.js +0 -1
  34. package/dist/web-ui/assets/format-lzQY461O.js +0 -1
  35. package/dist/web-ui/assets/index-BCZqYZB7.js +0 -49
  36. package/dist/web-ui/assets/message-B4CpctQv.js +0 -2
  37. package/dist/web-ui/assets/router-B8DYHNvS.js +0 -6
  38. package/dist/web-ui/assets/useToast-C7Ey6ket.js +0 -1
@@ -1 +1 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,a as f,at as ee,bt as p,et as m,fn as h,ht as te,it as g,j as _,k as v,mt as y,nt as ne,vt as b,w as x}from"./router-B8DYHNvS.js";import{t as S}from"./useManagerApi-CCQ0LO2A.js";import{t as C}from"./providers-D_WDYn62.js";import{n as w,t as T}from"./useCopyToast-CO6fr7kf.js";import{n as E,t as re}from"./useQuickRangeFilter-DOA0bSoV.js";import{a as ie,o as D,r as ae,t as oe}from"./format-lzQY461O.js";b();function se(e){let{loadError:t,run:n}=w(e),r=c(null);function i(e){let t=async()=>{let i=await n(e);return i?r.value===t&&(r.value=null):r.value=t,i};return t}function a(e){n(r.value??e)}return{loadError:t,track:i,retry:a}}l(),b(),u();var ce={class:`flex-col-gap`},le={class:`kv-grid`},ue={class:`kv-item kv-span-2`},de={class:`kv-value`},fe={class:`kv-item`},pe={class:`kv-value`},me={class:`kv-item`},he={class:`kv-value`},ge={class:`kv-unit`},_e={class:`kv-item`},O={class:`kv-value`},k={class:`kv-item`},A={class:`kv-value`},j={class:`flex-between card-header-wrap`},M={class:`flex-gap-8`},N={class:`usage-grid`},P={class:`usage-cell`},F={class:`usage-num orange`},I={class:`usage-cell`},ve={class:`usage-num blue`},ye={class:`usage-cell`},be={class:`usage-num green`},xe={class:`usage-cell`},Se={class:`usage-num purple`},Ce={class:`usage-cell`},we={class:`usage-num purple`},Te={key:0,class:`usage-cell`},Ee={class:`usage-num gray`},De={key:0},Oe=[`onClick`],L=n({__name:`DashboardView`,setup(n){let l=C(),{copyWithToast:u}=T(),{loadError:b,track:w,retry:L}=se(),R=c(null),z=c(!0),B=c(``),{rangeKey:V,dateRange:H,onRangeChange:ke}=re(()=>U(),`today`),Ae=()=>{V.value=``,U()},je=i(()=>{let e=new Set;for(let t of l.suppliers)for(let n of t.models)e.add(n.modelName);if(R.value?.models)for(let t of R.value.models)e.add(t.model);return[...e].sort()}),Me=E(),U=w(async()=>{let e=Me();z.value=!0;try{let t=new URLSearchParams;B.value&&t.set(`model`,B.value),H.value?.length===2&&(t.set(`startDate`,H.value[0]),t.set(`endDate`,H.value[1]));let n=t.toString(),r=await f.get(`/api/usage${n?`?${n}`:``}`);if(!e())return;R.value=r}catch(t){if(!e())return;throw t}finally{e()&&(z.value=!1)}}),Ne=E(),W=w(async()=>{let e=Ne();try{await Promise.all([U(),l.loadProviders()])}catch(t){if(!e())return;throw t}finally{e()&&(z.value=!1)}}),Pe=()=>L(W),Fe=window.location.hostname,G=Number(window.location.port)||null,K=i(()=>oe({protocol:window.location.protocol,hostname:Fe,port:G})),q=c(null),J=c(null),Y=c(!1),X=c(!0),Z=c(Date.now()),Q=async()=>{let[e,t]=await Promise.allSettled([S.processes(),f.get(`/api/status`)]);if(X.value=!1,e.status===`fulfilled`&&(q.value=e.value[0]??null),t.status===`rejected`){J.value=null,Y.value=!0;return}let n=t.value?.masterKeySet;J.value=typeof n==`boolean`?n:null,Y.value=typeof n!=`boolean`,Z.value=Date.now()},Ie=e=>{if(!e.startedAt)return`-`;let t=Math.max(0,Math.floor((Z.value-e.startedAt)/1e3)),n=Math.floor(t/86400);t-=n*86400;let r=Math.floor(t/3600);t-=r*3600;let i=Math.floor(t/60);return t-=i*60,[n?`${n}天`:``,r?`${r}时`:``,i?`${i}分`:``,`${t}秒`].filter(Boolean).join(` `)},Le=i(()=>Y.value?`获取失败,请刷新重试`:J.value===null?`-`:J.value?`已设置(/v1 需 Bearer 认证)`:`未设置(/v1 免鉴权)`),$;return d(()=>{W(),Q(),$=window.setInterval(Q,1e4)}),s(()=>window.clearInterval($)),(n,i)=>{let s=g(`el-button`),c=g(`el-alert`),l=g(`el-card`),d=g(`el-option`),f=g(`el-select`),S=g(`el-date-picker`),C=g(`el-table-column`),w=g(`el-table`),T=g(`el-empty`),E=ee(`loading`);return m(),r(`div`,ce,[o(b)?(m(),e(c,{key:0,title:o(b),type:`error`,"show-icon":``,closable:!1},{default:y(()=>[t(s,{size:`small`,onClick:Pe},{default:y(()=>[...i[4]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),t(l,{shadow:`never`},{header:y(()=>[...i[5]||=[v(`span`,{class:`fw-600`},`服务信息`,-1)]]),default:y(()=>[te((m(),r(`div`,le,[v(`div`,ue,[i[6]||=v(`div`,{class:`kv-label`},`API 地址`,-1),v(`div`,de,[v(`span`,{class:`copy-text`,onClick:i[0]||=e=>o(u)(K.value)},h(K.value),1)])]),v(`div`,fe,[i[7]||=v(`div`,{class:`kv-label`},`API 密钥`,-1),v(`div`,pe,h(Le.value),1)]),v(`div`,me,[i[10]||=v(`div`,{class:`kv-label`},`运行状态`,-1),v(`div`,he,[q.value?(m(),r(x,{key:0},[i[8]||=v(`span`,{class:`status-dot running`},null,-1),i[9]||=a(`运行中 `,-1),v(`span`,ge,`PID `+h(q.value.pid??`-`),1)],64)):(m(),r(x,{key:1},[a(`-`)],64))])]),v(`div`,_e,[i[11]||=v(`div`,{class:`kv-label`},`运行时长`,-1),v(`div`,O,h(q.value?Ie(q.value):`-`),1)]),v(`div`,k,[i[12]||=v(`div`,{class:`kv-label`},`内存占用`,-1),v(`div`,A,h(q.value?o(ie)(q.value.memory):`-`),1)])])),[[E,z.value||X.value]])]),_:1}),R.value?(m(),e(l,{key:1,shadow:`never`},{header:y(()=>[v(`div`,j,[i[14]||=v(`span`,{class:`fw-600`},`用量统计`,-1),v(`div`,M,[t(f,{modelValue:B.value,"onUpdate:modelValue":i[1]||=e=>B.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`220px`},onChange:o(U)},{default:y(()=>[(m(!0),r(x,null,ne(je.value,t=>(m(),e(d,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`onChange`]),t(f,{modelValue:o(V),"onUpdate:modelValue":i[2]||=e=>p(V)?V.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`130px`},onChange:o(ke)},{default:y(()=>[t(d,{label:`今天`,value:`today`}),t(d,{label:`昨天`,value:`yesterday`}),t(d,{label:`前天`,value:`beforeYesterday`}),t(d,{label:`近三天`,value:`last3days`}),t(d,{label:`本周`,value:`week`}),t(d,{label:`本月`,value:`month`})]),_:1},8,[`modelValue`,`onChange`]),t(S,{modelValue:o(H),"onUpdate:modelValue":i[3]||=e=>p(H)?H.value=e:null,type:`daterange`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,"value-format":`YYYY-MM-DD`,style:{width:`260px`},onChange:Ae},null,8,[`modelValue`]),t(s,{loading:z.value,onClick:o(U)},{default:y(()=>[...i[13]||=[a(`刷新`,-1)]]),_:1},8,[`loading`,`onClick`])])])]),default:y(()=>[v(`div`,N,[v(`div`,P,[v(`div`,F,h(o(D)(R.value.total.total_tokens)),1),i[15]||=v(`div`,{class:`usage-label`},`总 Token`,-1)]),v(`div`,I,[v(`div`,ve,h(o(D)(R.value.total.input_tokens)),1),i[16]||=v(`div`,{class:`usage-label`},`输入 Token`,-1)]),v(`div`,ye,[v(`div`,be,h(o(D)(R.value.total.output_tokens)),1),i[17]||=v(`div`,{class:`usage-label`},`输出 Token`,-1)]),v(`div`,xe,[v(`div`,Se,h(o(D)(R.value.total.cache_read_tokens)),1),i[18]||=v(`div`,{class:`usage-label`},`缓存读取`,-1)]),v(`div`,Ce,[v(`div`,we,h(R.value.total.cache_rate==null?`-`:R.value.total.cache_rate+`%`),1),i[19]||=v(`div`,{class:`usage-label`},`缓存命中率`,-1)]),R.value.logStorageMB==null?_(``,!0):(m(),r(`div`,Te,[v(`div`,Ee,h(R.value.logStorageMB),1),i[20]||=v(`div`,{class:`usage-label`},`数据目录占用 (MB)`,-1)]))]),R.value.models?.length?(m(),r(`div`,De,[i[21]||=v(`div`,{class:`section-title`},`模型用量`,-1),t(w,{data:R.value.models,stripe:``,class:`full-width`},{default:y(()=>[t(C,{prop:`model`,label:`模型`,"min-width":`200`},{default:y(({row:e})=>[v(`span`,{class:`copy-text`,onClick:t=>o(u)(e.model)},h(e.model),9,Oe)]),_:1}),t(C,{label:`调用次数`,width:`90`,align:`center`},{default:y(({row:e})=>[a(h(e.calls),1)]),_:1}),t(C,{label:`平均耗时`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(o(ae)(e.avg_duration)),1)]),_:1}),t(C,{label:`总 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.total_tokens)),1)]),_:1}),t(C,{label:`输入 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.input_tokens)),1)]),_:1}),t(C,{label:`输出 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.output_tokens)),1)]),_:1}),t(C,{label:`缓存读取`,width:`130`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.cache_read_tokens)),1)]),_:1}),t(C,{label:`缓存命中率`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(e.cache_rate==null?`-`:e.cache_rate+`%`),1)]),_:1})]),_:1},8,[`data`])])):(m(),e(T,{key:1,description:`暂无调用记录`,"image-size":60}))]),_:1})):_(``,!0)])}}});export{L as default};
1
+ import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,a as f,at as ee,bt as p,et as m,fn as h,ht as te,it as g,j as _,k as v,mt as y,nt as ne,vt as b,w as x}from"./router-DvvoEPD-.js";import{t as S}from"./useManagerApi-CqT4wuBt.js";import{t as C}from"./providers-CmBRlVkF.js";import{n as w,t as T}from"./useCopyToast-BNDnj8jd.js";import{n as E,t as re}from"./useQuickRangeFilter-DPujpXE5.js";import{c as ie,l as D,o as ae,t as oe}from"./format-BwEbbkjl.js";b();function se(e){let{loadError:t,run:n}=w(e),r=c(null);function i(e){let t=async()=>{let i=await n(e);return i?r.value===t&&(r.value=null):r.value=t,i};return t}function a(e){n(r.value??e)}return{loadError:t,track:i,retry:a}}l(),b(),u();var ce={class:`flex-col-gap`},le={class:`kv-grid`},ue={class:`kv-item kv-span-2`},de={class:`kv-value`},fe={class:`kv-item`},pe={class:`kv-value`},me={class:`kv-item`},he={class:`kv-value`},ge={class:`kv-unit`},_e={class:`kv-item`},O={class:`kv-value`},k={class:`kv-item`},A={class:`kv-value`},j={class:`flex-between card-header-wrap`},M={class:`flex-gap-8`},N={class:`usage-grid`},P={class:`usage-cell`},F={class:`usage-num orange`},I={class:`usage-cell`},ve={class:`usage-num blue`},ye={class:`usage-cell`},be={class:`usage-num green`},xe={class:`usage-cell`},Se={class:`usage-num purple`},Ce={class:`usage-cell`},we={class:`usage-num purple`},Te={key:0,class:`usage-cell`},Ee={class:`usage-num gray`},De={key:0},Oe=[`onClick`],L=n({__name:`DashboardView`,setup(n){let l=C(),{copyWithToast:u}=T(),{loadError:b,track:w,retry:L}=se(),R=c(null),z=c(!0),B=c(``),{rangeKey:V,dateRange:H,onRangeChange:ke}=re(()=>U(),`today`),Ae=()=>{V.value=``,U()},je=i(()=>{let e=new Set;for(let t of l.suppliers)for(let n of t.models)e.add(n.modelName);if(R.value?.models)for(let t of R.value.models)e.add(t.model);return[...e].sort()}),Me=E(),U=w(async()=>{let e=Me();z.value=!0;try{let t=new URLSearchParams;B.value&&t.set(`model`,B.value),H.value?.length===2&&(t.set(`startDate`,H.value[0]),t.set(`endDate`,H.value[1]));let n=t.toString(),r=await f.get(`/api/usage${n?`?${n}`:``}`);if(!e())return;R.value=r}catch(t){if(!e())return;throw t}finally{e()&&(z.value=!1)}}),Ne=E(),W=w(async()=>{let e=Ne();try{await Promise.all([U(),l.loadProviders()])}catch(t){if(!e())return;throw t}finally{e()&&(z.value=!1)}}),Pe=()=>L(W),Fe=window.location.hostname,G=Number(window.location.port)||null,K=i(()=>oe({protocol:window.location.protocol,hostname:Fe,port:G})),q=c(null),J=c(null),Y=c(!1),X=c(!0),Z=c(Date.now()),Q=async()=>{let[e,t]=await Promise.allSettled([S.processes(),f.get(`/api/status`)]);if(X.value=!1,e.status===`fulfilled`&&(q.value=e.value[0]??null),t.status===`rejected`){J.value=null,Y.value=!0;return}let n=t.value?.masterKeySet;J.value=typeof n==`boolean`?n:null,Y.value=typeof n!=`boolean`,Z.value=Date.now()},Ie=e=>{if(!e.startedAt)return`-`;let t=Math.max(0,Math.floor((Z.value-e.startedAt)/1e3)),n=Math.floor(t/86400);t-=n*86400;let r=Math.floor(t/3600);t-=r*3600;let i=Math.floor(t/60);return t-=i*60,[n?`${n}天`:``,r?`${r}时`:``,i?`${i}分`:``,`${t}秒`].filter(Boolean).join(` `)},Le=i(()=>Y.value?`获取失败,请刷新重试`:J.value===null?`-`:J.value?`已设置(/v1 需 Bearer 认证)`:`未设置(/v1 免鉴权)`),$;return d(()=>{W(),Q(),$=window.setInterval(Q,1e4)}),s(()=>window.clearInterval($)),(n,i)=>{let s=g(`el-button`),c=g(`el-alert`),l=g(`el-card`),d=g(`el-option`),f=g(`el-select`),S=g(`el-date-picker`),C=g(`el-table-column`),w=g(`el-table`),T=g(`el-empty`),E=ee(`loading`);return m(),r(`div`,ce,[o(b)?(m(),e(c,{key:0,title:o(b),type:`error`,"show-icon":``,closable:!1},{default:y(()=>[t(s,{size:`small`,onClick:Pe},{default:y(()=>[...i[4]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),t(l,{shadow:`never`},{header:y(()=>[...i[5]||=[v(`span`,{class:`fw-600`},`服务信息`,-1)]]),default:y(()=>[te((m(),r(`div`,le,[v(`div`,ue,[i[6]||=v(`div`,{class:`kv-label`},`API 地址`,-1),v(`div`,de,[v(`span`,{class:`copy-text`,onClick:i[0]||=e=>o(u)(K.value)},h(K.value),1)])]),v(`div`,fe,[i[7]||=v(`div`,{class:`kv-label`},`API 密钥`,-1),v(`div`,pe,h(Le.value),1)]),v(`div`,me,[i[10]||=v(`div`,{class:`kv-label`},`运行状态`,-1),v(`div`,he,[q.value?(m(),r(x,{key:0},[i[8]||=v(`span`,{class:`status-dot running`},null,-1),i[9]||=a(`运行中 `,-1),v(`span`,ge,`PID `+h(q.value.pid??`-`),1)],64)):(m(),r(x,{key:1},[a(`-`)],64))])]),v(`div`,_e,[i[11]||=v(`div`,{class:`kv-label`},`运行时长`,-1),v(`div`,O,h(q.value?Ie(q.value):`-`),1)]),v(`div`,k,[i[12]||=v(`div`,{class:`kv-label`},`内存占用`,-1),v(`div`,A,h(q.value?o(ie)(q.value.memory):`-`),1)])])),[[E,z.value||X.value]])]),_:1}),R.value?(m(),e(l,{key:1,shadow:`never`},{header:y(()=>[v(`div`,j,[i[14]||=v(`span`,{class:`fw-600`},`用量统计`,-1),v(`div`,M,[t(f,{modelValue:B.value,"onUpdate:modelValue":i[1]||=e=>B.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`220px`},onChange:o(U)},{default:y(()=>[(m(!0),r(x,null,ne(je.value,t=>(m(),e(d,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`onChange`]),t(f,{modelValue:o(V),"onUpdate:modelValue":i[2]||=e=>p(V)?V.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`130px`},onChange:o(ke)},{default:y(()=>[t(d,{label:`今天`,value:`today`}),t(d,{label:`昨天`,value:`yesterday`}),t(d,{label:`前天`,value:`beforeYesterday`}),t(d,{label:`近三天`,value:`last3days`}),t(d,{label:`本周`,value:`week`}),t(d,{label:`本月`,value:`month`})]),_:1},8,[`modelValue`,`onChange`]),t(S,{modelValue:o(H),"onUpdate:modelValue":i[3]||=e=>p(H)?H.value=e:null,type:`daterange`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,"value-format":`YYYY-MM-DD`,style:{width:`260px`},onChange:Ae},null,8,[`modelValue`]),t(s,{loading:z.value,onClick:o(U)},{default:y(()=>[...i[13]||=[a(`刷新`,-1)]]),_:1},8,[`loading`,`onClick`])])])]),default:y(()=>[v(`div`,N,[v(`div`,P,[v(`div`,F,h(o(D)(R.value.total.total_tokens)),1),i[15]||=v(`div`,{class:`usage-label`},`总 Token`,-1)]),v(`div`,I,[v(`div`,ve,h(o(D)(R.value.total.input_tokens)),1),i[16]||=v(`div`,{class:`usage-label`},`输入 Token`,-1)]),v(`div`,ye,[v(`div`,be,h(o(D)(R.value.total.output_tokens)),1),i[17]||=v(`div`,{class:`usage-label`},`输出 Token`,-1)]),v(`div`,xe,[v(`div`,Se,h(o(D)(R.value.total.cache_read_tokens)),1),i[18]||=v(`div`,{class:`usage-label`},`缓存读取`,-1)]),v(`div`,Ce,[v(`div`,we,h(R.value.total.cache_rate==null?`-`:R.value.total.cache_rate+`%`),1),i[19]||=v(`div`,{class:`usage-label`},`缓存命中率`,-1)]),R.value.logStorageMB==null?_(``,!0):(m(),r(`div`,Te,[v(`div`,Ee,h(R.value.logStorageMB),1),i[20]||=v(`div`,{class:`usage-label`},`数据目录占用 (MB)`,-1)]))]),R.value.models?.length?(m(),r(`div`,De,[i[21]||=v(`div`,{class:`section-title`},`模型用量`,-1),t(w,{data:R.value.models,stripe:``,class:`full-width`},{default:y(()=>[t(C,{prop:`model`,label:`模型`,"min-width":`200`},{default:y(({row:e})=>[v(`span`,{class:`copy-text`,onClick:t=>o(u)(e.model)},h(e.model),9,Oe)]),_:1}),t(C,{label:`调用次数`,width:`90`,align:`center`},{default:y(({row:e})=>[a(h(e.calls),1)]),_:1}),t(C,{label:`平均耗时`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(o(ae)(e.avg_duration)),1)]),_:1}),t(C,{label:`总 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.total_tokens)),1)]),_:1}),t(C,{label:`输入 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.input_tokens)),1)]),_:1}),t(C,{label:`输出 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.output_tokens)),1)]),_:1}),t(C,{label:`缓存读取`,width:`130`,align:`center`},{default:y(({row:e})=>[a(h(o(D)(e.cache_read_tokens)),1)]),_:1}),t(C,{label:`缓存命中率`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(e.cache_rate==null?`-`:e.cache_rate+`%`),1)]),_:1})]),_:1},8,[`data`])])):(m(),e(T,{key:1,description:`暂无调用记录`,"image-size":60}))]),_:1})):_(``,!0)])}}});export{L as default};
@@ -1 +1 @@
1
- .mt-8[data-v-ea1efda8]{margin-top:8px}.mt-12[data-v-ea1efda8]{margin-top:12px}.check-body[data-v-ea1efda8]{min-height:80px}.alert-hint[data-v-ea1efda8]{margin-top:4px;font-size:12px;line-height:1.6}.alert-hint code[data-v-ea1efda8]{background:var(--el-fill-color-light);border-radius:4px;padding:1px 6px;font-size:12px}.version-row[data-v-ea1efda8]{align-items:center;gap:8px;margin-bottom:8px;display:flex}.version-label[data-v-ea1efda8]{color:var(--el-text-color-secondary);font-size:13px}.muted-sm[data-v-ea1efda8]{color:var(--el-text-color-secondary);margin-top:8px;font-size:12px}.user-chip[data-v-84476c36]{cursor:pointer;border-radius:999px;outline:none;align-items:center;gap:8px;padding:4px 8px 4px 4px;transition:background .15s;display:flex}.user-chip[data-v-84476c36]:hover{background:var(--el-fill-color-light)}.user-avatar[data-v-84476c36]{color:#fff;background:linear-gradient(135deg,#4f8df9 0%,#2563eb 100%);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:28px;height:28px;font-size:13px;font-weight:600;display:inline-flex}.user-name[data-v-84476c36]{color:var(--el-text-color-primary);text-overflow:ellipsis;white-space:nowrap;max-width:120px;font-size:13px;overflow:hidden}.user-chip .el-icon--right[data-v-84476c36]{color:var(--el-text-color-secondary);font-size:12px}
1
+ .mt-8[data-v-ea1efda8]{margin-top:8px}.mt-12[data-v-ea1efda8]{margin-top:12px}.check-body[data-v-ea1efda8]{min-height:80px}.alert-hint[data-v-ea1efda8]{margin-top:4px;font-size:12px;line-height:1.6}.alert-hint code[data-v-ea1efda8]{background:var(--el-fill-color-light);border-radius:4px;padding:1px 6px;font-size:12px}.version-row[data-v-ea1efda8]{align-items:center;gap:8px;margin-bottom:8px;display:flex}.version-label[data-v-ea1efda8]{color:var(--el-text-color-secondary);font-size:13px}.muted-sm[data-v-ea1efda8]{color:var(--el-text-color-secondary);margin-top:8px;font-size:12px}.user-chip[data-v-26778c58]{cursor:pointer;border-radius:999px;outline:none;align-items:center;gap:8px;padding:4px 8px 4px 4px;transition:background .15s;display:flex}.user-chip[data-v-26778c58]:hover{background:var(--el-fill-color-light)}.user-avatar[data-v-26778c58]{color:#fff;background:linear-gradient(135deg,#4f8df9 0%,#2563eb 100%);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:28px;height:28px;font-size:13px;font-weight:600;display:inline-flex}.user-name[data-v-26778c58]{color:var(--el-text-color-primary);text-overflow:ellipsis;white-space:nowrap;max-width:120px;font-size:13px;overflow:hidden}.user-chip .el-icon--right[data-v-26778c58]{color:var(--el-text-color-secondary);font-size:12px}
@@ -1 +1 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Tt as s,V as c,Wt as l,Z as u,at as d,et as f,fn as p,ht as m,i as h,it as g,j as _,k as v,l as y,lt as b,mt as x,n as S,o as C,u as w,vt as T,w as E}from"./router-B8DYHNvS.js";import{m as D}from"./message-B4CpctQv.js";import{n as O,t as k}from"./index-BCZqYZB7.js";import{n as A,t as j}from"./useManagerApi-CCQ0LO2A.js";import{t as M}from"./useToast-C7Ey6ket.js";import{n as N,t as P}from"./version-DegxwpkG.js";c(),l(),T();var F={class:`check-body`},I={class:`version-row`},L={class:`version-row`},R={class:`muted-sm`},z=k(n({__name:`UpdateCheckDialog`,props:{modelValue:{type:Boolean,default:!1},modelModifiers:{}},emits:[`update:modelValue`],setup(n){let{toast:i}=M(),c=b(n,`modelValue`),l=s(!1),u=s(!1),h=s(null),y=s(null),S=s(null),C=s(null),w=null,T=()=>w?.abort(),D=e=>new Date(e).toLocaleString(),k=e=>`https://www.npmjs.com/package/ezllm/v/${e}`,z=async()=>{y.value=null,S.value=null,C.value=null,l.value=!0;try{let e=await j.update();if(h.value=e,!e.supported)return;y.value=await j.checkUpdate()}catch(e){S.value=e.message||`检查更新失败`}finally{l.value=!1}},B=async()=>{if(!y.value)return;let e=y.value.latestVersion;try{await O.confirm(`确定更新到 ${e}?服务会自动重启并在启动时安装新版本:重启期间管理台短暂不可访问(预计 1~3 分钟),更新完成后自动恢复。`,`更新确认`,{confirmButtonText:`立即更新`,cancelButtonText:`取消`,type:`warning`})}catch{return}u.value=!0;let t=new AbortController;w=t;try{let e=await j.update(),n=await j.applyUpdate();if(!n.updated){C.value=`已是最新版本 ${n.toVersion}`,y.value={hasUpdate:!1,currentVersion:n.toVersion,latestVersion:n.toVersion,checkedAt:Date.now()};return}C.value=`正在重启服务并安装 ${n.toVersion}(预计 1~3 分钟):重启期间管理台短暂不可访问,完成后这里会自动显示结果。`;let r=await A({targetVersion:n.toVersion,sinceAppliedAt:e.lastApply?.appliedAt??null,signal:t.signal});if(t.signal.aborted)return;r&&!r.error?(i(`已更新到 ${r.toVersion}`,`success`),C.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`,y.value={hasUpdate:!1,currentVersion:r.toVersion,latestVersion:r.toVersion,checkedAt:Date.now()}):r?.error?(i(`更新失败:${r.error}`,`error`),C.value=N(r.error)):C.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){i(e.message||`更新失败`,`error`)}finally{u.value=!1,w===t&&(w=null)}};return(n,i)=>{let s=g(`el-alert`),b=g(`el-tag`),w=g(`el-link`),O=g(`el-button`),A=g(`el-dialog`),j=d(`loading`);return f(),e(A,{modelValue:c.value,"onUpdate:modelValue":i[2]||=e=>c.value=e,title:`检查更新`,width:`420px`,"close-on-click-modal":!u.value,onOpen:z,onClose:T},{footer:x(()=>[y.value?.hasUpdate?(f(),e(O,{key:0,type:`primary`,loading:u.value,onClick:B},{default:x(()=>[a(p(u.value?`更新中...`:`立即更新`),1)]),_:1},8,[`loading`])):_(``,!0),t(O,{onClick:i[1]||=e=>c.value=!1},{default:x(()=>[...i[11]||=[a(`关闭`,-1)]]),_:1})]),default:x(()=>[m((f(),r(`div`,F,[h.value&&!h.value.supported?(f(),e(s,{key:0,title:`当前为源码运行模式,更新功能不可用`,type:`info`,"show-icon":``,closable:!1},{default:x(()=>[...i[3]||=[v(`div`,{class:`alert-hint`},[a(` 仅 npm 全局安装的包支持自动更新。本地开发用仓库里的 `),v(`code`,null,`pnpm upgrade:local`),a(` 更新运行中的服务。 `)],-1)]]),_:1})):y.value?(f(),r(E,{key:1},[v(`div`,I,[i[5]||=v(`span`,{class:`version-label`},`当前版本`,-1),t(b,{size:`small`},{default:x(()=>[a(p(y.value.currentVersion),1)]),_:1}),o(P)(y.value.currentVersion)?(f(),e(b,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:x(()=>[...i[4]||=[a(`本地构建`,-1)]]),_:1})):_(``,!0)]),v(`div`,L,[i[6]||=v(`span`,{class:`version-label`},`最新版本`,-1),t(b,{type:y.value.hasUpdate?`warning`:`success`,size:`small`,"disable-transitions":``},{default:x(()=>[a(p(y.value.latestVersion),1)]),_:1},8,[`type`])]),t(s,{title:y.value.hasUpdate?`发现新版本 ${y.value.latestVersion}(当前 ${y.value.currentVersion})`:`已是最新版本 ${y.value.currentVersion}`,type:y.value.hasUpdate?`warning`:`success`,"show-icon":``,closable:!1,class:`mt-12`},null,8,[`title`,`type`]),v(`div`,R,[a(` 检查时间:`+p(D(y.value.checkedAt))+` `,1),y.value.hasUpdate?(f(),r(E,{key:0},[i[8]||=a(` · `,-1),t(w,{type:`primary`,href:k(y.value.latestVersion),target:`_blank`},{default:x(()=>[...i[7]||=[a(`在 npm 查看该版本`,-1)]]),_:1},8,[`href`])],64)):_(``,!0)])],64)):!l.value&&S.value?(f(),e(s,{key:2,title:S.value,type:`error`,"show-icon":``,closable:!1},{default:x(()=>[i[10]||=v(`div`,{class:`alert-hint`},` 检查需访问 npm 源,可能是网络不可达或版本号解析失败;稍后重试即可。 `,-1),t(O,{size:`small`,class:`mt-8`,onClick:z},{default:x(()=>[...i[9]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0)])),[[j,l.value]]),C.value?(f(),e(s,{key:0,title:C.value,type:`info`,"show-icon":``,class:`mt-12`,onClose:i[0]||=e=>C.value=null},null,8,[`title`])):_(``,!0)]),_:1},8,[`modelValue`,`close-on-click-modal`])}}}),[[`__scopeId`,`data-v-ea1efda8`]]);c(),l(),T();var B={class:`layout`},V=[`title`],H={key:0,class:`header-version-tag`},U={class:`header-nav`},W={class:`header-actions`},G={class:`user-chip`},K={class:`user-avatar`},q={class:`user-name`},J={class:`main`},Y={class:`page`},X=k(n({__name:`LayoutView`,setup(n){let c=y(),l=w(),d=s(!1);u(()=>{S()});let m=i(()=>h.value?.version||``),b=i(()=>P(h.value?.version)),T=i(()=>b.value?`本地构建版本(upgrade:local 产物)`:`当前运行版本`),E=i(()=>h.value?.authRequired!==!1),O=i(()=>{if(!E.value)return`免登录`;let e=localStorage.getItem(`webui_token`)||``;try{return atob(e).split(`:`)[0]||`用户`}catch{return`用户`}}),k=i(()=>{let e=c.path;return e===`/`?`/`:e.startsWith(`/providers`)?`/providers`:e.startsWith(`/service-status`)?`/service-status`:e.startsWith(`/managed-services`)?`/managed-services`:e.startsWith(`/settings`)?`/settings`:e.startsWith(`/logs`)?`/logs`:`/`}),A=()=>{C(),l.push(`/login`)},j=e=>{e===`logout`&&A(),e===`check-update`&&(d.value=!0)};return(n,i)=>{let s=g(`el-menu-item`),c=g(`el-menu`),l=g(`el-icon`),u=g(`el-dropdown-item`),h=g(`el-dropdown-menu`),y=g(`el-dropdown`),S=g(`el-header`),C=g(`router-view`);return f(),r(`div`,B,[t(S,{class:`header`},{default:x(()=>[i[9]||=v(`div`,{class:`brand`},[v(`span`,{class:`brand-mark`},`EZ`),v(`h1`,null,`LLM`)],-1),m.value?(f(),r(`span`,{key:0,class:`header-version`,title:T.value},[a(` v`+p(m.value),1),b.value?(f(),r(`span`,H,`本地构建`)):_(``,!0)],8,V)):_(``,!0),v(`nav`,U,[t(c,{mode:`horizontal`,"default-active":k.value,ellipsis:!1,router:``,class:`header-menu`},{default:x(()=>[t(s,{index:`/`},{default:x(()=>[...i[1]||=[a(`首页`,-1)]]),_:1}),t(s,{index:`/providers`},{default:x(()=>[...i[2]||=[a(`供应商管理`,-1)]]),_:1}),t(s,{index:`/service-status`},{default:x(()=>[...i[3]||=[a(`服务状态`,-1)]]),_:1}),t(s,{index:`/managed-services`},{default:x(()=>[...i[4]||=[a(`托管服务`,-1)]]),_:1}),t(s,{index:`/logs`},{default:x(()=>[...i[5]||=[a(`日志`,-1)]]),_:1}),t(s,{index:`/settings`},{default:x(()=>[...i[6]||=[a(`设置`,-1)]]),_:1})]),_:1},8,[`default-active`])]),v(`div`,W,[t(y,{trigger:`click`,onCommand:j,class:`ml-12`},{dropdown:x(()=>[t(h,null,{default:x(()=>[t(u,{command:`check-update`},{default:x(()=>[...i[7]||=[a(`检查更新`,-1)]]),_:1}),E.value?(f(),e(u,{key:0,command:`logout`,divided:``},{default:x(()=>[...i[8]||=[a(`退出`,-1)]]),_:1})):_(``,!0)]),_:1})]),default:x(()=>[v(`div`,G,[v(`span`,K,p(O.value.charAt(0).toUpperCase()),1),v(`span`,q,p(O.value),1),t(l,{class:`el-icon--right`},{default:x(()=>[t(o(D))]),_:1})])]),_:1})])]),_:1}),v(`main`,J,[v(`div`,Y,[t(C)])]),t(z,{modelValue:d.value,"onUpdate:modelValue":i[0]||=e=>d.value=e},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-84476c36`]]);export{X as default};
1
+ import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Tt as s,V as c,Wt as l,Z as u,at as d,et as f,fn as p,ht as m,i as h,it as g,j as _,k as v,l as y,lt as b,mt as x,n as S,o as C,u as w,vt as T,w as E}from"./router-DvvoEPD-.js";import{m as D}from"./message-C5ZFfxcO.js";import{n as O,t as k}from"./index-DPq2QylL.js";import{n as A,t as j}from"./useManagerApi-CqT4wuBt.js";import{t as M}from"./useToast-DeKoozwQ.js";import{n as N,t as P}from"./version-DegxwpkG.js";c(),l(),T();var F={class:`check-body`},I={class:`version-row`},L={class:`version-row`},R={class:`muted-sm`},z=k(n({__name:`UpdateCheckDialog`,props:{modelValue:{type:Boolean,default:!1},modelModifiers:{}},emits:[`update:modelValue`],setup(n){let{toast:i}=M(),c=b(n,`modelValue`),l=s(!1),u=s(!1),h=s(null),y=s(null),S=s(null),C=s(null),w=null,T=()=>w?.abort(),D=e=>new Date(e).toLocaleString(),k=e=>`https://www.npmjs.com/package/ezllm/v/${e}`,z=async()=>{y.value=null,S.value=null,C.value=null,l.value=!0;try{let e=await j.update();if(h.value=e,!e.supported)return;y.value=await j.checkUpdate()}catch(e){S.value=e.message||`检查更新失败`}finally{l.value=!1}},B=async()=>{if(!y.value)return;let e=y.value.latestVersion;try{await O.confirm(`确定更新到 ${e}?服务会自动重启并在启动时安装新版本:重启期间管理台短暂不可访问(预计 1~3 分钟),更新完成后自动恢复。`,`更新确认`,{confirmButtonText:`立即更新`,cancelButtonText:`取消`,type:`warning`})}catch{return}u.value=!0;let t=new AbortController;w=t;try{let e=await j.update(),n=await j.applyUpdate();if(!n.updated){C.value=`已是最新版本 ${n.toVersion}`,y.value={hasUpdate:!1,currentVersion:n.toVersion,latestVersion:n.toVersion,checkedAt:Date.now()};return}C.value=`正在重启服务并安装 ${n.toVersion}(预计 1~3 分钟):重启期间管理台短暂不可访问,完成后这里会自动显示结果。`;let r=await A({targetVersion:n.toVersion,sinceAppliedAt:e.lastApply?.appliedAt??null,signal:t.signal});if(t.signal.aborted)return;r&&!r.error?(i(`已更新到 ${r.toVersion}`,`success`),C.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`,y.value={hasUpdate:!1,currentVersion:r.toVersion,latestVersion:r.toVersion,checkedAt:Date.now()}):r?.error?(i(`更新失败:${r.error}`,`error`),C.value=N(r.error)):C.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){i(e.message||`更新失败`,`error`)}finally{u.value=!1,w===t&&(w=null)}};return(n,i)=>{let s=g(`el-alert`),b=g(`el-tag`),w=g(`el-link`),O=g(`el-button`),A=g(`el-dialog`),j=d(`loading`);return f(),e(A,{modelValue:c.value,"onUpdate:modelValue":i[2]||=e=>c.value=e,title:`检查更新`,width:`420px`,"close-on-click-modal":!u.value,onOpen:z,onClose:T},{footer:x(()=>[y.value?.hasUpdate?(f(),e(O,{key:0,type:`primary`,loading:u.value,onClick:B},{default:x(()=>[a(p(u.value?`更新中...`:`立即更新`),1)]),_:1},8,[`loading`])):_(``,!0),t(O,{onClick:i[1]||=e=>c.value=!1},{default:x(()=>[...i[11]||=[a(`关闭`,-1)]]),_:1})]),default:x(()=>[m((f(),r(`div`,F,[h.value&&!h.value.supported?(f(),e(s,{key:0,title:`当前为源码运行模式,更新功能不可用`,type:`info`,"show-icon":``,closable:!1},{default:x(()=>[...i[3]||=[v(`div`,{class:`alert-hint`},[a(` 仅 npm 全局安装的包支持自动更新。本地开发用仓库里的 `),v(`code`,null,`pnpm upgrade:local`),a(` 更新运行中的服务。 `)],-1)]]),_:1})):y.value?(f(),r(E,{key:1},[v(`div`,I,[i[5]||=v(`span`,{class:`version-label`},`当前版本`,-1),t(b,{size:`small`},{default:x(()=>[a(p(y.value.currentVersion),1)]),_:1}),o(P)(y.value.currentVersion)?(f(),e(b,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:x(()=>[...i[4]||=[a(`本地构建`,-1)]]),_:1})):_(``,!0)]),v(`div`,L,[i[6]||=v(`span`,{class:`version-label`},`最新版本`,-1),t(b,{type:y.value.hasUpdate?`warning`:`success`,size:`small`,"disable-transitions":``},{default:x(()=>[a(p(y.value.latestVersion),1)]),_:1},8,[`type`])]),t(s,{title:y.value.hasUpdate?`发现新版本 ${y.value.latestVersion}(当前 ${y.value.currentVersion})`:`已是最新版本 ${y.value.currentVersion}`,type:y.value.hasUpdate?`warning`:`success`,"show-icon":``,closable:!1,class:`mt-12`},null,8,[`title`,`type`]),v(`div`,R,[a(` 检查时间:`+p(D(y.value.checkedAt))+` `,1),y.value.hasUpdate?(f(),r(E,{key:0},[i[8]||=a(` · `,-1),t(w,{type:`primary`,href:k(y.value.latestVersion),target:`_blank`},{default:x(()=>[...i[7]||=[a(`在 npm 查看该版本`,-1)]]),_:1},8,[`href`])],64)):_(``,!0)])],64)):!l.value&&S.value?(f(),e(s,{key:2,title:S.value,type:`error`,"show-icon":``,closable:!1},{default:x(()=>[i[10]||=v(`div`,{class:`alert-hint`},` 检查需访问 npm 源,可能是网络不可达或版本号解析失败;稍后重试即可。 `,-1),t(O,{size:`small`,class:`mt-8`,onClick:z},{default:x(()=>[...i[9]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0)])),[[j,l.value]]),C.value?(f(),e(s,{key:0,title:C.value,type:`info`,"show-icon":``,class:`mt-12`,onClose:i[0]||=e=>C.value=null},null,8,[`title`])):_(``,!0)]),_:1},8,[`modelValue`,`close-on-click-modal`])}}}),[[`__scopeId`,`data-v-ea1efda8`]]);c(),l(),T();var B={class:`layout`},V=[`title`],H={key:0,class:`header-version-tag`},U={class:`header-nav`},W={class:`header-actions`},G={class:`user-chip`},K={class:`user-avatar`},q={class:`user-name`},J={class:`main`},Y={class:`page`},X=k(n({__name:`LayoutView`,setup(n){let c=y(),l=w(),d=s(!1);u(()=>{S()});let m=i(()=>h.value?.version||``),b=i(()=>P(h.value?.version)),T=i(()=>b.value?`本地构建版本(upgrade:local 产物)`:`当前运行版本`),E=i(()=>h.value?.authRequired!==!1),O=i(()=>{if(!E.value)return`免登录`;let e=localStorage.getItem(`webui_token`)||``;try{return atob(e).split(`:`)[0]||`用户`}catch{return`用户`}}),k=i(()=>{let e=c.path;return e===`/`?`/`:e.startsWith(`/providers`)?`/providers`:e.startsWith(`/service-status`)?`/service-status`:e.startsWith(`/managed-services`)?`/managed-services`:e.startsWith(`/settings`)?`/settings`:e.startsWith(`/logs`)?`/logs`:`/`}),A=e=>{e===`logout`&&(C(),l.push(`/login`)),e===`check-update`&&(d.value=!0)};return(n,i)=>{let s=g(`el-menu-item`),c=g(`el-menu`),l=g(`el-icon`),u=g(`el-dropdown-item`),h=g(`el-dropdown-menu`),y=g(`el-dropdown`),S=g(`el-header`),C=g(`router-view`);return f(),r(`div`,B,[t(S,{class:`header`},{default:x(()=>[i[9]||=v(`div`,{class:`brand`},[v(`span`,{class:`brand-mark`},`EZ`),v(`h1`,null,`LLM`)],-1),m.value?(f(),r(`span`,{key:0,class:`header-version`,title:T.value},[a(` v`+p(m.value),1),b.value?(f(),r(`span`,H,`本地构建`)):_(``,!0)],8,V)):_(``,!0),v(`nav`,U,[t(c,{mode:`horizontal`,"default-active":k.value,ellipsis:!1,router:``,class:`header-menu`},{default:x(()=>[t(s,{index:`/`},{default:x(()=>[...i[1]||=[a(`首页`,-1)]]),_:1}),t(s,{index:`/providers`},{default:x(()=>[...i[2]||=[a(`供应商管理`,-1)]]),_:1}),t(s,{index:`/service-status`},{default:x(()=>[...i[3]||=[a(`服务状态`,-1)]]),_:1}),t(s,{index:`/managed-services`},{default:x(()=>[...i[4]||=[a(`托管服务`,-1)]]),_:1}),t(s,{index:`/logs`},{default:x(()=>[...i[5]||=[a(`日志`,-1)]]),_:1}),t(s,{index:`/settings`},{default:x(()=>[...i[6]||=[a(`设置`,-1)]]),_:1})]),_:1},8,[`default-active`])]),v(`div`,W,[t(y,{trigger:`click`,onCommand:A,class:`ml-12`},{dropdown:x(()=>[t(h,null,{default:x(()=>[t(u,{command:`check-update`},{default:x(()=>[...i[7]||=[a(`检查更新`,-1)]]),_:1}),E.value?(f(),e(u,{key:0,command:`logout`,divided:``},{default:x(()=>[...i[8]||=[a(`退出`,-1)]]),_:1})):_(``,!0)]),_:1})]),default:x(()=>[v(`div`,G,[v(`span`,K,p(O.value.charAt(0).toUpperCase()),1),v(`span`,q,p(O.value),1),t(l,{class:`el-icon--right`},{default:x(()=>[t(o(D))]),_:1})])]),_:1})])]),_:1}),v(`main`,J,[v(`div`,Y,[t(C)])]),t(z,{modelValue:d.value,"onUpdate:modelValue":i[0]||=e=>d.value=e},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-26778c58`]]);export{X as default};
@@ -1 +1 @@
1
- import{A as e,F as t,I as n,M as r,P as i,S as a,Tt as o,V as s,a as c,c as l,et as u,it as d,j as f,k as p,m,mt as h,u as g,vt as _,x as v}from"./router-B8DYHNvS.js";import{t as y}from"./index-BCZqYZB7.js";s(),m(),_();var b={class:`login-wrap`},x=y(n({__name:`LoginView`,setup(n){let s=g(),m=o(``),_=o(``),y=o(``),x=o(!1);async function S(){if(!m.value){y.value=`请输入用户名`;return}if(!_.value){y.value=`请输入密码`;return}x.value=!0,y.value=``;try{let e=await c.post(`/api/auth/login`,{username:m.value.trim(),password:_.value});l(e.token),s.push(`/`)}catch(e){y.value=e.message||`登录失败`}finally{x.value=!1}}return(n,o)=>{let s=d(`el-input`),c=d(`el-form-item`),l=d(`el-alert`),g=d(`el-button`),C=d(`el-form`),w=d(`el-card`);return u(),r(`div`,b,[t(w,{shadow:`never`,class:`login-card`},{default:h(()=>[o[3]||=p(`div`,{class:`login-brand`},[p(`span`,{class:`brand-mark`},`EZ`),p(`span`,{class:`login-title`},`LLM`)],-1),o[4]||=p(`p`,{class:`login-sub`},`本地 LLM 网关 · 管理台登录`,-1),t(C,{"label-position":`top`,onSubmit:a(S,[`prevent`])},{default:h(()=>[t(c,{label:`用户名`},{default:h(()=>[t(s,{modelValue:m.value,"onUpdate:modelValue":o[0]||=e=>m.value=e,placeholder:`请输入用户名`,onKeyup:v(S,[`enter`])},null,8,[`modelValue`])]),_:1}),t(c,{label:`密码`},{default:h(()=>[t(s,{modelValue:_.value,"onUpdate:modelValue":o[1]||=e=>_.value=e,type:`password`,placeholder:`请输入密码`,"show-password":``,onKeyup:v(S,[`enter`])},null,8,[`modelValue`])]),_:1}),y.value?(u(),e(l,{key:0,title:y.value,type:`error`,"show-icon":``,class:`mb-16`},null,8,[`title`])):f(``,!0),t(g,{type:`primary`,class:`full-width`,loading:x.value,onClick:S},{default:h(()=>[...o[2]||=[i(` 登录 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-b3e448fa`]]);export{x as default};
1
+ import{A as e,F as t,I as n,M as r,P as i,S as a,Tt as o,V as s,a as c,c as l,et as u,it as d,j as f,k as p,m,mt as h,u as g,vt as _,x as v}from"./router-DvvoEPD-.js";import{t as y}from"./index-DPq2QylL.js";s(),m(),_();var b={class:`login-wrap`},x=y(n({__name:`LoginView`,setup(n){let s=g(),m=o(``),_=o(``),y=o(``),x=o(!1);async function S(){if(!m.value){y.value=`请输入用户名`;return}if(!_.value){y.value=`请输入密码`;return}x.value=!0,y.value=``;try{let e=await c.post(`/api/auth/login`,{username:m.value.trim(),password:_.value});l(e.token),s.push(`/`)}catch(e){y.value=e.message||`登录失败`}finally{x.value=!1}}return(n,o)=>{let s=d(`el-input`),c=d(`el-form-item`),l=d(`el-alert`),g=d(`el-button`),C=d(`el-form`),w=d(`el-card`);return u(),r(`div`,b,[t(w,{shadow:`never`,class:`login-card`},{default:h(()=>[o[3]||=p(`div`,{class:`login-brand`},[p(`span`,{class:`brand-mark`},`EZ`),p(`span`,{class:`login-title`},`LLM`)],-1),o[4]||=p(`p`,{class:`login-sub`},`本地 LLM 网关 · 管理台登录`,-1),t(C,{"label-position":`top`,onSubmit:a(S,[`prevent`])},{default:h(()=>[t(c,{label:`用户名`},{default:h(()=>[t(s,{modelValue:m.value,"onUpdate:modelValue":o[0]||=e=>m.value=e,placeholder:`请输入用户名`,onKeyup:v(S,[`enter`])},null,8,[`modelValue`])]),_:1}),t(c,{label:`密码`},{default:h(()=>[t(s,{modelValue:_.value,"onUpdate:modelValue":o[1]||=e=>_.value=e,type:`password`,placeholder:`请输入密码`,"show-password":``,onKeyup:v(S,[`enter`])},null,8,[`modelValue`])]),_:1}),y.value?(u(),e(l,{key:0,title:y.value,type:`error`,"show-icon":``,class:`mb-16`},null,8,[`title`])):f(``,!0),t(g,{type:`primary`,class:`full-width`,loading:x.value,onClick:S},{default:h(()=>[...o[2]||=[i(` 登录 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-b3e448fa`]]);export{x as default};
@@ -0,0 +1,5 @@
1
+ import{A as e,Ct as t,F as n,I as r,M as i,O as a,P as o,Pt as s,S as c,Tt as l,V as u,Wt as d,Z as f,a as p,at as ee,bt as m,et as h,fn as g,ft as _,ht as v,it as y,j as b,k as x,m as S,mt as C,nt as w,vt as T,w as E,x as D,xt as O}from"./router-DvvoEPD-.js";import{R as k,S as te}from"./message-C5ZFfxcO.js";import{n as A,t as j}from"./index-DPq2QylL.js";import{t as M}from"./providers-CmBRlVkF.js";import{n as N,t as P}from"./useCopyToast-BNDnj8jd.js";import{t as F}from"./useToast-DeKoozwQ.js";import{n as I,t as ne}from"./useQuickRangeFilter-DPujpXE5.js";import{_ as re,a as L,d as R,f as z,i as ie,l as B,n as ae,o as oe,p as V,r as se,u as H,v as U}from"./format-BwEbbkjl.js";u(),T(),d();var W={class:`detail-content`},ce={key:0,class:`ip-link`},le={class:`ip-pop`},G={class:`ip-pop-row`},ue={key:0,class:`ip-pop-row`},K={key:1,class:`ip-pop-error`},q={key:2},J=[`href`],de={key:1},fe={key:1},pe={class:`error-text`},Y={class:`pane-bar`},me={class:`json-block`},he={class:`pane-bar`},ge={class:`json-block`},X={class:`pane-bar`},_e={class:`json-block`},ve={class:`pane-bar`},Z={class:`json-block`},ye={class:`pane-bar`},Q={class:`json-block`},be={class:`pane-bar`},xe={class:`json-block`},$={class:`pane-bar`},Se={class:`json-block`},Ce={class:`pane-bar`},we={class:`json-block`},Te=j(r({__name:`LogDetailDialog`,setup(t,{expose:r}){let{copyWithToast:c}=P(),{loadError:u,run:d}=N(),f=l(!1),m=l(null),_=l(!1),S=l(`info`),w=l(!1),T=l(null),D=I(),k=e=>{T.value=e,f.value=!0,m.value=null,S.value=`info`;let t=D();_.value=!0,d(async()=>{try{let n=`?id=${String(e.id)}`,r=await p.get(`/api/logs/detail`+n);if(!t())return;if(r&&r.detail){let e={...r.detail,...r.meta};e.response&&=O(e.response),e.request&&=O(e.request),m.value=e}else m.value=r}catch(e){if(!t())return;throw e}finally{t()&&(_.value=!1)}})},te=()=>{T.value&&k(T.value)};r({open:k});let A=a(()=>H(m.value?.response?.inbound_request)),j=a(()=>H(m.value?.response?.upstream_request)),M=a(()=>z(m.value?.response?.upstream_response_text)),F=a(()=>(m.value?.response?.upstream_stream_frames||[]).join(`
2
+
3
+ `)),ne=a(()=>H(m.value?.response?.client_response)),re=a(()=>(m.value?.response?.client_stream_frames||[]).join(`
4
+
5
+ `)),L=a(()=>H(m.value?.request)),ie=a(()=>H(m.value?.response)),V=async e=>{if(!(e._ipInfo||e._ipInfoError)){w.value=!0;try{let t=await p.get(`/api/logs/ipinfo?ip=${encodeURIComponent(e.ip)}`);t.error?e._ipInfoError=t.error:e._ipInfo=t}catch{e._ipInfoError=`查询失败`}finally{w.value=!1}}},se=e=>[e.country,e.region,e.city].filter(Boolean).join(` · `)||`-`;return(t,r)=>{let a=y(`el-button`),l=y(`el-alert`),d=y(`el-descriptions-item`),p=y(`el-tag`),T=y(`el-divider`),D=y(`el-popover`),O=y(`el-descriptions`),k=y(`el-tab-pane`),N=y(`el-tabs`),P=y(`el-dialog`),I=ee(`loading`);return h(),e(P,{modelValue:f.value,"onUpdate:modelValue":r[11]||=e=>f.value=e,title:`日志详情`,width:`80%`,top:`5vh`,"destroy-on-close":``},{default:C(()=>[s(u)?(h(),e(l,{key:0,title:s(u),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:C(()=>[n(a,{size:`small`,onClick:te},{default:C(()=>[...r[12]||=[o(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):b(``,!0),v((h(),i(`div`,W,[m.value?(h(),e(N,{key:0,modelValue:S.value,"onUpdate:modelValue":r[10]||=e=>S.value=e},{default:C(()=>[n(k,{lazy:``,label:`基本信息`,name:`info`},{default:C(()=>[n(O,{column:2,border:``},{default:C(()=>[n(d,{label:`时间`},{default:C(()=>[o(g(s(R)(m.value.time)),1)]),_:1}),n(d,{label:`模型`},{default:C(()=>[o(g(m.value.model),1)]),_:1}),n(d,{label:`方法`},{default:C(()=>[o(g(m.value.method),1)]),_:1}),n(d,{label:`路径`},{default:C(()=>[o(g(m.value.path),1)]),_:1}),n(d,{label:`状态码`},{default:C(()=>[o(g(m.value.status),1)]),_:1}),n(d,{label:`流式`},{default:C(()=>[n(p,{type:m.value.stream?`warning`:`info`},{default:C(()=>[o(g(m.value.stream?`是`:`否`),1)]),_:1},8,[`type`])]),_:1}),n(d,{label:`IP`},{default:C(()=>[m.value.ip?(h(),i(`span`,ce,[n(D,{placement:`right`,width:`240`,trigger:`click`,onShow:r[0]||=e=>V(m.value)},{reference:C(()=>[x(`span`,null,g(m.value.ip),1)]),default:C(()=>[v((h(),i(`div`,le,[m.value._ipInfo?(h(),i(E,{key:0},[x(`div`,G,[r[13]||=x(`span`,{class:`ip-pop-label`},`归属地`,-1),x(`span`,null,g(se(m.value._ipInfo)),1)]),m.value._ipInfo.isp?(h(),i(`div`,ue,[r[14]||=x(`span`,{class:`ip-pop-label`},`运营商`,-1),x(`span`,null,g(m.value._ipInfo.isp),1)])):b(``,!0)],64)):m.value._ipInfoError?(h(),i(`div`,K,g(m.value._ipInfoError),1)):(h(),i(`span`,q,`查询中...`)),n(T,{style:{margin:`8px 0`}}),x(`a`,{class:`ip-pop-link`,href:`https://m.ip138.com/iplookup.php?ip=${encodeURIComponent(m.value.ip)}`,target:`_blank`},`在 ip138 查看`,8,J)])),[[I,w.value]])]),_:1})])):(h(),i(`span`,de,`-`))]),_:1}),n(d,{label:`Session`},{default:C(()=>[o(g(m.value.session_id||`-`),1)]),_:1}),n(d,{label:`ID`},{default:C(()=>[m.value._id==null?(h(),i(`span`,fe,`-`)):(h(),i(`span`,{key:0,class:`request-id`,title:`点击复制(日志 id 同时是响应头 x-request-id)`,onClick:r[1]||=e=>s(c)(String(m.value._id))},g(m.value._id),1))]),_:1}),n(d,{label:`输入 Token(含缓存读取)`},{default:C(()=>[o(g(s(B)(m.value.input_tokens??0)),1)]),_:1}),n(d,{label:`输出 Token`},{default:C(()=>[o(g(s(B)(m.value.output_tokens??0)),1)]),_:1}),n(d,{label:`缓存读取`},{default:C(()=>[o(g(s(B)(m.value.cache_read_tokens??0)),1)]),_:1}),n(d,{label:`请求耗时`},{default:C(()=>[o(g(s(oe)(m.value.duration)),1)]),_:1}),n(d,{label:`缓存命中率`},{default:C(()=>[o(g(s(ae)(m.value)),1)]),_:1}),m.value.error?(h(),e(d,{key:0,label:`错误`,span:2},{default:C(()=>[x(`span`,pe,g(m.value.error),1)]),_:1})):b(``,!0)]),_:1}),m.value.response?.truncated?(h(),e(l,{key:0,class:`mt-16`,type:`warning`,closable:!1,title:`内容超过单请求捕获上限,已截断`})):b(``,!0)]),_:1}),m.value.response?._capture?(h(),i(E,{key:0},[n(k,{lazy:``,label:`客户端请求`,name:`inbound`},{default:C(()=>[x(`div`,Y,[n(a,{size:`small`,class:`copy-btn`,onClick:r[2]||=e=>s(c)(A.value)},{default:C(()=>[...r[15]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,me,g(s(U)(A.value)),1)]),_:1}),n(k,{lazy:``,label:`转发上游的请求`,name:`upstreamReq`},{default:C(()=>[x(`div`,he,[n(a,{size:`small`,class:`copy-btn`,onClick:r[3]||=e=>s(c)(j.value)},{default:C(()=>[...r[16]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,ge,g(s(U)(j.value)),1)]),_:1}),m.value.response.upstream_response_text?(h(),e(k,{key:0,lazy:``,label:`上游响应(原始)`,name:`upstreamRes`},{default:C(()=>[x(`div`,X,[n(a,{size:`small`,class:`copy-btn`,onClick:r[4]||=e=>s(c)(m.value.response.upstream_response_text)},{default:C(()=>[...r[17]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,_e,g(s(U)(M.value)),1)]),_:1})):m.value.response.upstream_stream_frames?.length?(h(),e(k,{key:1,lazy:``,label:`上游响应(原始流,${m.value.response.upstream_stream_frames.length} 帧)`,name:`upstreamStream`},{default:C(()=>[x(`div`,ve,[n(a,{size:`small`,class:`copy-btn`,onClick:r[5]||=e=>s(c)(F.value)},{default:C(()=>[...r[18]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,Z,g(s(U)(F.value)),1)]),_:1},8,[`label`])):b(``,!0),m.value.response.client_response!==void 0&&m.value.response.client_response!==null?(h(),e(k,{key:2,lazy:``,label:`回写客户端(转换后)`,name:`clientRes`},{default:C(()=>[x(`div`,ye,[n(a,{size:`small`,class:`copy-btn`,onClick:r[6]||=e=>s(c)(ne.value)},{default:C(()=>[...r[19]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,Q,g(s(U)(ne.value)),1)]),_:1})):m.value.response.client_stream_frames?.length?(h(),e(k,{key:3,lazy:``,label:`回写客户端(${m.value.response.client_stream_frames.length} 帧)`,name:`clientStream`},{default:C(()=>[x(`div`,be,[n(a,{size:`small`,class:`copy-btn`,onClick:r[7]||=e=>s(c)(re.value)},{default:C(()=>[...r[20]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,xe,g(s(U)(re.value)),1)]),_:1},8,[`label`])):b(``,!0)],64)):(h(),i(E,{key:1},[n(k,{lazy:``,label:`请求体`,name:`request`},{default:C(()=>[x(`div`,$,[n(a,{size:`small`,class:`copy-btn`,onClick:r[8]||=e=>s(c)(L.value)},{default:C(()=>[...r[21]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,Se,g(s(U)(L.value)),1)]),_:1}),n(k,{lazy:``,label:`响应体`,name:`response`},{default:C(()=>[x(`div`,Ce,[n(a,{size:`small`,class:`copy-btn`,onClick:r[9]||=e=>s(c)(ie.value)},{default:C(()=>[...r[22]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,we,g(s(U)(ie.value)),1)]),_:1})],64))]),_:1},8,[`modelValue`])):b(``,!0)])),[[I,_.value]])]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-9c192d20`]]);u(),T(),d(),S();var Ee={class:`session-table`},De={class:`group-detail`},Oe=[`title`],ke={key:0,class:`detail-error`},Ae={class:`detail-footer`},je={class:`detail-count`},Me=[`title`,`onClick`],Ne=[`title`],Pe=[`title`],Fe=50,Ie=j(r({__name:`SessionGroupTable`,props:{groups:{},noSession:{},loading:{type:Boolean},filterParams:{}},emits:[`open-detail`],setup(r,{emit:u}){let d=r,f=u,{copyWithToast:m}=P(),S=a(()=>d.noSession?[...d.groups,d.noSession]:d.groups),w=e=>e.session_id||`__no_session__`,T=l(null),E=t(new Map),D={loading:!1,items:[],total:0,nextPage:1,error:null},O=e=>E.get(w(e))??D,k=async(e,t)=>{let n=(e=>(E.has(e)||E.set(e,{loading:!1,items:[],total:0,nextPage:1,error:null}),E.get(e)))(w(e));if(!n.loading){n.loading=!0,n.error=null;try{let r={...d.filterParams,sort:`time`,order:`desc`,page:String(t),pageSize:String(Fe)};e.session_id?r.sessionId=e.session_id:r.noSession=`1`;let i=await p.get(`/api/logs?`+new URLSearchParams(r).toString()),a=i.items||[];n.items=t===1?a:[...n.items,...a],n.total=i.total||0,n.nextPage=t+1}catch(e){n.error=e?.message||`加载失败`}finally{n.loading=!1}}},te=(e,t)=>{t.some(t=>w(t)===w(e))&&O(e).items.length===0&&k(e,1)},A=e=>{let t=O(e);t.loading||t.items.length>=t.total||k(e,t.nextPage)},j=e=>{T.value?.toggleRowExpansion(e)};return _(()=>S.value.map(w),e=>{let t=new Set(e);for(let e of[...E.keys()])t.has(e)||E.delete(e)}),(t,a)=>{let l=y(`el-table-column`),u=y(`el-tag`),d=y(`el-button`),p=y(`el-table`),_=y(`el-empty`),E=ee(`loading`);return h(),i(`div`,Ee,[S.value.length>0||r.loading?v((h(),e(p,{key:0,ref_key:`tableRef`,ref:T,data:S.value,height:`100%`,"row-key":w,stripe:``,onExpandChange:te,onRowClick:j},{default:C(()=>[n(l,{type:`expand`},{default:C(({row:t})=>[x(`div`,De,[v((h(),e(p,{data:O(t).items,size:`small`,stripe:``},{default:C(()=>[n(l,{label:`时间`,width:`165`},{default:C(({row:e})=>[o(g(s(R)(e.time)),1)]),_:1}),n(l,{prop:`model`,label:`模型`,"min-width":`150`}),n(l,{label:`客户端`,"min-width":`130`},{default:C(({row:e})=>[x(`span`,{title:e.user_agent||``},g(s(se)(e)),9,Oe)]),_:1}),n(l,{label:`状态`,width:`80`,align:`center`},{default:C(({row:e})=>[n(u,{size:`small`,type:e.status>=400?`danger`:e.status>=300?`warning`:`success`},{default:C(()=>[o(g(e.status),1)]),_:2},1032,[`type`])]),_:1}),n(l,{label:`输入`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.input_tokens??0)),1)]),_:1}),n(l,{label:`输出`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.output_tokens??0)),1)]),_:1}),n(l,{label:`缓存读取`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.cache_read_tokens??0)),1)]),_:1}),n(l,{label:`缓存命中率`,width:`105`,align:`center`},{default:C(({row:e})=>[o(g(s(ae)(e)),1)]),_:1}),n(l,{label:`请求耗时`,width:`90`,align:`center`},{default:C(({row:e})=>[o(g(s(oe)(e.duration)),1)]),_:1}),n(l,{label:`详情`,width:`70`,align:`center`},{default:C(({row:e})=>[n(d,{link:``,type:`primary`,onClick:t=>f(`open-detail`,e)},{default:C(()=>[...a[0]||=[o(`查看`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`])),[[E,O(t).loading]]),O(t).error?(h(),i(`div`,ke,[o(g(O(t).error)+` `,1),n(d,{link:``,type:`primary`,size:`small`,onClick:e=>k(t,1)},{default:C(()=>[...a[1]||=[o(`重试`,-1)]]),_:1},8,[`onClick`])])):b(``,!0),x(`div`,Ae,[x(`span`,je,`已显示 `+g(O(t).items.length)+` / `+g(O(t).total)+` 条`,1),O(t).items.length<O(t).total?(h(),e(d,{key:0,size:`small`,loading:O(t).loading,onClick:e=>A(t)},{default:C(()=>[...a[2]||=[o(` 加载更多 `,-1)]]),_:1},8,[`loading`,`onClick`])):b(``,!0)])])]),_:1}),n(l,{label:`Session`,width:`140`},{default:C(({row:t})=>[t.session_id?(h(),i(`span`,{key:0,class:`session-id`,title:`${t.session_id}(点击复制)`,onClick:c(e=>s(m)(t.session_id),[`stop`])},g(s(re)(t.session_id)),9,Me)):(h(),e(u,{key:1,size:`small`,type:`info`,title:`未携带会话标识的请求(NULL / 空串 session_id)`},{default:C(()=>[...a[3]||=[o(` 无 Session `,-1)]]),_:1}))]),_:1}),n(l,{label:`请求数`,width:`80`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.calls)),1)]),_:1}),n(l,{label:`模型`,"min-width":`150`},{default:C(({row:e})=>[x(`span`,{title:e.models||``},g(s(V)(e.models)),9,Ne)]),_:1}),n(l,{label:`客户端`,"min-width":`140`},{default:C(({row:e})=>[x(`span`,{title:e.clients||``},g(s(L)(e.clients)),9,Pe)]),_:1}),n(l,{label:`输入`,width:`105`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.input_tokens)),1)]),_:1}),n(l,{label:`输出`,width:`105`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.output_tokens)),1)]),_:1}),n(l,{label:`缓存读取`,width:`120`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.cache_read_tokens)),1)]),_:1}),n(l,{label:`首次请求`,width:`165`},{default:C(({row:e})=>[o(g(s(R)(e.first_time)),1)]),_:1}),n(l,{label:`最后请求`,width:`165`},{default:C(({row:e})=>[o(g(s(R)(e.last_time)),1)]),_:1})]),_:1},8,[`data`])),[[E,r.loading]]):(h(),e(_,{key:1,description:`当前筛选下没有日志`}))])}}}),[[`__scopeId`,`data-v-2ff0b8c0`]]);u(),T(),S(),d();var Le={class:`logs-page`},Re={class:`filter-bar`},ze={class:`table-wrap`},Be=[`onClick`],Ve={key:1},He=[`title`,`onClick`],Ue={key:1},We=[`title`,`onClick`],Ge={key:1},Ke={class:`pagination-bar`},qe=j(r({__name:`LogsView`,setup(t){let r=M(),{toast:c}=F(),{copyWithToast:u}=P(),{loadError:d,run:_}=N(),{rangeKey:S,dateRange:T,setRange:O,onRangeChange:j}=ne(()=>$()),L=l(`2xx`),z=l(``),V=l(``),H=l(``),U=l(`session`),W=l([]),ce=l([]),le=l(null),G=l(0),ue=l(0),K=l(1),q=l(20),J=l(!1),de=l(null),fe=e=>{de.value?.open(e)},pe=a(()=>{let e=new Set;for(let t of r.suppliers)for(let n of t.models)e.add(n.modelName);for(let t of W.value)t.model&&e.add(t.model);return[...e].sort()}),Y=l([]),me=a(()=>{let e=new Set(Y.value);for(let t of W.value)t.client&&e.add(t.client);return[...e].sort()}),he=async()=>{try{let e=await p.get(`/api/logs/clients`);Y.value=e.clients||[]}catch{Y.value=[]}},ge=e=>{S.value=``,T.value=e||null,$()},X=()=>{let e={};T.value&&T.value.length===2&&(e.startDate=T.value[0],e.endDate=T.value[1]),L.value&&(e.status=L.value),z.value&&(e.model=z.value),V.value&&(e.client=V.value);let t=H.value.trim();return t&&(e.sessionId=t),e},_e=a(()=>X()),ve=I(),Z=()=>_(async()=>{let e=ve();J.value=!0;try{let t={...X(),page:String(K.value),pageSize:String(q.value)};if(U.value===`session`){let n=new URLSearchParams(t).toString(),r=await p.get(`/api/logs/sessions?`+n);if(!e())return;ce.value=r.groups||[],le.value=r.noSession??null,G.value=r.total||0,ue.value=r.rowsTotal||0}else{let n=new URLSearchParams({...t,sort:`time`,order:`desc`}).toString(),r=await p.get(`/api/logs?`+n);if(!e())return;W.value=r.items||[],G.value=r.total||0}}catch(t){if(!e())return;throw t}finally{e()&&(J.value=!1)}}),ye=e=>{U.value!==e&&(U.value=e,K.value=1,q.value=U.value===`session`?20:50,Z())},Q=l(!1),be=a(()=>U.value===`session`?ue.value:G.value),xe=async()=>{if(Q.value||be.value===0)return;let e=U.value===`session`?`(按筛选行数计,含「无 Session」组)`:``;try{await A.confirm(`将永久清理当前筛选条件下的 ${be.value} 条日志${e},清理后不可恢复,请谨慎操作!`,`清理确认`,{confirmButtonText:`确认清理`,cancelButtonText:`取消`,type:`warning`})}catch{return}Q.value=!0;try{let e=new URLSearchParams(X()).toString(),t=await p.post(`/api/logs/clear?`+e,{});c(`已清理 ${t.deleted??0} 条日志`,`success`),K.value>1&&(K.value=1),Z()}catch(e){c(e.message||`清理失败`,`error`)}finally{Q.value=!1}},$=()=>{K.value=1,he(),Z()},Se=()=>{S.value=`today`,T.value=null,L.value=`2xx`,z.value=``,V.value=``,H.value=``,K.value=1,q.value=U.value===`session`?20:50,O(`today`)};return f(()=>{r.loadProviders().catch(()=>{}),he(),O(`today`)}),(t,r)=>{let a=y(`el-button`),c=y(`el-alert`),l=y(`el-option`),f=y(`el-select`),p=y(`el-date-picker`),_=y(`el-input`),O=y(`el-tooltip`),A=y(`el-button-group`),M=y(`el-card`),N=y(`el-table-column`),P=y(`el-tag`),F=y(`el-table`),I=y(`el-pagination`),ne=ee(`loading`);return h(),i(`div`,Le,[s(d)?(h(),e(c,{key:0,title:s(d),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:C(()=>[n(a,{size:`small`,onClick:Z},{default:C(()=>[...r[10]||=[o(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):b(``,!0),n(M,{shadow:`never`},{default:C(()=>[x(`div`,Re,[n(f,{modelValue:s(S),"onUpdate:modelValue":r[0]||=e=>m(S)?S.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`114px`},onChange:s(j)},{default:C(()=>[n(l,{label:`今天`,value:`today`}),n(l,{label:`昨天`,value:`yesterday`}),n(l,{label:`前天`,value:`beforeYesterday`}),n(l,{label:`近三天`,value:`last3days`}),n(l,{label:`本周`,value:`week`}),n(l,{label:`本月`,value:`month`})]),_:1},8,[`modelValue`,`onChange`]),n(p,{modelValue:s(T),"onUpdate:modelValue":r[1]||=e=>m(T)?T.value=e:null,type:`daterange`,"value-format":`YYYY-MM-DD`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,style:{width:`240px`},onChange:ge},null,8,[`modelValue`]),n(f,{modelValue:L.value,"onUpdate:modelValue":r[2]||=e=>L.value=e,placeholder:`全部状态`,clearable:``,style:{width:`106px`},onChange:$},{default:C(()=>[n(l,{label:`成功 (2xx)`,value:`2xx`}),n(l,{label:`3xx`,value:`3xx`}),n(l,{label:`4xx`,value:`4xx`}),n(l,{label:`5xx`,value:`5xx`}),n(l,{label:`错误 (4xx+)`,value:`err`})]),_:1},8,[`modelValue`]),n(f,{modelValue:z.value,"onUpdate:modelValue":r[3]||=e=>z.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`176px`},onChange:$},{default:C(()=>[(h(!0),i(E,null,w(pe.value,t=>(h(),e(l,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`]),n(f,{modelValue:V.value,"onUpdate:modelValue":r[4]||=e=>V.value=e,placeholder:`全部客户端`,clearable:``,filterable:``,style:{width:`130px`},onChange:$},{default:C(()=>[(h(!0),i(E,null,w(me.value,t=>(h(),e(l,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`]),n(_,{modelValue:H.value,"onUpdate:modelValue":r[5]||=e=>H.value=e,class:`session-input`,placeholder:`Session ID(前缀匹配)`,clearable:``,onKeyup:D($,[`enter`])},null,8,[`modelValue`]),n(A,{class:`view-switch push-right`},{default:C(()=>[n(O,{content:`按会话分组`,placement:`top`,"show-after":300},{default:C(()=>[n(a,{type:U.value===`session`?`primary`:`default`,icon:s(te),"aria-label":`按会话分组`,onClick:r[6]||=e=>ye(`session`)},null,8,[`type`,`icon`])]),_:1}),n(O,{content:`列表`,placement:`top`,"show-after":300},{default:C(()=>[n(a,{type:U.value===`list`?`primary`:`default`,icon:s(k),"aria-label":`列表视图`,onClick:r[7]||=e=>ye(`list`)},null,8,[`type`,`icon`])]),_:1})]),_:1}),n(a,{type:`primary`,onClick:$},{default:C(()=>[...r[11]||=[o(`搜索`,-1)]]),_:1}),n(a,{onClick:Se},{default:C(()=>[...r[12]||=[o(`重置`,-1)]]),_:1})])]),_:1}),n(M,{shadow:`never`,class:`mt-16 table-card`},{default:C(()=>[x(`div`,ze,[U.value===`list`?v((h(),e(F,{key:0,data:W.value,stripe:``,height:`100%`},{default:C(()=>[n(N,{prop:`id`,label:`ID`,"min-width":`80`},{default:C(({row:e})=>[e.id==null?(h(),i(`span`,Ve,`-`)):(h(),i(`span`,{key:0,class:`request-id`,title:`点击复制(日志 id 同时是响应头 x-request-id,可用于关联控制台日志与检索)`,onClick:t=>s(u)(String(e.id))},g(e.id),9,Be))]),_:1}),n(N,{prop:`time`,label:`时间`,width:`180`},{default:C(({row:e})=>[o(g(s(R)(e.time)),1)]),_:1}),n(N,{prop:`model`,label:`模型`,"min-width":`180`}),n(N,{label:`客户端`,"min-width":`150`},{default:C(({row:e})=>[e.client||e.user_agent?(h(),i(`span`,{key:0,class:`request-id`,title:s(ie)(e),onClick:t=>s(u)(e.user_agent||e.client)},g(s(se)(e)),9,He)):(h(),i(`span`,Ue,`-`))]),_:1}),n(N,{label:`Session`,width:`140`},{default:C(({row:e})=>[e.session_id?(h(),i(`span`,{key:0,class:`request-id`,title:`${e.session_id}(点击复制)`,onClick:t=>s(u)(e.session_id)},g(s(re)(e.session_id)),9,We)):(h(),i(`span`,Ge,`-`))]),_:1}),n(N,{label:`输入`,"min-width":`110`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.input_tokens??0)),1)]),_:1}),n(N,{label:`输出`,"min-width":`110`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.output_tokens??0)),1)]),_:1}),n(N,{label:`缓存读取`,"min-width":`90`,align:`center`},{default:C(({row:e})=>[o(g(s(B)(e.cache_read_tokens??0)),1)]),_:1}),n(N,{label:`缓存命中率`,"min-width":`105`,align:`center`},{default:C(({row:e})=>[x(`span`,null,g(s(ae)(e)),1)]),_:1}),n(N,{label:`请求耗时`,"min-width":`90`,align:`center`},{default:C(({row:e})=>[o(g(s(oe)(e.duration)),1)]),_:1}),n(N,{prop:`status`,label:`状态`,width:`80`,align:`center`},{default:C(({row:e})=>[n(P,{size:`small`,type:e.status>=400?`danger`:e.status>=300?`warning`:`success`},{default:C(()=>[o(g(e.status),1)]),_:2},1032,[`type`])]),_:1}),n(N,{label:`详情`,width:`70`,align:`center`},{default:C(({row:e})=>[n(a,{link:``,type:`primary`,onClick:t=>fe(e)},{default:C(()=>[...r[13]||=[o(`查看`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`])),[[ne,J.value]]):b(``,!0),U.value===`session`?(h(),e(Ie,{key:1,groups:ce.value,"no-session":le.value,loading:J.value,"filter-params":_e.value,onOpenDetail:fe},null,8,[`groups`,`no-session`,`loading`,`filter-params`])):b(``,!0)]),x(`div`,Ke,[n(a,{type:`danger`,plain:``,size:`small`,loading:Q.value,disabled:be.value===0,onClick:xe},{default:C(()=>[...r[14]||=[o(`清理已筛选日志`,-1)]]),_:1},8,[`loading`,`disabled`]),n(I,{class:`push-right`,"current-page":K.value,"onUpdate:currentPage":r[8]||=e=>K.value=e,"page-size":q.value,"onUpdate:pageSize":r[9]||=e=>q.value=e,total:G.value,"page-sizes":[20,50,100,200],layout:`total, sizes, prev, pager, next`,onCurrentChange:Z,onSizeChange:Z},null,8,[`current-page`,`page-size`,`total`])])]),_:1}),n(Te,{ref_key:`logDetailRef`,ref:de},null,512)])}}}),[[`__scopeId`,`data-v-9b1602a9`]]);export{qe as default};
@@ -0,0 +1 @@
1
+ .ip-link[data-v-9c192d20]{color:#409eff;cursor:pointer}.ip-link[data-v-9c192d20]:hover{text-decoration:underline}.ip-pop[data-v-9c192d20]{min-height:20px;font-size:13px}.ip-pop-row[data-v-9c192d20]{gap:8px;margin-bottom:4px;display:flex}.ip-pop-label[data-v-9c192d20]{color:#909399;flex-shrink:0}.ip-pop-error[data-v-9c192d20]{color:#f56c6c}.ip-pop-link[data-v-9c192d20]{color:#409eff;font-size:13px}.error-text[data-v-9c192d20]{color:#f56c6c}.pane-bar[data-v-9c192d20]{flex-shrink:0;justify-content:flex-end;margin-bottom:8px;display:flex}.json-block[data-v-9c192d20]{white-space:pre-wrap;word-break:break-all;background:#f5f7fa;border:1px solid #e4e7ed;border-radius:4px;flex:1;min-height:0;padding:12px;font-size:13px;line-height:1.5;overflow:auto}.detail-content[data-v-9c192d20]{flex-direction:column;height:78vh;display:flex;overflow:hidden}.detail-content[data-v-9c192d20] .el-tabs{flex-direction:column;flex:1;min-height:0;display:flex}.detail-content[data-v-9c192d20] .el-tabs__content{flex:1;min-height:0}.detail-content[data-v-9c192d20] .el-tab-pane{flex-direction:column;height:100%;display:flex;overflow:auto}.copy-btn[data-v-9c192d20]{margin-left:8px;padding:2px 10px;font-size:12px}.session-table[data-v-2ff0b8c0]{height:100%}.session-id[data-v-2ff0b8c0]{cursor:pointer;white-space:nowrap;text-overflow:ellipsis;font-family:ui-monospace,Consolas,monospace;display:block;overflow:hidden}.session-id[data-v-2ff0b8c0]:hover{color:var(--el-color-primary)}.group-detail[data-v-2ff0b8c0]{padding:4px 16px 8px 48px}.detail-error[data-v-2ff0b8c0]{color:var(--el-color-danger);margin-top:8px;font-size:12px}.detail-footer[data-v-2ff0b8c0]{justify-content:flex-end;align-items:center;gap:12px;margin-top:8px;display:flex}.detail-count[data-v-2ff0b8c0]{color:var(--el-text-color-secondary);font-size:12px}.logs-page[data-v-9b1602a9]{flex-direction:column;height:calc(100vh - 124px);display:flex;overflow:hidden}.request-id[data-v-9b1602a9]{cursor:pointer;white-space:nowrap;text-overflow:ellipsis;font-family:ui-monospace,Consolas,monospace;display:block;overflow:hidden}.request-id[data-v-9b1602a9]:hover{color:var(--el-color-primary)}.filter-bar[data-v-9b1602a9]{flex-wrap:nowrap;align-items:center;gap:12px;display:flex}.filter-bar[data-v-9b1602a9]>*{flex:none}.filter-bar .session-input[data-v-9b1602a9]{flex:160px;min-width:100px}.filter-bar .push-right[data-v-9b1602a9]{margin-left:auto}.filter-bar .view-switch[data-v-9b1602a9]{flex:none}.filter-bar[data-v-9b1602a9] .el-button+.el-button{margin-left:0}@media (width<=900px){.filter-bar[data-v-9b1602a9]{flex-wrap:wrap}.filter-bar .session-input[data-v-9b1602a9]{flex-basis:100%;min-width:0}.filter-bar .push-right[data-v-9b1602a9]{margin-left:auto}}.mt-16[data-v-9b1602a9]{margin-top:16px}.table-card[data-v-9b1602a9]{flex:1;min-height:0;overflow:hidden}.table-card[data-v-9b1602a9] .el-card__body{flex-direction:column;height:100%;display:flex}.table-wrap[data-v-9b1602a9]{flex:1;min-height:0}.pagination-bar[data-v-9b1602a9]{flex-shrink:0;justify-content:space-between;align-items:center;margin-top:16px;display:flex}
@@ -1,6 +1,6 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,at as f,et as p,fn as m,ht as h,it as g,j as _,k as v,mt as y,vt as b,w as x}from"./router-B8DYHNvS.js";import{H as S}from"./message-B4CpctQv.js";import{n as C,t as w}from"./index-BCZqYZB7.js";import{t as T}from"./useManagerApi-CCQ0LO2A.js";import{n as E,t as D}from"./useCopyToast-CO6fr7kf.js";import{t as O}from"./useToast-C7Ey6ket.js";import{c as k}from"./format-lzQY461O.js";l(),u(),b();var A={class:`form-hint`},j={key:1,class:`form-hint form-hint--block`},M=w(n({__name:`ManagedServiceModal`,props:{editingName:{},service:{}},emits:[`close`,`saved`],setup(n,{emit:o}){let s=n,l=o,{toast:u}=O(),d=c(),f=c(!1),h=c(!0),b=i(()=>s.service?.pid!=null),S=c({name:s.service?.name??``,exec:s.service?.exec??``,cwd:s.service?.cwd??``,autostart:s.service?.autostart??!0}),C=c((s.service?.args??[]).join(`
2
- `)),w={name:[{required:!0,message:`请填写服务名`,trigger:`blur`},{pattern:/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,message:`只能用字母、数字、点、下划线、短横线(字母或数字开头,不超过 64 个字符)`,trigger:`blur`}],cwd:[{required:!0,message:`请填写工作目录`,trigger:`blur`}]};function E(e){return e.split(`
3
- `).map(e=>e.trim()).filter(e=>e!==``)}let D=async()=>{if(!await d.value?.validate().catch(()=>!1)){u(`请补全标红的必填项`,`error`);return}let e={name:S.value.name.trim(),exec:S.value.exec.trim(),args:E(C.value),cwd:S.value.cwd.trim(),autostart:S.value.autostart};b.value||(e.start=h.value),f.value=!0;try{s.editingName===null?(await T.createManagedService(e),u(e.start?`服务已添加并启动`:`服务已添加`,`success`)):(await T.updateManagedService(s.editingName,e),u(b.value?`已保存,服务正按新配置重启`:`已保存`,`success`)),l(`saved`)}catch(e){u(e.message||`保存失败`,`error`)}finally{f.value=!1}};return(i,o)=>{let s=g(`el-input`),c=g(`el-form-item`),u=g(`el-switch`),T=g(`el-form`),E=g(`el-button`),O=g(`el-dialog`);return p(),e(O,{"model-value":!0,title:n.editingName?`编辑托管服务`:`添加托管服务`,width:`720px`,top:`6vh`,"align-center":``,"close-on-click-modal":!1,onClose:o[7]||=e=>l(`close`)},{footer:y(()=>[t(E,{disabled:f.value,onClick:o[6]||=e=>l(`close`)},{default:y(()=>[...o[13]||=[a(`取消`,-1)]]),_:1},8,[`disabled`]),t(E,{type:`primary`,loading:f.value,onClick:D},{default:y(()=>[a(m(f.value?`保存中...`:n.editingName?`保存`:`添加服务`),1)]),_:1},8,[`loading`])]),default:y(()=>[t(T,{ref_key:`formRef`,ref:d,model:S.value,rules:w,"label-position":`top`},{default:y(()=>[t(c,{label:`服务名`,prop:`name`},{default:y(()=>[t(s,{modelValue:S.value.name,"onUpdate:modelValue":o[0]||=e=>S.value.name=e,disabled:n.editingName!==null,placeholder:`如 codebuddy-cpa(字母数字开头,可用 . _ -)`},null,8,[`modelValue`,`disabled`]),v(`div`,A,[o[8]||=a(` 名称用于日志文件名(logs/out-<名称>.log)与进程标识;`,-1),n.editingName===null?_(``,!0):(p(),r(x,{key:0},[a(`编辑时不可修改(改名请删除后重新添加)。`)],64))])]),_:1}),t(c,{label:`工作目录`,prop:`cwd`},{default:y(()=>[t(s,{modelValue:S.value.cwd,"onUpdate:modelValue":o[1]||=e=>S.value.cwd=e,placeholder:`如 E:\\gitee\\codebuddy-cpa(服务的运行目录)`},null,8,[`modelValue`]),o[9]||=v(`div`,{class:`form-hint`},`服务在此目录下启动;保存时会校验目录是否存在。`,-1)]),_:1}),t(c,{label:`可执行文件`},{default:y(()=>[t(s,{modelValue:S.value.exec,"onUpdate:modelValue":o[2]||=e=>S.value.exec=e,placeholder:`留空 = 使用 ezllm 主进程的 Node;也可填 npm.cmd 或绝对路径`},null,8,[`modelValue`]),o[10]||=v(`div`,{class:`form-hint`},` 留空时用主进程的 Node 直接运行下方参数(第一个参数通常是脚本相对工作目录的路径)。 Windows 上 .cmd / .bat / 无扩展名的命令(如 npm)会自动经 cmd.exe 执行;其他平台直接执行。 `,-1)]),_:1}),t(c,{label:`参数`},{default:y(()=>[t(s,{modelValue:C.value,"onUpdate:modelValue":o[3]||=e=>C.value=e,type:`textarea`,rows:3,placeholder:`每行一个参数,如:
1
+ import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,at as f,et as p,fn as m,ht as h,it as g,j as _,k as v,mt as y,vt as b,w as x}from"./router-DvvoEPD-.js";import{W as S}from"./message-C5ZFfxcO.js";import{n as C,t as w}from"./index-DPq2QylL.js";import{t as T}from"./useManagerApi-CqT4wuBt.js";import{n as E,t as D}from"./useCopyToast-BNDnj8jd.js";import{t as O}from"./useToast-DeKoozwQ.js";import{d as k}from"./format-BwEbbkjl.js";l(),u(),b();var A={class:`form-hint`},j={key:1,class:`form-hint form-hint--block`},M=w(n({__name:`ManagedServiceModal`,props:{editingName:{},service:{}},emits:[`close`,`saved`],setup(n,{emit:o}){let s=n,l=o,{toast:u}=O(),d=c(),f=c(!1),h=c(!0),b=i(()=>s.service?.pid!=null),S=c({name:s.service?.name??``,exec:s.service?.exec??``,cwd:s.service?.cwd??``,autostart:s.service?.autostart??!0}),C=c((s.service?.args??[]).join(`
2
+ `)),w={name:[{required:!0,message:`请填写服务名`,trigger:`blur`},{pattern:/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,message:`只能用字母、数字、点、下划线、短横线(字母或数字开头,不超过 64 个字符)`,trigger:`blur`}],cwd:[{required:!0,message:`请填写工作目录`,trigger:`blur`}]},E=async()=>{let e=e=>e.split(`
3
+ `).map(e=>e.trim()).filter(e=>e!==``);if(!await d.value?.validate().catch(()=>!1)){u(`请补全标红的必填项`,`error`);return}let t={name:S.value.name.trim(),exec:S.value.exec.trim(),args:e(C.value),cwd:S.value.cwd.trim(),autostart:S.value.autostart};b.value||(t.start=h.value),f.value=!0;try{s.editingName===null?(await T.createManagedService(t),u(t.start?`服务已添加并启动`:`服务已添加`,`success`)):(await T.updateManagedService(s.editingName,t),u(b.value?`已保存,服务正按新配置重启`:`已保存`,`success`)),l(`saved`)}catch(e){u(e.message||`保存失败`,`error`)}finally{f.value=!1}};return(i,o)=>{let s=g(`el-input`),c=g(`el-form-item`),u=g(`el-switch`),T=g(`el-form`),D=g(`el-button`),O=g(`el-dialog`);return p(),e(O,{"model-value":!0,title:n.editingName?`编辑托管服务`:`添加托管服务`,width:`720px`,top:`6vh`,"align-center":``,"close-on-click-modal":!1,onClose:o[7]||=e=>l(`close`)},{footer:y(()=>[t(D,{disabled:f.value,onClick:o[6]||=e=>l(`close`)},{default:y(()=>[...o[13]||=[a(`取消`,-1)]]),_:1},8,[`disabled`]),t(D,{type:`primary`,loading:f.value,onClick:E},{default:y(()=>[a(m(f.value?`保存中...`:n.editingName?`保存`:`添加服务`),1)]),_:1},8,[`loading`])]),default:y(()=>[t(T,{ref_key:`formRef`,ref:d,model:S.value,rules:w,"label-position":`top`},{default:y(()=>[t(c,{label:`服务名`,prop:`name`},{default:y(()=>[t(s,{modelValue:S.value.name,"onUpdate:modelValue":o[0]||=e=>S.value.name=e,disabled:n.editingName!==null,placeholder:`如 codebuddy-cpa(字母数字开头,可用 . _ -)`},null,8,[`modelValue`,`disabled`]),v(`div`,A,[o[8]||=a(` 名称用于日志文件名(logs/out-<名称>.log)与进程标识;`,-1),n.editingName===null?_(``,!0):(p(),r(x,{key:0},[a(`编辑时不可修改(改名请删除后重新添加)。`)],64))])]),_:1}),t(c,{label:`工作目录`,prop:`cwd`},{default:y(()=>[t(s,{modelValue:S.value.cwd,"onUpdate:modelValue":o[1]||=e=>S.value.cwd=e,placeholder:`如 E:\\gitee\\codebuddy-cpa(服务的运行目录)`},null,8,[`modelValue`]),o[9]||=v(`div`,{class:`form-hint`},`服务在此目录下启动;保存时会校验目录是否存在。`,-1)]),_:1}),t(c,{label:`可执行文件`},{default:y(()=>[t(s,{modelValue:S.value.exec,"onUpdate:modelValue":o[2]||=e=>S.value.exec=e,placeholder:`留空 = 使用 ezllm 主进程的 Node;也可填 npm.cmd 或绝对路径`},null,8,[`modelValue`]),o[10]||=v(`div`,{class:`form-hint`},` 留空时用主进程的 Node 直接运行下方参数(第一个参数通常是脚本相对工作目录的路径)。 Windows 上 .cmd / .bat / 无扩展名的命令(如 npm)会自动经 cmd.exe 执行;其他平台直接执行。 `,-1)]),_:1}),t(c,{label:`参数`},{default:y(()=>[t(s,{modelValue:C.value,"onUpdate:modelValue":o[3]||=e=>C.value=e,type:`textarea`,rows:3,placeholder:`每行一个参数,如:
4
4
  src/proxy.js
5
5
  --log
6
- proxy.log`},null,8,[`modelValue`]),o[11]||=v(`div`,{class:`form-hint`},`逐行填写,每行作为一个完整参数传递(含空格也不拆分),不需要加引号。`,-1)]),_:1}),t(c,{label:`开机自启`},{default:y(()=>[t(u,{modelValue:S.value.autostart,"onUpdate:modelValue":o[4]||=e=>S.value.autostart=e},null,8,[`modelValue`]),o[12]||=v(`span`,{class:`form-hint form-hint--inline`},` 开启后随 ezllm 主进程启动自动拉起(系统登录后、以及 ezllm 更新重启后) `,-1)]),_:1}),b.value?(p(),r(`div`,j,` 该服务当前正在运行:保存后将按新配置自动重启,使改动立即生效。 `)):(p(),e(c,{key:0,label:`保存后立即启动`},{default:y(()=>[t(u,{modelValue:h.value,"onUpdate:modelValue":o[5]||=e=>h.value=e},null,8,[`modelValue`])]),_:1}))]),_:1},8,[`model`])]),_:1},8,[`title`])}}}),[[`__scopeId`,`data-v-9aaa9859`]]);l(),b(),u();var N={class:`page-head`},P={class:`page-head-actions`},F={class:`flex-between`},I={class:`muted-sm`},L={class:`name-cell`},R={class:`fw-600`},z={class:`cmd-cell`},B={class:`mono`},V=[`title`],H={class:`mono`},U={class:`muted-sm`},W={key:1,class:`muted-sm`},G=w(n({__name:`ManagedServicesView`,setup(n){let{toast:i}=O(),{copyWithToast:l}=D(),{loadError:u,run:b}=E(`托管服务加载失败,请重试`),w=c([]),A=c(null),j=c(!0),G=c(!0),K=c(null),q=c(!1),J=c(null),Y=e=>[e.exec===``?`主进程 Node`:e.exec,...e.args].join(` `),X=()=>b(async()=>{try{let e=await T.managedServices();w.value=e.services??[],A.value=e.configError??null,G.value=!0}catch(e){if(typeof e?.message==`string`&&e.message.includes(`未由 ezllm 主进程托管`)){G.value=!1,w.value=[],A.value=null,u.value=null;return}throw e}finally{j.value=!1}}),Z=()=>{J.value=null,q.value=!0},ee=e=>{J.value=e.name,q.value=!0},te=async()=>{q.value=!1,await X()},Q=async(e,t,n)=>{if(!K.value){K.value=e;try{await t(),i(n,`success`),await X()}catch(e){i(e.message||`操作失败`,`error`)}finally{K.value=null}}},$=async(e,t)=>{let n={start:`启动`,stop:`停止`,restart:`重启`}[t];if(t===`stop`||t===`restart`)try{await C.confirm(`确定${n}服务 ${e.name}?`,`${n}确认`,{confirmButtonText:n,cancelButtonText:`取消`,type:`warning`})}catch{return}let r={start:()=>T.startManagedService(e.name),stop:()=>T.stopManagedService(e.name),restart:()=>T.restartManagedService(e.name)}[t];await Q(`${t}:${e.name}`,async()=>void await r(),`${n}指令已执行:${e.name}`)},ne=async(e,t)=>{let n=t?`开启「${e.name}」开机自启?此后随 ezllm 主进程启动自动拉起(不改变当前运行状态)。`:`关闭「${e.name}」开机自启?此后不再随 ezllm 启动自动拉起(不改变当前运行状态)。`;try{await C.confirm(n,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}await Q(`autostart:${e.name}`,async()=>{await T.updateManagedService(e.name,{name:e.name,exec:e.exec,args:e.args,cwd:e.cwd,autostart:t})},t?`已开启开机自启`:`已关闭开机自启`)},re=async e=>{try{await C.confirm(`确定删除托管服务 ${e.name}?${e.pid?`该服务正在运行,会先被停止;`:``}此后不再随 ezllm 启动,其配置将被移除。`,`确认删除`,{confirmButtonText:`确定`,cancelButtonText:`取消`,type:`warning`})}catch{return}await Q(`remove:${e.name}`,async()=>{await T.removeManagedService(e.name)},`已删除:${e.name}`)},ie=async e=>{await l(e.logFiles.out,`已复制日志路径:${e.logFiles.out}`)},ae=window.setInterval(()=>{q.value||K.value||X()},5e3);return s(()=>window.clearInterval(ae)),d(X),(n,i)=>{let s=g(`el-button`),c=g(`el-icon`),l=g(`el-alert`),d=g(`el-tag`),b=g(`el-table-column`),C=g(`el-switch`),T=g(`el-table`),E=g(`el-card`),D=f(`loading`);return p(),r(`div`,null,[v(`div`,N,[i[3]||=v(`div`,null,[v(`div`,{class:`page-head-title`},`托管服务`),v(`div`,{class:`page-head-sub`},` 由 ezllm 主进程守护的外部服务:可随开机自启、崩溃自动重启,与网关服务同等纳管 `)],-1),v(`div`,P,[t(s,{loading:j.value,onClick:X},{default:y(()=>[...i[1]||=[a(`刷新`,-1)]]),_:1},8,[`loading`]),t(s,{type:`primary`,disabled:!G.value,onClick:Z},{default:y(()=>[t(c,null,{default:y(()=>[t(o(S))]),_:1}),i[2]||=a(` 添加服务 `,-1)]),_:1},8,[`disabled`])])]),o(u)?(p(),e(l,{key:0,title:o(u),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[t(s,{size:`small`,onClick:X},{default:y(()=>[...i[4]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),A.value?(p(),e(l,{key:1,title:`托管服务清单不可用:${A.value}`,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[...i[5]||=[v(`div`,{class:`muted-sm`},` 修复该文件后重启 ezllm(或重新添加服务)即可恢复;期间已有服务不会自动加载。 `,-1)]]),_:1},8,[`title`])):_(``,!0),t(E,{shadow:`never`},{header:y(()=>[v(`div`,F,[i[6]||=v(`span`,{class:`fw-600`},`服务列表`,-1),v(`span`,I,m(w.value.length)+` 个服务`,1)])]),default:y(()=>[h((p(),e(T,{data:w.value,"empty-text":`暂无托管服务,点击右上角「添加服务」创建`},{default:y(()=>[t(b,{label:`服务名`,"min-width":`150`},{default:y(({row:t})=>[v(`div`,L,[v(`span`,R,m(t.name),1),t.pid?(p(),e(d,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:y(()=>[...i[7]||=[a(`运行中`,-1)]]),_:1})):(p(),e(d,{key:1,type:`info`,size:`small`,"disable-transitions":``},{default:y(()=>[...i[8]||=[a(`已停止`,-1)]]),_:1}))])]),_:1}),t(b,{label:`启动命令`,"min-width":`240`},{default:y(({row:e})=>[v(`div`,z,[v(`span`,B,m(Y(e)),1),v(`span`,{class:`muted-sm cwd-text`,title:e.cwd},m(e.cwd),9,V)])]),_:1}),t(b,{label:`进程`,width:`110`},{default:y(({row:e})=>[e.pid?(p(),r(x,{key:0},[v(`div`,H,`pid `+m(e.pid),1),v(`div`,U,m(e.startedAt?o(k)(e.startedAt):``),1)],64)):(p(),r(`span`,W,`-`))]),_:1}),t(b,{label:`开机自启`,width:`100`,align:`center`},{default:y(({row:e})=>[t(C,{"model-value":e.autostart,loading:K.value===`autostart:${e.name}`,onChange:t=>ne(e,!!t)},null,8,[`model-value`,`loading`,`onChange`])]),_:1}),t(b,{label:`日志`,width:`100`,align:`center`},{default:y(({row:e})=>[t(s,{link:``,type:`primary`,onClick:t=>ie(e)},{default:y(()=>[...i[9]||=[a(`复制路径`,-1)]]),_:1},8,[`onClick`])]),_:1}),t(b,{label:`操作`,width:`230`,align:`center`},{default:y(({row:n})=>[n.pid?(p(),r(x,{key:1},[t(s,{link:``,type:`warning`,loading:K.value===`restart:${n.name}`,onClick:e=>$(n,`restart`)},{default:y(()=>[...i[11]||=[a(`重启`,-1)]]),_:1},8,[`loading`,`onClick`]),t(s,{link:``,type:`danger`,loading:K.value===`stop:${n.name}`,onClick:e=>$(n,`stop`)},{default:y(()=>[...i[12]||=[a(`停止`,-1)]]),_:1},8,[`loading`,`onClick`])],64)):(p(),e(s,{key:0,link:``,type:`primary`,loading:K.value===`start:${n.name}`,onClick:e=>$(n,`start`)},{default:y(()=>[...i[10]||=[a(`启动`,-1)]]),_:1},8,[`loading`,`onClick`])),t(s,{link:``,onClick:e=>ee(n)},{default:y(()=>[...i[13]||=[a(`编辑`,-1)]]),_:1},8,[`onClick`]),t(s,{link:``,type:`danger`,loading:K.value===`remove:${n.name}`,onClick:e=>re(n)},{default:y(()=>[...i[14]||=[a(`删除`,-1)]]),_:1},8,[`loading`,`onClick`])]),_:1})]),_:1},8,[`data`])),[[D,j.value]])]),_:1}),q.value?(p(),e(M,{key:2,"editing-name":J.value,service:J.value==null?void 0:w.value.find(e=>e.name===J.value),onClose:i[0]||=e=>q.value=!1,onSaved:te},null,8,[`editing-name`,`service`])):_(``,!0)])}}}),[[`__scopeId`,`data-v-f4d654e1`]]);export{G as default};
6
+ proxy.log`},null,8,[`modelValue`]),o[11]||=v(`div`,{class:`form-hint`},`逐行填写,每行作为一个完整参数传递(含空格也不拆分),不需要加引号。`,-1)]),_:1}),t(c,{label:`开机自启`},{default:y(()=>[t(u,{modelValue:S.value.autostart,"onUpdate:modelValue":o[4]||=e=>S.value.autostart=e},null,8,[`modelValue`]),o[12]||=v(`span`,{class:`form-hint form-hint--inline`},` 开启后随 ezllm 主进程启动自动拉起(系统登录后、以及 ezllm 更新重启后) `,-1)]),_:1}),b.value?(p(),r(`div`,j,` 该服务当前正在运行:保存后将按新配置自动重启,使改动立即生效。 `)):(p(),e(c,{key:0,label:`保存后立即启动`},{default:y(()=>[t(u,{modelValue:h.value,"onUpdate:modelValue":o[5]||=e=>h.value=e},null,8,[`modelValue`])]),_:1}))]),_:1},8,[`model`])]),_:1},8,[`title`])}}}),[[`__scopeId`,`data-v-55b26af7`]]);l(),b(),u();var N={class:`page-head`},P={class:`page-head-actions`},F={class:`flex-between`},I={class:`muted-sm`},L={class:`name-cell`},R={class:`fw-600`},z={class:`cmd-cell`},B={class:`mono`},V=[`title`],H={class:`mono`},U={class:`muted-sm`},W={key:1,class:`muted-sm`},G=w(n({__name:`ManagedServicesView`,setup(n){let{toast:i}=O(),{copyWithToast:l}=D(),{loadError:u,run:b}=E(`托管服务加载失败,请重试`),w=c([]),A=c(null),j=c(!0),G=c(!0),K=c(null),q=c(!1),J=c(null),Y=e=>[e.exec===``?`主进程 Node`:e.exec,...e.args].join(` `),X=()=>b(async()=>{try{let e=await T.managedServices();w.value=e.services??[],A.value=e.configError??null,G.value=!0}catch(e){if(typeof e?.message==`string`&&e.message.includes(`未由 ezllm 主进程托管`)){G.value=!1,w.value=[],A.value=null,u.value=null;return}throw e}finally{j.value=!1}}),Z=()=>{J.value=null,q.value=!0},ee=e=>{J.value=e.name,q.value=!0},te=async()=>{q.value=!1,await X()},Q=async(e,t,n)=>{if(!K.value){K.value=e;try{await t(),i(n,`success`),await X()}catch(e){i(e.message||`操作失败`,`error`)}finally{K.value=null}}},$=async(e,t)=>{let n={start:`启动`,stop:`停止`,restart:`重启`}[t];if(t===`stop`||t===`restart`)try{await C.confirm(`确定${n}服务 ${e.name}?`,`${n}确认`,{confirmButtonText:n,cancelButtonText:`取消`,type:`warning`})}catch{return}let r={start:()=>T.startManagedService(e.name),stop:()=>T.stopManagedService(e.name),restart:()=>T.restartManagedService(e.name)}[t];await Q(`${t}:${e.name}`,async()=>void await r(),`${n}指令已执行:${e.name}`)},ne=async(e,t)=>{let n=t?`开启「${e.name}」开机自启?此后随 ezllm 主进程启动自动拉起(不改变当前运行状态)。`:`关闭「${e.name}」开机自启?此后不再随 ezllm 启动自动拉起(不改变当前运行状态)。`;try{await C.confirm(n,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}await Q(`autostart:${e.name}`,async()=>{await T.updateManagedService(e.name,{name:e.name,exec:e.exec,args:e.args,cwd:e.cwd,autostart:t})},t?`已开启开机自启`:`已关闭开机自启`)},re=async e=>{try{await C.confirm(`确定删除托管服务 ${e.name}?${e.pid?`该服务正在运行,会先被停止;`:``}此后不再随 ezllm 启动,其配置将被移除。`,`确认删除`,{confirmButtonText:`确定`,cancelButtonText:`取消`,type:`warning`})}catch{return}await Q(`remove:${e.name}`,async()=>{await T.removeManagedService(e.name)},`已删除:${e.name}`)},ie=async e=>{await l(e.logFiles.out,`已复制日志路径:${e.logFiles.out}`)},ae=window.setInterval(()=>{q.value||K.value||X()},5e3);return s(()=>window.clearInterval(ae)),d(X),(n,i)=>{let s=g(`el-button`),c=g(`el-icon`),l=g(`el-alert`),d=g(`el-tag`),b=g(`el-table-column`),C=g(`el-switch`),T=g(`el-table`),E=g(`el-card`),D=f(`loading`);return p(),r(`div`,null,[v(`div`,N,[i[3]||=v(`div`,null,[v(`div`,{class:`page-head-title`},`托管服务`),v(`div`,{class:`page-head-sub`},` 由 ezllm 主进程守护的外部服务:可随开机自启、崩溃自动重启,与网关服务同等纳管 `)],-1),v(`div`,P,[t(s,{loading:j.value,onClick:X},{default:y(()=>[...i[1]||=[a(`刷新`,-1)]]),_:1},8,[`loading`]),t(s,{type:`primary`,disabled:!G.value,onClick:Z},{default:y(()=>[t(c,null,{default:y(()=>[t(o(S))]),_:1}),i[2]||=a(` 添加服务 `,-1)]),_:1},8,[`disabled`])])]),o(u)?(p(),e(l,{key:0,title:o(u),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[t(s,{size:`small`,onClick:X},{default:y(()=>[...i[4]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),A.value?(p(),e(l,{key:1,title:`托管服务清单不可用:${A.value}`,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[...i[5]||=[v(`div`,{class:`muted-sm`},` 修复该文件后重启 ezllm(或重新添加服务)即可恢复;期间已有服务不会自动加载。 `,-1)]]),_:1},8,[`title`])):_(``,!0),t(E,{shadow:`never`},{header:y(()=>[v(`div`,F,[i[6]||=v(`span`,{class:`fw-600`},`服务列表`,-1),v(`span`,I,m(w.value.length)+` 个服务`,1)])]),default:y(()=>[h((p(),e(T,{data:w.value,"empty-text":`暂无托管服务,点击右上角「添加服务」创建`},{default:y(()=>[t(b,{label:`服务名`,"min-width":`150`},{default:y(({row:t})=>[v(`div`,L,[v(`span`,R,m(t.name),1),t.pid?(p(),e(d,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:y(()=>[...i[7]||=[a(`运行中`,-1)]]),_:1})):(p(),e(d,{key:1,type:`info`,size:`small`,"disable-transitions":``},{default:y(()=>[...i[8]||=[a(`已停止`,-1)]]),_:1}))])]),_:1}),t(b,{label:`启动命令`,"min-width":`240`},{default:y(({row:e})=>[v(`div`,z,[v(`span`,B,m(Y(e)),1),v(`span`,{class:`muted-sm cwd-text`,title:e.cwd},m(e.cwd),9,V)])]),_:1}),t(b,{label:`进程`,width:`110`},{default:y(({row:e})=>[e.pid?(p(),r(x,{key:0},[v(`div`,H,`pid `+m(e.pid),1),v(`div`,U,m(e.startedAt?o(k)(e.startedAt):``),1)],64)):(p(),r(`span`,W,`-`))]),_:1}),t(b,{label:`开机自启`,width:`100`,align:`center`},{default:y(({row:e})=>[t(C,{"model-value":e.autostart,loading:K.value===`autostart:${e.name}`,onChange:t=>ne(e,!!t)},null,8,[`model-value`,`loading`,`onChange`])]),_:1}),t(b,{label:`日志`,width:`100`,align:`center`},{default:y(({row:e})=>[t(s,{link:``,type:`primary`,onClick:t=>ie(e)},{default:y(()=>[...i[9]||=[a(`复制路径`,-1)]]),_:1},8,[`onClick`])]),_:1}),t(b,{label:`操作`,width:`230`,align:`center`},{default:y(({row:n})=>[n.pid?(p(),r(x,{key:1},[t(s,{link:``,type:`warning`,loading:K.value===`restart:${n.name}`,onClick:e=>$(n,`restart`)},{default:y(()=>[...i[11]||=[a(`重启`,-1)]]),_:1},8,[`loading`,`onClick`]),t(s,{link:``,type:`danger`,loading:K.value===`stop:${n.name}`,onClick:e=>$(n,`stop`)},{default:y(()=>[...i[12]||=[a(`停止`,-1)]]),_:1},8,[`loading`,`onClick`])],64)):(p(),e(s,{key:0,link:``,type:`primary`,loading:K.value===`start:${n.name}`,onClick:e=>$(n,`start`)},{default:y(()=>[...i[10]||=[a(`启动`,-1)]]),_:1},8,[`loading`,`onClick`])),t(s,{link:``,onClick:e=>ee(n)},{default:y(()=>[...i[13]||=[a(`编辑`,-1)]]),_:1},8,[`onClick`]),t(s,{link:``,type:`danger`,loading:K.value===`remove:${n.name}`,onClick:e=>re(n)},{default:y(()=>[...i[14]||=[a(`删除`,-1)]]),_:1},8,[`loading`,`onClick`])]),_:1})]),_:1},8,[`data`])),[[D,j.value]])]),_:1}),q.value?(p(),e(M,{key:2,"editing-name":J.value,service:J.value==null?void 0:w.value.find(e=>e.name===J.value),onClose:i[0]||=e=>q.value=!1,onSaved:te},null,8,[`editing-name`,`service`])):_(``,!0)])}}}),[[`__scopeId`,`data-v-f4d654e1`]]);export{G as default};
@@ -1 +1 @@
1
- .form-hint[data-v-9aaa9859]{color:var(--el-text-color-secondary);margin-top:4px;font-size:12px;line-height:1.6}.form-hint--inline[data-v-9aaa9859]{margin-top:0;margin-left:8px}.form-hint--block[data-v-9aaa9859]{margin-bottom:8px}.name-cell[data-v-f4d654e1]{align-items:center;gap:8px;display:flex}.cmd-cell[data-v-f4d654e1]{flex-direction:column;gap:2px;min-width:0;display:flex}.mono[data-v-f4d654e1]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}.cwd-text[data-v-f4d654e1]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
1
+ .form-hint[data-v-55b26af7]{color:var(--el-text-color-secondary);margin-top:4px;font-size:12px;line-height:1.6}.form-hint--inline[data-v-55b26af7]{margin-top:0;margin-left:8px}.form-hint--block[data-v-55b26af7]{margin-bottom:8px}.name-cell[data-v-f4d654e1]{align-items:center;gap:8px;display:flex}.cmd-cell[data-v-f4d654e1]{flex-direction:column;gap:2px;min-width:0;display:flex}.mono[data-v-f4d654e1]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}.cwd-text[data-v-f4d654e1]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
@@ -1 +1 @@
1
- .quota-block[data-v-cda3702d]{background:#fafbfc;border:1px solid #f0f2f5;border-radius:6px;margin-bottom:4px;padding:8px 10px}.quota-header[data-v-cda3702d]{justify-content:space-between;align-items:center;gap:8px;margin-bottom:6px;display:flex}.quota-block-title[data-v-cda3702d]{color:#303133;flex-shrink:0;font-size:13px;font-weight:600}.quota-header-stats[data-v-cda3702d]{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:4px;min-width:0;display:flex}.quota-hint[data-v-cda3702d]{color:#c0c4cc;font-size:12px}.quota-error[data-v-cda3702d]{color:#f56c6c;word-break:break-all;margin-bottom:4px;font-size:12px}.quota-row[data-v-cda3702d]{align-items:flex-start;gap:8px;padding:3px 0;display:flex}.quota-label[data-v-cda3702d]{color:#909399;flex-shrink:0;width:72px;font-size:12px;line-height:18px}.quota-main[data-v-cda3702d]{flex:1;min-width:0}.quota-main[data-v-cda3702d] .el-progress{width:100%}.quota-main[data-v-cda3702d] .el-progress-bar__outer{background-color:#f2f2f2}.quota-main[data-v-cda3702d] .el-progress-bar__inner{align-items:center;display:flex}.quota-main[data-v-cda3702d] .el-progress-bar__innerText{color:#303133;white-space:nowrap;margin:0 5px;font-size:12px;line-height:1}.quota-cap-null[data-v-cda3702d]{color:#606266;font-size:12px}.provider-card[data-v-ba756612]{cursor:grab;min-width:0;transition:box-shadow .2s,border-color .2s}.provider-card[data-v-ba756612] .el-card__header{padding-bottom:10px}.provider-card[data-v-ba756612] .el-card__body{padding-top:12px}.provider-card[data-v-ba756612]:hover{border-color:var(--el-color-primary-light-5);box-shadow:var(--ez-card-shadow-hover)}.provider-card.dragging[data-v-ba756612]{cursor:grabbing}.provider-card.is-disabled[data-v-ba756612]{background:#fafafa}.provider-card.is-disabled .provider-name[data-v-ba756612]{color:#a8abb2}.provider-card.is-disabled[data-v-ba756612] .el-card__header{background:#fafafa}.card-header-right[data-v-ba756612]{flex-shrink:0;align-items:center;gap:10px;display:flex}.header-switch[data-v-ba756612]{cursor:auto;align-items:center;display:flex}.header-switch[data-v-ba756612] .el-switch{cursor:pointer}.card-header[data-v-ba756612]{justify-content:space-between;align-items:center;gap:12px;display:flex}.card-title[data-v-ba756612]{align-items:center;gap:8px;min-width:0;display:flex}.provider-name[data-v-ba756612]{color:#303133;text-overflow:ellipsis;white-space:nowrap;font-size:15px;font-weight:600;overflow:hidden}.card-actions[data-v-ba756612]{cursor:auto;flex-shrink:0;gap:0;display:flex}.model-tags[data-v-ba756612]{flex-wrap:wrap;gap:6px;margin-top:10px;display:flex}.model-tag[data-v-ba756612]{color:#606266;cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:#f5f7fa;border:1px solid #0000;border-radius:999px;align-items:center;max-width:100%;padding:3px 10px;font-size:12px;line-height:18px;transition:color .15s,background .15s;display:inline-flex;overflow:hidden}.model-tag[data-v-ba756612]:hover{color:#3b82f6;background:#eff6ff}.model-tag.ok[data-v-ba756612]{color:#16a34a;background:#f0fdf4}.model-tag.error[data-v-ba756612]{color:#dc2626;background:#fef2f2}.badge-mark[data-v-ba756612]{margin-left:3px}.card-footer[data-v-ba756612]{border-top:1px solid #f0f2f5;justify-content:space-between;align-items:center;margin-top:14px;padding-top:12px;display:flex}.model-count[data-v-ba756612]{color:#16a34a;cursor:pointer;border-radius:4px;font-size:13px;font-weight:500}.model-count[data-v-ba756612]:hover{text-decoration:underline}.drag-hint-icon[data-v-ba756612]{color:#c0c4cc;cursor:grab;flex-shrink:0}.drag-hint-icon[data-v-ba756612]:hover{color:#909399}.el-dropdown-menu__item.danger-item[data-v-ba756612]{color:var(--el-color-danger)}.el-dropdown-menu__item.danger-item[data-v-ba756612]:hover,.el-dropdown-menu__item.danger-item[data-v-ba756612]:focus{color:var(--el-color-danger);background-color:#fef2f2}.dropdown[data-v-ba756612]{margin-left:12px}.detail-body[data-v-08dfa117]{max-height:70vh;overflow-y:auto}.detail-head[data-v-08dfa117]{align-items:center;gap:12px;margin-bottom:12px;display:flex}.detail-name[data-v-08dfa117]{font-size:14px;font-weight:600}.detail-pre[data-v-08dfa117]{color:#303133;white-space:pre-wrap;word-break:break-all;background:#f5f7fa;border:1px solid #e4e7ed;border-radius:6px;max-height:300px;margin:0;padding:12px;font-size:12px;line-height:1.6;overflow:auto}.protocol-help .help-intro[data-v-2248b61a]{color:#606266;margin-bottom:14px;font-size:13px}.protocol-help .help-item[data-v-2248b61a]{margin-bottom:12px}.protocol-help .help-title[data-v-2248b61a]{color:#303133;align-items:center;gap:8px;margin-bottom:4px;font-size:14px;font-weight:600;display:flex}.protocol-help .help-item p[data-v-2248b61a]{color:#606266;margin:0;font-size:13px;line-height:1.7}.protocol-help .help-table-note[data-v-2248b61a]{margin-bottom:8px}.protocol-help .help-table[data-v-2248b61a]{width:100%}.model-select-wrap[data-v-5ab9aafa]{flex-shrink:0;width:400px}.test-result-link[data-v-5ab9aafa]{font-size:12px}.col-help[data-v-5ab9aafa]{margin-right:4px}.dialog-body[data-v-1d6d4d0a]{max-height:80vh;padding-bottom:100px;overflow:hidden auto}.test-ok-text[data-v-1d6d4d0a]{color:#16a34a;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:140px;font-size:12px;display:inline-block;overflow:hidden}.test-fail-text[data-v-1d6d4d0a]{color:#dc2626;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:140px;font-size:12px;display:inline-block;overflow:hidden}.protocol-hint[data-v-1d6d4d0a]{line-height:1.8}.label-inline-toggle[data-v-1d6d4d0a]{align-items:center;gap:6px;margin-left:8px;display:inline-flex}.models-dialog-body[data-v-7b39dd25]{flex-direction:column;height:calc(94vh - 100px);display:flex}.models-dialog-body .models-table[data-v-7b39dd25]{flex:1;min-height:0}.error-tag[data-v-7b39dd25]{text-overflow:ellipsis;white-space:nowrap;max-width:100px;overflow:hidden}.quota-help[data-v-775466be]{background:#fff;height:70vh;overflow:hidden auto}.quota-help .help-intro[data-v-775466be]{color:#606266;margin-bottom:14px;font-size:13px;line-height:1.7}.quota-help .help-item[data-v-775466be]{margin-bottom:12px}.quota-help .help-title[data-v-775466be]{color:#303133;margin-bottom:4px;font-size:14px;font-weight:600}.quota-help .help-item p[data-v-775466be]{color:#606266;margin:0;font-size:13px;line-height:1.7}.quota-help .help-tip[data-v-775466be]{color:#909399!important;margin-top:4px!important}.quota-help .help-shot[data-v-775466be]{border:1px solid #dcdfe6;border-radius:6px;width:100%;margin:8px 0;display:block}.quota-help code[data-v-775466be]{background:#f5f7fa;border-radius:3px;padding:1px 4px;font-size:12px}.quota-help .help-table[data-v-775466be]{width:100%}.footer[data-v-775466be]{place-content:center;display:flex}.dialog-body[data-v-8066b35a]{min-height:70vh;overflow-y:auto}.muted-sm[data-v-8066b35a]{color:#909399;font-size:12px;line-height:1.6}.status-row[data-v-8066b35a]{margin-top:4px}.test-ok-text-full[data-v-8066b35a]{color:#16a34a;font-size:12px}.test-fail-text-full[data-v-8066b35a]{color:#dc2626;word-break:break-all;font-size:12px}.col-help-icon[data-v-8066b35a]{margin-left:4px}.ghost[data-v-550e94f2]{opacity:.4}.provider-grid[data-v-550e94f2]{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}@media (width<=992px){.provider-grid[data-v-550e94f2]{grid-template-columns:1fr}}
1
+ .quota-block[data-v-331f3ebe]{background:#fafbfc;border:1px solid #f0f2f5;border-radius:6px;margin-bottom:4px;padding:8px 10px}.quota-header[data-v-331f3ebe]{justify-content:space-between;align-items:center;gap:8px;margin-bottom:6px;display:flex}.quota-block-title[data-v-331f3ebe]{color:#303133;flex-shrink:0;font-size:13px;font-weight:600}.quota-header-stats[data-v-331f3ebe]{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:4px;min-width:0;display:flex}.quota-hint[data-v-331f3ebe]{color:#c0c4cc;font-size:12px}.quota-error[data-v-331f3ebe]{color:#f56c6c;word-break:break-all;margin-bottom:4px;font-size:12px}.quota-row[data-v-331f3ebe]{align-items:flex-start;gap:8px;padding:3px 0;display:flex}.quota-label[data-v-331f3ebe]{color:#909399;flex-shrink:0;width:72px;font-size:12px;line-height:18px}.quota-main[data-v-331f3ebe]{flex:1;min-width:0}.quota-main[data-v-331f3ebe] .el-progress{width:100%}.quota-main[data-v-331f3ebe] .el-progress-bar__outer{background-color:#f2f2f2}.quota-main[data-v-331f3ebe] .el-progress-bar__inner{align-items:center;display:flex}.quota-main[data-v-331f3ebe] .el-progress-bar__innerText{color:#303133;white-space:nowrap;margin:0 5px;font-size:12px;line-height:1}.quota-cap-null[data-v-331f3ebe]{color:#606266;font-size:12px}.provider-card[data-v-ba756612]{cursor:grab;min-width:0;transition:box-shadow .2s,border-color .2s}.provider-card[data-v-ba756612] .el-card__header{padding-bottom:10px}.provider-card[data-v-ba756612] .el-card__body{padding-top:12px}.provider-card[data-v-ba756612]:hover{border-color:var(--el-color-primary-light-5);box-shadow:var(--ez-card-shadow-hover)}.provider-card.dragging[data-v-ba756612]{cursor:grabbing}.provider-card.is-disabled[data-v-ba756612]{background:#fafafa}.provider-card.is-disabled .provider-name[data-v-ba756612]{color:#a8abb2}.provider-card.is-disabled[data-v-ba756612] .el-card__header{background:#fafafa}.card-header-right[data-v-ba756612]{flex-shrink:0;align-items:center;gap:10px;display:flex}.header-switch[data-v-ba756612]{cursor:auto;align-items:center;display:flex}.header-switch[data-v-ba756612] .el-switch{cursor:pointer}.card-header[data-v-ba756612]{justify-content:space-between;align-items:center;gap:12px;display:flex}.card-title[data-v-ba756612]{align-items:center;gap:8px;min-width:0;display:flex}.provider-name[data-v-ba756612]{color:#303133;text-overflow:ellipsis;white-space:nowrap;font-size:15px;font-weight:600;overflow:hidden}.card-actions[data-v-ba756612]{cursor:auto;flex-shrink:0;gap:0;display:flex}.model-tags[data-v-ba756612]{flex-wrap:wrap;gap:6px;margin-top:10px;display:flex}.model-tag[data-v-ba756612]{color:#606266;cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:#f5f7fa;border:1px solid #0000;border-radius:999px;align-items:center;max-width:100%;padding:3px 10px;font-size:12px;line-height:18px;transition:color .15s,background .15s;display:inline-flex;overflow:hidden}.model-tag[data-v-ba756612]:hover{color:#3b82f6;background:#eff6ff}.model-tag.ok[data-v-ba756612]{color:#16a34a;background:#f0fdf4}.model-tag.error[data-v-ba756612]{color:#dc2626;background:#fef2f2}.badge-mark[data-v-ba756612]{margin-left:3px}.card-footer[data-v-ba756612]{border-top:1px solid #f0f2f5;justify-content:space-between;align-items:center;margin-top:14px;padding-top:12px;display:flex}.model-count[data-v-ba756612]{color:#16a34a;cursor:pointer;border-radius:4px;font-size:13px;font-weight:500}.model-count[data-v-ba756612]:hover{text-decoration:underline}.drag-hint-icon[data-v-ba756612]{color:#c0c4cc;cursor:grab;flex-shrink:0}.drag-hint-icon[data-v-ba756612]:hover{color:#909399}.el-dropdown-menu__item.danger-item[data-v-ba756612]{color:var(--el-color-danger)}.el-dropdown-menu__item.danger-item[data-v-ba756612]:hover,.el-dropdown-menu__item.danger-item[data-v-ba756612]:focus{color:var(--el-color-danger);background-color:#fef2f2}.dropdown[data-v-ba756612]{margin-left:12px}.detail-body[data-v-08dfa117]{max-height:70vh;overflow-y:auto}.detail-head[data-v-08dfa117]{align-items:center;gap:12px;margin-bottom:12px;display:flex}.detail-name[data-v-08dfa117]{font-size:14px;font-weight:600}.detail-pre[data-v-08dfa117]{color:#303133;white-space:pre-wrap;word-break:break-all;background:#f5f7fa;border:1px solid #e4e7ed;border-radius:6px;max-height:300px;margin:0;padding:12px;font-size:12px;line-height:1.6;overflow:auto}.protocol-help .help-intro[data-v-2248b61a]{color:#606266;margin-bottom:14px;font-size:13px}.protocol-help .help-item[data-v-2248b61a]{margin-bottom:12px}.protocol-help .help-title[data-v-2248b61a]{color:#303133;align-items:center;gap:8px;margin-bottom:4px;font-size:14px;font-weight:600;display:flex}.protocol-help .help-item p[data-v-2248b61a]{color:#606266;margin:0;font-size:13px;line-height:1.7}.protocol-help .help-table-note[data-v-2248b61a]{margin-bottom:8px}.protocol-help .help-table[data-v-2248b61a]{width:100%}.model-select-wrap[data-v-67bd57e3]{flex-shrink:0;width:400px}.test-result-link[data-v-67bd57e3]{font-size:12px}.col-help[data-v-67bd57e3]{margin-right:4px}.dialog-body[data-v-54cea1cb]{max-height:80vh;padding-bottom:100px;overflow:hidden auto}.test-ok-text[data-v-54cea1cb]{color:#16a34a;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:140px;font-size:12px;display:inline-block;overflow:hidden}.test-fail-text[data-v-54cea1cb]{color:#dc2626;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:140px;font-size:12px;display:inline-block;overflow:hidden}.protocol-hint[data-v-54cea1cb]{line-height:1.8}.label-inline-toggle[data-v-54cea1cb]{align-items:center;gap:6px;margin-left:8px;display:inline-flex}.models-dialog-body[data-v-7b39dd25]{flex-direction:column;height:calc(94vh - 100px);display:flex}.models-dialog-body .models-table[data-v-7b39dd25]{flex:1;min-height:0}.error-tag[data-v-7b39dd25]{text-overflow:ellipsis;white-space:nowrap;max-width:100px;overflow:hidden}.quota-help[data-v-775466be]{background:#fff;height:70vh;overflow:hidden auto}.quota-help .help-intro[data-v-775466be]{color:#606266;margin-bottom:14px;font-size:13px;line-height:1.7}.quota-help .help-item[data-v-775466be]{margin-bottom:12px}.quota-help .help-title[data-v-775466be]{color:#303133;margin-bottom:4px;font-size:14px;font-weight:600}.quota-help .help-item p[data-v-775466be]{color:#606266;margin:0;font-size:13px;line-height:1.7}.quota-help .help-tip[data-v-775466be]{color:#909399!important;margin-top:4px!important}.quota-help .help-shot[data-v-775466be]{border:1px solid #dcdfe6;border-radius:6px;width:100%;margin:8px 0;display:block}.quota-help code[data-v-775466be]{background:#f5f7fa;border-radius:3px;padding:1px 4px;font-size:12px}.quota-help .help-table[data-v-775466be]{width:100%}.footer[data-v-775466be]{place-content:center;display:flex}.dialog-body[data-v-8066b35a]{min-height:70vh;overflow-y:auto}.muted-sm[data-v-8066b35a]{color:#909399;font-size:12px;line-height:1.6}.status-row[data-v-8066b35a]{margin-top:4px}.test-ok-text-full[data-v-8066b35a]{color:#16a34a;font-size:12px}.test-fail-text-full[data-v-8066b35a]{color:#dc2626;word-break:break-all;font-size:12px}.col-help-icon[data-v-8066b35a]{margin-left:4px}.ghost[data-v-550e94f2]{opacity:.4}.provider-grid[data-v-550e94f2]{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}@media (width<=992px){.provider-grid[data-v-550e94f2]{grid-template-columns:1fr}}